diff --git a/.dockerignore b/.dockerignore index b3b2d4d926..b6d62a3209 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,7 +2,7 @@ !ci !config !data -!database +!migrations !docker !languages !library diff --git a/.env b/.env new file mode 100644 index 0000000000..6120c1cb1c --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +APP_ENV=prod +APP_DEBUG=false diff --git a/.github/workflows/run-cypress.yml b/.github/workflows/run-cypress.yml index 063aaada71..ad7d47d54a 100644 --- a/.github/workflows/run-cypress.yml +++ b/.github/workflows/run-cypress.yml @@ -3,6 +3,8 @@ on: push: branches: - main + - upgrade + - feature/sf_upgrade_44 pull_request: workflow_dispatch: # run at 6 hour UTC @@ -14,24 +16,24 @@ jobs: timeout-minutes: 30 strategy: matrix: - php: [ php72 ] + php: [ php82 ] env: - PROD_PHP: php72 + PROD_PHP: php82 DOCKER_COMPOSE: docker compose -f docker-compose.yml -f docker-compose-${{matrix.php}}.yml steps: - name: Checkout uses: actions/checkout@master - name: chown some dirs run: | - mkdir tmp vendor && sudo chown -R 33 app/ theme/ web/ tmp/ vendor/ + mkdir tmp vendor && sudo chown -R 33 theme/ public/ tmp/ vendor/ var/ config/ - name: Build Docker environmnent if: always() run: | cd docker && ${DOCKER_COMPOSE} up -d --build && docker compose exec -T --user www-data engine.dev.openconext.local bash -c ' - SYMFONY_ENV=ci composer install --prefer-dist -n -o --ignore-platform-reqs && \ - ./app/console cache:clear --env=ci && \ + composer install --prefer-dist -n -o --ignore-platform-reqs && \ + ./bin/console cache:clear --env=ci && \ cd theme && CYPRESS_INSTALL_BINARY=0 yarn install --frozen-lockfile && EB_THEME=skeune yarn build ' - name: Run Cypress integration tests @@ -42,11 +44,11 @@ jobs: EB_THEME=skeune ./theme/scripts/prepare-test.js ' && \ docker compose exec -T cypress bash -c ' - cd e2e && yarn install && cypress run --spec cypress/integration/skeune/**/*.spec.js,cypress/integration/shared/*.spec.js --browser=chrome --headless + yarn install && cypress run --spec "cypress/integration/skeune/**/*.spec.js,cypress/integration/shared/*.spec.js" --browser=chrome --headless ' && \ docker compose exec -T --user www-data engine.dev.openconext.local bash -c ' EB_THEME=openconext ./theme/scripts/prepare-test.js ' && \ docker compose exec -T cypress bash -c ' - cd e2e && cypress run --spec cypress/integration/openconext/**/*.spec.js --browser=chrome --headless + cypress run --spec "cypress/integration/openconext/**/*.spec.js" --browser=chrome --headless ' diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 16c36de771..e75cb18f2c 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -3,6 +3,8 @@ on: push: branches: - main + - upgrade + - feature/sf_upgrade_44 pull_request: # run at 6 hour UTC schedule: @@ -13,25 +15,24 @@ jobs: timeout-minutes: 30 strategy: matrix: - # php82 is ready to run alongside the 72, but is not enabled now as the code is not 82 compatible yet - php: [ php72 ] + php: [ php82 ] env: - PROD_PHP: php72 + PROD_PHP: php82 DOCKER_COMPOSE: docker compose -f docker-compose.yml -f docker-compose-${{matrix.php}}.yml steps: - name: Checkout uses: actions/checkout@master - name: chown some dirs run: | - mkdir tmp vendor && sudo chown -R 33 app/ theme/ web/ tmp/ vendor/ + mkdir tmp vendor && sudo chown -R 33 theme/ public/ tmp/ vendor/ var/ tests/ config/ - name: Build Docker environmnent if: always() run: | cd docker && ${DOCKER_COMPOSE} up -d --build && docker compose exec -T --user www-data engine.dev.openconext.local bash -c ' - SYMFONY_ENV=ci composer install --prefer-dist -n -o --ignore-platform-reqs && \ - ./app/console cache:clear --env=ci && \ + composer install --prefer-dist -n -o --ignore-platform-reqs && \ + ./bin/console cache:clear --env=ci && \ cd theme && CYPRESS_INSTALL_BINARY=0 yarn install --frozen-lockfile && EB_THEME=skeune yarn build ' - name: Run code quality tests @@ -47,58 +48,50 @@ jobs: echo -e "\nDoc header check\n" && \ ./vendor/bin/docheader check src/ tests/ library/ --exclude-dir resources --exclude-dir languages ' - env: - SYMFONY_ENV: ci - name: Run unit tests if: always() run: | - cd docker && APP_ENV=ci SYMFONY_ENV=ci docker compose exec -T --user www-data engine.dev.openconext.local bash -c ' + cd docker && APP_ENV=ci docker compose exec -e XDEBUG_MODE=coverage -T --user www-data engine.dev.openconext.local bash -c ' echo -e "\nInstalling database fixtures...\n" && \ - ./app/console doctrine:schema:drop --force --env=ci && \ - ./app/console doctrine:schema:create --env=ci && \ + ./bin/console doctrine:schema:drop --force --env=ci && \ + ./bin/console doctrine:schema:create --env=ci && \ echo -e "\nPHPUnit legacy tests\n" && \ ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=eb4 --coverage-text && \ echo -e "\nPHPUnit unit tests\n" && \ ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=unit --coverage-text && \ echo -e "\nPHPUnit API acceptance tests\n" && \ - APP_ENV=ci ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=functional --coverage-text && \ + APP_ENV=test ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=functional --coverage-text && \ echo -e "\nPHPUnit integration tests\n" && \ ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=integration --coverage-text ' - env: - SYMFONY_ENV: ci - name: Run acceptance tests if: always() run: | cd docker && docker compose exec -T --user www-data engine.dev.openconext.local bash -c ' echo -e "\nInstalling database fixtures...\n" && \ - ./app/console doctrine:schema:drop --force --env=ci && \ - ./app/console doctrine:schema:create --env=ci && \ + ./bin/console doctrine:schema:drop --force --env=ci && \ + ./bin/console doctrine:schema:create --env=ci && \ echo -e "\nPreparing frontend assets\n" && \ EB_THEME=skeune ./theme/scripts/prepare-test.js > /dev/null && \ echo -e "\nRun the Behat tests\n" && \ - ./vendor/bin/behat -c ./tests/behat-ci.yml --suite default -vv --format progress --strict && \ - echo -e "\nBehat tests (with selenium and headless Chrome)\n" && \ - ./vendor/bin/behat -c ./tests/behat-ci.yml --suite selenium -vv --format progress --strict + ./vendor/bin/behat -c ./tests/behat.yml --suite default -vv --format pretty --strict && \ + echo -e "\nBehat tests (with headless Chrome)\n" && \ + ./vendor/bin/behat -c ./tests/behat.yml --suite functional -vv --format pretty --strict ' - env: - SYMFONY_ENV: ci - name: Run linting tests if: always() run: | cd docker && docker compose exec -T --user www-data engine.dev.openconext.local bash -c ' echo -e "\nTwig lint\n" && \ - app/console lint:twig theme/ && \ + bin/console lint:twig theme/ && \ cd theme && \ echo -e "\nLint frontend assets\n" && \ yarn lint ' - env: - SYMFONY_ENV: ci - name: Show log on failure if: failure() run: | - cd docker && docker compose exec -T engine.dev.openconext.local cat /var/www/html/app/logs/ci/ci.log + cd docker && docker compose exec -T engine.dev.openconext.local cat /var/www/html/var/log/application.log - name: Send notification on production build nightly build failure uses: sonots/slack-notice-action@v3 with: diff --git a/.gitignore b/.gitignore index 0a12fb5f9b..b7eeb2c991 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,47 @@ -/build -/vendor/ -/www/authentication/generated/ -bin/ignore_me.php -/web/bundles -/web/app_dev.php -/web/javascripts/* -/web/stylesheets/* -/web/images/* -/web/fonts/* -!/web/fonts/.gitkeep -/app/cache -/app/logs -/app/SymfonyRequirements.php -/app/check.php -/tmp/ -/app/config/functional_testing.yml -/app/config/parameters.yml -/app/config/config_local.yml -.idea -local-php-security-checker -/tests/e2e/node_modules -/tests/.phpunit.result.cache -/languages/overrides.*.php -/theme/node_modules -/theme/.sass-cache -/theme/**/visual-regression/screenshots/* -!/theme/**/visual-regression/screenshots/.gitkeep -/theme/**/__image_snapshots__ +config/packages/parameters.yml + +var/cache/* +var/log/* +!var/cache/.gitkeep +!var/log/.gitkeep + +public/fonts +public/images +public/javascripts +public/stylesheets + +theme/node_modules +vendor + +tests/.phpunit.result.cache +tests/e2e/node_modules + +coverage.xml +.idea .DS_Store + +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/public/bundles/ +/var/ +/vendor/ +###< symfony/framework-bundle ### + +###> phpunit/phpunit ### +/phpunit.xml +.phpunit.result.cache +###< phpunit/phpunit ### + +###> symfony/phpunit-bridge ### +.phpunit +.phpunit.result.cache +/phpunit.xml +###< symfony/phpunit-bridge ### + +###> friends-of-behat/symfony-extension ### +/behat.yml +###< friends-of-behat/symfony-extension ### diff --git a/CHANGELOG.md b/CHANGELOG.md index b5dd9b12b0..c060bcb826 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,24 @@ More information about our release strategy can be found in the [Development Guidelines](https://github.com/OpenConext/OpenConext-engineblock/wiki/Development-Guidelines#release-notes) on the EngineBlock wiki. +## 7.0.0 +Breaking changes please see: [upgrading](UPGRADING.md#700) + +Maintenance: +* upgrade to symfony 4.4 + +### DB json_array +Doctrine no longer supports `json_array` types. +If the production database currently has columns with `COMMENT '(DC2Type:json_array)'`, they need to be changed to `COMMENT '(DC2Type:json)'`. + +This is not done in a Migration, as production is not in sync with the schema as defined in the migrations. + +Reference query as an example: +```mysql +ALTER TABLE sso_provider_roles_eb5 + CHANGE consent_settings consent_settings MEDIUMTEXT DEFAULT NULL COMMENT '(DC2Type:json)'; +``` + ## 6.18.0 Dependencies: diff --git a/README.md b/README.md index 54b05bbbd2..55fa25e28a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # OpenConext EngineBlock Build Status: @@ -19,10 +18,12 @@ See the [UPGRADING.md][upgrading] file ## (Theme) Development -Please see the [wiki][eb-wiki-theme-development] for information on how to get started with developing themes for OpenConext EngineBlock +Please see the [wiki][eb-wiki-theme-development] for information on how to get started with developing themes for +OpenConext EngineBlock In short, themes require front-end resource compilation which can be done by running the following commands: -First set the desired theme name in the parameters.yml. This will load the correct Twig templates as they are a part of the Symfony config. +First set the desired theme name in the parameters.yml. This will load the correct Twig templates as they are a part of +the Symfony config. ``` parameters: @@ -36,10 +37,11 @@ Next build the front-end assets for the selected theme. (cd theme && yarn install --frozen-lockfile && yarn build) ``` -Finally, when not in an environment with the debug flag enabled, you need to clear the cache. This will ensure the translations and templates are swapped out for the ones found in the new theme. +Finally, when not in an environment with the debug flag enabled, you need to clear the cache. This will ensure the +translations and templates are swapped out for the ones found in the new theme. ``` -$ php72 ./app/console cache:clear --env=prod +$ php72 ./bin/console cache:clear --env=prod ``` To setup the required tooling on the container, the following steps might be useful: @@ -50,7 +52,8 @@ To setup the required tooling on the container, the following steps might be use sudo npm install --global yarn (yarn install --frozen-lockfile && yarn build) -In addition to the npm/yarn scripts that are available to run (unit/e2e) tests and quality assurance, you can also use the +In addition to the npm/yarn scripts that are available to run (unit/e2e) tests and quality assurance, you can also use +the Twig linting tool built into Symfony. To run this linter: ``` @@ -58,7 +61,7 @@ If you are able to run Ant build targets use: $ ant php-twig-lint But you can also run the linter directly from the Symfony console. From the webroot: -$ php72 ./app/console lint:twig theme/ +$ php72 ./bin/console lint:twig theme/ ``` ## System Requirements @@ -84,7 +87,8 @@ it is only regularly tested with RedHat Enterprise Linux and CentOS._ _**Note**: you are highly encouraged to use [OpenConext-Devconf][op-dev] to deploy OpenConext installations._ -If you are reading this then you've probably already installed a copy of EngineBlock somewhere on the destination server, +If you are reading this then you've probably already installed a copy of EngineBlock somewhere on the destination +server, if not, then that would be step 1 for the installation. If you do not use [OpenConext-Devconf][op-dev] and have an installed copy and your server meets all the requirements @@ -104,57 +108,62 @@ above, then please follow the steps below to start your installation. mysql> create database engineblock default charset utf8 default collate utf8_unicode_ci; - ### Then configure application EngineBlock requires you to have the folders below writable by your webserver user. - app/cache + var/cache + var/log Run the command below in the root of your project to install the required dependencies. composer install --no-interaction --optimize-autoloader --prefer-dist --no-dev - **Note**: +**Note**: The command above assumes that the application must be build for production, and omits development dependencies. -Then edit the `parameters.yml` with your favorite editor and review the settings to make sure it matches your configuration. +Then edit the `parameters.yml` with your favorite editor and review the settings to make sure it matches your +configuration. ### Install database schema updates To install possible database updates, call doctrine migrations by using the following console command: - app/console doctrine:migrations:migrate --env=prod + bin/console doctrine:migrations:migrate --env=prod _**Note**: EngineBlock requires database settings, without it doctrine migrate will not function. Furthermore, this assumes that the application must use the production settings (`--env=prod`), this could be replaced with `dev` should you run a development version._ - ### Configure HTTP server -Configure a single virtual host, this should point to the `web` directory: +Configure a single virtual host, this should point to the `public` directory: - DocumentRoot /opt/www/engineblock/web + DocumentRoot /opt/www/engineblock/public It should also serve both the `engine.yourdomain.example` and `engine-api.yourdomain.example` domains. -Make sure the `ENGINEBLOCK_ENV` is set, and that the `SYMFONY_ENV` is set, this can be mapped from `ENGINEBLOCK_ENV` as: +Make sure the `APP_ENV` is set for the correct environment: -| `ENGINEBLOCK_ENV` | `SYMFONY_ENV` | -|-------------------| --- | -| production | prod | -| acceptance | acc | -| test | test | -| dev | dev | +| `APP_ENV` | Command | +|---------------|-------------------------------------------------------------------------------------------------------| +| prod | For production environment | +| acc | For acceptance environment | +| testing | For test environment | +| test | For unit testing: This suite has additional configuration and loads additional testing services | +| ci | For functional testing: This suite has additional configuration and loads additional testing services | +| dev | For development: This suite has additional debug configuration | + +Besides `APP_ENV` the only other environment variable supported is `APP_DEBUG`. For other adjustments, you would have to +adjust the parameters.yml file and place it in the corresponding environment folder in `config/`. **EXAMPLE** - SetEnv ENGINEBLOCK_ENV !!ENV!! - SetEnv SYMFONY_ENV !!SF_ENV!! + SetEnv APP_ENV !!SF_ENV!! + SetEnv APP_DEBUG true/false -Make sure you have the following rewrite rules (replace `app.php` with `app_dev.php` for development): +Make sure you have the following rewrite rules: RewriteEngine On # We support only GET/POST/HEAD @@ -164,10 +173,10 @@ Make sure you have the following rewrite rules (replace `app.php` with `app_dev. # Note that the requested URL MUST be appended because Corto uses the PATH_INFO server variable RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d - RewriteRule ^(.*)$ /app.php/$1 [L] # Send the query string to index.php + RewriteRule ^(.*)$ /index.php/$1 [L] # Send the query string to index.php # Requests to the domain (no query string) - RewriteRule ^$ app.php/ [L] + RewriteRule ^$ index.php/ [L] Note that EngineBlock SHOULD run on HTTPS, you can redirect users from HTTP to HTTPS with the following Apache rewrite rules on a *:80 VirtualHost: @@ -176,13 +185,6 @@ with the following Apache rewrite rules on a *:80 VirtualHost: RewriteCond %{SERVER_PORT} ^80$ RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R=301] -### Grab the front controller -Copy the `app_dev.php.dist` file to the `web` directory. - -```bash -Openconext-engineblock $ cp app_dev.php.dist web/app_dev.php -``` - ### Test your EngineBlock instance Use these URLs to test your EngineBlock instance: @@ -219,7 +221,7 @@ If you are using this pattern, an update can be done with the following: 3. Run the database migrations script. - app/console doctrine:migrations:migrate --env=prod + bin/console doctrine:migrations:migrate --env=prod 4. Change the symlink. @@ -228,14 +230,14 @@ If you are using this pattern, an update can be done with the following: The list of browsers that should be supported: | [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [iOS Safari](http://godban.github.io/browsers-support-badges/)
iOS Safari | [Samsung](http://godban.github.io/browsers-support-badges/)
Samsung | [Opera](http://godban.github.io/browsers-support-badges/)
Opera | -| --------- | --------- | --------- | --------- | --------- | --------- | --------- | -| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions| last 2 versions| last 2 versions| last 2 versions +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions The list of browsers being tested: | [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome Android | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | [iOS Safari](http://godban.github.io/browsers-support-badges/)
iOS Safari | -| --------- | --------- | --------- | --------- | --------- | --------- | -| IE11, Edge last version| last version| last version| last version| last version| last version| +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| IE11, Edge last version | last version | last version | last version | last version | last version | ## Additional Documentation @@ -250,17 +252,31 @@ Also, the following documentation can be found in the [docs][docs] directory: 1. [Release notes for releases < 5.0.0][docs-release-notes] [qa-build]: https://github.com/OpenConext/OpenConext-engineblock/workflows/test-integration/badge.svg + [license]: LICENSE + [notice]: NOTICE.txt + [upgrading]: UPGRADING.md + [comp]: https://getcomposer.org/ + [op-dev]: https://github.com/OpenConext/OpenConext-devconf + [manage]: https://github.com/OpenConext/OpenConext-manage + [eb-wiki-theme-development]: https://github.com/OpenConext/OpenConext-engineblock/wiki/Development-Guidelines#theme-development + [wiki]: https://github.com/OpenConext/OpenConext-engineblock/wiki + [wiki-development]: https://github.com/OpenConext/OpenConext-engineblock/wiki/Development-Guidelines + [docs]: https://github.com/OpenConext/OpenConext-engineblock/tree/master/docs/index.md + [docs-license]: https://github.com/OpenConext/OpenConext-engineblock/tree/master/docs/LICENSE + [docs-release]: https://github.com/OpenConext/OpenConext-engineblock/tree/master/docs/release_procedure.md + [docs-filter]: https://github.com/OpenConext/OpenConext-engineblock/tree/master/docs/filter_commands.md + [docs-release-notes]: https://github.com/OpenConext/OpenConext-engineblock/tree/master/docs/release_notes diff --git a/UPGRADING.md b/UPGRADING.md index 4827ff2fe0..6a789280be 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,86 @@ # UPGRADE NOTES +## 7.0.0 +Upgraded Symfony from **version 3.3** to **version 4.4 (LTS)**. +This update brings modernized architecture, performance improvements, enhanced developer experience, and long-term support till November 2023. + +### Directory Structure Overhaul - technical changes: +- The `app/` directory has been replaced with `config/` and `src/` +- All configuration files now reside under [config/](config), organized by environment +- Application configuration resides in [config/packages](config/packages) +- The console has moved form `app/console` to [bin/console](bin/console) +- Database migrations have moved to [migrations/](migrations) +- `AppKernel` has been replaced with [Kernel](src/Kernel.php) +- Logs has moved from `app/logs` to [var/log](var/log) +- cache has moved from `app/cache` to [var/cache](var/cache) +- The public access folder has changed from `web/` to [public/](public) +- The entry point has changed from `app.php` to [index.php](public/index.php) +- Some environment variables have changed. +- [index.php](public/index.php) has been updated to load based on environment variables and has some additional environment variables checks. +- All configurations injections from inside `src/` has been moved to `config/` + +### ⚠️ Breaking Changes - Configurational adjustments required: + +#### New public folder +Replace `web/` with `public/`. Ensure the folder `public/` is accessible and your php webservice is pointing to `public/index.php`. In apache this would mean: + +```shell +DocumentRoot /var/www/html/public + + Require all granted + Options -MultiViews + RewriteEngine On + RewriteBase / + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php [QSA,L] + +``` + +#### Configuration +1. **Any** configuration parameters should be mapped to a different folder location inside `config/`. + Most likely the only change will be `app/config/parameters.yml` to `config/packages/[env]/parameters.yml` +2. Overwriting the `config/packages/parameters.yml` will still work however, using the correct environment package is encouraged. +3. The value 'secret' in the parameters.yml is no longer used. Instead you should set `APP_SECRET` as an + environment variable: +
+ Length: While Symfony doesn’t enforce a strict length, at least 32 bytes (64 hex characters) is recommended for strong security. Uniqueness: Each application instance should have its own unique secret. Reusing secrets across projects or environments is discouraged +4. Remove the following environment variables: + - `ENGINEBLOCK_ENV` + - `SYMFONY_ENV` +5. Add the following environment variables: + - `APP_ENV` set for the correct env. See [README](README.md#configure-http-server) + - `APP_SECRET` + - `APP_DEBUG` set to true to enable debug mode. + +Example `.env` +```shell +APP_ENV=prod +APP_DEBUG=false +APP_SECRET=04d8ec52d3fd4eb9a8f5d4c69d82cfaec39f764af74b223c44e1ba9574b4b3d6 +``` + +**Swiftmailer > Symfony Mail** +In parameters.yml, the Swiftmailer smtp configuration has been replaced with a SMTP dsn for Symfony Mailer. +Replace: +```dotenv +mailer_transport: 'smtp' +mailer_host: 'localhost' +mailer_port: '25' +mailer_user: '' +mailer_password: '' +``` +with: +`mailer_dsn: 'smtp://user:password@localhost:25'` + +### Devconf + +Note: +
+See [apache2.conf](docker/ci/apache2.conf) and [docker-compose.yml](docker/docker-compose.yml) as an example. +
+See The changes in [https://github.com/OpenConext/OpenConext-devconf/compare/main...feature/sf_upgrade_44](https://github.com/OpenConext/OpenConext-devconf/compare/main...feature/sf_upgrade_44) as an example + + ## 6.15 -> 6.18 ### Dependencies @@ -113,7 +194,7 @@ application will result in the soft deletion of the consent row for that person, consent removal of. In order to work with this feature, the latest database migration must be installed on your database(s) containing the -`consent` table. This should be as simple as running `app/console doctrine:migrations:migrate`. Or executing +`consent` table. This should be as simple as running `bin/console doctrine:migrations:migrate`. Or executing `Version20220425090852` manually. ## 6.2 > 6.3 @@ -568,7 +649,7 @@ database.dbname = engineblock When a master/slave setup is still required, this can be configured by creating a `config_local.yml` in `app/config`. This file will be loaded automatically if present and will allow overriding any configuration present. Do note that in -order to be able to load the file `app/console cache:clear --env={current_env_as_in_vhost}` must be executed once. +order to be able to load the file `bin/console cache:clear --env={current_env_as_in_vhost}` must be executed once. More information on how to configure Doctrine can be found in [the bundle documentation][doct1] and the [configuration reference documentation][doct2]. Before considering using a master/slave setup, please review [this documentation][doct3] as to when a master or slave is used for a connection. diff --git a/app/.htaccess b/app/.htaccess deleted file mode 100644 index fb1de45bdb..0000000000 --- a/app/.htaccess +++ /dev/null @@ -1,7 +0,0 @@ - - Require all denied - - - Order deny,allow - Deny from all - diff --git a/app/AppCache.php b/app/AppCache.php deleted file mode 100644 index 639ec2cd7e..0000000000 --- a/app/AppCache.php +++ /dev/null @@ -1,7 +0,0 @@ -getEnvironment(), array('dev', 'test', 'ci'))) { - $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); - $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); - - // own bundles - $bundles[] = new OpenConext\EngineBlockFunctionalTestingBundle\OpenConextEngineBlockFunctionalTestingBundle(); - } - - return $bundles; - } - - public function registerContainerConfiguration(LoaderInterface $loader) - { - $configurationDirectory = $this->getRootDir() . '/config/'; - $loader->load($configurationDirectory . 'config_' . $this->getEnvironment() . '.yml'); - - $localConfiguration = $configurationDirectory . 'config_local.yml'; - if (!file_exists($localConfiguration)) { - return; - } - - if (!is_readable($localConfiguration)) { - throw new \RuntimeException(sprintf('Local configuration file "%s" is not readable', $localConfiguration)); - } - - $loader->load(($localConfiguration)); - } - - public function getCacheDir() - { - return $this->rootDir . '/cache/' . $this->environment; - } - - public function getLogDir() - { - return $this->rootDir . '/logs/' . $this->environment; - } - - public function getProjectDir() - { - // This is needed to define the project dir without composer.json - // @see: https://symfony.com/doc/current/reference/configuration/kernel.html#configuration-kernel-project-directory - return \dirname(__DIR__); - } - -} diff --git a/app/autoload.php b/app/autoload.php deleted file mode 100644 index 31321faa58..0000000000 --- a/app/autoload.php +++ /dev/null @@ -1,11 +0,0 @@ -getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev'); -$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod'; - -if ($debug) { - Debug::enable(); -} - -$kernel = new AppKernel($env, $debug); -$application = new Application($kernel); -$application->run($input); diff --git a/app/phpunit.xml.dist b/app/phpunit.xml.dist deleted file mode 100644 index dc1bf70bde..0000000000 --- a/app/phpunit.xml.dist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - ../src/*/*Bundle/Tests - ../src/*/Bundle/*Bundle/Tests - ../src/*Bundle/Tests - - - - - - - - ../src - - ../src/*Bundle/Resources - ../src/*Bundle/Tests - ../src/*/*Bundle/Resources - ../src/*/*Bundle/Tests - ../src/*/Bundle/*Bundle/Resources - ../src/*/Bundle/*Bundle/Tests - - - - diff --git a/bin/console b/bin/console new file mode 100755 index 0000000000..3882cc1776 --- /dev/null +++ b/bin/console @@ -0,0 +1,39 @@ +#!/usr/bin/env php +getParameterOption(['--env', '-e'], $_ENV['APP_ENV'], true); +$debug = filter_var($_ENV['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) && !$input->hasParameterOption('--no-debug', true); + +if ($debug) { + umask(0000); + + Debug::enable(); +} + +$kernel = new Kernel($env, $debug); +$application = new Application($kernel); +$application->run($input); diff --git a/bin/makeRelease.sh b/bin/makeRelease.sh index cefd67aef8..766ab35c4c 100755 --- a/bin/makeRelease.sh +++ b/bin/makeRelease.sh @@ -1,9 +1,7 @@ #!/bin/bash -PREVIOUS_SF_ENV=${SYMFONY_ENV} -PREVIOUS_EB_ENV=${ENGINEBLOCK_ENV} -export SYMFONY_ENV=prod -export ENGINEBLOCK_ENV=production +PREVIOUS_APP_ENV=${APP_ENV} +export APP_ENV=prod RELEASE_DIR=${HOME}/Releases GITHUB_USER=OpenConext @@ -166,5 +164,4 @@ then fi fi -export SYMFONY_ENV=${PREVIOUS_SF_ENV} -export ENGINEBLOCK_ENV=${PREVIOUS_EB_ENV} +export APP_ENV=${PREVIOUS_APP_ENV} diff --git a/ci/qa-config/rector.php b/ci/qa-config/rector.php new file mode 100644 index 0000000000..687ba884ee --- /dev/null +++ b/ci/qa-config/rector.php @@ -0,0 +1,36 @@ +withPaths([ + __DIR__ . '/../../config', + __DIR__ . '/../../src', + __DIR__ . '/../../library', + __DIR__ . '/../../tests', + ]) + ->withPhpSets() + ->withComposerBased(doctrine: true, phpunit: true, symfony: true) + ->withAttributesSets(symfony: false, doctrine: true, phpunit: true) + ->withSkip([ + \Rector\Php53\Rector\Ternary\TernaryToElvisRector::class, + \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class, + \Rector\Php70\Rector\StmtsAwareInterface\IfIssetToCoalescingRector::class, + \Rector\Php70\Rector\Ternary\TernaryToNullCoalescingRector::class, + \Rector\Php71\Rector\List_\ListToArrayDestructRector::class, + \Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector::class, + \Rector\Php73\Rector\FuncCall\SetCookieRector::class, + \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class, + \Rector\Php74\Rector\Assign\NullCoalescingOperatorRector::class, + \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class, + \Rector\Php80\Rector\Class_\StringableForToStringRector::class, + \Rector\Php80\Rector\Identical\StrStartsWithRector::class, + \Rector\Php80\Rector\NotIdentical\StrContainsRector::class, + \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class, + \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class, + \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class, + \Rector\Php81\Rector\Array_\FirstClassCallableRector::class, + \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class, + \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class, + \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class, + ]); diff --git a/ci/qa/all.sh b/ci/qa/all.sh index 972f99043b..e782ddd219 100755 --- a/ci/qa/all.sh +++ b/ci/qa/all.sh @@ -9,3 +9,4 @@ cd $(dirname $0)/../../ ./ci/qa/phpunit.sh ./ci/qa/behat.sh ./ci/qa/lint.sh +./ci/qa/rector.sh --dry-run diff --git a/ci/qa/behat.sh b/ci/qa/behat.sh index d542fa36ba..ab9ebf1002 100755 --- a/ci/qa/behat.sh +++ b/ci/qa/behat.sh @@ -4,7 +4,7 @@ set -e cd $(dirname $0)/../../ -CURRENT_ENV="${SYMFONY_ENV:-dev}" +CURRENT_ENV="${APP_ENV:-dev}" if [ "${CURRENT_ENV}" != "ci" ] then @@ -13,17 +13,23 @@ then fi echo -e "\nInstalling database fixtures...\n" -./app/console doctrine:schema:drop --force --env=ci -./app/console doctrine:schema:create --env=ci +./bin/console doctrine:schema:drop --force --env=ci +./bin/console doctrine:schema:create --env=ci echo -e "\nPreparing frontend assets\n" +rm -rf var/cache/ci EB_THEME=skeune ./theme/scripts/prepare-test.js > /dev/null +mkdir -p var/cache/ci +chown -R www-data:www-data var +chmod -R 2775 var +find var -type d -exec chmod 2775 {} \; +find var -type d -exec chown www-data:www-data {} \; -chown -R www-data app/cache/ +mkdir -p /tmp/eb-fixtures chmod -R 0777 /tmp/eb-fixtures echo -e "\nRun the Behat tests\n" -./vendor/bin/behat -c ./tests/behat-ci.yml --suite default -vv --format progress --strict $@ +./vendor/bin/behat -c ./tests/behat.yml --suite default -vv --format pretty --strict -#echo -e "\nBehat tests (with selenium and headless Chrome)\n" -#./vendor/bin/behat -c ./tests/behat-ci.yml --suite selenium -vv --format progress --strict +echo -e "\nBehat tests (with headless Chrome)\n" +./vendor/bin/behat -c ./tests/behat.yml --suite functional -vv --format pretty --strict diff --git a/ci/qa/lint.sh b/ci/qa/lint.sh index f1f6ec23f4..16eac7e720 100755 --- a/ci/qa/lint.sh +++ b/ci/qa/lint.sh @@ -4,11 +4,12 @@ set -e cd $(dirname $0)/../../ echo -e "\nTwig lint\n" -app/console lint:twig theme/ +bin/console lint:twig theme/ cd theme echo -e "\nLint frontend assets\n" +yarn install yarn lint cd - diff --git a/ci/qa/phpunit.sh b/ci/qa/phpunit.sh index 9865233c2a..bd12241a73 100755 --- a/ci/qa/phpunit.sh +++ b/ci/qa/phpunit.sh @@ -3,21 +3,24 @@ set -e cd $(dirname $0)/../../ -chown -R www-data app/cache/ +chown -R www-data var/cache/ +mkdir -p /tmp/eb-fixtures chmod -R 0777 /tmp/eb-fixtures echo -e "\nInstalling database fixtures...\n" -./app/console doctrine:schema:drop --force --env=ci -./app/console doctrine:schema:create --env=ci +./bin/console cache:clear --env=ci --no-warmup +./bin/console doctrine:schema:drop --force --env=ci +./bin/console doctrine:schema:create --env=ci echo -e "\nPHPUnit legacy tests\n" -./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=eb4 --coverage-text +XDEBUG_MODE=coverage ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=eb4 --coverage-clover coverage.xml echo -e "\nPHPUnit unit tests\n" -./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=unit --coverage-text +XDEBUG_MODE=coverage ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=unit --coverage-clover coverage.xml echo -e "\nPHPUnit API acceptance tests\n" -APP_ENV=ci ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=functional --coverage-text +./bin/console cache:clear --env=test --no-warmup +APP_ENV=test XDEBUG_MODE=coverage ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=functional --coverage-clover coverage.xml echo -e "\nPHPUnit integration tests\n" -./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=integration --coverage-text +XDEBUG_MODE=coverage ./vendor/bin/phpunit --configuration=./tests/phpunit.xml --testsuite=integration --coverage-clover coverage.xml diff --git a/ci/qa/rector.sh b/ci/qa/rector.sh new file mode 100755 index 0000000000..774400d0ad --- /dev/null +++ b/ci/qa/rector.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +# Ensure we run from project root +cd "$(dirname "$0")/../../" || exit 1 +./vendor/bin/rector --config=ci/qa-config/rector.php "$@" diff --git a/composer.json b/composer.json index 384d3ba81c..985e5d1efd 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "openconext/engineblock", "description": "OpenConext SAML proxy", + "version": "7.0.0-dev", "type": "project", "keywords": [ "saml", @@ -15,52 +16,70 @@ "source": "https://github.com/OpenConext/OpenConext-engineblock" }, "require": { - "php": "~7.2", + "php": "^8.2", "ext-dom": "*", "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", - "beberlei/assert": "^2.6", + "ext-pdo": "*", + "beberlei/assert": "^3.3", "composer/package-versions-deprecated": "^1.11", - "doctrine/doctrine-bundle": "^1.11", - "doctrine/doctrine-migrations-bundle": "^1.3", - "doctrine/orm": "~2.6", - "guzzlehttp/guzzle": "^6.3", - "incenteev/composer-parameter-handler": "~2.0", - "monolog/monolog": "~1.13", - "openconext/monitor-bundle": "^2.1", - "openconext/saml-value-object": "^1.3", - "pimple/pimple": "~2.1", - "ramsey/uuid": "^3.3.0", - "sensio/framework-extra-bundle": "^3.0", - "sensio/generator-bundle": "^3.0", - "simplesamlphp/saml2": "4.17.*", - "swiftmailer/swiftmailer": "^5.4", - "symfony/monolog-bundle": "^3.1.0", - "symfony/swiftmailer-bundle": "^2.6", - "symfony/symfony": "3.4.*", - "twig/extensions": "^1.5", - "twig/twig": "^2.0" + "doctrine/dbal": "^3.10.2", + "doctrine/doctrine-bundle": "^2.13.3", + "doctrine/doctrine-migrations-bundle": "^3.4.2", + "doctrine/orm": "^3.5.2", + "guzzlehttp/guzzle": "^7.10", + "incenteev/composer-parameter-handler": "^2.2", + "monolog/monolog": "^2.10", + "openconext/monitor-bundle": "^4.2", + "openconext/saml-value-object": "^3.0", + "pimple/pimple": "^3.5", + "ramsey/uuid": "^4.9", + "robrichards/xmlseclibs": "^3.1", + "sensio/framework-extra-bundle": "^6.2", + "simplesamlphp/saml2": "^4.0", + "symfony/asset": "^5.4", + "symfony/console": "^5.4", + "symfony/dotenv": "^5.4", + "symfony/expression-language": "^5.4", + "symfony/flex": "^2.8.2", + "symfony/form": "^5.4", + "symfony/framework-bundle": "^5.4", + "symfony/mailer": "5.4.*", + "symfony/monolog-bundle": "^3.5", + "symfony/security-bundle": "^5.4", + "symfony/templating": "5.4.*", + "symfony/translation": "^5.4", + "symfony/twig-bundle": "^5.4", + "symfony/validator": "^5.4", + "symfony/yaml": "^5.4", + "twig/twig": "^v3.11.3" }, "require-dev": { "ext-zlib": "*", - "behat/behat": "~3.7.0", + "behat/behat": "^3.23", "behat/mink": "~1.7", - "behat/mink-extension": "~2.0", - "behat/mink-goutte-driver": "~1.0", - "behat/mink-selenium2-driver": "^1.3", - "behat/symfony2-extension": "~2.0", + "behat/mink-browserkit-driver": "^2.0", + "dmore/behat-chrome-extension": "^1.4", + "dmore/chrome-mink-driver": "^2.9", + "friends-of-behat/mink-extension": "^2.6", + "friends-of-behat/symfony-extension": "^2.4", "ingenerator/behat-tableassert": "^1.1", - "league/flysystem": "^2.5", - "liip/functional-test-bundle": "^4.3", - "malukenho/docheader": "^0.1.8", - "mockery/mockery": "^1.3", + "league/flysystem": "^3.30", + "liip/functional-test-bundle": "^4.9", + "malukenho/docheader": "^1.1", + "mockery/mockery": "^1.6", "phake/phake": "^4.4", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "^2.13", - "phpunit/phpunit": "^8.5", + "phpunit/phpunit": "^10.5.55", + "rector/rector": "^2.1", "squizlabs/php_codesniffer": "^3.7", - "symfony/phpunit-bridge": "^3.0" + "symfony/debug-bundle": "5.4.*", + "symfony/http-client": "5.4.*", + "symfony/phpunit-bridge": "^7.3", + "symfony/var-dumper": "5.4.*", + "symfony/web-profiler-bundle": "5.4.*" }, "replace": { "symfony/polyfill-mbstring": "1.99", @@ -69,6 +88,10 @@ "symfony/polyfill-php56": "1.99" }, "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, "post-install-cmd": [ "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters" ], @@ -92,8 +115,7 @@ "OpenConext\\": "src/OpenConext" }, "classmap": [ - "app/AppKernel.php", - "app/AppCache.php" + "src/Kernel.php" ] }, "autoload-dev": { @@ -103,31 +125,30 @@ "tests/integration/OpenConext/", "tests/functional/OpenConext/" ] - }, - "files": [ - "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php" - ] + } }, "config": { "optimize-autoloader": true, "platform": { - "php": "7.2" + "php": "8.2" }, - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "symfony/flex": true + } }, "extra": { - "symfony-app-dir": "app", - "symfony-var-dir": "app", - "symfony-bin-dir": "app", - "symfony-web-dir": "web", - "incenteev-parameters": [ - { - "file": "app/config/parameters.yml" - }, - { - "file": "app/config/functional_testing.yml" - } - ] + "symfony": { + "allow-contrib": false, + "require": "5.4.*" + }, + "symfony-var-dir": "var", + "symfony-bin-dir": "bin", + "symfony-web-dir": "public", + "incenteev-parameters": { + "file": "config/packages/parameters.yml", + "dist-file": "config/packages/parameters.yml.dist" + } }, "archive": { "exclude": [ diff --git a/composer.lock b/composer.lock index e67a2e4e9d..849801c826 100644 --- a/composer.lock +++ b/composer.lock @@ -4,29 +4,37 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5a2344673cd54385a01a30f9a8940f79", + "content-hash": "8214c600a0278c65443803dee8f736f7", "packages": [ { "name": "beberlei/assert", - "version": "v2.9.9", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/beberlei/assert.git", - "reference": "124317de301b7c91d5fce34c98bba2c6925bec95" + "reference": "b5fd8eacd8915a1b627b8bfc027803f1939734dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beberlei/assert/zipball/124317de301b7c91d5fce34c98bba2c6925bec95", - "reference": "124317de301b7c91d5fce34c98bba2c6925bec95", + "url": "https://api.github.com/repos/beberlei/assert/zipball/b5fd8eacd8915a1b627b8bfc027803f1939734dd", + "reference": "b5fd8eacd8915a1b627b8bfc027803f1939734dd", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-mbstring": "*", - "php": ">=5.3" + "ext-simplexml": "*", + "php": "^7.1 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.1.1", - "phpunit/phpunit": "^4.8.35|^5.7" + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": ">=6.0.0", + "yoast/phpunit-polyfills": "^0.1.0" + }, + "suggest": { + "ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles" }, "type": "library", "autoload": { @@ -59,20 +67,84 @@ "assertion", "validation" ], - "time": "2019-05-28T15:27:37+00:00" + "support": { + "issues": "https://github.com/beberlei/assert/issues", + "source": "https://github.com/beberlei/assert/tree/v3.3.3" + }, + "time": "2024-07-15T13:18:35+00:00" + }, + { + "name": "brick/math", + "version": "0.14.0", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", + "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2", + "shasum": "" + }, + "require": { + "php": "^8.2" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.14.0" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-08-29T12:40:03+00:00" }, { "name": "composer/package-versions-deprecated", - "version": "1.11.99", + "version": "1.11.99.5", "source": { "type": "git", "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855" + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855", - "reference": "c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", "shasum": "" }, "require": { @@ -114,6 +186,10 @@ } ], "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" + }, "funding": [ { "url": "https://packagist.com", @@ -128,34 +204,38 @@ "type": "tidelift" } ], - "time": "2020-08-25T05:50:16+00:00" + "time": "2022-01-17T14:14:24+00:00" }, { "name": "doctrine/annotations", - "version": "1.13.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f" + "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f", - "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/901c2ee5d26eb64ff43c47976e114bf00843acf7", + "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", + "doctrine/lexer": "^2 || ^3", "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", + "php": "^7.2 || ^8.0", "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2" + "doctrine/cache": "^2.0", + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.10.28", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^5.4 || ^6.4 || ^7", + "vimeo/psalm": "^4.30 || ^5.14" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, "type": "library", "autoload": { @@ -196,41 +276,39 @@ "docblock", "parser" ], - "time": "2021-05-16T18:07:53+00:00" + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/2.0.2" + }, + "time": "2024-09-05T10:17:24+00:00" }, { "name": "doctrine/cache", - "version": "1.11.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "163074496dc7c3c7b8ccbf3d4376c0187424ed81" + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/163074496dc7c3c7b8ccbf3d4376c0187424ed81", - "reference": "163074496dc7c3c7b8ccbf3d4376c0187424ed81", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", "shasum": "" }, "require": { "php": "~7.1 || ^8.0" }, "conflict": { - "doctrine/common": ">2.2,<2.4", - "psr/cache": ">=3" + "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^8.0", - "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", - "predis/predis": "~1.0", - "psr/cache": "^1.0 || ^2.0", - "symfony/cache": "^4.4 || ^5.2" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" }, "type": "library", "autoload": { @@ -277,6 +355,10 @@ "redis", "xcache" ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -291,35 +373,38 @@ "type": "tidelift" } ], - "time": "2021-05-18T16:45:32+00:00" + "time": "2022-05-20T20:07:39+00:00" }, { "name": "doctrine/collections", - "version": "1.6.7", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a" + "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/55f8b799269a1a472457bd1a41b4f379d4cfba4a", - "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d", + "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d", "shasum": "" }, "require": { - "php": "^7.1.3 || ^8.0" + "doctrine/deprecations": "^1", + "php": "^8.1", + "symfony/polyfill-php84": "^1.30" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan-shim": "^0.9.2", - "phpunit/phpunit": "^7.0", - "vimeo/psalm": "^3.8.1" + "doctrine/coding-standard": "^12", + "ext-json": "*", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^10.5" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + "Doctrine\\Common\\Collections\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -356,89 +441,10 @@ "iterators", "php" ], - "time": "2020-07-27T17:53:49+00:00" - }, - { - "name": "doctrine/common", - "version": "2.13.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "f3812c026e557892c34ef37f6ab808a6b567da7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/f3812c026e557892c34ef37f6ab808a6b567da7f", - "reference": "f3812c026e557892c34ef37f6ab808a6b567da7f", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/inflector": "^1.0", - "doctrine/lexer": "^1.0", - "doctrine/persistence": "^1.3.3", - "doctrine/reflection": "^1.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^1.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^4.0.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } + "support": { + "issues": "https://github.com/doctrine/collections/issues", + "source": "https://github.com/doctrine/collections/tree/2.3.0" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", - "homepage": "https://www.doctrine-project.org/projects/common.html", - "keywords": [ - "common", - "doctrine", - "php" - ], "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -449,38 +455,49 @@ "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections", "type": "tidelift" } ], - "time": "2020-06-05T16:46:05+00:00" + "time": "2025-03-22T10:17:19+00:00" }, { "name": "doctrine/dbal", - "version": "v2.10.1", + "version": "3.10.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8" + "reference": "c6c16cf787eaba3112203dfcd715fa2059c62282" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8", - "reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c6c16cf787eaba3112203dfcd715fa2059c62282", + "reference": "c6c16cf787eaba3112203dfcd715fa2059c62282", "shasum": "" }, "require": { - "doctrine/cache": "^1.0", - "doctrine/event-manager": "^1.0", - "ext-pdo": "*", - "php": "^7.2" + "composer-runtime-api": "^2", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1|^2", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "doctrine/cache": "< 1.11" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "jetbrains/phpstorm-stubs": "^2019.1", - "phpstan/phpstan": "^0.11.3", - "phpunit/phpunit": "^8.4.1", - "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + "doctrine/cache": "^1.11|^2.0", + "doctrine/coding-standard": "13.0.1", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.1", + "phpstan/phpstan": "2.1.22", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "9.6.23", + "slevomat/coding-standard": "8.16.2", + "squizlabs/php_codesniffer": "3.13.1", + "symfony/cache": "^5.4|^6.0|^7.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." @@ -489,15 +506,9 @@ "bin/doctrine-dbal" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.10.x-dev", - "dev-develop": "3.0.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + "Doctrine\\DBAL\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -540,159 +551,147 @@ "queryobject", "sasql", "sql", - "sqlanywhere", "sqlite", "sqlserver", "sqlsrv" ], - "time": "2020-01-04T12:56:21+00:00" + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.10.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2025-09-04T23:51:27+00:00" }, { - "name": "doctrine/doctrine-bundle", - "version": "1.12.7", + "name": "doctrine/deprecations", + "version": "1.1.5", "source": { "type": "git", - "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "18fb7d271676dcb8e882adb0157ac1445c8fe89c" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/18fb7d271676dcb8e882adb0157ac1445c8fe89c", - "reference": "18fb7d271676dcb8e882adb0157ac1445c8fe89c", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", "shasum": "" }, "require": { - "doctrine/dbal": "^2.5.12", - "doctrine/doctrine-cache-bundle": "~1.2", - "doctrine/persistence": "^1.3.3", - "jdorn/sql-formatter": "^1.2.16", - "php": "^7.1", - "symfony/cache": "^3.4.30|^4.3.3", - "symfony/config": "^3.4.30|^4.3.3", - "symfony/console": "^3.4.30|^4.3.3", - "symfony/dependency-injection": "^3.4.30|^4.3.3", - "symfony/doctrine-bridge": "^3.4.30|^4.3.3", - "symfony/framework-bundle": "^3.4.30|^4.3.3", - "symfony/service-contracts": "^1.1.1|^2.0" + "php": "^7.1 || ^8.0" }, "conflict": { - "doctrine/orm": "<2.6", - "twig/twig": "<1.34|>=2.0,<2.4" + "phpunit/phpunit": "<=7.5 || >=13" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "doctrine/orm": "^2.6", - "ocramius/proxy-manager": "^2.1", - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^7.5", - "symfony/phpunit-bridge": "^4.2", - "symfony/property-info": "^3.4.30|^4.3.3", - "symfony/proxy-manager-bridge": "^3.4|^4|^5", - "symfony/twig-bridge": "^3.4|^4.1", - "symfony/validator": "^3.4.30|^4.3.3", - "symfony/web-profiler-bundle": "^3.4.30|^4.3.3", - "symfony/yaml": "^3.4.30|^4.3.3", - "twig/twig": "^1.34|^2.12" + "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": { - "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", - "symfony/web-profiler-bundle": "To use the data collector." - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.12.x-dev" - } + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, + "type": "library", "autoload": { "psr-4": { - "Doctrine\\Bundle\\DoctrineBundle\\": "" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org/" - } - ], - "description": "Symfony DoctrineBundle", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "orm", - "persistence" - ], - "time": "2020-01-10T12:25:22+00:00" + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" }, { - "name": "doctrine/doctrine-cache-bundle", - "version": "1.4.0", + "name": "doctrine/doctrine-bundle", + "version": "2.13.3", "source": { "type": "git", - "url": "https://github.com/doctrine/DoctrineCacheBundle.git", - "reference": "6bee2f9b339847e8a984427353670bad4e7bdccb" + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "aac7562c96d117e16cbadfe41bef17d2fc760f74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineCacheBundle/zipball/6bee2f9b339847e8a984427353670bad4e7bdccb", - "reference": "6bee2f9b339847e8a984427353670bad4e7bdccb", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/aac7562c96d117e16cbadfe41bef17d2fc760f74", + "reference": "aac7562c96d117e16cbadfe41bef17d2fc760f74", "shasum": "" }, "require": { - "doctrine/cache": "^1.4.2", - "doctrine/inflector": "^1.0", - "php": "^7.1", - "symfony/doctrine-bridge": "^3.4|^4.0" + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/dbal": "^3.7.0 || ^4.0", + "doctrine/persistence": "^2.2 || ^3", + "doctrine/sql-formatter": "^1.0.1", + "php": "^7.4 || ^8.0", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/doctrine-bridge": "^5.4.46 || ~6.3.12 || ^6.4.3 || ^7.0.3", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3" + }, + "conflict": { + "doctrine/annotations": ">=3.0", + "doctrine/orm": "<2.17 || >=4.0", + "twig/twig": "<1.34 || >=2.0 <2.4" }, "require-dev": { - "instaclick/coding-standard": "~1.1", - "instaclick/object-calisthenics-sniffs": "dev-master", - "instaclick/symfony2-coding-standard": "dev-remaster", - "phpunit/phpunit": "^7.0", - "predis/predis": "~0.8", - "satooshi/php-coveralls": "^1.0", - "squizlabs/php_codesniffer": "~1.5", - "symfony/console": "^3.4|^4.0", - "symfony/finder": "^3.4|^4.0", - "symfony/framework-bundle": "^3.4|^4.0", - "symfony/phpunit-bridge": "^3.4|^4.0", - "symfony/security-acl": "^2.8", - "symfony/validator": "^3.4|^4.0", - "symfony/yaml": "^3.4|^4.0" + "doctrine/annotations": "^1 || ^2", + "doctrine/coding-standard": "^12", + "doctrine/deprecations": "^1.0", + "doctrine/orm": "^2.17 || ^3.0", + "friendsofphp/proxy-manager-lts": "^1.0", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9.5.26", + "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", + "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" }, "suggest": { - "symfony/security-acl": "For using this bundle to cache ACLs" + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "ext-pdo": "*", + "symfony/web-profiler-bundle": "To use the data collector." }, "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Bundle\\DoctrineCacheBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Doctrine\\Bundle\\DoctrineBundle\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -707,64 +706,81 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Fabio B. Silva", - "email": "fabio.bat.silva@gmail.com" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@hotmail.com" - }, { "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "homepage": "https://symfony.com/contributors" }, { "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org/" + "homepage": "https://www.doctrine-project.org/" } ], - "description": "Symfony Bundle for Doctrine Cache", + "description": "Symfony DoctrineBundle", "homepage": "https://www.doctrine-project.org", "keywords": [ - "cache", - "caching" + "database", + "dbal", + "orm", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineBundle/issues", + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.13.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle", + "type": "tidelift" + } ], - "abandoned": true, - "time": "2019-11-29T11:22:01+00:00" + "time": "2025-03-16T10:55:20+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", - "version": "v1.3.2", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "49fa399181db4bf4f9f725126bd1cb65c4398dce" + "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/49fa399181db4bf4f9f725126bd1cb65c4398dce", - "reference": "49fa399181db4bf4f9f725126bd1cb65c4398dce", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/5a6ac7120c2924c4c070a869d08b11ccf9e277b9", + "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9", "shasum": "" }, "require": { - "doctrine/doctrine-bundle": "~1.0", - "doctrine/migrations": "^1.1", - "php": ">=5.4.0", - "symfony/framework-bundle": "~2.7|~3.3|~4.0" + "doctrine/doctrine-bundle": "^2.4", + "doctrine/migrations": "^3.2", + "php": "^7.2 || ^8.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^7.4" + "composer/semver": "^3.0", + "doctrine/coding-standard": "^12", + "doctrine/orm": "^2.6 || ^3", + "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" }, "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Bundle\\MigrationsBundle\\": "" + "Doctrine\\Bundle\\MigrationsBundle\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -773,60 +789,76 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org" + "homepage": "https://www.doctrine-project.org" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony DoctrineMigrationsBundle", - "homepage": "http://www.doctrine-project.org", + "homepage": "https://www.doctrine-project.org", "keywords": [ "dbal", "migrations", "schema" ], - "time": "2018-12-03T11:55:33+00:00" + "support": { + "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.4.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", + "type": "tidelift" + } + ], + "time": "2025-03-11T17:36:26+00:00" }, { "name": "doctrine/event-manager", - "version": "1.1.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f" + "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/41370af6a30faa9dc0368c4a6814d596e81aba7f", - "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520", + "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520", "shasum": "" }, "require": { + "doctrine/deprecations": "^0.5.3 || ^1", "php": "^7.1 || ^8.0" }, "conflict": { - "doctrine/common": "<2.9@dev" + "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.0" + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.8", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.24" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" + "Doctrine\\Common\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -868,6 +900,10 @@ "event system", "events" ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/1.2.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -882,42 +918,36 @@ "type": "tidelift" } ], - "time": "2020-05-29T18:28:51+00:00" + "time": "2022-10-12T20:51:15+00:00" }, { "name": "doctrine/inflector", - "version": "1.4.4", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9" + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", - "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector", - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -960,6 +990,10 @@ "uppercase", "words" ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.1.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -974,7 +1008,7 @@ "type": "tidelift" } ], - "time": "2021-04-16T17:34:40+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "doctrine/instantiator", @@ -1048,35 +1082,32 @@ }, { "name": "doctrine/lexer", - "version": "1.2.1", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", - "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11.8", - "phpunit/phpunit": "^8.2" + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1106,6 +1137,10 @@ "parser", "php" ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -1120,54 +1155,64 @@ "type": "tidelift" } ], - "time": "2020-05-25T17:44:05+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "doctrine/migrations", - "version": "v1.8.1", + "version": "3.9.4", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "215438c0eef3e5f9b7da7d09c6b90756071b43e6" + "reference": "1b88fcb812f2cd6e77c83d16db60e3cf1e35c66c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/215438c0eef3e5f9b7da7d09c6b90756071b43e6", - "reference": "215438c0eef3e5f9b7da7d09c6b90756071b43e6", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/1b88fcb812f2cd6e77c83d16db60e3cf1e35c66c", + "reference": "1b88fcb812f2cd6e77c83d16db60e3cf1e35c66c", "shasum": "" }, "require": { - "doctrine/dbal": "~2.6", - "ocramius/proxy-manager": "^1.0|^2.0", - "php": "^7.1", - "symfony/console": "~3.3|^4.0" + "composer-runtime-api": "^2", + "doctrine/dbal": "^3.6 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2.0", + "php": "^8.1", + "psr/log": "^1.1.3 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^6.2 || ^7.0" + }, + "conflict": { + "doctrine/orm": "<2.12 || >=4" }, "require-dev": { - "doctrine/coding-standard": "^1.0", - "doctrine/orm": "~2.5", - "jdorn/sql-formatter": "~1.1", - "mikey179/vfsstream": "^1.6", - "phpunit/phpunit": "~7.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/yaml": "~3.3|^4.0" + "doctrine/coding-standard": "^13", + "doctrine/orm": "^2.13 || ^3", + "doctrine/persistence": "^2 || ^3 || ^4", + "doctrine/sql-formatter": "^1.0", + "ext-pdo_sqlite": "*", + "fig/log-test": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpstan/phpstan-symfony": "^2", + "phpunit/phpunit": "^10.3 || ^11.0 || ^12.0", + "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { - "jdorn/sql-formatter": "Allows to generate formatted SQL with the diff command.", + "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", "symfony/yaml": "Allows the use of yaml for migration configuration files." }, "bin": [ "bin/doctrine-migrations" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "v1.8.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Migrations\\": "lib/Doctrine/Migrations", - "Doctrine\\DBAL\\Migrations\\": "lib/Doctrine/DBAL/Migrations" + "Doctrine\\Migrations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1188,62 +1233,83 @@ "email": "contact@mikesimonson.com" } ], - "description": "Database Schema migrations using Doctrine DBAL", + "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.", "homepage": "https://www.doctrine-project.org/projects/migrations.html", "keywords": [ "database", + "dbal", "migrations" ], - "time": "2018-06-06T21:00:30+00:00" + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/3.9.4" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2025-08-19T06:41:07+00:00" }, { "name": "doctrine/orm", - "version": "v2.7.1", + "version": "3.5.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "445796af0e873d9bd04f2502d322a7d5009b6846" + "reference": "5a541b8b3a327ab1ea5f93b1615b4ff67a34e109" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/445796af0e873d9bd04f2502d322a7d5009b6846", - "reference": "445796af0e873d9bd04f2502d322a7d5009b6846", + "url": "https://api.github.com/repos/doctrine/orm/zipball/5a541b8b3a327ab1ea5f93b1615b4ff67a34e109", + "reference": "5a541b8b3a327ab1ea5f93b1615b4ff67a34e109", "shasum": "" }, "require": { - "doctrine/annotations": "^1.8", - "doctrine/cache": "^1.9.1", - "doctrine/collections": "^1.5", - "doctrine/common": "^2.11", - "doctrine/dbal": "^2.9.3", - "doctrine/event-manager": "^1.1", - "doctrine/instantiator": "^1.3", - "doctrine/persistence": "^1.2", - "ext-pdo": "*", - "ocramius/package-versions": "^1.2", - "php": "^7.1", - "symfony/console": "^3.0|^4.0|^5.0" + "composer-runtime-api": "^2", + "doctrine/collections": "^2.2", + "doctrine/dbal": "^3.8.2 || ^4", + "doctrine/deprecations": "^0.5.3 || ^1", + "doctrine/event-manager": "^1.2 || ^2", + "doctrine/inflector": "^1.4 || ^2.0", + "doctrine/instantiator": "^1.3 || ^2", + "doctrine/lexer": "^3", + "doctrine/persistence": "^3.3.1 || ^4", + "ext-ctype": "*", + "php": "^8.1", + "psr/cache": "^1 || ^2 || ^3", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/var-exporter": "^6.3.9 || ^7.0" }, "require-dev": { - "doctrine/coding-standard": "^5.0", - "phpunit/phpunit": "^7.5", - "symfony/yaml": "^3.4|^4.0|^5.0" + "doctrine/coding-standard": "^13.0", + "phpbench/phpbench": "^1.0", + "phpdocumentor/guides-cli": "^1.4", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "2.0.3", + "phpstan/phpstan-deprecation-rules": "^2", + "phpunit/phpunit": "^10.4.0", + "psr/log": "^1 || ^2 || ^3", + "squizlabs/php_codesniffer": "3.12.0", + "symfony/cache": "^5.4 || ^6.2 || ^7.0" }, "suggest": { - "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + "ext-dom": "Provides support for XSD validation for XML mapping files", + "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0" }, - "bin": [ - "bin/doctrine" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\ORM\\": "lib/Doctrine/ORM" + "Doctrine\\ORM\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1278,49 +1344,47 @@ "database", "orm" ], - "time": "2020-02-15T14:35:56+00:00" + "support": { + "issues": "https://github.com/doctrine/orm/issues", + "source": "https://github.com/doctrine/orm/tree/3.5.2" + }, + "time": "2025-08-08T17:00:40+00:00" }, { "name": "doctrine/persistence", - "version": "1.3.8", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "7a6eac9fb6f61bba91328f15aa7547f4806ca288" + "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/7a6eac9fb6f61bba91328f15aa7547f4806ca288", - "reference": "7a6eac9fb6f61bba91328f15aa7547f4806ca288", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/0ea965320cec355dba75031c1b23d4c78362e3ff", + "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff", "shasum": "" }, "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.2", - "php": "^7.1 || ^8.0" + "doctrine/event-manager": "^1 || ^2", + "php": "^7.2 || ^8.0", + "psr/cache": "^1.0 || ^2.0 || ^3.0" }, "conflict": { - "doctrine/common": "<2.10@dev" + "doctrine/common": "<2.10" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", - "vimeo/psalm": "^3.11" + "doctrine/coding-standard": "^12", + "doctrine/common": "^3.0", + "phpstan/phpstan": "1.12.7", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5.38 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common", - "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + "Doctrine\\Persistence\\": "src/Persistence" } }, "notification-url": "https://packagist.org/downloads/", @@ -1354,7 +1418,7 @@ } ], "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://doctrine-project.org/projects/persistence.html", + "homepage": "https://www.doctrine-project.org/projects/persistence.html", "keywords": [ "mapper", "object", @@ -1362,6 +1426,10 @@ "orm", "persistence" ], + "support": { + "issues": "https://github.com/doctrine/persistence/issues", + "source": "https://github.com/doctrine/persistence/tree/3.4.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -1376,46 +1444,38 @@ "type": "tidelift" } ], - "time": "2020-06-20T12:56:16+00:00" + "time": "2024-10-30T19:48:12+00:00" }, { - "name": "doctrine/reflection", - "version": "1.2.2", + "name": "doctrine/sql-formatter", + "version": "1.5.2", "source": { "type": "git", - "url": "https://github.com/doctrine/reflection.git", - "reference": "fa587178be682efe90d005e3a322590d6ebb59a5" + "url": "https://github.com/doctrine/sql-formatter.git", + "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/reflection/zipball/fa587178be682efe90d005e3a322590d6ebb59a5", - "reference": "fa587178be682efe90d005e3a322590d6ebb59a5", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d6d00aba6fd2957fe5216fe2b7673e9985db20c8", + "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8", "shasum": "" }, "require": { - "doctrine/annotations": "^1.0", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": "<2.9" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^6.0 || ^8.2.0", - "doctrine/common": "^2.10", - "phpstan/phpstan": "^0.11.0 || ^0.12.20", - "phpstan/phpstan-phpunit": "^0.11.0 || ^0.12.16", - "phpunit/phpunit": "^7.5 || ^9.1.5" + "doctrine/coding-standard": "^12", + "ergebnis/phpunit-slow-test-detector": "^2.14", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5" }, + "bin": [ + "bin/sql-formatter" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" + "Doctrine\\SqlFormatter\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1424,73 +1484,58 @@ ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "https://jeremydorn.com/" } ], - "description": "The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some additional functionality on top of the reflection functionality that comes with PHP. It allows you to get the reflection information about classes, methods and properties statically.", - "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/doctrine/sql-formatter/", "keywords": [ - "reflection", - "static" + "highlight", + "sql" ], - "abandoned": "roave/better-reflection", - "time": "2020-10-27T21:46:55+00:00" + "support": { + "issues": "https://github.com/doctrine/sql-formatter/issues", + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.2" + }, + "time": "2025-01-24T11:45:48+00:00" }, { - "name": "fig/link-util", - "version": "1.1.2", + "name": "egulias/email-validator", + "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/php-fig/link-util.git", - "reference": "5d7b8d04ed3393b4b59968ca1e906fb7186d81e8" + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/link-util/zipball/5d7b8d04ed3393b4b59968ca1e906fb7186d81e8", - "reference": "5d7b8d04ed3393b4b59968ca1e906fb7186d81e8", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", "shasum": "" }, "require": { - "php": ">=5.5.0", - "psr/link": "~1.0@dev" - }, - "provide": { - "psr/link-implementation": "1.0" + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "phpunit/phpunit": "^5.1", - "squizlabs/php_codesniffer": "^2.3.1" + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { "psr-4": { - "Fig\\Link\\": "src/" + "Egulias\\EmailValidator\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1499,54 +1544,73 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Eduardo Gulias Davis" } ], - "description": "Common utility implementations for HTTP links", + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", "keywords": [ - "http", - "http-link", - "link", - "psr", - "psr-13", - "rest" + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } ], - "time": "2021-02-03T23:36:04+00:00" + "time": "2025-03-06T22:45:56+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.5.8", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.9", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.17" + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.1" + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "6.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { @@ -1599,16 +1663,21 @@ } ], "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", "keywords": [ "client", "curl", "framework", "http", "http client", + "psr-18", + "psr-7", "rest", "web service" ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -1623,38 +1692,37 @@ "type": "tidelift" } ], - "time": "2022-06-20T22:16:07+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.1", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", - "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -1689,6 +1757,10 @@ "keywords": [ "promise" ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.3.0" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -1703,42 +1775,48 @@ "type": "tidelift" } ], - "time": "2021-10-22T20:56:57+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.9.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/e4490cabc77465aaee90b20cfc9a770f8c04be6b", - "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { - "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } @@ -1777,6 +1855,11 @@ "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", @@ -1792,7 +1875,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.9.1" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -1808,35 +1891,37 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:00:37+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "incenteev/composer-parameter-handler", - "version": "v2.1.3", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/Incenteev/ParameterHandler.git", - "reference": "933c45a34814f27f2345c11c37d46b3ca7303550" + "reference": "90bffce926e96b365579a2ef024aab457f4b80c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Incenteev/ParameterHandler/zipball/933c45a34814f27f2345c11c37d46b3ca7303550", - "reference": "933c45a34814f27f2345c11c37d46b3ca7303550", + "url": "https://api.github.com/repos/Incenteev/ParameterHandler/zipball/90bffce926e96b365579a2ef024aab457f4b80c5", + "reference": "90bffce926e96b365579a2ef024aab457f4b80c5", "shasum": "" }, "require": { - "php": ">=5.3.3", - "symfony/yaml": "^2.3 || ^3.0 || ^4.0" + "php": ">=7.4", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "composer/composer": "^1.0@dev", - "symfony/filesystem": "^2.3 || ^3 || ^4", - "symfony/phpunit-bridge": "^4.0" + "composer/composer": "^2.0@dev", + "phpspec/prophecy-phpunit": "^2.1", + "phpunit/phpunit": "^9.6", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/phpunit-bridge": "^6.4.1 || ^7.0.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -1859,105 +1944,75 @@ "keywords": [ "parameters management" ], - "time": "2018-02-13T18:05:56+00:00" - }, - { - "name": "jdorn/sql-formatter", - "version": "v1.2.17", - "source": { - "type": "git", - "url": "https://github.com/jdorn/sql-formatter.git", - "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", - "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "lib" - ] + "support": { + "issues": "https://github.com/Incenteev/ParameterHandler/issues", + "source": "https://github.com/Incenteev/ParameterHandler/tree/v2.2.0" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Dorn", - "email": "jeremy@jeremydorn.com", - "homepage": "http://jeremydorn.com/" - } - ], - "description": "a PHP SQL highlighting library", - "homepage": "https://github.com/jdorn/sql-formatter/", - "keywords": [ - "highlight", - "sql" - ], - "time": "2014-01-12T16:20:24+00:00" + "time": "2023-12-09T10:31:14+00:00" }, { "name": "monolog/monolog", - "version": "1.26.0", + "version": "2.10.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33" + "reference": "5cf826f2991858b54d5c3809bee745560a1042a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/2209ddd84e7ef1256b7af205d0717fb62cfc9c33", - "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5cf826f2991858b54d5c3809bee745560a1042a7", + "reference": "5cf826f2991858b54d5c3809bee745560a1042a7", "shasum": "" }, "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpstan/phpstan": "^0.12.59", - "phpunit/phpunit": "~4.5", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "^5.3|^6.0" + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.38 || ^9.6.19", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, "autoload": { "psr-4": { "Monolog\\": "src/Monolog" @@ -1971,16 +2026,20 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ "log", "logging", "psr-3" ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.10.0" + }, "funding": [ { "url": "https://github.com/Seldaek", @@ -1991,109 +2050,40 @@ "type": "tidelift" } ], - "time": "2020-12-14T12:56:38+00:00" - }, - { - "name": "ocramius/proxy-manager", - "version": "2.2.3", - "source": { - "type": "git", - "url": "https://github.com/Ocramius/ProxyManager.git", - "reference": "4d154742e31c35137d5374c998e8f86b54db2e2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/4d154742e31c35137d5374c998e8f86b54db2e2f", - "reference": "4d154742e31c35137d5374c998e8f86b54db2e2f", - "shasum": "" - }, - "require": { - "ocramius/package-versions": "^1.1.3", - "php": "^7.2.0", - "zendframework/zend-code": "^3.3.0" - }, - "require-dev": { - "couscous/couscous": "^1.6.1", - "ext-phar": "*", - "humbug/humbug": "1.0.0-RC.0@RC", - "nikic/php-parser": "^3.1.1", - "padraic/phpunit-accelerator": "dev-master@DEV", - "phpbench/phpbench": "^0.12.2", - "phpstan/phpstan": "dev-master#856eb10a81c1d27c701a83f167dc870fd8f4236a as 0.9.999", - "phpstan/phpstan-phpunit": "dev-master#5629c0a1f4a9c417cb1077cf6693ad9753895761", - "phpunit/phpunit": "^6.4.3", - "squizlabs/php_codesniffer": "^2.9.1" - }, - "suggest": { - "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects", - "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)", - "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)", - "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "ProxyManager\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.io/" - } - ], - "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", - "homepage": "https://github.com/Ocramius/ProxyManager", - "keywords": [ - "aop", - "lazy loading", - "proxy", - "proxy pattern", - "service proxies" - ], - "time": "2019-08-10T08:37:15+00:00" + "time": "2024-11-12T12:43:37+00:00" }, { "name": "openconext/monitor-bundle", - "version": "2.1.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/OpenConext/Monitor-bundle.git", - "reference": "f06e967b702bc5d78d85c39ba4a90219af152a67" + "reference": "6167c618146da13300eacf8997e957b1f3c25f49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/OpenConext/Monitor-bundle/zipball/f06e967b702bc5d78d85c39ba4a90219af152a67", - "reference": "f06e967b702bc5d78d85c39ba4a90219af152a67", + "url": "https://api.github.com/repos/OpenConext/Monitor-bundle/zipball/6167c618146da13300eacf8997e957b1f3c25f49", + "reference": "6167c618146da13300eacf8997e957b1f3c25f49", "shasum": "" }, "require": { - "php": ">=5.4,<8.0-dev", - "symfony/dependency-injection": ">=3.4,<5", - "symfony/framework-bundle": ">=3.4,<5", - "webmozart/assert": "^1.2" + "doctrine/orm": "^2.9|^3.0", + "php": ">=8.2, <9.0-dev", + "symfony/dependency-injection": "^5.4|^6.3|^7.0", + "symfony/framework-bundle": "^5.4|^6.3|^7.0", + "webmozart/assert": "^1.10" }, "require-dev": { - "jakub-onderka/php-parallel-lint": "^0.9.2", - "malukenho/docheader": "^0.1.6", - "matthiasnoback/symfony-config-test": "^2.1", - "mockery/mockery": "~0.9", - "phpdocumentor/reflection-docblock": "3.3.*", - "phpmd/phpmd": "^2.6", - "phpunit/php-token-stream": "1.4.*", - "phpunit/phpunit": "^5.7", - "sebastian/phpcpd": "^3.0", - "squizlabs/php_codesniffer": "^3.1" + "malukenho/docheader": "^1.0", + "matthiasnoback/symfony-config-test": "^4.3", + "mockery/mockery": "^1.3.5|^1.4.4", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpdocumentor/reflection-docblock": "^5.2", + "phpmd/phpmd": "^2.13", + "phpunit/php-token-stream": "^3.1.3|^4.0.4", + "phpunit/phpunit": "^9.6|^10.4", + "sebastian/phpcpd": "^4.1|^5.0|^6.0", + "squizlabs/php_codesniffer": "^3.6" }, "type": "symfony-bundle", "autoload": { @@ -2105,7 +2095,7 @@ "license": [ "Apache-2.0" ], - "description": "A Symfony 4 bundle that facilitates health and info endpoints to a Symfony application. The bundle is backwards compatible with Symfony 2 projects.", + "description": "A Symfony 5/6/7 bundle that facilitates health and info endpoints to a Symfony application.", "keywords": [ "OpenConext", "health", @@ -2113,29 +2103,39 @@ "stepup", "surfnet" ], - "time": "2021-09-28T11:09:57+00:00" + "support": { + "issues": "https://github.com/OpenConext/Monitor-bundle/issues", + "source": "https://github.com/OpenConext/Monitor-bundle/tree/4.2.0" + }, + "time": "2024-04-09T08:51:19+00:00" }, { "name": "openconext/saml-value-object", - "version": "1.3.2", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/OpenConext/SamlValueObject.git", - "reference": "d47dfa6f30f30b81454f35fe49abdf77ddea1edd" + "reference": "70d0b1d50ecf60b4d66afb7c845b349f2088dd92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/OpenConext/SamlValueObject/zipball/d47dfa6f30f30b81454f35fe49abdf77ddea1edd", - "reference": "d47dfa6f30f30b81454f35fe49abdf77ddea1edd", + "url": "https://api.github.com/repos/OpenConext/SamlValueObject/zipball/70d0b1d50ecf60b4d66afb7c845b349f2088dd92", + "reference": "70d0b1d50ecf60b4d66afb7c845b349f2088dd92", "shasum": "" }, "require": { - "beberlei/assert": "^2.6", - "php": ">=5.4,<8.0-dev" + "beberlei/assert": "^3.3.3", + "php": ">=8.2" }, "require-dev": { - "ibuildings/qa-tools": "^1.1", - "liip/rmt": "~1.2" + "ergebnis/composer-normalize": "^2.48.2", + "overtrue/phplint": "^9.6.2", + "phpmd/phpmd": "^2.15", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", + "phpunit/phpunit": "^11.5.39", + "squizlabs/php_codesniffer": "^4.0" }, "type": "library", "autoload": { @@ -2154,79 +2154,91 @@ } ], "description": "Set of value objects for usage with SAML2", - "time": "2018-01-22T15:22:14+00:00" + "support": { + "issues": "https://github.com/OpenConext/SamlValueObject/issues", + "source": "https://github.com/OpenConext/SamlValueObject/tree/3.0.0" + }, + "time": "2025-09-16T09:01:35+00:00" }, { - "name": "paragonie/random_compat", - "version": "v9.99.99", + "name": "pimple/pimple", + "version": "v3.5.0", "source": { "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed", + "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed", "shasum": "" }, "require": { - "php": "^7" + "php": ">=7.2.5", + "psr/container": "^1.1 || ^2.0" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + "symfony/phpunit-bridge": "^5.4@dev" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "https://pimple.symfony.com", "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" + "container", + "dependency injection" ], - "time": "2018-07-02T15:55:56+00:00" + "support": { + "source": "https://github.com/silexphp/Pimple/tree/v3.5.0" + }, + "time": "2021-10-28T11:13:42+00:00" }, { - "name": "pimple/pimple", - "version": "v2.1.1", + "name": "psr/cache", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76" + "url": "https://github.com/php-fig/cache.git", + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/ea22fb2880faf7b7b0e17c9809c6fe25b071fd76", - "reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76", + "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Pimple": "src/" + "psr-4": { + "Psr\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2235,44 +2247,42 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", - "homepage": "http://pimple.sensiolabs.org", + "description": "Common interface for caching libraries", "keywords": [ - "container", - "dependency injection" + "cache", + "psr", + "psr-6" ], - "time": "2014-07-24T07:10:08+00:00" + "support": { + "source": "https://github.com/php-fig/cache/tree/2.0.0" + }, + "time": "2021-02-03T23:23:37+00:00" }, { - "name": "psr/cache", - "version": "1.0.1", + "name": "psr/container", + "version": "1.1.2", "source": { "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Psr\\Cache\\": "src/" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2282,38 +2292,50 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interface for caching libraries", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "cache", - "psr", - "psr-6" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], - "time": "2016-08-06T20:24:11+00:00" + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" }, { - "name": "psr/container", - "version": "1.1.1", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { "php": ">=7.2.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Psr\\EventDispatcher\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2323,50 +2345,48 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Standard interfaces for event handling.", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "events", + "psr", + "psr-14" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" }, - "time": "2021-03-05T17:36:06+00:00" + "time": "2019-01-08T18:20:26+00:00" }, { - "name": "psr/http-message", - "version": "1.1", + "name": "psr/http-client", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2376,40 +2396,39 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ "http", - "http-message", + "http-client", "psr", - "psr-7", - "request", - "response" + "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { - "name": "psr/link", - "version": "1.0.0", + "name": "psr/http-factory", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/link.git", - "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/link/zipball/eea8e8662d5cd3ae4517c9b864493f59fca95562", - "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -2419,7 +2438,7 @@ }, "autoload": { "psr-4": { - "Psr\\Link\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2429,46 +2448,51 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for HTTP links", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ + "factory", "http", - "http-link", - "link", + "message", "psr", - "psr-13", - "rest" + "psr-17", + "psr-7", + "request", + "response" ], - "time": "2016-10-28T16:06:13+00:00" + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" }, { - "name": "psr/log", - "version": "1.1.4", + "name": "psr/http-message", + "version": "2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2481,44 +2505,47 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "log", + "http", + "http-message", "psr", - "psr-3" + "psr-7", + "request", + "response" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { - "name": "psr/simple-cache", - "version": "1.0.1", + "name": "psr/log", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "url": "https://github.com/php-fig/log.git", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\SimpleCache\\": "src/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2528,18 +2555,20 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for simple caching", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "cache", - "caching", + "log", "psr", - "psr-16", - "simple-cache" + "psr-3" ], - "time": "2017-10-23T01:57:42+00:00" + "support": { + "source": "https://github.com/php-fig/log/tree/2.0.0" + }, + "time": "2021-07-14T16:41:46+00:00" }, { "name": "ralouphie/getallheaders", @@ -2585,56 +2614,140 @@ }, "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, { "name": "ramsey/uuid", - "version": "3.8.0", + "version": "4.9.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3" + "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/d09ea80159c1929d75b3f9c60504d613aeb4a1e3", - "reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440", + "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440", "shasum": "" }, "require": { - "paragonie/random_compat": "^1.0|^2.0|9.99.99", - "php": "^5.4 || ^7.0", - "symfony/polyfill-ctype": "^1.8" + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" }, "replace": { "rhumsaa/uuid": "self.version" }, "require-dev": { - "codeception/aspect-mock": "^1.0 | ~2.0.0", - "doctrine/annotations": "~1.2.0", - "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ~2.1.0", - "ircmaxell/random-lib": "^1.1", - "jakub-onderka/php-parallel-lint": "^0.9.0", - "mockery/mockery": "^0.9.9", - "moontoast/math": "^1.1", - "php-mock/php-mock-phpunit": "^0.3|^1.1", - "phpunit/phpunit": "^4.7|^5.0|^6.5", - "squizlabs/php_codesniffer": "^2.3" + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { - "ext-ctype": "Provides support for PHP Ctype functions", - "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", - "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", - "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", - "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", - "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.x-dev" + "captainhook": { + "force-install": true } }, "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { "Ramsey\\Uuid\\": "src/" } @@ -2643,39 +2756,17 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - }, - { - "name": "Marijn Huizendveld", - "email": "marijn.huizendveld@gmail.com" - }, - { - "name": "Thibaud Fabre", - "email": "thibaud@aztech.io" - } - ], - "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", - "homepage": "https://github.com/ramsey/uuid", + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", "keywords": [ "guid", "identifier", "uuid" ], - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2018-07-19T23:38:55+00:00" + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.9.1" + }, + "time": "2025-09-04T20:59:21+00:00" }, { "name": "robrichards/xmlseclibs", @@ -2721,56 +2812,60 @@ }, { "name": "sensio/framework-extra-bundle", - "version": "v3.0.29", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", - "reference": "bb907234df776b68922eb4b25bfa061683597b6a" + "reference": "2f886f4b31f23c76496901acaedfedb6936ba61f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/bb907234df776b68922eb4b25bfa061683597b6a", - "reference": "bb907234df776b68922eb4b25bfa061683597b6a", + "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/2f886f4b31f23c76496901acaedfedb6936ba61f", + "reference": "2f886f4b31f23c76496901acaedfedb6936ba61f", "shasum": "" }, "require": { - "doctrine/common": "~2.2", - "symfony/dependency-injection": "~2.3|~3.0", - "symfony/framework-bundle": "~2.3|~3.0|~4.0" + "doctrine/annotations": "^1.0|^2.0", + "php": ">=7.2.5", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/framework-bundle": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0" }, - "require-dev": { - "doctrine/doctrine-bundle": "~1.5", - "doctrine/orm": "~2.4,>=2.4.5", - "symfony/asset": "~2.7|~3.0|~4.0", - "symfony/browser-kit": "~2.3|~3.0|~4.0", - "symfony/dom-crawler": "~2.3|~3.0|~4.0", - "symfony/expression-language": "~2.4|~3.0|~4.0", - "symfony/finder": "~2.3|~3.0|~4.0", - "symfony/phpunit-bridge": "~3.2|~4.0", - "symfony/psr-http-message-bridge": "^0.3|^1.0", - "symfony/security-bundle": "~2.4|~3.0|~4.0", - "symfony/templating": "~2.3|~3.0|~4.0", - "symfony/translation": "~2.3|~3.0|~4.0", - "symfony/twig-bundle": "~2.3|~3.0|~4.0", - "symfony/yaml": "~2.3|~3.0|~4.0", - "twig/twig": "~1.12|~2.0", - "zendframework/zend-diactoros": "^1.3" + "conflict": { + "doctrine/doctrine-cache-bundle": "<1.3.1", + "doctrine/persistence": "<1.3" }, - "suggest": { - "symfony/expression-language": "", - "symfony/psr-http-message-bridge": "To use the PSR-7 converters", - "symfony/security-bundle": "" + "require-dev": { + "doctrine/dbal": "^2.10|^3.0", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.5", + "symfony/browser-kit": "^4.4|^5.0|^6.0", + "symfony/doctrine-bridge": "^4.4|^5.0|^6.0", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/monolog-bridge": "^4.0|^5.0|^6.0", + "symfony/monolog-bundle": "^3.2", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0", + "symfony/security-bundle": "^4.4|^5.0|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0", + "twig/twig": "^1.34|^2.4|^3.0" }, "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "6.1.x-dev" } }, "autoload": { "psr-4": { - "Sensio\\Bundle\\FrameworkExtraBundle\\": "" - } + "Sensio\\Bundle\\FrameworkExtraBundle\\": "src/" + }, + "exclude-from-classmap": [ + "/tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2787,75 +2882,24 @@ "annotations", "controllers" ], - "time": "2017-12-14T19:03:23+00:00" - }, - { - "name": "sensio/generator-bundle", - "version": "v3.1.7", - "source": { - "type": "git", - "url": "https://github.com/sensiolabs/SensioGeneratorBundle.git", - "reference": "28cbaa244bd0816fd8908b93f90380bcd7b67a65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioGeneratorBundle/zipball/28cbaa244bd0816fd8908b93f90380bcd7b67a65", - "reference": "28cbaa244bd0816fd8908b93f90380bcd7b67a65", - "shasum": "" - }, - "require": { - "symfony/console": "~2.7|~3.0", - "symfony/framework-bundle": "~2.7|~3.0", - "symfony/process": "~2.7|~3.0", - "symfony/yaml": "~2.7|~3.0", - "twig/twig": "^1.28.2|^2.0" - }, - "require-dev": { - "doctrine/orm": "~2.4", - "symfony/doctrine-bridge": "~2.7|~3.0", - "symfony/filesystem": "~2.7|~3.0", - "symfony/phpunit-bridge": "^3.3" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Sensio\\Bundle\\GeneratorBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "support": { + "source": "https://github.com/sensiolabs/SensioFrameworkExtraBundle/tree/v6.2.10" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "This bundle generates code for you", - "abandoned": "symfony/maker-bundle", - "time": "2017-12-07T15:36:41+00:00" + "abandoned": "Symfony", + "time": "2023-02-24T14:57:12+00:00" }, { "name": "simplesamlphp/saml2", - "version": "v4.17.0", + "version": "v4.19.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/saml2.git", - "reference": "bdf16d1021363a0819c35806124a20e74a78c2c9" + "reference": "a1e25f1351591c2b007449735c0e62e016696576" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/bdf16d1021363a0819c35806124a20e74a78c2c9", - "reference": "bdf16d1021363a0819c35806124a20e74a78c2c9", + "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/a1e25f1351591c2b007449735c0e62e016696576", + "reference": "a1e25f1351591c2b007449735c0e62e016696576", "shasum": "" }, "require": { @@ -2901,101 +2945,137 @@ "description": "SAML2 PHP library from SimpleSAMLphp", "support": { "issues": "https://github.com/simplesamlphp/saml2/issues", - "source": "https://github.com/simplesamlphp/saml2/tree/v4.17.0" + "source": "https://github.com/simplesamlphp/saml2/tree/v4.19.0" }, - "time": "2025-03-11T17:35:33+00:00" + "time": "2025-09-05T23:47:51+00:00" }, { - "name": "swiftmailer/swiftmailer", - "version": "v5.4.12", + "name": "symfony/asset", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + "url": "https://github.com/symfony/asset.git", + "reference": "b7a18eaff1d717c321b4f13403413f8815bf9cb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", - "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "url": "https://api.github.com/repos/symfony/asset/zipball/b7a18eaff1d717c321b4f13403413f8815bf9cb0", + "reference": "b7a18eaff1d717c321b4f13403413f8815bf9cb0", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/http-foundation": "<5.3" }, "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "~3.2" + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^5.3|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.4-dev" - } + "suggest": { + "symfony/http-foundation": "" }, + "type": "library", "autoload": { - "files": [ - "lib/swift_required.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ - { - "name": "Chris Corbyn" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Swiftmailer, free feature-rich PHP mailer", - "homepage": "https://swiftmailer.symfony.com", - "keywords": [ - "email", - "mail", - "mailer" + "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/v5.4.45" + }, + "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" + } ], - "abandoned": "symfony/mailer", - "time": "2018-07-31T09:26:32+00:00" + "time": "2024-10-22T13:05:35+00:00" }, { - "name": "symfony/monolog-bundle", - "version": "v3.4.0", + "name": "symfony/cache", + "version": "v5.4.46", "source": { "type": "git", - "url": "https://github.com/symfony/monolog-bundle.git", - "reference": "7fbecb371c1c614642c93c6b2cbcdf723ae8809d" + "url": "https://github.com/symfony/cache.git", + "reference": "0fe08ee32cec2748fbfea10c52d3ee02049e0f6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/7fbecb371c1c614642c93c6b2cbcdf723ae8809d", - "reference": "7fbecb371c1c614642c93c6b2cbcdf723ae8809d", + "url": "https://api.github.com/repos/symfony/cache/zipball/0fe08ee32cec2748fbfea10c52d3ee02049e0f6b", + "reference": "0fe08ee32cec2748fbfea10c52d3ee02049e0f6b", "shasum": "" }, "require": { - "monolog/monolog": "~1.22", - "php": ">=5.6", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4.10|^4.0.10", - "symfony/http-kernel": "~3.4|~4.0", - "symfony/monolog-bridge": "~3.4|~4.0" + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0", + "psr/log": "^1.1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/var-exporter": "^4.4|^5.0|^6.0" }, - "require-dev": { - "symfony/console": "~3.4|~4.0", - "symfony/phpunit-bridge": "^3.4.19|^4.0", - "symfony/yaml": "~3.4|~4.0" + "conflict": { + "doctrine/dbal": "<2.13.1", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } + "provide": { + "psr/cache-implementation": "1.0|2.0", + "psr/simple-cache-implementation": "1.0|2.0", + "symfony/cache-implementation": "1.0|2.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "^1.6|^2.0", + "doctrine/dbal": "^2.13.1|^3|^4", + "predis/predis": "^1.1|^2.0", + "psr/simple-cache": "^1.0|^2.0", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/filesystem": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Bundle\\MonologBundle\\": "" + "Symfony\\Component\\Cache\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3007,55 +3087,73 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony MonologBundle", - "homepage": "http://symfony.com", + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", "keywords": [ - "log", - "logging" + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v5.4.46" + }, + "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": "2019-06-20T12:18:19+00:00" + "time": "2024-11-04T11:43:55+00:00" }, { - "name": "symfony/polyfill-apcu", - "version": "v1.22.1", + "name": "symfony/cache-contracts", + "version": "v2.5.4", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "bc9974e74f8c05f4ceb500b1e0603e36be7d8223" + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "517c3a3619dadfa6952c4651767fcadffb4df65e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/bc9974e74f8c05f4ceb500b1e0603e36be7d8223", - "reference": "bc9974e74f8c05f4ceb500b1e0603e36be7d8223", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/517c3a3619dadfa6952c4651767fcadffb4df65e", + "reference": "517c3a3619dadfa6952c4651767fcadffb4df65e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" + "Symfony\\Contracts\\Cache\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -3072,15 +3170,19 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions", + "description": "Generic abstractions related to caching", "homepage": "https://symfony.com", "keywords": [ - "apcu", - "compatibility", - "polyfill", - "portable", - "shim" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v2.5.4" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3095,45 +3197,51 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "name": "symfony/config", + "version": "v5.4.46", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "url": "https://github.com/symfony/config.git", + "reference": "977c88a02d7d3f16904a81907531b19666a08e78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/config/zipball/977c88a02d7d3f16904a81907531b19666a08e78", + "reference": "977c88a02d7d3f16904a81907531b19666a08e78", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^4.4|^5.0|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22" }, - "provide": { - "ext-ctype": "*" + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/yaml": "^4.4|^5.0|^6.0" }, "suggest": { - "ext-ctype": "For best performance" + "symfony/yaml": "To use the yaml reference dumper" }, "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3141,24 +3249,18 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/config/tree/v5.4.46" }, "funding": [ { @@ -3174,48 +3276,62 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-10-30T07:58:02+00:00" }, { - "name": "symfony/polyfill-intl-icu", - "version": "v1.22.1", + "name": "symfony/console", + "version": "v5.4.47", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "af1842919c7e7364aaaa2798b29839e3ba168588" + "url": "https://github.com/symfony/console.git", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/af1842919c7e7364aaaa2798b29839e3ba168588", - "reference": "af1842919c7e7364aaaa2798b29839e3ba168588", + "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "suggest": { - "ext-intl": "For best performance and support of other locales than \"en\"" + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Icu\\": "" + "Symfony\\Component\\Console\\": "" }, - "classmap": [ - "Resources/stubs" - ], "exclude-from-classmap": [ "/Tests/" ] @@ -3226,24 +3342,25 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's ICU-related data and classes", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "icu", - "intl", - "polyfill", - "portable", - "shim" + "cli", + "command-line", + "console", + "terminal" ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.47" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3258,47 +3375,61 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2024-11-06T11:30:55+00:00" }, { - "name": "symfony/polyfill-intl-idn", - "version": "v1.26.0", + "name": "symfony/dependency-injection", + "version": "v5.4.48", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8" + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "e5ca16dee39ef7d63e552ff0bf0a2526a1142c92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e5ca16dee39ef7d63e552ff0bf0a2526a1142c92", + "reference": "e5ca16dee39ef7d63e552ff0bf0a2526a1142c92", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2.5", + "psr/container": "^1.1.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<5.3", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4.26" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/config": "^5.3|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4.26|^5.0|^6.0" }, "suggest": { - "ext-intl": "For best performance" + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3306,28 +3437,19 @@ ], "authors": [ { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v5.4.48" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3342,47 +3464,38 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-11-20T10:51:57+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3399,16 +3512,11 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3423,34 +3531,88 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", + "name": "symfony/doctrine-bridge", + "version": "v5.4.48", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "43ed5e31c9188e4f4d3845d16986db4a86644eef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/43ed5e31c9188e4f4d3845d16986db4a86644eef", + "reference": "43ed5e31c9188e4f4d3845d16986db4a86644eef", "shasum": "" }, "require": { - "php": ">=7.1" + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^2|^3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3" }, - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } + "conflict": { + "doctrine/dbal": "<2.13.1", + "doctrine/lexer": "<1.1", + "doctrine/orm": "<2.7.4", + "symfony/cache": "<5.4", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5.4.38|>=6,<6.4.6", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/proxy-manager-bridge": "<4.4.19", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5.3", + "symfony/validator": "<5.4.25|>=6,<6.2.12|>=6.3,<6.3.1" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4|^2", + "doctrine/collections": "^1.0|^2.0", + "doctrine/data-fixtures": "^1.1|^2", + "doctrine/dbal": "^2.13.1|^3|^4", + "doctrine/orm": "^2.7.4|^3", + "psr/log": "^1|^2|^3", + "symfony/cache": "^5.4|^6.0", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/doctrine-messenger": "^5.1|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/form": "^5.4.38|^6.4.6", + "symfony/http-kernel": "^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/property-access": "^4.4|^5.0|^6.0", + "symfony/property-info": "^5.0|^6.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0|^6.0", + "symfony/security-core": "^5.3|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "symfony/translation": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "symfony/validator": "^5.4.25|~6.2.12|^6.3.1", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3458,22 +3620,19 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "support": { + "source": "https://github.com/symfony/doctrine-bridge/tree/v5.4.48" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3488,31 +3647,38 @@ "type": "tidelift" } ], - "time": "2020-10-23T14:02:19+00:00" + "time": "2024-11-20T10:49:45+00:00" }, { - "name": "symfony/polyfill-php72", - "version": "v1.31.0", + "name": "symfony/dotenv", + "version": "v5.4.48", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce" + "url": "https://github.com/symfony/dotenv.git", + "reference": "08013403089c8a126c968179179b817a552841ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce", - "reference": "fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/08013403089c8a126c968179179b817a552841ab", + "reference": "08013403089c8a126c968179179b817a552841ab", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3" }, - "type": "metapackage", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } + "require-dev": { + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3520,24 +3686,23 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "description": "Registers environment variables from a .env file", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "dotenv", + "env", + "environment" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.31.0" + "source": "https://github.com/symfony/dotenv/tree/v5.4.48" }, "funding": [ { @@ -3553,43 +3718,43 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-11-27T09:33:00+00:00" }, { - "name": "symfony/service-contracts", - "version": "v1.1.9", + "name": "symfony/error-handler", + "version": "v5.4.46", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "b776d18b303a39f56c63747bcb977ad4b27aca26" + "url": "https://github.com/symfony/error-handler.git", + "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b776d18b303a39f56c63747bcb977ad4b27aca26", - "reference": "b776d18b303a39f56c63747bcb977ad4b27aca26", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/d19ede7a2cafb386be9486c580649d0f9e3d0363", + "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363", "shasum": "" }, "require": { - "php": ">=7.1.3", - "psr/container": "^1.0" + "php": ">=7.2.5", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4.4|^5.0|^6.0" }, - "suggest": { - "symfony/service-implementation": "" + "require-dev": { + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/serializer": "^4.4|^5.0|^6.0" }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3597,24 +3762,19 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], + "support": { + "source": "https://github.com/symfony/error-handler/tree/v5.4.46" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3629,200 +3789,125 @@ "type": "tidelift" } ], - "time": "2020-07-06T13:19:58+00:00" + "time": "2024-11-05T14:17:06+00:00" }, { - "name": "symfony/swiftmailer-bundle", - "version": "v2.6.7", + "name": "symfony/event-dispatcher", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/symfony/swiftmailer-bundle.git", - "reference": "c4808f5169efc05567be983909d00f00521c53ec" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/swiftmailer-bundle/zipball/c4808f5169efc05567be983909d00f00521c53ec", - "reference": "c4808f5169efc05567be983909d00f00521c53ec", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9", + "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9", "shasum": "" }, "require": { - "php": ">=5.3.2", - "swiftmailer/swiftmailer": "~4.2|~5.0", - "symfony/config": "~2.7|~3.0", - "symfony/dependency-injection": "~2.7|~3.0", - "symfony/http-kernel": "~2.7|~3.0" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { - "symfony/console": "~2.7|~3.0", - "symfony/framework-bundle": "~2.7|~3.0", - "symfony/phpunit-bridge": "~3.3@dev", - "symfony/yaml": "~2.7|~3.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" }, "suggest": { - "psr/log": "Allows logging" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Bundle\\SwiftmailerBundle\\": "" - } + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, { "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.45" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "Symfony SwiftmailerBundle", - "homepage": "http://symfony.com", - "abandoned": "symfony/mailer", - "time": "2017-10-19T01:06:41+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { - "name": "symfony/symfony", - "version": "v3.4.49", + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/symfony.git", - "reference": "ba0e346e3ad11de4a307fe4fa2452a3656dcc17b" + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/symfony/zipball/ba0e346e3ad11de4a307fe4fa2452a3656dcc17b", - "reference": "ba0e346e3ad11de4a307fe4fa2452a3656dcc17b", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { - "doctrine/common": "~2.4", - "ext-xml": "*", - "fig/link-util": "^1.0", - "php": "^5.5.9|>=7.0.8", - "psr/cache": "~1.0", - "psr/container": "^1.0", - "psr/link": "^1.0", - "psr/log": "~1.0", - "psr/simple-cache": "^1.0", - "symfony/polyfill-apcu": "~1.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.6", - "twig/twig": "^1.41|^2.10" - }, - "conflict": { - "monolog/monolog": ">=2", - "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", - "phpdocumentor/type-resolver": "<0.3.0", - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" - }, - "provide": { - "psr/cache-implementation": "1.0", - "psr/container-implementation": "1.0", - "psr/log-implementation": "1.0", - "psr/simple-cache-implementation": "1.0" - }, - "replace": { - "symfony/asset": "self.version", - "symfony/browser-kit": "self.version", - "symfony/cache": "self.version", - "symfony/class-loader": "self.version", - "symfony/config": "self.version", - "symfony/console": "self.version", - "symfony/css-selector": "self.version", - "symfony/debug": "self.version", - "symfony/debug-bundle": "self.version", - "symfony/dependency-injection": "self.version", - "symfony/doctrine-bridge": "self.version", - "symfony/dom-crawler": "self.version", - "symfony/dotenv": "self.version", - "symfony/event-dispatcher": "self.version", - "symfony/expression-language": "self.version", - "symfony/filesystem": "self.version", - "symfony/finder": "self.version", - "symfony/form": "self.version", - "symfony/framework-bundle": "self.version", - "symfony/http-foundation": "self.version", - "symfony/http-kernel": "self.version", - "symfony/inflector": "self.version", - "symfony/intl": "self.version", - "symfony/ldap": "self.version", - "symfony/lock": "self.version", - "symfony/monolog-bridge": "self.version", - "symfony/options-resolver": "self.version", - "symfony/process": "self.version", - "symfony/property-access": "self.version", - "symfony/property-info": "self.version", - "symfony/proxy-manager-bridge": "self.version", - "symfony/routing": "self.version", - "symfony/security": "self.version", - "symfony/security-bundle": "self.version", - "symfony/security-core": "self.version", - "symfony/security-csrf": "self.version", - "symfony/security-guard": "self.version", - "symfony/security-http": "self.version", - "symfony/serializer": "self.version", - "symfony/stopwatch": "self.version", - "symfony/templating": "self.version", - "symfony/translation": "self.version", - "symfony/twig-bridge": "self.version", - "symfony/twig-bundle": "self.version", - "symfony/validator": "self.version", - "symfony/var-dumper": "self.version", - "symfony/web-link": "self.version", - "symfony/web-profiler-bundle": "self.version", - "symfony/web-server-bundle": "self.version", - "symfony/workflow": "self.version", - "symfony/yaml": "self.version" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.6", - "doctrine/data-fixtures": "^1.1", - "doctrine/dbal": "~2.4", - "doctrine/doctrine-bundle": "~1.4", - "doctrine/orm": "~2.4,>=2.4.5", - "egulias/email-validator": "~1.2,>=1.2.8|~2.0", - "monolog/monolog": "~1.11", - "ocramius/proxy-manager": "~0.4|~1.0|~2.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", - "predis/predis": "~1.0", - "symfony/phpunit-bridge": "^5.2", - "symfony/security-acl": "~2.8|~3.0" + "php": ">=8.1", + "psr/event-dispatcher": "^1" }, "type": "library", "extra": { - "branch-version": "3.4" + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } }, "autoload": { "psr-4": { - "Symfony\\Bundle\\": "src/Symfony/Bundle/", - "Symfony\\Component\\": "src/Symfony/Component/", - "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/", - "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/", - "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/", - "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/" - }, - "classmap": [ - "src/Symfony/Component/Intl/Resources/stubs" - ], - "exclude-from-classmap": [ - "**/Tests/" - ] + "Symfony\\Contracts\\EventDispatcher\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3830,19 +3915,27 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "The Symfony PHP framework", + "description": "Generic abstractions related to dispatching event", "homepage": "https://symfony.com", "keywords": [ - "framework" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3857,45 +3950,35 @@ "type": "tidelift" } ], - "time": "2021-05-19T12:07:19+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { - "name": "twig/extensions", - "version": "v1.5.4", + "name": "symfony/expression-language", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/twigphp/Twig-extensions.git", - "reference": "57873c8b0c1be51caa47df2cdb824490beb16202" + "url": "https://github.com/symfony/expression-language.git", + "reference": "a784b66edc4c151eb05076d04707906ee2c209a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/57873c8b0c1be51caa47df2cdb824490beb16202", - "reference": "57873c8b0c1be51caa47df2cdb824490beb16202", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/a784b66edc4c151eb05076d04707906ee2c209a9", + "reference": "a784b66edc4c151eb05076d04707906ee2c209a9", "shasum": "" }, "require": { - "twig/twig": "^1.27|^2.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.4", - "symfony/translation": "^2.7|^3.4" - }, - "suggest": { - "symfony/translation": "Allow the time_diff output to be translated" + "php": ">=7.2.5", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, "autoload": { - "psr-0": { - "Twig_Extensions_": "lib/" - }, "psr-4": { - "Twig\\Extensions\\": "src/" - } + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3905,131 +3988,4744 @@ { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Common additional features for Twig that do not directly belong in core", - "keywords": [ - "i18n", - "text" + "description": "Provides an engine that can compile and evaluate expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/expression-language/tree/v5.4.45" + }, + "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" + } ], - "abandoned": true, - "time": "2018-12-05T18:34:18+00:00" + "time": "2024-10-04T14:55:40+00:00" }, { - "name": "twig/twig", - "version": "v2.16.1", + "name": "symfony/filesystem", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "19185947ec75d433a3ac650af32fc05649b95ee1" + "url": "https://github.com/symfony/filesystem.git", + "reference": "57c8294ed37d4a055b77057827c67f9558c95c54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/19185947ec75d433a3ac650af32fc05649b95ee1", - "reference": "19185947ec75d433a3ac650af32fc05649b95ee1", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54", + "reference": "57c8294ed37d4a055b77057827c67f9558c95c54", "shasum": "" }, "require": { - "php": ">=7.1.3", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php72": "^1.8" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "psr/container": "^1.0", - "symfony/phpunit-bridge": "^5.4.9|^6.3" + "symfony/process": "^5.4|^6.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.16-dev" - } - }, "autoload": { - "psr-0": { - "Twig_": "lib/" - }, "psr-4": { - "Twig\\": "src/" - } + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" + "email": "fabien@symfony.com" }, { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v2.16.1" + "source": "https://github.com/symfony/filesystem/tree/v5.4.45" }, "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, { "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T17:53:56+00:00" + "time": "2024-10-22T13:05:35+00:00" }, { - "name": "webmozart/assert", - "version": "1.11.0", + "name": "symfony/finder", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "url": "https://github.com/symfony/finder.git", + "reference": "63741784cd7b9967975eec610b256eed3ede022b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", + "reference": "63741784cd7b9967975eec610b256eed3ede022b", "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" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, "autoload": { "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.45" + }, + "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-28T13:32:08+00:00" + }, + { + "name": "symfony/flex", + "version": "v2.8.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/flex.git", + "reference": "f356aa35f3cf3d2f46c31d344c1098eb2d260426" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/flex/zipball/f356aa35f3cf3d2f46c31d344c1098eb2d260426", + "reference": "f356aa35f3cf3d2f46c31d344c1098eb2d260426", + "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", + "symfony/filesystem": "^5.4|^6.0", + "symfony/phpunit-bridge": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Flex\\Flex" + }, + "autoload": { + "psr-4": { + "Symfony\\Flex\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien.potencier@gmail.com" + } + ], + "description": "Composer plugin for Symfony", + "support": { + "issues": "https://github.com/symfony/flex/issues", + "source": "https://github.com/symfony/flex/tree/v2.8.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-22T07:17:23+00:00" + }, + { + "name": "symfony/form", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/form.git", + "reference": "c1974a723cdee8a273cb49ce13fada5c1667706a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/form/zipball/c1974a723cdee8a273cb49ce13fada5c1667706a", + "reference": "c1974a723cdee8a273cb49ce13fada5c1667706a", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/options-resolver": "^5.1|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.23", + "symfony/property-access": "^5.0.8|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/console": "<4.4", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.4.21|>=6,<6.2.7", + "symfony/error-handler": "<4.4.5", + "symfony/framework-bundle": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3", + "symfony/translation-contracts": "<1.1.7", + "symfony/twig-bridge": "<5.4.21|>=6,<6.2.7" + }, + "require-dev": { + "doctrine/collections": "^1.0|^2.0", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/security-csrf": "^4.4|^5.0|^6.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3", + "symfony/uid": "^5.1|^6.0", + "symfony/validator": "^4.4.17|^5.1.9|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/security-csrf": "For protecting forms against CSRF attacks.", + "symfony/twig-bridge": "For templating with Twig.", + "symfony/validator": "For form validation." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Form\\": "" + }, + "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 to easily create, process and reuse HTML forms", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/form/tree/v5.4.45" + }, + "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-08T07:27:17+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "3d70f14176422d4d8ee400b6acae4e21f7c25ca2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/3d70f14176422d4d8ee400b6acae4e21f7c25ca2", + "reference": "3d70f14176422d4d8ee400b6acae4e21f7c25ca2", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=7.2.5", + "symfony/cache": "^5.2|^6.0", + "symfony/config": "^5.3|^6.0", + "symfony/dependency-injection": "^5.4.44|^6.0.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^4.4.1|^5.0.1|^6.0", + "symfony/event-dispatcher": "^5.1|^6.0", + "symfony/filesystem": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^5.4.24|^6.2.11", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", + "symfony/routing": "^5.3|^6.0" + }, + "conflict": { + "doctrine/annotations": "<1.13.1", + "doctrine/cache": "<1.11", + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/asset": "<5.3", + "symfony/console": "<5.2.5|>=7.0", + "symfony/dom-crawler": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/form": "<5.2", + "symfony/http-client": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<5.2", + "symfony/messenger": "<5.4", + "symfony/mime": "<4.4", + "symfony/property-access": "<5.3", + "symfony/property-info": "<4.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", + "symfony/security-csrf": "<5.3", + "symfony/serializer": "<5.2", + "symfony/service-contracts": ">=3.0", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.3", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<5.3.11", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<5.2" + }, + "require-dev": { + "doctrine/annotations": "^1.13.1|^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/persistence": "^1.3|^2|^3", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/asset": "^5.3|^6.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/console": "^5.4.9|^6.0.9", + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/dom-crawler": "^4.4.30|^5.3.7|^6.0", + "symfony/dotenv": "^5.1|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/form": "^5.2|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/mailer": "^5.2|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/notifier": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/property-info": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0", + "symfony/security-bundle": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "symfony/string": "^5.0|^6.0", + "symfony/translation": "^5.3|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0", + "symfony/validator": "^5.3.11|^6.0", + "symfony/web-link": "^4.4|^5.0|^6.0", + "symfony/workflow": "^5.2|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0", + "twig/twig": "^2.10|^3.0.4" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/framework-bundle/tree/v5.4.45" + }, + "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-22T13:05:35+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "3f38b8af283b830e1363acd79e5bc3412d055341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3f38b8af283b830e1363acd79e5bc3412d055341", + "reference": "3f38b8af283b830e1363acd79e5bc3412d055341", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "predis/predis": "^1.0|^2.0", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" + }, + "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/v5.4.48" + }, + "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-11-13T18:58:02+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "c2dbfc92b851404567160d1ecf3fb7d9b7bde9b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c2dbfc92b851404567160d1ecf3fb7d9b7bde9b0", + "reference": "c2dbfc92b851404567160d1ecf3fb7d9b7bde9b0", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/log": "^1|^2", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^5.0|^6.0", + "symfony/http-foundation": "^5.4.21|^6.2.7", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/console": "<4.4", + "symfony/dependency-injection": "<5.3", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^5.4|^6.0", + "symfony/config": "^5.0|^6.0", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.3|^6.0", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/routing": "^4.4|^5.0|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "symfony/translation": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/var-dumper": "^4.4.31|^5.4", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v5.4.48" + }, + "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-11-27T12:43:17+00:00" + }, + { + "name": "symfony/mailer", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "f732e1fafdf0f4a2d865e91f1018aaca174aeed9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/f732e1fafdf0f4a2d865e91f1018aaca174aeed9", + "reference": "f732e1fafdf0f4a2d865e91f1018aaca174aeed9", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=7.2.5", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/mime": "^5.2.6|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<4.4" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/8c1b9b3e5b52981551fc6044539af1d974e39064", + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<4.4", + "symfony/serializer": "<5.4.35|>=6,<6.3.12|>=6.4,<6.4.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/process": "^5.4|^6.4", + "symfony/property-access": "^4.4|^5.1|^6.0", + "symfony/property-info": "^4.4|^5.1|^6.0", + "symfony/serializer": "^5.4.35|~6.3.12|^6.4.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/v5.4.45" + }, + "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-23T20:18:32+00:00" + }, + { + "name": "symfony/monolog-bridge", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bridge.git", + "reference": "cf7d75d4d64a41fbb1c0e92301bec404134fa84b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/cf7d75d4d64a41fbb1c0e92301bec404134fa84b", + "reference": "cf7d75d4d64a41fbb1c0e92301bec404134fa84b", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.25.1|^2", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-kernel": "^5.3|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3" + }, + "conflict": { + "symfony/console": "<4.4", + "symfony/http-foundation": "<5.3" + }, + "require-dev": { + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/mailer": "^4.4|^5.0|^6.0", + "symfony/messenger": "^4.4|^5.0|^6.0", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/security-core": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/console": "For the possibility to show log messages in console commands depending on verbosity settings.", + "symfony/http-kernel": "For using the debugging handlers together with the response life cycle of the HTTP kernel.", + "symfony/var-dumper": "For using the debugging handlers like the console handler or the log server handler." + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Monolog\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Monolog with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/monolog-bridge/tree/v5.4.45" + }, + "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-10T06:37:45+00:00" + }, + { + "name": "symfony/monolog-bundle", + "version": "v3.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bundle.git", + "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", + "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0", + "php": ">=7.2.5", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", + "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/phpunit-bridge": "^6.3 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MonologBundle\\": "" + }, + "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": "Symfony MonologBundle", + "homepage": "https://symfony.com", + "keywords": [ + "log", + "logging" + ], + "support": { + "issues": "https://github.com/symfony/monolog-bundle/issues", + "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-11-06T17:08:13+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6", + "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/password-hasher", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/password-hasher.git", + "reference": "6c5993b24505f98b90ca4896448012bbec54c7c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/6c5993b24505f98b90ca4896448012bbec54c7c8", + "reference": "6c5993b24505f98b90ca4896448012bbec54c7c8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/security-core": "<5.3" + }, + "require-dev": { + "symfony/console": "^5.3|^6.0", + "symfony/security-core": "^5.3|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PasswordHasher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robin Chalas", + "email": "robin.chalas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides password hashing utilities", + "homepage": "https://symfony.com", + "keywords": [ + "hashing", + "password" + ], + "support": { + "source": "https://github.com/symfony/password-hasher/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T09:58:17+00:00" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", + "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "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": "Symfony polyfill for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-20T22:24:30+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "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\\Php73\\": "" + }, + "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 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-24T13:30:11+00:00" + }, + { + "name": "symfony/property-access", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "111e7ed617509f1a9139686055d234aad6e388e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/111e7ed617509f1a9139686055d234aad6e388e0", + "reference": "111e7ed617509f1a9139686055d234aad6e388e0", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/property-info": "^5.2|^6.0" + }, + "require-dev": { + "symfony/cache": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "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 functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/property-info", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "a0396295ad585f95fccd690bc6a281e5bd303902" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/a0396295ad585f95fccd690bc6a281e5bd303902", + "reference": "a0396295ad585f95fccd690bc6a281e5bd303902", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/dependency-injection": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4|^2", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/serializer": "^4.4|^5.0|^6.0" + }, + "suggest": { + "phpdocumentor/reflection-docblock": "To use the PHPDoc", + "psr/cache-implementation": "To cache results", + "symfony/doctrine-bridge": "To use Doctrine metadata", + "symfony/serializer": "To use Serializer metadata" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v5.4.48" + }, + "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-11-25T16:14:41+00:00" + }, + { + "name": "symfony/routing", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "dd08c19879a9b37ff14fd30dcbdf99a4cf045db1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/dd08c19879a9b37ff14fd30dcbdf99a4cf045db1", + "reference": "dd08c19879a9b37ff14fd30dcbdf99a4cf045db1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "symfony/config": "<5.3", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.3|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v5.4.48" + }, + "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-11-12T18:20:21+00:00" + }, + { + "name": "symfony/security-bundle", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-bundle.git", + "reference": "d6081d1b9118f944df90bb77444a8617eba01542" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/d6081d1b9118f944df90bb77444a8617eba01542", + "reference": "d6081d1b9118f944df90bb77444a8617eba01542", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=7.2.5", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4.43|^6.4.11", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher": "^5.1|^6.0", + "symfony/http-foundation": "^5.3|^6.0", + "symfony/http-kernel": "^5.3|^6.0", + "symfony/password-hasher": "^5.3|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/security-core": "^5.4|^6.0", + "symfony/security-csrf": "^4.4|^5.0|^6.0", + "symfony/security-guard": "^5.3", + "symfony/security-http": "^5.4.30|^6.3.6", + "symfony/service-contracts": "^1.10|^2|^3" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/framework-bundle": "<4.4", + "symfony/ldap": "<5.1", + "symfony/twig-bundle": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4|^2", + "symfony/asset": "^4.4|^5.0|^6.0", + "symfony/browser-kit": "^4.4|^5.0|^6.0", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/form": "^4.4|^5.0|^6.0", + "symfony/framework-bundle": "^5.3|^6.0", + "symfony/ldap": "^5.3|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0", + "symfony/serializer": "^4.4|^5.0|^6.0", + "symfony/translation": "^4.4|^5.0|^6.0", + "symfony/twig-bridge": "^4.4|^5.0|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0", + "symfony/validator": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\SecurityBundle\\": "" + }, + "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 Security component into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-bundle/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/security-core", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "cca947b1a74bdbc21c4d6288a4abb938d9a7eaba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/cca947b1a74bdbc21c4d6288a4abb938d9a7eaba", + "reference": "cca947b1a74bdbc21c4d6288a4abb938d9a7eaba", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^1.1|^2|^3", + "symfony/password-hasher": "^5.3|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1.6|^2|^3" + }, + "conflict": { + "symfony/event-dispatcher": "<4.4", + "symfony/http-foundation": "<5.3", + "symfony/ldap": "<4.4", + "symfony/security-guard": "<4.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3", + "symfony/validator": "<5.2" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "psr/container": "^1.0|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^5.3|^6.0", + "symfony/ldap": "^4.4|^5.0|^6.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3", + "symfony/validator": "^5.2|^6.0" + }, + "suggest": { + "psr/container-implementation": "To instantiate the Security class", + "symfony/event-dispatcher": "", + "symfony/expression-language": "For using the expression voter", + "symfony/http-foundation": "", + "symfony/ldap": "For using LDAP integration", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Core\\": "" + }, + "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": "Symfony Security Component - Core Library", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-core/tree/v5.4.48" + }, + "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-11-27T08:58:20+00:00" + }, + { + "name": "symfony/security-csrf", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "28dcafc3220f12264bb2aabe2389a2163458c1f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/28dcafc3220f12264bb2aabe2389a2163458c1f4", + "reference": "28dcafc3220f12264bb2aabe2389a2163458c1f4", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16", + "symfony/security-core": "^4.4|^5.0|^6.0" + }, + "conflict": { + "symfony/http-foundation": "<5.3" + }, + "require-dev": { + "symfony/http-foundation": "^5.3|^6.0" + }, + "suggest": { + "symfony/http-foundation": "For using the class SessionTokenStorage." + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Csrf\\": "" + }, + "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": "Symfony Security Component - CSRF Library", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-csrf/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/security-guard", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-guard.git", + "reference": "f3da3dbec38aaedaf287ffeb4e3a90994af37faa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-guard/zipball/f3da3dbec38aaedaf287ffeb4e3a90994af37faa", + "reference": "f3da3dbec38aaedaf287ffeb4e3a90994af37faa", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.15", + "symfony/security-core": "^5.0", + "symfony/security-http": "^5.3" + }, + "require-dev": { + "psr/log": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Guard\\": "" + }, + "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": "Symfony Security Component - Guard", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-guard/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/security-http", + "version": "v5.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-http.git", + "reference": "cde02b002e0447075430e6a84482e38f2fd9268d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-http/zipball/cde02b002e0447075430e6a84482e38f2fd9268d", + "reference": "cde02b002e0447075430e6a84482e38f2fd9268d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-foundation": "^5.3|^6.0", + "symfony/http-kernel": "^5.3|^6.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/property-access": "^4.4|^5.0|^6.0", + "symfony/security-core": "^5.4.19|~6.0.19|~6.1.11|^6.2.5", + "symfony/service-contracts": "^1.10|^2|^3" + }, + "conflict": { + "symfony/event-dispatcher": "<4.3", + "symfony/security-bundle": "<5.3", + "symfony/security-csrf": "<4.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0", + "symfony/routing": "^4.4|^5.0|^6.0", + "symfony/security-csrf": "^4.4|^5.0|^6.0", + "symfony/translation": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/security-csrf": "For using tokens to protect authentication/logout attempts" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Http\\": "" + }, + "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": "Symfony Security Component - HTTP Integration", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-http/tree/v5.4.47" + }, + "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-11-07T14:12:41+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "fb2c199cf302eb207f8c23e7ee174c1c31a5c004" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fb2c199cf302eb207f8c23e7ee174c1c31a5c004", + "reference": "fb2c199cf302eb207f8c23e7ee174c1c31a5c004", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/string", + "version": "v5.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.47" + }, + "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-11-10T20:33:58+00:00" + }, + { + "name": "symfony/templating", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/templating.git", + "reference": "e9e46b530d8e202071bc5efcea1a3d3174d68a9b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/templating/zipball/e9e46b530d8e202071bc5efcea1a3d3174d68a9b", + "reference": "e9e46b530d8e202071bc5efcea1a3d3174d68a9b", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "require-dev": { + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log-implementation": "For using debug logging in loaders" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Templating\\": "" + }, + "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 all the tools needed to build any kind of template system", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/templating/tree/v5.4.45" + }, + "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-22T13:05:35+00:00" + }, + { + "name": "symfony/translation", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "98f26acc99341ca4bab345fb14d7b1d7cb825bed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/98f26acc99341ca4bab345fb14d7b1d7cb825bed", + "reference": "98f26acc99341ca4bab345fb14d7b1d7cb825bed", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation-contracts": "^2.3" + }, + "conflict": { + "symfony/config": "<4.4", + "symfony/console": "<5.3", + "symfony/dependency-injection": "<5.0", + "symfony/http-kernel": "<5.0", + "symfony/twig-bundle": "<5.0", + "symfony/yaml": "<4.4" + }, + "provide": { + "symfony/translation-implementation": "2.3" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.0|^6.0", + "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "450d4172653f38818657022252f9d81be89ee9a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/450d4172653f38818657022252f9d81be89ee9a8", + "reference": "450d4172653f38818657022252f9d81be89ee9a8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v2.5.4" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/twig-bridge", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "853a0c9aa40123a9feeb335c865b659d94e49e5d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/853a0c9aa40123a9feeb335c865b659d94e49e5d", + "reference": "853a0c9aa40123a9feeb335c865b659d94e49e5d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16", + "symfony/translation-contracts": "^1.1|^2|^3", + "twig/twig": "^2.13|^3.0.4" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/console": "<5.3", + "symfony/form": "<5.4.21|>=6,<6.2.7", + "symfony/http-foundation": "<5.3", + "symfony/http-kernel": "<4.4", + "symfony/translation": "<5.2", + "symfony/workflow": "<5.2" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "egulias/email-validator": "^2.1.10|^3|^4", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/asset": "^4.4|^5.0|^6.0", + "symfony/console": "^5.3|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/form": "^5.4.21|^6.2.7", + "symfony/http-foundation": "^5.3|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/mime": "^5.2|^6.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/property-info": "^4.4|^5.1|^6.0", + "symfony/routing": "^4.4|^5.0|^6.0", + "symfony/security-acl": "^2.8|^3.0", + "symfony/security-core": "^4.4|^5.0|^6.0", + "symfony/security-csrf": "^4.4|^5.0|^6.0", + "symfony/security-http": "^4.4|^5.0|^6.0", + "symfony/serializer": "^5.4.35|~6.3.12|^6.4.3", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "symfony/translation": "^5.2|^6.0", + "symfony/web-link": "^4.4|^5.0|^6.0", + "symfony/workflow": "^5.2|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0", + "twig/cssinliner-extra": "^2.12|^3", + "twig/inky-extra": "^2.12|^3", + "twig/markdown-extra": "^2.12|^3" + }, + "suggest": { + "symfony/asset": "For using the AssetExtension", + "symfony/expression-language": "For using the ExpressionExtension", + "symfony/finder": "", + "symfony/form": "For using the FormExtension", + "symfony/http-kernel": "For using the HttpKernelExtension", + "symfony/routing": "For using the RoutingExtension", + "symfony/security-core": "For using the SecurityExtension", + "symfony/security-csrf": "For using the CsrfExtension", + "symfony/security-http": "For using the LogoutUrlExtension", + "symfony/stopwatch": "For using the StopwatchExtension", + "symfony/translation": "For using the TranslationExtension", + "symfony/var-dumper": "For using the DumpExtension", + "symfony/web-link": "For using the WebLinkExtension", + "symfony/yaml": "For using the YamlExtension" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Twig with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bridge/tree/v5.4.48" + }, + "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-11-22T08:19:51+00:00" + }, + { + "name": "symfony/twig-bundle", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bundle.git", + "reference": "e1ca56e1dc7791eb19f0aff71d3d94e6a91cc8f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/e1ca56e1dc7791eb19f0aff71d3d94e6a91cc8f9", + "reference": "e1ca56e1dc7791eb19f0aff71d3d94e6a91cc8f9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^5.0|^6.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/twig-bridge": "^5.3|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "conflict": { + "symfony/dependency-injection": "<5.3", + "symfony/framework-bundle": "<5.0", + "symfony/service-contracts": ">=3.0", + "symfony/translation": "<5.0" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4|^2", + "doctrine/cache": "^1.0|^2.0", + "symfony/asset": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.3|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/form": "^4.4|^5.0|^6.0", + "symfony/framework-bundle": "^5.0|^6.0", + "symfony/routing": "^4.4|^5.0|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "symfony/translation": "^5.0|^6.0", + "symfony/web-link": "^4.4|^5.0|^6.0", + "symfony/yaml": "^4.4|^5.0|^6.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\TwigBundle\\": "" + }, + "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 Twig into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bundle/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "symfony/validator", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "883667679d93d6c30f1b7490d669801712d3be2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/883667679d93d6c30f1b7490d669801712d3be2f", + "reference": "883667679d93d6c30f1b7490d669801712d3be2f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/polyfill-php81": "^1.22", + "symfony/translation-contracts": "^1.1|^2|^3" + }, + "conflict": { + "doctrine/annotations": "<1.13", + "doctrine/cache": "<1.11", + "doctrine/lexer": "<1.1", + "symfony/dependency-injection": "<4.4", + "symfony/expression-language": "<5.1", + "symfony/http-kernel": "<4.4", + "symfony/intl": "<4.4", + "symfony/property-info": "<5.3", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "^1.13|^2", + "doctrine/cache": "^1.11|^2.0", + "egulias/email-validator": "^2.1.10|^3|^4", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^5.1|^6.0", + "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.3|^6.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3", + "symfony/yaml": "^4.4|^5.0|^6.0" + }, + "suggest": { + "egulias/email-validator": "Strict (RFC compliant) email validation", + "psr/cache-implementation": "For using the mapping cache.", + "symfony/config": "", + "symfony/expression-language": "For using the Expression validator and the ExpressionLanguageSyntax constraints", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For accessing properties within comparison constraints", + "symfony/property-info": "To automatically add NotNull and Type constraints", + "symfony/translation": "For translating validation errors.", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/", + "/Resources/bin/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to validate values", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/validator/tree/v5.4.48" + }, + "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-11-27T08:58:20+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/42f18f170aa86d612c3559cfb3bd11a375df32c8", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.4.48" + }, + "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-11-08T15:21:10+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v6.4.25", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "4ff50a1b7c75d1d596aca50899d0c8c7e3de8358" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/4ff50a1b7c75d1d596aca50899d0c8c7e3de8358", + "reference": "4ff50a1b7c75d1d596aca50899d0c8c7e3de8358", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v6.4.25" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-18T13:06:32+00:00" + }, + { + "name": "symfony/yaml", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "a454d47278cc16a5db371fe73ae66a78a633371e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a454d47278cc16a5db371fe73ae66a78a633371e", + "reference": "a454d47278cc16a5db371fe73ae66a78a633371e", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.3" + }, + "require-dev": { + "symfony/console": "^5.3|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.4.45" + }, + "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:11:13+00:00" + }, + { + "name": "twig/twig", + "version": "v3.21.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "shasum": "" + }, + "require": { + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" + }, + "type": "library", + "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" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "behat/behat", + "version": "v3.24.1", + "source": { + "type": "git", + "url": "https://github.com/Behat/Behat.git", + "reference": "1b67565a55283b6c0d050a0e4c4e44025c791a67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Behat/zipball/1b67565a55283b6c0d050a0e4c4e44025c791a67", + "reference": "1b67565a55283b6c0d050a0e4c4e44025c791a67", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.12.0", + "composer-runtime-api": "^2.2", + "composer/xdebug-handler": "^1.4 || ^2.0 || ^3.0", + "ext-mbstring": "*", + "nikic/php-parser": "^4.19.2 || ^5.2", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.* ", + "psr/container": "^1.0 || ^2.0", + "symfony/config": "^5.4 || ^6.4 || ^7.0", + "symfony/console": "^5.4 || ^6.4 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", + "symfony/translation": "^5.4 || ^6.4 || ^7.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.68", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^9.6", + "rector/rector": "2.1.4", + "sebastian/diff": "^4.0", + "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", + "symfony/polyfill-php84": "^1.31", + "symfony/process": "^5.4 || ^6.4 || ^7.0" + }, + "suggest": { + "ext-dom": "Needed to output test results in JUnit format." + }, + "bin": [ + "bin/behat" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Hook\\": "src/Behat/Hook/", + "Behat\\Step\\": "src/Behat/Step/", + "Behat\\Behat\\": "src/Behat/Behat/", + "Behat\\Config\\": "src/Behat/Config/", + "Behat\\Testwork\\": "src/Behat/Testwork/", + "Behat\\Transformation\\": "src/Behat/Transformation/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Scenario-oriented BDD framework for PHP", + "homepage": "https://behat.org/", + "keywords": [ + "Agile", + "BDD", + "ScenarioBDD", + "Scrum", + "StoryBDD", + "User story", + "business", + "development", + "documentation", + "examples", + "symfony", + "testing" + ], + "support": { + "issues": "https://github.com/Behat/Behat/issues", + "source": "https://github.com/Behat/Behat/tree/v3.24.1" + }, + "time": "2025-09-15T09:09:06+00:00" + }, + { + "name": "behat/gherkin", + "version": "v4.14.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", + "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*" + }, + "require-dev": { + "cucumber/gherkin-monorepo": "dev-gherkin-v32.1.1", + "friendsofphp/php-cs-fixer": "^3.65", + "mikey179/vfsstream": "^1.6", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpunit/phpunit": "^10.5", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Gherkin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "https://everzet.com" + } + ], + "description": "Gherkin DSL parser for PHP", + "homepage": "https://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "support": { + "issues": "https://github.com/Behat/Gherkin/issues", + "source": "https://github.com/Behat/Gherkin/tree/v4.14.0" + }, + "time": "2025-05-23T15:06:40+00:00" + }, + { + "name": "behat/mink", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/minkphp/Mink.git", + "reference": "7e4edec6c335937029cb3569ce7ef81182804d0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/Mink/zipball/7e4edec6c335937029cb3569ce7ef81182804d0a", + "reference": "7e4edec6c335937029cb3569ce7ef81182804d0a", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/css-selector": "^4.4 || ^5.0 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^8.5.22 || ^9.5.11", + "symfony/error-handler": "^4.4 || ^5.0 || ^6.0 || ^7.0", + "symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "behat/mink-browserkit-driver": "fast headless driver for any app without JS emulation", + "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)", + "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Mink\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Browser controller/emulator abstraction for PHP", + "homepage": "https://mink.behat.org/", + "keywords": [ + "browser", + "testing", + "web" + ], + "support": { + "issues": "https://github.com/minkphp/Mink/issues", + "source": "https://github.com/minkphp/Mink/tree/v1.12.0" + }, + "time": "2024-10-30T18:48:14+00:00" + }, + { + "name": "behat/mink-browserkit-driver", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", + "reference": "16d53476e42827ed3aafbfa4fde17a1743eafd50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/16d53476e42827ed3aafbfa4fde17a1743eafd50", + "reference": "16d53476e42827ed3aafbfa4fde17a1743eafd50", + "shasum": "" + }, + "require": { + "behat/mink": "^1.11.0@dev", + "ext-dom": "*", + "php": ">=7.2", + "symfony/browser-kit": "^4.4 || ^5.0 || ^6.0 || ^7.0", + "symfony/dom-crawler": "^4.4 || ^5.0 || ^6.0 || ^7.0" + }, + "require-dev": { + "mink/driver-testsuite": "dev-master", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/error-handler": "^4.4 || ^5.0 || ^6.0 || ^7.0", + "symfony/http-client": "^4.4 || ^5.0 || ^6.0 || ^7.0", + "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0 || ^7.0", + "symfony/mime": "^4.4 || ^5.0 || ^6.0 || ^7.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Symfony2 BrowserKit driver for Mink framework", + "homepage": "https://mink.behat.org/", + "keywords": [ + "Mink", + "Symfony2", + "browser", + "testing" + ], + "support": { + "issues": "https://github.com/minkphp/MinkBrowserKitDriver/issues", + "source": "https://github.com/minkphp/MinkBrowserKitDriver/tree/v2.2.0" + }, + "time": "2023-12-09T11:30:50+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "dmore/behat-chrome-extension", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://gitlab.com/behat-chrome/behat-chrome-extension.git", + "reference": "888e91f52b3ffd19afe61cea3d5edebb0a4d43a7" + }, + "dist": { + "type": "zip", + "url": "https://gitlab.com/api/v4/projects/behat-chrome%2Fbehat-chrome-extension/repository/archive.zip?sha=888e91f52b3ffd19afe61cea3d5edebb0a4d43a7", + "reference": "888e91f52b3ffd19afe61cea3d5edebb0a4d43a7", + "shasum": "" + }, + "require": { + "behat/behat": "^3.0.4", + "dmore/chrome-mink-driver": "^2.4.1", + "friends-of-behat/mink-extension": "^2.0", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "DMore\\ChromeExtension\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dorian More", + "email": "doriancmore@gmail.com" + } + ], + "description": "Behat extension for controlling Chrome without Selenium", + "homepage": "https://gitlab.com/behat-chrome/chrome-mink-driver", + "keywords": [ + "Behat", + "chrome", + "driver", + "headless" + ], + "support": { + "issues": "https://gitlab.com/behat-chrome/behat-chrome-extension/-/issues", + "source": "https://gitlab.com/behat-chrome/behat-chrome-extension/-/tree/1.4.0" + }, + "time": "2022-04-10T04:25:11+00:00" + }, + { + "name": "dmore/chrome-mink-driver", + "version": "2.9.3", + "source": { + "type": "git", + "url": "https://gitlab.com/behat-chrome/chrome-mink-driver.git", + "reference": "4dc18d3b4668e749ab7bef5a6796c13711c93e61" + }, + "dist": { + "type": "zip", + "url": "https://gitlab.com/api/v4/projects/behat-chrome%2Fchrome-mink-driver/repository/archive.zip?sha=4dc18d3b4668e749ab7bef5a6796c13711c93e61", + "reference": "4dc18d3b4668e749ab7bef5a6796c13711c93e61", + "shasum": "" + }, + "require": { + "behat/mink": "^1.9", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "phrity/websocket": "^1.7.0" + }, + "require-dev": { + "mink/driver-testsuite": "dev-master", + "phpunit/phpunit": "^8.5.22 || ^9.5.11", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "DMore\\ChromeDriver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dorian More", + "email": "doriancmore@gmail.com" + } + ], + "description": "Mink driver for controlling chrome without selenium", + "homepage": "https://gitlab.com/behat-chrome/chrome-mink-driver", + "support": { + "issues": "https://gitlab.com/behat-chrome/chrome-mink-driver/-/issues", + "source": "https://gitlab.com/behat-chrome/chrome-mink-driver/-/tree/2.9.3" + }, + "time": "2024-05-17T12:26:55+00:00" + }, + { + "name": "friends-of-behat/mink-extension", + "version": "v2.7.5", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfBehat/MinkExtension.git", + "reference": "854336030e11983f580f49faad1b49a1238f9846" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfBehat/MinkExtension/zipball/854336030e11983f580f49faad1b49a1238f9846", + "reference": "854336030e11983f580f49faad1b49a1238f9846", + "shasum": "" + }, + "require": { + "behat/behat": "^3.0.5", + "behat/mink": "^1.5", + "php": ">=7.4", + "symfony/config": "^4.4 || ^5.0 || ^6.0 || ^7.0" + }, + "replace": { + "behat/mink-extension": "self.version" + }, + "require-dev": { + "behat/mink-goutte-driver": "^1.1 || ^2.0", + "phpspec/phpspec": "^6.0 || ^7.0 || 7.1.x-dev" + }, + "type": "behat-extension", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\MinkExtension": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com" + }, + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + } + ], + "description": "Mink extension for Behat", + "homepage": "http://extensions.behat.org/mink", + "keywords": [ + "browser", + "gui", + "test", + "web" + ], + "support": { + "issues": "https://github.com/FriendsOfBehat/MinkExtension/issues", + "source": "https://github.com/FriendsOfBehat/MinkExtension/tree/v2.7.5" + }, + "time": "2024-01-11T09:12:02+00:00" + }, + { + "name": "friends-of-behat/symfony-extension", + "version": "v2.4.2", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfBehat/SymfonyExtension.git", + "reference": "957df89b214f1575b40203e374bcafcd6d200a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfBehat/SymfonyExtension/zipball/957df89b214f1575b40203e374bcafcd6d200a1d", + "reference": "957df89b214f1575b40203e374bcafcd6d200a1d", + "shasum": "" + }, + "require": { + "behat/behat": "^3.6.1", + "php": "^7.4 || ^8.0", + "symfony/dependency-injection": "^4.4 || ^5.3 || ^6.0", + "symfony/http-kernel": "^4.4 || ^5.3 || ^6.0", + "symfony/proxy-manager-bridge": "^4.4 || ^5.3 || ^6.0" + }, + "require-dev": { + "behat/mink": "^1.9", + "behat/mink-browserkit-driver": "^2.0", + "behat/mink-selenium2-driver": "^1.3", + "friends-of-behat/mink-extension": "^2.5", + "friends-of-behat/page-object-extension": "^0.3.2", + "friends-of-behat/service-container-extension": "^1.1", + "sylius-labs/coding-standard": ">=4.1.1, <=4.2.1", + "symfony/browser-kit": "^4.4 || ^5.3 || ^6.0", + "symfony/framework-bundle": "^4.4 || ^5.3 || ^6.0", + "symfony/process": "^4.4 || ^5.3 || ^6.0", + "symfony/yaml": "^4.4 || ^5.3 || ^6.0", + "vimeo/psalm": "4.30.0" + }, + "suggest": { + "behat/mink": "^1.9", + "behat/mink-browserkit-driver": "^2.0", + "friends-of-behat/mink-extension": "^2.5" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "FriendsOfBehat\\SymfonyExtension\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kamil Kokot", + "email": "kamil@kokot.me", + "homepage": "https://kamilkokot.com" + } + ], + "description": "Integrates Behat with Symfony.", + "support": { + "issues": "https://github.com/FriendsOfBehat/SymfonyExtension/issues", + "source": "https://github.com/FriendsOfBehat/SymfonyExtension/tree/v2.4.2" + }, + "time": "2023-12-09T12:17:26+00:00" + }, + { + "name": "friendsofphp/proxy-manager-lts", + "version": "v1.0.18", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/proxy-manager-lts.git", + "reference": "2c8a6cffc3220e99352ad958fe7cf06bf6f7690f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/proxy-manager-lts/zipball/2c8a6cffc3220e99352ad958fe7cf06bf6f7690f", + "reference": "2c8a6cffc3220e99352ad958fe7cf06bf6f7690f", + "shasum": "" + }, + "require": { + "laminas/laminas-code": "~3.4.1|^4.0", + "php": ">=7.1", + "symfony/filesystem": "^4.4.17|^5.0|^6.0|^7.0" + }, + "conflict": { + "laminas/laminas-stdlib": "<3.2.1", + "zendframework/zend-stdlib": "<3.2.1" + }, + "replace": { + "ocramius/proxy-manager": "^2.1" + }, + "require-dev": { + "ext-phar": "*", + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/Ocramius/ProxyManager", + "name": "ocramius/proxy-manager" + } + }, + "autoload": { + "psr-4": { + "ProxyManager\\": "src/ProxyManager" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + } + ], + "description": "Adding support for a wider range of PHP versions to ocramius/proxy-manager", + "homepage": "https://github.com/FriendsOfPHP/proxy-manager-lts", + "keywords": [ + "aop", + "lazy loading", + "proxy", + "proxy pattern", + "service proxies" + ], + "support": { + "issues": "https://github.com/FriendsOfPHP/proxy-manager-lts/issues", + "source": "https://github.com/FriendsOfPHP/proxy-manager-lts/tree/v1.0.18" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager", + "type": "tidelift" + } + ], + "time": "2024-03-20T12:50:41+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "ingenerator/behat-tableassert", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/ingenerator/behat-tableassert.git", + "reference": "1aaba36c15fabc7fdf403baf1ff9d4a15a3ce86b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ingenerator/behat-tableassert/zipball/1aaba36c15fabc7fdf403baf1ff9d4a15a3ce86b", + "reference": "1aaba36c15fabc7fdf403baf1ff9d4a15a3ce86b", + "shasum": "" + }, + "require": { + "behat/gherkin": ">=2.0.0 <5.0.0", + "ext-dom": "*", + "ext-libxml": "*", + "ext-simplexml": "*", + "masterminds/html5": "^2.7.5", + "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "behat/mink": "^1.7", + "phpunit/phpunit": "^9.6.22" + }, + "suggest": { + "behat/mink": "For parsing tables from a browser response" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ingenerator\\BehatTableAssert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Andrew Coulton", + "email": "andrew@ingenerator.com" + } + ], + "description": "Assertions for all sorts of tabular data in behat", + "homepage": "https://github.com/ingenerator/behat-tableassert", + "support": { + "issues": "https://github.com/ingenerator/behat-tableassert/issues", + "source": "https://github.com/ingenerator/behat-tableassert/" + }, + "time": "2025-05-06T09:34:08+00:00" + }, + { + "name": "laminas/laminas-code", + "version": "4.16.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-code.git", + "reference": "1793e78dad4108b594084d05d1fb818b85b110af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1793e78dad4108b594084d05d1fb818b85b110af", + "reference": "1793e78dad4108b594084d05d1fb818b85b110af", + "shasum": "" + }, + "require": { + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0.1", + "ext-phar": "*", + "laminas/laminas-coding-standard": "^3.0.0", + "laminas/laminas-stdlib": "^3.18.0", + "phpunit/phpunit": "^10.5.37", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.15.0" + }, + "suggest": { + "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", + "laminas/laminas-stdlib": "Laminas\\Stdlib component" + }, + "type": "library", + "autoload": { + "psr-4": { + "Laminas\\Code\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", + "homepage": "https://laminas.dev", + "keywords": [ + "code", + "laminas", + "laminasframework" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-code/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-code/issues", + "rss": "https://github.com/laminas/laminas-code/releases.atom", + "source": "https://github.com/laminas/laminas-code" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2024-11-20T13:15:13+00:00" + }, + { + "name": "league/flysystem", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4037,182 +8733,247 @@ ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "description": "Assertions to validate method input/output with nice error messages.", + "description": "File storage abstraction for PHP", "keywords": [ - "assert", - "check", - "validate" + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" ], "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2025-06-25T13:29:59+00:00" }, { - "name": "zendframework/zend-code", - "version": "3.3.2", + "name": "league/flysystem-local", + "version": "3.30.0", "source": { "type": "git", - "url": "https://github.com/zendframework/zend-code.git", - "reference": "936fa7ad4d53897ea3e3eb41b5b760828246a20b" + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-code/zipball/936fa7ad4d53897ea3e3eb41b5b760828246a20b", - "reference": "936fa7ad4d53897ea3e3eb41b5b760828246a20b", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", "shasum": "" }, "require": { - "php": "^7.1", - "zendframework/zend-eventmanager": "^2.6 || ^3.0" - }, - "require-dev": { - "doctrine/annotations": "^1.0", - "ext-phar": "*", - "phpunit/phpunit": "^7.5.15", - "zendframework/zend-coding-standard": "^1.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0" - }, - "suggest": { - "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", - "zendframework/zend-stdlib": "Zend\\Stdlib component" + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3.x-dev", - "dev-develop": "3.4.x-dev" + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" + }, + "time": "2025-05-21T10:34:19+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" }, + "type": "library", "autoload": { "psr-4": { - "Zend\\Code\\": "src/" + "League\\MimeTypeDetection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", - "keywords": [ - "ZendFramework", - "code", - "zf" + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } ], - "abandoned": "laminas/laminas-code", - "time": "2019-08-31T14:14:34+00:00" + "time": "2024-09-21T08:32:55+00:00" }, { - "name": "zendframework/zend-eventmanager", - "version": "3.2.1", + "name": "liip/functional-test-bundle", + "version": "4.13.0", "source": { "type": "git", - "url": "https://github.com/zendframework/zend-eventmanager.git", - "reference": "a5e2583a211f73604691586b8406ff7296a946dd" + "url": "https://github.com/liip/LiipFunctionalTestBundle.git", + "reference": "f2c43ab303fadc0658edeef224159cfd493a69be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/a5e2583a211f73604691586b8406ff7296a946dd", - "reference": "a5e2583a211f73604691586b8406ff7296a946dd", + "url": "https://api.github.com/repos/liip/LiipFunctionalTestBundle/zipball/f2c43ab303fadc0658edeef224159cfd493a69be", + "reference": "f2c43ab303fadc0658edeef224159cfd493a69be", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.4 || ^8.0", + "phpunit/phpunit": "^9.6 || ^10.0 || ^11.0", + "symfony/browser-kit": "^5.4 || ^6.4 || ^7.0", + "symfony/framework-bundle": "^5.4 || ^6.4 || ^7.0" + }, + "conflict": { + "symfony/framework-bundle": "4.3.0" }, "require-dev": { - "athletic/athletic": "^0.1", - "container-interop/container-interop": "^1.1.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", - "zendframework/zend-coding-standard": "~1.0.0", - "zendframework/zend-stdlib": "^2.7.3 || ^3.0" + "doctrine/annotations": "^1.3 || ^2.0", + "doctrine/doctrine-bundle": "^2.11", + "doctrine/orm": "^2.7", + "ext-json": "*", + "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0", + "symfony/css-selector": "^5.4 || ^6.4 || ^7.0", + "symfony/doctrine-bridge": "^5.4 || ^6.4 || ^7.0", + "symfony/form": "^5.4 || ^6.4 || ^7.0", + "symfony/http-kernel": "^5.4 || ^6.4 || ^7.0", + "symfony/monolog-bundle": "^3.4", + "symfony/security-bundle": "^5.4 || ^6.4 || ^7.0", + "symfony/twig-bundle": "^5.4 || ^6.4 || ^7.0", + "symfony/validator": "^5.4 || ^6.4 || ^7.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0", + "twig/twig": "^2.0 || ^3.8" }, "suggest": { - "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", - "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" + "doctrine/annotations": "Required to use the @QueryCount(…) annotation", + "liip/test-fixtures-bundle": "Efficient loading of Doctrine fixtures in functional test-cases for Symfony applications" }, - "type": "library", + "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-master": "3.2-dev", - "dev-develop": "3.3-dev" + "dev-master": "4.x-dev" } }, "autoload": { "psr-4": { - "Zend\\EventManager\\": "src/" + "Liip\\FunctionalTestBundle\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" + ], + "authors": [ + { + "name": "Liip AG", + "homepage": "http://www.liip.ch/" + }, + { + "name": "Community contributions", + "homepage": "https://github.com/liip/LiipFunctionalTestBundle/contributors" + } ], - "description": "Trigger and listen to events within a PHP application", - "homepage": "https://github.com/zendframework/zend-eventmanager", + "description": "This bundles provides additional functional test-cases for Symfony applications", "keywords": [ - "event", - "eventmanager", - "events", - "zf2" + "symfony", + "testing" ], - "abandoned": "laminas/laminas-eventmanager", - "time": "2018-04-25T15:33:34+00:00" - } - ], - "packages-dev": [ + "support": { + "issues": "https://github.com/liip/LiipFunctionalTestBundle/issues", + "source": "https://github.com/liip/LiipFunctionalTestBundle/tree/4.13.0" + }, + "time": "2025-03-12T18:08:44+00:00" + }, { - "name": "behat/behat", - "version": "v3.7.0", + "name": "malukenho/docheader", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/Behat/Behat.git", - "reference": "08052f739619a9e9f62f457a67302f0715e6dd13" + "url": "https://github.com/malukenho/docheader.git", + "reference": "263320d434c727a014650239c90240bbe808bd17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/08052f739619a9e9f62f457a67302f0715e6dd13", - "reference": "08052f739619a9e9f62f457a67302f0715e6dd13", + "url": "https://api.github.com/repos/malukenho/docheader/zipball/263320d434c727a014650239c90240bbe808bd17", + "reference": "263320d434c727a014650239c90240bbe808bd17", "shasum": "" }, "require": { - "behat/gherkin": "^4.6.0", - "behat/transliterator": "^1.2", - "ext-mbstring": "*", - "php": ">=5.3.3", - "psr/container": "^1.0", - "symfony/config": "^2.7.51 || ^3.0 || ^4.0 || ^5.0", - "symfony/console": "^2.7.51 || ^2.8.33 || ^3.3.15 || ^3.4.3 || ^4.0.3 || ^5.0", - "symfony/dependency-injection": "^2.7.51 || ^3.0 || ^4.0 || ^5.0", - "symfony/event-dispatcher": "^2.7.51 || ^3.0 || ^4.0 || ^5.0", - "symfony/translation": "^2.7.51 || ^3.0 || ^4.0 || ^5.0", - "symfony/yaml": "^2.7.51 || ^3.0 || ^4.0 || ^5.0" + "php": "^8.0", + "symfony/console": "^4.4 || ^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "container-interop/container-interop": "^1.2", - "herrera-io/box": "~1.6.1", - "phpunit/phpunit": "^4.8.36 || ^6.5.14 || ^7.5.20", - "symfony/process": "~2.5 || ^3.0 || ^4.0 || ^5.0" - }, - "suggest": { - "ext-dom": "Needed to output test results in JUnit format." + "doctrine/coding-standard": "^9.0", + "mikey179/vfsstream": "^1.6.10", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.23 || ^5.0" }, "bin": [ - "bin/behat" + "bin/docheader" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.6.x-dev" - } - }, "autoload": { "psr-4": { - "Behat\\Behat\\": "src/Behat/Behat/", - "Behat\\Testwork\\": "src/Behat/Testwork/" + "DocHeader\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4221,1023 +8982,1207 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Jefersson Nathan", + "email": "malukenho.dev@gmail.com" } ], - "description": "Scenario-oriented BDD framework for PHP 5.3", - "homepage": "http://behat.org/", + "description": "A small library to check header docs", + "homepage": "https://github.com/malukenho/docheader", "keywords": [ - "Agile", - "BDD", - "ScenarioBDD", - "Scrum", - "StoryBDD", - "User story", - "business", - "development", - "documentation", - "examples", - "symfony", - "testing" + "Code style", + "code standard", + "license", + "static analysis" ], "support": { - "issues": "https://github.com/Behat/Behat/issues", - "source": "https://github.com/Behat/Behat/tree/v3.7.0" + "issues": "https://github.com/malukenho/docheader/issues", + "source": "https://github.com/malukenho/docheader/tree/1.1.0" }, - "time": "2020-06-03T13:08:44+00:00" + "time": "2024-02-05T12:05:53+00:00" }, { - "name": "behat/gherkin", - "version": "v4.6.0", + "name": "masterminds/html5", + "version": "2.10.0", "source": { "type": "git", - "url": "https://github.com/Behat/Gherkin.git", - "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07" + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "fcf91eb64359852f00d921887b219479b4f21251" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/ab0a02ea14893860bca00f225f5621d351a3ad07", - "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", + "reference": "fcf91eb64359852f00d921887b219479b4f21251", "shasum": "" }, "require": { - "php": ">=5.3.1" + "ext-dom": "*", + "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "~4.5|~5", - "symfony/phpunit-bridge": "~2.7|~3|~4", - "symfony/yaml": "~2.3|~3|~4" - }, - "suggest": { - "symfony/yaml": "If you want to parse features, represented in YAML files" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" + }, + "time": "2025-07-25T09:04:22+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } ], - "description": "Gherkin DSL parser for PHP 5.3", - "homepage": "http://behat.org/", + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", "keywords": [ "BDD", - "Behat", - "Cucumber", - "DSL", - "gherkin", - "parser" + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" ], - "time": "2019-01-16T14:22:17+00:00" + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" }, { - "name": "behat/mink", - "version": "v1.7.1", + "name": "myclabs/deep-copy", + "version": "1.13.4", "source": { "type": "git", - "url": "https://github.com/minkphp/Mink.git", - "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/Mink/zipball/e6930b9c74693dff7f4e58577e1b1743399f3ff9", - "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { - "php": ">=5.3.1", - "symfony/css-selector": "~2.1|~3.0" + "php": "^7.1 || ^8.0" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, - "suggest": { - "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", - "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", - "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", - "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "Behat\\Mink\\": "src/" + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" } ], - "description": "Browser controller/emulator abstraction for PHP", - "homepage": "http://mink.behat.org/", - "keywords": [ - "browser", - "testing", - "web" - ], - "time": "2016-03-05T08:26:18+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { - "name": "behat/mink-browserkit-driver", - "version": "1.3.3", + "name": "nikic/php-parser", + "version": "v5.6.1", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", - "reference": "1b9a7ce903cfdaaec5fb32bfdbb26118343662eb" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/1b9a7ce903cfdaaec5fb32bfdbb26118343662eb", - "reference": "1b9a7ce903cfdaaec5fb32bfdbb26118343662eb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", "shasum": "" }, "require": { - "behat/mink": "^1.7.1@dev", - "php": ">=5.3.6", - "symfony/browser-kit": "~2.3|~3.0|~4.0", - "symfony/dom-crawler": "~2.3|~3.0|~4.0" + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" }, "require-dev": { - "mink/driver-testsuite": "dev-master", - "symfony/http-kernel": "~2.3|~3.0|~4.0" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" }, - "type": "mink-driver", + "bin": [ + "bin/php-parse" + ], + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "Behat\\Mink\\Driver\\": "src/" + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Nikita Popov" } ], - "description": "Symfony2 BrowserKit driver for Mink framework", - "homepage": "http://mink.behat.org/", + "description": "A PHP parser written in PHP", "keywords": [ - "Mink", - "Symfony2", - "browser", - "testing" + "parser", + "php" ], - "time": "2018-05-02T09:25:31+00:00" + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + }, + "time": "2025-08-13T20:13:15+00:00" }, { - "name": "behat/mink-extension", - "version": "2.3.1", + "name": "pdepend/pdepend", + "version": "2.16.2", "source": { "type": "git", - "url": "https://github.com/Behat/MinkExtension.git", - "reference": "80f7849ba53867181b7e412df9210e12fba50177" + "url": "https://github.com/pdepend/pdepend.git", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/80f7849ba53867181b7e412df9210e12fba50177", - "reference": "80f7849ba53867181b7e412df9210e12fba50177", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", "shasum": "" }, "require": { - "behat/behat": "^3.0.5", - "behat/mink": "^1.5", - "php": ">=5.3.2", - "symfony/config": "^2.7|^3.0|^4.0" + "php": ">=5.3.7", + "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/polyfill-mbstring": "^1.19" }, "require-dev": { - "behat/mink-goutte-driver": "^1.1", - "phpspec/phpspec": "^2.0" + "easy-doc/easy-doc": "0.0.0|^1.2.3", + "gregwar/rst": "^1.0", + "squizlabs/php_codesniffer": "^2.0.0" }, - "type": "behat-extension", + "bin": [ + "src/bin/pdepend" + ], + "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { - "psr-0": { - "Behat\\MinkExtension": "src/" + "psr-4": { + "PDepend\\": "src/main/php/PDepend" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "authors": [ - { - "name": "Christophe Coevoet", - "email": "stof@notk.org" - }, + "description": "Official version of pdepend to be handled with Composer", + "keywords": [ + "PHP Depend", + "PHP_Depend", + "dev", + "pdepend" + ], + "support": { + "issues": "https://github.com/pdepend/pdepend/issues", + "source": "https://github.com/pdepend/pdepend/tree/2.16.2" + }, + "funding": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com" + "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", + "type": "tidelift" } ], - "description": "Mink extension for Behat", - "homepage": "http://extensions.behat.org/mink", - "keywords": [ - "browser", - "gui", - "test", - "web" - ], - "time": "2018-02-06T15:36:30+00:00" + "time": "2023-12-17T18:09:59+00:00" }, { - "name": "behat/mink-goutte-driver", - "version": "v1.2.1", + "name": "phake/phake", + "version": "v4.6.1", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkGoutteDriver.git", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" + "url": "https://github.com/phake/phake.git", + "reference": "fca279683f26db1ec729da773479f6bfceb6f0e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "url": "https://api.github.com/repos/phake/phake/zipball/fca279683f26db1ec729da773479f6bfceb6f0e0", + "reference": "fca279683f26db1ec729da773479f6bfceb6f0e0", "shasum": "" }, "require": { - "behat/mink": "~1.6@dev", - "behat/mink-browserkit-driver": "~1.2@dev", - "fabpot/goutte": "~1.0.4|~2.0|~3.1", - "php": ">=5.3.1" + "doctrine/instantiator": "^1.4", + "php": "^7.1|^8.0", + "sebastian/comparator": "^1.1|^2.0|^3.0|^4.0|^5.0|^6.0|^7.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" + "doctrine/annotations": "^1.13", + "hamcrest/hamcrest-php": "^1.1|^2.0", + "phpunit/phpunit": "^6.5|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "psalm/phar": "^4.18" }, - "type": "mink-driver", + "suggest": { + "doctrine/annotations": "Allows mock annotations to use import statements for classes.", + "hamcrest/hamcrest-php": "Use Hamcrest matchers." + }, + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-4.4": "4.4.x-dev", + "dev-master": "5.0.x-dev" } }, "autoload": { + "files": [ + "src/Phake.php" + ], "psr-4": { - "Behat\\Mink\\Driver\\": "src/" + "Phake\\": "src/Phake" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Mike Lively", + "email": "m@digitalsandwich.com" } ], - "description": "Goutte driver for Mink framework", - "homepage": "http://mink.behat.org/", + "description": "The Phake mock testing library", + "homepage": "https://phake.github.io", "keywords": [ - "browser", - "goutte", - "headless", + "mock", + "phake", + "spy", + "stub", + "test-doubles", "testing" ], - "time": "2016-03-05T09:04:22+00:00" + "support": { + "docs": "https://phake.github.io/doc/", + "issues": "https://github.com/phake/phake/issues", + "source": "https://github.com/phake/phake/tree/v4.6.1" + }, + "time": "2025-03-11T03:06:35+00:00" }, { - "name": "behat/mink-selenium2-driver", - "version": "v1.3.1", + "name": "phar-io/manifest", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkSelenium2Driver.git", - "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/473a9f3ebe0c134ee1e623ce8a9c852832020288", - "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "behat/mink": "~1.7@dev", - "instaclick/php-webdriver": "~1.1", - "php": ">=5.3.1" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, - "type": "mink-driver", + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-4": { - "Behat\\Mink\\Driver\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "name": "Pete Otaqui", - "email": "pete@otaqui.com", - "homepage": "https://github.com/pete-otaqui" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Selenium2 (WebDriver) driver for Mink framework", - "homepage": "http://mink.behat.org/", - "keywords": [ - "ajax", - "browser", - "javascript", - "selenium", - "testing", - "webdriver" + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } ], - "time": "2016-03-05T09:10:18+00:00" + "time": "2024-03-03T12:33:53+00:00" }, { - "name": "behat/symfony2-extension", - "version": "2.1.5", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/Behat/Symfony2Extension.git", - "reference": "d7c834487426a784665f9c1e61132274dbf2ea26" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Symfony2Extension/zipball/d7c834487426a784665f9c1e61132274dbf2ea26", - "reference": "d7c834487426a784665f9c1e61132274dbf2ea26", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "behat/behat": "^3.4.3", - "php": ">=5.3.3", - "symfony/framework-bundle": "~2.0|~3.0|~4.0" - }, - "require-dev": { - "behat/mink": "~1.7@dev", - "behat/mink-browserkit-driver": "~1.3@dev", - "behat/mink-extension": "~2.0", - "phpspec/phpspec": "~2.0|~3.0|~4.0", - "phpunit/phpunit": "~4.0|~5.0", - "symfony/symfony": "~2.1|~3.0|~4.0" - }, - "type": "behat-extension", - "extra": { - "branch-alias": { - "dev-master": "2.1.x-dev" - } + "php": "^7.2 || ^8.0" }, + "type": "library", "autoload": { - "psr-0": { - "Behat\\Symfony2Extension": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Christophe Coevoet", - "email": "stof@notk.org" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Symfony2 framework extension for Behat", - "homepage": "http://behat.org", - "keywords": [ - "BDD", - "framework", - "symfony" - ], - "abandoned": "friends-of-behat/symfony-extension", - "time": "2018-04-20T15:48:23+00:00" + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "behat/transliterator", - "version": "v1.2.0", + "name": "phpcompatibility/php-compatibility", + "version": "9.3.5", "source": { "type": "git", - "url": "https://github.com/Behat/Transliterator.git", - "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c" + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Transliterator/zipball/826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", - "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" }, - "require-dev": { - "chuyskywalker/rolling-curl": "^3.1", - "php-yaoi/php-yaoi": "^1.0" + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } + "require-dev": { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" }, - "autoload": { - "psr-0": { - "Behat\\Transliterator": "src/" - } + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "Artistic-1.0" + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } ], - "description": "String transliterator", + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", "keywords": [ - "i18n", - "slug", - "transliterator" + "compatibility", + "phpcs", + "standards" ], - "time": "2017-04-04T11:38:05+00:00" + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" + }, + "time": "2019-12-27T09:44:58+00:00" }, { - "name": "composer/pcre", - "version": "1.0.1", + "name": "phpmd/phpmd", + "version": "2.15.0", "source": { "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + "url": "https://github.com/phpmd/phpmd.git", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", + "ext-xml": "*", + "pdepend/pdepend": "^2.16.1", + "php": ">=5.3.9" }, "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" + "easy-doc/easy-doc": "0.0.0 || ^1.3.2", + "ext-json": "*", + "ext-simplexml": "*", + "gregwar/rst": "^1.0", + "mikey179/vfsstream": "^1.6.8", + "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" }, + "bin": [ + "src/bin/phpmd" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" + "psr-0": { + "PHPMD\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Manuel Pichler", + "email": "github@manuel-pichler.de", + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" + }, + { + "name": "Marc Würth", + "email": "ravage@bluewin.ch", + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" + }, + { + "name": "Other contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" } ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", + "homepage": "https://phpmd.org/", "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" + "dev", + "mess detection", + "mess detector", + "pdepend", + "phpmd", + "pmd" ], "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.1" + "irc": "irc://irc.freenode.org/phpmd", + "issues": "https://github.com/phpmd/phpmd/issues", + "source": "https://github.com/phpmd/phpmd/tree/2.15.0" }, "funding": [ { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", "type": "tidelift" } ], - "time": "2022-01-21T20:24:37+00:00" + "time": "2023-12-11T08:22:20+00:00" }, { - "name": "composer/xdebug-handler", - "version": "2.0.5", + "name": "phpstan/phpstan", + "version": "2.1.28", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" + "url": "https://github.com/phpstan/phpstan.git", + "reference": "578fa296a166605d97b94091f724f1257185d278" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/578fa296a166605d97b94091f724f1257185d278", + "reference": "578fa296a166605d97b94091f724f1257185d278", "shasum": "" }, "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" + "php": "^7.4|^8.0" }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + "conflict": { + "phpstan/phpstan-shim": "*" }, + "bin": [ + "phpstan", + "phpstan.phar" + ], "type": "library", "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "Xdebug", - "performance" + "dev", + "static analysis" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + "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://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", + "url": "https://github.com/ondrejmirtes", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" + "url": "https://github.com/phpstan", + "type": "github" } ], - "time": "2022-02-24T20:20:32+00:00" + "time": "2025-09-19T08:58:49+00:00" }, { - "name": "fabpot/goutte", - "version": "v3.2.3", + "name": "phpunit/php-code-coverage", + "version": "10.1.16", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "3f0eaf0a40181359470651f1565b3e07e3dd31b8" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/3f0eaf0a40181359470651f1565b3e07e3dd31b8", - "reference": "3f0eaf0a40181359470651f1565b3e07e3dd31b8", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "^6.0", - "php": ">=5.5.0", - "symfony/browser-kit": "~2.1|~3.0|~4.0", - "symfony/css-selector": "~2.1|~3.0|~4.0", - "symfony/dom-crawler": "~2.1|~3.0|~4.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "symfony/phpunit-bridge": "^3.3 || ^4" + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, - "type": "application", + "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { - "psr-4": { - "Goutte\\": "Goutte" - }, - "exclude-from-classmap": [ - "Goutte/Tests" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A simple PHP Web Scraper", - "homepage": "https://github.com/FriendsOfPHP/Goutte", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "scraper" + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2018-06-29T15:13:57+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { - "name": "hamcrest/hamcrest-php", - "version": "v2.0.0", + "name": "phpunit/php-file-iterator", + "version": "4.1.0", "source": { "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "776503d3a8e85d4f9a1148614f95b7a608b046ad" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/776503d3a8e85d4f9a1148614f95b7a608b046ad", - "reference": "776503d3a8e85d4f9a1148614f95b7a608b046ad", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": "^5.3|^7.0" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" + "php": ">=8.1" }, "require-dev": { - "phpunit/php-file-iterator": "1.3.3", - "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "^1.0" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ - "hamcrest" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD" + "BSD-3-Clause" ], - "description": "This is the PHP port of Hamcrest Matchers", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ - "test" + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2016-01-20T08:20:44+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { - "name": "ingenerator/behat-tableassert", - "version": "v1.2.0", + "name": "phpunit/php-invoker", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/ingenerator/behat-tableassert.git", - "reference": "9c0b254fc798f75151200c58662c31f6d6a05184" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ingenerator/behat-tableassert/zipball/9c0b254fc798f75151200c58662c31f6d6a05184", - "reference": "9c0b254fc798f75151200c58662c31f6d6a05184", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "behat/gherkin": ">=2.0.0 <5.0.0", - "ext-dom": "*", - "ext-libxml": "*", - "ext-simplexml": "*", - "php": "^7.2" + "php": ">=8.1" }, "require-dev": { - "behat/mink": "^1.7", - "phpunit/phpunit": "^7.0" + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" }, "suggest": { - "behat/mink": "For parsing tables from a browser response" + "ext-pcntl": "*" }, "type": "library", - "autoload": { - "psr-4": { - "Ingenerator\\BehatTableAssert\\": "src/" + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Andrew Coulton", - "email": "andrew@ingenerator.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Assertions for all sorts of tabular data in behat", - "homepage": "https://github.com/ingenerator/behat-tableassert", - "time": "2019-04-03T14:26:15+00:00" + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" }, { - "name": "instaclick/php-webdriver", - "version": "1.4.6", + "name": "phpunit/php-text-template", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/instaclick/php-webdriver.git", - "reference": "bd9405077ca04129a73059a06873bedb5e138402" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/bd9405077ca04129a73059a06873bedb5e138402", - "reference": "bd9405077ca04129a73059a06873bedb5e138402", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "ext-curl": "*", - "php": ">=5.3.2" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0||^2.0" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { - "psr-0": { - "WebDriver": "lib/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "BSD-3-Clause" ], "authors": [ { - "name": "Justin Bishop", - "email": "jubishop@gmail.com", - "role": "Developer" - }, - { - "name": "Anthon Pang", - "email": "apang@softwaredevelopment.ca", - "role": "Fork Maintainer" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "PHP WebDriver for Selenium 2", - "homepage": "http://instaclick.com/", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "browser", - "selenium", - "webdriver", - "webtest" + "template" ], - "time": "2019-09-23T15:50:44+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" }, { - "name": "league/flysystem", - "version": "2.5.0", + "name": "phpunit/php-timer", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/thephpleague/flysystem.git", - "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8aaffb653c5777781b0f7f69a5d937baf7ab6cdb", - "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "ext-json": "*", - "league/mime-type-detection": "^1.0.0", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "guzzlehttp/ringphp": "<1.1.1" + "php": ">=8.1" }, "require-dev": { - "async-aws/s3": "^1.5", - "async-aws/simple-s3": "^1.0", - "aws/aws-sdk-php": "^3.132.4", - "composer/semver": "^3.0", - "ext-fileinfo": "*", - "ext-ftp": "*", - "friendsofphp/php-cs-fixer": "^3.2", - "google/cloud-storage": "^1.23", - "phpseclib/phpseclib": "^2.0", - "phpstan/phpstan": "^0.12.26", - "phpunit/phpunit": "^8.5 || ^9.4", - "sabre/dav": "^4.1" + "phpunit/phpunit": "^10.0" }, "type": "library", - "autoload": { - "psr-4": { - "League\\Flysystem\\": "src" + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Frank de Jonge", - "email": "info@frankdejonge.nl" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "File storage abstraction for PHP", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "WebDAV", - "aws", - "cloud", - "file", - "files", - "filesystem", - "filesystems", - "ftp", - "s3", - "sftp", - "storage" + "timer" ], "support": { - "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/2.5.0" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { - "url": "https://ecologi.com/frankdejonge", - "type": "custom" - }, - { - "url": "https://github.com/frankdejonge", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/league/flysystem", - "type": "tidelift" } ], - "time": "2022-09-17T21:02:32+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { - "name": "league/mime-type-detection", - "version": "1.7.0", + "name": "phpunit/phpunit", + "version": "10.5.55", "source": { "type": "git", - "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "4b2d546b336876bd9562f24641b08a25335b06b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3", - "reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b2d546b336876bd9562f24641b08a25335b06b6", + "reference": "4b2d546b336876bd9562f24641b08a25335b06b6", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "php": "^7.2 || ^8.0" + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.4", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.1", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "phpstan/phpstan": "^0.12.68", - "phpunit/phpunit": "^8.5.8 || ^9.3" + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" }, + "bin": [ + "phpunit" + ], "type": "library", - "autoload": { - "psr-4": { - "League\\MimeTypeDetection\\": "src" + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" } }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Frank de Jonge", - "email": "info@frankdejonge.nl" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Mime-type detection for Flysystem", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.55" + }, "funding": [ { - "url": "https://github.com/frankdejonge", + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2021-01-18T20:58:21+00:00" + "time": "2025-09-14T06:19:20+00:00" }, { - "name": "liip/functional-test-bundle", - "version": "4.3.0", + "name": "phrity/net-stream", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/liip/LiipFunctionalTestBundle.git", - "reference": "9797828746b67b7aeb03a136a951d28781f09253" + "url": "https://github.com/sirn-se/phrity-net-stream.git", + "reference": "9105931b65ad90c75f4885a40b268b0f65802e3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/liip/LiipFunctionalTestBundle/zipball/9797828746b67b7aeb03a136a951d28781f09253", - "reference": "9797828746b67b7aeb03a136a951d28781f09253", + "url": "https://api.github.com/repos/sirn-se/phrity-net-stream/zipball/9105931b65ad90c75f4885a40b268b0f65802e3e", + "reference": "9105931b65ad90c75f4885a40b268b0f65802e3e", "shasum": "" }, "require": { - "doctrine/annotations": "^1.3", - "php": "^7.2 || ^8.0", - "phpunit/phpunit": "^7.5.0 || ^8.0 || ^9.0", - "symfony/browser-kit": "^3.4 || ^4.4 || ^5.1", - "symfony/framework-bundle": "^3.4 || ^4.4 || ^5.1" - }, - "conflict": { - "symfony/framework-bundle": "4.3.0" + "php": "^7.4 | ^8.0", + "phrity/util-errorhandler": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 | ^2.0" }, "require-dev": { - "doctrine/doctrine-bundle": "^1.8 || ^2.0", - "doctrine/orm": "^2.6.3", - "monolog/monolog": "~1.11", - "symfony/css-selector": "^3.4.33 || ^4.4 || ^5.1", - "symfony/form": "^3.4.33 || ^4.4 || ^5.1", - "symfony/http-kernel": "^3.4.33 || ^4.4 || ^5.1", - "symfony/monolog-bundle": "^3.4", - "symfony/phpunit-bridge": "^3.4.33 || ^4.4 || ^5.1", - "symfony/security-bundle": "^3.4.33 || ^4.4 || ^5.1", - "symfony/twig-bundle": "^3.4.33 || ^4.4 || ^5.1", - "symfony/validator": "^3.4.33 || ^4.4 || ^5.1", - "symfony/yaml": "^3.4.33 || ^4.4 || ^5.1", - "twig/twig": "^2.0 || ^3.0" - }, - "suggest": { - "liip/test-fixtures-bundle": "Efficient loading of Doctrine fixtures in functional test-cases for Symfony applications" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } + "php-coveralls/php-coveralls": "^2.0", + "phpunit/phpunit": "^9.0 | ^10.0", + "phrity/net-uri": "^1.1", + "squizlabs/php_codesniffer": "^3.0" }, + "type": "library", "autoload": { "psr-4": { - "Liip\\FunctionalTestBundle\\": "src/" + "Phrity\\Net\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -5246,56 +10191,56 @@ ], "authors": [ { - "name": "Liip AG", - "homepage": "http://www.liip.ch/" - }, - { - "name": "Community contributions", - "homepage": "https://github.com/liip/LiipFunctionalTestBundle/contributors" + "name": "Sören Jensen", + "email": "sirn@sirn.se", + "homepage": "https://phrity.sirn.se" } ], - "description": "This bundles provides additional functional test-cases for Symfony applications", + "description": "Socket stream classes implementing PSR-7 Stream and PSR-17 StreamFactory", + "homepage": "https://phrity.sirn.se/net-stream", "keywords": [ - "symfony", - "testing" + "Socket", + "client", + "psr-17", + "psr-7", + "server", + "stream", + "stream factory" ], "support": { - "issues": "https://github.com/liip/LiipFunctionalTestBundle/issues", - "source": "https://github.com/liip/LiipFunctionalTestBundle/tree/4.3.0" + "issues": "https://github.com/sirn-se/phrity-net-stream/issues", + "source": "https://github.com/sirn-se/phrity-net-stream/tree/1.3.0" }, - "time": "2021-02-24T21:17:26+00:00" + "time": "2023-10-22T10:47:03+00:00" }, { - "name": "malukenho/docheader", - "version": "0.1.8", + "name": "phrity/net-uri", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/malukenho/docheader.git", - "reference": "a15c22ba8a44add72a2b2bca5e40af244a53497c" + "url": "https://github.com/sirn-se/phrity-net-uri.git", + "reference": "3f458e0c4d1ddc0e218d7a5b9420127c63925f43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/malukenho/docheader/zipball/a15c22ba8a44add72a2b2bca5e40af244a53497c", - "reference": "a15c22ba8a44add72a2b2bca5e40af244a53497c", + "url": "https://api.github.com/repos/sirn-se/phrity-net-uri/zipball/3f458e0c4d1ddc0e218d7a5b9420127c63925f43", + "reference": "3f458e0c4d1ddc0e218d7a5b9420127c63925f43", "shasum": "" }, "require": { - "php": "^7.1 | ^8.0", - "symfony/console": "^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^3.0 || ^4.0 || ^5.0" + "php": "^7.4 | ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 | ^2.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.0 || ^8.0", - "vimeo/psalm": "^3.3" + "php-coveralls/php-coveralls": "^2.0", + "phpunit/phpunit": "^9.0 | ^10.0", + "squizlabs/php_codesniffer": "^3.0" }, - "bin": [ - "bin/docheader" - ], "type": "library", "autoload": { "psr-4": { - "DocHeader\\": "src/" + "Phrity\\Net\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -5304,246 +10249,228 @@ ], "authors": [ { - "name": "Jefersson Nathan", - "email": "malukenho.dev@gmail.com" + "name": "Sören Jensen", + "email": "sirn@sirn.se", + "homepage": "https://phrity.sirn.se" } ], - "description": "A small library to check header docs", - "homepage": "https://github.com/malukenho/docheader", + "description": "PSR-7 Uri and PSR-17 UriFactory implementation", + "homepage": "https://phrity.sirn.se/net-uri", "keywords": [ - "Code style", - "code standard", - "license" + "psr-17", + "psr-7", + "uri", + "uri factory" ], "support": { - "issues": "https://github.com/malukenho/docheader/issues", - "source": "https://github.com/malukenho/docheader/tree/master" + "issues": "https://github.com/sirn-se/phrity-net-uri/issues", + "source": "https://github.com/sirn-se/phrity-net-uri/tree/1.3.0" }, - "time": "2019-11-22T07:32:36+00:00" + "time": "2023-08-21T10:33:06+00:00" }, { - "name": "mockery/mockery", - "version": "1.3.1", + "name": "phrity/util-errorhandler", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be" + "url": "https://github.com/sirn-se/phrity-util-errorhandler.git", + "reference": "9825f15ef9b4a93252ce53ca8962278832d834da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be", - "reference": "f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be", + "url": "https://api.github.com/repos/sirn-se/phrity-util-errorhandler/zipball/9825f15ef9b4a93252ce53ca8962278832d834da", + "reference": "9825f15ef9b4a93252ce53ca8962278832d834da", "shasum": "" }, "require": { - "hamcrest/hamcrest-php": "~2.0", - "lib-pcre": ">=7.0", - "php": ">=5.6.0" + "php": "^8.1" }, "require-dev": { - "phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0" + "php-coveralls/php-coveralls": "^2.0", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.0 | ^11.0 | ^12.0", + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { - "psr-0": { - "Mockery": "library/" + "psr-4": { + "Phrity\\Util\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" - }, - { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" - } - ], - "description": "Mockery is a simple yet flexible PHP mock object framework", - "homepage": "https://github.com/mockery/mockery", - "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" + "MIT" + ], + "authors": [ + { + "name": "Sören Jensen", + "email": "sirn@sirn.se", + "homepage": "https://phrity.sirn.se" + } + ], + "description": "Inline error handler; catch and resolve errors for code block.", + "homepage": "https://phrity.sirn.se/util-errorhandler", + "keywords": [ + "error", + "warning" ], "support": { - "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/master" + "issues": "https://github.com/sirn-se/phrity-util-errorhandler/issues", + "source": "https://github.com/sirn-se/phrity-util-errorhandler/tree/1.2.1" }, - "time": "2019-12-26T09:49:15+00:00" + "time": "2025-08-08T09:48:45+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.10.2", + "name": "phrity/websocket", + "version": "1.7.3", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "url": "https://github.com/sirn-se/websocket-php.git", + "reference": "8a525da4457b599ab1960f24183f25626c96ce3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/sirn-se/websocket-php/zipball/8a525da4457b599ab1960f24183f25626c96ce3c", + "reference": "8a525da4457b599ab1960f24183f25626c96ce3c", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.4 | ^8.0", + "phrity/net-stream": "^1.2", + "phrity/net-uri": "^1.2", + "phrity/util-errorhandler": "^1.0", + "psr/http-message": "^1.1 | ^2.0", + "psr/log": "^1.0 | ^2.0 | ^3.0" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "php-coveralls/php-coveralls": "^2.0", + "phpunit/phpunit": "^9.0 | ^10.0", + "phrity/net-mock": "^1.3", + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], "psr-4": { - "DeepCopy\\": "src/DeepCopy/" + "WebSocket\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "ISC" ], - "description": "Create deep copies (clones) of your objects", + "authors": [ + { + "name": "Fredrik Liljegren" + }, + { + "name": "Sören Jensen", + "email": "sirn@sirn.se", + "homepage": "https://phrity.sirn.se" + } + ], + "description": "WebSocket client and server", + "homepage": "https://phrity.sirn.se/websocket", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "client", + "server", + "websocket" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + "issues": "https://github.com/sirn-se/websocket-php/issues", + "source": "https://github.com/sirn-se/websocket-php/tree/1.7.3" }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2024-05-31T13:43:32+00:00" }, { - "name": "pdepend/pdepend", - "version": "2.13.0", + "name": "rector/rector", + "version": "2.1.7", "source": { "type": "git", - "url": "https://github.com/pdepend/pdepend.git", - "reference": "31be7cd4f305f3f7b52af99c1cb13fc938d1cfad" + "url": "https://github.com/rectorphp/rector.git", + "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/31be7cd4f305f3f7b52af99c1cb13fc938d1cfad", - "reference": "31be7cd4f305f3f7b52af99c1cb13fc938d1cfad", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/c34cc07c4698f007a20dc5c99ff820089ae413ce", + "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce", "shasum": "" }, "require": { - "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5|^6.0", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0", - "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0" + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.18" }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0|^1.2.3", - "gregwar/rst": "^1.0", - "phpunit/phpunit": "^4.8.36|^5.7.27", - "squizlabs/php_codesniffer": "^2.0.0" + "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": [ - "src/bin/pdepend" + "bin/rector" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, "autoload": { - "psr-4": { - "PDepend\\": "src/main/php/PDepend" - } + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "homepage": "https://getrector.com/", + "keywords": [ + "automation", + "dev", + "migration", + "refactoring" ], - "description": "Official version of pdepend to be handled with Composer", "support": { - "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.13.0" + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/2.1.7" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", - "type": "tidelift" + "url": "https://github.com/tomasvotruba", + "type": "github" } ], - "time": "2023-02-28T20:56:15+00:00" + "time": "2025-09-10T11:13:58+00:00" }, { - "name": "phake/phake", - "version": "v4.4.0", + "name": "sebastian/cli-parser", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/phake/phake.git", - "reference": "5c8954791645d9b7fc027bf76822a221a5a4de8a" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phake/phake/zipball/5c8954791645d9b7fc027bf76822a221a5a4de8a", - "reference": "5c8954791645d9b7fc027bf76822a221a5a4de8a", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.4", - "php": "^7.1|^8.0", - "sebastian/comparator": "^1.1|^2.0|^3.0|^4.0|^5.0" + "php": ">=8.1" }, "require-dev": { - "doctrine/annotations": "^1.13", - "hamcrest/hamcrest-php": "1.1.*", - "phpunit/phpunit": "^6.5|^7.0|^8.0|^9.0|^10.0", - "psalm/phar": "^4.18" - }, - "suggest": { - "doctrine/annotations": "Allows mock annotations to use import statements for classes.", - "hamcrest/hamcrest-php": "Use Hamcrest matchers." + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-main": "2.0-dev" } }, "autoload": { - "files": [ - "src/Phake.php" - ], - "psr-4": { - "Phake\\": "src/Phake" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5551,52 +10478,50 @@ ], "authors": [ { - "name": "Mike Lively", - "email": "m@digitalsandwich.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "The Phake mock testing library", - "homepage": "https://phake.github.io", - "keywords": [ - "mock", - "phake", - "spy", - "stub", - "test-doubles", - "testing" - ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { - "docs": "https://phake.github.io/doc/", - "issues": "https://github.com/phake/phake/issues", - "source": "https://github.com/phake/phake/tree/v4.4.0" + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, - "time": "2023-02-10T20:32:41+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:12:49+00:00" }, { - "name": "phar-io/manifest", - "version": "2.0.3", + "name": "sebastian/code-unit", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -5609,47 +10534,52 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", - "role": "Developer" + "role": "lead" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" }, { - "name": "phar-io/version", - "version": "3.2.1", + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -5660,210 +10590,197 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "email": "sebastian@phpunit.de" } ], - "description": "Library for handling version information and constraints", + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, - "time": "2022-02-21T01:04:05+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" }, { - "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", + "name": "sebastian/comparator", + "version": "5.0.4", "source": { "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e8e53097718d2b53cfb2aa859b06a41abf58c62e", + "reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e", "shasum": "" }, "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" - }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^10.5" }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] }, - "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-or-later" + "BSD-3-Clause" ], "authors": [ { - "name": "Wim Godden", - "homepage": "https://github.com/wimg", - "role": "lead" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Contributors", - "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ - "compatibility", - "phpcs", - "standards" + "comparator", + "compare", + "equality" ], "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.4" }, - "time": "2019-12-27T09:44:58+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2025-09-07T05:25:07+00:00" }, { - "name": "phpmd/phpmd", - "version": "2.13.0", + "name": "sebastian/complexity", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/phpmd/phpmd.git", - "reference": "dad0228156856b3ad959992f9748514fa943f3e3" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/dad0228156856b3ad959992f9748514fa943f3e3", - "reference": "dad0228156856b3ad959992f9748514fa943f3e3", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { - "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", - "ext-xml": "*", - "pdepend/pdepend": "^2.12.1", - "php": ">=5.3.9" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "easy-doc/easy-doc": "0.0.0 || ^1.3.2", - "ext-json": "*", - "ext-simplexml": "*", - "gregwar/rst": "^1.0", - "mikey179/vfsstream": "^1.6.8", - "phpunit/phpunit": "^4.8.36 || ^5.7.27", - "squizlabs/php_codesniffer": "^2.0" + "phpunit/phpunit": "^10.0" }, - "bin": [ - "src/bin/phpmd" - ], "type": "library", - "autoload": { - "psr-0": { - "PHPMD\\": "src/main/php" + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Manuel Pichler", - "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" - }, - { - "name": "Marc Würth", - "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84", - "role": "Project Maintainer" - }, - { - "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", - "homepage": "https://phpmd.org/", - "keywords": [ - "mess detection", - "mess detector", - "pdepend", - "phpmd", - "pmd" - ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", "support": { - "irc": "irc://irc.freenode.org/phpmd", - "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.13.0" + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", - "type": "tidelift" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "time": "2022-09-10T08:44:15+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "7.0.15", + "name": "sebastian/diff", + "version": "5.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "819f92bba8b001d4363065928088de22f25a3a48" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/819f92bba8b001d4363065928088de22f25a3a48", - "reference": "819f92bba8b001d4363065928088de22f25a3a48", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": ">=7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.3 || ^4.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^8.2.2" - }, - "suggest": { - "ext-xdebug": "^2.7.2" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -5878,20 +10795,25 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "coverage", - "testing", - "xunit" + "diff", + "udiff", + "unidiff", + "unified diff" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.15" + "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" }, "funding": [ { @@ -5899,32 +10821,35 @@ "type": "github" } ], - "time": "2021-07-26T12:20:09+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "2.0.5", + "name": "sebastian/environment", + "version": "6.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5", - "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -5939,19 +10864,20 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ - "filesystem", - "iterator" + "Xdebug", + "environment", + "hhvm" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.5" + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -5959,26 +10885,36 @@ "type": "github" } ], - "time": "2021-12-02T12:42:26+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "sebastian/exporter", + "version": "5.1.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "9e7e86260de48e405ec3086bcb62e677ef192e7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/9e7e86260de48e405ec3086bcb62e677ef192e7f", + "reference": "9e7e86260de48e405ec3086bcb62e677ef192e7f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -5991,45 +10927,83 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "template" + "export", + "exporter" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.3" }, - "time": "2015-06-21T13:50:34+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-22T05:25:48+00:00" }, { - "name": "phpunit/php-timer", - "version": "2.1.3", + "name": "sebastian/global-state", + "version": "6.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", - "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "ext-dom": "*", + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -6044,18 +11018,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ - "timer" + "global state" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -6063,33 +11037,33 @@ "type": "github" } ], - "time": "2020-11-30T08:20:02+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "3.1.3", + "name": "sebastian/lines-of-code", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9c1da83261628cb24b6a6df371b6e312b3954768", - "reference": "9c1da83261628cb24b6a6df371b6e312b3954768", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.1" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -6104,17 +11078,16 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", - "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.3" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -6122,61 +11095,34 @@ "type": "github" } ], - "abandoned": true, - "time": "2021-07-26T12:15:06+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { - "name": "phpunit/phpunit", - "version": "8.5.33", + "name": "sebastian/object-enumerator", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e", - "reference": "7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.0", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.2", - "phpunit/php-code-coverage": "^7.0.12", - "phpunit/php-file-iterator": "^2.0.4", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.2", - "sebastian/comparator": "^3.0.5", - "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.3", - "sebastian/exporter": "^3.1.5", - "sebastian/global-state": "^3.0.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.3", - "sebastian/version": "^2.0.1" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0.0" + "require-dev": { + "phpunit/phpunit": "^10.0" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "8.5-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -6191,61 +11137,47 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.33" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" } ], - "time": "2023-02-27T13:04:50+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.2", + "name": "sebastian/object-reflector", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -6263,11 +11195,11 @@ "email": "sebastian@phpunit.de" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -6275,34 +11207,32 @@ "type": "github" } ], - "time": "2020-11-30T08:15:22+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { - "name": "sebastian/comparator", - "version": "3.0.5", + "name": "sebastian/recursion-context", + "version": "5.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", - "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", "shasum": "" }, "require": { - "php": ">=7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -6324,58 +11254,61 @@ "email": "whatthejeff@gmail.com" }, { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2022-09-14T12:31:48+00:00" + "time": "2025-08-10T07:50:56+00:00" }, { - "name": "sebastian/diff", - "version": "3.0.4", + "name": "sebastian/type", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/6296a0c086dd0117c1b78b059374d7fcbe7545ae", - "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -6390,24 +11323,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/3.0.4" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -6415,35 +11339,29 @@ "type": "github" } ], - "time": "2023-05-07T05:30:20+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { - "name": "sebastian/environment", - "version": "4.2.4", + "name": "sebastian/version", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", - "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5" - }, - "suggest": { - "ext-posix": "*" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -6458,19 +11376,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -6478,578 +11392,749 @@ "type": "github" } ], - "time": "2020-11-30T07:53:42+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { - "name": "sebastian/exporter", - "version": "3.1.5", + "name": "squizlabs/php_codesniffer", + "version": "3.13.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/73a9676f2833b9a7c36968f9d882589cd75511e6", - "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ad545ea9c1b7d270ce0fc9cbfb884161cd706119", + "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/recursion-context": "^3.0" + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "src/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" + "name": "Greg Sherwood", + "role": "Former lead" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Juliette Reinders Folmer", + "role": "Current lead" }, { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ - "export", - "exporter" + "phpcs", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.5" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCSStandards", "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2022-09-14T06:00:17+00:00" + "time": "2025-09-05T05:47:09+00:00" }, { - "name": "sebastian/global-state", - "version": "3.0.2", + "name": "symfony/browser-kit", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "de036ec91d55d2a9e0db2ba975b512cdb1c23921" + "url": "https://github.com/symfony/browser-kit.git", + "reference": "03cce39764429e07fbab9b989a1182a24578341d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/de036ec91d55d2a9e0db2ba975b512cdb1c23921", - "reference": "de036ec91d55d2a9e0db2ba975b512cdb1c23921", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/03cce39764429e07fbab9b989a1182a24578341d", + "reference": "03cce39764429e07fbab9b989a1182a24578341d", "shasum": "" }, "require": { - "php": ">=7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": ">=7.2.5", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^8.0" + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0" }, "suggest": { - "ext-uopz": "*" + "symfony/process": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], + "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.2" + "source": "https://github.com/symfony/browser-kit/tree/v5.4.45" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "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": "2022-02-10T06:55:38+00:00" + "time": "2024-10-22T13:05:35+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "3.0.4", + "name": "symfony/css-selector", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" + "url": "https://github.com/symfony/css-selector.git", + "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", - "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/4f7f3c35fba88146b56d0025d20ace3f3901f097", + "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097", "shasum": "" }, "require": { - "php": ">=7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + "source": "https://github.com/symfony/css-selector/tree/v5.4.45" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "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": "2020-11-30T07:40:27+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { - "name": "sebastian/object-reflector", - "version": "1.1.2", + "name": "symfony/debug-bundle", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "653c7629d036ef24ac5de54a157aecdc400d2570" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", - "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/653c7629d036ef24ac5de54a157aecdc400d2570", + "reference": "653c7629d036ef24ac5de54a157aecdc400d2570", "shasum": "" }, "require": { - "php": ">=7.0" + "ext-xml": "*", + "php": ">=7.2.5", + "symfony/http-kernel": "^4.4|^5.0|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/twig-bridge": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "conflict": { + "symfony/config": "<4.4", + "symfony/dependency-injection": "<5.2" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/web-profiler-bundle": "^4.4|^5.0|^6.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } + "suggest": { + "symfony/config": "For service container configuration", + "symfony/dependency-injection": "For using as a service from the container" }, + "type": "symfony-bundle", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "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": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + "source": "https://github.com/symfony/debug-bundle/tree/v5.4.45" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "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": "2020-11-30T07:37:18+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { - "name": "sebastian/recursion-context", - "version": "3.0.1", + "name": "symfony/dom-crawler", + "version": "v5.4.48", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "b57df76f4757a9a8dfbb57ba48d7780cc20776c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", - "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b57df76f4757a9a8dfbb57ba48d7780cc20776c6", + "reference": "b57df76f4757a9a8dfbb57ba48d7780cc20776c6", "shasum": "" }, "require": { - "php": ">=7.0" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "masterminds/html5": "<2.6" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "masterminds/html5": "^2.6", + "symfony/css-selector": "^4.4|^5.0|^6.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } + "suggest": { + "symfony/css-selector": "" }, + "type": "library", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "description": "Eases DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + "source": "https://github.com/symfony/dom-crawler/tree/v5.4.48" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "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": "2020-11-30T07:34:24+00:00" + "time": "2024-11-13T14:36:38+00:00" }, { - "name": "sebastian/resource-operations", - "version": "2.0.2", + "name": "symfony/http-client", + "version": "v5.4.49", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" + "url": "https://github.com/symfony/http-client.git", + "reference": "d77d8e212cde7b5c4a64142bf431522f19487c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", - "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "url": "https://api.github.com/repos/symfony/http-client/zipball/d77d8e212cde7b5c4a64142bf431522f19487c28", + "reference": "d77d8e212cde7b5c4a64142bf431522f19487c28", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2.5", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/http-client-contracts": "^2.5.4", + "symfony/polyfill-php73": "^1.11", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.0|^2|^3" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "2.4" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "php-http/message-factory": "^1.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^4.4.13|^5.1.5|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0" }, + "type": "library", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" + "source": "https://github.com/symfony/http-client/tree/v5.4.49" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "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": "2020-11-30T07:30:19+00:00" + "time": "2024-11-28T08:37:04+00:00" }, { - "name": "sebastian/type", - "version": "1.1.4", + "name": "symfony/http-client-contracts", + "version": "v2.5.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "48ef1d0a082885877b664332b9427662065a360c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", - "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/48ef1d0a082885877b664332b9427662065a360c", + "reference": "48ef1d0a082885877b664332b9427662065a360c", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.2.5" }, - "require-dev": { - "phpunit/phpunit": "^8.2" + "suggest": { + "symfony/http-client-implementation": "" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "2.5-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" + "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.5" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "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": "2020-11-30T07:25:11+00:00" + "time": "2024-11-28T08:37:04+00:00" }, { - "name": "sebastian/version", - "version": "2.0.1", + "name": "symfony/phpunit-bridge", + "version": "v7.3.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "7954e563ed14f924593169f6c4645d58d9d9ac77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/7954e563ed14f924593169f6c4645d58d9d9ac77", + "reference": "7954e563ed14f924593169f6c4645d58d9d9ac77", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.2.5" }, - "type": "library", + "conflict": { + "phpunit/phpunit": "<7.5|9.1.2" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/error-handler": "^5.4|^6.4|^7.0", + "symfony/polyfill-php81": "^1.27" + }, + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" + "thanks": { + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" } }, "autoload": { - "classmap": [ - "src/" + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/", + "/bin/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "Provides utilities for PHPUnit, especially user deprecation notices management", + "homepage": "https://symfony.com", + "keywords": [ + "testing" + ], "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.3" }, - "time": "2016-10-03T07:35:21+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-04T15:15:28+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "3.7.2", + "name": "symfony/proxy-manager-bridge", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + "url": "https://github.com/symfony/proxy-manager-bridge.git", + "reference": "e96cd37f3de0b75ff32f6b79c180ba77c4037eec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/e96cd37f3de0b75ff32f6b79c180ba77c4037eec", + "reference": "e96cd37f3de0b75ff32f6b79c180ba77c4037eec", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" + "friendsofphp/proxy-manager-lts": "^1.0.2", + "php": ">=7.2.5", + "symfony/dependency-injection": "^5.0|^6.0", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "symfony/config": "^4.4|^5.0|^6.0" }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\ProxyManager\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards", - "static analysis" - ], + "description": "Provides integration for ProxyManager with various Symfony components", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "source": "https://github.com/symfony/proxy-manager-bridge/tree/v5.4.45" }, - "time": "2023-02-22T23:07:41+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:11:13+00:00" }, { - "name": "symfony/phpunit-bridge", - "version": "v3.4.31", + "name": "symfony/web-profiler-bundle", + "version": "v5.4.48", "source": { "type": "git", - "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "028617b04ae19d99d89089626ac969d161244ebc" + "url": "https://github.com/symfony/web-profiler-bundle.git", + "reference": "4afb0399456b966be92410d2bbd6146cc3ce2174" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/028617b04ae19d99d89089626ac969d161244ebc", - "reference": "028617b04ae19d99d89089626ac969d161244ebc", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/4afb0399456b966be92410d2bbd6146cc3ce2174", + "reference": "4afb0399456b966be92410d2bbd6146cc3ce2174", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/framework-bundle": "^5.3|^6.0,<6.4", + "symfony/http-kernel": "^5.3|^6.0", + "symfony/polyfill-php80": "^1.16", + "symfony/routing": "^4.4|^5.0|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0", + "twig/twig": "^2.13|^3.0.4" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" - }, - "suggest": { - "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" + "symfony/dependency-injection": "<5.2", + "symfony/form": "<4.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<4.4" }, - "bin": [ - "bin/simple-phpunit" - ], - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - }, - "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" - } + "require-dev": { + "symfony/browser-kit": "^4.4|^5.0|^6.0", + "symfony/console": "^4.4|^5.0|^6.0", + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/stopwatch": "^4.4|^5.0|^6.0" }, + "type": "symfony-bundle", "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Bridge\\PhpUnit\\": "" + "Symfony\\Bundle\\WebProfilerBundle\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -7061,30 +12146,47 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony PHPUnit Bridge", + "description": "Provides a development tool that gives detailed information about the execution of any request", "homepage": "https://symfony.com", - "time": "2019-08-20T13:31:17+00:00" + "support": { + "source": "https://github.com/symfony/web-profiler-bundle/tree/v5.4.48" + }, + "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-11-19T09:26:40+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -7113,7 +12215,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -7121,26 +12223,27 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~7.2", + "php": "^8.2", "ext-dom": "*", "ext-json": "*", "ext-mbstring": "*", - "ext-openssl": "*" + "ext-openssl": "*", + "ext-pdo": "*" }, "platform-dev": { "ext-zlib": "*" }, "platform-overrides": { - "php": "7.2" + "php": "8.2" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/bootstrap.php b/config/bootstrap.php new file mode 100644 index 0000000000..55560fb830 --- /dev/null +++ b/config/bootstrap.php @@ -0,0 +1,23 @@ +=1.2) +if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) { + (new Dotenv(false))->populate($env); +} else { + // load all the .env files + (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env'); +} + +$_SERVER += $_ENV; +$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; +$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; +$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/config/bundles.php b/config/bundles.php new file mode 100644 index 0000000000..e74063e1a0 --- /dev/null +++ b/config/bundles.php @@ -0,0 +1,18 @@ + ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + OpenConext\MonitorBundle\OpenConextMonitorBundle::class => ['all' => true], + OpenConext\EngineBlockBundle\OpenConextEngineBlockBundle::class => ['all' => true], + Liip\FunctionalTestBundle\LiipFunctionalTestBundle::class => ['test' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true, 'ci' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'ci' => true], + OpenConext\EngineBlockFunctionalTestingBundle\OpenConextEngineBlockFunctionalTestingBundle::class => ['test' => true, 'ci' => true], + FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['ci' => true], +]; diff --git a/app/logs/.gitkeep b/config/packages/acc/.gitkeep similarity index 100% rename from app/logs/.gitkeep rename to config/packages/acc/.gitkeep diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml new file mode 100644 index 0000000000..0ecd1881d2 --- /dev/null +++ b/config/packages/cache.yaml @@ -0,0 +1,26 @@ +#framework: +# cache: + # Unique name of your app: used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The "app" cache stores to the filesystem by default. + # The data in this cache should persist between deploys. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: null +framework: + cache: + pools: + doctrine.system_cache_pool: + adapter: cache.system + doctrine.result_cache_pool: + adapter: cache.app diff --git a/app/config/config_ci.yml b/config/packages/ci/doctrine.yaml similarity index 84% rename from app/config/config_ci.yml rename to config/packages/ci/doctrine.yaml index 3997141ef5..26f9ce1f98 100644 --- a/app/config/config_ci.yml +++ b/config/packages/ci/doctrine.yaml @@ -1,7 +1,3 @@ -imports: - - { resource: functional_testing.yml } - - { resource: config_test.yml } - doctrine: dbal: default_connection: engineblock_test @@ -10,7 +6,7 @@ doctrine: driver: pdo_mysql # This must be PDO until all database interaction runs through doctrine server_version: '10.6.0-MariaDB' dbname: "%database.dbname%" - host: "mariadb" + host: "%database.test.host%" port: "%database.port%" user: "%database.user%" password: "%database.password%" @@ -18,7 +14,7 @@ doctrine: driver: pdo_mysql # This must be PDO until all database interaction runs through doctrine server_version: '10.6.0-MariaDB' dbname: "%database.test.dbname%" - host: "mariadb" + host: "%database.test.host%" port: "%database.test.port%" user: "%database.test.user%" password: "%database.test.password%" diff --git a/config/packages/ci/framework.yaml b/config/packages/ci/framework.yaml new file mode 100644 index 0000000000..f76cc2ef5a --- /dev/null +++ b/config/packages/ci/framework.yaml @@ -0,0 +1,2 @@ +framework: + test: true diff --git a/config/packages/ci/parameters.yaml b/config/packages/ci/parameters.yaml new file mode 100644 index 0000000000..50b103c88f --- /dev/null +++ b/config/packages/ci/parameters.yaml @@ -0,0 +1,9 @@ +# This file is auto-generated during the composer install +parameters: + router.request_context.host: engine.%domain% + router.request_context.scheme: https + idp_fixture_file: /tmp/eb-fixtures/db/idp.states.php.serialized + sp_fixture_file: /tmp/eb-fixtures/db/sp.states.php.serialized + stepup.sfo.override_engine_entityid: 'https://engine.dev.openconext.local/new/stepup/metadata' + # Disable for local tests + database.test.host: mariadb diff --git a/config/packages/ci/web_profiler.yaml b/config/packages/ci/web_profiler.yaml new file mode 100644 index 0000000000..102c6c65da --- /dev/null +++ b/config/packages/ci/web_profiler.yaml @@ -0,0 +1,14 @@ +# Only use dev toolbar locally as cypress test fail when adding toolbar, because of invalid HTML syntax +# +#web_profiler: +# toolbar: true +# intercept_redirects: false +# +#framework: +# profiler: { only_exceptions: false } +web_profiler: + toolbar: false + intercept_redirects: false + +framework: + profiler: { collect: false } diff --git a/config/packages/config.yaml b/config/packages/config.yaml new file mode 100644 index 0000000000..fa1fd7978b --- /dev/null +++ b/config/packages/config.yaml @@ -0,0 +1,10 @@ +# Put parameters here that don't need to change on each machine where the app is deployed +parameters: + # based on the hardcoded value in + # https://github.com/OpenConext/OpenConext-engineblock/blob/ + # 4102bffe58a9ecbce3c7c934e0aa8ece46efcf82/library/EngineBlock/Application/Bootstrapper.php#L242 + locale: en + container.autowiring.strict_mode: true + + # This value is used as cache-buster, replaced by the release script + asset_version: "#ASSET_VERSION#" diff --git a/config/packages/dev/config.yaml b/config/packages/dev/config.yaml new file mode 100644 index 0000000000..752ac3237d --- /dev/null +++ b/config/packages/dev/config.yaml @@ -0,0 +1,24 @@ +parameters: + # This value is used as cache-buster + asset_version: "dev" + global.site_notice.show: false + +framework: + translator: + enabled: true + fallbacks: [ "%locale%" ] + paths: + - '%kernel.project_dir%/languages' + - '%kernel.project_dir%/theme/base/translations' + - '%kernel.project_dir%/theme/%theme.name%/translations' + profiler: { only_exceptions: false } + +web_profiler: + toolbar: true + intercept_redirects: false + +twig: + cache: false + auto_reload: true + debug: true + strict_variables: false diff --git a/config/packages/dev/debug.yaml b/config/packages/dev/debug.yaml new file mode 100644 index 0000000000..26d4e53d2c --- /dev/null +++ b/config/packages/dev/debug.yaml @@ -0,0 +1,4 @@ +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/dev/monolog.yaml b/config/packages/dev/monolog.yaml new file mode 100644 index 0000000000..b02340fed5 --- /dev/null +++ b/config/packages/dev/monolog.yaml @@ -0,0 +1,25 @@ +monolog: + channels: ["engineblock", "authentication"] + handlers: + main: + type: fingers_crossed + activation_strategy: OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy + passthru_level: "%logger.fingers_crossed.passthru_level%" + handler: nested + level: debug + channels: ["!authentication"] + nested: + type: stream + level: debug + path: "%kernel.logs_dir%/application.log" + formatter: OpenConext\EngineBlockBundle\Monolog\Formatter\SyslogJsonFormatter + authentication: + type: stream + path: "%kernel.logs_dir%/authentication.log" + level: debug + channels: [authentication] + formatter: OpenConext\EngineBlockBundle\Monolog\Formatter\SyslogJsonFormatter + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine", "!console"] diff --git a/config/packages/dev/web_profiler.yaml b/config/packages/dev/web_profiler.yaml new file mode 100644 index 0000000000..e92166a7fd --- /dev/null +++ b/config/packages/dev/web_profiler.yaml @@ -0,0 +1,6 @@ +web_profiler: + toolbar: true + intercept_redirects: false + +framework: + profiler: { only_exceptions: false } diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml new file mode 100644 index 0000000000..57cbc24adf --- /dev/null +++ b/config/packages/doctrine.yaml @@ -0,0 +1,52 @@ +doctrine: + dbal: + + default_connection: engineblock + connections: + engineblock: + # schema_filter: ~^(?!group_|virtual_|service_provider_|saml_persistent_id|sso_provider_roles|log_logins|db_changelog|consent)~ + driver: pdo_mysql # This must be PDO until all database interaction runs through doctrine + dbname: "%database.dbname%" + host: "%database.host%" + port: "%database.port%" + user: "%database.user%" + password: "%database.password%" + charset: UTF8 + # when true, queries are logged to a 'doctrine' monolog channel + logging: '%kernel.debug%' + profiling: '%kernel.debug%' + server_version: '10.11.13-MariaDB' + mapping_types: + enum: string + types: + engineblock_collab_person_id: OpenConext\EngineBlockBundle\Doctrine\Type\CollabPersonIdType + engineblock_collab_person_uuid: OpenConext\EngineBlockBundle\Doctrine\Type\CollabPersonUuidType + engineblock_metadata_coins: OpenConext\EngineBlockBundle\Doctrine\Type\MetadataCoinType + engineblock_metadata_mdui: OpenConext\EngineBlockBundle\Doctrine\Type\MetadataMduiType + orm: + auto_generate_proxy_classes: "%kernel.debug%" + proxy_dir: '%kernel.cache_dir%/doctrine/orm/Proxies' + enable_lazy_ghost_objects: true + entity_managers: + engineblock: + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + connection: ~ + # Opt-in to new mapping driver mode as of Doctrine ORM 2.16, https://github.com/doctrine/orm/pull/10455 + report_fields_where_declared: true + mappings: + # An array of mappings, which may be a bundle name or something else + Authentication: + mapping: true + type: attribute + dir: "%kernel.project_dir%/src/OpenConext/EngineBlockBundle/Authentication" + prefix: OpenConext\EngineBlockBundle\Authentication + is_bundle: false + Metadata: + mapping: true + type: attribute + dir: "%kernel.project_dir%/src/OpenConext/EngineBlock/Metadata" + prefix: OpenConext\EngineBlock\Metadata + is_bundle: false + dql: + string_functions: + md5: OpenConext\EngineBlockBundle\Doctrine\DqlFunction\Md5 diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml new file mode 100644 index 0000000000..0c232efcbf --- /dev/null +++ b/config/packages/doctrine_migrations.yaml @@ -0,0 +1,6 @@ +doctrine_migrations: + migrations_paths: + OpenConext\EngineBlock\Doctrine\Migrations: '%kernel.project_dir%/migrations/DoctrineMigrations' + storage: + table_storage: + table_name: 'migration_versions' diff --git a/config/packages/engineblock_features.yaml b/config/packages/engineblock_features.yaml new file mode 100644 index 0000000000..467d8c1908 --- /dev/null +++ b/config/packages/engineblock_features.yaml @@ -0,0 +1,17 @@ +parameters: + custom_features: + api.metadata_push: "%feature_api_metadata_push%" + api.consent_listing: "%feature_api_consent_listing%" + api.consent_remove: "%feature_api_consent_remove%" + api.metadata_api: "%feature_api_metadata_api%" + api.deprovision: "%feature_api_deprovision%" + eb.encrypted_assertions: "%feature_eb_encrypted_assertions%" + eb.encrypted_assertions_require_outer_signature: "%feature_eb_encrypted_assertions_require_outer_signature%" + eb.run_all_manipulations_prior_to_consent: "%feature_run_all_manipulations_prior_to_consent%" + eb.block_user_on_violation: "%feature_block_user_on_violation%" + eb.enable_sso_notification: "%feature_enable_sso_notification%" + eb.feature_enable_consent: "%feature_enable_consent%" + eb.enable_sso_session_cookie: "%feature_enable_sso_session_cookie%" + eb.feature_enable_idp_initiated_flow: "%feature_enable_idp_initiated_flow%" + eb.stepup.sfo.override_engine_entityid: "%feature_stepup_sfo_override_engine_entityid%" + eb.stepup.send_user_attributes: "%feature_stepup_send_user_attributes%" diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml new file mode 100644 index 0000000000..118705b27f --- /dev/null +++ b/config/packages/framework.yaml @@ -0,0 +1,31 @@ +framework: + secret: '%env(APP_SECRET)%' + esi: false + translator: + fallbacks: [ "%locale%" ] + paths: + - '%kernel.project_dir%/languages' + - '%kernel.project_dir%/theme/base/translations' + - '%kernel.project_dir%/theme/%theme.name%/translations' + form: ~ + csrf_protection: ~ + validation: { enable_annotations: true } + default_locale: "%locale%" + trusted_hosts: ~ + + # 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: + # ID of the service used for session storage + # NULL means that Symfony uses PHP default session mechanism + handler_id: null + storage_factory_id: session.storage.factory.native + + fragments: false + http_method_override: true + assets: ~ + php_errors: + log: true + error_controller: 'Symfony\Component\HttpKernel\Controller\ErrorController::show' + router: + utf8: true diff --git a/config/packages/mailer.yaml b/config/packages/mailer.yaml new file mode 100644 index 0000000000..ada8111f85 --- /dev/null +++ b/config/packages/mailer.yaml @@ -0,0 +1,3 @@ +framework: + mailer: + dsn: '%mailer_dsn%' diff --git a/config/packages/monolog.yaml b/config/packages/monolog.yaml new file mode 100644 index 0000000000..35ac3149bb --- /dev/null +++ b/config/packages/monolog.yaml @@ -0,0 +1,25 @@ +monolog: + channels: ["engineblock", "authentication"] + handlers: + main: + type: fingers_crossed + activation_strategy: OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy + passthru_level: "%logger.fingers_crossed.passthru_level%" + handler: nested + level: info + channels: ["!authentication"] + nested: + type: stream + level: info + path: "%kernel.logs_dir%/application.log" + formatter: OpenConext\EngineBlockBundle\Monolog\Formatter\SyslogJsonFormatter + authentication: + type: stream + path: "%kernel.logs_dir%/authentication.log" + level: info + channels: [authentication] + formatter: OpenConext\EngineBlockBundle\Monolog\Formatter\SyslogJsonFormatter + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine", "!console"] diff --git a/app/config/parameters.yml.dist b/config/packages/parameters.yml.dist similarity index 96% rename from app/config/parameters.yml.dist rename to config/packages/parameters.yml.dist index 0847a0d2af..f8fe5741e8 100644 --- a/app/config/parameters.yml.dist +++ b/config/packages/parameters.yml.dist @@ -2,11 +2,6 @@ parameters: ########################################################################################## ## GLOBAL SETTINGS ########################################################################################## - ## This is a string that should be unique to your application and it's commonly used to add more - ## entropy to security related operations. Its value should be a series of characters, numbers and - ## symbols chosen randomly and the recommended length is around 32 characters. - secret: secret - ## Note: due to legacy reasons, hostname must be left empty (hostname ## from the Host header will be used) or set to match the domain ## setting. For example: @@ -36,7 +31,7 @@ parameters: ## * How attributes are displayed in Profile and Consent ## * How attributes are Normalized and Denormalized ## * How attributes are validated - attribute_definition_file_path: %kernel.project_dir%/application/configs/attributes.json + attribute_definition_file_path: '%kernel.project_dir%/application/configs/attributes.json' ## The Signing / Encryption keys used for the SAML2 authentication and metadata ## When EngineBlock signs responses (when it acts as an Idp) @@ -67,7 +62,7 @@ parameters: php_settings: memory_limit: 256M display_errors: '1' - error_reporting: '6135' + error_reporting: '30719' date.timezone: Europe/Amsterdam sendmail_from: 'OpenConext EngineBlock ' @@ -209,12 +204,8 @@ parameters: name: 'OpenConext Admin' subject: 'IdP debug info from %%1$s' - ## Swiftmailer configuration - mailer_transport: 'smtp' - mailer_host: 'localhost' - mailer_port: '25' - mailer_user: '' - mailer_password: '' + ## Symfony Mailer configuration + mailer_dsn: 'smtp://user:password@localhost:25' ########################################################################################## ## FEATURE SETTINGS diff --git a/config/packages/prod/.gitkeep b/config/packages/prod/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/config/security.yml b/config/packages/security.yaml similarity index 86% rename from app/config/security.yml rename to config/packages/security.yaml index dc4dad1b20..3dfe8a212d 100644 --- a/app/config/security.yml +++ b/config/packages/security.yaml @@ -13,7 +13,7 @@ security: password: "%api.users.deprovision.password%" roles: 'ROLE_API_USER_DEPROVISION' - encoders: + password_hashers: Symfony\Component\Security\Core\User\User: plaintext firewalls: @@ -29,10 +29,11 @@ security: api: host: ^engine-api\..+ http_basic: ~ - entry_point: engineblock.security.http_basic_entry_point + entry_point: OpenConext\EngineBlockBundle\Security\Http\EntryPoint\JsonBasicAuthenticationEntryPoint stateless: true pattern: ^/.+ main: - anonymous: ~ stateless: true + + enable_authenticator_manager: true diff --git a/config/packages/sensio_framework_extra.yaml b/config/packages/sensio_framework_extra.yaml new file mode 100644 index 0000000000..1821ccc079 --- /dev/null +++ b/config/packages/sensio_framework_extra.yaml @@ -0,0 +1,3 @@ +sensio_framework_extra: + router: + annotations: false diff --git a/config/packages/test/config.yaml b/config/packages/test/config.yaml new file mode 100644 index 0000000000..76b7fb3ad2 --- /dev/null +++ b/config/packages/test/config.yaml @@ -0,0 +1,30 @@ +# Test service DI container overwrites (used for test and ci envs) +services: + engineblock.features: + class: OpenConext\EngineBlockBundle\Configuration\TestFeatureConfiguration + public: true + + engineblock.twig.extension.global_site_notice: + class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\FunctionalTestingGlobalSiteNotice + arguments: + - "@request_stack" + - "%global.site_notice.allowed.tags%" + tags: + - { name: 'twig.extension' } + +web_profiler: + toolbar: false + intercept_redirects: false + + +security: + providers: + in_memory: + memory: + users: + no_roles: + password: no_roles + roles: [] + + + diff --git a/config/packages/test/doctrine.yaml b/config/packages/test/doctrine.yaml new file mode 100644 index 0000000000..448b48047c --- /dev/null +++ b/config/packages/test/doctrine.yaml @@ -0,0 +1,15 @@ +doctrine: + dbal: + default_connection: engineblock_test + connections: + engineblock_test: + driver: pdo_mysql # This must be PDO until all database interaction runs through doctrine + server_version: '10.6.0-MariaDB' + dbname: "%database.test.dbname%" + host: "%database.test.host%" + port: "%database.test.port%" + user: "%database.test.user%" + password: "%database.test.password%" +# +#parameters: +# database.test.host: 127.0.0.1 diff --git a/config/packages/test/framework.yaml b/config/packages/test/framework.yaml new file mode 100644 index 0000000000..ab94566e8a --- /dev/null +++ b/config/packages/test/framework.yaml @@ -0,0 +1,16 @@ +framework: + test: ~ + translator: + fallbacks: ["%locale%"] + paths: + - '%kernel.project_dir%/languages' + - '%kernel.project_dir%/theme/base/translations' + - '%kernel.project_dir%/theme/%theme.name%/translations' + - '%kernel.project_dir%/src/OpenConext/EngineBlockFunctionalTestingBundle/Resources/languages' + session: + storage_factory_id: session.storage.factory.mock_file + name: MOCKSESSION + router: + strict_requirements: true + profiler: + collect: false diff --git a/config/packages/test/monolog.yaml b/config/packages/test/monolog.yaml new file mode 100644 index 0000000000..0866a82e37 --- /dev/null +++ b/config/packages/test/monolog.yaml @@ -0,0 +1,14 @@ +# override the logging settings so that we can log to readable files on github actions +monolog: + channels: ["%logger.channel%", "authentication"] + handlers: + main: + type: fingers_crossed + activation_strategy: OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy + passthru_level: "%logger.fingers_crossed.passthru_level%" + handler: nested + channels: ['!event'] + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: DEBUG diff --git a/config/packages/test/twig.yaml b/config/packages/test/twig.yaml new file mode 100644 index 0000000000..8c6e0b401d --- /dev/null +++ b/config/packages/test/twig.yaml @@ -0,0 +1,2 @@ +twig: + strict_variables: true diff --git a/config/packages/test/web_profiler.yaml b/config/packages/test/web_profiler.yaml new file mode 100644 index 0000000000..03752de213 --- /dev/null +++ b/config/packages/test/web_profiler.yaml @@ -0,0 +1,6 @@ +web_profiler: + toolbar: false + intercept_redirects: false + +framework: + profiler: { collect: false } diff --git a/config/packages/testing/.gitkeep b/config/packages/testing/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml new file mode 100644 index 0000000000..f103727c1c --- /dev/null +++ b/config/packages/twig.yaml @@ -0,0 +1,19 @@ +# Twig Configuration +twig: + exception_controller: null + debug: '%kernel.debug%' + strict_variables: '%kernel.debug%' + paths: + "%kernel.project_dir%/theme/%theme.name%/templates/modules": theme + "%kernel.project_dir%/theme/%theme.name%/templates/layouts": themeLayouts + "%kernel.project_dir%/theme/%theme.name%/images": images + "%kernel.project_dir%/theme/base/templates/modules": theme + "%kernel.project_dir%/theme/base/templates/layouts": themeLayouts + "%kernel.project_dir%/theme/base/images": images + globals: + assetsVersion: "%asset_version%" + defaultTitle: "%view_default_title%" + defaultHeader: "%view_default_header%" + defaultLogo: "%view_default_logo%" + envName: "%env_name%" + envRibbonColor: "%env_ribbon_color%" diff --git a/config/packages/validator.yaml b/config/packages/validator.yaml new file mode 100644 index 0000000000..7b2a2a1c77 --- /dev/null +++ b/config/packages/validator.yaml @@ -0,0 +1,8 @@ +#framework: +# validation: +# email_validation_mode: html5 +# +# # Enables validator auto-mapping support. +# # For instance, basic validation constraints will be inferred from Doctrine's metadata. +# #auto_mapping: +# # App\Entity\: [] diff --git a/config/preload.php b/config/preload.php new file mode 100644 index 0000000000..064bdcd6a9 --- /dev/null +++ b/config/preload.php @@ -0,0 +1,9 @@ + - DocumentRoot /var/www/html/web - + DocumentRoot /var/www/html/public + Require all granted Options -MultiViews RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ app.php [QSA,L] + RewriteRule ^(.*)$ index.php [QSA,L] Require all granted Header always set X-Content-Type-Options "nosniff" - SetEnv APP_ENV=ci - SetEnv SYMFONY_ENV=ci - SetEnv ENGINEBLOCK_ENV=ci SetEnv HTTPS on diff --git a/docker/conf/engine.conf b/docker/conf/engine.conf index 31bd65f392..9e8111c8b5 100644 --- a/docker/conf/engine.conf +++ b/docker/conf/engine.conf @@ -1,14 +1,14 @@ -DocumentRoot /var/www/html/web +DocumentRoot /var/www/html/public ServerName engine SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 - + Require all granted Options -MultiViews RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ app.php [QSA,L] + RewriteRule ^(.*)$ index.php [QSA,L] Header always set X-Content-Type-Options "nosniff" diff --git a/docker/docker-compose-php82.yml b/docker/docker-compose-php82.yml index e5457a8d54..8345d58e22 100644 --- a/docker/docker-compose-php82.yml +++ b/docker/docker-compose-php82.yml @@ -1,5 +1,3 @@ -version: '2.4' - services: engine.dev.openconext.local: build: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 93270ca474..5c8f9bd3b8 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,9 +1,7 @@ -version: '2.4' - services: mariadb: - image: mariadb:10.2 + image: mariadb:10.6 restart: always container_name: eb-db-test environment: @@ -26,6 +24,9 @@ services: # override this in a dedicated dockerfile per php version # dockerfile: docker/ci/Dockerfile container_name: eb-phpfpm +# Local debugging +# ports: +# - 443:443 volumes: - ../:/var/www/html - ../ci/qa-config/files/engine.dev.openconext.local.crt:/config/engine/engineblock.crt @@ -35,30 +36,29 @@ services: condition: service_healthy environment: APP_ENV: ci - SYMFONY_ENV: ci + APP_SECRET: secret + APP_DEBUG: false - selenium.dev.openconext.local: - image: selenium/standalone-chrome:2.53.1 - container_name: eb-selenium - user: "${UID}:${GID}" + chrome.dev.openconext.local: + image: alpeware/chrome-headless-trunk + ports: + - 9222:9222 environment: - START_XVFB: "false" + - CHROME_OPTS=--ignore-certificate-errors --window-size=1920,1080 --ignore-ssl-errors volumes: - - /dev/shm:/dev/shm - healthcheck: - test: ["CMD", "/opt/bin/check-grid.sh:", "--host", "0.0.0.0", "--port", "4444"] - timeout: 30s - retries: 5 - interval: 15s + - /tmp/chromedata/:/data +# Remove commands for local X11 debugging cypress: image: "cypress/included:13.1.0" environment: - CYPRESS_baseUrl=https://engine.dev.openconext.local - working_dir: /e2e +# - DISPLAY=${DISPLAY} + working_dir: /e2e/ entrypoint: cypress open --project . volumes: - - ../tests:/e2e +# - /tmp/.X11-unix:/tmp/.X11-unix + - ../tests/e2e:/e2e - ../theme:/theme volumes: diff --git a/docs/logging.md b/docs/logging.md index 3096c279d1..435144b1f0 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -18,14 +18,14 @@ monolog: type: fingers_crossed activation_strategy: engineblock.logger.manual_or_error_activation_strategy passthru_level: "%logger.fingers_crossed.passthru_level%" - channels: [!authentication] + channels: ["!authentication"] handler: nested authentication: type: syslog ident: EBAUTH facility: user level: INFO - channels: [authentication] + channels: ["authentication"] formatter: engineblock.logger.formatter.syslog_json nested: type: syslog @@ -34,4 +34,4 @@ monolog: console: type: console process_psr_3_messages: false - channels: [!event, !doctrine, !console] + channels: ["!event", "!doctrine", "!console"] diff --git a/docs/php_testing.md b/docs/php_testing.md index a9ac9a721f..efc2df7b9e 100644 --- a/docs/php_testing.md +++ b/docs/php_testing.md @@ -35,6 +35,21 @@ Some aids in working with these tests: 1. When you want to try the test in your own browser: Echo the `$ssoStartLocation` and stop execution in `MockSpContext::iTriggerTheLoginEitherAtOrUnsolicitedAtEb`. Run the test and open the link in your own browser. Ensure you run EngineBlock in test environment in order to use the test fixtures. 2. Xdebug Step debugging: Add the `Xdebug step debugging is enabled in the browser` step definition to your test to let Mink set the debug cookie in the browser. Enabling you to listen for incoming debug requests. 3. WIP tests: add the `@WIP` or `@SKIP` annotations to any scenario to flag it a WIP, or skip it altogether. When calling Behat from CLI, be sure to only run the `wip` suite. +4. To enable step debugging in web requests triggered through behat tests, enable xdebug by default: +```bash +echo "xdebug.start_with_request=yes" | tee -a /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +apachectl graceful +``` + +### Showing deprecation notices triggered during behat: +In order to see deprecation notices generated when running the test suite, add these lines to te top of: `\EngineBlock_Application_ErrorHandler::error` +```php +if($errorNumber === E_DEPRECATED || $errorNumber === E_USER_DEPRECATED){ + file_put_contents(__DIR__ . '/../../../var/log/deprecations.log', $errorMessage . '|' . $errorFile . ':' . $errorLine . PHP_EOL, FILE_APPEND); + return false; +} +``` + ## Quality assurance The different QA tooling we know and love in other OpenConext projects are also included in EngineBlock. Most can be run using one of the ant build targets. diff --git a/library/EngineBlock/Application/Bootstrapper.php b/library/EngineBlock/Application/Bootstrapper.php index 21b5e03b9a..ea70f9c89d 100644 --- a/library/EngineBlock/Application/Bootstrapper.php +++ b/library/EngineBlock/Application/Bootstrapper.php @@ -87,7 +87,7 @@ protected function _bootstrapHttpCommunication() $configuredHostname = $this->_application->getDiContainer()->getHostname(); if (empty($configuredHostname)) { throw new RuntimeException( - "The 'hostname' parameters.yml setting is required" + "The 'hostname' parameters.yaml setting is required" ); } $httpRequest->setHostName($configuredHostname); diff --git a/library/EngineBlock/Application/DiContainer.php b/library/EngineBlock/Application/DiContainer.php index d2fc9f0252..b4ded1095f 100644 --- a/library/EngineBlock/Application/DiContainer.php +++ b/library/EngineBlock/Application/DiContainer.php @@ -27,8 +27,10 @@ use OpenConext\EngineBlock\Stepup\StepupGatewayCallOutHelper; use OpenConext\EngineBlock\Validator\AllowedSchemeValidator; use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; +use Symfony\Component\Mailer\MailerInterface; +use Twig\Environment; -class EngineBlock_Application_DiContainer extends Pimple +class EngineBlock_Application_DiContainer extends \Pimple\Container { const ATTRIBUTE_METADATA = 'attributeMetadata'; const ATTRIBUTE_DEFINITIONS_DENORMALIZED = 'attributeDefinitionsDenormalized'; @@ -69,7 +71,7 @@ public function getPhpSettings() */ public function getAuthenticationLogger() { - return $this->container->get('engineblock.bridge.authentication_logger_adapter'); + return $this->container->get(\OpenConext\EngineBlockBridge\Logger\AuthenticationLoggerAdapter::class); } /** @@ -83,7 +85,7 @@ public function getSymfonyRequest() /** * @return EngineBlock_Corto_XmlToArray */ - public function getXmlConverter() + public function getXmlConverter(): EngineBlock_Corto_XmlToArray { return $this->container->get('engineblock.compat.xml_converter'); } @@ -91,7 +93,7 @@ public function getXmlConverter() /** * @return EngineBlock_Corto_Filter_Command_Factory */ - public function getFilterCommandFactory() + public function getFilterCommandFactory(): EngineBlock_Corto_Filter_Command_Factory { return $this->container->get('engineblock.compat.corto_filter_command_factory'); } @@ -99,7 +101,7 @@ public function getFilterCommandFactory() /** * @return EngineBlock_Database_ConnectionFactory */ - public function getDatabaseConnectionFactory() + public function getDatabaseConnectionFactory(): EngineBlock_Database_ConnectionFactory { return $this->container->get('engineblock.compat.database_connection_factory'); } @@ -107,7 +109,7 @@ public function getDatabaseConnectionFactory() /** * @return EngineBlock_Corto_Model_Consent_Factory */ - public function getConsentFactory() + public function getConsentFactory(): EngineBlock_Corto_Model_Consent_Factory { return $this->container->get('engineblock.compat.corto_model_consent_factory'); } @@ -117,7 +119,7 @@ public function getConsentFactory() */ public function getAttributeAggregationClient() { - return $this->container->get('engineblock.attribute_aggregation.client'); + return $this->container->get(\OpenConext\EngineBlockBundle\AttributeAggregation\AttributeAggregationClient::class); } /** @@ -125,7 +127,7 @@ public function getAttributeAggregationClient() */ public function getMetadataRepository() { - return $this->container->get('engineblock.metadata.repository.cached_doctrine'); + return $this->container->get(\OpenConext\EngineBlock\Metadata\MetadataRepository\CachedDoctrineMetadataRepository::class); } /** @@ -133,7 +135,7 @@ public function getMetadataRepository() */ public function getUserDirectory() { - return $this->container->get('engineblock.bridge.authentication.user_directory'); + return $this->container->get(\OpenConext\EngineBlockBridge\Authentication\Repository\UserDirectoryAdapter::class); } /** @@ -141,7 +143,7 @@ public function getUserDirectory() */ public function getFeatureConfiguration() { - return $this->container->get('engineblock.features'); + return $this->container->get(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class); } /** @@ -149,7 +151,7 @@ public function getFeatureConfiguration() */ public function getAuthenticationLoopGuard() { - return $this->container->get('engineblock.authentication.authentication_loop_guard'); + return $this->container->get(\OpenConext\EngineBlockBundle\Authentication\AuthenticationLoopGuard::class); } /** @@ -157,7 +159,7 @@ public function getAuthenticationLoopGuard() */ public function getConsentService() { - return $this->container->get('engineblock.service.consent'); + return $this->container->get(\OpenConext\EngineBlock\Service\ConsentService::class); } /** @@ -165,7 +167,7 @@ public function getConsentService() */ public function getTimeProvider() { - return $this->container->get('engineblock.service.time_provider'); + return $this->container->get(\OpenConext\EngineBlock\Service\TimeProvider\TimeProvider::class); } /** @@ -279,15 +281,16 @@ public function getRememberChoice() */ public function getSession() { - return $this->container->get('session'); + $requestStack = $this->container->get('request_stack'); + + assert($requestStack instanceof \Symfony\Component\HttpFoundation\RequestStack); + + return $requestStack->getSession(); } - /** - * @return Swift_Mailer - */ - public function getMailer() + public function getMailer(): MailerInterface { - return $this->container->get('mailer'); + return $this->container->get('symfony.mailer'); } /** @@ -308,7 +311,7 @@ protected function getSymfonyContainer() public function getPdpClient() { - return $this->container->get('engineblock.pdp.pdp_client'); + return $this->container->get(\OpenConext\EngineBlockBundle\Pdp\PdpClient::class); } public function getPdpClientId() @@ -326,11 +329,11 @@ public function getFunctionalTestingPdpClient() */ public function getLocaleProvider() { - return $this->container->get('engineblock.locale_provider'); + return $this->container->get(\OpenConext\EngineBlockBundle\Localization\LocaleProvider::class); } /** - * @return \Symfony\Component\Translation\TranslatorInterface + * @return \Symfony\Contracts\Translation\TranslatorInterface */ public function getTranslator() { @@ -342,7 +345,7 @@ public function getTranslator() */ public function getUrlProvider() { - return $this->container->get('engineblock.url_provider'); + return $this->container->get(\OpenConext\EngineBlockBundle\Url\UrlProvider::class); } /** @@ -374,7 +377,7 @@ public function getStepupServiceProvider(EngineBlock_Corto_ProxyServer $server) */ public function getStepupGatewayCallOutHelper() { - return $this->container->get('engineblock.service.stepup.gateway_callout_helper'); + return $this->container->get(\OpenConext\EngineBlock\Stepup\StepupGatewayCallOutHelper::class); } @@ -383,7 +386,7 @@ public function getStepupGatewayCallOutHelper() */ public function getServiceProviderFactory() { - return $this->container->get('engineblock.factory.service_provider_factory'); + return $this->container->get(\OpenConext\EngineBlock\Metadata\Factory\Factory\ServiceProviderFactory::class); } /** @@ -391,7 +394,7 @@ public function getServiceProviderFactory() */ public function getLoaRepository() { - return $this->container->get('engineblock.configuration.stepup.loa_repository'); + return $this->container->get(\OpenConext\EngineBlock\Metadata\LoaRepository::class); } /** @@ -403,7 +406,7 @@ public function getEncryptionKeysConfiguration() } /** - * @return Twig_Environment + * @return Environment */ public function getTwigEnvironment() { @@ -431,7 +434,7 @@ public function getForbiddenSignatureMethods() */ public function getAcsLocationSchemeValidator() { - return $this->container->get('engineblock.validator.allowed_scheme_validator'); + return $this->container->get(\OpenConext\EngineBlock\Validator\AllowedSchemeValidator::class); } /** @@ -452,7 +455,7 @@ public function isConsentStoreValuesActive() public function getAuthenticationStateHelper() { - return $this->container->get('engineblock.service.authentication_state_helper'); + return $this->container->get(\OpenConext\EngineBlock\Service\AuthenticationStateHelper::class); } /** @@ -460,7 +463,7 @@ public function getAuthenticationStateHelper() */ public function getProcessingStateHelper() { - return $this->container->get('engineblock.service.processing_state_helper'); + return $this->container->get(\OpenConext\EngineBlock\Service\ProcessingStateHelper::class); } /** @@ -468,12 +471,12 @@ public function getProcessingStateHelper() */ public function getDiscoverySelectionService() { - return $this->container->get('engineblock.service.discovery_selection_service'); + return $this->container->get(\OpenConext\EngineBlockBundle\Service\DiscoverySelectionService::class); } public function getMfaHelper(): MfaHelperInterface { - return $this->container->get('engineblock.service.mfa_helper'); + return $this->container->get(\OpenConext\EngineBlock\Service\MfaHelper::class); } /** @@ -535,7 +538,7 @@ public function getAuthnContextClassRefBlacklistRegex() /** @return \OpenConext\EngineBlock\Stepup\StepupEndpoint $stepupEndpoint */ protected function getStepupEndpoint() { - return $this->container->get('engineblock.configuration.stepup.endpoint'); + return $this->container->get(\OpenConext\EngineBlock\Stepup\StepupEndpoint::class); } /** @return string */ @@ -560,7 +563,7 @@ public function getCookieDomain() */ public function getCookieService() { - return $this->container->get('engineblock.service.cookie'); + return $this->container->get(\OpenConext\EngineBlock\Service\CookieService::class); } /** @@ -568,7 +571,7 @@ public function getCookieService() */ public function getSsoSessionService() { - return $this->container->get('engineblock.service.sso_session'); + return $this->container->get(\OpenConext\EngineBlock\Service\SsoSessionService::class); } /** @@ -576,7 +579,7 @@ public function getSsoSessionService() */ public function getSsoNotificationService() { - return $this->container->get('engineblock.service.sso_notification'); + return $this->container->get(\OpenConext\EngineBlock\Service\SsoNotificationService::class); } /** diff --git a/library/EngineBlock/Application/ErrorHandler.php b/library/EngineBlock/Application/ErrorHandler.php index 83c0be8c3b..d33eb4cdbd 100644 --- a/library/EngineBlock/Application/ErrorHandler.php +++ b/library/EngineBlock/Application/ErrorHandler.php @@ -62,6 +62,7 @@ public function exception(Throwable $e) foreach ($this->_exitHandlers as $exitHandler) { $exitHandler($e); } + throw $e; $this->_application->reportError($e); diff --git a/library/EngineBlock/Application/TestDiContainer.php b/library/EngineBlock/Application/TestDiContainer.php index 39246a54b9..a2957d1427 100644 --- a/library/EngineBlock/Application/TestDiContainer.php +++ b/library/EngineBlock/Application/TestDiContainer.php @@ -29,17 +29,17 @@ class EngineBlock_Application_TestDiContainer extends EngineBlock_Application_Di */ private $pdpClient; - public function getXmlConverter() + public function getXmlConverter(): EngineBlock_Corto_XmlToArray { return Phake::mock('EngineBlock_Corto_XmlToArray'); } - public function getFilterCommandFactory() + public function getFilterCommandFactory(): EngineBlock_Corto_Filter_Command_Factory { return Phake::mock('EngineBlock_Corto_Filter_Command_Factory'); } - public function getDatabaseConnectionFactory() + public function getDatabaseConnectionFactory(): EngineBlock_Database_ConnectionFactory { return Phake::mock('EngineBlock_Database_ConnectionFactory'); } @@ -54,7 +54,7 @@ public function setPdpClient(PdpClientInterface $pdpClient) $this->pdpClient = $pdpClient; } - public function getConsentFactory() + public function getConsentFactory(): EngineBlock_Corto_Model_Consent_Factory { $consentFactoryMock = Phake::mock('EngineBlock_Corto_Model_Consent_Factory'); @@ -72,7 +72,7 @@ public function getAttributeMetadata() { // returns a realistic representation of the attribute metadata $definitions = json_decode(file_get_contents(__DIR__ . '/../../../tests/resources/config/attributes-fixture.json'), true); - return new EngineBlock_Attributes_Metadata($definitions, Phake::mock('\Psr\Log\LoggerInterface')); + return new EngineBlock_Attributes_Metadata($definitions, Phake::mock(\Psr\Log\LoggerInterface::class)); } /** @@ -89,7 +89,7 @@ public function getEncryptionKeysConfiguration() return [ 'default' => [ - 'publicFile' => '/config/engine/engineblock.crt', + 'publicFile' => $basePath . '/ci/qa-config/files/engineblock.crt', 'privateFile' => $basePath . '/ci/qa-config/files/engineblock.pem', ], ]; diff --git a/library/EngineBlock/ApplicationSingleton.php b/library/EngineBlock/ApplicationSingleton.php index 06dc87a4e2..1c4055ee44 100644 --- a/library/EngineBlock/ApplicationSingleton.php +++ b/library/EngineBlock/ApplicationSingleton.php @@ -128,7 +128,7 @@ public static function getLog() */ public function flushLog($reason) { - $logger = $this->getLog(); + $logger = static::getLog(); if ($this->_activationStrategy) { $this->_activationStrategy->activate(); diff --git a/library/EngineBlock/Arp/AttributeReleasePolicyEnforcer.php b/library/EngineBlock/Arp/AttributeReleasePolicyEnforcer.php index 619dea9f25..11556f2151 100644 --- a/library/EngineBlock/Arp/AttributeReleasePolicyEnforcer.php +++ b/library/EngineBlock/Arp/AttributeReleasePolicyEnforcer.php @@ -20,7 +20,7 @@ class EngineBlock_Arp_AttributeReleasePolicyEnforcer { - public function enforceArp(AttributeReleasePolicy $arp = null, $responseAttributes, $showSources = false) + public function enforceArp($responseAttributes, AttributeReleasePolicy $arp = null, $showSources = false) { if (!$arp) { if ($showSources) { diff --git a/library/EngineBlock/Corto/Exception/HasFeedbackInfoInterface.php b/library/EngineBlock/Corto/Exception/HasFeedbackInfoInterface.php index fac6c02b95..58afee759d 100644 --- a/library/EngineBlock/Corto/Exception/HasFeedbackInfoInterface.php +++ b/library/EngineBlock/Corto/Exception/HasFeedbackInfoInterface.php @@ -21,5 +21,5 @@ interface EngineBlock_Corto_Exception_HasFeedbackInfoInterface /** * @return array */ - public function getFeedbackInfo(); + public function getFeedbackInfo(): array; } diff --git a/library/EngineBlock/Corto/Exception/InvalidAttributeValue.php b/library/EngineBlock/Corto/Exception/InvalidAttributeValue.php index 4bdc5cda9b..fea0992d0f 100644 --- a/library/EngineBlock/Corto/Exception/InvalidAttributeValue.php +++ b/library/EngineBlock/Corto/Exception/InvalidAttributeValue.php @@ -45,7 +45,7 @@ public function getAttributeValue() /** * @return array */ - public function getFeedbackInfo() + public function getFeedbackInfo(): array { return [ 'attributeName' => $this->attributeName, diff --git a/library/EngineBlock/Corto/Exception/InvalidStepupCalloutResponse.php b/library/EngineBlock/Corto/Exception/InvalidStepupCalloutResponse.php index 5587d15d06..18692e8740 100644 --- a/library/EngineBlock/Corto/Exception/InvalidStepupCalloutResponse.php +++ b/library/EngineBlock/Corto/Exception/InvalidStepupCalloutResponse.php @@ -32,7 +32,7 @@ public function __construct($message, EngineBlock_Corto_Exception_ReceivedErrorS /** * @return array */ - public function getFeedbackInfo() + public function getFeedbackInfo(): array { return $this->feedback; } diff --git a/library/EngineBlock/Corto/Exception/InvalidStepupLoaLevel.php b/library/EngineBlock/Corto/Exception/InvalidStepupLoaLevel.php index 424e8ee36b..f99c8fe156 100644 --- a/library/EngineBlock/Corto/Exception/InvalidStepupLoaLevel.php +++ b/library/EngineBlock/Corto/Exception/InvalidStepupLoaLevel.php @@ -32,7 +32,7 @@ public function __construct($message, EngineBlock_Corto_Exception_ReceivedErrorS /** * @return array */ - public function getFeedbackInfo() + public function getFeedbackInfo(): array { return $this->feedback; } diff --git a/library/EngineBlock/Corto/Exception/ReceivedErrorStatusCode.php b/library/EngineBlock/Corto/Exception/ReceivedErrorStatusCode.php index 7e1a4baec0..795ff34d17 100644 --- a/library/EngineBlock/Corto/Exception/ReceivedErrorStatusCode.php +++ b/library/EngineBlock/Corto/Exception/ReceivedErrorStatusCode.php @@ -44,7 +44,7 @@ public function setResponse(EngineBlock_Saml2_ResponseAnnotationDecorator $respo $this->response = $response; } - public function getFeedbackInfo() + public function getFeedbackInfo(): array { return $this->feedbackInfo; } diff --git a/library/EngineBlock/Corto/Exception/UserCancelledStepupCallout.php b/library/EngineBlock/Corto/Exception/UserCancelledStepupCallout.php index 1fd61cfb2c..b7535386fa 100644 --- a/library/EngineBlock/Corto/Exception/UserCancelledStepupCallout.php +++ b/library/EngineBlock/Corto/Exception/UserCancelledStepupCallout.php @@ -32,7 +32,7 @@ public function __construct($message, EngineBlock_Corto_Exception_ReceivedErrorS /** * @return array */ - public function getFeedbackInfo() + public function getFeedbackInfo(): array { return $this->feedback; } diff --git a/library/EngineBlock/Corto/Filter/Command/AttributeAggregator.php b/library/EngineBlock/Corto/Filter/Command/AttributeAggregator.php index a31e659aa0..3eebd38978 100644 --- a/library/EngineBlock/Corto/Filter/Command/AttributeAggregator.php +++ b/library/EngineBlock/Corto/Filter/Command/AttributeAggregator.php @@ -62,7 +62,7 @@ public function __construct( /** * {@inheritdoc} */ - public function getResponse() + public function getResponse(): EngineBlock_Saml2_ResponseAnnotationDecorator { return $this->_response; } diff --git a/library/EngineBlock/Corto/Filter/Command/AttributeReleasePolicy.php b/library/EngineBlock/Corto/Filter/Command/AttributeReleasePolicy.php index ec69e6bee2..6792fec67f 100644 --- a/library/EngineBlock/Corto/Filter/Command/AttributeReleasePolicy.php +++ b/library/EngineBlock/Corto/Filter/Command/AttributeReleasePolicy.php @@ -28,7 +28,7 @@ public function getResponseAttributes() return $this->_responseAttributes; } - public function getResponseAttributeValueTypes() + public function getResponseAttributeValueTypes(): array { return $this->_responseAttributeValueTypes; } @@ -57,7 +57,7 @@ public function execute() } $logger->info("Applying attribute release policy for $spEntityId"); - $attributes = $enforcer->enforceArp($arp, $attributes); + $attributes = $enforcer->enforceArp($attributes, $arp); $this->_responseAttributeValueTypes = $enforcer->updateAttributeValueTypes( $attributes, diff --git a/library/EngineBlock/Corto/Filter/Command/CollabPersonIdModificationInterface.php b/library/EngineBlock/Corto/Filter/Command/CollabPersonIdModificationInterface.php index b820de3737..aebb994803 100644 --- a/library/EngineBlock/Corto/Filter/Command/CollabPersonIdModificationInterface.php +++ b/library/EngineBlock/Corto/Filter/Command/CollabPersonIdModificationInterface.php @@ -21,7 +21,7 @@ interface EngineBlock_Corto_Filter_Command_CollabPersonIdModificationInterface /** * This command modifies the collabPersonId * - * @return string + * @return string|null */ public function getCollabPersonId(); } diff --git a/library/EngineBlock/Corto/Filter/Command/ProvisionUser.php b/library/EngineBlock/Corto/Filter/Command/ProvisionUser.php index b77b9205ff..765b051118 100644 --- a/library/EngineBlock/Corto/Filter/Command/ProvisionUser.php +++ b/library/EngineBlock/Corto/Filter/Command/ProvisionUser.php @@ -37,7 +37,7 @@ public function __construct(UserDirectoryAdapter $userDirectory) /** * {@inheritdoc} */ - public function getResponse() + public function getResponse(): EngineBlock_Saml2_ResponseAnnotationDecorator { return $this->_response; } diff --git a/library/EngineBlock/Corto/Filter/Command/ResponseAttributeValueTypesModificationInterface.php b/library/EngineBlock/Corto/Filter/Command/ResponseAttributeValueTypesModificationInterface.php index 03abc48f49..e5d3a76189 100644 --- a/library/EngineBlock/Corto/Filter/Command/ResponseAttributeValueTypesModificationInterface.php +++ b/library/EngineBlock/Corto/Filter/Command/ResponseAttributeValueTypesModificationInterface.php @@ -23,5 +23,5 @@ interface EngineBlock_Corto_Filter_Command_ResponseAttributeValueTypesModificati * * @return array */ - public function getResponseAttributeValueTypes(); + public function getResponseAttributeValueTypes(): array; } diff --git a/library/EngineBlock/Corto/Filter/Command/ResponseModificationInterface.php b/library/EngineBlock/Corto/Filter/Command/ResponseModificationInterface.php index 7ad0cf8d27..a3762c35c9 100644 --- a/library/EngineBlock/Corto/Filter/Command/ResponseModificationInterface.php +++ b/library/EngineBlock/Corto/Filter/Command/ResponseModificationInterface.php @@ -23,5 +23,5 @@ interface EngineBlock_Corto_Filter_Command_ResponseModificationInterface * * @return EngineBlock_Saml2_ResponseAnnotationDecorator */ - public function getResponse(); + public function getResponse(): EngineBlock_Saml2_ResponseAnnotationDecorator; } diff --git a/library/EngineBlock/Corto/Filter/Command/RunAttributeManipulations.php b/library/EngineBlock/Corto/Filter/Command/RunAttributeManipulations.php index 69352e2b37..5b10186dfa 100644 --- a/library/EngineBlock/Corto/Filter/Command/RunAttributeManipulations.php +++ b/library/EngineBlock/Corto/Filter/Command/RunAttributeManipulations.php @@ -41,7 +41,7 @@ function __construct($type) /** * {@inheritdoc} */ - public function getResponse() + public function getResponse(): EngineBlock_Saml2_ResponseAnnotationDecorator { return $this->_response; } @@ -57,7 +57,7 @@ public function getResponseAttributes() /** * {@inheritdoc} */ - public function getResponseAttributeValueTypes() + public function getResponseAttributeValueTypes(): array { return $this->_responseAttributeValueTypes; } diff --git a/library/EngineBlock/Corto/Model/Consent.php b/library/EngineBlock/Corto/Model/Consent.php index 96c013357d..40bd3e1ef6 100644 --- a/library/EngineBlock/Corto/Model/Consent.php +++ b/library/EngineBlock/Corto/Model/Consent.php @@ -16,6 +16,7 @@ * limitations under the License. */ +use Doctrine\DBAL\Statement; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; use OpenConext\EngineBlock\Authentication\Value\ConsentType; @@ -112,7 +113,7 @@ public function giveImplicitConsentFor(ServiceProvider $serviceProvider) } /** - * @return bool|PDO + * @return Doctrine\DBAL\Connection */ protected function _getConsentDatabaseConnection() { @@ -149,11 +150,16 @@ private function _storeConsent(ServiceProvider $serviceProvider, $consentType) return false; } + $consentUuid = $this->_getConsentUid(); + if(! is_string($consentUuid)){ + return false; + } + $query = "INSERT INTO consent (hashed_user_id, service_id, attribute, consent_type, consent_date, deleted_at) VALUES (?, ?, ?, ?, NOW(), '0000-00-00 00:00:00') ON DUPLICATE KEY UPDATE attribute=VALUES(attribute), consent_type=VALUES(consent_type), consent_date=NOW()"; $parameters = array( - sha1($this->_getConsentUid()), + sha1($consentUuid), $serviceProvider->entityId, $this->_getAttributesHash($this->_responseAttributes), $consentType, @@ -167,10 +173,16 @@ private function _storeConsent(ServiceProvider $serviceProvider, $consentType) ); } - /** @var $statement PDOStatement */ - if (!$statement->execute($parameters)) { + assert($statement instanceof Statement); + try{ + foreach ($parameters as $index => $parameter){ + $statement->bindValue($index + 1, $parameter); + } + + $statement->executeStatement(); + }catch (\Doctrine\DBAL\Exception $e){ throw new EngineBlock_Corto_Module_Services_Exception( - sprintf('Error storing consent: "%s"', var_export($statement->errorInfo(), true)), + sprintf('Error storing consent: "%s"', var_export($e->getMessage(), true)), EngineBlock_Exception::CODE_CRITICAL ); } @@ -187,6 +199,11 @@ private function _hasStoredConsent(ServiceProvider $serviceProvider, $consentTyp $attributesHash = $this->_getAttributesHash($this->_responseAttributes); + $consentUuid = $this->_getConsentUid(); + if (!is_string($consentUuid)) { + return false; + } + $query = " SELECT * FROM {$this->_tableName} @@ -196,7 +213,7 @@ private function _hasStoredConsent(ServiceProvider $serviceProvider, $consentTyp AND consent_type = ? AND deleted_at IS NULL "; - $hashedUserId = sha1($this->_getConsentUid()); + $hashedUserId = sha1($consentUuid); $parameters = array( $hashedUserId, $serviceProvider->entityId, @@ -204,12 +221,14 @@ private function _hasStoredConsent(ServiceProvider $serviceProvider, $consentTyp $consentType, ); - /** @var $statement PDOStatement */ $statement = $dbh->prepare($query); - $statement->execute($parameters); - $rows = $statement->fetchAll(); + assert($statement instanceof Statement); + foreach ($parameters as $position => $parameter) { + $statement->bindValue($position + 1, $parameter); + } + $rows = $statement->executeQuery(); - if (count($rows) < 1) { + if ($rows->rowCount() < 1) { // No stored consent found return false; } diff --git a/library/EngineBlock/Corto/Module/Bindings.php b/library/EngineBlock/Corto/Module/Bindings.php index 7581c11d9e..1a47e8aefb 100644 --- a/library/EngineBlock/Corto/Module/Bindings.php +++ b/library/EngineBlock/Corto/Module/Bindings.php @@ -36,6 +36,7 @@ use SAML2\Message; use SAML2\Response; use SAML2\Signature\PublicKeyValidator; +use Twig\Environment; /** * The bindings module for Corto, which implements support for various data @@ -94,7 +95,7 @@ class EngineBlock_Corto_Module_Bindings extends EngineBlock_Corto_Module_Abstrac private $_logger; /** - * @var Twig_Environment + * @var Environment */ private $twig; @@ -455,7 +456,7 @@ public function receiveResponse($serviceEntityId, $expectedDestination) } catch (Exception $exception) { throw new ResponseProcessingFailedException( - sprintf('Response processing failed: "%s"', $exception->getMessage()), null, $exception + sprintf('Response processing failed: "%s"', $exception->getMessage()), 0, $exception ); } @@ -665,7 +666,7 @@ public function send( // If the processed assertion consumer service is set on the response, it is posted back to the SP using the // the 'return' hidden form field. - if (method_exists($message, 'getReturn') && !empty(trim($message->getReturn()))) { + if (method_exists($message, 'getReturn') && !empty(trim($message->getReturn() ?? ''))) { $extra .= ''; } diff --git a/library/EngineBlock/Corto/Module/Service/Abstract.php b/library/EngineBlock/Corto/Module/Service/Abstract.php index fb24803408..ce7e00fcd1 100644 --- a/library/EngineBlock/Corto/Module/Service/Abstract.php +++ b/library/EngineBlock/Corto/Module/Service/Abstract.php @@ -1,5 +1,7 @@ _server = $server; $this->_xmlConverter = $xmlConverter; diff --git a/library/EngineBlock/Corto/Module/Service/ContinueToIdp.php b/library/EngineBlock/Corto/Module/Service/ContinueToIdp.php index d83d5f9269..ee3a3a0f3b 100644 --- a/library/EngineBlock/Corto/Module/Service/ContinueToIdp.php +++ b/library/EngineBlock/Corto/Module/Service/ContinueToIdp.php @@ -20,6 +20,7 @@ use OpenConext\EngineBlock\Metadata\Factory\Factory\ServiceProviderFactory; use OpenConext\EngineBlock\Metadata\X509\KeyPairFactory; use Symfony\Component\HttpFoundation\Request; +use Twig\Environment; class EngineBlock_Corto_Module_Service_ContinueToIdp implements EngineBlock_Corto_Module_Service_ServiceInterface { @@ -32,7 +33,7 @@ class EngineBlock_Corto_Module_Service_ContinueToIdp implements EngineBlock_Cort protected $_xmlConverter; /** - * @var Twig_Environment + * @var Environment */ protected $twig; @@ -44,7 +45,7 @@ class EngineBlock_Corto_Module_Service_ContinueToIdp implements EngineBlock_Cort public function __construct( EngineBlock_Corto_ProxyServer $server, EngineBlock_Corto_XmlToArray $xmlConverter, - Twig_Environment $twig, + Environment $twig, ServiceProviderFactory $serviceProviderFactory ) { $this->_server = $server; diff --git a/library/EngineBlock/Corto/Module/Service/Interface.php b/library/EngineBlock/Corto/Module/Service/Interface.php index def5d555cd..2b6d463557 100644 --- a/library/EngineBlock/Corto/Module/Service/Interface.php +++ b/library/EngineBlock/Corto/Module/Service/Interface.php @@ -1,5 +1,7 @@ getDiContainer(); - // Profile url is configurable in parameters.yml (profile_base_url) + // Profile url is configurable in parameters.yaml (profile_base_url) $profileUrl = '#'; $configuredUrl = $settings->getProfileBaseUrl(); if (!empty($configuredUrl)) { diff --git a/library/EngineBlock/Corto/Module/Service/SingleSignOn.php b/library/EngineBlock/Corto/Module/Service/SingleSignOn.php index e05b0cf2aa..2ebb46598a 100644 --- a/library/EngineBlock/Corto/Module/Service/SingleSignOn.php +++ b/library/EngineBlock/Corto/Module/Service/SingleSignOn.php @@ -28,6 +28,8 @@ use SAML2\Response; use SAML2\XML\saml\Issuer; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Mime\Address; +use Twig\Environment; class EngineBlock_Corto_Module_Service_SingleSignOn implements EngineBlock_Corto_Module_Service_ServiceInterface { @@ -42,7 +44,7 @@ class EngineBlock_Corto_Module_Service_SingleSignOn implements EngineBlock_Corto protected $_xmlConverter; /** - * @var Twig_Environment + * @var Environment */ protected $twig; @@ -59,7 +61,7 @@ class EngineBlock_Corto_Module_Service_SingleSignOn implements EngineBlock_Corto public function __construct( EngineBlock_Corto_ProxyServer $server, EngineBlock_Corto_XmlToArray $xmlConverter, - Twig_Environment $twig, + Environment $twig, ServiceProviderFactory $serviceProviderFactory, DiscoverySelectionService $discoverySelectionService ) { @@ -584,13 +586,12 @@ protected function _sendDebugMail(EngineBlock_Saml2_ResponseAnnotationDecorator $diContainer = EngineBlock_ApplicationSingleton::getInstance()->getDiContainer(); $emailConfiguration = $diContainer->getEmailIdpDebuggingConfiguration(); - $message = new Swift_Message(); + $message = new Symfony\Component\Mime\Email(); $message - ->setSubject(sprintf($emailConfiguration['subject'], $identityProvider->nameEn)) - ->setFrom($emailConfiguration['from']['address'], $emailConfiguration['from']['name']) - ->setTo($emailConfiguration['to']['address'], $emailConfiguration['to']['name']) - ->setBody($output, 'text/plain'); - + ->subject(sprintf($emailConfiguration['subject'], $identityProvider->nameEn)) + ->from(new Address($emailConfiguration['from']['address'], $emailConfiguration['from']['name'])) + ->to(new Address($emailConfiguration['to']['address'], $emailConfiguration['to']['name'])) + ->text($output); $diContainer->getMailer()->send($message); } diff --git a/library/EngineBlock/Corto/Module/Services.php b/library/EngineBlock/Corto/Module/Services.php index d700844d3a..763469a5aa 100644 --- a/library/EngineBlock/Corto/Module/Services.php +++ b/library/EngineBlock/Corto/Module/Services.php @@ -16,23 +16,6 @@ * limitations under the License. */ -class EngineBlock_Corto_Module_Services_Exception extends EngineBlock_Corto_ProxyServer_Exception -{ - public function __construct($message, $severity = self::CODE_NOTICE, Exception $previous = null) - { - parent::__construct($message, $severity, $previous); - } - -} - -class EngineBlock_Corto_Module_Services_SessionLostException extends EngineBlock_Corto_Module_Services_Exception -{ -} - -class EngineBlock_Corto_Module_Services_SessionNotStartedException extends EngineBlock_Corto_Module_Services_Exception -{ -} - class EngineBlock_Corto_Module_Services extends EngineBlock_Corto_Module_Abstract { protected $_aliases = array( diff --git a/library/EngineBlock/Corto/Module/Services/Exception.php b/library/EngineBlock/Corto/Module/Services/Exception.php new file mode 100644 index 0000000000..c6c94e43b2 --- /dev/null +++ b/library/EngineBlock/Corto/Module/Services/Exception.php @@ -0,0 +1,26 @@ +_server = $this; $this->twig = $twig; diff --git a/library/EngineBlock/Corto/XmlToArray.php b/library/EngineBlock/Corto/XmlToArray.php index 77a3863e3b..fa2eb8b1cc 100644 --- a/library/EngineBlock/Corto/XmlToArray.php +++ b/library/EngineBlock/Corto/XmlToArray.php @@ -417,7 +417,7 @@ public static function array2attributes($attributes) foreach((array)$attributes as $name => $attribute) { // Name must be a uri // Uri checking is hard, so at least check for a scheme. - assert('(bool)preg_match("|(\w+)\:.+|", $name)'); + assert((bool) preg_match("|(\\w+)\\:.+|", $name)); $newAttribute = array( '_Name' => $name, '_NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', diff --git a/library/EngineBlock/Database/ConnectionFactory.php b/library/EngineBlock/Database/ConnectionFactory.php index 82612d990e..0889e08132 100644 --- a/library/EngineBlock/Database/ConnectionFactory.php +++ b/library/EngineBlock/Database/ConnectionFactory.php @@ -31,17 +31,9 @@ public function __construct(EntityManager $em) $this->connection = $em->getConnection(); } - /** - * Create a new Database connection, for a given mode self::MODE_READ and self::MODE_WRITE, - * defaults to write mode. - * - * @return \Doctrine\DBAL\Driver\PDOConnection - * - * @deprecated This functionality will be removed - */ - public function create() + public function create(): Doctrine\DBAL\Connection { - return $this->connection->getWrappedConnection(); + return $this->connection; } } diff --git a/library/EngineBlock/Http/Request.php b/library/EngineBlock/Http/Request.php index 6f5adc0040..6a67b523cb 100644 --- a/library/EngineBlock/Http/Request.php +++ b/library/EngineBlock/Http/Request.php @@ -38,17 +38,17 @@ public static function createFromEnvironment() $request = new self(); $request->setProtocol((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']==='on')); - $request->setMethod($_SERVER['REQUEST_METHOD']); - $request->setHttpProtocol($_SERVER['SERVER_PROTOCOL']); + $request->setMethod($_SERVER['REQUEST_METHOD'] ?? null); + $request->setHttpProtocol($_SERVER['SERVER_PROTOCOL'] ?? null); - $queryStart = strpos($_SERVER['REQUEST_URI'], '?'); + $queryStart = strpos($_SERVER['REQUEST_URI'] ?? '', '?'); if ($queryStart !== false) { - $request->setUri(substr($_SERVER['REQUEST_URI'], 0, $queryStart)); + $request->setUri(substr($_SERVER['REQUEST_URI'] ?? null, 0, $queryStart)); } else { - $request->setUri($_SERVER['REQUEST_URI']); + $request->setUri($_SERVER['REQUEST_URI'] ?? null); } - $request->setQueryString($_SERVER['QUERY_STRING']); + $request->setQueryString($_SERVER['QUERY_STRING'] ?? null); $request->_setPostParameters($_POST); $headers = array(); @@ -95,6 +95,12 @@ public function getHttpProtocol() public function setUri($uri) { + if (!is_string($uri)) { + $this->_uri = ''; + + return $this; + } + $this->_uri = urldecode($uri); return $this; } @@ -131,6 +137,10 @@ public function getQueryParameters() protected function _setQueryParameters($queryString) { + if (!is_string($queryString)) { + return; + } + $this->_queryParameters = array(); $queryParts = explode("&", $queryString); foreach($queryParts as $queryPart) { diff --git a/library/EngineBlock/Saml2/AuthnRequestAnnotationDecorator.php b/library/EngineBlock/Saml2/AuthnRequestAnnotationDecorator.php index 2f10449b46..847b4548db 100644 --- a/library/EngineBlock/Saml2/AuthnRequestAnnotationDecorator.php +++ b/library/EngineBlock/Saml2/AuthnRequestAnnotationDecorator.php @@ -18,6 +18,7 @@ use OpenConext\EngineBlock\Metadata\Loa; use SAML2\AuthnRequest; +use SAML2\DOMDocumentFactory; /** * @method getProxyCount() @@ -57,6 +58,16 @@ class EngineBlock_Saml2_AuthnRequestAnnotationDecorator extends EngineBlock_Saml */ protected $transparent = false; + /** + * @var string|null Temporary storage for serialized XML + */ + private ?string $_serializableSspMessageXml = null; + + /** + * @var string|null Persisted RelayState while serialized (not part of the AuthnRequest XML itself) + */ + private ?string $_serializableRelayState = null; + /** * @param AuthnRequest $request */ @@ -184,4 +195,34 @@ public function setForceAuthn(bool $isForceAuthn) { $this->sspMessage->setForceAuthn($isForceAuthn); } + + /** + * @return array + */ + public function __sleep() + { + if ($this->sspMessage instanceof AuthnRequest) { + $this->_serializableSspMessageXml = $this->sspMessage->toUnsignedXML()->ownerDocument->saveXML(); + $this->_serializableRelayState = $this->sspMessage->getRelayState(); + } + + return ['keyId', 'wasSigned', 'debug', 'unsolicited', 'transparent', '_serializableSspMessageXml', '_serializableRelayState']; + } + + public function __wakeup() + { + if (isset($this->_serializableSspMessageXml)) { + $document = DOMDocumentFactory::fromString($this->_serializableSspMessageXml); + $messageDomElement = $document->getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:protocol', 'AuthnRequest')->item(0); + + if ($messageDomElement) { + $this->sspMessage = AuthnRequest::fromXML($messageDomElement); + if (isset($this->_serializableRelayState) && $this->_serializableRelayState !== null) { + $this->sspMessage->setRelayState($this->_serializableRelayState); + } + } + + unset($this->_serializableSspMessageXml, $this->_serializableRelayState); + } + } } diff --git a/library/EngineBlock/Saml2/AuthnRequestFactory.php b/library/EngineBlock/Saml2/AuthnRequestFactory.php index a6b85e7e7c..b2311efa1e 100644 --- a/library/EngineBlock/Saml2/AuthnRequestFactory.php +++ b/library/EngineBlock/Saml2/AuthnRequestFactory.php @@ -49,7 +49,7 @@ public static function createFromRequest( $sspRequest = new AuthnRequest(); $sspRequest->setId($server->getNewId(EngineBlock_Saml2_IdGenerator::ID_USAGE_SAML2_REQUEST)); $sspRequest->setIssueInstant(time()); - $sspRequest->setDestination($idpMetadata->singleSignOnServices[0]->location); + $sspRequest->setDestination(isset($idpMetadata->singleSignOnServices[0]) ? $idpMetadata->singleSignOnServices[0]->location : null); $sspRequest->setForceAuthn($originalRequest->getForceAuthn()); $sspRequest->setIsPassive($originalRequest->getIsPassive()); $sspRequest->setAssertionConsumerServiceURL($server->getUrl($acsServiceName)); @@ -81,7 +81,7 @@ public static function createFromRequest( // Use the default binding even if more exist $request = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($sspRequest); - $request->setDeliverByBinding($idpMetadata->singleSignOnServices[0]->binding); + $request->setDeliverByBinding(isset($idpMetadata->singleSignOnServices[0]) ? $idpMetadata->singleSignOnServices[0]->binding : null); return $request; } diff --git a/library/EngineBlock/Saml2/Container.php b/library/EngineBlock/Saml2/Container.php index accf72ca60..a7dfe2577c 100644 --- a/library/EngineBlock/Saml2/Container.php +++ b/library/EngineBlock/Saml2/Container.php @@ -64,7 +64,7 @@ public function redirect($url, $data = array()): void throw new BadMethodCallException( sprintf( '"%s":"%s" may not be called in the Surfnet\\SamlBundle as it doesn\'t work with Symfony', - __CLASS__, + self::class, __METHOD__ ) ); @@ -75,7 +75,7 @@ public function postRedirect($url, $data = array()): void throw new BadMethodCallException( sprintf( '"%s":"%s" may not be called in the Surfnet\\SamlBundle as it doesn\'t work with Symfony"', - __CLASS__, + self::class, __METHOD__ ) ); @@ -86,7 +86,7 @@ public function getTempDir(): string throw new BadMethodCallException( sprintf( '"%s":"%s" may not be called in the Surfnet\\SamlBundle as it doesn\'t work with Symfony"', - __CLASS__, + self::class, __METHOD__ ) ); @@ -97,7 +97,7 @@ public function writeFile(string $filename, string $data, int $mode = null): voi throw new BadMethodCallException( sprintf( '"%s":"%s" may not be called in the Surfnet\\SamlBundle as it doesn\'t work with Symfony"', - __CLASS__, + self::class, __METHOD__ ) ); diff --git a/library/EngineBlock/Saml2/MessageAnnotationDecorator.php b/library/EngineBlock/Saml2/MessageAnnotationDecorator.php index 7e8eb37442..0ddc1172af 100644 --- a/library/EngineBlock/Saml2/MessageAnnotationDecorator.php +++ b/library/EngineBlock/Saml2/MessageAnnotationDecorator.php @@ -135,7 +135,17 @@ public function getMessageType() public function __toString() { $vars = get_object_vars($this); + + if (array_key_exists('_serializableRelayState', $vars) && $vars['_serializableRelayState'] === null) { + unset($vars['_serializableRelayState']); + } + + if (array_key_exists('_serializableSspMessageXml', $vars) && $vars['_serializableSspMessageXml'] === null) { + unset($vars['_serializableSspMessageXml']); + } + $vars['sspMessage'] = $this->sspMessage->toUnsignedXML()->ownerDocument->saveXML(); + return json_encode($vars); } } diff --git a/library/EngineBlock/Saml2/NameIdResolver.php b/library/EngineBlock/Saml2/NameIdResolver.php index 9df8b31937..0db5876bb0 100644 --- a/library/EngineBlock/Saml2/NameIdResolver.php +++ b/library/EngineBlock/Saml2/NameIdResolver.php @@ -16,6 +16,7 @@ * limitations under the License. */ +use Doctrine\DBAL\Statement; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; use Psr\Log\LoggerInterface; use Ramsey\Uuid\Uuid; @@ -264,23 +265,34 @@ protected function _fetchServiceProviderUuid($spEntityId) $statement = $this->_getDb()->prepare( 'SELECT uuid FROM service_provider_uuid WHERE service_provider_entity_id=?' ); - $statement->execute(array($spEntityId)); - $result = $statement->fetchAll(); + assert($statement instanceof Statement); + $statement->bindValue(1, $spEntityId); + $resultSet = $statement->executeQuery(); - if (count($result) > 1) { + + if ($resultSet->rowCount() > 1) { throw new EngineBlock_Exception(sprintf('Multiple SP UUIDs found? For SP: "%s"', $spEntityId)); } + if($resultSet->rowCount() === 0){ + return false; + } + + $result = $resultSet->fetchAllAssociative(); + return isset($result[0]['uuid']) ? $result[0]['uuid'] : false; } protected function _storeServiceProviderUuid($spEntityId, $uuid) { - $this->_getDb()->prepare( + $statement = $this->_getDb()->prepare( 'INSERT INTO service_provider_uuid (uuid, service_provider_entity_id) VALUES (?,?)' - )->execute( - array($uuid, $spEntityId) ); + + $statement->bindValue(1, $uuid); + $statement->bindValue(2, $spEntityId); + + $statement->executeStatement(); } protected function _fetchPersistentId($serviceProviderUuid, $userUuid) @@ -288,9 +300,12 @@ protected function _fetchPersistentId($serviceProviderUuid, $userUuid) $statement = $this->_getDb()->prepare( "SELECT persistent_id FROM saml_persistent_id WHERE service_provider_uuid = ? AND user_uuid = ?" ); - $statement->execute(array($serviceProviderUuid, $userUuid)); - $result = $statement->fetchAll(); - if (count($result) > 1) { + + $statement->bindValue(1, $serviceProviderUuid); + $statement->bindValue(2, $userUuid); + + $resultSet = $statement->executeQuery(); + if ($resultSet->rowCount() > 1) { throw new EngineBlock_Exception( sprintf( 'Multiple persistent IDs found? For: SP UUID: "%s" and user UUID: "%s"', @@ -299,6 +314,9 @@ protected function _fetchPersistentId($serviceProviderUuid, $userUuid) ) ); } + + $result = $resultSet->fetchAllAssociative(); + return isset($result[0]['persistent_id']) ? $result[0]['persistent_id'] : false; } @@ -309,14 +327,18 @@ protected function _generatePersistentId($serviceProviderUuid, $userUuid) protected function _storePersistentId($persistentId, $serviceProviderUuid, $userUuid) { - $this->_getDb()->prepare( + $statement = $this->_getDb()->prepare( "INSERT INTO saml_persistent_id (persistent_id, service_provider_uuid, user_uuid) VALUES (?,?,?)" - )->execute( - array($persistentId, $serviceProviderUuid, $userUuid) ); + + $statement->bindValue(1, $persistentId); + $statement->bindValue(2, $serviceProviderUuid); + $statement->bindValue(3, $userUuid); + + $statement->executeStatement(); } - protected function _getDb() + protected function _getDb(): Doctrine\DBAL\Connection { static $s_db; if ($s_db) { diff --git a/library/EngineBlock/Saml2/ResponseAnnotationDecorator.php b/library/EngineBlock/Saml2/ResponseAnnotationDecorator.php index 366781a56e..7ba6f9856e 100644 --- a/library/EngineBlock/Saml2/ResponseAnnotationDecorator.php +++ b/library/EngineBlock/Saml2/ResponseAnnotationDecorator.php @@ -17,6 +17,7 @@ */ use SAML2\Assertion; +use SAML2\DOMDocumentFactory; use SAML2\EncryptedAssertion; use SAML2\Response; use SAML2\XML\saml\NameID; @@ -82,6 +83,16 @@ class EngineBlock_Saml2_ResponseAnnotationDecorator extends EngineBlock_Saml2_Me protected $isTransparentErrorResponse = false; + /** + * @var string Temporary storage for serialized XML + */ + private ?string $_serializableSspMessageXml = null; + + /** + * @var string|null Persisted RelayState while serialized (not part of the AuthnRequest XML itself) + */ + private ?string $_serializableRelayState = null; + /** * @param Response $response */ @@ -308,4 +319,51 @@ public function setIsTransparentErrorResponse(bool $isTransparentErrorResponse): { $this->isTransparentErrorResponse = $isTransparentErrorResponse; } + + /** + * @return array + */ + public function __sleep() + { + if ($this->sspMessage instanceof Response) { + $this->_serializableSspMessageXml = $this->sspMessage->toUnsignedXML()->ownerDocument->saveXML(); + $this->_serializableRelayState = $this->sspMessage->getRelayState(); + } + + return [ + 'return', + 'originalIssuer', + 'originalNameId', + 'originalBinding', + 'originalResponse', + 'collabPersonId', + 'customNameId', + 'intendedNameId', + 'pdpRequestedLoas', + 'isTransparentErrorResponse', + '_serializableSspMessageXml', + '_serializableRelayState', + ]; + } + + /** + * Custom deserialization to recreate $sspMessage from XML string + */ + public function __wakeup() + { + if (isset($this->_serializableSspMessageXml)) { + $document = DOMDocumentFactory::fromString($this->_serializableSspMessageXml); + $messageDomElement = $document->getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:protocol', 'Response')->item(0); + + if ($messageDomElement) { + $this->sspMessage = \OpenConext\EngineBlockFunctionalTestingBundle\Saml2\Response::fromXML($messageDomElement); + } + + if (isset($this->_serializableRelayState) && $this->_serializableRelayState !== null) { + $this->sspMessage->setRelayState($this->_serializableRelayState); + } + + unset($this->_serializableSspMessageXml); + } + } } diff --git a/library/EngineBlock/User.php b/library/EngineBlock/User.php index 266c879ab4..221815c474 100644 --- a/library/EngineBlock/User.php +++ b/library/EngineBlock/User.php @@ -45,9 +45,12 @@ public function deleteConsent($spId) $query = "DELETE FROM consent WHERE hashed_user_id = ? AND service_id = ?"; - $parameters = array(sha1($this->getUid()), $spId); + $statement = $pdo->prepare($query); - $statement->execute($parameters); + + $statement->bindValue(1, sha1($this->getUid())); + $statement->bindValue(2, $spId); + $statement->executeStatement(); } public function getConsent() @@ -56,12 +59,9 @@ public function getConsent() $query = 'SELECT service_id FROM consent WHERE hashed_user_id = ? AND deleted_at IS NULL'; - $parameters = array( - sha1($this->getUid()) - ); $statement = $pdo->prepare($query); - $statement->execute($parameters); - $resultSet = $statement->fetchAll(); + $statement->bindValue(1, sha1($this->getUid())); + $resultSet = $statement->executeQuery()->fetchAllAssociative(); $result = array(); foreach($resultSet as $value) { @@ -112,16 +112,14 @@ protected function _deleteUserConsent() $query = "DELETE FROM consent WHERE hashed_user_id = ?"; - $parameters = array( - sha1($this->getUid()) - ); $statement = $pdo->prepare($query); - $statement->execute($parameters); + $statement->bindValue(1, sha1($this->getUid())); + $statement->executeStatement(); } /** - * @return PDO + * @return \Doctrine\DBAL\Connection */ protected function _getDatabaseConnection() { diff --git a/database/DoctrineMigrations/Version20160307162928.php b/migrations/DoctrineMigrations/Version20160307162928.php similarity index 93% rename from database/DoctrineMigrations/Version20160307162928.php rename to migrations/DoctrineMigrations/Version20160307162928.php index 75400f6438..128b87b47c 100644 --- a/database/DoctrineMigrations/Version20160307162928.php +++ b/migrations/DoctrineMigrations/Version20160307162928.php @@ -2,8 +2,8 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; +use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! @@ -13,7 +13,7 @@ class Version20160307162928 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -25,7 +25,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20160412141621.php b/migrations/DoctrineMigrations/Version20160412141621.php similarity index 89% rename from database/DoctrineMigrations/Version20160412141621.php rename to migrations/DoctrineMigrations/Version20160412141621.php index d4914fccf7..176ad2d1a6 100644 --- a/database/DoctrineMigrations/Version20160412141621.php +++ b/migrations/DoctrineMigrations/Version20160412141621.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20160412141621 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20160721121856.php b/migrations/DoctrineMigrations/Version20160721121856.php similarity index 84% rename from database/DoctrineMigrations/Version20160721121856.php rename to migrations/DoctrineMigrations/Version20160721121856.php index 104b4338cd..bb32e42989 100644 --- a/database/DoctrineMigrations/Version20160721121856.php +++ b/migrations/DoctrineMigrations/Version20160721121856.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20160721121856 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->addSql('CREATE TABLE sso_provider_roles_eb5 LIKE sso_provider_roles'); @@ -23,7 +23,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->addSql('DROP TABLE sso_provider_roles_eb5'); diff --git a/database/DoctrineMigrations/Version20161123131704.php b/migrations/DoctrineMigrations/Version20161123131704.php similarity index 93% rename from database/DoctrineMigrations/Version20161123131704.php rename to migrations/DoctrineMigrations/Version20161123131704.php index c4802288aa..8e3c138746 100644 --- a/database/DoctrineMigrations/Version20161123131704.php +++ b/migrations/DoctrineMigrations/Version20161123131704.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20161123131704 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs @@ -30,7 +30,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->addSql('CREATE TABLE IF NOT EXISTS virtual_organisation (vo_id VARCHAR(255) NOT NULL, vo_type enum(\'GROUP\',\'STEM\',\'IDP\', \'MIXED\') NOT NULL, PRIMARY KEY (vo_id)) ENGINE=InnoDB'); diff --git a/database/DoctrineMigrations/Version20161209145942.php b/migrations/DoctrineMigrations/Version20161209145942.php similarity index 83% rename from database/DoctrineMigrations/Version20161209145942.php rename to migrations/DoctrineMigrations/Version20161209145942.php index 78eff0c503..1540ac1407 100644 --- a/database/DoctrineMigrations/Version20161209145942.php +++ b/migrations/DoctrineMigrations/Version20161209145942.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20161209145942 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // Make sure consent_date is not updated every time a row is updated $this->addSql('ALTER TABLE consent CHANGE consent_date consent_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;'); @@ -22,7 +22,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { $this->addSql('ALTER TABLE consent CHANGE consent_date consent_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;'); diff --git a/database/DoctrineMigrations/Version20161209152354.php b/migrations/DoctrineMigrations/Version20161209152354.php similarity index 79% rename from database/DoctrineMigrations/Version20161209152354.php rename to migrations/DoctrineMigrations/Version20161209152354.php index dcf42e2b3c..5c2944f338 100644 --- a/database/DoctrineMigrations/Version20161209152354.php +++ b/migrations/DoctrineMigrations/Version20161209152354.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20161209152354 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { $this->addSql('ALTER TABLE consent DROP COLUMN usage_date'); @@ -22,7 +22,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { $this->addSql('ALTER TABLE consent ADD COLUMN usage_date TIMESTAMP DEFAULT \'0000-00-00 00:00:00\' AFTER consent_date'); } diff --git a/database/DoctrineMigrations/Version20170331145533.php b/migrations/DoctrineMigrations/Version20170331145533.php similarity index 89% rename from database/DoctrineMigrations/Version20170331145533.php rename to migrations/DoctrineMigrations/Version20170331145533.php index 2b1451975b..afac06ec23 100644 --- a/database/DoctrineMigrations/Version20170331145533.php +++ b/migrations/DoctrineMigrations/Version20170331145533.php @@ -2,19 +2,19 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; class Version20170331145533 extends AbstractMigration { - public function up(Schema $schema) + public function up(Schema $schema): void { $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); $this->addSql('DROP TABLE IF EXISTS log_logins'); } - public function down(Schema $schema) + public function down(Schema $schema): void { $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20170912155800.php b/migrations/DoctrineMigrations/Version20170912155800.php similarity index 97% rename from database/DoctrineMigrations/Version20170912155800.php rename to migrations/DoctrineMigrations/Version20170912155800.php index f17664ccf7..22f543c78f 100644 --- a/database/DoctrineMigrations/Version20170912155800.php +++ b/migrations/DoctrineMigrations/Version20170912155800.php @@ -2,12 +2,12 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; class Version20170912155800 extends AbstractMigration { - public function up(Schema $schema) + public function up(Schema $schema): void { $this->addSql('DROP TABLE IF EXISTS group_provider'); $this->addSql('DROP TABLE IF EXISTS group_provider_decorator'); @@ -21,7 +21,7 @@ public function up(Schema $schema) $this->addSql('DROP TABLE IF EXISTS service_provider_group_acl'); } - public function down(Schema $schema) + public function down(Schema $schema): void { $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180118115853.php b/migrations/DoctrineMigrations/Version20180118115853.php similarity index 89% rename from database/DoctrineMigrations/Version20180118115853.php rename to migrations/DoctrineMigrations/Version20180118115853.php index 208f174b80..65163526cc 100644 --- a/database/DoctrineMigrations/Version20180118115853.php +++ b/migrations/DoctrineMigrations/Version20180118115853.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180118115853 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -25,7 +25,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180202131013.php b/migrations/DoctrineMigrations/Version20180202131013.php similarity index 97% rename from database/DoctrineMigrations/Version20180202131013.php rename to migrations/DoctrineMigrations/Version20180202131013.php index f9710ee1a5..663b358d6b 100644 --- a/database/DoctrineMigrations/Version20180202131013.php +++ b/migrations/DoctrineMigrations/Version20180202131013.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180202131013 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -26,7 +26,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180215132859.php b/migrations/DoctrineMigrations/Version20180215132859.php similarity index 88% rename from database/DoctrineMigrations/Version20180215132859.php rename to migrations/DoctrineMigrations/Version20180215132859.php index 95471756ea..2ba18cabcb 100644 --- a/database/DoctrineMigrations/Version20180215132859.php +++ b/migrations/DoctrineMigrations/Version20180215132859.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180215132859 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180219171531.php b/migrations/DoctrineMigrations/Version20180219171531.php similarity index 90% rename from database/DoctrineMigrations/Version20180219171531.php rename to migrations/DoctrineMigrations/Version20180219171531.php index 3cd0faac3f..5e30cd68d7 100644 --- a/database/DoctrineMigrations/Version20180219171531.php +++ b/migrations/DoctrineMigrations/Version20180219171531.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180219171531 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180220080549.php b/migrations/DoctrineMigrations/Version20180220080549.php similarity index 87% rename from database/DoctrineMigrations/Version20180220080549.php rename to migrations/DoctrineMigrations/Version20180220080549.php index 11d87548a5..528552d7d3 100644 --- a/database/DoctrineMigrations/Version20180220080549.php +++ b/migrations/DoctrineMigrations/Version20180220080549.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180220080549 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -26,7 +26,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180221133212.php b/migrations/DoctrineMigrations/Version20180221133212.php similarity index 88% rename from database/DoctrineMigrations/Version20180221133212.php rename to migrations/DoctrineMigrations/Version20180221133212.php index 8fa6005f42..25ea732eb3 100644 --- a/database/DoctrineMigrations/Version20180221133212.php +++ b/migrations/DoctrineMigrations/Version20180221133212.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180221133212 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180618134736.php b/migrations/DoctrineMigrations/Version20180618134736.php similarity index 88% rename from database/DoctrineMigrations/Version20180618134736.php rename to migrations/DoctrineMigrations/Version20180618134736.php index 02ace26888..5a9f5d8360 100644 --- a/database/DoctrineMigrations/Version20180618134736.php +++ b/migrations/DoctrineMigrations/Version20180618134736.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -15,7 +15,7 @@ class Version20180618134736 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -26,7 +26,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20180804090135.php b/migrations/DoctrineMigrations/Version20180804090135.php similarity index 87% rename from database/DoctrineMigrations/Version20180804090135.php rename to migrations/DoctrineMigrations/Version20180804090135.php index 200d697983..1f7833e575 100644 --- a/database/DoctrineMigrations/Version20180804090135.php +++ b/migrations/DoctrineMigrations/Version20180804090135.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20180804090135 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20190425205743.php b/migrations/DoctrineMigrations/Version20190425205743.php similarity index 87% rename from database/DoctrineMigrations/Version20190425205743.php rename to migrations/DoctrineMigrations/Version20190425205743.php index b059efa7bb..71abad4cbf 100644 --- a/database/DoctrineMigrations/Version20190425205743.php +++ b/migrations/DoctrineMigrations/Version20190425205743.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20190425205743 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20190504110100.php b/migrations/DoctrineMigrations/Version20190504110100.php similarity index 91% rename from database/DoctrineMigrations/Version20190504110100.php rename to migrations/DoctrineMigrations/Version20190504110100.php index 830faf8d8e..6c820fe02b 100644 --- a/database/DoctrineMigrations/Version20190504110100.php +++ b/migrations/DoctrineMigrations/Version20190504110100.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -21,7 +21,7 @@ class Version20190504110100 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -32,7 +32,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20190703235333.php b/migrations/DoctrineMigrations/Version20190703235333.php similarity index 88% rename from database/DoctrineMigrations/Version20190703235333.php rename to migrations/DoctrineMigrations/Version20190703235333.php index 0a63d107f4..78053373c8 100644 --- a/database/DoctrineMigrations/Version20190703235333.php +++ b/migrations/DoctrineMigrations/Version20190703235333.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20190703235333 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20190710141146.php b/migrations/DoctrineMigrations/Version20190710141146.php similarity index 94% rename from database/DoctrineMigrations/Version20190710141146.php rename to migrations/DoctrineMigrations/Version20190710141146.php index ef1cee0967..06d3b81b80 100644 --- a/database/DoctrineMigrations/Version20190710141146.php +++ b/migrations/DoctrineMigrations/Version20190710141146.php @@ -2,7 +2,7 @@ namespace OpenConext\EngineBlock\Doctrine\Migrations; -use Doctrine\DBAL\Migrations\AbstractMigration; +use Doctrine\Migrations\AbstractMigration; use Doctrine\DBAL\Schema\Schema; /** @@ -13,7 +13,7 @@ class Version20190710141146 extends AbstractMigration /** * @param Schema $schema */ - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -24,7 +24,7 @@ public function up(Schema $schema) /** * @param Schema $schema */ - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20191011132428.php b/migrations/DoctrineMigrations/Version20191011132428.php similarity index 100% rename from database/DoctrineMigrations/Version20191011132428.php rename to migrations/DoctrineMigrations/Version20191011132428.php diff --git a/database/DoctrineMigrations/Version20200422145000.php b/migrations/DoctrineMigrations/Version20200422145000.php similarity index 93% rename from database/DoctrineMigrations/Version20200422145000.php rename to migrations/DoctrineMigrations/Version20200422145000.php index 63fa5cede4..a4442cde1e 100644 --- a/database/DoctrineMigrations/Version20200422145000.php +++ b/migrations/DoctrineMigrations/Version20200422145000.php @@ -10,7 +10,7 @@ */ final class Version20200422145000 extends AbstractMigration { - public function up(Schema $schema) + public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); @@ -19,7 +19,7 @@ public function up(Schema $schema) '); } - public function down(Schema $schema) + public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); diff --git a/database/DoctrineMigrations/Version20201005161700.php b/migrations/DoctrineMigrations/Version20201005161700.php similarity index 100% rename from database/DoctrineMigrations/Version20201005161700.php rename to migrations/DoctrineMigrations/Version20201005161700.php diff --git a/database/DoctrineMigrations/Version20220425090852.php b/migrations/DoctrineMigrations/Version20220425090852.php similarity index 100% rename from database/DoctrineMigrations/Version20220425090852.php rename to migrations/DoctrineMigrations/Version20220425090852.php diff --git a/database/DoctrineMigrations/Version20230418113623.php b/migrations/DoctrineMigrations/Version20230418113623.php similarity index 100% rename from database/DoctrineMigrations/Version20230418113623.php rename to migrations/DoctrineMigrations/Version20230418113623.php diff --git a/database/DoctrineMigrations/Version20230824090020.php b/migrations/DoctrineMigrations/Version20230824090020.php similarity index 85% rename from database/DoctrineMigrations/Version20230824090020.php rename to migrations/DoctrineMigrations/Version20230824090020.php index 4f1eb6e2ae..bc36a433f8 100644 --- a/database/DoctrineMigrations/Version20230824090020.php +++ b/migrations/DoctrineMigrations/Version20230824090020.php @@ -15,24 +15,24 @@ public function up(Schema $schema) : void ALTER TABLE sso_provider_roles_eb5 CHANGE organization_nl_name organization_nl_name TEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', CHANGE organization_en_name organization_en_name TEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', - CHANGE organization_pt_name organization_pt_name TEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', - CHANGE name_id_format name_id_format VARCHAR(255) DEFAULT NULL, + CHANGE organization_pt_name organization_pt_name TEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', + CHANGE name_id_format name_id_format VARCHAR(255) DEFAULT NULL, CHANGE single_logout_service single_logout_service TEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', - CHANGE attribute_release_policy attribute_release_policy TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE assertion_consumer_services assertion_consumer_services TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE allowed_idp_entity_ids allowed_idp_entity_ids MEDIUMTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE requested_attributes requested_attributes TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE support_url_en support_url_en VARCHAR(255) DEFAULT NULL, - CHANGE support_url_nl support_url_nl VARCHAR(255) DEFAULT NULL, - CHANGE support_url_pt support_url_pt VARCHAR(255) DEFAULT NULL, - CHANGE single_sign_on_services single_sign_on_services TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE consent_settings consent_settings MEDIUMTEXT DEFAULT NULL COMMENT \'(DC2Type:json_array)\', - CHANGE shib_md_scopes shib_md_scopes TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE mdui mdui TEXT NOT NULL COMMENT \'(DC2Type:array)\', - CHANGE coins coins TEXT NOT NULL COMMENT \'(DC2Type:array)\', - CHANGE name_id_formats name_id_formats TEXT NOT NULL COMMENT \'(DC2Type:array)\', - CHANGE contact_persons contact_persons TEXT NOT NULL COMMENT \'(DC2Type:array)\', - CHANGE certificates certificates TEXT NOT NULL COMMENT \'(DC2Type:array)\', + CHANGE attribute_release_policy attribute_release_policy TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE assertion_consumer_services assertion_consumer_services TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE allowed_idp_entity_ids allowed_idp_entity_ids MEDIUMTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE requested_attributes requested_attributes TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE support_url_en support_url_en VARCHAR(255) DEFAULT NULL, + CHANGE support_url_nl support_url_nl VARCHAR(255) DEFAULT NULL, + CHANGE support_url_pt support_url_pt VARCHAR(255) DEFAULT NULL, + CHANGE single_sign_on_services single_sign_on_services TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE consent_settings consent_settings MEDIUMTEXT DEFAULT NULL COMMENT \'(DC2Type:json)\', + CHANGE shib_md_scopes shib_md_scopes TEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE mdui mdui TEXT NOT NULL COMMENT \'(DC2Type:array)\', + CHANGE coins coins TEXT NOT NULL COMMENT \'(DC2Type:array)\', + CHANGE name_id_formats name_id_formats TEXT NOT NULL COMMENT \'(DC2Type:array)\', + CHANGE contact_persons contact_persons TEXT NOT NULL COMMENT \'(DC2Type:array)\', + CHANGE certificates certificates TEXT NOT NULL COMMENT \'(DC2Type:array)\', CHANGE manipulation manipulation TEXT NOT NULL COMMENT \'(DC2Type:array)\' '); } @@ -43,8 +43,8 @@ public function down(Schema $schema) : void $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); $this->addSql(' - ALTER TABLE sso_provider_roles_eb5 - CHANGE organization_nl_name organization_nl_name LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', + ALTER TABLE sso_provider_roles_eb5 + CHANGE organization_nl_name organization_nl_name LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', CHANGE organization_en_name organization_en_name LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', CHANGE organization_pt_name organization_pt_name LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:object)\', CHANGE name_id_format name_id_format VARCHAR(255) DEFAULT NULL, @@ -55,9 +55,9 @@ public function down(Schema $schema) : void CHANGE requested_attributes requested_attributes LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', CHANGE support_url_en support_url_en VARCHAR(255) DEFAULT NULL, CHANGE support_url_nl support_url_nl VARCHAR(255) DEFAULT NULL, - CHANGE support_url_pt support_url_pt VARCHAR(255) DEFAULT NULL, - CHANGE single_sign_on_services single_sign_on_services LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', - CHANGE consent_settings consent_settings LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json_array)\', + CHANGE support_url_pt support_url_pt VARCHAR(255) DEFAULT NULL, + CHANGE single_sign_on_services single_sign_on_services LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', + CHANGE consent_settings consent_settings LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json)\', CHANGE shib_md_scopes shib_md_scopes LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:array)\', CHANGE mdui mdui LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', CHANGE coins coins LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', diff --git a/database/DoctrineMigrations/Version20250206095609.php b/migrations/DoctrineMigrations/Version20250206095609.php similarity index 100% rename from database/DoctrineMigrations/Version20250206095609.php rename to migrations/DoctrineMigrations/Version20250206095609.php diff --git a/public/.gitignore b/public/.gitignore new file mode 100644 index 0000000000..3283583e8f --- /dev/null +++ b/public/.gitignore @@ -0,0 +1,5 @@ +cached +fonts +images +javascripts +stylesheets diff --git a/web/favicon.ico b/public/favicon.ico similarity index 100% rename from web/favicon.ico rename to public/favicon.ico diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000000..e75c311da3 --- /dev/null +++ b/public/index.php @@ -0,0 +1,39 @@ +handle($request); +$response->send(); +$kernel->terminate($request, $response); diff --git a/web/robots.txt b/public/robots.txt similarity index 100% rename from web/robots.txt rename to public/robots.txt diff --git a/src/Kernel.php b/src/Kernel.php new file mode 100644 index 0000000000..3a88b0fe05 --- /dev/null +++ b/src/Kernel.php @@ -0,0 +1,76 @@ +getProjectDir().'/config/bundles.php'; + foreach ($contents as $class => $envs) { + if ($envs[$this->environment] ?? $envs['all'] ?? false) { + yield new $class(); + } + } + } + + public function getProjectDir(): string + { + return \dirname(__DIR__); + } + + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void + { + $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); + $container->setParameter('container.dumper.inline_class_loader', \PHP_VERSION_ID < 70400 || $this->debug); + $container->setParameter('container.dumper.inline_factories', true); + + $confDir = $this->getProjectDir().'/config'; + + $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{packages}/'.$this->environment.'/*'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); + } + + protected function configureRoutes(RoutingConfigurator $routes): void + { + $confDir = $this->getProjectDir().'/config'; + + // Import env-specific routes + $routes->import($confDir.'/routes/'.$this->environment.'/*.yaml'); + $routes->import($confDir.'/routes/'.$this->environment.'/*.yml'); + // Import generic routes directory + $routes->import($confDir.'/routes/*.yaml'); + $routes->import($confDir.'/routes/*.yml'); + // Import top-level routes file + $routes->import($confDir.'/routes.yaml'); + } +} diff --git a/src/OpenConext/EngineBlock/Assert/Assertion.php b/src/OpenConext/EngineBlock/Assert/Assertion.php index ba001b4667..681dda1c6b 100644 --- a/src/OpenConext/EngineBlock/Assert/Assertion.php +++ b/src/OpenConext/EngineBlock/Assert/Assertion.php @@ -29,7 +29,7 @@ class Assertion extends BaseAssertion const INVALID_NON_EMPTY_STRING = 1001; const INVALID_HASHING_ALGORITHM = 1002; - protected static $exceptionClass = 'OpenConext\EngineBlock\Exception\InvalidArgumentException'; + protected static $exceptionClass = \OpenConext\EngineBlock\Exception\InvalidArgumentException::class; /** * @param string $value diff --git a/src/OpenConext/EngineBlock/Authentication/Model/Consent.php b/src/OpenConext/EngineBlock/Authentication/Model/Consent.php index c2fa7cc89c..875ddd5862 100644 --- a/src/OpenConext/EngineBlock/Authentication/Model/Consent.php +++ b/src/OpenConext/EngineBlock/Authentication/Model/Consent.php @@ -109,7 +109,7 @@ public function getConsentType() * * @return array */ - public function jsonSerialize() + public function jsonSerialize(): array { return [ 'user_id' => $this->userId, diff --git a/src/OpenConext/EngineBlock/Authentication/Model/User.php b/src/OpenConext/EngineBlock/Authentication/Model/User.php index cec6db46a3..0b651074a0 100644 --- a/src/OpenConext/EngineBlock/Authentication/Model/User.php +++ b/src/OpenConext/EngineBlock/Authentication/Model/User.php @@ -61,7 +61,7 @@ public function getCollabPersonUuid() * * @return array */ - public function jsonSerialize() + public function jsonSerialize(): array { return [ 'collab_person_id' => $this->getCollabPersonId()->getCollabPersonId(), diff --git a/src/OpenConext/EngineBlock/Authentication/Value/ConsentType.php b/src/OpenConext/EngineBlock/Authentication/Value/ConsentType.php index adb448b512..7896d835dd 100644 --- a/src/OpenConext/EngineBlock/Authentication/Value/ConsentType.php +++ b/src/OpenConext/EngineBlock/Authentication/Value/ConsentType.php @@ -76,7 +76,7 @@ public function equals(ConsentType $other) /** * @return string */ - public function jsonSerialize() + public function jsonSerialize(): mixed { return $this->consentType; } diff --git a/src/OpenConext/EngineBlock/Driver/File/FilesystemAdapter.php b/src/OpenConext/EngineBlock/Driver/File/FilesystemAdapter.php index 9684d23e07..3240370716 100644 --- a/src/OpenConext/EngineBlock/Driver/File/FilesystemAdapter.php +++ b/src/OpenConext/EngineBlock/Driver/File/FilesystemAdapter.php @@ -44,7 +44,7 @@ public function writeTo($data, $filePath) $this->filesystem->dumpFile($filePath, $data); } catch (IOException $exception) { $newMessage = sprintf('Could not write data to file "%s": "%s"', $filePath, $exception->getMessage()); - throw new RuntimeException($newMessage, null, $exception); + throw new RuntimeException($newMessage, 0, $exception); } } diff --git a/src/OpenConext/EngineBlock/Exception/InvalidArgumentException.php b/src/OpenConext/EngineBlock/Exception/InvalidArgumentException.php index 7e48a4eba9..907dd1260c 100644 --- a/src/OpenConext/EngineBlock/Exception/InvalidArgumentException.php +++ b/src/OpenConext/EngineBlock/Exception/InvalidArgumentException.php @@ -22,11 +22,8 @@ class InvalidArgumentException extends InvalidAssertionException implements Exception { - // according to CS used, propertypath and value should be switched, but that breaks the integration with the library - // @codingStandardsIgnoreStart - public function __construct($message, $code, $propertyPath = null, $value, array $constraints = []) + public function __construct($message, $code, $propertyPath = null, $value = null, array $constraints = []) { - // @codingStandardsIgnoreEnd if ($propertyPath !== null && strpos($message, $propertyPath) === false) { $message = sprintf('Invalid argument given for "%s": %s', $propertyPath, $message); } diff --git a/src/OpenConext/EngineBlock/Logger/AuthenticationLogger.php b/src/OpenConext/EngineBlock/Logger/AuthenticationLogger.php index a235271ad0..65daba576e 100644 --- a/src/OpenConext/EngineBlock/Logger/AuthenticationLogger.php +++ b/src/OpenConext/EngineBlock/Logger/AuthenticationLogger.php @@ -102,9 +102,6 @@ function (Entity $entity) { */ private function generateTimestamp() { - $microTime = microtime(true); - $microseconds = sprintf("%06d", ($microTime - floor($microTime)) * 1000000); - $timestamp = new DateTime(date('Y-m-d H:i:s.' . $microseconds, $microTime)); - return $timestamp->format('Y-m-d\TH:i:s.uP'); + return (new DateTime())->format('Y-m-d\TH:i:s.uP'); } } diff --git a/src/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatter.php b/src/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatter.php index 3117f4d885..fe3cc5d12e 100644 --- a/src/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatter.php +++ b/src/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatter.php @@ -34,12 +34,12 @@ public function __construct(FormatterInterface $formatter) $this->formatter = $formatter; } - public function format(array $record) + public function format(array $record): mixed { return $this->formatter->format($this->addAdditionalInfoForEngineBlockExceptions($record)); } - public function formatBatch(array $records) + public function formatBatch(array $records): mixed { foreach ($records as &$value) { $value = $this->addAdditionalInfoForEngineBlockExceptions($value); diff --git a/src/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrDecoratedActivationStrategy.php b/src/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrDecoratedActivationStrategy.php index 735a0ccb0b..e7d521cf13 100644 --- a/src/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrDecoratedActivationStrategy.php +++ b/src/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrDecoratedActivationStrategy.php @@ -42,7 +42,7 @@ public function activate() $this->wasManuallyActivated = true; } - public function isHandlerActivated(array $record) + public function isHandlerActivated(array $record): bool { return $this->wasManuallyActivated || $this->decoratedStrategy->isHandlerActivated($record); } diff --git a/src/OpenConext/EngineBlock/Metadata/ConsentSettings.php b/src/OpenConext/EngineBlock/Metadata/ConsentSettings.php index 64ea7bf4ac..cc1c8c95f4 100644 --- a/src/OpenConext/EngineBlock/Metadata/ConsentSettings.php +++ b/src/OpenConext/EngineBlock/Metadata/ConsentSettings.php @@ -162,7 +162,7 @@ private function findSettingsFor($entityId) /** * @return array */ - public function jsonSerialize() + public function jsonSerialize(): mixed { return $this->settings; } diff --git a/src/OpenConext/EngineBlock/Metadata/Discovery.php b/src/OpenConext/EngineBlock/Metadata/Discovery.php index a13bd42db1..7053e1634a 100644 --- a/src/OpenConext/EngineBlock/Metadata/Discovery.php +++ b/src/OpenConext/EngineBlock/Metadata/Discovery.php @@ -81,7 +81,7 @@ private static function assertLocaleValueArray(array $array): void } } - public function jsonSerialize() + public function jsonSerialize(): mixed { return [ 'names' => $this->names, diff --git a/src/OpenConext/EngineBlock/Metadata/Entity/AbstractRole.php b/src/OpenConext/EngineBlock/Metadata/Entity/AbstractRole.php index 3a22868797..05187a3253 100644 --- a/src/OpenConext/EngineBlock/Metadata/Entity/AbstractRole.php +++ b/src/OpenConext/EngineBlock/Metadata/Entity/AbstractRole.php @@ -37,37 +37,19 @@ * @package OpenConext\EngineBlock\Metadata\Entity * @SuppressWarnings(PHPMD.TooManyFields) * - * @ORM\Entity - * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT") - * @ORM\Table( - * name="sso_provider_roles_eb5", - * uniqueConstraints={ - * @ORM\UniqueConstraint( - * name="idx_sso_provider_roles_entity_id_type", - * columns={"type", "entity_id"} - * ) - * }, - * indexes={ - * @ORM\Index( - * name="idx_sso_provider_roles_type", - * columns={"type"} - * ), - * @ORM\Index( - * name="idx_sso_provider_roles_entity_id", - * columns={"entity_id"} - * ), - * } - * ) - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="type", type="string") - * @ORM\DiscriminatorMap({ - * "sp" = "OpenConext\EngineBlock\Metadata\Entity\ServiceProvider", - * "idp" = "OpenConext\EngineBlock\Metadata\Entity\IdentityProvider" - * }) * * @SuppressWarnings(PHPMD.UnusedPrivateField) * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ +#[ORM\Entity] +#[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'type', type: 'string')] +#[ORM\DiscriminatorMap(['sp' => ServiceProvider::class, 'idp' => IdentityProvider::class])] +#[ORM\Table(name: 'sso_provider_roles_eb5')] +#[ORM\Index(name: 'idx_sso_provider_roles_type', columns: ['type'])] +#[ORM\Index(name: 'idx_sso_provider_roles_entity_id', columns: ['entity_id'])] +#[ORM\UniqueConstraint(name: 'idx_sso_provider_roles_entity_id_type', columns: ['type', 'entity_id'])] abstract class AbstractRole { const WORKFLOW_STATE_PROD = 'prodaccepted'; @@ -76,199 +58,182 @@ abstract class AbstractRole /** * @var int - * - * @ORM\Id - * @ORM\Column(name="id", type="integer") - * @ORM\GeneratedValue(strategy="AUTO") */ - public $id; + #[ORM\Id] + #[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] + public ?int $id = null; /** * @var string - * - * @ORM\Column(name="entity_id", type="string") */ - public $entityId; + #[ORM\Column(name: 'entity_id', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $entityId = null; /** * @var string - * @ORM\Column(name="name_nl", type="string") */ - public $nameNl; + #[ORM\Column(name: 'name_nl', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $nameNl = null; /** * @var string - * - * @ORM\Column(name="name_en", type="string") */ - public $nameEn; + #[ORM\Column(name: 'name_en', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $nameEn = null; /** * @var string - * - * @ORM\Column(name="name_pt", type="string") */ - public $namePt; + #[ORM\Column(name: 'name_pt', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $namePt = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="description_nl", type="string") */ - public $descriptionNl; + #[ORM\Column(name: 'description_nl', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $descriptionNl = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="description_en", type="string") */ - public $descriptionEn; + #[ORM\Column(name: 'description_en', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $descriptionEn = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="description_pt", type="string") */ - public $descriptionPt; + #[ORM\Column(name: 'description_pt', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $descriptionPt = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="display_name_nl", type="string") */ - public $displayNameNl; + #[ORM\Column(name: 'display_name_nl', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $displayNameNl = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="display_name_en", type="string") */ - public $displayNameEn; + #[ORM\Column(name: 'display_name_en', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $displayNameEn = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="display_name_pt", type="string") */ - public $displayNamePt; + #[ORM\Column(name: 'display_name_pt', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $displayNamePt = null; /** * @var Logo * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="logo", type="object") */ + #[ORM\Column(name: 'logo', type: \Doctrine\DBAL\Types\Types::OBJECT)] public $logo; /** * @var Organization - * - * @ORM\Column(name="organization_nl_name",type="object", nullable=true, length=65535) */ + #[ORM\Column(name: 'organization_nl_name', type: \Doctrine\DBAL\Types\Types::OBJECT, nullable: true, length: 65535)] public $organizationNl; /** * @var Organization - * - * @ORM\Column(name="organization_en_name",type="object", nullable=true, length=65535) */ + #[ORM\Column(name: 'organization_en_name', type: \Doctrine\DBAL\Types\Types::OBJECT, nullable: true, length: 65535)] public $organizationEn; /** * @var Organization - * - * @ORM\Column(name="organization_pt_name",type="object", nullable=true, length=65535) */ + #[ORM\Column(name: 'organization_pt_name', type: \Doctrine\DBAL\Types\Types::OBJECT, nullable: true, length: 65535)] public $organizationPt; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="keywords_nl", type="string") */ - public $keywordsNl; + #[ORM\Column(name: 'keywords_nl', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $keywordsNl = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="keywords_en", type="string") */ - public $keywordsEn; + #[ORM\Column(name: 'keywords_en', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $keywordsEn = null; /** * @var string * @deprecated Will be removed in favour of using the Mdui value object, use the getter for this field instead - * @ORM\Column(name="keywords_pt", type="string") */ - public $keywordsPt; + #[ORM\Column(name: 'keywords_pt', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $keywordsPt = null; /** * @var X509Certificate[] - * - * @ORM\Column(name="certificates", type="array", length=65535) */ + #[ORM\Column(name: 'certificates', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $certificates = array(); /** * @var string - * - * @ORM\Column(name="workflow_state", type="string") */ - public $workflowState = self::WORKFLOW_STATE_DEFAULT; + #[ORM\Column(name: 'workflow_state', type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $workflowState = self::WORKFLOW_STATE_DEFAULT; /** * @var ContactPerson[] - * - * @ORM\Column(name="contact_persons", type="array", length=65535) */ + #[ORM\Column(name: 'contact_persons', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $contactPersons; /** * @var string - * - * @ORM\Column(name="name_id_format", type="string", nullable=true) */ - public $nameIdFormat; + #[ORM\Column(name: 'name_id_format', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] + public ?string $nameIdFormat = null; /** * @var string[] - * - * @ORM\Column(name="name_id_formats", type="array", length=65535) */ + #[ORM\Column(name: 'name_id_formats', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $supportedNameIdFormats; /** * @var Service - * - * @ORM\Column(name="single_logout_service", type="object", nullable=true, length=65535) */ + #[ORM\Column(name: 'single_logout_service', type: \Doctrine\DBAL\Types\Types::OBJECT, nullable: true, length: 65535)] public $singleLogoutService; /** * @var bool - * - * @ORM\Column(name="requests_must_be_signed", type="boolean") */ - public $requestsMustBeSigned = false; + #[ORM\Column(name: 'requests_must_be_signed', type: \Doctrine\DBAL\Types\Types::BOOLEAN)] + public ?bool $requestsMustBeSigned = false; /** * @var string - * - * @ORM\Column(name="manipulation", type="text", length=65535) */ - public $manipulation; + #[ORM\Column(name: 'manipulation', type: \Doctrine\DBAL\Types\Types::TEXT, length: 65535)] + public ?string $manipulation = null; /** * @var Coins - * - * @ORM\Column(name="coins", type="engineblock_metadata_coins") */ + #[ORM\Column(name: 'coins', type: 'engineblock_metadata_coins')] protected $coins = array(); /** * @var Mdui - * - * @ORM\Column(name="mdui", type="engineblock_metadata_mdui") */ + #[ORM\Column(name: 'mdui', type: 'engineblock_metadata_mdui')] protected $mdui; public function __construct( diff --git a/src/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssembler.php b/src/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssembler.php index d6764250f4..f5cffab3ff 100644 --- a/src/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssembler.php +++ b/src/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssembler.php @@ -104,7 +104,7 @@ function ($allowedConnection) { ); } - if ($connection->allow_all_entities) { + if (isset($connection->allow_all_entities) && $connection->allow_all_entities) { $spAllowedEntityIds[$role->entityId] = true; } } @@ -121,7 +121,7 @@ function ($allowedConnection) { ); } - if ($connection->allow_all_entities) { + if (isset($connection->allow_all_entities) && $connection->allow_all_entities) { $idpAllowedEntityIds[$role->entityId] = true; } } @@ -136,9 +136,12 @@ function ($allowedConnection) { } // Get the IdPs that are allowed for this SP. - $allowedIdpEntityIds = $spAllowedEntityIds[$role->entityId]; - if ($allowedIdpEntityIds === true) { - $allowedIdpEntityIds = $allIdpEntityIds; + $allowedIdpEntityIds = null; + if (isset($spAllowedEntityIds[$role->entityId])) { + $allowedIdpEntityIds = $spAllowedEntityIds[$role->entityId]; + if ($allowedIdpEntityIds === true) { + $allowedIdpEntityIds = $allIdpEntityIds; + } } // Strip out the IdPs that disallow the SP @@ -535,7 +538,9 @@ private function assembleStepupConnections(stdClass $connection) $connections = []; foreach ($connection->stepup_connections as $sp) { - $connections[(string)$sp->name] = (string)$sp->level; + if (isset($sp->name, $sp->level)) { + $connections[(string)$sp->name] = (string)$sp->level; + } } return array( diff --git a/src/OpenConext/EngineBlock/Metadata/Entity/IdentityProvider.php b/src/OpenConext/EngineBlock/Metadata/Entity/IdentityProvider.php index 3d23c9b850..cb5ed5daca 100644 --- a/src/OpenConext/EngineBlock/Metadata/Entity/IdentityProvider.php +++ b/src/OpenConext/EngineBlock/Metadata/Entity/IdentityProvider.php @@ -37,7 +37,6 @@ /** * @package OpenConext\EngineBlock\Metadata\Entity - * @ORM\Entity * @SuppressWarnings(PHPMD.CamelCasePropertyName) * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -45,6 +44,7 @@ * WARNING: Please don't use this entity directly but use the dedicated factory instead. * @see \OpenConext\EngineBlock\Factory\Factory\IdentityProviderFactory */ +#[ORM\Entity] class IdentityProvider extends AbstractRole { const GUEST_QUALIFIER_ALL = 'All'; @@ -64,37 +64,32 @@ class IdentityProvider extends AbstractRole /** * @var bool - * - * @ORM\Column(name="enabled_in_wayf", type="boolean") */ - public $enabledInWayf = true; + #[ORM\Column(name: 'enabled_in_wayf', type: \Doctrine\DBAL\Types\Types::BOOLEAN)] + public ?bool $enabledInWayf = true; /** * @var Service[] - * - * @ORM\Column(name="single_sign_on_services", type="array", length=65535) */ + #[ORM\Column(name: 'single_sign_on_services', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $singleSignOnServices = array(); /** * @var ConsentSettings - * - * @ORM\Column(name="consent_settings", type="json_array", length=16777215) */ + #[ORM\Column(name: 'consent_settings', type: \Doctrine\DBAL\Types\Types::JSON, length: 16777215)] private $consentSettings; /** * @var ShibMdScope[] - * - * @ORM\Column(name="shib_md_scopes", type="array", length=65535) */ + #[ORM\Column(name: 'shib_md_scopes', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $shibMdScopes = array(); /** * @var array - * - * @ORM\Column(name="idp_discoveries", type="json") */ + #[ORM\Column(name: 'idp_discoveries', type: \Doctrine\DBAL\Types\Types::JSON)] private $discoveries; /** @@ -284,9 +279,12 @@ private function ensureDiscoveriesDeserialized(): void foreach ($this->discoveries as $index => $discovery) { try { if (!$discovery instanceof Discovery) { - $logo = new Logo($discovery['logo']['url']); - $logo->width = $discovery['logo']['width']; - $logo->height = $discovery['logo']['height']; + $logo = null; + if (isset($discovery['logo']) && is_array($discovery['logo'])) { + $logo = new Logo($discovery['logo']['url']); + $logo->width = $discovery['logo']['width']; + $logo->height = $discovery['logo']['height']; + } $this->discoveries[$index] = Discovery::create( $discovery['names'] ?? [], @@ -308,4 +306,47 @@ private function assertAllDiscoveries(array $discoveries): void } } } + + /** + * Certificates are not available on the object after deserialisation! + * + * @return array + */ + public function __sleep() + { + return [ + 'enabledInWayf', + 'singleSignOnServices', + 'consentSettings', + 'shibMdScopes', + 'discoveries', + 'id', + 'entityId', + 'nameNl', + 'nameEn', + 'namePt', + 'descriptionNl', + 'descriptionEn', + 'descriptionPt', + 'displayNameNl', + 'displayNameEn', + 'displayNamePt', + 'logo', + 'organizationNl', + 'organizationEn', + 'organizationPt', + 'keywordsNl', + 'keywordsEn', + 'keywordsPt', + 'workflowState', + 'contactPersons', + 'nameIdFormat', + 'supportedNameIdFormats', + 'singleLogoutService', + 'requestsMustBeSigned', + 'manipulation', + 'coins', + 'mdui', + ]; + } } diff --git a/src/OpenConext/EngineBlock/Metadata/Entity/ServiceProvider.php b/src/OpenConext/EngineBlock/Metadata/Entity/ServiceProvider.php index 7be6d2fe4f..e78e2ed3a5 100644 --- a/src/OpenConext/EngineBlock/Metadata/Entity/ServiceProvider.php +++ b/src/OpenConext/EngineBlock/Metadata/Entity/ServiceProvider.php @@ -34,7 +34,6 @@ /** * @package OpenConext\EngineBlock\Metadata\Entity - * @ORM\Entity * @SuppressWarnings(PHPMD.TooManyMethods) * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -43,63 +42,56 @@ * WARNING: Please don't use this entity directly but use the dedicated factory instead. * @see \OpenConext\EngineBlock\Factory\Factory\ServiceProviderFactory */ +#[ORM\Entity] class ServiceProvider extends AbstractRole { /** * @var null|AttributeReleasePolicy - * - * @ORM\Column(name="attribute_release_policy", type="array", length=65535) */ + #[ORM\Column(name: 'attribute_release_policy', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $attributeReleasePolicy; /** * @var IndexedService[] - * - * @ORM\Column(name="assertion_consumer_services", type="array", length=65535) */ + #[ORM\Column(name: 'assertion_consumer_services', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $assertionConsumerServices; /** * @var string[] - * - * @ORM\Column(name="allowed_idp_entity_ids", type="array", length=6777215) */ + #[ORM\Column(name: 'allowed_idp_entity_ids', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 6777215)] public $allowedIdpEntityIds; /** * @var bool - * - * @ORM\Column(name="allow_all", type="boolean") */ - public $allowAll; + #[ORM\Column(name: 'allow_all', type: \Doctrine\DBAL\Types\Types::BOOLEAN)] + public ?bool $allowAll = null; /** * @var null|RequestedAttribute[] - * - * @ORM\Column(name="requested_attributes", type="array", length=65535) */ + #[ORM\Column(name: 'requested_attributes', type: \Doctrine\DBAL\Types\Types::ARRAY, length: 65535)] public $requestedAttributes; /** * @var null|string - * - * @ORM\Column(name="support_url_en", type="string", nullable=true) */ - public $supportUrlEn; + #[ORM\Column(name: 'support_url_en', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] + public ?string $supportUrlEn = null; /** * @var null|string - * - * @ORM\Column(name="support_url_nl", type="string", nullable=true) */ - public $supportUrlNl; + #[ORM\Column(name: 'support_url_nl', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] + public ?string $supportUrlNl = null; /** * @var null|string - * - * @ORM\Column(name="support_url_pt", type="string", nullable=true) */ - public $supportUrlPt; + #[ORM\Column(name: 'support_url_pt', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] + public ?string $supportUrlPt = null; /** * WARNING: Please don't use this entity directly but use the dedicated factory instead. @@ -309,7 +301,11 @@ public function getDisplayName(string $preferredLocale = 'en'): string $preferredName = $this->mdui->getDisplayName($preferredLocale); $fallback = 'name' . ucfirst($preferredLocale); - $spName = $preferredName !== '' ? $preferredName : $this->$fallback; + if ($preferredName !== '') { + $spName = $preferredName; + } elseif (isset($this->$fallback)) { + $spName = $this->$fallback; + } if ($preferredLocale !== 'en' & empty($spName)) { $englishDisplayName = $this->mdui->getDisplayName('en'); @@ -335,12 +331,14 @@ public function getOrganizationName(string $preferredLocale = 'en'): string { $orgLocale = 'organization' . ucfirst($preferredLocale); // Load the preferred locale org. display name, falling back on org. name - $orgName = !empty($this->$orgLocale->displayName) - ? $this->$orgLocale->displayName - : $this->$orgLocale->name; + if (isset($this->$orgLocale)) { + $orgName = !empty($this->$orgLocale->displayName) + ? $this->$orgLocale->displayName + : $this->$orgLocale->name; + } // Fallback to EN naming preferences when the preferred locale was not set or yielded no value - if (($preferredLocale !== 'en' && empty($orgName)) || empty($orgName)) { + if ((($preferredLocale !== 'en' && empty($orgName)) || empty($orgName)) && isset($this->organizationEn)) { $orgName = !empty($this->organizationEn->displayName) ? $this->organizationEn->displayName : $this->organizationEn->name; } @@ -365,4 +363,50 @@ public function isAttributeAggregationRequired() return count($rules) > 0; } + + /** + * Certificates are not available on the object after deserialisation! + * + * @return array + */ + public function __sleep() + { + return [ + 'attributeReleasePolicy', + 'assertionConsumerServices', + 'allowedIdpEntityIds', + 'allowAll', + 'requestedAttributes', + 'supportUrlEn', + 'supportUrlNl', + 'supportUrlPt', + 'id', + 'entityId', + 'nameNl', + 'nameEn', + 'namePt', + 'descriptionNl', + 'descriptionEn', + 'descriptionPt', + 'displayNameNl', + 'displayNameEn', + 'displayNamePt', + 'logo', + 'organizationNl', + 'organizationEn', + 'organizationPt', + 'keywordsNl', + 'keywordsEn', + 'keywordsPt', + 'workflowState', + 'contactPersons', + 'nameIdFormat', + 'supportedNameIdFormats', + 'singleLogoutService', + 'requestsMustBeSigned', + 'manipulation', + 'coins', + 'mdui', + ]; + } } diff --git a/src/OpenConext/EngineBlock/Metadata/Factory/Collection/IdentityProviderEntityCollection.php b/src/OpenConext/EngineBlock/Metadata/Factory/Collection/IdentityProviderEntityCollection.php index 26ed8d1dc1..639430576f 100644 --- a/src/OpenConext/EngineBlock/Metadata/Factory/Collection/IdentityProviderEntityCollection.php +++ b/src/OpenConext/EngineBlock/Metadata/Factory/Collection/IdentityProviderEntityCollection.php @@ -40,7 +40,7 @@ public function get(string $entityId) : IdentityProviderEntityInterface return $this->map[$entityId]; } - public function getIterator() + public function getIterator(): ArrayIterator { return new ArrayIterator($this->map); } diff --git a/src/OpenConext/EngineBlock/Metadata/Factory/MduiPushAssemblerFactory.php b/src/OpenConext/EngineBlock/Metadata/Factory/MduiPushAssemblerFactory.php index 0a62875163..5717d072c3 100644 --- a/src/OpenConext/EngineBlock/Metadata/Factory/MduiPushAssemblerFactory.php +++ b/src/OpenConext/EngineBlock/Metadata/Factory/MduiPushAssemblerFactory.php @@ -36,21 +36,21 @@ public static function buildFrom(array $properties, stdClass $connection): Mdui { $displayNameElement = self::assembleElement( 'DisplayName', - $properties['displayNameEn'], - $properties['displayNameNl'], - $properties['displayNamePt'] + $properties['displayNameEn'] ?? null, + $properties['displayNameNl'] ?? null, + $properties['displayNamePt'] ?? null ); $descriptionElement = self::assembleElement( 'Description', - $properties['descriptionEn'], - $properties['descriptionNl'], - $properties['descriptionPt'] + $properties['descriptionEn'] ?? null, + $properties['descriptionNl'] ?? null, + $properties['descriptionPt'] ?? null ); $keywordsElement = self::assembleElement( 'Keywords', - $properties['keywordsEn'], - $properties['keywordsNl'], - $properties['keywordsPt'] + $properties['keywordsEn'] ?? null, + $properties['keywordsNl'] ?? null, + $properties['keywordsPt'] ?? null ); $privacyStatementUrlElement = self::assemblePrivacyStatement($connection); diff --git a/src/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfiguration.php b/src/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfiguration.php index b6c43a0bb8..f5cb677e83 100644 --- a/src/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfiguration.php +++ b/src/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfiguration.php @@ -76,7 +76,7 @@ class EngineBlockConfiguration private $contactPersons; public function __construct( - TranslatorInterface $translator, + \Symfony\Contracts\Translation\TranslatorInterface $translator, string $supportMail, string $description, string $engineHostName, diff --git a/src/OpenConext/EngineBlock/Metadata/Logo.php b/src/OpenConext/EngineBlock/Metadata/Logo.php index c18b5bb5d1..3bf21c1426 100644 --- a/src/OpenConext/EngineBlock/Metadata/Logo.php +++ b/src/OpenConext/EngineBlock/Metadata/Logo.php @@ -66,7 +66,7 @@ public function translate(string $language): MultilingualValue throw new MduiRuntimeException('We do not implement the Mdui Logo in a multilingual fashion'); } - public function jsonSerialize() + public function jsonSerialize(): mixed { return [ 'name' => $this->getName(), diff --git a/src/OpenConext/EngineBlock/Metadata/Mdui.php b/src/OpenConext/EngineBlock/Metadata/Mdui.php index 08ac3c2b55..95569187bf 100644 --- a/src/OpenConext/EngineBlock/Metadata/Mdui.php +++ b/src/OpenConext/EngineBlock/Metadata/Mdui.php @@ -163,7 +163,7 @@ public function getLanguagesByElementName(string $elementName): array public function hasDisplayName(string $language): bool { /** @var MultilingualElement $displayName */ - $displayName = $this->values['DisplayName']; + $displayName = $this->values['DisplayName'] ?? null; if (!$displayName || $displayName instanceof EmptyMduiElement) { return false; } diff --git a/src/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepository.php b/src/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepository.php index c3c7b60775..d26c4c12d6 100644 --- a/src/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepository.php +++ b/src/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepository.php @@ -67,7 +67,7 @@ public function __construct(DoctrineMetadataRepository $repository) */ public function invoke($name, array $args) { - $signature = $name . ':' . serialize($args); + $signature = $name . ':' . json_encode($args); if (!isset($this->cache[$signature])) { $this->cache[$signature] = call_user_func_array(array($this->repository, $name), $args); diff --git a/src/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataPushRepository.php b/src/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataPushRepository.php index 8308b62e4f..d3bca9fdf3 100644 --- a/src/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataPushRepository.php +++ b/src/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataPushRepository.php @@ -80,7 +80,7 @@ public function synchronize(array $roles) { $result = new SynchronizationResult(); - $this->connection->transactional(function () use ($roles, $result) { + $this->connection->transactional(function () use ($roles, $result): void { $idpsToBeRemoved = $this->findAllRoleEntityIds($this->idpMetadata); $spsToBeRemoved = $this->findAllRoleEntityIds($this->spMetadata); @@ -154,7 +154,7 @@ private function insertRole(AbstractRole $role, ClassMetadata $metadata) $stmt = $this->connection->prepare($query->getSQL()); $this->bindParameters($normalized, $stmt); - $stmt->execute(); + $stmt->executeQuery(); } private function updateRole(AbstractRole $role, ClassMetadata $metadata) @@ -166,7 +166,7 @@ private function updateRole(AbstractRole $role, ClassMetadata $metadata) $stmt = $this->connection->prepare($query->getSQL()); $this->bindParameters($normalized, $stmt); - $stmt->execute(); + $stmt->executeQuery(); } private function deleteRolesByIds(array $roles, ClassMetadata $metadata) @@ -174,11 +174,11 @@ private function deleteRolesByIds(array $roles, ClassMetadata $metadata) $query = $this->connection->createQueryBuilder() ->delete(self::ROLES_TABLE_NAME) ->where('id IN (:ids)') - ->setParameter('ids', $roles, Connection::PARAM_INT_ARRAY); + ->setParameter('ids', $roles, \Doctrine\DBAL\ArrayParameterType::INTEGER); $this->addDiscriminatorQuery($query, $metadata); - $result = $query->execute(); + $result = $query->executeStatement(); return $result; } @@ -188,13 +188,16 @@ private function findAllRoleEntityIds(ClassMetadata $metadata) ->select('id, entity_id') ->from(self::ROLES_TABLE_NAME); + assert($query instanceof QueryBuilder); $this->addDiscriminatorQuery($query, $metadata); - $result = $query->execute(); + $result = $query->executeQuery(); + $results = []; - foreach ($result->fetchAll() as $record) { + foreach ($result->fetchAllAssociative() as $record) { $results[$record['id']] = $record['entity_id']; } + return $results; } @@ -229,26 +232,26 @@ private function bindParameters($normalized, Statement $statement) private function addDiscriminatorQuery(QueryBuilder $queryBuilder, ClassMetadata $metadata) { - $queryBuilder->andWhere(sprintf('%s = :%s', $metadata->discriminatorColumn['fieldName'], $metadata->discriminatorColumn['name'])) - ->setParameter($metadata->discriminatorColumn['name'], $metadata->discriminatorValue, $metadata->discriminatorColumn['type']); + $queryBuilder->andWhere(sprintf('%s = :%s', $metadata->discriminatorColumn->fieldName, $metadata->discriminatorColumn->name)) + ->setParameter($metadata->discriminatorColumn->name, $metadata->discriminatorValue, $metadata->discriminatorColumn->type); } private function normalizeData(AbstractRole $role, ClassMetadata $metadata) { $result = []; foreach ($metadata->fieldMappings as $id => $columnInfo) { - $result[$columnInfo['columnName']] = [ - self::FIELD_VALUE => $metadata->reflFields[$id]->getValue($role), - self::FIELD_TYPE => $columnInfo['type'], + $result[$columnInfo->columnName] = [ + self::FIELD_VALUE => $metadata->propertyAccessors[$id]->getValue($role), + self::FIELD_TYPE => $columnInfo->type, ]; } // The primary id field is autogenerated and should not be added to the SQL statement. unset($result["id"]); - $result[$metadata->discriminatorColumn['name']] = [ + $result[$metadata->discriminatorColumn->name] = [ self::FIELD_VALUE => $metadata->discriminatorValue, - self::FIELD_TYPE => $metadata->discriminatorColumn['type'], + self::FIELD_TYPE => $metadata->discriminatorColumn->type, ]; return $result; diff --git a/src/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveDisallowedIdentityProvidersFilter.php b/src/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveDisallowedIdentityProvidersFilter.php index a22eb1603d..933a85002d 100644 --- a/src/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveDisallowedIdentityProvidersFilter.php +++ b/src/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveDisallowedIdentityProvidersFilter.php @@ -75,7 +75,7 @@ public function filterRole(AbstractRole $role, LoggerInterface $logger = null) */ public function toQueryBuilder(QueryBuilder $queryBuilder, $repositoryClassName) { - if ($repositoryClassName !== 'OpenConext\EngineBlock\Metadata\Entity\IdentityProvider') { + if ($repositoryClassName !== \OpenConext\EngineBlock\Metadata\Entity\IdentityProvider::class) { return null; } diff --git a/src/OpenConext/EngineBlock/Metadata/StepupConnections.php b/src/OpenConext/EngineBlock/Metadata/StepupConnections.php index e42d5f5a9e..162eb88619 100644 --- a/src/OpenConext/EngineBlock/Metadata/StepupConnections.php +++ b/src/OpenConext/EngineBlock/Metadata/StepupConnections.php @@ -65,7 +65,7 @@ public function getLoa($entityId) return $this->connections[$entityId]; } - public function jsonSerialize() + public function jsonSerialize(): mixed { return $this->connections; } diff --git a/src/OpenConext/EngineBlock/Metadata/X509/X509PrivateKey.php b/src/OpenConext/EngineBlock/Metadata/X509/X509PrivateKey.php index 58df7a4b9d..b6627a068e 100644 --- a/src/OpenConext/EngineBlock/Metadata/X509/X509PrivateKey.php +++ b/src/OpenConext/EngineBlock/Metadata/X509/X509PrivateKey.php @@ -82,8 +82,6 @@ public function sign($data) $signature = null; openssl_sign($data, $signature, $privateKeyResource); - openssl_free_key($privateKeyResource); - return $signature; } } diff --git a/src/OpenConext/EngineBlock/Service/AuthenticationStateHelper.php b/src/OpenConext/EngineBlock/Service/AuthenticationStateHelper.php index 2e634b3db0..aea65ee164 100644 --- a/src/OpenConext/EngineBlock/Service/AuthenticationStateHelper.php +++ b/src/OpenConext/EngineBlock/Service/AuthenticationStateHelper.php @@ -19,6 +19,7 @@ namespace OpenConext\EngineBlock\Service; use OpenConext\EngineBlockBundle\Authentication\AuthenticationStateInterface; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\SessionInterface; class AuthenticationStateHelper implements AuthenticationStateHelperInterface @@ -28,9 +29,9 @@ class AuthenticationStateHelper implements AuthenticationStateHelperInterface */ private $session; - public function __construct(SessionInterface $session) + public function __construct(RequestStack $requestStack) { - $this->session = $session; + $this->session = $requestStack->getSession(); } /** diff --git a/src/OpenConext/EngineBlock/Service/ProcessingStateHelper.php b/src/OpenConext/EngineBlock/Service/ProcessingStateHelper.php index 14c7d07973..9e0d31929e 100644 --- a/src/OpenConext/EngineBlock/Service/ProcessingStateHelper.php +++ b/src/OpenConext/EngineBlock/Service/ProcessingStateHelper.php @@ -23,6 +23,7 @@ use EngineBlock_Saml2_ResponseAnnotationDecorator; use OpenConext\EngineBlock\Metadata\Entity\AbstractRole; use OpenConext\EngineBlock\Service\Dto\ProcessingStateStep; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\SessionInterface; class ProcessingStateHelper implements ProcessingStateHelperInterface @@ -35,9 +36,9 @@ class ProcessingStateHelper implements ProcessingStateHelperInterface */ private $session; - public function __construct(SessionInterface $session) + public function __construct(RequestStack $requestStack) { - $this->session = $session; + $this->session = $requestStack->getSession(); } /** diff --git a/src/OpenConext/EngineBlock/Service/RequestAccessMailer.php b/src/OpenConext/EngineBlock/Service/RequestAccessMailer.php index 9eefed4a4a..11b0f38fae 100644 --- a/src/OpenConext/EngineBlock/Service/RequestAccessMailer.php +++ b/src/OpenConext/EngineBlock/Service/RequestAccessMailer.php @@ -18,8 +18,8 @@ namespace OpenConext\EngineBlock\Service; -use Swift_Mailer; -use Swift_Message; +use Symfony\Component\Mailer\MailerInterface; +use Symfony\Component\Mime\Email; class RequestAccessMailer { @@ -46,10 +46,7 @@ class RequestAccessMailer TPL; - /** - * @var Swift_Mailer - */ - private $mailer; + private MailerInterface $mailer; /** * @var string @@ -57,10 +54,9 @@ class RequestAccessMailer private $requestAccessEmailAddress; /** - * @param Swift_Mailer $mailer * @param string $requestAccessEmailAddress */ - public function __construct(Swift_Mailer $mailer, $requestAccessEmailAddress) + public function __construct(MailerInterface $mailer, $requestAccessEmailAddress) { $this->mailer = $mailer; $this->requestAccessEmailAddress = $requestAccessEmailAddress; @@ -93,12 +89,12 @@ public function sendRequestAccessEmailForIdp($spName, $spEntityId, $institution, // We use the destination email address also as a From since we do // not have a better generic sender address available currently. - $message = new Swift_Message(); + $message = new Email(); $message - ->setSubject($subject) - ->setFrom($this->requestAccessEmailAddress) - ->setTo($this->requestAccessEmailAddress) - ->setBody($body, 'text/plain'); + ->subject($subject) + ->from($this->requestAccessEmailAddress) + ->to($this->requestAccessEmailAddress) + ->text($body); $this->mailer->send($message); } @@ -126,12 +122,12 @@ public function sendRequestAccessEmailForInstitution($spName, $spEntityId, $inst $comment ); - $message = new Swift_Message(); + $message = new Email(); $message - ->setSubject($subject) - ->setFrom($this->requestAccessEmailAddress) - ->setTo($this->requestAccessEmailAddress) - ->setBody($body, 'text/plain'); + ->subject($subject) + ->from($this->requestAccessEmailAddress) + ->to($this->requestAccessEmailAddress) + ->text($body); $this->mailer->send($message); diff --git a/src/OpenConext/EngineBlock/Service/SsoSessionService.php b/src/OpenConext/EngineBlock/Service/SsoSessionService.php index d0128f30d4..7c99062b1d 100644 --- a/src/OpenConext/EngineBlock/Service/SsoSessionService.php +++ b/src/OpenConext/EngineBlock/Service/SsoSessionService.php @@ -120,7 +120,7 @@ public function clearSsoSessionCookie(): void private function createSsoSessionCookie(ParameterBag $cookies, string $issuer): string { - $ssoSession = json_decode($this->getSsoCookie($cookies)); + $ssoSession = json_decode($this->getSsoCookie($cookies) ?? ''); if (!is_array($ssoSession)) { $ssoSession = []; diff --git a/src/OpenConext/EngineBlock/Stepup/StepupDecision.php b/src/OpenConext/EngineBlock/Stepup/StepupDecision.php index 87821745a6..b446b41364 100644 --- a/src/OpenConext/EngineBlock/Stepup/StepupDecision.php +++ b/src/OpenConext/EngineBlock/Stepup/StepupDecision.php @@ -141,7 +141,7 @@ public function getStepupLoa(): ?Loa return $l->getIdentifier(); }, $this->authnRequestLoas), 'metadata_sp' => $this->spLoa ? [$this->spLoa->getIdentifier()] : [], - 'metadata_idp' => $this->idppLoa ? [$this->idpLoa->getIdentifier()] : [], + 'metadata_idp' => $this->idpLoa ? [$this->idpLoa->getIdentifier()] : [], ]; $this->logger->info(sprintf('StepupDecision: requiring LoA %s', $highestLevel->getIdentifier()), $logData); return $highestLevel; diff --git a/src/OpenConext/EngineBlockBridge/ErrorReporter.php b/src/OpenConext/EngineBlockBridge/ErrorReporter.php index 17da6ae3d3..6c61b62c86 100644 --- a/src/OpenConext/EngineBlockBridge/ErrorReporter.php +++ b/src/OpenConext/EngineBlockBridge/ErrorReporter.php @@ -24,6 +24,7 @@ use EngineBlock_Exception; use Exception; use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\SessionInterface; class ErrorReporter @@ -44,11 +45,11 @@ class ErrorReporter public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, LoggerInterface $logger, - SessionInterface $session + RequestStack $requestStack, ) { $this->engineBlockApplicationSingleton = $engineBlockApplicationSingleton; $this->logger = $logger; - $this->session = $session; + $this->session = $requestStack->getSession(); } /** diff --git a/src/OpenConext/EngineBlockBridge/EventListener/SetCortoTranslationsLocaleListener.php b/src/OpenConext/EngineBlockBridge/EventListener/SetCortoTranslationsLocaleListener.php index 79ebac8c84..34abf3cebb 100644 --- a/src/OpenConext/EngineBlockBridge/EventListener/SetCortoTranslationsLocaleListener.php +++ b/src/OpenConext/EngineBlockBridge/EventListener/SetCortoTranslationsLocaleListener.php @@ -36,7 +36,7 @@ final class SetCortoTranslationsLocaleListener private $localeProvider; /** - * @var TranslatorInterface + * @var \Symfony\Contracts\Translation\TranslatorInterface */ private $translator; diff --git a/src/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/Request.php b/src/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/Request.php index e10e1ba014..61befd95a5 100644 --- a/src/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/Request.php +++ b/src/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/Request.php @@ -89,7 +89,7 @@ private static function filterNonStringValuesFromAttributes($attributes) }); } - public function jsonSerialize() + public function jsonSerialize(): mixed { return [ 'userAttributes' => array_merge( diff --git a/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureList.php b/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureList.php index 2a5de64a3a..e42e114ed0 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureList.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureList.php @@ -89,7 +89,7 @@ public function contains(AuthenticationProcedure $other) return false; } - public function count() + public function count(): int { return count($this->authenticationProcedures); } diff --git a/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMap.php b/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMap.php index c13f2867a3..7156967883 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMap.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMap.php @@ -106,7 +106,7 @@ public function contains(AuthenticationProcedure $other): bool return false; } - public function count() + public function count(): int { return count($this->authenticationProcedures); } diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Entity/Consent.php b/src/OpenConext/EngineBlockBundle/Authentication/Entity/Consent.php index 9380af890b..b23788f512 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Entity/Consent.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Entity/Consent.php @@ -25,56 +25,49 @@ * Note: this entity is currently only used to configure doctrine to create * the schema on installation. The ConsentService and ConsentRepository do not * use entities. - * - * @ORM\Entity() - * @ORM\Table(indexes={ - * @ORM\Index(name="hashed_user_id", columns={"hashed_user_id"}), - * @ORM\Index(name="service_id", columns={"service_id"}), - * @ORM\Index(name="deleted_at", columns={"deleted_at"}), - * }) */ +#[ORM\Entity] +#[ORM\Index(name: 'hashed_user_id', columns: ['hashed_user_id'])] +#[ORM\Index(name: 'service_id', columns: ['service_id'])] +#[ORM\Index(name: 'deleted_at', columns: ['deleted_at'])] class Consent { /** * @var DateTime - * @ORM\Column(name="consent_date", type="datetime", nullable=false) */ - public $date; + #[ORM\Column(name: 'consent_date', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: false)] + public \DateTimeInterface $date; /** * @var string - * - * @ORM\Id - * @ORM\Column(type="string", length=80) */ - public $hashedUserId; + #[ORM\Id] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 80)] + public ?string $hashedUserId = null; /** * @var string - * - * @ORM\Id - * @ORM\Column(type="string") */ - public $serviceId; + #[ORM\Id] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] + public ?string $serviceId = null; /** * @var string - * - * @ORM\Column(type="string", length=80) */ - public $attribute; + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 80)] + public ?string $attribute = null; /** * @var string - * - * @ORM\Column(name="consent_type", type="string", nullable=true, length=20, options={"default": "explicit"}) */ - public $type; + #[ORM\Column(name: 'consent_type', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true, length: 20, options: ['default' => 'explicit'])] + public ?string $type = null; /** - * @ORM\Id * @var DateTime - * @ORM\Column(name="deleted_at", type="datetime", nullable=true, options={"default": NULL})) */ - public $deletedAt; + #[ORM\Id] + #[ORM\Column(name: 'deleted_at', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true, options: ['default' => null])] + public ?\DateTimeInterface $deletedAt = null; } diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Entity/SamlPersistentId.php b/src/OpenConext/EngineBlockBundle/Authentication/Entity/SamlPersistentId.php index 35a73e8124..d16b387a60 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Entity/SamlPersistentId.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Entity/SamlPersistentId.php @@ -18,35 +18,30 @@ namespace OpenConext\EngineBlockBundle\Authentication\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; +use OpenConext\EngineBlockBundle\Authentication\Repository\SamlPersistentIdRepository; -/** - * @ORM\Entity(repositoryClass="OpenConext\EngineBlockBundle\Authentication\Repository\SamlPersistentIdRepository") - * @ORM\Table(indexes={ - * @ORM\Index(name="user_uuid", columns={"user_uuid", "service_provider_uuid"}), - * }) - */ +#[ORM\Entity(repositoryClass: SamlPersistentIdRepository::class)] +#[ORM\Index(columns: ['user_uuid', 'service_provider_uuid'], name: 'user_uuid')] class SamlPersistentId { /** * @var string - * - * @ORM\Id - * @ORM\Column(type="string", length=40, options={"fixed": true, "comment": "SHA1 of service_provider_uuid + user_uuid"}) */ - public $persistentId; + #[ORM\Id] + #[ORM\Column(type: Types::STRING, length: 40, options: ['fixed' => true, 'comment' => 'SHA1 of service_provider_uuid + user_uuid'])] + public ?string $persistentId = null; /** * @var string - * - * @ORM\Column(type="string", length=36, options={"fixed": true}) */ - public $userUuid; + #[ORM\Column(type: Types::STRING, length: 36, options: ['fixed' => true])] + public ?string $userUuid = null; /** * @var string - * - * @ORM\Column(type="string", length=36, options={"fixed": true}) */ - public $serviceProviderUuid; + #[ORM\Column(type: Types::STRING, length: 36, options: ['fixed' => true])] + public ?string $serviceProviderUuid = null; } diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Entity/ServiceProviderUuid.php b/src/OpenConext/EngineBlockBundle/Authentication/Entity/ServiceProviderUuid.php index 43ead9e0b8..bfffd621f1 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Entity/ServiceProviderUuid.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Entity/ServiceProviderUuid.php @@ -19,31 +19,22 @@ namespace OpenConext\EngineBlockBundle\Authentication\Entity; use Doctrine\ORM\Mapping as ORM; +use OpenConext\EngineBlockBundle\Authentication\Repository\ServiceProviderUuidRepository; -/** - * @ORM\Entity(repositoryClass="OpenConext\EngineBlockBundle\Authentication\Repository\ServiceProviderUuidRepository") - * @ORM\Table(indexes={ - * @ORM\Index( - * name="service_provider_entity_id", - * columns={"service_provider_entity_id"}, - * options={"lengths" = {255}} - * ), - * }) - */ +#[ORM\Entity(repositoryClass: ServiceProviderUuidRepository::class)] +#[ORM\Index(name: 'service_provider_entity_id', columns: ['service_provider_entity_id'], options: ['lengths' => [255]])] class ServiceProviderUuid { /** * @var string - * - * @ORM\Id - * @ORM\Column(type="string", length=36, options={"fixed": true}) */ - public $uuid; + #[ORM\Id] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 36, options: ['fixed' => true])] + public ?string $uuid = null; /** * @var string - * - * @ORM\Column(type="string", length=1024) */ - public $serviceProviderEntityId; + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 1024)] + public ?string $serviceProviderEntityId = null; } diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php b/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php index fa25f5e722..747a5d97d6 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php @@ -20,26 +20,23 @@ use Doctrine\ORM\Mapping as ORM; use OpenConext\EngineBlock\Authentication\Value\CollabPersonUuid; +use OpenConext\EngineBlockBundle\Authentication\Repository\UserRepository; -/** - * @ORM\Entity(repositoryClass="OpenConext\EngineBlockBundle\Authentication\Repository\UserRepository") - * @ORM\Table(indexes={@ORM\Index(name="idx_user_uuid", columns={"uuid"})}) - */ +#[ORM\Entity(repositoryClass: UserRepository::class)] +#[ORM\Index(name: 'idx_user_uuid', columns: ['uuid'])] class User { /** * @var - * - * @ORM\Id - * @ORM\Column(type="engineblock_collab_person_id") */ + #[ORM\Id] + #[ORM\Column(type: 'engineblock_collab_person_id')] public $collabPersonId; /** * @var CollabPersonUuid * - * - * @ORM\Column(name="uuid", type="engineblock_collab_person_uuid") */ + #[ORM\Column(name: 'uuid', type: 'engineblock_collab_person_uuid')] public $collabPersonUuid; } diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Repository/DbalConsentRepository.php b/src/OpenConext/EngineBlockBundle/Authentication/Repository/DbalConsentRepository.php index 881a7dacfe..f323c5e751 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Repository/DbalConsentRepository.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Repository/DbalConsentRepository.php @@ -19,17 +19,20 @@ namespace OpenConext\EngineBlockBundle\Authentication\Repository; use DateTime; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\DBAL\Connection as DbalConnection; -use Doctrine\DBAL\DBALException; +use Doctrine\Persistence\ManagerRegistry; use OpenConext\EngineBlock\Authentication\Model\Consent; use OpenConext\EngineBlock\Authentication\Repository\ConsentRepository; use OpenConext\EngineBlock\Authentication\Value\ConsentType; use OpenConext\EngineBlock\Exception\RuntimeException; -use PDO; use Psr\Log\LoggerInterface; use function sha1; -final class DbalConsentRepository implements ConsentRepository +/** + * @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\OpenConext\EngineBlock\Authentication\Model\Consent> + */ +final class DbalConsentRepository extends ServiceEntityRepository implements ConsentRepository { /** * @var DbalConnection @@ -41,9 +44,11 @@ final class DbalConsentRepository implements ConsentRepository */ private $logger; - public function __construct(DbalConnection $connection, LoggerInterface $logger) + public function __construct(ManagerRegistry $registry, LoggerInterface $logger) { - $this->connection = $connection; + parent::__construct($registry, Consent::class); + + $this->connection = $registry->getConnection(); $this->logger = $logger; } @@ -72,8 +77,8 @@ public function findAllFor($userId) try { $statement = $this->connection->executeQuery($sql, ['hashed_user_id' => sha1($userId)]); - $rows = $statement->fetchAll(PDO::FETCH_ASSOC); - } catch (DBALException $exception) { + $rows = $statement->fetchAllAssociative(); + } catch (\Doctrine\DBAL\Exception $exception) { throw new RuntimeException('Could not fetch user consents from the database', 0, $exception); } @@ -103,7 +108,7 @@ public function deleteAllFor($userId) try { $this->connection->executeQuery($sql, ['hashed_user_id' => sha1($userId)]); $this->logger->notice(sprintf('Removed consent for hashed user id %s (%s)', sha1($userId), $userId)); - } catch (DBALException $exception) { + } catch (\Doctrine\DBAL\Exception $exception) { throw new RuntimeException( sprintf( 'Could not delete user consents from the database for user %s', @@ -149,7 +154,7 @@ public function deleteOneFor(string $userId, string $serviceProviderEntityId): b ); return $result->rowCount() > 0; - } catch (DBALException $exception) { + } catch (\Doctrine\DBAL\Exception $exception) { throw new RuntimeException( sprintf( 'Could not delete user %s consent from the database for a specific SP %s', diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Repository/SamlPersistentIdRepository.php b/src/OpenConext/EngineBlockBundle/Authentication/Repository/SamlPersistentIdRepository.php index bc2335cd7e..a54faec28f 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Repository/SamlPersistentIdRepository.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Repository/SamlPersistentIdRepository.php @@ -18,12 +18,21 @@ namespace OpenConext\EngineBlockBundle\Authentication\Repository; -use Doctrine\ORM\EntityRepository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; use OpenConext\EngineBlock\Authentication\Value\CollabPersonUuid; use OpenConext\EngineBlockBundle\Authentication\Entity\SamlPersistentId; -class SamlPersistentIdRepository extends EntityRepository +/** + * @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\OpenConext\EngineBlockBundle\Authentication\Entity\SamlPersistentId> + */ +class SamlPersistentIdRepository extends ServiceEntityRepository { + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, SamlPersistentId::class); + } + /** * @param CollabPersonUuid $uuid * @return SamlPersistentId[] diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Repository/ServiceProviderUuidRepository.php b/src/OpenConext/EngineBlockBundle/Authentication/Repository/ServiceProviderUuidRepository.php index 07a2a3a2bd..4826232ee9 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Repository/ServiceProviderUuidRepository.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Repository/ServiceProviderUuidRepository.php @@ -18,11 +18,20 @@ namespace OpenConext\EngineBlockBundle\Authentication\Repository; -use Doctrine\ORM\EntityRepository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; use OpenConext\EngineBlockBundle\Authentication\Entity\ServiceProviderUuid; -class ServiceProviderUuidRepository extends EntityRepository +/** + * @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\OpenConext\EngineBlockBundle\Authentication\Entity\ServiceProviderUuid> + */ +class ServiceProviderUuidRepository extends ServiceEntityRepository { + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ServiceProviderUuid::class); + } + /** * @param string $uuid * @return string|null diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Repository/UserRepository.php b/src/OpenConext/EngineBlockBundle/Authentication/Repository/UserRepository.php index 9f1de0477e..900ba93ae5 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Repository/UserRepository.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Repository/UserRepository.php @@ -18,15 +18,22 @@ namespace OpenConext\EngineBlockBundle\Authentication\Repository; -use Doctrine\ORM\EntityRepository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; use OpenConext\EngineBlock\Authentication\Value\CollabPersonId; use OpenConext\EngineBlockBundle\Authentication\Entity\User; /** * + * @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\OpenConext\EngineBlockBundle\Authentication\Entity\User> */ -class UserRepository extends EntityRepository +class UserRepository extends ServiceEntityRepository { + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, User::class); + } + /** * @param User $user */ @@ -59,7 +66,7 @@ public function deleteUserWithCollabPersonId(CollabPersonId $collabPersonId) $queryBuilder = $this->getEntityManager()->createQueryBuilder(); $queryBuilder - ->delete($this->_entityName, 'u') + ->delete(User::class, 'u') ->where('u.collabPersonId = :collabPersonId') ->setParameter('collabPersonId', $collabPersonId->getCollabPersonId()) ->getQuery() diff --git a/src/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfiguration.php b/src/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfiguration.php index 0e445a8ace..38c7ca1fae 100644 --- a/src/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfiguration.php +++ b/src/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfiguration.php @@ -18,7 +18,7 @@ namespace OpenConext\EngineBlockBundle\Configuration; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ErrorFeedbackConfiguration implements ErrorFeedbackConfigurationInterface { diff --git a/src/OpenConext/EngineBlockBundle/Configuration/FeatureConfiguration.php b/src/OpenConext/EngineBlockBundle/Configuration/FeatureConfiguration.php index 6223760c7e..dfd001b185 100644 --- a/src/OpenConext/EngineBlockBundle/Configuration/FeatureConfiguration.php +++ b/src/OpenConext/EngineBlockBundle/Configuration/FeatureConfiguration.php @@ -33,10 +33,13 @@ class FeatureConfiguration implements FeatureConfigurationInterface */ public function __construct(array $features) { - Assertion::allIsInstanceOf($features, Feature::class); - Assertion::allString(array_keys($features), 'All keys for features must be a string (the feature key itself).'); + $this->features = []; + foreach ($features as $feature => $onOrOff) { + $this->features[$feature] = new Feature($feature, $onOrOff); + } - $this->features = $features; + Assertion::allIsInstanceOf($this->features, Feature::class); + Assertion::allString(array_keys($this->features), 'All keys for features must be a string (the feature key itself).'); } public function hasFeature($featureKey) diff --git a/src/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyController.php b/src/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyController.php index cac09e461f..fe17e34368 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyController.php @@ -27,14 +27,22 @@ use OpenConext\EngineBlockBundle\Http\Response\JsonResponse; use OpenConext\Value\Saml\EntityId; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; final class AttributeReleasePolicyController { /** - * @var AuthorizationCheckerInterface + * @var TokenStorageInterface */ - private $authorizationChecker; + private $tokenStorage; + + /** + * @var AccessDecisionManagerInterface + */ + private $accessDecisionManager; /** * @var MetadataServiceInterface @@ -47,18 +55,19 @@ final class AttributeReleasePolicyController private $arpEnforcer; public function __construct( - AuthorizationCheckerInterface $authorizationChecker, + TokenStorageInterface $tokenStorage, + AccessDecisionManagerInterface $accessDecisionManager, MetadataServiceInterface $metadataService, EngineBlock_Arp_AttributeReleasePolicyEnforcer $arpEnforcer ) { - $this->authorizationChecker = $authorizationChecker; + $this->tokenStorage = $tokenStorage; + $this->accessDecisionManager = $accessDecisionManager; $this->metadataService = $metadataService; $this->arpEnforcer = $arpEnforcer; } /** - * @param Request $request - * @return JsonResponse + * @Route("/arp", name="api_apply_attribute_release_policy", defaults={"_format"="json"}) * * @SuppressWarnings(PHPMD.CyclomaticComplexity) Extensive request validation * @SuppressWarnings(PHPMD.NPathComplexity) Extensive request validation @@ -69,9 +78,7 @@ public function applyArpAction(Request $request) throw ApiMethodNotAllowedHttpException::methodNotAllowed($request->getMethod(), [Request::METHOD_POST]); } - if (!$this->authorizationChecker->isGranted('ROLE_API_USER_PROFILE')) { - throw new ApiAccessDeniedHttpException('Access to the ARP API requires the role ROLE_API_USER_PROFILE'); - } + $this->assertAuthorized(); $body = JsonRequestHelper::decodeContentAsArrayOf($request); @@ -115,15 +122,14 @@ public function applyArpAction(Request $request) $releasedAttributes = []; foreach ($body['entityIds'] as $entityId) { $arp = $this->metadataService->findArpForServiceProviderByEntityId(new EntityId($entityId)); - $releasedAttributes[$entityId] = $this->arpEnforcer->enforceArp($arp, $body['attributes'], $showSources); + $releasedAttributes[$entityId] = $this->arpEnforcer->enforceArp($body['attributes'], $arp, $showSources); } return new JsonResponse(json_encode($releasedAttributes)); } /** - * @param Request $request - * @return JsonResponse + * @Route("/read-arp", name="api_read_attribute_release_policy", defaults={"_format"="json"}) */ public function readArpAction(Request $request) { @@ -131,9 +137,7 @@ public function readArpAction(Request $request) throw ApiMethodNotAllowedHttpException::methodNotAllowed($request->getMethod(), [Request::METHOD_POST]); } - if (!$this->authorizationChecker->isGranted('ROLE_API_USER_PROFILE')) { - throw new ApiAccessDeniedHttpException('Access to the ARP API requires the role ROLE_API_USER_PROFILE'); - } + $this->assertAuthorized(); $body = JsonRequestHelper::decodeContentAsArrayOf($request); if (!is_array($body)) { @@ -161,4 +165,16 @@ public function readArpAction(Request $request) return new JsonResponse(json_encode($arpCollection)); } + + private function assertAuthorized(): void + { + $token = $this->tokenStorage->getToken(); + if (!$token || !$token->getUser()) { + throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token.'); + } + + if (!$this->accessDecisionManager->decide($token, ['ROLE_API_USER_PROFILE'], null)) { + throw new ApiAccessDeniedHttpException('Access to the ARP API requires the role ROLE_API_USER_PROFILE'); + } + } } diff --git a/src/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsController.php b/src/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsController.php index 24be5ed7fa..695c1b7837 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsController.php @@ -31,7 +31,10 @@ use OpenConext\EngineBlockBundle\Http\Request\JsonRequestHelper; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Static calls, factories, and having to check HTTP methods which is @@ -47,9 +50,14 @@ class ConnectionsController private $pushMetadataAssembler; /** - * @var AuthorizationCheckerInterface + * @var TokenStorageInterface */ - private $authorizationChecker; + private $tokenStorage; + + /** + * @var AccessDecisionManagerInterface + */ + private $accessDecisionManager; /** * @var FeatureConfigurationInterface @@ -68,25 +76,31 @@ class ConnectionsController /** * @param MetadataAssemblerInterface $assembler - * @param AuthorizationCheckerInterface $authorizationChecker + * @param TokenStorageInterface $tokenStorage + * @param AccessDecisionManagerInterface $accessDecisionManager * @param FeatureConfigurationInterface $featureConfiguration * @param DoctrineMetadataPushRepository $repository * @param string|null $memoryLimit */ public function __construct( MetadataAssemblerInterface $assembler, - AuthorizationCheckerInterface $authorizationChecker, + TokenStorageInterface $tokenStorage, + AccessDecisionManagerInterface $accessDecisionManager, FeatureConfigurationInterface $featureConfiguration, DoctrineMetadataPushRepository $repository, $memoryLimit ) { $this->pushMetadataAssembler = $assembler; - $this->authorizationChecker = $authorizationChecker; + $this->tokenStorage = $tokenStorage; + $this->accessDecisionManager = $accessDecisionManager; $this->featureConfiguration = $featureConfiguration; $this->repository = $repository; $this->memoryLimit = $memoryLimit; } + /** + * @Route("/api/connections", name="api_connections", defaults={"_format"="json"}) + */ public function pushConnectionsAction(Request $request) { if (!$request->isMethod(Request::METHOD_POST)) { @@ -97,11 +111,7 @@ public function pushConnectionsAction(Request $request) throw new ApiNotFoundHttpException('Metadata push API is disabled'); } - if (!$this->authorizationChecker->isGranted(['ROLE_API_USER_METADATA_PUSH'])) { - throw new ApiAccessDeniedHttpException( - 'Access to the metadata push API requires the role ROLE_API_USER_METADATA_PUSH' - ); - } + $this->assertAuthorized(); if ($this->memoryLimit) { ini_set('memory_limit', $this->memoryLimit); @@ -109,7 +119,7 @@ public function pushConnectionsAction(Request $request) $body = JsonRequestHelper::decodeContentOf($request); - if (!is_object($body) || !isset($body->connections) && !is_object($body->connections)) { + if (!is_object($body) || !isset($body->connections) || !is_object($body->connections)) { throw new BadApiRequestHttpException('Unrecognized structure for JSON'); } @@ -129,4 +139,18 @@ public function pushConnectionsAction(Request $request) return new JsonResponse($result); } + + private function assertAuthorized(): void + { + $token = $this->tokenStorage->getToken(); + if (!$token || !$token->getUser()) { + throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token.'); + } + + if (!$this->accessDecisionManager->decide($token, ['ROLE_API_USER_METADATA_PUSH'], null)) { + throw new ApiAccessDeniedHttpException( + 'Access to the metadata push API requires the role ROLE_API_USER_METADATA_PUSH' + ); + } + } } diff --git a/src/OpenConext/EngineBlockBundle/Controller/Api/ConsentController.php b/src/OpenConext/EngineBlockBundle/Controller/Api/ConsentController.php index 4c0adeba5f..3f1ce4d40a 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/Api/ConsentController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/Api/ConsentController.php @@ -19,18 +19,23 @@ namespace OpenConext\EngineBlockBundle\Controller\Api; use OpenConext\EngineBlock\Exception\RuntimeException; +use OpenConext\EngineBlock\Http\Exception\AccessDeniedException; use OpenConext\EngineBlock\Service\ConsentServiceInterface; use OpenConext\EngineBlockBundle\Configuration\FeatureConfigurationInterface; -use OpenConext\EngineBlockBundle\Exception\InvalidArgumentException as EngineBlockInvalidArgumentException; use OpenConext\EngineBlockBundle\Factory\CollabPersonIdFactory; use OpenConext\EngineBlockBundle\Http\Exception\ApiAccessDeniedHttpException; use OpenConext\EngineBlockBundle\Http\Exception\ApiInternalServerErrorHttpException; use OpenConext\EngineBlockBundle\Http\Exception\ApiMethodNotAllowedHttpException; use OpenConext\EngineBlockBundle\Http\Exception\ApiNotFoundHttpException; +use OpenConext\EngineBlockBundle\Http\Exception\BadApiRequestHttpException; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; + use function array_key_exists; use function sprintf; @@ -50,20 +55,30 @@ final class ConsentController private $featureConfiguration; /** - * @var AuthorizationCheckerInterface + * @var TokenStorageInterface + */ + private $tokenStorage; + + /** + * @var AccessDecisionManagerInterface */ - private $authorizationChecker; + private $accessDecisionManager; public function __construct( - AuthorizationCheckerInterface $authorizationChecker, + TokenStorageInterface $tokenStorage, + AccessDecisionManagerInterface $accessDecisionManager, FeatureConfigurationInterface $featureConfiguration, ConsentServiceInterface $consentService ) { - $this->authorizationChecker = $authorizationChecker; + $this->tokenStorage = $tokenStorage; + $this->accessDecisionManager = $accessDecisionManager; $this->featureConfiguration = $featureConfiguration; $this->consentService = $consentService; } + /** + * @Route("/consent/{userId}", name="api_consent_user", defaults={"_format"="json"}) + */ public function userAction($userId, Request $request) { if (!$request->isMethod(Request::METHOD_GET)) { @@ -78,11 +93,7 @@ public function userAction($userId, Request $request) throw new ApiNotFoundHttpException('Consent listing API is disabled'); } - if (!$this->authorizationChecker->isGranted('ROLE_API_USER_PROFILE')) { - throw new ApiAccessDeniedHttpException( - 'Access to the content listing API requires the role ROLE_API_USER_PROFILE' - ); - } + $this->assertAuthorized(); try { $consentList = $this->consentService->findAllFor($userId)->jsonSerialize(); @@ -100,6 +111,9 @@ public function userAction($userId, Request $request) return new JsonResponse($consentList, Response::HTTP_OK); } + /** + * @Route("/remove-consent", name="api_remove_consent_user", defaults={"_format"="json"}) + */ public function removeAction(Request $request): JsonResponse { if (!$request->isMethod(Request::METHOD_POST)) { @@ -114,17 +128,12 @@ public function removeAction(Request $request): JsonResponse throw new ApiNotFoundHttpException('Consent remove API is disabled'); } - if (!$this->authorizationChecker->isGranted('ROLE_API_USER_PROFILE')) { - throw new ApiAccessDeniedHttpException( - 'Access to the consent removal API requires the role ROLE_API_USER_PROFILE' - ); - } + $this->assertAuthorized(); + // The data is posted json encoded from EngineBlock $data = json_decode($request->getContent(), true); if (!$data || !array_key_exists('collabPersonId', $data) || !array_key_exists('serviceProviderEntityId', $data)) { - throw new EngineBlockInvalidArgumentException( - 'The required data for removing the consent is not present in the request parameters json' - ); + return new JsonResponse('The required data for removing the consent is not present in the request parameters json', Response::HTTP_FOUND); } $userId = $data['collabPersonId']; @@ -146,4 +155,18 @@ public function removeAction(Request $request): JsonResponse return new JsonResponse($removed, Response::HTTP_OK); } + + private function assertAuthorized(): void + { + $token = $this->tokenStorage->getToken(); + if (!$token || !$token->getUser()) { + throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token.'); + } + + if (!$this->accessDecisionManager->decide($token, ['ROLE_API_USER_PROFILE'], null)) { + throw new ApiAccessDeniedHttpException( + 'Access to the content API requires the role ROLE_API_USER_PROFILE' + ); + } + } } diff --git a/src/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionController.php b/src/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionController.php index 5ed524b4bf..7c940c88b8 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionController.php @@ -21,13 +21,17 @@ use OpenConext\EngineBlockBundle\Configuration\FeatureConfigurationInterface; use OpenConext\EngineBlockBundle\Factory\CollabPersonIdFactory; use OpenConext\EngineBlockBundle\Http\Exception\ApiAccessDeniedHttpException; +use OpenConext\EngineBlockBundle\Factory\CollabPersonIdFactory as CollabFactory; use OpenConext\EngineBlock\Service\DeprovisionService; use OpenConext\EngineBlockBundle\Http\Exception\ApiMethodNotAllowedHttpException; use OpenConext\EngineBlockBundle\Http\Exception\ApiNotFoundHttpException; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -45,9 +49,14 @@ final class DeprovisionController private $featureConfiguration; /** - * @var AuthorizationCheckerInterface + * @var TokenStorageInterface */ - private $authorizationChecker; + private $tokenStorage; + + /** + * @var AccessDecisionManagerInterface + */ + private $accessDecisionManager; /** * @var string @@ -55,27 +64,32 @@ final class DeprovisionController private $applicationName; /** - * @param AuthorizationCheckerInterface $authorizationChecker + * @param TokenStorageInterface $tokenStorage + * @param AccessDecisionManagerInterface $accessDecisionManager * @param FeatureConfigurationInterface $featureConfiguration * @param DeprovisionService $deprovisionService * @param string $applicationName */ public function __construct( - AuthorizationCheckerInterface $authorizationChecker, + TokenStorageInterface $tokenStorage, + AccessDecisionManagerInterface $accessDecisionManager, FeatureConfigurationInterface $featureConfiguration, DeprovisionService $deprovisionService, $applicationName ) { - $this->authorizationChecker = $authorizationChecker; + $this->tokenStorage = $tokenStorage; + $this->accessDecisionManager = $accessDecisionManager; $this->featureConfiguration = $featureConfiguration; $this->deprovisionService = $deprovisionService; $this->applicationName = $applicationName; } /** - * @param Request $request - * @param string $collabPersonId - * @return JsonResponse + * @Route( + * "/deprovision/{collabPersonId}", + * name="api_deprovision_get_user_data", + * defaults={"_format"="json"} + * ) */ public function userDataAction(Request $request, $collabPersonId) { @@ -95,9 +109,11 @@ public function userDataAction(Request $request, $collabPersonId) } /** - * @param Request $request - * @param string $collabPersonId - * @return JsonResponse + * @Route( + * "/deprovision/{collabPersonId}/dry-run", + * name="api_deprovision_delete_user_data_dry_run", + * defaults={"_format"="json"} + * ) */ public function dryRunAction(Request $request, $collabPersonId) { @@ -163,9 +179,14 @@ private function assertRequestMethod(Request $request, array $expectedMethods) /** * @throws ApiAccessDeniedHttpException */ - private function assertUserHasDeprovisionRole() + private function assertUserHasDeprovisionRole(): void { - if (!$this->authorizationChecker->isGranted('ROLE_API_USER_DEPROVISION')) { + $token = $this->tokenStorage->getToken(); + if (!$token || !$token->getUser()) { + throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token.'); + } + + if (!$this->accessDecisionManager->decide($token, ['ROLE_API_USER_DEPROVISION'], null)) { throw new ApiAccessDeniedHttpException( 'Access to the content listing API requires the role ROLE_API_USER_DEPROVISION' ); diff --git a/src/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatController.php b/src/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatController.php index af8c84a262..3f24a43601 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatController.php @@ -19,9 +19,13 @@ namespace OpenConext\EngineBlockBundle\Controller\Api; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; class HeartbeatController { + /** + * @Route("/", name="api_heartbeat", defaults={"_format"="json"}) + */ public function itWorksAction() { return new Response(); diff --git a/src/OpenConext/EngineBlockBundle/Controller/Api/MetadataController.php b/src/OpenConext/EngineBlockBundle/Controller/Api/MetadataController.php index 5339a995e2..f94d403a07 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/Api/MetadataController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/Api/MetadataController.php @@ -29,7 +29,10 @@ use OpenConext\Value\Exception\InvalidArgumentException; use OpenConext\Value\Saml\EntityId; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Static calls, factories, and having to check HTTP methods which is @@ -48,20 +51,30 @@ final class MetadataController private $featureConfiguration; /** - * @var AuthorizationCheckerInterface + * @var TokenStorageInterface */ - private $authorizationChecker; + private $tokenStorage; + + /** + * @var AccessDecisionManagerInterface + */ + private $accessDecisionManager; public function __construct( - AuthorizationCheckerInterface $authorizationChecker, + TokenStorageInterface $tokenStorage, + AccessDecisionManagerInterface $accessDecisionManager, FeatureConfiguration $featureConfiguration, MetadataServiceInterface $metadataService ) { - $this->authorizationChecker = $authorizationChecker; + $this->tokenStorage = $tokenStorage; + $this->accessDecisionManager = $accessDecisionManager; $this->featureConfiguration = $featureConfiguration; $this->metadataService = $metadataService; } + /** + * @Route("/metadata/idp", name="api_metadata_idp", defaults={"_format"="json"}) + */ public function idpAction(Request $request) { if (!$request->isMethod(Request::METHOD_GET)) { @@ -74,11 +87,7 @@ public function idpAction(Request $request) throw new ApiNotFoundHttpException('Metadata API is disabled'); } - if (!$this->authorizationChecker->isGranted('ROLE_API_USER_PROFILE')) { - throw new ApiAccessDeniedHttpException( - 'Access to the Metadata API requires the role ROLE_API_USER_PROFILE' - ); - } + $this->assertAuthorized(); try { $entityId = new EntityId($entityIdValue); @@ -97,4 +106,18 @@ public function idpAction(Request $request) return new JsonResponse(JsonHelper::serializeIdentityProvider($identityProvider), JsonResponse::HTTP_OK); } + + private function assertAuthorized(): void + { + $token = $this->tokenStorage->getToken(); + if (!$token || !$token->getUser()) { + throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token.'); + } + + if (!$this->accessDecisionManager->decide($token, ['ROLE_API_USER_PROFILE'], null)) { + throw new ApiAccessDeniedHttpException( + 'Access to the Metadata API requires the role ROLE_API_USER_PROFILE' + ); + } + } } diff --git a/src/OpenConext/EngineBlockBundle/Controller/DebugController.php b/src/OpenConext/EngineBlockBundle/Controller/DebugController.php index b7d85fd8f9..fa77f92544 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/DebugController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/DebugController.php @@ -24,7 +24,9 @@ use OpenConext\Value\Saml\Entity; use OpenConext\Value\Saml\EntityId; use OpenConext\Value\Saml\EntityType; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\Routing\Annotation\Route; class DebugController implements AuthenticationLoopThrottlingController { @@ -40,14 +42,14 @@ class DebugController implements AuthenticationLoopThrottlingController public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, - SessionInterface $session + RequestStack $requestStack, ) { $this->engineBlockApplicationSingleton = $engineBlockApplicationSingleton; - $this->session = $session; + $this->session = $requestStack->getSession(); } /** - * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * @Route("/authentication/sp/debug", name="authentication_sp_debug", methods={"GET","POST"}) */ public function debugSpConnectionAction() { diff --git a/src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php b/src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php index 877e3f7a13..7f12630b70 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php @@ -24,8 +24,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Translation\TranslatorInterface; -use Twig_Environment; +use Twig\Environment; /** * @SuppressWarnings(PHPMD.TooManyPublicMethods) Mimics the previous methodology, will be refactored @@ -35,12 +36,12 @@ class FeedbackController { /** - * @var TranslatorInterface + * @var \Symfony\Contracts\Translation\TranslatorInterface */ private $translator; /** - * @var Twig_Environment + * @var Environment */ private $twig; @@ -50,8 +51,8 @@ class FeedbackController private $logger; public function __construct( - TranslatorInterface $translator, - Twig_Environment $twig, + \Symfony\Contracts\Translation\TranslatorInterface $translator, + Environment $twig, LoggerInterface $logger ) { $this->translator = $translator; @@ -64,8 +65,11 @@ public function __construct( } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unable-to-receive-message", + * name="authentication_feedback_unable_to_receive_message", + * methods={"GET"} + * ) */ public function unableToReceiveMessageAction() { @@ -75,6 +79,9 @@ public function unableToReceiveMessageAction() ); } + /** + * @Route("/feedback/unknown-error", name="feedback_unknown_error", methods={"GET"}) + */ public function unknownErrorAction() { return new Response( @@ -83,9 +90,9 @@ public function unknownErrorAction() ); } + /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/feedback/session-lost", name="authentication_feedback_session_lost", methods={"GET"}) */ public function sessionLostAction() { @@ -93,8 +100,7 @@ public function sessionLostAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/feedback/session-not-started", name="authentication_feedback_session_not_started", methods={"GET"}) */ public function sessionNotStartedAction() { @@ -102,8 +108,7 @@ public function sessionNotStartedAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/feedback/no-idps", name="authentication_feedback_no_idps", methods={"GET"}) */ public function noIdpsAction() { @@ -113,8 +118,7 @@ public function noIdpsAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/feedback/invalidAcsLocation", name="authentication_feedback_invalid_acs_location", methods={"GET"}) */ public function invalidAcsLocationAction() { @@ -125,9 +129,11 @@ public function invalidAcsLocationAction() } /** - * @param Request $request - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unsupportedSignatureMethod", + * name="authentication_feedback_unsupported_signature_method", + * methods={"GET"} + * ) */ public function unsupportedSignatureMethodAction(Request $request) { @@ -144,8 +150,11 @@ public function unsupportedSignatureMethodAction(Request $request) } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unsupported-acs-location-scheme", + * name="authentication_feedback_unsupported_acs_location_uri_scheme", + * methods={"GET"} + * ) */ public function unsupportedAcsLocationSchemeAction() { @@ -158,10 +167,13 @@ public function unsupportedAcsLocationSchemeAction() ); } + /** - * @param Request $request - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unknown-service-provider", + * name="authentication_feedback_unknown_service_provider", + * methods={"GET"} + * ) */ public function unknownServiceProviderAction(Request $request) { @@ -182,9 +194,11 @@ public function unknownServiceProviderAction(Request $request) } /** - * @param Request $request - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unknown-identity-provider", + * name="authentication_feedback_unknown_identity_provider", + * methods={"GET"} + * ) */ public function unknownIdentityProviderAction(Request $request) { @@ -202,9 +216,11 @@ public function unknownIdentityProviderAction(Request $request) } /** - * @param Request $request - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unknown-signing-key", + * name="authentication_feedback_unknown_signing_key", + * methods={"GET"} + * ) */ public function unknownSigningKeyAction(Request $request) { @@ -214,9 +230,13 @@ public function unknownSigningKeyAction(Request $request) ); } + /** - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/missing-required-fields", + * name="authentication_feedback_missing_required_fields", + * methods={"GET"} + * ) */ public function missingRequiredFieldsAction() { @@ -227,7 +247,11 @@ public function missingRequiredFieldsAction() } /** - * @return Response + * @Route( + * "/authentication/feedback/authn-context-class-ref-blacklisted", + * name="authentication_authn_context_class_ref_blacklisted", + * methods={"GET"} + * ) */ public function authnContextClassRefBlacklistedAction() { @@ -239,7 +263,11 @@ public function authnContextClassRefBlacklistedAction() /** - * @return Response + * @Route( + * "/authentication/feedback/invalid-mfa-authn-context-class-ref", + * name="authentication_invalid_mfa_authn_context_class_ref", + * methods={"GET"} + * ) */ public function invalidMfAuthnContextClassRefAction() { @@ -249,9 +277,9 @@ public function invalidMfAuthnContextClassRefAction() ); } + /** - * @param Request $request - * @return Response + * @Route("/authentication/feedback/invalid-attribute-value", name="authentication_feedback_invalid_attribute_value", methods={"GET"}) */ public function invalidAttributeValueAction(Request $request) { @@ -272,6 +300,13 @@ public function invalidAttributeValueAction(Request $request) ); } + /** + * @Route( + * "/authentication/feedback/metadata-entity-not-found", + * name="authentication_feedback_metadata_entity_not_found", + * methods={"GET"} + * ) + */ public function metadataEntityNotFoundAction(Request $request) { // The exception message is used on the error page. As mostly developers or other tech-savvy people will see @@ -297,8 +332,7 @@ public function metadataEntityNotFoundAction(Request $request) } /** - * @param Request $request - * @return Response + * @Route("/authentication/feedback/custom", name="authentication_feedback_custom", methods={"GET"}) */ public function customAction(Request $request) { @@ -331,8 +365,7 @@ public function customAction(Request $request) } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/feedback/invalid-acs-binding", name="authentication_feedback_invalid_acs_binding", methods={"GET"}) */ public function invalidAcsBindingAction() { @@ -341,8 +374,11 @@ public function invalidAcsBindingAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/received-error-status-code", + * name="authentication_feedback_received_error_status_code", + * methods={"GET"} + * ) */ public function receivedErrorStatusCodeAction() { @@ -353,8 +389,11 @@ public function receivedErrorStatusCodeAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/received-invalid-signed-response", + * name="authentication_feedback_signature_verification_failed", + * methods={"GET"} + * ) */ public function signatureVerificationFailedAction() { @@ -365,8 +404,7 @@ public function signatureVerificationFailedAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/feedback/received-invalid-response", name="authentication_feedback_verification_failed", methods={"GET"}) */ public function receivedInvalidResponseAction() { @@ -377,8 +415,11 @@ public function receivedInvalidResponseAction() } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route( + * "/authentication/feedback/unknown_requesterid_in_authnrequest", + * name="authentication_feedback_unknown_requesterid_in_authnrequest", + * methods={"GET"} + * ) */ public function unknownRequesterIdInAuthnRequestAction() { @@ -388,9 +429,13 @@ public function unknownRequesterIdInAuthnRequestAction() ); } + /** - * @param Request $request - * @return Response + * @Route( + * "/authentication/feedback/authorization-policy-violation", + * name="authentication_feedback_pep_violation", + * methods={"GET"} + * ) */ public function authorizationPolicyViolationAction(Request $request) { @@ -425,8 +470,11 @@ public function authorizationPolicyViolationAction(Request $request) } /** - * @param Request $request - * @return Response + * @Route( + * "/authentication/feedback/unknown-preselected-idp", + * name="authentication_feedback_unknown_preselected_idp", + * methods={"GET"} + * ) */ public function unknownPreselectedIdpAction(Request $request) { @@ -442,6 +490,9 @@ public function unknownPreselectedIdpAction(Request $request) ); } + /** + * @Route("/authentication/feedback/unknown-keyid", name="authentication_feedback_unknown_keyid", methods={"GET"}) + */ public function unknownKeyIdAction(Request $request): Response { // Add feedback info from url @@ -457,7 +508,7 @@ public function unknownKeyIdAction(Request $request): Response } /** - * @return Response + * @Route("/authentication/feedback/stuck-in-authentication-loop", name="authentication_feedback_stuck_in_authentication_loop", methods={"GET"}) */ public function stuckInAuthenticationLoopAction() { @@ -467,6 +518,13 @@ public function stuckInAuthenticationLoopAction() ); } + /** + * @Route( + * "/authentication/feedback/authentication-limit-exceeded", + * name="authentication_feedback_authentication_limit_exceeded", + * methods={"GET"} + * ) + */ public function authenticationLimitExceededAction() { return new Response( @@ -476,7 +534,11 @@ public function authenticationLimitExceededAction() } /** - * @return Response + * @Route( + * "/authentication/feedback/invalid-request-method-on-sso", + * name="authentication_feedback_no_authentication_request_received", + * methods={"GET"} + * ) */ public function noAuthenticationRequestReceivedAction(Request $request) { @@ -503,7 +565,7 @@ public function noAuthenticationRequestReceivedAction(Request $request) } /** - * @return Response + * @Route("/authentication/feedback/clock-issue", name="authentication_feedback_response_clock_issue", methods={"GET"}) */ public function clockIssueAction() { @@ -514,7 +576,7 @@ public function clockIssueAction() } /** - * @return Response + * @Route("/authentication/feedback/stepup-callout-user-cancelled", name="authentication_feedback_stepup_callout_user_cancelled", methods={"GET"}) */ public function stepupCalloutUserCancelledAction(Request $request) { @@ -525,7 +587,7 @@ public function stepupCalloutUserCancelledAction(Request $request) } /** - * @return Response + * @Route("/authentication/feedback/stepup-callout-unmet-loa", name="authentication_feedback_stepup_callout_unmet_loa", methods={"GET"}) */ public function stepupCalloutUnmetLoaAction(Request $request) { @@ -536,7 +598,7 @@ public function stepupCalloutUnmetLoaAction(Request $request) } /** - * @return Response + * @Route("/authentication/feedback/stepup-callout-unknown", name="authentication_feedback_stepup_callout_unknown", methods={"GET"}) */ public function stepupCalloutUnknownAction(Request $request) { diff --git a/src/OpenConext/EngineBlockBundle/Controller/IdentityProviderController.php b/src/OpenConext/EngineBlockBundle/Controller/IdentityProviderController.php index 5ca07895e4..70f1699310 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/IdentityProviderController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/IdentityProviderController.php @@ -29,7 +29,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Twig_Environment; +use Symfony\Component\Routing\Annotation\Route; +use Twig\Environment; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Due to the compatibility requirements @@ -42,7 +43,7 @@ class IdentityProviderController implements AuthenticationLoopThrottlingControll private $engineBlockApplicationSingleton; /** - * @var Twig_Environment + * @var Environment */ private $twig; @@ -83,7 +84,7 @@ class IdentityProviderController implements AuthenticationLoopThrottlingControll public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, - Twig_Environment $twig, + Environment $twig, LoggerInterface $loggerInterface, RequestAccessMailer $requestAccessMailer, RequestValidator $requestValidator, @@ -106,19 +107,37 @@ public function __construct( /** * The SSO action * - * Currently supported request method / binding combinations for SSO are: + * Currently supported request method / binding combinations for SSO are: * - * | SAML Binding | Request method | Parameter name | - * | ---------------- | -------------- | -------------- | - * | HttpRedirect | GET | SAMLRequest | - * | HTTPPost | POST | SAMLRequest | + * | SAML Binding | Request method | Parameter name | + * |--------------|----------------|----------------| + * | HttpRedirect | GET | SAMLRequest | + * | HTTPPost | POST | SAMLRequest | * - * @param Request $request - * @param null|string $keyId - * @param null|string $idpHash * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * + * @Route( + * "/authentication/idp/single-sign-on", + * name="authentication_idp_sso", + * methods={"GET", "POST"} + * ) + * @Route( + * "/authentication/idp/single-sign-on/key:{keyId}/{idpHash}", + * name="authentication_idp_sso_keyid_idphash", + * methods={"GET", "POST"} + * ) + * @Route( + * "/authentication/idp/single-sign-on/key:{keyId}", + * name="authentication_idp_sso_keyid", + * methods={"GET", "POST"} + * ) + * @Route( + * "/authentication/idp/single-sign-on/{idpHash}", + * name="authentication_idp_sso_idphash", + * methods={"GET", "POST"} + * ) */ - public function singleSignOnAction(Request $request, $keyId = null, $idpHash = null) + public function singleSignOnAction(Request $request, string $keyId = null, string $idpHash = null) { $this->requestValidator->isValid($request); $this->bindingValidator->isValid($request); @@ -135,13 +154,32 @@ public function singleSignOnAction(Request $request, $keyId = null, $idpHash = n } /** - * @param Request $request - * @param null|string $keyId - * @param null|string $idpHash * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response * @throws NotFoundHttpException If the IdP-initiated flow has been disabled by config + * + * @Route( + * "/authentication/idp/unsolicited-single-sign-on", + * name="authentication_idp_unsolicited_sso", + * methods={"GET"} + * ) + * @Route( + * "/authentication/idp/unsolicited-single-sign-on/key:{keyId}/{idpHash}", + * name="authentication_idp_unsolicited_sso_keyid_idphash", + * methods={"GET"} + * ) + * @Route( + * "/authentication/idp/unsolicited-single-sign-on/key:{keyId}", + * name="authentication_idp_unsolicited_sso_keyid", + * methods={"GET"} + * ) + * @Route( + * "/authentication/idp/unsolicited-single-sign-on/{idpHash}", + * name="authentication_idp_unsolicited_sso_idphash", + * methods={"GET"} + * ) */ - public function unsolicitedSingleSignOnAction(Request $request, $keyId = null, $idpHash = null) + + public function unsolicitedSingleSignOnAction(Request $request, string $keyId = null, string $idpHash = null) { if (!$this->featureConfiguration->isEnabled('eb.feature_enable_idp_initiated_flow')) { throw new NotFoundHttpException(); @@ -162,6 +200,8 @@ public function unsolicitedSingleSignOnAction(Request $request, $keyId = null, $ /** * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response + * + * @Route("/authentication/idp/process-consent", name="authentication_idp_process_consent", methods={"POST"}) */ public function processConsentAction() { @@ -175,6 +215,8 @@ public function processConsentAction() * @param Request $request * @return Response * @throws \EngineBlock_Exception + * + * @Route("/authentication/idp/requestAccess", name="authentication_idp_request_access", methods={"GET"}) */ public function requestAccessAction(Request $request) { @@ -190,6 +232,8 @@ public function requestAccessAction(Request $request) * @param Request $request * @return Response * @throws \EngineBlock_Exception + * + * @Route("/authentication/idp/performRequestAccess", name="authentication_idp_perform_request_access_two", methods={"POST"}) */ public function performRequestAccessAction(Request $request) { diff --git a/src/OpenConext/EngineBlockBundle/Controller/IndexController.php b/src/OpenConext/EngineBlockBundle/Controller/IndexController.php index 91b7c2e649..b3bcbaed52 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/IndexController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/IndexController.php @@ -19,10 +19,12 @@ namespace OpenConext\EngineBlockBundle\Controller; use OpenConext\EngineBlock\Metadata\X509\KeyPairFactory; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; use Twig\Environment; -class IndexController +class IndexController extends AbstractController { /** * @var Environment @@ -41,7 +43,7 @@ public function __construct(Environment $twig, array $keyPairs) } /** - * @return Response + * @Route("/", name="open_conext_engine_block_authentication_homepage") */ public function indexAction() { diff --git a/src/OpenConext/EngineBlockBundle/Controller/LogoutController.php b/src/OpenConext/EngineBlockBundle/Controller/LogoutController.php index b956d26a0d..32c2026986 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/LogoutController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/LogoutController.php @@ -21,7 +21,8 @@ use OpenConext\EngineBlock\Service\SsoSessionService; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Twig_Environment; +use Symfony\Component\Routing\Annotation\Route; +use Twig\Environment; /** * @SuppressWarnings(PHPMD.Superglobals) see docblock at logoutAction @@ -29,7 +30,7 @@ class LogoutController { /** - * @var Twig_Environment + * @var Environment */ private $twig; @@ -38,7 +39,7 @@ class LogoutController */ private $ssoSessionService; - public function __construct(Twig_Environment $twig, SsoSessionService $ssoSessionService) + public function __construct(Environment $twig, SsoSessionService $ssoSessionService) { $this->twig = $twig; $this->ssoSessionService = $ssoSessionService; @@ -49,8 +50,7 @@ public function __construct(Twig_Environment $twig, SsoSessionService $ssoSessio * manages the sessions (for now). Therefore we destroy these the same way * as is being done in EB4 * - * @param Request $request - * @return Response + * @Route("/logout", name="authentication_logout", methods={"GET", "POST"}) */ public function logoutAction(Request $request) { diff --git a/src/OpenConext/EngineBlockBundle/Controller/MetadataController.php b/src/OpenConext/EngineBlockBundle/Controller/MetadataController.php index d84a8e32e4..5136b4896e 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/MetadataController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/MetadataController.php @@ -25,6 +25,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RouterInterface; use OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration; @@ -49,6 +50,10 @@ public function __construct( $this->engineBlockConfiguration = $engineBlockConfiguration; } + /** + * @Route("/authentication/idp/metadata", name="metadata_idp", methods={"GET"}) + * @Route("/authentication/idp/metadata/key:{keyId}", name="metadata_idp_key", methods={"GET"}) + */ public function idpMetadataAction(string $keyId = null): Response { $metadataXml = $this->metadataService->metadataForIdp($keyId); @@ -59,7 +64,11 @@ public function idpMetadataAction(string $keyId = null): Response return $response; } - public function spMetadataAction(string $keyId): Response + /** + * @Route("/authentication/sp/metadata", name="metadata_sp", methods={"GET"}) + * @Route("/authentication/sp/metadata/key:{keyId}", name="metadata_sp_key", methods={"GET"}) + */ + public function spMetadataAction(string $keyId = ''): Response { if (empty($keyId)) { $keyId = KeyPairFactory::DEFAULT_KEY_PAIR_IDENTIFIER; @@ -73,6 +82,10 @@ public function spMetadataAction(string $keyId): Response return $response; } + /** + * @Route("/authentication/proxy/idps-metadata", name="metadata_all_idps", methods={"GET"}) + * @Route("/authentication/proxy/idps-metadata/key:{keyId}", name="metadata_all_idps_key", methods={"GET"}) + */ public function allIdpsMetadataAction(Request $request, string $keyId = null): Response { $spEntityId = $request->query->get('sp-entity-id', null); @@ -86,6 +99,10 @@ public function allIdpsMetadataAction(Request $request, string $keyId = null): R return $response; } + /** + * @Route("/authentication/stepup/metadata", name="metadata_stepup", methods={"GET"}) + * @Route("/authentication/stepup/metadata/key:{keyId}", name="metadata_stepup_key", methods={"GET"}) + */ public function stepupMetadataAction(string $keyId = null): Response { if (empty($keyId)) { @@ -100,6 +117,13 @@ public function stepupMetadataAction(string $keyId = null): Response return $response; } + /** + * TODO: SYMFONY 4.4 UPGRADE - Is it correct that both SP and IDP point to the same? It was like this in the previous config + * @Route("/authentication/idp/certificate", name="certificate_idp", methods={"GET"}) + * @Route("/authentication/idp/certificate/key:{keyId}", name="certificate_idp_key", methods={"GET"}) + * @Route("/authentication/sp/certificate", name="certificate_sp", methods={"GET"}) + * @Route("/authentication/sp/certificate/key:{keyId}", name="certificate_sp_key", methods={"GET"}) + */ public function signingCertificateAction(string $keyId = null): Response { if (empty($keyId)) { diff --git a/src/OpenConext/EngineBlockBundle/Controller/ProxyController.php b/src/OpenConext/EngineBlockBundle/Controller/ProxyController.php index d51afc5b9f..3584602901 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/ProxyController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/ProxyController.php @@ -21,6 +21,7 @@ use EngineBlock_ApplicationSingleton; use EngineBlock_Corto_Adapter; use OpenConext\EngineBlockBridge\ResponseFactory; +use Symfony\Component\Routing\Annotation\Route; class ProxyController { @@ -39,6 +40,8 @@ public function __construct(EngineBlock_ApplicationSingleton $engineBlockApplica /** * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * + * @Route("/authentication/proxy/processed-assertion", name="authentication_proxy_processed_assertion", methods={"GET","POST"}) */ public function processedAssertionAction() { diff --git a/src/OpenConext/EngineBlockBundle/Controller/ServiceProviderController.php b/src/OpenConext/EngineBlockBundle/Controller/ServiceProviderController.php index be0702c3f9..af4b495b2d 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/ServiceProviderController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/ServiceProviderController.php @@ -23,7 +23,7 @@ use OpenConext\EngineBlock\Validator\RequestValidator; use OpenConext\EngineBlockBridge\ResponseFactory; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\Routing\Annotation\Route; class ServiceProviderController implements AuthenticationLoopThrottlingController { @@ -32,11 +32,6 @@ class ServiceProviderController implements AuthenticationLoopThrottlingControlle */ private $engineBlockApplicationSingleton; - /** - * @var Session - */ - private $session; - /** * @var RequestValidator */ @@ -54,13 +49,11 @@ class ServiceProviderController implements AuthenticationLoopThrottlingControlle public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, - Session $session, RequestValidator $requestValidator, RequestValidator $bindingValidator, RequestValidator $samlResponseValidator ) { $this->engineBlockApplicationSingleton = $engineBlockApplicationSingleton; - $this->session = $session; $this->requestValidator = $requestValidator; $this->bindingValidator = $bindingValidator; $this->responseValidator = $samlResponseValidator; @@ -69,6 +62,8 @@ public function __construct( /** * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * + * @Route("/authentication/sp/consume-assertion", name="authentication_sp_consume_assertion", methods={"POST"}) */ public function consumeAssertionAction(Request $request) { @@ -84,6 +79,8 @@ public function consumeAssertionAction(Request $request) /** * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * + * @Route("/authentication/sp/process-consent", name="authentication_sp_process_consent", methods={"GET","POST"}) */ public function processConsentAction() { diff --git a/src/OpenConext/EngineBlockBundle/Controller/StepupController.php b/src/OpenConext/EngineBlockBundle/Controller/StepupController.php index bf44f8a7a4..37a4b4a590 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/StepupController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/StepupController.php @@ -23,7 +23,7 @@ use OpenConext\EngineBlock\Validator\RequestValidator; use OpenConext\EngineBlockBridge\ResponseFactory; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\Routing\Annotation\Route; class StepupController implements AuthenticationLoopThrottlingController { @@ -32,11 +32,6 @@ class StepupController implements AuthenticationLoopThrottlingController */ private $engineBlockApplicationSingleton; - /** - * @var Session - */ - private $session; - /** * @var RequestValidator */ @@ -54,13 +49,11 @@ class StepupController implements AuthenticationLoopThrottlingController public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, - Session $session, RequestValidator $requestValidator, RequestValidator $bindingValidator, RequestValidator $samlResponseValidator ) { $this->engineBlockApplicationSingleton = $engineBlockApplicationSingleton; - $this->session = $session; $this->requestValidator = $requestValidator; $this->bindingValidator = $bindingValidator; $this->responseValidator = $samlResponseValidator; @@ -69,6 +62,8 @@ public function __construct( /** * @param Request $request * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * + * @Route("/authentication/stepup/consume-assertion", name="authentication_stepup_consume_assertion", methods={"POST"}) */ public function consumeAssertionAction(Request $request) { diff --git a/src/OpenConext/EngineBlockBundle/Controller/WayfController.php b/src/OpenConext/EngineBlockBundle/Controller/WayfController.php index 07ce836aba..589c9e2791 100644 --- a/src/OpenConext/EngineBlockBundle/Controller/WayfController.php +++ b/src/OpenConext/EngineBlockBundle/Controller/WayfController.php @@ -28,7 +28,8 @@ use Psr\Log\LogLevel; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; -use Twig_Environment; +use Symfony\Component\Routing\Annotation\Route; +use Twig\Environment; class WayfController { @@ -37,7 +38,7 @@ class WayfController */ private $engineBlockApplicationSingleton; /** - * @var Twig_Environment + * @var Environment */ private $twig; /** @@ -56,12 +57,12 @@ class WayfController /** * @param EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton - * @param Twig_Environment $twig + * @param Environment $twig * @param SsoSessionService $sessionService */ public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, - Twig_Environment $twig, + Environment $twig, SsoSessionService $sessionService, DiscoverySelectionService $discoverySelectionService, LoggerInterface $logger @@ -74,7 +75,7 @@ public function __construct( } /** - * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response + * @Route("/authentication/idp/process-wayf", name="authentication_wayf_process_wayf", methods={"GET", "POST"}) */ public function processWayfAction(Request $request) { @@ -101,10 +102,7 @@ public function processWayfAction(Request $request) } /** - * This method is not used in the skeune theme - * - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/idp/help-discover", name="authentication_wayf_help_discover", methods={"GET"}) */ public function helpDiscoverAction() { @@ -124,8 +122,7 @@ private function getCookies(): array } /** - * @return Response - * @throws \EngineBlock_Exception + * @Route("/authentication/idp/remove-cookies", name="authentication_wayf_remove_cookie", methods={"GET", "POST"}) */ public function cookieAction(Request $request) { diff --git a/src/OpenConext/EngineBlockBundle/DependencyInjection/Configuration.php b/src/OpenConext/EngineBlockBundle/DependencyInjection/Configuration.php deleted file mode 100644 index 02f5676cb9..0000000000 --- a/src/OpenConext/EngineBlockBundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,88 +0,0 @@ -root('open_conext_engine_block'); - - $this->appendFeatureConfiguration($root); - $this->appendErrorFeedbackConfiguration($root); - - return $treeBuilder; - } - - public function appendFeatureConfiguration(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('features') - ->prototype('boolean') - ->example('some.feature.key: true') - ->info('Allows configuring a feature, identified by the feature key as enabled or disabled') - ->end() - ->end() - ->end(); - } - - private function appendErrorFeedbackConfiguration(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('error_feedback') - ->children() - ->arrayNode('wiki_links') - ->children() - ->arrayNode('fallback') - ->isRequired() - ->info('Provide a fallback wiki link that is used when a language/page combination cannot be found.') - ->scalarPrototype() - ->info('Provide a URI to the default/fallback wiki page for this specific error page language combination. - Please review the example in parameter.yml.dist') - ->end() - ->end() - ->arrayNode('specified') - ->arrayPrototype() - ->info('Please specify an array of i18n language abbreviation keys, mapped to wiki links matching - that language. Example: [en => https://wiki.example.com/page1, pt => https://wiki.example.pt/page1].') - ->scalarPrototype() - ->info('Provide a URI to the wiki page for this specific error page language combination. - Please review the example in parameter.yml.dist') - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('idp_contact') - ->scalarPrototype() - ->info('Specify page identifiers to show the IdP mailto link on.') - ->end() - ->end() - ->end() - ->end() - ->end(); - } -} diff --git a/src/OpenConext/EngineBlockBundle/DependencyInjection/OpenConextEngineBlockExtension.php b/src/OpenConext/EngineBlockBundle/DependencyInjection/OpenConextEngineBlockExtension.php deleted file mode 100644 index cf8aea0604..0000000000 --- a/src/OpenConext/EngineBlockBundle/DependencyInjection/OpenConextEngineBlockExtension.php +++ /dev/null @@ -1,90 +0,0 @@ -processConfiguration(new Configuration(), $configs); - - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('controllers.yml'); - $loader->load('event_listeners.yml'); - $loader->load('repositories.yml'); - $loader->load('services.yml'); - $loader->load('logging.yml'); - - $loader->load('bridge.yml'); - $loader->load('bridge_event_listeners.yml'); - $loader->load('compat.yml'); - - $this->overwriteDefaultLogger($container); - $this->setUrlParameterBasedOnEnv($container); - $this->setFeatureConfiguration($container, $configuration['features']); - } - - /** - * @param ContainerBuilder $container - */ - private function overwriteDefaultLogger(ContainerBuilder $container) - { - $container->removeAlias('logger'); - $container->setAlias('logger', 'monolog.logger.'.$container->getParameter('logger.channel')); - } - - /** - * @param ContainerBuilder $container - */ - private function setUrlParameterBasedOnEnv(ContainerBuilder $container) - { - if (in_array($container->getParameter('kernel.environment'), ['dev', 'test', 'ci'])) { - $container->setParameter( - 'engineblock_url', - sprintf('https://engine.%s', $container->getParameter('domain')) - ); - } - } - - /** - * Loads the feature configuration in a manner that can be dumped in the container cache - * - * @param ContainerBuilder $container - * @param array $featureConfiguration - */ - private function setFeatureConfiguration(ContainerBuilder $container, array $featureConfiguration) - { - // do note that duplicates cannot exist since the feature keys are keys in the configuration, which are - // enforced to be unique by the config component. - $features = []; - foreach ($featureConfiguration as $feature => $onOrOff) { - $features[$feature] = new Definition(Feature::class, [$feature, $onOrOff]); - } - - $featureConfigurationService = $container->getDefinition('engineblock.features'); - $featureConfigurationService->replaceArgument(0, $features); - } -} diff --git a/src/OpenConext/EngineBlockBundle/Doctrine/DqlFunction/Md5.php b/src/OpenConext/EngineBlockBundle/Doctrine/DqlFunction/Md5.php index cb3df9fee6..486167e0e1 100644 --- a/src/OpenConext/EngineBlockBundle/Doctrine/DqlFunction/Md5.php +++ b/src/OpenConext/EngineBlockBundle/Doctrine/DqlFunction/Md5.php @@ -19,30 +19,26 @@ namespace OpenConext\EngineBlockBundle\Doctrine\DqlFunction; use Doctrine\ORM\Query\AST\Functions\FunctionNode; -use Doctrine\ORM\Query\Lexer; use Doctrine\ORM\Query\Parser; use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\TokenType; class Md5 extends FunctionNode { public $value; - public function getSql(SqlWalker $walker) + public function getSql(SqlWalker $sqlWalker): string { - $platform = $walker->getConnection()->getDatabasePlatform(); - - return $platform->getMd5Expression( - $this->value->dispatch($walker) - ); + return 'MD5(' . $this->value->dispatch($sqlWalker) . ')'; } - public function parse(Parser $parser) + public function parse(Parser $parser): void { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(TokenType::T_IDENTIFIER); + $parser->match(TokenType::T_OPEN_PARENTHESIS); $this->value = $parser->StringPrimary(); - $parser->match(Lexer::T_CLOSE_PARENTHESIS); + $parser->match(TokenType::T_CLOSE_PARENTHESIS); } } diff --git a/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdType.php b/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdType.php index febc11a6f3..855c9c492c 100644 --- a/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdType.php +++ b/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdType.php @@ -28,26 +28,27 @@ class CollabPersonIdType extends Type { const NAME = 'engineblock_collab_person_id'; - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string { // overwrite the fieldDeclaration to always be MAX_LENGTH characters max, this is also enforced in the VO. $fieldDeclaration['length'] = CollabPersonId::MAX_LENGTH; - return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration); + return $platform->getStringTypeDeclarationSQL($fieldDeclaration); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; } if (!$value instanceof CollabPersonId) { + $valueForMessage = $this->getValueForExceptionMessage($value); throw new ConversionException( sprintf( 'Value "%s" must be null or an instance of CollabPersonId to be able to ' . 'convert it to a database value', - is_object($value) ? get_class($value) : (string)$value + $valueForMessage ) ); } @@ -55,7 +56,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) return $value->getCollabPersonId(); } - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; @@ -65,11 +66,12 @@ public function convertToPHPValue($value, AbstractPlatform $platform) $entityId = new CollabPersonId($value); } catch (InvalidArgumentException $e) { // get nice standard message, so we can throw it keeping the exception chain - $doctrineExceptionMessage = ConversionException::conversionFailedFormat( + $doctrineExceptionMessage = sprintf( + 'Could not convert database value "%s" to Doctrine Type %s. Expected format: %s', $value, $this->getName(), 'a valid CollabPersonId' - )->getMessage(); + ); throw new ConversionException($doctrineExceptionMessage, 0, $e); } @@ -77,8 +79,29 @@ public function convertToPHPValue($value, AbstractPlatform $platform) return $entityId; } - public function getName() + public function getName(): string { return self::NAME; } + + /** + * @see https://github.com/doctrine/DoctrineBundle/issues/977#issuecomment-497215968 + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) : bool + { + return true; + } + + private function getValueForExceptionMessage($value): string + { + if (is_object($value)) { + return get_class($value); + } + + if (is_array($value)) { + return 'Array'; + } + + return (string)$value; + } } diff --git a/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidType.php b/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidType.php index 95c2a536a7..0df007518e 100644 --- a/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidType.php +++ b/src/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidType.php @@ -28,23 +28,24 @@ class CollabPersonUuidType extends Type { const NAME = 'engineblock_collab_person_uuid'; - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { - return $platform->getGuidTypeDeclarationSQL($fieldDeclaration); + return $platform->getGuidTypeDeclarationSQL($column); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; } if (!$value instanceof CollabPersonUuid) { + $valueForMessage = $this->getValueForExceptionMessage($value); throw new ConversionException( sprintf( 'Value "%s" must be null or an instance of CollabPersonUuid to be able to ' . 'convert it to a database value', - is_object($value) ? get_class($value) : (string)$value + $valueForMessage ) ); } @@ -52,7 +53,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) return $value->getUuid(); } - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; @@ -62,11 +63,12 @@ public function convertToPHPValue($value, AbstractPlatform $platform) $collabPersonUuid = new CollabPersonUuid($value); } catch (InvalidArgumentException $e) { // get nice standard message, so we can throw it keeping the exception chain - $doctrineExceptionMessage = ConversionException::conversionFailedFormat( + $doctrineExceptionMessage = sprintf( + 'Could not convert database value "%s" to Doctrine Type %s. Expected format: %s', $value, $this->getName(), 'valid UUIDv4' - )->getMessage(); + ); throw new ConversionException($doctrineExceptionMessage, 0, $e); } @@ -74,8 +76,29 @@ public function convertToPHPValue($value, AbstractPlatform $platform) return $collabPersonUuid; } - public function getName() + public function getName(): string { return self:: NAME; } + + /** + * @see https://github.com/doctrine/DoctrineBundle/issues/977#issuecomment-497215968 + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) : bool + { + return true; + } + + private function getValueForExceptionMessage($value): string + { + if (is_object($value)) { + return get_class($value); + } + + if (is_array($value)) { + return 'Array'; + } + + return (string)$value; + } } diff --git a/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataCoinType.php b/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataCoinType.php index a7d13b3057..e0dbbc0197 100644 --- a/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataCoinType.php +++ b/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataCoinType.php @@ -28,15 +28,15 @@ class MetadataCoinType extends Type { const NAME = 'engineblock_metadata_coins'; - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { // We want a `TEXT` field declaration in our column, the `LONGTEXT` default causes issues when running the // DBMS in strict mode. - $fieldDeclaration['length'] = 65535; - return $platform->getJsonTypeDeclarationSQL($fieldDeclaration); + $column['length'] = 65535; + return $platform->getJsonTypeDeclarationSQL($column); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; @@ -55,12 +55,12 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) return $value->toJson(); } - public function getMappedDatabaseTypes(AbstractPlatform $platform) + public function getMappedDatabaseTypes(AbstractPlatform $platform): array { return parent::getMappedDatabaseTypes($platform); // TODO: Change the autogenerated stub } - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; @@ -70,11 +70,12 @@ public function convertToPHPValue($value, AbstractPlatform $platform) $coins = Coins::fromJson($value); } catch (InvalidArgumentException $e) { // get nice standard message, so we can throw it keeping the exception chain - $doctrineExceptionMessage = ConversionException::conversionFailedFormat( + $doctrineExceptionMessage = sprintf( + 'Could not convert database value "%s" to Doctrine Type %s. Expected format: %s', $value, $this->getName(), 'valid serialized coin json' - )->getMessage(); + ); throw new ConversionException($doctrineExceptionMessage, 0, $e); } @@ -82,8 +83,16 @@ public function convertToPHPValue($value, AbstractPlatform $platform) return $coins; } - public function getName() + public function getName(): string { return self::NAME; } + + /** + * @see https://github.com/doctrine/DoctrineBundle/issues/977#issuecomment-497215968 + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) : bool + { + return true; + } } diff --git a/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataMduiType.php b/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataMduiType.php index 312378ad6f..ed460e95e5 100644 --- a/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataMduiType.php +++ b/src/OpenConext/EngineBlockBundle/Doctrine/Type/MetadataMduiType.php @@ -28,15 +28,15 @@ class MetadataMduiType extends Type { const NAME = 'engineblock_metadata_mdui'; - public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { // We want a `TEXT` field declaration in our column, the `LONGTEXT` default causes issues when running the // DBMS in strict mode. - $fieldDeclaration['length'] = 65535; - return $platform->getJsonTypeDeclarationSQL($fieldDeclaration); + $column['length'] = 65535; + return $platform->getJsonTypeDeclarationSQL($column); } - public function convertToDatabaseValue($value, AbstractPlatform $platform) + public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; @@ -55,7 +55,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) return $value->toJson(); } - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue($value, AbstractPlatform $platform): mixed { if (is_null($value)) { return $value; @@ -65,11 +65,12 @@ public function convertToPHPValue($value, AbstractPlatform $platform) $mdui = Mdui::fromJson($value); } catch (InvalidArgumentException $e) { // get nice standard message, so we can throw it keeping the exception chain - $doctrineExceptionMessage = ConversionException::conversionFailedFormat( + $doctrineExceptionMessage = sprintf( + 'Could not convert database value "%s" to Doctrine Type %s. Expected format: %s', $value, $this->getName(), 'valid serialized mdui json' - )->getMessage(); + ); throw new ConversionException($doctrineExceptionMessage, 0, $e); } @@ -77,8 +78,16 @@ public function convertToPHPValue($value, AbstractPlatform $platform) return $mdui; } - public function getName() + public function getName(): string { return self::NAME; } + + /** + * @see https://github.com/doctrine/DoctrineBundle/issues/977#issuecomment-497215968 + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) : bool + { + return true; + } } diff --git a/src/OpenConext/EngineBlockBundle/EventListener/ApiHttpExceptionListener.php b/src/OpenConext/EngineBlockBundle/EventListener/ApiHttpExceptionListener.php index 4691e7ae8f..0dfe1dff92 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/ApiHttpExceptionListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/ApiHttpExceptionListener.php @@ -22,7 +22,7 @@ use OpenConext\EngineBlockBridge\ErrorReporter; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; class ApiHttpExceptionListener { @@ -46,9 +46,9 @@ public function __construct(LoggerInterface $logger, ErrorReporter $errorReporte $this->errorReporter = $errorReporter; } - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); if (!$exception instanceof ApiHttpException) { return; diff --git a/src/OpenConext/EngineBlockBundle/EventListener/AuthenticationStateInitializer.php b/src/OpenConext/EngineBlockBundle/EventListener/AuthenticationStateInitializer.php index 82deceeb02..308998d0e2 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/AuthenticationStateInitializer.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/AuthenticationStateInitializer.php @@ -21,6 +21,7 @@ use EngineBlock_ApplicationSingleton; use OpenConext\EngineBlockBundle\Authentication\AuthenticationState; use OpenConext\EngineBlockBundle\Controller\AuthenticationLoopThrottlingController; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; @@ -31,12 +32,12 @@ final class AuthenticationStateInitializer */ private $session; - public function __construct(Session $session) + public function __construct(RequestStack $requestStack) { - $this->session = $session; + $this->session = $requestStack->getSession(); } - public function onKernelController(FilterControllerEvent $event) + public function onKernelController(\Symfony\Component\HttpKernel\Event\ControllerEvent $event) { if (!$event->getController()[0] instanceof AuthenticationLoopThrottlingController) { return; diff --git a/src/OpenConext/EngineBlockBundle/EventListener/ExecutionTimePaddingListener.php b/src/OpenConext/EngineBlockBundle/EventListener/ExecutionTimePaddingListener.php index 702b8aaf27..d3b6b443f6 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/ExecutionTimePaddingListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/ExecutionTimePaddingListener.php @@ -23,7 +23,7 @@ use OpenConext\EngineBlockBundle\Value\ExecutionTime; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; final class ExecutionTimePaddingListener @@ -67,9 +67,9 @@ public function __construct( $this->minimumExecutionTime = $minimumExecutionTime; } - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); if (!$exception instanceof AddExecutionTimePadding) { return; diff --git a/src/OpenConext/EngineBlockBundle/EventListener/FallbackExceptionListener.php b/src/OpenConext/EngineBlockBundle/EventListener/FallbackExceptionListener.php index 8fbc46f405..23f2e410da 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/FallbackExceptionListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/FallbackExceptionListener.php @@ -22,7 +22,7 @@ use OpenConext\EngineBlockBridge\ErrorReporter; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** @@ -66,9 +66,9 @@ public function __construct( $this->urlGenerator = $urlGenerator; } - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); $this->logger->debug(sprintf( 'Caught Exception "%s":"%s"', diff --git a/src/OpenConext/EngineBlockBundle/EventListener/LocaleListener.php b/src/OpenConext/EngineBlockBundle/EventListener/LocaleListener.php index 2bef7315b1..ccf75521be 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/LocaleListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/LocaleListener.php @@ -20,8 +20,8 @@ use OpenConext\EngineBlockBundle\Http\Cookies\CookieFactory; use OpenConext\EngineBlockBundle\Localization\LocaleProvider; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; final class LocaleListener { @@ -45,7 +45,7 @@ public function __construct(LocaleProvider $localeProvider, CookieFactory $cooki $this->cookieFactory = $cookieFactory; } - public function onKernelRequest(GetResponseEvent $event) + public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); @@ -54,7 +54,7 @@ public function onKernelRequest(GetResponseEvent $event) $request->setLocale($this->localeProvider->getLocale()); } - public function onKernelResponse(FilterResponseEvent $event) + public function onKernelResponse(ResponseEvent $event) { $cookie = $this->cookieFactory->createCookie($this->localeProvider->getLocale()); $event->getResponse()->headers->setCookie($cookie); diff --git a/src/OpenConext/EngineBlockBundle/EventListener/MethodNotAllowedHttpExceptionListener.php b/src/OpenConext/EngineBlockBundle/EventListener/MethodNotAllowedHttpExceptionListener.php index e92c4ad460..cad5a1428b 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/MethodNotAllowedHttpExceptionListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/MethodNotAllowedHttpExceptionListener.php @@ -21,14 +21,14 @@ use EngineBlock_ApplicationSingleton; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Twig_Environment; +use Twig\Environment; final class MethodNotAllowedHttpExceptionListener { /** - * @var Twig_Environment + * @var Environment */ private $twig; /** @@ -38,20 +38,20 @@ final class MethodNotAllowedHttpExceptionListener /** * @param EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton - * @param Twig_Environment $twig + * @param Environment $twig * @param LoggerInterface $logger */ public function __construct( - Twig_Environment $twig, + Environment $twig, LoggerInterface $logger ) { $this->twig = $twig; $this->logger = $logger; } - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); if (!$exception instanceof MethodNotAllowedHttpException) { return; } diff --git a/src/OpenConext/EngineBlockBundle/EventListener/NotFoundHttpExceptionListener.php b/src/OpenConext/EngineBlockBundle/EventListener/NotFoundHttpExceptionListener.php index 4760477e6f..afdd307647 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/NotFoundHttpExceptionListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/NotFoundHttpExceptionListener.php @@ -22,9 +22,9 @@ use OpenConext\EngineBlockBundle\Http\Exception\ApiHttpException; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Twig_Environment; +use Twig\Environment; /** * When there was nothing to dispatch to, the dispatcher invoked a 404 page. This mimics that behaviour. When @@ -34,7 +34,7 @@ class NotFoundHttpExceptionListener { /** - * @var Twig_Environment + * @var Environment */ private $twig; /** @@ -48,12 +48,12 @@ class NotFoundHttpExceptionListener /** * @param EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton - * @param Twig_Environment $twig + * @param Environment $twig * @param LoggerInterface $logger */ public function __construct( EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton, - Twig_Environment $twig, + Environment $twig, LoggerInterface $logger ) { $this->engineBlockApplicationSingleton = $engineBlockApplicationSingleton; @@ -61,9 +61,9 @@ public function __construct( $this->logger = $logger; } - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); if (!$exception instanceof NotFoundHttpException) { return; } diff --git a/src/OpenConext/EngineBlockBundle/EventListener/RedirectToFeedbackPageExceptionListener.php b/src/OpenConext/EngineBlockBundle/EventListener/RedirectToFeedbackPageExceptionListener.php index fd332aee1e..2b0701171c 100644 --- a/src/OpenConext/EngineBlockBundle/EventListener/RedirectToFeedbackPageExceptionListener.php +++ b/src/OpenConext/EngineBlockBundle/EventListener/RedirectToFeedbackPageExceptionListener.php @@ -54,6 +54,7 @@ use OpenConext\EngineBlockBundle\Exception\UnknownKeyIdException; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -98,13 +99,13 @@ public function __construct( } /** - * @param GetResponseForExceptionEvent $event + * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event * * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - See comment in class doc block */ - public function onKernelException(GetResponseForExceptionEvent $event) + public function onKernelException(ExceptionEvent $event) { - $exception = $event->getException(); + $exception = $event->getThrowable(); $redirectParams = []; if ($exception instanceof EngineBlock_Corto_Module_Bindings_UnableToReceiveMessageException) { @@ -233,7 +234,9 @@ public function onKernelException(GetResponseForExceptionEvent $event) $redirectToRoute )); - $this->logger->notice($message); + if (isset($message)) { + $this->logger->notice($message); + } $this->errorReporter->reportError($exception, '-> Redirecting to feedback page'); diff --git a/src/OpenConext/EngineBlockBundle/Exception/InvalidArgumentException.php b/src/OpenConext/EngineBlockBundle/Exception/InvalidArgumentException.php index 5900d5f4ab..0d3608f000 100644 --- a/src/OpenConext/EngineBlockBundle/Exception/InvalidArgumentException.php +++ b/src/OpenConext/EngineBlockBundle/Exception/InvalidArgumentException.php @@ -29,7 +29,7 @@ public static function invalidType($expectedType, $propertyPath, $parameter) 'Invalid argument "%s": "%s" expected, "%s" given', $propertyPath, $expectedType, - is_object($parameter) ? get_class($parameter) : gettype($parameter) + get_debug_type($parameter) ) ); } diff --git a/src/OpenConext/EngineBlockBundle/HealthCheck/DoctrineConnectionHealthCheck.php b/src/OpenConext/EngineBlockBundle/HealthCheck/DoctrineConnectionHealthCheck.php index 41256f3618..1a62982852 100644 --- a/src/OpenConext/EngineBlockBundle/HealthCheck/DoctrineConnectionHealthCheck.php +++ b/src/OpenConext/EngineBlockBundle/HealthCheck/DoctrineConnectionHealthCheck.php @@ -52,12 +52,12 @@ public function __construct($query) * @param HealthReportInterface $report * @return HealthReportInterface */ - public function check(HealthReportInterface $report) + public function check(HealthReportInterface $report): HealthReportInterface { // Was the entityManager injected? When it is not the project does not use Doctrine ORM if (!is_null($this->entityManager)) { try { - $this->entityManager->getConnection()->query($this->query); + $this->entityManager->getConnection()->executeQuery($this->query); } catch (Exception $e) { return HealthReport::buildStatusDown('Unable to execute a query on the database.'); } diff --git a/src/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactory.php b/src/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactory.php index 3506c60645..abdb152505 100644 --- a/src/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactory.php +++ b/src/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactory.php @@ -94,14 +94,6 @@ public function createCookie($value) $expiresAt = $this->now->add(DateInterval::createFromDateString($this->expiryInSeconds . ' seconds')); } - return new Cookie( - $this->name, - $value, - $expiresAt, - '/', - $this->domain, - $this->secure, - $this->httpOnly - ); + return \Symfony\Component\HttpFoundation\Cookie::create($this->name, $value, $expiresAt, '/', $this->domain, $this->secure, $this->httpOnly); } } diff --git a/src/OpenConext/EngineBlockBundle/Monolog/Formatter/SyslogJsonFormatter.php b/src/OpenConext/EngineBlockBundle/Monolog/Formatter/SyslogJsonFormatter.php index f712817477..9501b056ca 100644 --- a/src/OpenConext/EngineBlockBundle/Monolog/Formatter/SyslogJsonFormatter.php +++ b/src/OpenConext/EngineBlockBundle/Monolog/Formatter/SyslogJsonFormatter.php @@ -22,12 +22,12 @@ class SyslogJsonFormatter extends JsonFormatter { - public function format(array $record) + public function format(array $record): string { return parent::format($this->mapRecord($record)); } - public function formatBatch(array $records) + public function formatBatch(array $records): string { return parent::formatBatch( array_map( diff --git a/src/OpenConext/EngineBlockBundle/OpenConextEngineBlockBundle.php b/src/OpenConext/EngineBlockBundle/OpenConextEngineBlockBundle.php index 7fc184edde..f89f1b2858 100644 --- a/src/OpenConext/EngineBlockBundle/OpenConextEngineBlockBundle.php +++ b/src/OpenConext/EngineBlockBundle/OpenConextEngineBlockBundle.php @@ -28,8 +28,8 @@ public function boot() $engineBlockApplicationSingleton = EngineBlock_ApplicationSingleton::getInstance(); $engineBlockApplicationSingleton->bootstrap( $this->container->get('monolog.logger.public'), - $this->container->get('engineblock.logger.manual_or_error_activation_strategy'), - $this->container->get('engineblock.request.request_id'), + $this->container->get(\OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy::class), + $this->container->get(\OpenConext\EngineBlock\Request\RequestId::class), $this->container ); } diff --git a/src/OpenConext/EngineBlockBundle/Pdp/PolicyDecision.php b/src/OpenConext/EngineBlockBundle/Pdp/PolicyDecision.php index 6d544c071a..126c23fdaa 100644 --- a/src/OpenConext/EngineBlockBundle/Pdp/PolicyDecision.php +++ b/src/OpenConext/EngineBlockBundle/Pdp/PolicyDecision.php @@ -79,10 +79,13 @@ public static function fromResponse(Response $response) : PolicyDecision $localizedDenyMessages = []; foreach ($response->associatedAdvices as $associatedAdvice) { foreach ($associatedAdvice->attributeAssignments as $attributeAssignment) { - list($identifier, $locale) = explode(':', $attributeAssignment->attributeId); + $parts = explode(':', $attributeAssignment->attributeId); + if (count($parts) >= 2) { + list($identifier, $locale) = $parts; - if ($identifier === 'DenyMessage') { - $localizedDenyMessages[$locale] = $attributeAssignment->value; + if ($identifier === 'DenyMessage') { + $localizedDenyMessages[$locale] = $attributeAssignment->value; + } } self::setAttributeAssignmentSource($attributeAssignment, $policyDecision); diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/bridge.yml b/src/OpenConext/EngineBlockBundle/Resources/config/bridge.yml deleted file mode 100644 index 4847baeb16..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/bridge.yml +++ /dev/null @@ -1,18 +0,0 @@ -services: - engineblock.bridge.error_reporter: - class: OpenConext\EngineBlockBridge\ErrorReporter - arguments: - - "@engineblock.compat.application" - - "@logger" - - "@session" - - engineblock.bridge.authentication_logger_adapter: - class: OpenConext\EngineBlockBridge\Logger\AuthenticationLoggerAdapter - arguments: - - "@engineblock.logger.authentication" - - engineblock.bridge.authentication.user_directory: - class: OpenConext\EngineBlockBridge\Authentication\Repository\UserDirectoryAdapter - arguments: - - "@engineblock.authentication.user_directory" - - "@logger" diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/controllers.yml b/src/OpenConext/EngineBlockBundle/Resources/config/controllers.yml deleted file mode 100644 index 842c4fc631..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/controllers.yml +++ /dev/null @@ -1,3 +0,0 @@ -imports: - - { resource: controllers/authentication.yml } - - { resource: controllers/api.yml } diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/controllers/api.yml b/src/OpenConext/EngineBlockBundle/Resources/config/controllers/api.yml deleted file mode 100644 index 03527e6941..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/controllers/api.yml +++ /dev/null @@ -1,41 +0,0 @@ -services: - engineblock.controller.api.connections: - class: OpenConext\EngineBlockBundle\Controller\Api\ConnectionsController - arguments: - - "@engineblock.metadata.push_metadata_assembler" - - "@security.authorization_checker" - - "@engineblock.features" - - "@engineblock.metadata_push.repository.doctrine" - - "%engineblock.metadata_push_memory_limit%" - - engineblock.controller.api.consent: - class: OpenConext\EngineBlockBundle\Controller\Api\ConsentController - arguments: - - "@security.authorization_checker" - - "@engineblock.features" - - "@engineblock.service.consent" - - engineblock.controller.api.deprovision: - class: OpenConext\EngineBlockBundle\Controller\Api\DeprovisionController - arguments: - - "@security.authorization_checker" - - "@engineblock.features" - - "@engineblock.service.deprovision" - - 'EngineBlock' - - engineblock.controller.api.heartbeat: - class: OpenConext\EngineBlockBundle\Controller\Api\HeartbeatController - - engineblock.controller.api.metadata: - class: OpenConext\EngineBlockBundle\Controller\Api\MetadataController - arguments: - - "@security.authorization_checker" - - "@engineblock.features" - - "@engineblock.service.metadata" - - engineblock.controller.api.attribute_release_policy: - class: OpenConext\EngineBlockBundle\Controller\Api\AttributeReleasePolicyController - arguments: - - "@security.authorization_checker" - - "@engineblock.service.metadata" - - "@engineblock.compat.attribute_release_policy_enforcer" diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/controllers/authentication.yml b/src/OpenConext/EngineBlockBundle/Resources/config/controllers/authentication.yml deleted file mode 100644 index 69c9a3930d..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/controllers/authentication.yml +++ /dev/null @@ -1,90 +0,0 @@ -services: - _defaults: - autowire: true - - engineblock.controller.authentication.service_provider: - class: OpenConext\EngineBlockBundle\Controller\ServiceProviderController - arguments: - - "@engineblock.compat.application" - - "@session" - - "@engineblock.validator.acs_request_validator" - - "@engineblock.validator.saml_binding_validator" - - "@engineblock.validator.saml_response_validator" - - engineblock.controller.authentication.identity_provider: - class: OpenConext\EngineBlockBundle\Controller\IdentityProviderController - arguments: - - "@engineblock.compat.application" - - "@twig" - - "@engineblock.compat.logger" - - "@engineblock.service.request_access_mailer" - - "@engineblock.validator.sso_request_validator" - - "@engineblock.validator.saml_binding_validator" - - "@engineblock.validator.unsolicited_sso_request_validator" - - "@engineblock.service.authentication_state_helper" - - "@engineblock.features" - - engineblock.controller.authentication.index: - class: OpenConext\EngineBlockBundle\Controller\IndexController - arguments: - - "@twig" - - "%encryption_keys%" - - engineblock.controller.authentication.feedback: - class: OpenConext\EngineBlockBundle\Controller\FeedbackController - arguments: - - "@translator" - - "@twig" - - "@engineblock.compat.logger" - - engineblock.controller.authentication.metadata: - class: OpenConext\EngineBlockBundle\Controller\MetadataController - arguments: - - '@OpenConext\EngineBlock\Xml\MetadataProvider' - - '@OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration' - - engineblock.controller.authentication.certificate: - class: OpenConext\EngineBlockBundle\Controller\CertificateController - arguments: - - "@engineblock.compat.application" - - engineblock.controller.authentication.debug: - class: OpenConext\EngineBlockBundle\Controller\DebugController - arguments: - - "@engineblock.compat.application" - - "@session" - - engineblock.controller.authentication.wayf: - class: OpenConext\EngineBlockBundle\Controller\WayfController - arguments: - - "@engineblock.compat.application" - - "@twig" - - "@engineblock.service.sso_session" - - "@engineblock.service.discovery_selection_service" - - "@engineblock.compat.logger" - - engineblock.controller.authentication.proxy: - class: OpenConext\EngineBlockBundle\Controller\ProxyController - arguments: - - "@engineblock.compat.application" - - engineblock.controller.authentication.stepup: - class: OpenConext\EngineBlockBundle\Controller\StepupController - arguments: - - "@engineblock.compat.application" - - "@session" - - "@engineblock.validator.acs_request_validator" - - "@engineblock.validator.saml_binding_validator" - - "@engineblock.validator.saml_response_validator" - - engineblock.controller.authentication.logout: - class: OpenConext\EngineBlockBundle\Controller\LogoutController - arguments: - - "@twig" - - "@engineblock.service.sso_session" - - engineblock.service.request_access_mailer: - class: OpenConext\EngineBlock\Service\RequestAccessMailer - arguments: - - "@mailer" - - "%email_request_access_address%" diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/event_listeners.yml b/src/OpenConext/EngineBlockBundle/Resources/config/event_listeners.yml deleted file mode 100644 index 3fa42e328e..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/event_listeners.yml +++ /dev/null @@ -1,79 +0,0 @@ -# also see bridge_event_listeners.yml for event listeners that provide bridge functionality -services: - engineblock.listener.execution_time_tracker: - class: OpenConext\EngineBlockBundle\EventListener\ExecutionTimeTracker - arguments: - - "@debug.stopwatch" - tags: - - { name: kernel.event_listener, event: kernel.request, method: startTracking, priority: 1000 } - - engineblock.listener.error_response_time_padding: - class: OpenConext\EngineBlockBundle\EventListener\ExecutionTimePaddingListener - arguments: - - "@engineblock.listener.execution_time_tracker" - - "@router" - - "@engineblock.compat.logger" - - "@engineblock.bridge.error_reporter" - - "@engineblock.minimum_execution_time_on_invalid_received_response" - tags: - - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 1000 } - - engineblock.listener.redirect_to_feedback_page_exception: - class: OpenConext\EngineBlockBundle\EventListener\RedirectToFeedbackPageExceptionListener - arguments: - - "@engineblock.compat.application" - - "@router" - - "@engineblock.bridge.error_reporter" - - "@engineblock.compat.logger" - tags: - - { name: kernel.event_listener, event: kernel.exception, method: onKernelException } - - engineblock.listener.api_http_exception_listener: - class: OpenConext\EngineBlockBundle\EventListener\ApiHttpExceptionListener - arguments: - - "@engineblock.compat.logger" - - "@engineblock.bridge.error_reporter" - tags: - - { name: kernel.event_listener, event: kernel.exception, method: onKernelException } - - engineblock.listener.not_found_http_exception: - class: OpenConext\EngineBlockBundle\EventListener\NotFoundHttpExceptionListener - arguments: - - "@engineblock.compat.application" - - "@twig" - - "@engineblock.compat.logger" - tags: - - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 25 } - - engineblock.listener.method_not_allowed_http_exception: - class: OpenConext\EngineBlockBundle\EventListener\MethodNotAllowedHttpExceptionListener - arguments: - - "@twig" - - "@engineblock.compat.logger" - tags: - - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 25 } - - engineblock.listener.fallback_exception: - class: OpenConext\EngineBlockBundle\EventListener\FallbackExceptionListener - arguments: - - "@engineblock.compat.logger" - - "@engineblock.bridge.error_reporter" - - "@router" - tags: - - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: -200 } - - engineblock.listener.authentication_state_initializer: - class: OpenConext\EngineBlockBundle\EventListener\AuthenticationStateInitializer - arguments: - - "@session" - tags: - - { name: kernel.event_listener, event: kernel.controller, method: onKernelController, priority: 10 } - - engineblock.listener.locale: - class: OpenConext\EngineBlockBundle\EventListener\LocaleListener - arguments: - - '@engineblock.locale_provider' - - '@engineblock.locale.cookie_factory' - tags: - - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 15 } - - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse, priority: 15 } diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/logging.yml b/src/OpenConext/EngineBlockBundle/Resources/config/logging.yml deleted file mode 100644 index 720d371c31..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/logging.yml +++ /dev/null @@ -1,45 +0,0 @@ -services: - - # Aliased the monolog logger for OpenConextEngineBlockBundle who boots the ApplicationSingleton without use of DI. - # Remove this once ApplicationSingleton is removed, or uses DI. - monolog.logger.public: - alias: 'monolog.logger' - public: true - - engineblock.logger.additional_info_formatter: - class: OpenConext\EngineBlock\Logger\Formatter\AdditionalInfoFormatter - arguments: - - "@engineblock.logger.line_formatter" - - engineblock.logger.line_formatter: - public: false - class: Monolog\Formatter\LineFormatter - arguments: - - "%logger.line_format%" - - engineblock.logger.manual_or_error_activation_strategy: - class: OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy - factory: [OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrErrorLevelActivationStrategyFactory, createActivationStrategy] - arguments: - - { action_level: "%logger.fingers_crossed.action_level%" } - public: true - - engineblock.logger.processor.request_id_processor: - class: OpenConext\EngineBlock\Logger\Processor\RequestIdProcessor - arguments: - - "@engineblock.request.request_id" - tags: - - { name: monolog.processor, method: processRecord } - - engineblock.logger.processor.session_id_processor: - class: OpenConext\EngineBlock\Logger\Processor\SessionIdProcessor - tags: - - { name: monolog.processor, method: processRecord } - - engineblock.logger.formatter.syslog_json: - class: OpenConext\EngineBlockBundle\Monolog\Formatter\SyslogJsonFormatter - - engineblock.logger.authentication: - class: OpenConext\EngineBlock\Logger\AuthenticationLogger - arguments: - - "@monolog.logger.authentication" diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/repositories.yml b/src/OpenConext/EngineBlockBundle/Resources/config/repositories.yml deleted file mode 100644 index ee2b295bde..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/repositories.yml +++ /dev/null @@ -1,43 +0,0 @@ -services: - engineblock.repository.consent: - public: false - class: OpenConext\EngineBlockBundle\Authentication\Repository\DbalConsentRepository - arguments: - - "@engineblock.compat.doctrine.dbal_connection" - - "@logger" - - engineblock.repository.user: - public: false - class: OpenConext\EngineBlockBundle\Authentication\Repository\UserRepository - factory: ["@doctrine.orm.entity_manager", getRepository] - arguments: - - 'OpenConext\EngineBlockBundle\Authentication\Entity\User' - - engineblock.repository.saml_persistent_id: - public: false - class: OpenConext\EngineBlockBundle\Authentication\Repository\SamlPersistentIdRepository - factory: ["@doctrine.orm.entity_manager", getRepository] - arguments: - - 'OpenConext\EngineBlockBundle\Authentication\Entity\SamlPersistentId' - - - engineblock.repository.service_provider_uuid: - public: false - class: OpenConext\EngineBlockBundle\Authentication\Repository\ServiceProviderUuidRepository - factory: ["@doctrine.orm.entity_manager", getRepository] - arguments: - - 'OpenConext\EngineBlockBundle\Authentication\Entity\ServiceProviderUuid' - - engineblock.repository.service_provider: - public: false - class: Doctrine\ORM\EntityRepository - factory: ["@doctrine.orm.entity_manager", getRepository] - arguments: - - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider' - - engineblock.repository.identity_provider: - public: false - class: Doctrine\ORM\EntityRepository - factory: ["@doctrine.orm.entity_manager", getRepository] - arguments: - - 'OpenConext\EngineBlock\Metadata\Entity\IdentityProvider' diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing.yml deleted file mode 100644 index 51be6ad67d..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing.yml +++ /dev/null @@ -1,33 +0,0 @@ -open_conext_engine_block_authentication_homepage: - path: / - defaults: { _controller: engineblock.controller.authentication.index:indexAction } - -authentication_sp_debug: - path: /authentication/sp/debug - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.debug:debugSpConnectionAction - -authentication_proxy_processed_assertion: - path: /authentication/proxy/processed-assertion - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.proxy:processedAssertionAction - -identity_provider: - resource: routing/identity_provider.yml - -service_provider: - resource: routing/service_provider.yml - -metadata: - resource: routing/metadata.yml - -feedback: - resource: routing/feedback.yml - -wayf: - resource: routing/wayf.yml - -logout: - resource: routing/logout.yml diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing/feedback.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing/feedback.yml deleted file mode 100644 index 2f8017d97c..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing/feedback.yml +++ /dev/null @@ -1,159 +0,0 @@ -feedback_unknown_error: - path: '/feedback/unknown-error' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownErrorAction } - -authentication_feedback_unable_to_receive_message: - path: '/authentication/feedback/unable-to-receive-message' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unableToReceiveMessageAction } - -authentication_feedback_session_lost: - path: '/authentication/feedback/session-lost' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:sessionLostAction } - -authentication_feedback_session_not_started: - path: '/authentication/feedback/session-not-started' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:sessionNotStartedAction } - -authentication_feedback_no_idps: - path: '/authentication/feedback/no-idps' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:noIdpsAction } - -authentication_feedback_invalid_acs_location: - path: '/authentication/feedback/invalidAcsLocation' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:invalidAcsLocationAction } - -authentication_feedback_unsupported_signature_method: - path: '/authentication/feedback/unsupportedSignatureMethod' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unsupportedSignatureMethodAction } - -authentication_feedback_unsupported_acs_location_uri_scheme: - path: '/authentication/feedback/unsupported-acs-location-scheme' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unsupportedAcsLocationSchemeAction } - -authentication_feedback_unknown_service_provider: - path: '/authentication/feedback/unknown-service-provider' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownServiceProviderAction } - -authentication_feedback_unknown_identity_provider: - path: '/authentication/feedback/unknown-identity-provider' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownIdentityProviderAction } - -authentication_feedback_unknown_signing_key: - path: '/authentication/feedback/unknown-signing-key' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownSigningKeyAction } - -authentication_feedback_missing_required_fields: - path: '/authentication/feedback/missing-required-fields' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:missingRequiredFieldsAction } - -authentication_authn_context_class_ref_blacklisted: - path: '/authentication/feedback/authn-context-class-ref-blacklisted' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:authnContextClassRefBlacklistedAction } - -authentication_invalid_mfa_authn_context_class_ref: - path: '/authentication/feedback/invalid-mfa-authn-context-class-ref' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:invalidMfAuthnContextClassRefAction } - -authentication_feedback_invalid_attribute_value: - path: '/authentication/feedback/invalid-attribute-value' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:invalidAttributeValueAction } - -authentication_feedback_custom: - path: '/authentication/feedback/custom' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:customAction } - -authentication_feedback_invalid_acs_binding: - path: '/authentication/feedback/invalid-acs-binding' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:invalidAcsBindingAction } - -authentication_feedback_received_error_status_code: - path: '/authentication/feedback/received-error-status-code' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:receivedErrorStatusCodeAction } - -authentication_feedback_signature_verification_failed: - path: '/authentication/feedback/received-invalid-signed-response' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:signatureVerificationFailedAction } - -authentication_feedback_verification_failed: - path: '/authentication/feedback/received-invalid-response' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:receivedInvalidResponseAction } - -authentication_feedback_unknown_requesterid_in_authnrequest: - path: '/authentication/feedback/unknown_requesterid_in_authnrequest' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownRequesterIdInAuthnRequestAction } - -authentication_feedback_pep_violation: - path: '/authentication/feedback/authorization-policy-violation' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:authorizationPolicyViolationAction } - -authentication_feedback_unknown_keyid: - path: '/authentication/feedback/unknown-keyid' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownKeyIdAction } - -authentication_feedback_unknown_preselected_idp: - path: '/authentication/feedback/unknown-preselected-idp' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:unknownPreselectedIdpAction } - -authentication_feedback_stuck_in_authentication_loop: - path: '/authentication/feedback/stuck-in-authentication-loop' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:stuckInAuthenticationLoopAction } - -authentication_feedback_authentication_limit_exceeded: - path: '/authentication/feedback/authentication-limit-exceeded' - methods: [ GET ] - defaults: { _controller: engineblock.controller.authentication.feedback:authenticationLimitExceededAction } - -authentication_feedback_no_authentication_request_received: - path: '/authentication/feedback/invalid-request-method-on-sso' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:noAuthenticationRequestReceivedAction } - -authentication_feedback_response_clock_issue: - path: '/authentication/feedback/clock-issue' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:clockIssueAction } - -authentication_feedback_stepup_callout_user_cancelled: - path: '/authentication/feedback/stepup-callout-user-cancelled' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:stepupCalloutUserCancelledAction } - -authentication_feedback_stepup_callout_unmet_loa: - path: '/authentication/feedback/stepup-callout-unmet-loa' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:stepupCalloutUnmetLoaAction } - -authentication_feedback_stepup_callout_unknown: - path: '/authentication/feedback/stepup-callout-unknown' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:stepupCalloutUnknownAction } - -authentication_feedback_metadata_entity_not_found: - path: '/authentication/feedback/metadata-entity-not-found' - methods: [GET] - defaults: { _controller: engineblock.controller.authentication.feedback:metadataEntityNotFoundAction } diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing/identity_provider.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing/identity_provider.yml deleted file mode 100644 index 14691039c4..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing/identity_provider.yml +++ /dev/null @@ -1,93 +0,0 @@ -# see https://github.com/OpenConext/OpenConext-engineblock/blob/cd83052a9da183ae057ba7ba3436195961a75c0c/theme/material/javascripts/application.js#L336 -authentication_idp_request_access: - path: '/authentication/idp/requestAccess' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.identity_provider:requestAccessAction - -# see https://github.com/OpenConext/OpenConext-engineblock/blob/cd83052a9da183ae057ba7ba3436195961a75c0c/theme/material/javascripts/application.js#L231 -authentication_idp_perform_request_access_two: - path: '/authentication/idp/performRequestAccess' - methods: [POST] - defaults: - _controller: engineblock.controller.authentication.identity_provider:performRequestAccessAction - -authentication_idp_process_consent: - path: '/authentication/idp/process-consent' - methods: [POST] - defaults: - _controller: engineblock.controller.authentication.identity_provider:processConsentAction - -### Sollicited - -authentication_idp_sso: - path: '/authentication/idp/single-sign-on' - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.identity_provider:singleSignOnAction - idpHash: ~ - keyId: ~ - -authentication_idp_sso_keyid: - path: '/authentication/idp/single-sign-on/key:{keyId}' - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.identity_provider:singleSignOnAction - idpHash: ~ - requirements: - idpHash: .+ - -authentication_idp_sso_keyid_idphash: - path: '/authentication/idp/single-sign-on/key:{keyId}/{idpHash}' - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.identity_provider:singleSignOnAction - requirements: - keyId: .+ - idpHash: .+ - -authentication_idp_sso_idphash: - path: '/authentication/idp/single-sign-on/{idpHash}' - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.identity_provider:singleSignOnAction - keyId: ~ - requirements: - idpHash: .+ - -### Unsollicited - -authentication_idp_unsolicited_sso: - path: '/authentication/idp/unsolicited-single-sign-on' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.identity_provider:unsolicitedSingleSignOnAction - idpHash: ~ - keyId: ~ - -authentication_idp_unsolicited_sso_keyid: - path: '/authentication/idp/unsolicited-single-sign-on/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.identity_provider:unsolicitedSingleSignOnAction - idpHash: ~ - requirements: - idpHash: .+ - -authentication_idp_unsolicited_sso_keyid_idphash: - path: '/authentication/idp/unsolicited-single-sign-on/key:{keyId}/{idpHash}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.identity_provider:unsolicitedSingleSignOnAction - requirements: - keyId: .+ - idpHash: .+ - -authentication_idp_unsolicited_sso_idphash: - path: '/authentication/idp/unsolicited-single-sign-on/{idpHash}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.identity_provider:unsolicitedSingleSignOnAction - keyId: ~ - requirements: - idpHash: .+ diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing/logout.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing/logout.yml deleted file mode 100644 index d07b9cee81..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing/logout.yml +++ /dev/null @@ -1,5 +0,0 @@ -authentication_logout: - path: /logout - methods: [GET,POST] # verify POST? - defaults: - _controller: engineblock.controller.authentication.logout:logoutAction diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing/metadata.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing/metadata.yml deleted file mode 100644 index bc33c4fa02..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing/metadata.yml +++ /dev/null @@ -1,99 +0,0 @@ -### Idp - -metadata_idp: - path: '/authentication/idp/metadata' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:idpMetadataAction - keyId: ~ - -metadata_idp_key: - path: '/authentication/idp/metadata/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:idpMetadataAction - requirements: - keyId: .+ - -### Sp - -metadata_sp: - path: '/authentication/sp/metadata' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:spMetadataAction - keyId: '' - -metadata_sp_key: - path: '/authentication/sp/metadata/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:spMetadataAction - requirements: - keyId: .+ - -### IdPs -metadata_all_idps: - path: '/authentication/proxy/idps-metadata' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:allIdpsMetadataAction - keyId: ~ - -metadata_all_idps_key: - path: '/authentication/proxy/idps-metadata/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:allIdpsMetadataAction - requirements: - keyId: .+ - -### Stepup -metadata_stepup: - path: '/authentication/stepup/metadata' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:stepupMetadataAction - keyId: ~ - -metadata_stepup_key: - path: '/authentication/stepup/metadata/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:stepupMetadataAction - requirements: - keyId: .+ - -### Certificate: IdP - -certificate_idp: - path: '/authentication/idp/certificate' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:signingCertificateAction - keyId: ~ - -certificate_idp_key: - path: '/authentication/idp/certificate/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:signingCertificateAction - requirements: - keyId: .+ - -## Certificate: Sp - -certificate_sp: - path: '/authentication/sp/certificate' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:signingCertificateAction - keyId: ~ - -certificate_sp_key: - path: '/authentication/sp/certificate/key:{keyId}' - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.metadata:signingCertificateAction - requirements: - keyId: .+ diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing/service_provider.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing/service_provider.yml deleted file mode 100644 index f6f50410a9..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing/service_provider.yml +++ /dev/null @@ -1,18 +0,0 @@ -authentication_sp_consume_assertion: - path: /authentication/sp/consume-assertion - methods: [POST] - defaults: - _controller: engineblock.controller.authentication.service_provider:consumeAssertionAction - -authentication_sp_process_consent: - path: /authentication/sp/process-consent - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.service_provider:processConsentAction - -# Stepup authentication -authentication_stepup_consume_assertion: - path: /authentication/stepup/consume-assertion - methods: [POST] - defaults: - _controller: engineblock.controller.authentication.stepup:consumeAssertionAction diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing/wayf.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing/wayf.yml deleted file mode 100644 index fbe7946fe2..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing/wayf.yml +++ /dev/null @@ -1,17 +0,0 @@ -authentication_wayf_process_wayf: - path: /authentication/idp/process-wayf - methods: [GET,POST] # verify GET? - defaults: - _controller: engineblock.controller.authentication.wayf:processWayfAction - -authentication_wayf_help_discover: - path: /authentication/idp/help-discover - methods: [GET] - defaults: - _controller: engineblock.controller.authentication.wayf:helpDiscoverAction - -authentication_wayf_remove_cookie: - path: /authentication/idp/remove-cookies - methods: [GET,POST] - defaults: - _controller: engineblock.controller.authentication.wayf:cookieAction diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/routing_api.yml b/src/OpenConext/EngineBlockBundle/Resources/config/routing_api.yml deleted file mode 100644 index 2ee35a9f2d..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/routing_api.yml +++ /dev/null @@ -1,63 +0,0 @@ -# This routing file is separated due to being hosted on a different sub-domain -# see app/config/routing.yml -# Allowed methods are registered in the controllers so API specific exceptions are thrown - -api_heartbeat: - path: / - defaults: - _controller: engineblock.controller.api.heartbeat:itWorksAction - _format: json - -api_connections: - path: /api/connections - defaults: - _controller: engineblock.controller.api.connections:pushConnectionsAction - _format: json - -api_consent_user: - path: /consent/{userId} - requirements: - userId: .+ - defaults: - _controller: engineblock.controller.api.consent:userAction - _format: json - -api_remove_consent_user: - path: /remove-consent - defaults: - _controller: engineblock.controller.api.consent:removeAction - _format: json - -api_deprovision_delete_user_data_dry_run: - path: /deprovision/{collabPersonId}/dry-run - requirements: - collabPersonId: .+ - defaults: - _controller: engineblock.controller.api.deprovision:dryRunAction - _format: json - -api_deprovision_get_user_data: - path: /deprovision/{collabPersonId} - requirements: - collabPersonId: .+ - defaults: - _controller: engineblock.controller.api.deprovision:userDataAction - _format: json - -api_metadata_idp: - path: /metadata/idp - defaults: - _controller: engineblock.controller.api.metadata:idpAction - _format: json - -api_apply_attribute_release_policy: - path: /arp - defaults: - _controller: engineblock.controller.api.attribute_release_policy:applyArpAction - _format: json - -api_read_attribute_release_policy: - path: /read-arp - defaults: - _controller: engineblock.controller.api.attribute_release_policy:readArpAction - _format: json diff --git a/src/OpenConext/EngineBlockBundle/Resources/config/services.yml b/src/OpenConext/EngineBlockBundle/Resources/config/services.yml deleted file mode 100644 index df8b1b8637..0000000000 --- a/src/OpenConext/EngineBlockBundle/Resources/config/services.yml +++ /dev/null @@ -1,383 +0,0 @@ -services: - OpenConext\EngineBlock\Xml\: - resource: '../../../EngineBlock/Xml' - exclude: '../../../EngineBlock/Xml/ValueObjects' - autowire: true - autoconfigure: true - - openconext.monitor.database_health_check: - class: OpenConext\EngineBlockBundle\HealthCheck\DoctrineConnectionHealthCheck - arguments: - - "%monitor_database_health_check_query%" - calls: - - [ setEntityManager, ['@?doctrine.orm.entity_manager']] - tags: - - { name: openconext.monitor.health_check } - - engineblock.minimum_execution_time_on_invalid_received_response: - class: OpenConext\EngineBlockBundle\Value\ExecutionTime - factory: [ OpenConext\EngineBlockBundle\Value\ExecutionTime, "of" ] - arguments: - - "%minimum_execution_time_on_invalid_received_response%" - - engineblock.configuration.stepup.endpoint: - class: OpenConext\EngineBlock\Stepup\StepupEndpoint - arguments: - - "%stepup.gateway.sfo.entity_id%" - - "%stepup.gateway.sfo.sso_location%" - - "%stepup.gateway.sfo.key_file%" - - engineblock.configuration.stepup.loa_repository: - class: OpenConext\EngineBlock\Metadata\LoaRepository - arguments: - - "%stepup.loa.mapping%" - - engineblock.configuration.stepup.gateway_loa_mapping: - class: OpenConext\EngineBlock\Stepup\StepupGatewayLoaMapping - arguments: - - "%stepup.loa.mapping%" - - "%stepup.loa.loa1%" - - "@engineblock.configuration.stepup.loa_repository" - - engineblock.request.request_id_generator: - public: false - class: OpenConext\EngineBlock\Request\UniqidGenerator - - engineblock.request.request_id: - class: OpenConext\EngineBlock\Request\RequestId - arguments: - - "@engineblock.request.request_id_generator" - public: true - - engineblock.security.http_basic_entry_point: - class: OpenConext\EngineBlockBundle\Security\Http\EntryPoint\JsonBasicAuthenticationEntryPoint - arguments: - - "engine-api.%domain%" - - engineblock.service.authentication_state_helper: - class: OpenConext\EngineBlock\Service\AuthenticationStateHelper - arguments: - - "@session" - - engineblock.service.processing_state_helper: - class: OpenConext\EngineBlock\Service\ProcessingStateHelper - arguments: - - "@session" - - engineblock.service.stepup.gateway_callout_helper: - class: OpenConext\EngineBlock\Stepup\StepupGatewayCallOutHelper - arguments: - - "@engineblock.configuration.stepup.gateway_loa_mapping" - - "@engineblock.configuration.stepup.loa_repository" - - "@logger" - - engineblock.service.consent: - class: OpenConext\EngineBlock\Service\ConsentService - arguments: - - "@engineblock.repository.consent" - - "@engineblock.service.metadata" - - "@engineblock.compat.logger" - - engineblock.service.deprovision: - class: OpenConext\EngineBlock\Service\DeprovisionService - arguments: - - "@engineblock.repository.consent" - - "@engineblock.authentication.user_directory" - - "@engineblock.repository.saml_persistent_id" - - "@engineblock.repository.service_provider_uuid" - - engineblock.service.metadata: - class: OpenConext\EngineBlock\Service\MetadataService - arguments: - - "@engineblock.compat.repository.metadata" - - "@engineblock.compat.logger" - - engineblock.service.mfa_helper: - class: OpenConext\EngineBlock\Service\MfaHelper - arguments: - - "@engineblock.compat.logger" - - "@engineblock.metadata.repository.cached_doctrine" - - engineblock.service.time_provider: - class: OpenConext\EngineBlock\Service\TimeProvider\TimeProvider - - engineblock.service.sso_notification: - class: OpenConext\EngineBlock\Service\SsoNotificationService - arguments: - - "%sso_notification_encryption_key%" - - "%sso_notification_encryption_key_salt%" - - "%sso_notification_encryption_algorithm%" - - "@engineblock.compat.logger" - - engineblock.service.sso_session: - class: OpenConext\EngineBlock\Service\SsoSessionService - arguments: - - "%sso_session_cookie_max_age%" - - "%cookie.locale.domain%" - - "%cookie.path%" - - "@engineblock.service.cookie" - - "@engineblock.compat.logger" - - engineblock.service.cookie: - class: OpenConext\EngineBlock\Service\CookieService - - engineblock.factory.service_provider_factory: - class: OpenConext\EngineBlock\Metadata\Factory\Factory\ServiceProviderFactory - arguments: - - '@engineblock.compat.metadata.definitions' - - '@OpenConext\EngineBlock\Metadata\X509\KeyPairFactory' - - '@OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration' - - '@engineblock.url_provider' - - '@engineblock.features' - - '%stepup.sfo.override_engine_entityid%' - - OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration: - public: false - arguments: - - '@translator' - - '%email_request_access_address%' - - '%view_default_header%' - - '%hostname%' - - '%view_default_logo%' - - '%view_default_logo_width%' - - '%view_default_logo_height%' - - engineblock.factory.identity_provider_factory: - class: OpenConext\EngineBlock\Metadata\Factory\Factory\IdentityProviderFactory - arguments: - - '@OpenConext\EngineBlock\Metadata\X509\KeyPairFactory' - - '@OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration' - - '@engineblock.url_provider' - - OpenConext\EngineBlock\Xml\MetadataRenderer: - arguments: - - "@engineblock.language_support_provider" - - "@twig" - - "@engineblock.compat.saml2_id_generator" - - "@OpenConext\\EngineBlock\\Metadata\\X509\\KeyPairFactory" - - "@OpenConext\\EngineBlock\\Xml\\DocumentSigner" - - "@engineblock.service.time_provider" - - "%metadata_add_requested_attributes%" - - OpenConext\EngineBlock\Xml\MetadataProvider: - arguments: - - '@OpenConext\EngineBlock\Xml\MetadataRenderer' - - '@engineblock.factory.service_provider_factory' - - '@engineblock.factory.identity_provider_factory' - - '@OpenConext\EngineBlock\Metadata\X509\KeyPairFactory' - - '@engineblock.metadata.repository.idps_metadata' - - engineblock.authentication.user_directory: - class: OpenConext\EngineBlockBundle\Authentication\Service\UserService - arguments: - - "@engineblock.repository.user" - - engineblock.features: - class: OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration - arguments: - - # replaced in the extension - - engineblock.error_feedback: - class: OpenConext\EngineBlockBundle\Configuration\ErrorFeedbackConfiguration - arguments: - - "@translator" - - engineblock.pdp.pdp_client: - class: OpenConext\EngineBlockBundle\Pdp\PdpClient - arguments: - - "@engineblock.pdp.http_client" - - "%pdp.policy_decision_point_path%" - - engineblock.pdp.http_client: - class: OpenConext\EngineBlock\Http\HttpClient - arguments: - - "@engineblock.pdp.guzzle_http_client" - - engineblock.pdp.guzzle_http_client: - class: GuzzleHttp\Client - arguments: - - base_uri: "%pdp.host%" - auth: ["%pdp.username%", "%pdp.password%", "Basic"] - # Verify CAs for certificates for prod, but not for other environments - # as we are working with self signed signatures - verify: "@=service('kernel').getEnvironment() === 'prod'" - timeout: "%http_client.timeout%" - - engineblock.authentication.authentication_loop_guard: - class: OpenConext\EngineBlockBundle\Authentication\AuthenticationLoopGuard - arguments: - - "%maximum_authentication_procedures_allowed%" - - "%time_frame_for_authentication_loop_in_seconds%" - - "%maximum_authentications_per_session%" - - engineblock.language_support_provider: - class: OpenConext\EngineBlockBundle\Localization\LanguageSupportProvider - arguments: - - ['en', 'nl', 'pt'] - - '%enabled_languages%' - - engineblock.locale_provider: - class: OpenConext\EngineBlockBundle\Localization\LocaleProvider - arguments: - - '@engineblock.language_support_provider' - - '%kernel.default_locale%' - - engineblock.url_provider: - class: OpenConext\EngineBlockBundle\Url\UrlProvider - arguments: - - '@Symfony\Component\Routing\Generator\UrlGeneratorInterface' - - engineblock.locale.cookie_factory: - class: OpenConext\EngineBlockBundle\Http\Cookies\CookieFactory - arguments: - - 'lang' - - '%cookie.locale.domain%' - - '%cookie.locale.expiry%' - - '%cookie.locale.http_only%' - - '%cookie.locale.secure%' - - OpenConext\EngineBlock\Service\ReleaseAsEnforcer: - class: OpenConext\EngineBlock\Service\ReleaseAsEnforcer - arguments: - - "@logger" - - engineblock.attribute_aggregation.client: - class: OpenConext\EngineBlockBundle\AttributeAggregation\AttributeAggregationClient - arguments: - - "@engineblock.attribute_aggregation.http_client" - - "%attribute_aggregation.base_url%" - - engineblock.attribute_aggregation.http_client: - class: OpenConext\EngineBlock\Http\HttpClient - arguments: - - "@engineblock.attribute_aggregation.guzzle_http_client" - - engineblock.attribute_aggregation.guzzle_http_client: - class: GuzzleHttp\Client - arguments: - - auth: ["%attribute_aggregation.username%", "%attribute_aggregation.password%", "Basic"] - timeout: "%http_client.timeout%" - - engineblock.metadata.repository.cached_doctrine: - class: OpenConext\EngineBlock\Metadata\MetadataRepository\CachedDoctrineMetadataRepository - arguments: - - "@engineblock.metadata.repository.doctrine" - - engineblock.metadata.repository.idps_metadata: - class: OpenConext\EngineBlock\Metadata\MetadataRepository\IdpsMetadataRepository - arguments: - - "@engineblock.metadata.repository.cached_doctrine" - - "@engineblock.factory.identity_provider_factory" - - "@engineblock.url_provider" - - OpenConext\EngineBlock\Metadata\MetadataRepository\MetadataRepositoryInterface: '@engineblock.metadata.repository.cached_doctrine' - - engineblock.metadata.repository.doctrine: - public: false - class: OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository - arguments: - - "@doctrine.orm.entity_manager" - - "@engineblock.repository.service_provider" - - "@engineblock.repository.identity_provider" - - engineblock.metadata_push.repository.doctrine: - public: false - class: OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataPushRepository - arguments: - - "@doctrine.orm.entity_manager" - - engineblock.metadata.push_metadata_assembler: - public: false - class: OpenConext\EngineBlock\Metadata\Entity\Assembler\PushMetadataAssembler - arguments: - - "@engineblock.validator.allowed_scheme_validator" - - "@engineblock.language_support_provider" - - "@engineblock.compat.logger" - - OpenConext\EngineBlock\Metadata\X509\KeyPairFactory: - arguments: - - '%encryption_keys%' - - engineblock.validator.allowed_scheme_validator: - class: OpenConext\EngineBlock\Validator\AllowedSchemeValidator - arguments: - - "%allowed_acs_location_schemes%" - - engineblock.validator.saml_binding_validator: - class: OpenConext\EngineBlock\Validator\SamlBindingValidator - - engineblock.validator.acs_request_validator: - class: OpenConext\EngineBlock\Validator\AcsRequestValidator - - engineblock.validator.sso_request_validator: - class: OpenConext\EngineBlock\Validator\SsoRequestValidator - - engineblock.validator.unsolicited_sso_request_validator: - class: OpenConext\EngineBlock\Validator\UnsolicitedSsoRequestValidator - - engineblock.validator.saml_response_validator: - class: OpenConext\EngineBlock\Validator\SamlResponseValidator - - OpenConext\EngineBlockBundle\Authentication\Service\SamlResponseHelper: - class: OpenConext\EngineBlockBundle\Authentication\Service\SamlResponseHelper - arguments: - - "@engineblock.metadata.repository.cached_doctrine" - - engineblock.twig.extension.debug: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Debug - tags: - - { name: 'twig.extension' } - - engineblock.twig.extension.feedback: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Feedback - arguments: - - "@engineblock.compat.application" - - "@engineblock.error_feedback" - - "@engineblock.compat.repository.metadata" - - "@OpenConext\\EngineBlockBundle\\Authentication\\Service\\SamlResponseHelper" - tags: - - { name: 'twig.extension' } - - engineblock.twig.extension.global_site_notice: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\GlobalSiteNotice - arguments: - - "%global.site_notice.show%" - - "%global.site_notice.allowed.tags%" - - "@translator" - tags: - - { name: 'twig.extension' } - - engineblock.twig.extension.i18n: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\I18n - arguments: - - "@translator" - tags: - - { name: 'twig.extension' } - - engineblock.twig.extension.locale: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Locale - arguments: - - "@request_stack" - - "@engineblock.language_support_provider" - - "%locale%" - tags: - - { name: 'twig.extension' } - - engineblock.twig.extension.metadata: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Metadata - arguments: - - "@engineblock.compat.metadata.definitions" - - "@translator" - tags: - - { name: 'twig.extension' } - - engineblock.twig.extension.wayf: - class: OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Wayf - arguments: - - "@request_stack" - - "@translator" - tags: - - { name: 'twig.extension' } - - engineblock.service.discovery_selection_service: - class: OpenConext\EngineBlockBundle\Service\DiscoverySelectionService diff --git a/src/OpenConext/EngineBlockBundle/Security/Http/EntryPoint/JsonBasicAuthenticationEntryPoint.php b/src/OpenConext/EngineBlockBundle/Security/Http/EntryPoint/JsonBasicAuthenticationEntryPoint.php index 283f500ce0..a4a337e2c8 100644 --- a/src/OpenConext/EngineBlockBundle/Security/Http/EntryPoint/JsonBasicAuthenticationEntryPoint.php +++ b/src/OpenConext/EngineBlockBundle/Security/Http/EntryPoint/JsonBasicAuthenticationEntryPoint.php @@ -20,6 +20,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; @@ -38,7 +39,7 @@ public function __construct($realmName) /** * {@inheritdoc} */ - public function start(Request $request, AuthenticationException $authException = null) + public function start(Request $request, AuthenticationException $authException = null): Response { $authExceptionMessage = $authException ? $authException->getMessage() : ''; $error = sprintf( diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Debug.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Debug.php index ec6648e3bc..a1f681a259 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Debug.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Debug.php @@ -18,15 +18,15 @@ namespace OpenConext\EngineBlockBundle\Twig\Extensions\Extension; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; /** * The debug extension is used to provide var_dump, var_export and print_r functions for usage in Twig templates. */ -class Debug extends Twig_Extension +class Debug extends AbstractExtension { - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction('var_export', [$this, 'varExport']), diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Feedback.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Feedback.php index 7617408481..43c697c965 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Feedback.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Feedback.php @@ -28,10 +28,10 @@ use OpenConext\EngineBlockBundle\Value\FeedbackInformation; use OpenConext\EngineBlockBundle\Value\FeedbackInformationMap; use SAML2\XML\saml\Issuer; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; -class Feedback extends Twig_Extension +class Feedback extends AbstractExtension { /** * @var EngineBlock_ApplicationSingleton @@ -65,7 +65,7 @@ public function __construct( $this->samlResponseHelper = $samlResponseHelper; } - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction('feedbackInfo', [$this, 'getFeedbackInfo']), @@ -183,7 +183,7 @@ public function getSamlFailedResponse(): string $session = $this->application->getSession(); $feedbackInfo = $session->get('feedbackInfo'); // If AuthnFailedResponse is not set, we are unable to render a createAuthnFailedResponse - $sspResponse = $feedbackInfo['AuthnFailedResponse']; + $sspResponse = $feedbackInfo['AuthnFailedResponse'] ?? null; $value = ''; if (!is_null($sspResponse)) { // Compose the Saml error response that can be used to travel back to the SP diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/FunctionalTestingGlobalSiteNotice.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/FunctionalTestingGlobalSiteNotice.php index 85f137e289..6233448e01 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/FunctionalTestingGlobalSiteNotice.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/FunctionalTestingGlobalSiteNotice.php @@ -19,10 +19,10 @@ namespace OpenConext\EngineBlockBundle\Twig\Extensions\Extension; use Symfony\Component\HttpFoundation\RequestStack; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; -class FunctionalTestingGlobalSiteNotice extends Twig_Extension implements GlobalSiteNoticeInterface +class FunctionalTestingGlobalSiteNotice extends AbstractExtension implements GlobalSiteNoticeInterface { private $request; @@ -39,7 +39,7 @@ public function __construct( $this->allowedHtml = $allowedHtml; } - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction('shouldDisplayGlobalSiteNotice', [$this, 'shouldDisplayGlobalSiteNotice']), diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/GlobalSiteNotice.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/GlobalSiteNotice.php index ea783e3366..ecd375e0fc 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/GlobalSiteNotice.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/GlobalSiteNotice.php @@ -19,10 +19,10 @@ namespace OpenConext\EngineBlockBundle\Twig\Extensions\Extension; use Symfony\Component\Translation\TranslatorInterface; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; -class GlobalSiteNotice extends Twig_Extension +class GlobalSiteNotice extends AbstractExtension { /** * @var bool @@ -35,21 +35,21 @@ class GlobalSiteNotice extends Twig_Extension private $allowedHtml; /** - * @var TranslatorInterface + * @var \Symfony\Contracts\Translation\TranslatorInterface */ private $translator; public function __construct( bool $shouldDisplayGlobalSiteNotice, string $allowedHtml, - TranslatorInterface $translator + \Symfony\Contracts\Translation\TranslatorInterface $translator ) { $this->shouldDisplayGlobalSiteNotice = $shouldDisplayGlobalSiteNotice; $this->allowedHtml = $allowedHtml; $this->translator = $translator; } - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction('shouldDisplayGlobalSiteNotice', [$this, 'shouldDisplayGlobalSiteNotice']), diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/I18n.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/I18n.php index 5eb5444b52..e555800fb1 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/I18n.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/I18n.php @@ -18,13 +18,12 @@ namespace OpenConext\EngineBlockBundle\Twig\Extensions\Extension; -use Twig_Extensions_Extension_I18n; -use Symfony\Component\Translation\TranslatorInterface; -use Twig_SimpleFilter; +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; +use Symfony\Contracts\Translation\TranslatorInterface; -class I18n extends Twig_Extensions_Extension_I18n +class I18n extends AbstractExtension { - /** * @var TranslatorInterface */ @@ -35,55 +34,35 @@ public function __construct(TranslatorInterface $translator) $this->translator = $translator; } - /** - * Returns a list of filters to add to the existing list. - * - * @return array An array of filters - */ public function getFilters() { - return array( - new Twig_SimpleFilter('trans', array($this, 'translateSingular')), - new Twig_SimpleFilter('transchoice', array($this, 'translatePlural')), - ); + return [ + new TwigFilter('trans', [$this, 'translateSingular']), + new TwigFilter('transchoice', [$this, 'translatePlural']), + ]; } - /** - * @return string - */ - public function translateSingular() + public function translateSingular($id, array $parameters = [], $domain = null, $locale = null) { - $args = func_get_args(); - return call_user_func_array( - [$this->translator, 'trans'], - $this->prepareDefaultPlaceholders($args) - ); + $parameters = $this->addDefaultPlaceholders($parameters); + return $this->translator->trans($id, $parameters, $domain, $locale); } - /** - * @return string - */ - public function translatePlural() + public function translatePlural($id, $count, array $parameters = [], $domain = null, $locale = null) { - $args = func_get_args(); - return call_user_func_array( - [$this->translator, 'transChoice'], - $this->prepareDefaultPlaceholders($args) - ); + $parameters = $this->addDefaultPlaceholders($parameters); + $parameters['%count%'] = $count; + return $this->translator->trans($id, $parameters, $domain, $locale); } - /** - * @param array $args - * @return array - */ - private function prepareDefaultPlaceholders(array $args) + private function addDefaultPlaceholders(array $parameters) { - $args[1]['%suiteName%'] = $this->translator->trans('suite_name'); - $args[1]['%supportUrl%'] = $this->translator->trans('openconext_support_url'); - $args[1]['%organisationNoun%'] = $this->translator->trans('organisation_noun'); - $args[1]['%organisationNounPlural%'] = $this->translator->trans('organisation_noun_plural'); - $args[1]['%accountNoun%'] = $this->translator->trans('account_noun'); + $parameters['%suiteName%'] = $this->translator->trans('suite_name'); + $parameters['%supportUrl%'] = $this->translator->trans('openconext_support_url'); + $parameters['%organisationNoun%'] = $this->translator->trans('organisation_noun'); + $parameters['%organisationNounPlural%'] = $this->translator->trans('organisation_noun_plural'); + $parameters['%accountNoun%'] = $this->translator->trans('account_noun'); - return $args; + return $parameters; } } diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Locale.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Locale.php index c616c8c4ce..4947444a78 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Locale.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Locale.php @@ -21,14 +21,14 @@ use OpenConext\EngineBlockBundle\Localization\LanguageSupportProvider; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; /** * The Locale extension can be used to retrieve the currently active locale. By default returns the locale that * can be found in the RequestStack. If none can be found in the request stack, the default locale is returned. */ -class Locale extends Twig_Extension +class Locale extends AbstractExtension { /** * @var string @@ -51,7 +51,7 @@ public function __construct(RequestStack $requestStack, LanguageSupportProvider $this->languageSupportProvider = $languageSupportProvider; } - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction('locale', [$this, 'getLocale']), diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Metadata.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Metadata.php index 5ff5b490fa..b1135c017c 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Metadata.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Metadata.php @@ -22,14 +22,14 @@ use OpenConext\Value\Saml\NameIdFormat; use SAML2\XML\saml\NameID; use Symfony\Component\Translation\TranslatorInterface; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; /** * Used to perform certain view related operations on metadata. For example this extension provides a function that * can sort metadata by display order. */ -class Metadata extends Twig_Extension +class Metadata extends AbstractExtension { /** * @var string @@ -37,17 +37,17 @@ class Metadata extends Twig_Extension private $attributeMetadata; /** - * @var TranslatorInterface + * @var \Symfony\Contracts\Translation\TranslatorInterface */ private $translator; - public function __construct(EngineBlock_Attributes_Metadata $attributesMetadata, TranslatorInterface $translator) + public function __construct(EngineBlock_Attributes_Metadata $attributesMetadata, \Symfony\Contracts\Translation\TranslatorInterface $translator) { $this->attributeMetadata = $attributesMetadata; $this->translator = $translator; } - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction( diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Spaceless.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Spaceless.php new file mode 100644 index 0000000000..1069241d31 --- /dev/null +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Spaceless.php @@ -0,0 +1,54 @@ + <" => "><"). Whitespace inside + * tags or textual content is preserved. + */ +class Spaceless extends AbstractExtension +{ + public function getFilters(): array + { + return [ + new TwigFilter('spaceless', [$this, 'spaceless'], ['is_safe' => ['html']]), + ]; + } + + /** + * Removes whitespaces between HTML/XML tags. + * Mirrors the prior (now deprecated) Twig spaceless filter behavior. + */ + public function spaceless(?string $content): string + { + if ($content === null) { + return ''; + } + return trim(preg_replace('/>\s+<', $content)); + } +} diff --git a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Wayf.php b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Wayf.php index 586de6097c..f136f3c0b9 100644 --- a/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Wayf.php +++ b/src/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/Wayf.php @@ -22,10 +22,10 @@ use OpenConext\EngineBlockBundle\Service\IdpHistoryService; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Translation\TranslatorInterface; +use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -use Twig_Extension; -class Wayf extends Twig_Extension +class Wayf extends AbstractExtension { const PREVIOUS_SELECTION_COOKIE_NAME = 'selectedidps'; const REMEMBER_CHOICE_COOKIE_NAME = 'rememberchoice'; @@ -33,7 +33,7 @@ class Wayf extends Twig_Extension private const ACCESS_ENABLED = '1'; /** - * @var TranslatorInterface + * @var \Symfony\Contracts\Translation\TranslatorInterface */ private $translator; @@ -42,13 +42,13 @@ class Wayf extends Twig_Extension */ private $previousSelection; - public function __construct(RequestStack $requestStack, TranslatorInterface $translator) + public function __construct(RequestStack $requestStack, \Symfony\Contracts\Translation\TranslatorInterface $translator) { $this->previousSelection = $this->loadPreviousSelectionFromCookie($requestStack); $this->translator = $translator; } - public function getFunctions() + public function getFunctions(): array { return [ new TwigFunction( @@ -105,17 +105,22 @@ private function formatIdpEntry(array $idp): array ? [] : array_values((array)$idp['Keywords']); + $connected = false; + if (isset($idp['Access']) && $idp['Access'] === self::ACCESS_ENABLED) { + $connected = true; + } + // In SingleSignOn.php, the IDP is transformed into an array for the frontend // Then, here, the array is transformed into another array for the frontend which is actually used in twig return [ - 'entityId' => $idp['EntityID'], - 'connected' => $idp['Access'] === self::ACCESS_ENABLED, - 'displayTitle' => $idp['Name'], - 'title' => strtolower($idp['Name']), + 'entityId' => $idp['EntityID'] ?? null, + 'connected' => $connected, + 'displayTitle' => $idp['Name'] ?? null, + 'title' => strtolower($idp['Name'] ?? ''), 'keywords' => strtolower(implode('|', $keywords)), - 'logo' => $idp['Logo'], - 'isDefaultIdp' => (bool)$idp['isDefaultIdp'], - 'discoveryHash' => $idp['DiscoveryHash'] + 'logo' => $idp['Logo'] ?? null, + 'isDefaultIdp' => (bool) ($idp['isDefaultIdp'] ?? null), + 'discoveryHash' => $idp['DiscoveryHash'] ?? null, ]; } @@ -214,7 +219,7 @@ private function loadPreviousSelectionFromCookie(RequestStack $requestStack) $previousSelectionIndexed = []; if ($request) { $previousSelection = json_decode( - $request->cookies->get(self::PREVIOUS_SELECTION_COOKIE_NAME, null), + $request->cookies->get(self::PREVIOUS_SELECTION_COOKIE_NAME, ''), true ); if ($previousSelection) { diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Command/DumpServiceRegistryCommand.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Command/DumpServiceRegistryCommand.php index dc2cffe9e5..677631cd32 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Command/DumpServiceRegistryCommand.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Command/DumpServiceRegistryCommand.php @@ -19,7 +19,7 @@ namespace OpenConext\EngineBlockFunctionalTestingBundle\Command; use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\DataStore\JsonDataStore; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -27,7 +27,7 @@ /** * Dump the contents of the (fake) Service Registry */ -class DumpServiceRegistryCommand extends ContainerAwareCommand +class DumpServiceRegistryCommand extends Command { protected function configure() { @@ -38,11 +38,11 @@ protected function configure() ->addArgument('file', InputArgument::OPTIONAL, 'File to get sessions from.'); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { /** @var JsonDataStore $jsonDataStore */ $jsonDataStore = $this->getContainer()->get('engineblock.functional_testing.data_store.service_registry'); $output->write(print_r($jsonDataStore->load(), true)); - return 0; + return \Symfony\Component\Console\Command\Command::SUCCESS; } } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ConsentController.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ConsentController.php index 4e6bf19b69..94bea032e5 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ConsentController.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ConsentController.php @@ -23,19 +23,22 @@ use SAML2\XML\saml\NameID; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Twig_Environment; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; use function base64_encode; class ConsentController { /** - * @var Twig_Environment + * @var Environment */ private $twig; public function __construct( - Twig_Environment $twig + Environment $twig ) { $this->twig = $twig; } @@ -56,9 +59,9 @@ public function sendAction() /** * @param Request $request * @return Response - * @throws \Twig\Error\LoaderError - * @throws \Twig\Error\RuntimeError - * @throws \Twig\Error\SyntaxError + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError */ public function consentAction(Request $request) { diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/FeedbackController.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/FeedbackController.php index 85e6394993..e813f01b97 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/FeedbackController.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/FeedbackController.php @@ -19,17 +19,17 @@ namespace OpenConext\EngineBlockFunctionalTestingBundle\Controllers; use Psr\Log\LoggerInterface; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; -use Twig_Environment; +use Symfony\Contracts\Translation\TranslatorInterface; +use Twig\Environment; /** * @package OpenConext\EngineBlockFunctionalTestingBundle\Controllers * @SuppressWarnings("PMD") */ -class FeedbackController extends Controller +class FeedbackController extends AbstractController { /** * @var TranslatorInterface @@ -37,7 +37,7 @@ class FeedbackController extends Controller private $translator; /** - * @var Twig_Environment + * @var Environment */ private $twig; @@ -48,7 +48,7 @@ class FeedbackController extends Controller public function __construct( TranslatorInterface $translator, - Twig_Environment $twig, + Environment $twig, LoggerInterface $logger ) { $this->translator = $translator; diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/IdentityProviderController.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/IdentityProviderController.php index ef0570751e..1e2a2259fc 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/IdentityProviderController.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/IdentityProviderController.php @@ -25,7 +25,7 @@ use SAML2\HTTPPost; use SAML2\HTTPRedirect; use SAML2\Utils; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -35,7 +35,7 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) just does a lot of manual lifting :( */ -class IdentityProviderController extends Controller +class IdentityProviderController extends AbstractController { /** * @var EntityRegistry diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ServiceProviderController.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ServiceProviderController.php index 5fd401aef9..064ac33711 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ServiceProviderController.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/ServiceProviderController.php @@ -28,7 +28,7 @@ use SAML2\HTTPRedirect; use SAML2\Response as SAMLResponse; use SAML2\Utils; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -38,7 +38,7 @@ * @package OpenConext\EngineBlockFunctionalTestingBundle\Controllers * @SuppressWarnings("PMD") */ -class ServiceProviderController extends Controller +class ServiceProviderController extends AbstractController { /** * @var EntityRegistry @@ -126,7 +126,6 @@ public function triggerLoginPostAction($spName) */ public function assertionConsumerAction(Request $request) { - $previous = libxml_disable_entity_loader(true); try { $httpPostBinding = new HTTPPost(); $message = $httpPostBinding->receive(); @@ -152,8 +151,6 @@ public function assertionConsumerAction(Request $request) $doc->loadXML($xml); $xml = $doc->saveXML(); - libxml_disable_entity_loader($previous); - return new Response( $xml, 200, diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/StepupMockController.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/StepupMockController.php index 87b8a55dd4..448f9e7587 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/StepupMockController.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/StepupMockController.php @@ -22,24 +22,24 @@ use SAML2\Constants; use SAML2\HTTPRedirect; use SAML2\Response as SamlResponse; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Twig_Environment; +use Twig\Environment; -class StepupMockController extends Controller +class StepupMockController extends AbstractController { /** * @var MockStepupGateway */ private $mockStepupGateway; /** - * @var Twig_Environment + * @var Environment */ private $twig; - public function __construct(MockStepupGateway $mockStepupGateway, Twig_Environment $twig) + public function __construct(MockStepupGateway $mockStepupGateway, Environment $twig) { $this->mockStepupGateway = $mockStepupGateway; $this->twig = $twig; diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/WayfController.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/WayfController.php index 349ed7cc3d..8c1ce73b88 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/WayfController.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Controllers/WayfController.php @@ -19,21 +19,21 @@ namespace OpenConext\EngineBlockFunctionalTestingBundle\Controllers; use OpenConext\EngineBlockFunctionalTestingBundle\Helper\TestEntitySeeder; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Twig_Environment; +use Twig\Environment; /** * @package OpenConext\EngineBlockFunctionalTestingBundle\Controllers * @SuppressWarnings("PMD") */ -class WayfController extends Controller +class WayfController extends AbstractController { private $twig; - public function __construct(Twig_Environment $twig) + public function __construct(Environment $twig) { $this->twig = $twig; } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/DependencyInjection/OpenConextEngineBlockFunctionalTestingExtension.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/DependencyInjection/OpenConextEngineBlockFunctionalTestingExtension.php deleted file mode 100644 index 0d8504acd3..0000000000 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/DependencyInjection/OpenConextEngineBlockFunctionalTestingExtension.php +++ /dev/null @@ -1,35 +0,0 @@ -load('services.yml'); - $loader->load('mocks.yml'); - $loader->load('controllers.yml'); - } -} diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/AttributeManipulation.feature b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/AttributeManipulation.feature index 7286403e2f..6317c301cb 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/AttributeManipulation.feature +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/AttributeManipulation.feature @@ -192,7 +192,7 @@ Feature: When I give my consent And I pass through EngineBlock Then the url should match "functional-testing/SP-with-Attribute-Manipulations/acs" - And the response should match xpath '/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="urn:mace:dir:attribute-def:uid"]/saml:AttributeValue[text()="https://engine.dev.openconext.local/authentication/idp/single-sign-on"]' + And the response should match xpath '/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="urn:mace:dir:attribute-def:uid"]/saml:AttributeValue[text()="/authentication/idp/single-sign-on"]' Scenario: The manipulation reduces a multivalued attribute to a single value Given the IdP "Dummy-IdP" sends attribute "urn:mace:dir:attribute-def:eduPersonAffiliation" with values "student,faculty,guest,member" and xsi:type is "xs:string" diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Bindings.feature b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Bindings.feature index b91c6e60c1..332392c0d6 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Bindings.feature +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Bindings.feature @@ -39,3 +39,74 @@ Feature: And I give my consent And I pass through EngineBlock Then the url should match "functional-testing/Dummy%20SP/acs" + + Scenario: RelayState is preserved through the complete SAML flow using HTTP-POST binding + Given the SP uses the HTTP POST Binding + And the SP sends RelayState "test-relay-state-post-binding" + When I log in at "Dummy SP" + And I pass through the SP + And I pass through EngineBlock + And I pass through the IdP + And I give my consent + Then the RelayState should be "test-relay-state-post-binding" + And I pass through EngineBlock + Then the url should match "functional-testing/Dummy%20SP/acs" + + Scenario: RelayState is preserved through the complete SAML flow using HTTP-Redirect binding + Given the SP uses the HTTP Redirect Binding + And the SP sends RelayState "test-relay-state-redirect-binding" + When I log in at "Dummy SP" + And I pass through EngineBlock + And I pass through the IdP + And I give my consent + Then the RelayState should be "test-relay-state-redirect-binding" + And I pass through EngineBlock + Then the url should match "functional-testing/Dummy%20SP/acs" + + Scenario: RelayState with special characters is preserved through the SAML flow + Given the SP uses the HTTP POST Binding + And the SP sends RelayState "test+state=with&special%20chars" + When I log in at "Dummy SP" + And I pass through the SP + And I pass through EngineBlock + And I pass through the IdP + And I give my consent + Then the RelayState should be "test+state=with&special%20chars" + And I pass through EngineBlock + Then the url should match "functional-testing/Dummy%20SP/acs" + + Scenario: RelayState is preserved with signed requests using HTTP-POST binding + Given the SP uses the HTTP POST Binding + And the SP signs its requests + And the SP sends RelayState "signed-request-relay-state" + When I log in at "Dummy SP" + And I pass through the SP + And I pass through EngineBlock + And I pass through the IdP + And I give my consent + Then the RelayState should be "signed-request-relay-state" + And I pass through EngineBlock + Then the url should match "functional-testing/Dummy%20SP/acs" + + Scenario: Empty RelayState is handled correctly + Given the SP uses the HTTP POST Binding + And the SP sends RelayState "" + When I log in at "Dummy SP" + And I pass through the SP + And I pass through EngineBlock + And I pass through the IdP + And I give my consent + Then no RelayState should be present + And I pass through EngineBlock + Then the url should match "functional-testing/Dummy%20SP/acs" + + Scenario: No RelayState is handled correctly + Given the SP uses the HTTP POST Binding + When I log in at "Dummy SP" + And I pass through the SP + And I pass through EngineBlock + And I pass through the IdP + And I give my consent + Then no RelayState should be present + And I pass through EngineBlock + Then the url should match "functional-testing/Dummy%20SP/acs" diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/EngineBlockContext.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/EngineBlockContext.php index f89f297e49..05dc879894 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/EngineBlockContext.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/EngineBlockContext.php @@ -23,6 +23,7 @@ use DOMDocument; use DOMElement; use DOMXPath; +use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\DataStore\AbstractDataStore; use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\FunctionalTestingAttributeAggregationClient; use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\FunctionalTestingAuthenticationLoopGuard; use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\FunctionalTestingFeatureConfiguration; @@ -116,6 +117,8 @@ class EngineBlockContext extends AbstractSubContext */ private $currentRequestId = ''; + private AbstractDataStore $dataStore; + /** * @param ServiceRegistryFixture $serviceRegistry * @param EngineBlock $engineBlock @@ -136,7 +139,8 @@ public function __construct( FunctionalTestingFeatureConfiguration $features, FunctionalTestingPdpClient $pdpClient, FunctionalTestingAuthenticationLoopGuard $authenticationLoopGuard, - FunctionalTestingAttributeAggregationClient $attributeAggregationClient + FunctionalTestingAttributeAggregationClient $attributeAggregationClient, + AbstractDataStore $authGuardDataStore, ) { $this->serviceRegistryFixture = $serviceRegistry; $this->engineBlock = $engineBlock; @@ -146,6 +150,7 @@ public function __construct( $this->pdpClient = $pdpClient; $this->authenticationLoopGuard = $authenticationLoopGuard; $this->attributeAggregationClient = $attributeAggregationClient; + $this->dataStore = $authGuardDataStore; } /** @@ -553,7 +558,8 @@ public function engineblockIsConfiguredToAllowAMaximumOfAuthenticationProcedures $this->authenticationLoopGuard->saveAuthenticationLoopGuardConfiguration( (int) $maximumAuthenticationProceduresAllowed, (int) $timeFrameForAuthenticationLoopInSeconds, - (int) $maximumAuthenticationsPerSession + (int) $maximumAuthenticationsPerSession, + $this->dataStore, ); $this->usingAuthenticationLoopGuard = true; } @@ -589,13 +595,14 @@ public function cleanUpFeatures() } /** - * @AftectScenario + * @AfterScenario */ public function cleanUpAuthenticationLoopGuard() { if ($this->usingAuthenticationLoopGuard) { - $this->authenticationLoopGuard->cleanUp(); + $this->authenticationLoopGuard->cleanUp($this->dataStore); } + $this->usingAuthenticationLoopGuard = false; } /** @@ -909,6 +916,56 @@ public function iExploitTheXMLSignatureBypass() $mink->pressButton('GO'); } + /** + * @Given /^the RelayState should be "([^"]*)"/ + */ + public function theRelayStateShouldBeSetInTheForm($expectedRelayState) + { + $mink = $this->getMinkContext(); + $page = $mink->getSession()->getPage(); + + // Check if the page contains a RelayState hidden form field + // This is how RelayState is typically preserved in SAML POST bindings + $relayStateField = $page->find('css', 'input[name="RelayState"]'); + + if ($relayStateField === null) { + throw new ExpectationException( + 'The RelayState field should be present, but it is not', + $mink->getSession()->getDriver() + ); + } + + // RelayState found as a form field + $relayStateValue = $relayStateField->getValue(); + if ($expectedRelayState !== $relayStateValue) { + throw new ExpectationException( + sprintf( + 'The RelayState field should contain "%s", but contains "%s"', + $expectedRelayState, + $relayStateValue + ), + $mink->getSession()->getDriver() + ); + } + } + + /** + * @Then /^no RelayState should be present/ + */ + public function noRelaystateShouldBePresent(): void + { + $mink = $this->getMinkContext(); + $page = $mink->getSession()->getPage(); + $relayStateField = $page->find('css', 'input[name="RelayState"]'); + + if ($relayStateField !== null) { + throw new ExpectationException( + 'The RelayState field should not be present, but it is', + $mink->getSession()->getDriver() + ); + } + } + /** * @param DOMElement $element * @return string diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MinkContext.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MinkContext.php index 97c7b70970..49c536378c 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MinkContext.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MinkContext.php @@ -44,7 +44,7 @@ class MinkContext extends BaseMinkContext */ public function putDebugCookie() { - $driver = $this->getSession()->getDriver(); + $driver = $this->getSession(); $driver->setCookie('XDEBUG_SESSION', 'PHPSTORM'); } @@ -235,6 +235,9 @@ public function iShouldNotSeeUrl($url) */ public function iOpenTwoBrowserTabsIdentifiedBy($numberOfTabs, $tabNames) { + $this->getMink()->getSession()->restart(); + $this->windows = []; // Reset the windows array to avoid confusion with previous tests + $tabs = explode(',', $tabNames); if (count($tabs) != $numberOfTabs) { throw new RuntimeException( @@ -243,17 +246,23 @@ public function iOpenTwoBrowserTabsIdentifiedBy($numberOfTabs, $tabNames) } foreach ($tabs as $tab) { + $windowsNames = $this->getMink()->getSession()->getWindowNames(); + if (!$windowsNames) { + throw new RuntimeException('The windows where not opened correctly.'); + } + $this->getMink() ->getSession() - ->executeScript("window.open('/','_blank');"); + ->executeScript("window.open('about:blank','_blank');"); - $windowsNames = $this->getSession()->getWindowNames(); + $newWindows = array_diff($this->getMink()->getSession()->getWindowNames(), $windowsNames); - if (!$windowsNames) { - throw new RuntimeException('The windows where not opened correctly.'); + if (count($newWindows) != 1) { + throw new RuntimeException('The new windows where not opened correctly.'); } + // Grab the window name (which is the last one added to the window list) - $windowName = array_pop($windowsNames); + $windowName = array_pop($newWindows); // Keep track of the opened windows in order allow switching between them $this->windows[trim($tab)] = $windowName; } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockIdpContext.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockIdpContext.php index 9f89c32b7c..71fbc87684 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockIdpContext.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockIdpContext.php @@ -79,6 +79,18 @@ public function __construct( $this->mockSpRegistry = $mockSpRegistry; } + /** + * @AfterScenario + */ + public function cleanUpMockIdpRegistry() + { + // Clear the mock IdP registry to prevent state pollution between scenarios + // Travis / PHP 5.6 issue requires gc cycle in order to actually clear the fixture + // https://www.pivotaltracker.com/story/show/161282428 + gc_collect_cycles(); + $this->mockIdpRegistry->clear()->save(); + } + /** * @Given /^an Identity Provider named "([^"]*)"$/ * @Given /^an Identity Provider named "([^"]*)" with discovery "([^"]*)"$/ @@ -323,7 +335,7 @@ public function theIdPSendsAttributeWithValuesAndType( /** @var MockIdentityProvider $mockIdp */ $mockIdp = $this->mockIdpRegistry->get($idpName); $explosion = explode(',', $attributeValues); - $mockIdp->setAttribute($attributeName, $explosion, $attributeValueType); + $mockIdp->setAttribute($attributeName, $explosion); $this->mockIdpRegistry->save(); } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockSpContext.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockSpContext.php index a842d502c0..ef5fb57cb4 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockSpContext.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context/MockSpContext.php @@ -74,6 +74,18 @@ public function __construct( $this->mockIdpRegistry = $mockIdpRegistry; } + /** + * @AfterScenario + */ + public function cleanUpMockSpRegistry() + { + // Clear the mock SP registry to prevent state pollution between scenarios + // Travis / PHP 5.6 issue requires gc cycle in order to actually clear the fixture + // https://www.pivotaltracker.com/story/show/161282428 + gc_collect_cycles(); + $this->mockSpRegistry->clear()->save(); + } + /** * @When /^I log in at SP "([^"]*)" which attempts to preselect nonexistent IdP "([^"]*)"$/ */ @@ -229,7 +241,7 @@ private function doSpSignsItsRequests(MockServiceProvider $sp) public function spIsATrustedProxy($spName) { $this->serviceRegistryFixture->setSpEntityTrustedProxy( - $this->mockSpRegistry->get($spName)->entityid() + $this->mockSpRegistry->get($spName)->entityId() ); $this->serviceRegistryFixture->save(); } @@ -240,7 +252,7 @@ public function spIsATrustedProxy($spName) public function spRequiresARequesterId($spName) { $this->serviceRegistryFixture->setSpEntityRequesterIdRequired( - $this->mockSpRegistry->get($spName)->entityid() + $this->mockSpRegistry->get($spName)->entityId() ); $this->serviceRegistryFixture->save(); } @@ -313,10 +325,7 @@ public function theSpUsesTheHttpRedirectBinding() */ public function noRegisteredServiceProviders() { - // Travis / PHP 5.6 issue requires gc cycle in order to actually clear the fixture - // https://www.pivotaltracker.com/story/show/161282428 - gc_collect_cycles(); - $this->mockSpRegistry->clear()->save(); + $this->cleanUpMockSpRegistry(); } /** @@ -699,4 +708,18 @@ public function theSPSendsNoAuthnContextClassRef(string $spName): void $request->setRequestedAuthnContext(); $this->mockSpRegistry->save(); } + + /** + * @Given /^the SP sends RelayState "([^"]*)"$/ + */ + public function theSPSendsRelayState($relayState) + { + /** @var MockServiceProvider $sp */ + $sp = $this->mockSpRegistry->getOnly(); + + $request = $sp->getAuthnRequest(); + $request->setRelayState($relayState); + + $this->mockSpRegistry->save(); + } } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/MultipleSingleSignOn.feature b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/MultipleSingleSignOn.feature index 8af0696034..cfbcd2906b 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/MultipleSingleSignOn.feature +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/MultipleSingleSignOn.feature @@ -1,4 +1,4 @@ -@selenium +@functional Feature: In order to offer a stable and user friendly service As EngineBlock @@ -11,10 +11,10 @@ Feature: And an Identity Provider named "SSO-IdP" And a Service Provider named "SSO-SP" And a Service Provider named "SSO-Two" - And I open 2 browser tabs identified by "Browser tab 1, Browser tab 2" Scenario: Two solicited authentication requests sequential - When I switch to "Browser tab 1" + When I open 2 browser tabs identified by "Browser tab 1, Browser tab 2" + And I switch to "Browser tab 1" And I log in at "SSO-SP" And I pass through the SP And I give my consent @@ -26,7 +26,8 @@ Feature: Then the url should match "functional-testing/SSO-Two/acs" Scenario: Two solicited authentication requests mixed - When I switch to "Browser tab 1" + When I open 2 browser tabs identified by "Browser tab 1, Browser tab 2" + And I switch to "Browser tab 1" And I log in at "SSO-SP" And I pass through the SP And I switch to "Browser tab 2" @@ -39,7 +40,8 @@ Feature: Then the url should match "functional-testing/SSO-SP/acs" Scenario: One solicited and one unsolicited authentication requests - When I switch to "Browser tab 1" + When I open 2 browser tabs identified by "Browser tab 1, Browser tab 2" + And I switch to "Browser tab 1" And I log in at "SSO-SP" And I pass through the SP And I switch to "Browser tab 2" diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/StepupKeyRollover.feature b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/StepupKeyRollover.feature index 84b0e71223..a2d476ea57 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/StepupKeyRollover.feature +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Features/StepupKeyRollover.feature @@ -23,7 +23,6 @@ Feature: Scenario: When stepup.sfo.override_engine_entityid is configured with a valid EntityId, stepup/metadata should show that EntityId Given feature "eb.stepup.sfo.override_engine_entityid" is enabled When I go to Engineblock URL "/authentication/stepup/metadata" - Then print last response Then the response should match xpath '//md:EntityDescriptor[@entityID="https://engine.dev.openconext.local/new/stepup/metadata"]' # Note that we can not ascertain programatically if the Issuer is updated as this is an internal diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingAuthenticationLoopGuard.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingAuthenticationLoopGuard.php index 69a39a0178..dc1b831108 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingAuthenticationLoopGuard.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingAuthenticationLoopGuard.php @@ -38,11 +38,6 @@ final class FunctionalTestingAuthenticationLoopGuard implements AuthenticationLo */ private $activeAuthenticationLoopGuard; - /** - * @var AbstractDataStore - */ - private $dataStore; - /** * @var false|array */ @@ -54,9 +49,12 @@ public function __construct( AbstractDataStore $dataStore ) { $this->originalAuthenticationLoopGuard = $authenticationLoopGuard; - $this->dataStore = $dataStore; - $this->authenticationGuardFixture = $dataStore->load(false); + try { + $this->authenticationGuardFixture = $dataStore->load(); + } catch (\Throwable $e) { + $this->authenticationGuardFixture = []; + } } /** @@ -67,13 +65,14 @@ public function __construct( public function saveAuthenticationLoopGuardConfiguration( int $maximumAuthenticationProceduresAllowed, int $timeFrameForAuthenticationLoopInSeconds, - int $maximumAuthenticationsPerSession + int $maximumAuthenticationsPerSession, + AbstractDataStore $dataStore ) { $this->authenticationGuardFixture['maximumAuthenticationProceduresAllowed'] = $maximumAuthenticationProceduresAllowed; $this->authenticationGuardFixture['timeFrameForAuthenticationLoopInSeconds'] = $timeFrameForAuthenticationLoopInSeconds; $this->authenticationGuardFixture['maximumAuthenticationsPerSession'] = $maximumAuthenticationsPerSession; - $this->dataStore->save($this->authenticationGuardFixture); + $dataStore->save($this->authenticationGuardFixture); } /** @@ -116,16 +115,16 @@ public function detectsAuthenticationLimit(AuthenticationProcedureMap $pastAuthe return false; } - public function cleanUp() + public function cleanUp(AbstractDataStore $dataStore) { $this->authenticationGuardFixture = []; $this->activeAuthenticationLoopGuard = $this->originalAuthenticationLoopGuard; - $this->dataStore->save($this->authenticationGuardFixture); + $dataStore->save($this->authenticationGuardFixture); } private function initAuthenticationLoopGuard(): void { - if ($this->authenticationGuardFixture === false) { + if ($this->authenticationGuardFixture === []) { $this->activeAuthenticationLoopGuard = $this->originalAuthenticationLoopGuard; } else { $this->activeAuthenticationLoopGuard = new AuthenticationLoopGuard( diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingFeatureConfiguration.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingFeatureConfiguration.php index 819558f565..80c3f5cbda 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingFeatureConfiguration.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingFeatureConfiguration.php @@ -28,7 +28,7 @@ final class FunctionalTestingFeatureConfiguration implements FeatureConfigurationInterface { /** - * @var FeatureConfiguration + * @var TestFeatureConfiguration */ private $featureConfiguration; @@ -42,7 +42,7 @@ final class FunctionalTestingFeatureConfiguration implements FeatureConfiguratio */ private $dataStore; - public function __construct(FeatureConfigurationInterface $featureConfiguration, AbstractDataStore $dataStore) + public function __construct(TestFeatureConfiguration $featureConfiguration, AbstractDataStore $dataStore) { $this->featureConfiguration = $featureConfiguration; $this->dataStore = $dataStore; diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingPdpClient.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingPdpClient.php index d1fc16c62d..ded6b3dd66 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingPdpClient.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/FunctionalTestingPdpClient.php @@ -91,12 +91,12 @@ public function requestDecisionFor(Request $request) : PolicyDecision $pdpResponse->decision = PolicyDecision::DECISION_INDETERMINATE; $pdpResponse->status = new Status(); - $pdpResponse->status->statusDetail = <<status->statusDetail = << -XML; +XML_WRAP; $pdpResponse->status->statusCode = new StatusCode(); $pdpResponse->status->statusCode->value = 'urn:oasis:names:tc:xacml:1.0:status:missing-attribute'; $pdpResponse->status->statusMessage = 'Missing required attribute'; @@ -123,7 +123,7 @@ public function requestDecisionFor(Request $request) : PolicyDecision default: $invalidData = $this->policyDecisionFixture; if (!is_string($invalidData)) { - $invalidData = is_object($invalidData) ? get_class($invalidData) : gettype($invalidData); + $invalidData = get_debug_type($invalidData); } throw new RuntimeException( diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/ServiceRegistryFixture.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/ServiceRegistryFixture.php index 2de4a8c4d3..994ee97d29 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/ServiceRegistryFixture.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Fixtures/ServiceRegistryFixture.php @@ -18,6 +18,7 @@ namespace OpenConext\EngineBlockFunctionalTestingBundle\Fixtures; +use Doctrine\DBAL\Statement; use Doctrine\ORM\EntityManager; use Exception; use OpenConext\EngineBlock\Metadata\AttributeReleasePolicy; @@ -89,6 +90,7 @@ private function getServiceProvider(string $entityId) ); } + // Why is this needed? $this->entityManager->persist($entity); return $entity; @@ -124,7 +126,7 @@ public function reset() $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder(); $queryBuilder ->delete('sso_provider_roles_eb5') - ->execute(); + ->executeStatement(); return $this; } @@ -133,12 +135,12 @@ public function remove($entityId, $role) { $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder(); $queryBuilder - ->delete('sso_provider_roles_eb5', 'roles') + ->delete('sso_provider_roles_eb5') ->where('roles.entity_id = :entityId') ->andWhere('roles.type = :type') ->setParameter('entityId', $entityId) ->setParameter('type', $role) - ->execute(); + ->executeStatement(); return $this; } @@ -169,8 +171,9 @@ public function registerSp($name, $entityId, $acsLocation, $certData = '') WHERE `type` = 'idp' QUERY; $query = $this->entityManager->getConnection()->prepare($idpEntityIDQuery); - $query->execute(); - $idps = $query->fetchAll(); + assert($query instanceof Statement); + $result = $query->executeQuery(); + $idps = $result->fetchAllAssociative(); foreach ($idps as $idpEntityId) { $idp = $this->repository->findIdentityProviderByEntityId($idpEntityId['entity_id']); @@ -205,12 +208,15 @@ public function registerIdp($name, $entityId, $ssoLocation, $certData = '', $dis WHERE `type` = 'sp' QUERY; $query = $this->entityManager->getConnection()->prepare($spEntityIDQuery); - $query->execute(); - $sps = $query->fetchAll(); + assert($query instanceof Statement); + $result = $query->executeQuery(); + $sps = $result->fetchAllAssociative(); foreach ($sps as $spEntityId) { $sp = $this->repository->findServiceProviderByEntityId($spEntityId['entity_id']); $sp->allowedIdpEntityIds[] = $idp->entityId; + + // Why is this needed? $this->entityManager->persist($sp); } @@ -381,7 +387,8 @@ public function allowNoAttributeValuesForSp($entityId) public function allowAttributeValueForSp($entityId, $arpAttribute, $attributeValue, $attributeSource = null, $motivation = null) { /** @var AttributeReleasePolicy $arp */ - $arp = $this->getServiceProvider($entityId)->attributeReleasePolicy; + $entity = $this->getServiceProvider($entityId); + $arp = $entity->attributeReleasePolicy; $rules = []; @@ -401,7 +408,7 @@ public function allowAttributeValueForSp($entityId, $arpAttribute, $attributeVal $rules[$arpAttribute] = [$arpRule]; - $this->getServiceProvider($entityId)->attributeReleasePolicy = new AttributeReleasePolicy($rules); + $entity->attributeReleasePolicy = new AttributeReleasePolicy($rules); return $this; } @@ -581,7 +588,6 @@ private function setCoin(AbstractRole $role, $key, $name) $object = new ReflectionClass($role); $property = $object->getProperty('coins'); - $property->setAccessible(true); $property->setValue($role, $coins); } private function setMdui(AbstractRole $role, string $elementName, MultilingualElement $value) @@ -596,7 +602,6 @@ private function setMdui(AbstractRole $role, string $elementName, MultilingualEl $object = new ReflectionClass($role); $property = $object->getProperty('mdui'); - $property->setAccessible(true); $property->setValue($role, $mdui); } } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Helper/TestEntitySeeder.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Helper/TestEntitySeeder.php index db2b196ba9..f0c69276ab 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Helper/TestEntitySeeder.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Helper/TestEntitySeeder.php @@ -165,7 +165,7 @@ public static function buildRandomIdps($numberOfIdps, $locale, $defaultIdpEntity $idps = []; for ($i=1; $i < (int) $numberOfIdps + 1; $i++) { - $connected = rand(0, 1) === 1; + $connected = random_int(0, 1) === 1; $entityId = $connected ? sprintf("https://example.com/entityId/%d", $i) : sprintf("https://unconnected.example.com/entityId/%d", $i); if ($i < 25) { @@ -223,8 +223,8 @@ private static function transformIdpsForWayf(array $idpEntityIds, $currentLocale } } - $nameSort = function ($a, $b) { - return strtolower($a['Name']) > strtolower($b['Name']); + $nameSort = static function ($a, $b) { + return strcmp(strtolower($a['Name']), strtolower($b['Name'])); }; // Sort the IdP entries by name @@ -245,7 +245,7 @@ private static function findIdentityProvidersByEntityId(array $idpEntityIds): ar $idp->nameEn = $idpData['name']; $idp->nameNl = $idpData['name']; $idp->namePt = $idpData['name']; - $idp->keywordsEn = ['Awesome IdP', 'Another keyword', 'Example']; + $idp->keywordsEn = 'Awesome IdP, Another keyword, Example'; $idp->enabledInWayf = $idpData['enabled']; $idp->setDiscoveries($idpData['discoveries'] ?? []); diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/AbstractMockEntityRole.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/AbstractMockEntityRole.php index d5885de4ae..832b945323 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/AbstractMockEntityRole.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/AbstractMockEntityRole.php @@ -135,7 +135,7 @@ public function getPrivateKeyPem() $certificate = array_reduce( $idpSsoRole->getKeyDescriptor()[0]->getKeyInfo()->getInfo(), function ($carry, $info) { - return $carry ? $carry : $info instanceof Chunk ? $info : false; + return $carry ?: ($info instanceof Chunk ? $info : false); } ); diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/FakeUserDirectory.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/FakeUserDirectory.php index 4b59aa41a1..67a89fbe30 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/FakeUserDirectory.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/FakeUserDirectory.php @@ -70,7 +70,7 @@ public function __construct(Filesystem $filesystem) } $users = json_decode($content, true); - array_walk($users, function (&$user) { + array_walk($users, function (&$user): void { $user = new User( new CollabPersonId($user['collab_person_id']), new CollabPersonUuid($user['collab_person_uuid']) @@ -165,13 +165,13 @@ private function saveToDisk() $filePath = self::$directory . self::$fileName; $users = $this->users; - array_walk($users, function (&$user) { + array_walk($users, function (&$user): void { $user = [ 'collab_person_id' => $user->getCollabPersonId()->getCollabPersonId(), 'collab_person_uuid' => $user->getCollabPersonUuid()->getUuid() ]; }); - $this->filesystem->dumpFile($filePath, json_encode($users), 0664); + $this->filesystem->dumpFile($filePath, json_encode($users)); } } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockIdentityProviderFactory.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockIdentityProviderFactory.php index 6e0a6ab210..057db87536 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockIdentityProviderFactory.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockIdentityProviderFactory.php @@ -102,7 +102,7 @@ private function generateDefaultResponse(MockIdentityProvider $mockIdp) $now = gmdate('Y-m-d\TH:i:s\Z'); $tomorrow = gmdate('Y-m-d\TH:i:s\Z', time() + (24 * 60 * 60)); - $uid = 'test' . time() . rand(10000, 99999); + $uid = 'test' . time() . random_int(10000, 99999); $schacHomeOrganization = 'engine-test-stand.openconext.org'; $nameId = 'ETS-MOCK-IDP-' . time(); diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockStepupGateway.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockStepupGateway.php index 21ea574f6b..0671db0e46 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockStepupGateway.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockStepupGateway.php @@ -188,7 +188,7 @@ private function parseRequest(Request $request, $fullRequestUri) // Catch any errors gzinflate triggers $errorNo = $errorMessage = null; - set_error_handler(function ($number, $message) use (&$errorNo, &$errorMessage) { + set_error_handler(function ($number, $message) use (&$errorNo, &$errorMessage): void { $errorNo = $number; $errorMessage = $message; }); @@ -204,10 +204,7 @@ private function parseRequest(Request $request, $fullRequestUri) } // 1. Parse to xml object - // additional security against XXE Processing vulnerability - $previous = libxml_disable_entity_loader(true); $document = DOMDocumentFactory::fromString($samlRequest); - libxml_disable_entity_loader($previous); // 2. Parse saml request $authnRequest = Message::fromXML($document->firstChild); @@ -215,7 +212,7 @@ private function parseRequest(Request $request, $fullRequestUri) if (!$authnRequest instanceof SAML2AuthnRequest) { throw new RuntimeException(sprintf( 'The received request is not an AuthnRequest, "%s" received instead', - substr(get_class($authnRequest), strrpos($authnRequest, '_') + 1) + substr(get_class($authnRequest), strrpos(get_class($authnRequest), '_') + 1) )); } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockTranslator.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockTranslator.php index b670cf36da..901bdf499f 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockTranslator.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Mock/MockTranslator.php @@ -20,7 +20,7 @@ use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\DataStore\AbstractDataStore; use Symfony\Component\Translation\DataCollectorTranslator; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; final class MockTranslator implements TranslatorInterface { @@ -58,7 +58,7 @@ public function clear() } // Decorated methods - public function trans($id, array $parameters = [], $domain = null, $locale = null) + public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null) { $this->translator->getCatalogue($locale)->add($this->translations); return $this->translator->trans($id, $parameters, $domain, $locale); @@ -70,7 +70,7 @@ public function transChoice($id, $number, array $parameters = [], $domain = null return $this->translator->transChoice($id, $number, $parameters, $domain, $locale); } - public function setLocale($locale) + public function setLocale(string $locale) { $this->translator->setLocale($locale); } diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Parser/Corto/XmlToArray.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Parser/Corto/XmlToArray.php index 9a1a67bf9f..efa6551414 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Parser/Corto/XmlToArray.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Parser/Corto/XmlToArray.php @@ -420,7 +420,7 @@ public static function array2attributes($attributes) foreach((array)$attributes as $name => $attribute) { // Name must be a uri // Uri checking is hard, so at least check for a scheme. - assert('(bool)preg_match("|(\w+)\:.+|", $name)'); + assert((bool) preg_match("|(\\w+)\\:.+|", $name)); $newAttribute = [ '_Name' => $name, '_NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Resources/config/controllers.yml b/src/OpenConext/EngineBlockFunctionalTestingBundle/Resources/config/controllers.yml deleted file mode 100644 index 109fbf9650..0000000000 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Resources/config/controllers.yml +++ /dev/null @@ -1,48 +0,0 @@ -services: - engineblock.functional_test.controller.identity_provider: - class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\IdentityProviderController - arguments: - - "@engineblock.mock_entities.idp_registry" - - "@engineblock.mock_entities.saml_response_factory" - - engineblock.functional_test.controller.service_provider: - class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\ServiceProviderController - arguments: - - "@engineblock.mock_entities.sp_registry" - - "@engineblock.functional_testing.service.engine_block" - - engineblock.functional_test.controller.wayf: - class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\WayfController - arguments: - - "@twig" - - engineblock.functional_test.controller.feedback: - class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\FeedbackController - arguments: - - "@translator" - - "@twig" - - "@engineblock.compat.logger" - - engineblock.functional_test.controller.consent: - class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\ConsentController - arguments: - - "@twig" - - engineblock.functional_test.controller.stepup_mock: - class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\StepupMockController - arguments: - - "@engineblock.mock_clients.mock_stepup_gateway" - - "@twig" - - engineblock.controller.authentication.identity_provider: - class: OpenConext\EngineBlockBundle\Controller\IdentityProviderController - arguments: - - "@engineblock.compat.application" - - "@twig" - - "@engineblock.compat.logger" - - "@engineblock.service.request_access_mailer" - - "@engineblock.validator.sso_request_validator" - - "@engineblock.validator.saml_binding_validator" - - "@engineblock.validator.unsolicited_sso_request_validator" - - "@engineblock.service.authentication_state_helper" - - "@engineblock.functional_testing.fixture.features" diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Saml2/Compat/Container.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Saml2/Compat/Container.php index 4212e56b14..a477e07256 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Saml2/Compat/Container.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Saml2/Compat/Container.php @@ -67,7 +67,7 @@ public function getLogger(): LoggerInterface */ public function generateId(): string { - return self::ID_PREFIX . rand(0, 100000000); + return self::ID_PREFIX . random_int(0, 100000000); } /** diff --git a/src/OpenConext/EngineBlockFunctionalTestingBundle/Service/EngineBlock.php b/src/OpenConext/EngineBlockFunctionalTestingBundle/Service/EngineBlock.php index 4a946a5630..946e9b207c 100644 --- a/src/OpenConext/EngineBlockFunctionalTestingBundle/Service/EngineBlock.php +++ b/src/OpenConext/EngineBlockFunctionalTestingBundle/Service/EngineBlock.php @@ -31,19 +31,13 @@ class EngineBlock const UNSOLICITED_SSO_START_PATH = '/authentication/idp/unsolicited-single-sign-on/%s'; const LOGOUT = '/logout'; - protected $baseUrl; - - /** - * @param $baseUrl - */ - public function __construct($baseUrl) + public function __construct() { - $this->baseUrl = $baseUrl; } public function idpEntityId() { - return $this->baseUrl . self::IDP_METADATA_PATH; + return self::IDP_METADATA_PATH; } public function transparentSsoLocation($idpEntityId) @@ -53,7 +47,7 @@ public function transparentSsoLocation($idpEntityId) public function singleSignOnLocation() { - return $this->baseUrl . self::SINGLE_SIGN_ON_PATH; + return self::SINGLE_SIGN_ON_PATH; } public function unsolicitedLocation($identityProviderEntityId, $serviceProviderEntityId, $keyId = false) @@ -62,30 +56,28 @@ public function unsolicitedLocation($identityProviderEntityId, $serviceProviderE if ($keyId) { $keyParameter = sprintf('key:%s/', $keyId); } - return $this->baseUrl - . sprintf(self::UNSOLICITED_SSO_START_PATH, $keyParameter . md5($identityProviderEntityId)) + return sprintf(self::UNSOLICITED_SSO_START_PATH, $keyParameter . md5($identityProviderEntityId)) . '?sp-entity-id=' . urlencode($serviceProviderEntityId); } public function unsolicitedLocationInvalidParam($identityProviderEntityId, $serviceProviderEntityId) { - return $this->baseUrl - . sprintf(self::UNSOLICITED_SSO_START_PATH, md5($identityProviderEntityId)) + return sprintf(self::UNSOLICITED_SSO_START_PATH, md5($identityProviderEntityId)) . '?wrong-parameter=' . urlencode($serviceProviderEntityId); } public function spEntityId() { - return $this->baseUrl . self::SP_METADATA_PATH; + return self::SP_METADATA_PATH; } public function assertionConsumerLocation() { - return $this->baseUrl . self::ASSERTION_CONSUMER_PATH; + return self::ASSERTION_CONSUMER_PATH; } public function logoutLocation() { - return $this->baseUrl . self::LOGOUT; + return self::LOGOUT; } } diff --git a/symfony.lock b/symfony.lock new file mode 100644 index 0000000000..ef248caf10 --- /dev/null +++ b/symfony.lock @@ -0,0 +1,285 @@ +{ + "doctrine/annotations": { + "version": "1.14", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "a2759dd6123694c8d901d0ec80006e044c2e6457" + }, + "files": [ + "config/routes/annotations.yaml" + ] + }, + "doctrine/deprecations": { + "version": "1.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "87424683adc81d7dc305eefec1fced883084aab9" + } + }, + "doctrine/doctrine-bundle": { + "version": "2.7", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.4", + "ref": "eaa0b7647c0ec3dbdcf24ade4625f381aa23c027" + }, + "files": [ + "config/packages/doctrine.yaml", + "src/Entity/.gitignore", + "src/Repository/.gitignore" + ] + }, + "doctrine/doctrine-migrations-bundle": { + "version": "3.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.1", + "ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33" + }, + "files": [ + "config/packages/doctrine_migrations.yaml", + "migrations/.gitignore" + ] + }, + "friends-of-behat/symfony-extension": { + "version": "2.1", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "2.0", + "ref": "1e012e04f573524ca83795cd19df9ea690adb604" + }, + "files": [ + "behat.yml.dist", + "config/services_test.yaml", + "features/demo.feature", + "tests/Behat/DemoContext.php" + ] + }, + "liip/functional-test-bundle": { + "version": "4.9.0" + }, + "openconext/monitor-bundle": { + "version": "3.1.0" + }, + "phpstan/phpstan": { + "version": "2.1", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "1.0", + "ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767" + } + }, + "phpunit/phpunit": { + "version": "8.5", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "4.7", + "ref": "4eea8d6a476c8e9eb28c56725a4c0716df7d14c1" + }, + "files": [ + ".env.test", + "phpunit.xml.dist", + "tests/bootstrap.php" + ] + }, + "sensio/framework-extra-bundle": { + "version": "5.6", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.2", + "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b" + }, + "files": [ + "config/packages/sensio_framework_extra.yaml" + ] + }, + "squizlabs/php_codesniffer": { + "version": "3.13", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "3.6", + "ref": "1019e5c08d4821cb9b77f4891f8e9c31ff20ac6f" + } + }, + "symfony/console": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "1781ff40d8a17d87cf53f8d4cf0c8346ed2bb461" + }, + "files": [ + "bin/console" + ] + }, + "symfony/debug-bundle": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b" + }, + "files": [ + "config/packages/debug.yaml" + ] + }, + "symfony/flex": { + "version": "1.22", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" + }, + "files": [ + ".env" + ] + }, + "symfony/framework-bundle": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.4", + "ref": "3cd216a4d007b78d8554d44a5b1c0a446dab24fb" + }, + "files": [ + "config/packages/cache.yaml", + "config/packages/framework.yaml", + "config/preload.php", + "config/routes/framework.yaml", + "config/services.yaml", + "public/index.php", + "src/Controller/.gitignore", + "src/Kernel.php" + ] + }, + "symfony/mailer": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "4.3", + "ref": "09051cfde49476e3c12cd3a0e44289ace1c75a4f" + }, + "files": [ + "config/packages/mailer.yaml" + ] + }, + "symfony/monolog-bundle": { + "version": "3.8", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.7", + "ref": "aff23899c4440dd995907613c1dd709b6f59503f" + }, + "files": [ + "config/packages/monolog.yaml" + ] + }, + "symfony/phpunit-bridge": { + "version": "6.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.3", + "ref": "a411a0480041243d97382cac7984f7dce7813c08" + }, + "files": [ + ".env.test", + "bin/phpunit", + "phpunit.xml.dist", + "tests/bootstrap.php" + ] + }, + "symfony/routing": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "85de1d8ae45b284c3c84b668171d2615049e698f" + }, + "files": [ + "config/packages/routing.yaml", + "config/routes.yaml" + ] + }, + "symfony/security-bundle": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "98f1f2b0d635908c2b40f3675da2d23b1a069d30" + }, + "files": [ + "config/packages/security.yaml" + ] + }, + "symfony/translation": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b" + }, + "files": [ + "config/packages/translation.yaml", + "translations/.gitignore" + ] + }, + "symfony/twig-bundle": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.4", + "ref": "bb2178c57eee79e6be0b297aa96fc0c0def81387" + }, + "files": [ + "config/packages/twig.yaml", + "templates/base.html.twig" + ] + }, + "symfony/validator": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "c32cfd98f714894c4f128bb99aa2530c1227603c" + }, + "files": [ + "config/packages/validator.yaml" + ] + }, + "symfony/web-profiler-bundle": { + "version": "5.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "5.3", + "ref": "24bbc3d84ef2f427f82104f766014e799eefcc3e" + }, + "files": [ + "config/packages/web_profiler.yaml", + "config/routes/web_profiler.yaml" + ] + } +} diff --git a/tests/behat-ci.yml b/tests/behat-ci.yml deleted file mode 100644 index 551a4c081b..0000000000 --- a/tests/behat-ci.yml +++ /dev/null @@ -1,91 +0,0 @@ -default: - autoload: - - '%paths.base%/../src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context' - - suites: - default: - paths: - - '%paths.base%/../src/OpenConext/EngineBlockFunctionalTestingBundle/Features' - formatter: - name: progress - filters: - tags: "~@WIP&&~@SKIP&&~@selenium" - contexts: &defaultContexts - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\EngineBlockContext: - serviceRegistry: '@engineblock.functional_testing.fixture.service_registry' - engineBlock: '@engineblock.functional_testing.service.engine_block' - mockSpRegistry: '@engineblock.mock_entities.sp_registry' - mockIdpRegistry: '@engineblock.mock_entities.idp_registry' - features: '@engineblock.functional_testing.fixture.features' - pdpClient: '@engineblock.functional_testing.fixture.pdp_client' - authenticationLoopGuard: '@engineblock.functional_testing.fixture.authentication_loop_guard' - attributeAggregationClient: '@engineblock.functional_testing.fixture.attribute_aggregation_client' - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\MockIdpContext: - serviceRegistryFixture: '@engineblock.functional_testing.fixture.service_registry' - engineBlock: '@engineblock.functional_testing.service.engine_block' - idpFactory: '@engineblock.mock_entities.idp_factory' - mockIdpRegistry: '@engineblock.mock_entities.idp_registry' - mockSpRegistry: '@engineblock.mock_entities.sp_registry' - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\MockSpContext: - serviceRegistryFixture: '@engineblock.functional_testing.fixture.service_registry' - engineBlock: '@engineblock.functional_testing.service.engine_block' - mockSpFactory: '@engineblock.mock_entities.sp_factory' - mockSpRegistry: '@engineblock.mock_entities.sp_registry' - mockIdpRegistry: '@engineblock.mock_entities.idp_registry' - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\StepupContext: - mockSpRegistry: '@engineblock.mock_entities.sp_registry' - mockIdpRegistry: '@engineblock.mock_entities.idp_registry' - gatewayMockConfiguration: '@engineblock.functional_testing.fixture.stepup_gateway_mock' - serviceRegistryFixture: '@engineblock.functional_testing.fixture.service_registry' - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\MfaEntitiesContext: - mockSpRegistry: '@engineblock.mock_entities.sp_registry' - mockIdpRegistry: '@engineblock.mock_entities.idp_registry' - serviceRegistryFixture: '@engineblock.functional_testing.fixture.service_registry' - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\TranslationContext: - mockTranslator: '@engineblock.functional_testing.mock.translator' - - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\MinkContext - selenium: - mink_session: chrome - mink_javascript_session: chrome - paths: - - '%paths.base%/../src/OpenConext/EngineBlockFunctionalTestingBundle/Features' - formatter: - name: progress - filters: - tags: "@selenium&&~@SKIP&&~@WIP" - contexts: *defaultContexts - wip: - paths: - - '%paths.base%/../src/OpenConext/EngineBlockFunctionalTestingBundle/Features' - formatter: - name: pretty - parameters: - verbose: true - filters: - tags: "@WIP&&~@SKIP&&~@selenium" - contexts: *defaultContexts - - extensions: - Behat\MinkExtension: - base_url: https://engine.dev.openconext.local/ - goutte: ~ - sessions: - default: - goutte: - guzzle_parameters: - verify: false - chrome: - selenium2: - browser: chrome - wd_host: http://selenium.dev.openconext.local:4444/wd/hub - capabilities: - chrome: - switches: - - "--headless" - - "--disable-gpu" - - "--window-size=1920,1080" - - "--no-sandbox" - Behat\Symfony2Extension: - kernel: - env: ci - debug: true diff --git a/tests/behat.yml b/tests/behat.yml index cfa9d6fc89..7df80fd6c4 100644 --- a/tests/behat.yml +++ b/tests/behat.yml @@ -1,7 +1,6 @@ default: - autoload: - - '%paths.base%/../src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context' - +# autoload: +# - '%paths.base%/../src/OpenConext/EngineBlockFunctionalTestingBundle/Features/Context' suites: default: paths: @@ -9,7 +8,7 @@ default: formatter: name: progress filters: - tags: "~@WIP&&~@SKIP&&~@selenium" + tags: "~@WIP&&~@SKIP&&~@functional" contexts: &defaultContexts - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\EngineBlockContext: serviceRegistry: '@engineblock.functional_testing.fixture.service_registry' @@ -44,7 +43,7 @@ default: - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\TranslationContext: mockTranslator: '@engineblock.functional_testing.mock.translator' - OpenConext\EngineBlockFunctionalTestingBundle\Features\Context\MinkContext - selenium: + functional: mink_session: chrome mink_javascript_session: chrome paths: @@ -52,7 +51,7 @@ default: formatter: name: progress filters: - tags: "@selenium&&~@SKIP&&~@WIP" + tags: "@functional&&~@SKIP&&~@WIP" contexts: *defaultContexts wip: paths: @@ -62,32 +61,25 @@ default: parameters: verbose: true filters: - tags: "@WIP&&~@SKIP&&~@selenium" + tags: "@WIP&&~@SKIP&&~@functional" contexts: *defaultContexts extensions: + DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~ Behat\MinkExtension: + browser_name: chrome base_url: https://engine.dev.openconext.local/ - goutte: ~ sessions: default: - goutte: - guzzle_parameters: - verify: false + browserkit_http: + http_client_parameters: + verify_peer: false + verify_host: false chrome: - selenium2: - browser: chrome - wd_host: http://127.0.0.1:4444/wd/hub - capabilities: - chrome: - switches: - - "--headless" - - "--disable-gpu" - - "--window-size=1920,1080" - - "--no-sandbox" - - "--disable-dev-shm-usage" - Behat\Symfony2Extension: + chrome: + api_url: http://chrome.dev.openconext.local:9222 + + FriendsOfBehat\SymfonyExtension: kernel: - env: ci + environment: ci debug: true - diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2ed28ce79e..431ac6874f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -16,11 +16,10 @@ * limitations under the License. */ -define('TEST_RESOURCES_DIR', dirname(__FILE__) . '/resources'); +define('TEST_RESOURCES_DIR', __DIR__ . '/resources'); -require_once realpath(__DIR__) . '/../app/autoload.php'; -require_once realpath(__DIR__) . '/../app/AppKernel.php'; +require_once realpath(__DIR__) . '/../vendor/autoload.php'; +require_once realpath(__DIR__) . '/../src/Kernel.php'; -$kernel = new AppKernel('test', true); -$kernel->loadClassCache(); +$kernel = new \App\Kernel('test', true); $kernel->boot(); diff --git a/tests/e2e/cypress.config.js b/tests/e2e/cypress.config.js index c3d1079b76..265e940c12 100644 --- a/tests/e2e/cypress.config.js +++ b/tests/e2e/cypress.config.js @@ -1,55 +1,44 @@ const { defineConfig } = require("cypress"); +const htmlvalidate = require("cypress-html-validate/plugin"); module.exports = defineConfig({ - - e2e: { - excludeSpecPattern: [ - "**/__snapshots__/*", - "**/__image_snapshots__/*", - "**/unit-tests/**" - ], - screenshotOnRunFailure: false, - setupNodeEvents: function (on, config) { - const htmlvalidate = require('cypress-html-validate/plugin'); - - htmlvalidate.install(on, { - "rules": { - "prefer-button": "off", - "prefer-native-element": ["error", { - "exclude": ["button"], - }], - "require-sri": ["error", { - "target": "crossorigin", - }], - }, - }); - - module.exports = (on, config) => { - - // debug a11y in ci - on('task', { - log(message) { - console.log(message); - - return null; - }, - table(message) { - console.table(message); - - return null; - }, - 'htmlvalidate:options'(opts) { - console.log(opts); - return null; - - } - }); - - return config; - }; - - }, - specPattern: "./cypress/integration/**/*.spec.js", - "video": false - }, + e2e: { + excludeSpecPattern: [ + "**/__snapshots__/*", + "**/__image_snapshots__/*", + "**/unit-tests/**" + ], + specPattern: "./cypress/integration/**/*.spec.js", + screenshotOnRunFailure: false, + video: false, + + setupNodeEvents(on, config) { + // 🧪 Install htmlvalidate plugin + htmlvalidate.install(on, { + rules: { + "prefer-button": "off", + "prefer-native-element": ["error", { + exclude: ["button"] + }], + "require-sri": ["error", { + target: "crossorigin" + }] + } + }); + + // Custom logging tasks + on("task", { + log(message) { + console.log(message); + return null; + }, + table(message) { + console.table(message); + return null; + } + }); + + return config; + } + } }); diff --git a/tests/e2e/cypress/integration/openconext/wayf/WayfMouseBehaviour.spec.js b/tests/e2e/cypress/integration/openconext/wayf/WayfMouseBehaviour.spec.js index f662ea4b29..11a0f92fa5 100644 --- a/tests/e2e/cypress/integration/openconext/wayf/WayfMouseBehaviour.spec.js +++ b/tests/e2e/cypress/integration/openconext/wayf/WayfMouseBehaviour.spec.js @@ -24,7 +24,7 @@ context('WayfMouseBehaviour', () => { cy.get('a.result.active.access:nth-child(1)').click({force:true}); // We visit the fake IdP, verify the right redirect is performed cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/1'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/1'); }); // Go back to the WAYF cy.visit('https://engine.dev.openconext.local/functional-testing/wayf?connectedIdps=10&displayUnconnectedIdpsWayf=true&unconnectedIdps=5'); @@ -32,7 +32,7 @@ context('WayfMouseBehaviour', () => { cy.get('a.result.active.access:nth-child(2)').click({force:true}); // We visit the fake IdP, verify the right redirect is performed cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/2'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/2'); }); // Go back to the WAYF cy.visit('https://engine.dev.openconext.local/functional-testing/wayf?connectedIdps=10&displayUnconnectedIdpsWayf=true&unconnectedIdps=5'); diff --git a/tests/e2e/cypress/integration/shared/cookieRemoval.a11y.spec.js b/tests/e2e/cypress/integration/shared/cookieRemoval.a11y.spec.js index 11d84e6a0c..636b92f076 100644 --- a/tests/e2e/cypress/integration/shared/cookieRemoval.a11y.spec.js +++ b/tests/e2e/cypress/integration/shared/cookieRemoval.a11y.spec.js @@ -1,5 +1,5 @@ /** - * This doesn't run in CI, which is why it's skipped. You can run it locally by setting the wayf.remember_choice flag to true in parameters.yml. + * This doesn't run in CI, which is why it's skipped. You can run it locally by setting the wayf.remember_choice flag to true in parameters.yaml. */ context.skip('Cookie removal page verify a11y', () => { beforeEach(() => { diff --git a/tests/e2e/cypress/integration/skeune/wayf/wayf.keyboard.spec.js b/tests/e2e/cypress/integration/skeune/wayf/wayf.keyboard.spec.js index a09e3b404e..e0da11ad3f 100644 --- a/tests/e2e/cypress/integration/skeune/wayf/wayf.keyboard.spec.js +++ b/tests/e2e/cypress/integration/skeune/wayf/wayf.keyboard.spec.js @@ -35,7 +35,7 @@ context('WAYF when using the keyboard', () => { .focus() .type('{enter}'); cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/2'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/2'); }); cy.visit('https://engine.dev.openconext.local/functional-testing/wayf'); }); @@ -45,7 +45,7 @@ context('WAYF when using the keyboard', () => { cy.get(searchFieldSelector) .type('{enter}'); cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/1'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/1'); }); }); @@ -55,7 +55,7 @@ context('WAYF when using the keyboard', () => { .type('2') .type('{enter}'); cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/2'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/2'); }); }); }); @@ -219,12 +219,16 @@ context('WAYF when using the keyboard', () => { cy.addOnePreviouslySelectedIdp(); cy.selectFirstIdp(false, selectedIdpDataIndex1); cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/1'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/1'); }); }); it('Test if the count was raised on the selected idp', () => { cy.addOnePreviouslySelectedIdp(); + cy.get(selectedIdpDataIndex1).should('have.attr', 'data-count', '1'); + cy.selectFirstIdp(false, selectedIdpDataIndex1); + cy.loadWayf(); + cy.get(selectedIdpDataIndex1).should('have.attr', 'data-count', '2'); cy.selectFirstIdp(false, selectedIdpDataIndex1); cy.loadWayf(); cy.get(selectedIdpDataIndex1).should('have.attr', 'data-count', '3'); diff --git a/tests/e2e/cypress/integration/skeune/wayf/wayf.mouse.spec.js b/tests/e2e/cypress/integration/skeune/wayf/wayf.mouse.spec.js index 43d79e03d7..bb018989de 100644 --- a/tests/e2e/cypress/integration/skeune/wayf/wayf.mouse.spec.js +++ b/tests/e2e/cypress/integration/skeune/wayf/wayf.mouse.spec.js @@ -12,7 +12,7 @@ context('WAYF when using the mouse', () => { .eq(1) .click({force: true}); cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/2'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/2'); }); cy.visit('https://engine.dev.openconext.local/functional-testing/wayf'); }); @@ -123,7 +123,7 @@ context('WAYF when using the mouse', () => { cy.addOnePreviouslySelectedIdp(false); cy.selectFirstIdp(true, selectedIdpDataIndex1); cy.location().should((loc) => { - expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https%3A//example.com/entityId/1'); + expect(loc.href).to.eq('https://engine.dev.openconext.local/?idp=https://example.com/entityId/1'); }); }); diff --git a/tests/e2e/cypress/support/commands.js b/tests/e2e/cypress/support/commands.js index 89a22e3a6f..9d979c8429 100644 --- a/tests/e2e/cypress/support/commands.js +++ b/tests/e2e/cypress/support/commands.js @@ -77,7 +77,7 @@ Cypress.Commands.add('selectFirstIdp', (click = true, firstElementSelector = '.w return; } - cy.get(firstElementSelector).type('{enter}', {force: true}); + cy.get(firstElementSelector).focus().type('{enter}', {force: true}); }); Cypress.Commands.add('selectFirstIdpAndReturn', (click = true, url = 'https://engine.dev.openconext.local/functional-testing/wayf') => { diff --git a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyControllerApiTest.php b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyControllerApiTest.php index 11f585f163..6ac5af1f45 100644 --- a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyControllerApiTest.php +++ b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/AttributeReleasePolicyControllerApiTest.php @@ -18,31 +18,25 @@ namespace OpenConext\EngineBlockBundle\Tests; +use Doctrine\DBAL\Query\QueryBuilder; use OpenConext\EngineBlock\Metadata\AttributeReleasePolicy; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; -use Symfony\Bundle\FrameworkBundle\Client; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; class AttributeReleasePolicyControllerApiTest extends WebTestCase { - public function setUp(): void - { - $this->clearMetadataFixtures(); - } - public function tearDown(): void { $this->clearMetadataFixtures(); + parent::tearDown(); // Ensure the kernel is properly shutdown to avoid state pollution between tests. } - /** - * @test - * @group Api - * @group Arp - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function authentication_is_required_for_applying_arps() { $unauthenticatedClient = static::createClient(); @@ -51,20 +45,17 @@ public function authentication_is_required_for_applying_arps() } /** - * @test - * @group Api - * @group Arp - * @group Profile * - * @dataProvider invalidHttpMethodProvider * @param string $invalidHttpMethod */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidHttpMethodProvider')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function only_post_requests_are_allowed_when_applying_arp($invalidHttpMethod) { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedClient(); $client->request($invalidHttpMethod, 'https://engine-api.dev.openconext.local/arp'); $this->assertStatusCode(Response::HTTP_METHOD_NOT_ALLOWED, $client); @@ -73,15 +64,15 @@ public function only_post_requests_are_allowed_when_applying_arp($invalidHttpMet $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Arp - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_apply_arp_if_user_does_not_have_profile_role() { - $client = static::createClient([], [ + $client = static::createClient(); + + $client->setServerParameters([ 'PHP_AUTH_USER' => 'no_roles', 'PHP_AUTH_PW' => 'no_roles', ]); @@ -94,20 +85,17 @@ public function cannot_apply_arp_if_user_does_not_have_profile_role() } /** - * @test - * @group Api - * @group Arp - * @group Profile * - * @dataProvider invalidJsonPayloadProvider * @param string $invalidJsonPayload */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidJsonPayloadProvider')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_push_invalid_content_to_the_arp_api($invalidJsonPayload) { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedClient(); $client->request( 'POST', @@ -123,12 +111,10 @@ public function cannot_push_invalid_content_to_the_arp_api($invalidJsonPayload) $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Arp - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function all_attributes_are_released_through_the_arp_api_if_no_arp_is_found_for_a_service_provider() { $spEntityId = 'https://my-test-sp.test'; @@ -136,14 +122,11 @@ public function all_attributes_are_released_through_the_arp_api_if_no_arp_is_fou 'attribute-key' => ['attribute-value'] ]; + $client = $this->createAuthorizedClient(); + $serviceProvider = new ServiceProvider($spEntityId); $this->addServiceProviderFixture($serviceProvider); - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); - $arpRequestData = [ 'entityIds' => [ $spEntityId @@ -172,12 +155,10 @@ public function all_attributes_are_released_through_the_arp_api_if_no_arp_is_fou $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Arp - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function arps_are_applied_to_sps_and_attributes_by_the_arp_api() { $spNotReceivingSpecialAttributeEntityId = 'https://sp-that-does-not-receive-special-attribute.test'; @@ -194,6 +175,8 @@ public function arps_are_applied_to_sps_and_attributes_by_the_arp_api() 'special-attribute' => ['*'], ]); + $client = $this->createAuthorizedClient(); + $spNotReceivingSpecialAttribute = $this->createServiceProviderWithArp( $spNotReceivingSpecialAttributeEntityId, $arpWithoutSpecialAttribute @@ -205,11 +188,6 @@ public function arps_are_applied_to_sps_and_attributes_by_the_arp_api() $this->addServiceProviderFixture($spNotReceivingSpecialAttribute); $this->addServiceProviderFixture($spReceivingSpecialAttribute); - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); - $arpRequestData = [ 'entityIds' => [ $spReceivingSpecialAttributeEntityId, @@ -245,12 +223,10 @@ public function arps_are_applied_to_sps_and_attributes_by_the_arp_api() $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Arp - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function arps_matching_on_exact_keys_are_applied_to_sps_and_attributes_by_the_arp_api() { $spNotReceivingSpecialAttributeEntityId = 'https://sp-that-does-not-receive-special-attribute.test'; @@ -268,6 +244,8 @@ public function arps_matching_on_exact_keys_are_applied_to_sps_and_attributes_by 'special-attribute' => ['secret-value'], ]); + $client = $this->createAuthorizedClient(); + $spNotReceivingSpecialAttribute = $this->createServiceProviderWithArp( $spNotReceivingSpecialAttributeEntityId, $arpWithoutMatchingSpecialAttribute @@ -279,10 +257,6 @@ public function arps_matching_on_exact_keys_are_applied_to_sps_and_attributes_by $this->addServiceProviderFixture($spNotReceivingSpecialAttribute); $this->addServiceProviderFixture($spReceivingSpecialAttribute); - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); $arpRequestData = [ 'entityIds' => [ @@ -319,12 +293,10 @@ public function arps_matching_on_exact_keys_are_applied_to_sps_and_attributes_by $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Arp - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Arp')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function arps_matching_on_partial_keys_are_applied_to_sps_and_attributes_by_the_arp_api() { $spNotReceivingSpecialAttributeEntityId = 'https://sp-that-does-not-receive-special-attribute.test'; @@ -342,6 +314,8 @@ public function arps_matching_on_partial_keys_are_applied_to_sps_and_attributes_ 'special-attribute' => ['secret-*'], ]); + $client = $this->createAuthorizedClient(); + $spNotReceivingSpecialAttribute = $this->createServiceProviderWithArp( $spNotReceivingSpecialAttributeEntityId, $arpWithoutMatchingSpecialAttribute @@ -353,10 +327,6 @@ public function arps_matching_on_partial_keys_are_applied_to_sps_and_attributes_ $this->addServiceProviderFixture($spNotReceivingSpecialAttribute); $this->addServiceProviderFixture($spReceivingSpecialAttribute); - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); $arpRequestData = [ 'entityIds' => [ @@ -393,7 +363,7 @@ public function arps_matching_on_partial_keys_are_applied_to_sps_and_attributes_ $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - public function invalidHttpMethodProvider() + public static function invalidHttpMethodProvider() { return [ 'GET' => ['GET'], @@ -404,7 +374,7 @@ public function invalidHttpMethodProvider() ]; } - public function invalidJsonPayloadProvider() + public static function invalidJsonPayloadProvider() { return [ 'string body' => ['"not-an-object"'], @@ -453,17 +423,11 @@ public function invalidJsonPayloadProvider() ]; } - private function assertStatusCode($expectedStatusCode, Client $client) + private function assertStatusCode($expectedStatusCode, KernelBrowser $client) { $this->assertEquals($expectedStatusCode, $client->getResponse()->getStatusCode()); } - private function getContainer() : ContainerInterface - { - self::bootKernel(); - return self::$kernel->getContainer(); - } - private function createServiceProviderWithArp($entityId, AttributeReleasePolicy $attributeReleasePolicy) { $sp = new ServiceProvider($entityId); @@ -473,16 +437,30 @@ private function createServiceProviderWithArp($entityId, AttributeReleasePolicy private function addServiceProviderFixture(ServiceProvider $serviceProvider) { - $em = $this->getContainer()->get('doctrine')->getEntityManager(); + $em = self::getContainer()->get('doctrine')->getManager(); $em->persist($serviceProvider); $em->flush(); } private function clearMetadataFixtures() { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->delete('sso_provider_roles_eb5') - ->execute(); + ->executeStatement() ; + } + + /** + * @return KernelBrowser + */ + private function createAuthorizedClient(): KernelBrowser + { + $client = static::createClient(); + $client->setServerParameters([ + 'PHP_AUTH_USER' => self::getContainer()->getParameter('api.users.profile.username'), + 'PHP_AUTH_PW' => self::getContainer()->getParameter('api.users.profile.password'), + ]); + return $client; } } diff --git a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsControllerTest.php b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsControllerTest.php index 304e2f4b88..e2e06877d4 100644 --- a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsControllerTest.php +++ b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConnectionsControllerTest.php @@ -18,46 +18,49 @@ namespace OpenConext\EngineBlockBundle\Tests; +use App\Kernel; +use Doctrine\DBAL\Query\QueryBuilder; use OpenConext\EngineBlock\Metadata\Entity\IdentityProvider; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; use OpenConext\EngineBlock\Metadata\StepupConnections; -use OpenConext\EngineBlockBundle\Configuration\Feature; use OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration; use Symfony\Bundle\FrameworkBundle\Client; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; class ConnectionsControllerTest extends WebTestCase { - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - */ + protected function tearDown(): void + { + $this->clearMetadataFixtures(); + parent::tearDown(); + } + + + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function authentication_is_required_for_pushing_metadata() { - $unauthenticatedClient = static::createClient();; + $unauthenticatedClient = static::createClient(); $unauthenticatedClient->request('POST', 'https://engine-api.dev.openconext.local/api/connections'); $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); } /** - * @test - * @group Api - * @group Connections - * @group MetadataPush * - * @dataProvider invalidHttpMethodProvider * @param string $invalidHttpMethod */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidHttpMethodProvider')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function only_post_requests_are_allowed_when_pushing_metadata($invalidHttpMethod) { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); $client->request($invalidHttpMethod, 'https://engine-api.dev.openconext.local/api/connections'); $this->assertStatusCode(Response::HTTP_METHOD_NOT_ALLOWED, $client); @@ -66,19 +69,14 @@ public function only_post_requests_are_allowed_when_pushing_metadata($invalidHtt $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - * @group FeatureToggle - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Group('FeatureToggle')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_push_metadata_if_feature_is_disabled() { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); $this->disableMetadataPushApiFeatureFor($client); @@ -89,15 +87,14 @@ public function cannot_push_metadata_if_feature_is_disabled() $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_push_metadata_if_user_does_not_have_manage_role() { - $client = static::createClient([], [ + $client = static::createClient(); + $client->setServerParameters([ 'PHP_AUTH_USER' => 'no_roles', 'PHP_AUTH_PW' => 'no_roles', ]); @@ -110,20 +107,17 @@ public function cannot_push_metadata_if_user_does_not_have_manage_role() } /** - * @test - * @group Api - * @group Connections - * @group MetadataPush * - * @dataProvider invalidJsonPayloadProvider * @param string $invalidJsonPayload */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidJsonPayloadProvider')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_push_invalid_content_to_the_metadata_push_api($invalidJsonPayload) { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); $client->request( 'POST', @@ -139,21 +133,13 @@ public function cannot_push_invalid_content_to_the_metadata_push_api($invalidJso $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - * - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function pushing_data_to_engineblock_should_succeed() { - $this->clearMetadataFixtures(); - - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); foreach ($this->validConnectionsData() as $step) { @@ -208,21 +194,13 @@ public function pushing_data_to_engineblock_should_succeed() } - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - * - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function pushing_data_with_coins_to_engineblock_should_succeed() { - $this->clearMetadataFixtures(); - - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); foreach ($this->validConnectionsWithCoinsData() as $connection) { @@ -262,21 +240,13 @@ public function pushing_data_with_coins_to_engineblock_should_succeed() } } - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - * - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function pushing_manage_sfo_data_should_succeed() { - $this->clearMetadataFixtures(); - - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); $payload = '{"connections" : { "2d96e27a-76cf-4ca2-ac70-ece5d4c49523": { @@ -352,20 +322,13 @@ public function pushing_manage_sfo_data_should_succeed() } - /** - * @test - * @group Api - * @group Connections - * @group MetadataPush - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Connections')] + #[\PHPUnit\Framework\Attributes\Group('MetadataPush')] + #[\PHPUnit\Framework\Attributes\Test] public function pushing_data_to_engineblock_can_fail() { - $this->clearMetadataFixtures(); - - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.metadataPush.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.metadataPush.password'), - ]); + $client = $this->createAuthorizedClient(); // The second 'step' will overwrite the entity id for the one entry. It only changes some case, resulting in // a sql error in Engine. That exception results in a 500 JSON response @@ -387,7 +350,7 @@ public function pushing_data_to_engineblock_can_fail() } } - public function invalidHttpMethodProvider() + public static function invalidHttpMethodProvider() { return [ 'GET' => ['GET'], @@ -398,7 +361,7 @@ public function invalidHttpMethodProvider() ]; } - public function invalidJsonPayloadProvider() + public static function invalidJsonPayloadProvider() { return [ 'string body' => ['"a-string"'], @@ -411,31 +374,26 @@ public function invalidJsonPayloadProvider() ]; } - private function assertStatusCode($expectedStatusCode, Client $client) + private function assertStatusCode($expectedStatusCode, KernelBrowser $client) { $this->assertEquals($expectedStatusCode, $client->getResponse()->getStatusCode()); } - private function getContainer() : ContainerInterface - { - self::bootKernel(); - return self::$kernel->getContainer(); - } - - private function disableMetadataPushApiFeatureFor(Client $client) + private function disableMetadataPushApiFeatureFor(KernelBrowser $client) { - $featureToggles = new FeatureConfiguration([ - 'api.metadata_push' => new Feature('api.metadata_push', false) + $mock = new FeatureConfiguration([ + 'api.metadata_push' => false, ]); - $client->getContainer()->set('engineblock.features', $featureToggles); + $client->getContainer()->set(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class, $mock); } private function clearMetadataFixtures() { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->delete('sso_provider_roles_eb5') - ->execute(); + ->executeStatement(); } /** @@ -443,7 +401,7 @@ private function clearMetadataFixtures() */ private function getStoredMetadata() { - $doctrine = $this->getContainer()->get('doctrine'); + $doctrine = self::getContainer()->get('doctrine'); $doctrine->getManager()->clear(); @@ -466,7 +424,7 @@ private function createJsonData($connections) { $connectionsJson = []; foreach ($connections as $data) { - $connectionsJson[] = $this->createPayloadConnectionJson($data['uuid'], $data['entityId'], $data['name'], $data['type'], $data['coins']); + $connectionsJson[] = $this->createPayloadConnectionJson($data['uuid'], $data['entityId'], $data['name'], $data['type'], $data['coins'] ?? []); } $connectionsJson = implode(',', $connectionsJson); @@ -661,4 +619,17 @@ private function failingConnectionsData() ] ]; } + + /** + * @return KernelBrowser + */ + private function createAuthorizedClient(): KernelBrowser + { + $client = static::createClient(); + $client->setServerParameters([ + 'PHP_AUTH_USER' => self::getContainer()->getParameter('api.users.metadataPush.username'), + 'PHP_AUTH_PW' => self::getContainer()->getParameter('api.users.metadataPush.password'), + ]); + return $client; + } } diff --git a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConsentControllerTest.php b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConsentControllerTest.php index 66e03cb552..ab6860cf48 100644 --- a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConsentControllerTest.php +++ b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/ConsentControllerTest.php @@ -19,52 +19,48 @@ namespace OpenConext\EngineBlockBundle\Tests; use DateTime; +use Doctrine\DBAL\Query\QueryBuilder; use OpenConext\EngineBlock\Metadata\ContactPerson; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; use OpenConext\EngineBlock\Metadata\Mdui; use OpenConext\EngineBlock\Metadata\Organization; -use OpenConext\EngineBlockBundle\Configuration\Feature; use OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration; use OpenConext\Value\Saml\NameIdFormat; use PDOStatement; -use Symfony\Bundle\FrameworkBundle\Client; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; use function json_decode; use function json_encode; final class ConsentControllerTest extends WebTestCase { - public function __construct($name = null, array $data = [], $dataName = '') - { - $this->clearConsentFixtures(); - $this->clearMetadataFixtures(); - - parent::__construct($name, $data, $dataName); - - } - public function tearDown(): void { $this->clearConsentFixtures(); $this->clearMetadataFixtures(); + parent::tearDown(); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function authentication_is_required_for_accessing_the_consent_api() { $userId = 'my-name-id'; $unauthenticatedClient = static::createClient(); $unauthenticatedClient->request('GET', 'https://engine-api.dev.openconext.local/consent/' . $userId); - $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + } + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] + public function authentication_is_required_for_accessing_the_remove_consent_api() + { $unauthenticatedClient = static::createClient(); $unauthenticatedClient->request('POST', 'https://engine-api.dev.openconext.local/remove-consent'); $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); @@ -72,22 +68,19 @@ public function authentication_is_required_for_accessing_the_consent_api() } /** - * @test - * @group Api - * @group Consent - * @group Profile * - * @dataProvider invalidHttpMethodProvider * @param string $invalidHttpMethod */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidHttpMethodProvider')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function only_get_requests_are_allowed_when_accessing_the_consent_api($invalidHttpMethod) { $userId = 'my-name-id'; - $client = $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $client->request($invalidHttpMethod, 'https://engine-api.dev.openconext.local/consent/' . $userId); $this->assertStatusCode(Response::HTTP_METHOD_NOT_ALLOWED, $client); @@ -96,21 +89,16 @@ public function only_get_requests_are_allowed_when_accessing_the_consent_api($in $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - * @group FeatureToggle - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Group('FeatureToggle')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_consent_api_if_the_feature_has_been_disabled() { $userId = 'my-name-id'; - $client = $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $this->disableConsentApiFeatureFor($client); @@ -121,12 +109,10 @@ public function cannot_access_the_consent_api_if_the_feature_has_been_disabled() $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_consent_api_if_user_does_not_have_profile_role() { $userId = 'my-name-id'; @@ -144,20 +130,15 @@ public function cannot_access_the_consent_api_if_user_does_not_have_profile_role $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function a_consent_listing_for_a_not_found_user_is_retrieved_as_an_empty_array_from_the_consent_api() { $userId = 'my-name-id'; - $client = $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $client->request('GET', 'https://engine-api.dev.openconext.local/consent/' . $userId); @@ -171,12 +152,10 @@ public function a_consent_listing_for_a_not_found_user_is_retrieved_as_an_empty_ $this->assertSame($expectedData, $responseData); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function a_consent_listing_for_a_given_user_is_retrieved_from_the_consent_api() { $userId = 'my-name-id'; @@ -208,10 +187,8 @@ public function a_consent_listing_for_a_given_user_is_retrieved_from_the_consent $secondSupportContact, ]; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); + $this->addServiceProviderFixture($serviceProvider); $this->addConsentFixture($userId, $spEntityId, $attributeHash, $consentType, $consentDate, $deletedAt); @@ -254,12 +231,10 @@ public function a_consent_listing_for_a_given_user_is_retrieved_from_the_consent $this->assertEquals($expectedData, $responseData); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function consent_is_soft_deleted_from_the_consent_api() { $userId = 'urn:collab:person:institution-a:my-name-id'; @@ -291,10 +266,7 @@ public function consent_is_soft_deleted_from_the_consent_api() $secondSupportContact, ]; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $this->addServiceProviderFixture($serviceProvider); $this->addConsentFixture($userId, $spEntityId, $attributeHash, $consentType, $consentDate, $deletedAt); @@ -313,12 +285,10 @@ public function consent_is_soft_deleted_from_the_consent_api() $this->assertNotNull($dbResults[0]['deleted_at']); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Test] public function consent_is_soft_deleted_from_the_consent_api_multiple_soft_deletions() { $userId = 'urn:collab:person:institution-a:my-name-id'; @@ -350,10 +320,7 @@ public function consent_is_soft_deleted_from_the_consent_api_multiple_soft_delet $secondSupportContact, ]; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $this->addServiceProviderFixture($serviceProvider); $this->addConsentFixture($userId, $spEntityId, $attributeHash, $consentType, $consentDate, $deletedAt); @@ -379,20 +346,15 @@ public function consent_is_soft_deleted_from_the_consent_api_multiple_soft_delet $this->assertEquals(3, $count['removed']); } - /** - * @test - * @group Api - * @group Consent - * @group FeatureToggle - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('FeatureToggle')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_remove_consent_api_if_the_feature_has_been_disabled() { $collabPersonId = 'urn:collab:person:test'; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.deprovision.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.deprovision.password'), - ]); + $client = $this->createAuthorizedDeprovisionClient(); $this->disableRemoveConsentApiFeatureFor($client); @@ -403,23 +365,18 @@ public function cannot_access_the_remove_consent_api_if_the_feature_has_been_dis $this->assertResponseIsJson($client); } - /** - * @param Client $client - */ - private function disableRemoveConsentApiFeatureFor(Client $client) + private function disableRemoveConsentApiFeatureFor(KernelBrowser $client) { - $featureToggles = new FeatureConfiguration([ - 'api.consent_remove' => new Feature('api.consent_remove', false), - 'eb.feature_enable_consent' => new Feature('eb.feature_enable_consent', true), + $mock = new FeatureConfiguration([ + 'api.consent_remove' => false, + 'eb.feature_enable_consent' => true, ]); - $client->getContainer()->set('engineblock.features', $featureToggles); + $client->getContainer()->set(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class, $mock); } - /** - * @test - * @group Api - * @group Consent - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_remove_consent_api_if_user_does_not_have_profile_role() { $collabPersonId = 'urn:collab:person:test'; @@ -436,17 +393,12 @@ public function cannot_access_the_remove_consent_api_if_user_does_not_have_profi $this->assertResponseIsJson($client); } - /** - * @test - * @group Api - * @group Consent - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Test] public function no_consent_is_removed_if_request_parameters_are_missing_or_incorrect() { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $data = json_encode(['userId' => 'urn:collab:person:test', 'serviceProviderId' => 'https://example.com/metadata']); $client->request('POST', 'https://engine-api.dev.openconext.local/remove-consent', [], [], [], $data); @@ -455,17 +407,12 @@ public function no_consent_is_removed_if_request_parameters_are_missing_or_incor $this->assertResponseIsJson($client); } - /** - * @test - * @group Api - * @group Consent - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Test] public function no_consent_is_removed_if_collab_person_id_is_unknown() { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $data = json_encode(['collabPersonId' => 'urn:collab:person:test', 'serviceProviderEntityId' => 'https://example.com/metadata']); $client->request('POST', 'https://engine-api.dev.openconext.local/remove-consent', [], [], [], $data); @@ -478,7 +425,7 @@ public function no_consent_is_removed_if_collab_person_id_is_unknown() $this->assertSame(false, $responseData); } - public function invalidHttpMethodProvider() + public static function invalidHttpMethodProvider() { return [ 'POST' => ['POST'], @@ -489,50 +436,60 @@ public function invalidHttpMethodProvider() ]; } - private function assertStatusCode($expectedStatusCode, Client $client) + private function assertStatusCode($expectedStatusCode, KernelBrowser $client) { $this->assertEquals($expectedStatusCode, $client->getResponse()->getStatusCode()); } - private function getContainer() : ContainerInterface + private function createAuthorizedProfileClient(): KernelBrowser { - self::bootKernel(); - return self::$kernel->getContainer(); + $client = static::createClient(); + $client->setServerParameters([ + 'PHP_AUTH_USER' => self::getContainer()->getParameter('api.users.profile.username'), + 'PHP_AUTH_PW' => self::getContainer()->getParameter('api.users.profile.password'), + ]); + return $client; } - private function disableConsentApiFeatureFor(Client $client) + private function createAuthorizedDeprovisionClient(): KernelBrowser { - $featureToggles = new FeatureConfiguration([ - 'api.consent_listing' => new Feature('api.consent_listing', false), - 'eb.feature_enable_consent' => new Feature('eb.feature_enable_consent', false), + $client = static::createClient(); + $client->setServerParameters([ + 'PHP_AUTH_USER' => self::getContainer()->getParameter('api.users.deprovision.username'), + 'PHP_AUTH_PW' => self::getContainer()->getParameter('api.users.deprovision.password'), ]); - $container = $client->getContainer(); - $container->set('engineblock.features', $featureToggles); + return $client; } - private function disableEngineConsentFeatureFor(Client $client) + private function disableConsentApiFeatureFor(KernelBrowser $client) { - $featureToggles = new FeatureConfiguration([ - 'eb.feature_enable_consent' => new Feature('eb.feature_enable_consent', false) + $mock = new FeatureConfiguration([ + 'api.consent_listing' => false, + 'eb.feature_enable_consent' => false, ]); - $container = $client->getContainer(); - $container->set('engineblock.features', $featureToggles); + //$client->disableReboot(); + $client->getContainer()->set(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class, $mock); } - /** - * @test - * @group Api - * @group Consent - * @group FeatureToggle - */ + private function disableEngineConsentFeatureFor(KernelBrowser $client) + { + $mock = new FeatureConfiguration([ + 'eb.feature_enable_consent' => false + ]); + //$client->disableReboot(); + $client->getContainer()->set(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class, $mock); + + } + + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('FeatureToggle')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_consent_post_api_if_the_engineblock_consent_feature_has_been_disabled() { $collabPersonId = 'urn:collab:person:test'; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.deprovision.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.deprovision.password'), - ]); + $client = $this->createAuthorizedDeprovisionClient(); $this->disableEngineConsentFeatureFor($client); @@ -543,21 +500,16 @@ public function cannot_access_the_consent_post_api_if_the_engineblock_consent_fe $this->assertResponseIsJson($client); } - /** - * @test - * @group Api - * @group Consent - * @group Profile - * @group FeatureToggle - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Group('Profile')] + #[\PHPUnit\Framework\Attributes\Group('FeatureToggle')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_consent_get_api_if_the_engineblock_consent_feature_has_been_disabled() { $userId = 'my-name-id'; - $client = $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.profile.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.profile.password'), - ]); + $client = $this->createAuthorizedProfileClient(); $this->disableEngineConsentFeatureFor($client); @@ -570,7 +522,8 @@ public function cannot_access_the_consent_get_api_if_the_engineblock_consent_fea private function addConsentFixture($userId, $serviceId, $attributeHash, $consentType, $consentDate, $deletedAt) { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->insert('consent') ->values([ @@ -582,56 +535,57 @@ private function addConsentFixture($userId, $serviceId, $attributeHash, $consent 'deleted_at' => ':deleted_at', ]) ->setParameters([ - ':user_id' => sha1($userId), - ':service_id' => $serviceId, - ':attribute' => $attributeHash, - ':consent_type' => $consentType, - ':consent_date' => $consentDate, - ':deleted_at' => $deletedAt, + 'user_id' => sha1($userId), + 'service_id' => $serviceId, + 'attribute' => $attributeHash, + 'consent_type' => $consentType, + 'consent_date' => $consentDate, + 'deleted_at' => $deletedAt, ]) - ->execute(); + ->executeStatement(); } private function findConsentByUserIdAndSPEntityId(string $collabPersonId, string $spEntityId): array { - /** @var \Doctrine\DBAL\Query\QueryBuilder $queryBuilder */ - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->select('*') ->from('consent') ->where('hashed_user_id = :userId') ->andWhere('service_id = :serviceId') ->setParameters([ - ':userId' => sha1($collabPersonId), - ':serviceId' => $spEntityId + 'userId' => sha1($collabPersonId), + 'serviceId' => $spEntityId ]); - /** @var PDOStatement $statement */ - $statement = $queryBuilder->execute(); - return (array) $statement->fetchAll(); + $result = $queryBuilder->executeQuery(); + return $result->fetchAllAssociative(); } private function addServiceProviderFixture(ServiceProvider $serviceProvider) { - $em = $this->getContainer()->get('doctrine')->getEntityManager(); + $em = self::getContainer()->get('doctrine')->getManager(); $em->persist($serviceProvider); $em->flush(); } private function clearMetadataFixtures() { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->delete('sso_provider_roles_eb5') - ->execute(); + ->executeStatement(); } private function clearConsentFixtures() { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->delete('consent') - ->execute(); + ->executeStatement(); } private function countConsentRemovals(array $dbResults): array @@ -651,7 +605,7 @@ private function countConsentRemovals(array $dbResults): array ]; } - private function assertResponseIsJson(Client $client) + private function assertResponseIsJson(KernelBrowser $client) { $isContentTypeJson = $client->getResponse()->headers->contains('Content-Type', 'application/json'); $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); diff --git a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionControllerTest.php b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionControllerTest.php index 50d9122701..61a1646a3f 100644 --- a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionControllerTest.php +++ b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/DeprovisionControllerTest.php @@ -19,61 +19,92 @@ namespace OpenConext\EngineBlockBundle\Tests; use DateTime; -use OpenConext\EngineBlockBundle\Configuration\Feature; +use Doctrine\DBAL\Query\QueryBuilder; use OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration; -use Symfony\Bundle\FrameworkBundle\Client; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; use function json_decode; use function trim; final class DeprovisionControllerTest extends WebTestCase { - public function setUp(): void + public function tearDown(): void { $this->clearFixtures(); + parent::tearDown(); } - /** - * @test - * @group Api - * @group Deprovision - */ - public function authentication_is_required_for_accessing_the_deprovision_api() + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] + public function authentication_is_required_for_accessing_the_deprovision_api_get() { $collabPersonId = 'urn:collab:person:test'; + $unauthenticatedClient = static::createClient(); + $unauthenticatedClient->request( + 'GET', + 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId + ); + $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + } + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] + public function authentication_is_required_for_accessing_the_deprovision_api_delete() + { + $collabPersonId = 'urn:collab:person:test'; $unauthenticatedClient = static::createClient(); - $unauthenticatedClient->request('GET', 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId); - $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + $unauthenticatedClient->request( + 'DELETE', + 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId + ); + $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + } + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] + public function authentication_is_required_for_accessing_the_deprovision_api_delete_dry_run() + { + $collabPersonId = 'urn:collab:person:test'; $unauthenticatedClient = static::createClient(); - $unauthenticatedClient->request('DELETE', 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId); - $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + $unauthenticatedClient->request( + 'DELETE', + 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId . '/dry-run' + ); + $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + } + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] + public function authentication_is_required_for_accessing_the_deprovision_api_delete_remove_consent() + { $unauthenticatedClient = static::createClient(); - $unauthenticatedClient->request('DELETE', 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId . '/dry-run'); + $unauthenticatedClient->request('POST', 'https://engine-api.dev.openconext.local/remove-consent'); $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + } + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] + public function delete_is_not_available_for_accessing_the_deprovision_api_delete_remove_consent() + { $unauthenticatedClient = static::createClient(); $unauthenticatedClient->request('DELETE', 'https://engine-api.dev.openconext.local/remove-consent'); - $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + $this->assertStatusCode(Response::HTTP_METHOD_NOT_ALLOWED, $unauthenticatedClient); } - /** - * @test - * @group Api - * @group Deprovision - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function only_get_or_delete_requests_are_allowed_when_accessing_the_deprovision_api() { $collabPersonId = 'urn:collab:person:test'; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.deprovision.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.deprovision.password'), - ]); + $client = $this->createAuthorizedClient(); $client->request('PUT', 'https://engine-api.dev.openconext.local/deprovision/' . $collabPersonId); $this->assertStatusCode(Response::HTTP_METHOD_NOT_ALLOWED, $client); @@ -87,20 +118,15 @@ public function only_get_or_delete_requests_are_allowed_when_accessing_the_depro $this->assertResponseIsJson($client); } - /** - * @test - * @group Api - * @group Deprovision - * @group FeatureToggle - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Group('FeatureToggle')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_deprovision_api_if_the_feature_has_been_disabled() { $collabPersonId = 'urn:collab:person:test'; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.deprovision.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.deprovision.password'), - ]); + $client = $this->createAuthorizedClient(); $this->disableDeprovisionApiFeatureFor($client); @@ -110,11 +136,9 @@ public function cannot_access_the_deprovision_api_if_the_feature_has_been_disabl $this->assertResponseIsJson($client); } - /** - * @test - * @group Api - * @group Deprovision - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_access_the_deprovision_api_if_user_does_not_have_deprovision_role() { $collabPersonId = 'urn:collab:person:test'; @@ -130,19 +154,13 @@ public function cannot_access_the_deprovision_api_if_user_does_not_have_deprovis $this->assertResponseIsJson($client); } - /** - * @test - * @group Api - * @group Deprovision - * - * @dataProvider provideDeprovisionEndPoints - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideDeprovisionEndPoints')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function no_user_data_is_returned_if_collab_person_id_is_unknown($method, $path) { - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.deprovision.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.deprovision.password'), - ]); + $client = $this->createAuthorizedClient(); $client->request($method, 'https://engine-api.dev.openconext.local/' . trim($path, '/')); @@ -175,12 +193,12 @@ public function no_user_data_is_returned_if_collab_person_id_is_unknown($method, * * - DELETE /deprovision/{collab_person_id} * - * @test - * @group Api - * @group Deprovision * - * @dataProvider provideDeprovisionEndPoints */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideDeprovisionEndPoints')] + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function all_user_data_for_collab_person_id_is_retrieved_and_deleted($method, $path) { $userId = 'urn:collab:person:test'; @@ -195,10 +213,7 @@ public function all_user_data_for_collab_person_id_is_retrieved_and_deleted($met $consentType = 'explicit'; $consentDate = '2017-04-18 13:37:00'; - $client = static::createClient([], [ - 'PHP_AUTH_USER' => $this->getContainer()->getParameter('api.users.deprovision.username'), - 'PHP_AUTH_PW' => $this->getContainer()->getParameter('api.users.deprovision.password'), - ]); + $client = $this->createAuthorizedClient(); $this->addServiceProviderUuidFixture($spUuid1, $spEntityId1); $this->addServiceProviderUuidFixture($spUuid2, $spEntityId2); @@ -287,7 +302,7 @@ public function all_user_data_for_collab_person_id_is_retrieved_and_deleted($met /** * @return array */ - public function provideDeprovisionEndpoints() + public static function provideDeprovisionEndpoints() { return [ ['GET', '/deprovision/urn:collab:person:test'], @@ -296,26 +311,17 @@ public function provideDeprovisionEndpoints() ]; } - private function assertStatusCode($expectedStatusCode, Client $client) + private function assertStatusCode($expectedStatusCode, KernelBrowser $client) { $this->assertEquals($expectedStatusCode, $client->getResponse()->getStatusCode()); } - private function getContainer() : ContainerInterface - { - self::bootKernel(); - return self::$kernel->getContainer(); - } - - /** - * @param Client $client - */ - private function disableDeprovisionApiFeatureFor(Client $client) + private function disableDeprovisionApiFeatureFor(KernelBrowser $client) { - $featureToggles = new FeatureConfiguration([ - 'api.deprovision' => new Feature('api.deprovision', false) + $mock = new FeatureConfiguration([ + 'api.deprovision' => false ]); - $client->getContainer()->set('engineblock.features', $featureToggles); + $client->getContainer()->set(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class, $mock); } /** @@ -324,7 +330,8 @@ private function disableDeprovisionApiFeatureFor(Client $client) */ private function addUserFixture($userId, $uuid) { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->insert('user') ->values([ @@ -332,10 +339,10 @@ private function addUserFixture($userId, $uuid) 'uuid' => ':uuid', ]) ->setParameters([ - ':collab_person_id' => $userId, - ':uuid' => $uuid, + 'collab_person_id' => $userId, + 'uuid' => $uuid, ]) - ->execute(); + ->executeStatement(); } /** @@ -344,7 +351,8 @@ private function addUserFixture($userId, $uuid) */ private function addServiceProviderUuidFixture($spUuid, $spEntityId) { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->insert('service_provider_uuid') ->values([ @@ -352,10 +360,10 @@ private function addServiceProviderUuidFixture($spUuid, $spEntityId) 'service_provider_entity_id' => ':service_provider_entity_id', ]) ->setParameters([ - ':uuid' => $spUuid, - ':service_provider_entity_id' => $spEntityId, + 'uuid' => $spUuid, + 'service_provider_entity_id' => $spEntityId, ]) - ->execute(); + ->executeStatement(); } /** @@ -365,7 +373,8 @@ private function addServiceProviderUuidFixture($spUuid, $spEntityId) */ private function addSamlPersistentIdFixture($userUuid, $spUuid, $persistentId) { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->insert('saml_persistent_id') ->values([ @@ -374,11 +383,11 @@ private function addSamlPersistentIdFixture($userUuid, $spUuid, $persistentId) 'persistent_id' => ':persistent_id', ]) ->setParameters([ - ':user_uuid' => $userUuid, - ':service_provider_uuid' => $spUuid, - ':persistent_id' => $persistentId, + 'user_uuid' => $userUuid, + 'service_provider_uuid' => $spUuid, + 'persistent_id' => $persistentId, ]) - ->execute(); + ->executeStatement(); } /** @@ -390,7 +399,8 @@ private function addSamlPersistentIdFixture($userUuid, $spUuid, $persistentId) */ private function addConsentFixture($userId, $serviceId, $attributeHash, $consentType, $consentDate) { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->insert('consent') ->values([ @@ -402,35 +412,48 @@ private function addConsentFixture($userId, $serviceId, $attributeHash, $consent 'deleted_at' => '"0000-00-00 00:00:00"', ]) ->setParameters([ - ':user_id' => sha1($userId), - ':service_id' => $serviceId, - ':attribute' => $attributeHash, - ':consent_type' => $consentType, - ':consent_date' => $consentDate, + 'user_id' => sha1($userId), + 'service_id' => $serviceId, + 'attribute' => $attributeHash, + 'consent_type' => $consentType, + 'consent_date' => $consentDate, ]) - ->execute(); + ->executeStatement(); } private function clearFixtures() { - $queryBuilder = $this->getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); $queryBuilder ->delete('service_provider_uuid') - ->execute(); + ->executeStatement(); $queryBuilder ->delete('user') - ->execute(); + ->executeStatement(); $queryBuilder ->delete('saml_persistent_id') - ->execute(); + ->executeStatement(); $queryBuilder ->delete('consent') - ->execute(); + ->executeStatement(); } - private function assertResponseIsJson(Client $client) + private function assertResponseIsJson(KernelBrowser $client) { $isContentTypeJson = $client->getResponse()->headers->contains('Content-Type', 'application/json'); $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); } + + private function createAuthorizedClient(): KernelBrowser + { + $client = static::createClient(); + $client->setServerParameters( + [ + 'PHP_AUTH_USER' => self::getContainer()->getParameter('api.users.deprovision.username'), + 'PHP_AUTH_PW' => self::getContainer()->getParameter('api.users.deprovision.password'), + ] + ); + return $client; + } } diff --git a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatControllerTest.php b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatControllerTest.php index 9ec9ee3be6..5e650a5f30 100644 --- a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatControllerTest.php +++ b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/HeartbeatControllerTest.php @@ -19,23 +19,22 @@ namespace OpenConext\EngineBlockBundle\Tests; use Symfony\Bundle\FrameworkBundle\Client; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\HttpFoundation\Response; final class HeartbeatControllerTest extends WebTestCase { - /** - * @test - * @group Api - */ + #[\PHPUnit\Framework\Attributes\Group('Api')] + #[\PHPUnit\Framework\Attributes\Test] public function engineblock_has_a_heartbeat() { - $client = $this->createClient(); + $client = self::createClient(); $client->request('GET', 'https://engine-api.dev.openconext.local/'); $this->assertStatusCode(Response::HTTP_OK, $client); } - private function assertStatusCode($expectedStatusCode, Client $client) + private function assertStatusCode($expectedStatusCode, KernelBrowser $client) { $this->assertEquals($expectedStatusCode, $client->getResponse()->getStatusCode()); } diff --git a/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/MetadataControllerTest.php b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/MetadataControllerTest.php new file mode 100644 index 0000000000..e363039a0c --- /dev/null +++ b/tests/functional/OpenConext/EngineBlockBundle/Controller/Api/MetadataControllerTest.php @@ -0,0 +1,122 @@ +clearMetadataFixtures(); + parent::tearDown(); + } + + #[\PHPUnit\Framework\Attributes\Test] + public function authentication_is_required_for_accessing_the_metadata_api() + { + $unauthenticatedClient = static::createClient(); + $unauthenticatedClient->request('GET', 'https://engine-api.dev.openconext.local/metadata/idp?entity-id=urn:test'); + $this->assertStatusCode(Response::HTTP_UNAUTHORIZED, $unauthenticatedClient); + } + + #[\PHPUnit\Framework\Attributes\Test] + public function cannot_access_if_user_does_not_have_profile_role() + { + $client = static::createClient([], [ + 'PHP_AUTH_USER' => 'no_roles', + 'PHP_AUTH_PW' => 'no_roles', + ]); + + $client->request('GET', 'https://engine-api.dev.openconext.local/metadata/idp?entity-id=urn:test'); + $this->assertStatusCode(Response::HTTP_FORBIDDEN, $client); + $isContentTypeJson = $client->getResponse()->headers->contains('Content-Type', 'application/json'); + $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); + } + + #[\PHPUnit\Framework\Attributes\Test] + public function cannot_access_if_feature_disabled() + { + $client = $this->createAuthorizedProfileClient(); + + $mock = new FeatureConfiguration([ + 'api.metadata_api' => false, + ]); + $client->getContainer()->set(\OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration::class, $mock); + + $client->request('GET', 'https://engine-api.dev.openconext.local/metadata/idp?entity-id=urn:test'); + $this->assertStatusCode(Response::HTTP_NOT_FOUND, $client); + } + + #[\PHPUnit\Framework\Attributes\Test] + public function returns_not_found_when_idp_missing() + { + $client = $this->createAuthorizedProfileClient(); + + $client->request('GET', 'https://engine-api.dev.openconext.local/metadata/idp?entity-id=https://does-not-exist.example'); + $this->assertStatusCode(Response::HTTP_NOT_FOUND, $client); + } + + #[\PHPUnit\Framework\Attributes\Test] + public function only_get_requests_are_allowed() + { + $client = $this->createAuthorizedProfileClient(); + $client->request('POST', 'https://engine-api.dev.openconext.local/metadata/idp?entity-id=urn:test'); + $this->assertStatusCode(Response::HTTP_METHOD_NOT_ALLOWED, $client); + + $isContentTypeJson = $client->getResponse()->headers->contains('Content-Type', 'application/json'); + $this->assertTrue($isContentTypeJson, 'Response should have Content-Type: application/json header'); + } + + private function assertStatusCode($expectedStatusCode, KernelBrowser $client) + { + $this->assertEquals($expectedStatusCode, $client->getResponse()->getStatusCode()); + } + + private function createAuthorizedProfileClient(): KernelBrowser + { + $client = static::createClient(); + $client->setServerParameters([ + 'PHP_AUTH_USER' => self::getContainer()->getParameter('api.users.profile.username'), + 'PHP_AUTH_PW' => self::getContainer()->getParameter('api.users.profile.password'), + ]); + return $client; + } + + private function addServiceProviderFixture(ServiceProvider $serviceProvider) + { + $em = self::getContainer()->get('doctrine')->getManager(); + $em->persist($serviceProvider); + $em->flush(); + } + + private function clearMetadataFixtures() + { + $queryBuilder = self::getContainer()->get('doctrine')->getConnection()->createQueryBuilder(); + assert($queryBuilder instanceof QueryBuilder); + $queryBuilder + ->delete('sso_provider_roles_eb5') + ->executeStatement(); + } +} diff --git a/tests/integration/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssemblerTest.php b/tests/integration/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssemblerTest.php index 1a0e09df67..8f31896bec 100644 --- a/tests/integration/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssemblerTest.php +++ b/tests/integration/OpenConext/EngineBlock/Metadata/Entity/Assembler/PushMetadataAssemblerTest.php @@ -61,9 +61,7 @@ public function test_it_rejects_empty_push() $this->assembler->assemble($input); } - /** - * @dataProvider invalidAcsLocations - */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidAcsLocations')] public function test_it_rejects_invalid_acs_location_schemes($acsLocation) { $this->expectException(\RuntimeException::class); @@ -127,7 +125,6 @@ public function test_it_rejects_invalid_acs_location_schemes($acsLocation) } /** - * @dataProvider validCoins * * @param string $coinName The name of the coin and used to set the coin in the meta push data * @param string $roleType The type of the role and used to set the coin in the meta push data @@ -135,6 +132,7 @@ public function test_it_rejects_invalid_acs_location_schemes($acsLocation) * @param string $type The type of coin data to run possible assertions against see the validCoinValues* helper * methods below which are used to assert the data after it went through the assembler. */ + #[\PHPUnit\Framework\Attributes\DataProvider('validCoins')] public function testCoins($coinName, $roleType, $parameter, $type) { $connection = '{ "2d96e27a-76cf-4ca2-ac70-ece5d4c49523": { @@ -364,7 +362,7 @@ public function test_it_assembles_mfa_entity_settings_with_transparent_option() $this->assertInstanceOf(TransparentMfaEntity::class, $transparent); } - public function invalidAcsLocations() + public static function invalidAcsLocations() { return [ 'invalid-scheme' => ['javascript:alert("hello world");'], @@ -372,7 +370,7 @@ public function invalidAcsLocations() ]; } - public function validCoins() + public static function validCoins() { return [ // SP diff --git a/tests/integration/OpenConext/EngineBlock/Metadata/MduiTest.php b/tests/integration/OpenConext/EngineBlock/Metadata/MduiTest.php index e76eb90d8f..96f9a2ff68 100644 --- a/tests/integration/OpenConext/EngineBlock/Metadata/MduiTest.php +++ b/tests/integration/OpenConext/EngineBlock/Metadata/MduiTest.php @@ -94,9 +94,7 @@ public function test_create_mdui_from_json() ); } - /** - * @dataProvider invalidJsonProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidJsonProvider')] public function test_creates_empty_mdui_from_json_invalid_json($invalidJson) { $mdui = Mdui::fromJson($invalidJson); @@ -104,7 +102,7 @@ public function test_creates_empty_mdui_from_json_invalid_json($invalidJson) $this->assertNull($mdui->getDisplayNameOrNull('en')); } - public function invalidJsonProvider() + public static function invalidJsonProvider() { return [ 'single quotes' => ['{"DisplayName":{\'name\':\'DisplayName\',"values":{"en":{"value":"bogus en value","language":"en"},"nl":{"value":"bogus nl value","language":"nl"}}},"Description":{"name":"Description","values":{"en":{"value":"bogus en value","language":"en"},"nl":{"value":"bogus nl value","language":"nl"}}},"Keywords":{"name":"Keywords","values":{"en":{"value":"bogus en value","language":"en"},"nl":{"value":"bogus nl value","language":"nl"}}},"Logo":{"name":"Logo","url":"https:\/\/link-to-my.logo.example.org\/img\/logo.png","width":null,"height":null},"PrivacyStatementURL":{"name":"PrivacyStatementURL","values":{"en":{"value":"bogus en value","language":"en"},"nl":{"value":"bogus nl value","language":"nl"}}}}'], diff --git a/tests/integration/OpenConext/EngineBlockBundle/ExecutionTimeTrackerTest.php b/tests/integration/OpenConext/EngineBlockBundle/ExecutionTimeTrackerTest.php index ea2b467c47..7300656a8a 100644 --- a/tests/integration/OpenConext/EngineBlockBundle/ExecutionTimeTrackerTest.php +++ b/tests/integration/OpenConext/EngineBlockBundle/ExecutionTimeTrackerTest.php @@ -24,9 +24,6 @@ use Symfony\Bridge\PhpUnit\ClockMock; use Symfony\Component\Stopwatch\Stopwatch; -// in order to be in control of time during our tests with the Stopwatch, we use the Symfony's ClockMock -require_once ENGINEBLOCK_FOLDER_VENDOR . '/symfony/symfony/src/Symfony/Bridge/PhpUnit/ClockMock.php'; - class ExecutionTimeTrackerTest extends TestCase { public static function setUpBeforeClass(): void @@ -40,10 +37,8 @@ public function setUp(): void ClockMock::withClockMock(0); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_tracker_is_tracking_when_it_has_been_started() { $executionTimeTracker = new ExecutionTimeTracker(new Stopwatch); @@ -54,10 +49,8 @@ public function execution_time_tracker_is_tracking_when_it_has_been_started() $this->assertTrue($isTracking); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_tracker_is_not_tracking_when_it_has_not_been_started() { $executionTimeTracker = new ExecutionTimeTracker(new Stopwatch); @@ -67,10 +60,8 @@ public function execution_time_tracker_is_not_tracking_when_it_has_not_been_star $this->assertFalse($isTracking); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function exceeding_of_execution_time_is_determined_correctly() { $executionTimeInMilliseconds = 10; @@ -110,10 +101,8 @@ public function exceeding_of_execution_time_is_determined_correctly() ); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function how_much_time_remains_until_a_given_time_that_is_longer_than_the_current_execution_time_is_reached_is_calculated_correctly() { $longerTimeInMilliseconds = 1000; @@ -127,10 +116,8 @@ public function how_much_time_remains_until_a_given_time_that_is_longer_than_the $this->assertEquals($longerTimeInMilliseconds, $timeRemaining->getExecutionTime()); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function there_is_no_time_remaining_until_a_given_time_that_is_the_same_as_the_current_execution_time() { $sameTimeInMilliseconds = 10; @@ -146,10 +133,8 @@ public function there_is_no_time_remaining_until_a_given_time_that_is_the_same_a $this->assertEquals(ExecutionTime::of(0), $timeRemaining); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function there_is_no_time_remaining_until_a_given_time_that_is_shorter_than_the_current_execution_time() { $currentExecutionTimeInMilliseconds = 10; diff --git a/tests/integration/OpenConext/EngineBlockBundle/Localization/LanguageSupportProviderTest.php b/tests/integration/OpenConext/EngineBlockBundle/Localization/LanguageSupportProviderTest.php index 02583b8432..36051656e6 100644 --- a/tests/integration/OpenConext/EngineBlockBundle/Localization/LanguageSupportProviderTest.php +++ b/tests/integration/OpenConext/EngineBlockBundle/Localization/LanguageSupportProviderTest.php @@ -23,9 +23,7 @@ class LanguageSupportProviderTest extends TestCase { - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function only_enabled_languages_should_be_supported() { $LanguageSupportProvider = new LanguageSupportProvider(['nl', 'en', 'pt'], ['nl', 'en']); @@ -33,9 +31,7 @@ public function only_enabled_languages_should_be_supported() $this->assertSame(['nl', 'en'], $LanguageSupportProvider->getSupportedLanguages()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function duplicate_language_entries_should_not_result_in_duplicate_entries_with_supported_languages() { $LanguageSupportProvider = new LanguageSupportProvider(['nl', 'en', 'pt', 'nl'], ['nl', 'en', 'nl']); @@ -43,9 +39,7 @@ public function duplicate_language_entries_should_not_result_in_duplicate_entrie $this->assertSame(['nl', 'en'], $LanguageSupportProvider->getSupportedLanguages()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function an_unsupported_language_should_throw_an_exception() { $this->expectException(UnsupportedLanguageException::class); @@ -54,9 +48,7 @@ public function an_unsupported_language_should_throw_an_exception() $LanguageSupportProvider = new LanguageSupportProvider(['nl', 'en', 'pt'], ['de']); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function no_setting_enabled_languages_should_result_in_an_exception() { $this->expectException(UnsupportedLanguageException::class); @@ -65,9 +57,7 @@ public function no_setting_enabled_languages_should_result_in_an_exception() $LanguageSupportProvider = new LanguageSupportProvider(['nl', 'en', 'pt'], []); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function no_active_languages_should_result_in_an__excpetion() { $this->expectException(UnsupportedLanguageException::class); diff --git a/tests/integration/OpenConext/EngineBlockBundle/Localization/LocaleProviderTest.php b/tests/integration/OpenConext/EngineBlockBundle/Localization/LocaleProviderTest.php index c63f5e0d5a..764d6f78f3 100644 --- a/tests/integration/OpenConext/EngineBlockBundle/Localization/LocaleProviderTest.php +++ b/tests/integration/OpenConext/EngineBlockBundle/Localization/LocaleProviderTest.php @@ -40,9 +40,7 @@ protected function setUp(): void } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_default_locale_should_be_returned_if_the_request_is_not_set() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -53,9 +51,7 @@ public function the_default_locale_should_be_returned_if_the_request_is_not_set( $this->assertSame('en', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function if_the_lang_query_string_is_set_it_should_be_used_to_determine_the_locale() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -70,9 +66,7 @@ public function if_the_lang_query_string_is_set_it_should_be_used_to_determine_t $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_lang_query_string_has_priority_over_the_request_body_cookie_and_accept_language_Header() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -94,9 +88,7 @@ public function the_lang_query_string_has_priority_over_the_request_body_cookie_ $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_query_string_locale_should_be_ignored_if_it_is_not_available() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -111,9 +103,7 @@ public function the_query_string_locale_should_be_ignored_if_it_is_not_available $this->assertSame('en', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function if_the_lang_query_string_is_not_set_the_locale_in_the_request_body_should_be_used() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -128,9 +118,7 @@ public function if_the_lang_query_string_is_not_set_the_locale_in_the_request_bo $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_request_body_has_priority_over_the_cookie_and_accept_language_Header() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -152,9 +140,7 @@ public function the_request_body_has_priority_over_the_cookie_and_accept_languag $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_request_body_locale_should_be_ignored_if_it_is_not_available() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -169,9 +155,7 @@ public function the_request_body_locale_should_be_ignored_if_it_is_not_available $this->assertSame('en', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_locale_stored_in_the_cookie_should_be_used_if_the_query_string_and_request_body_do_not_contain_a_locale() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -186,9 +170,7 @@ public function the_locale_stored_in_the_cookie_should_be_used_if_the_query_stri $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_cookie_has_priority_over_the_accept_language_header() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -203,9 +185,7 @@ public function the_cookie_has_priority_over_the_accept_language_header() $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_locale_stored_in_the_cookie_should_be_ignored_if_it_is_not_one_of_the_available_locales() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -220,9 +200,7 @@ public function the_locale_stored_in_the_cookie_should_be_ignored_if_it_is_not_o $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_accept_language_header_should_be_used_if_the_cookie_is_not_set() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -237,9 +215,7 @@ public function the_accept_language_header_should_be_used_if_the_cookie_is_not_s $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function accepted_languages_that_are_not_available_should_be_ignored() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -254,9 +230,7 @@ public function accepted_languages_that_are_not_available_should_be_ignored() $this->assertSame('nl', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_default_language_should_be_used_if_none_of_the_accepted_languages_are_available() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') @@ -271,9 +245,7 @@ public function the_default_language_should_be_used_if_none_of_the_accepted_lang $this->assertSame('en', $localeProvider->getLocale()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function the_default_language_should_be_used_if_neither_the_cookie_nor_the_accept_language_header_is_set() { $this->languageSupportProvider->shouldReceive('getSupportedLanguages') diff --git a/tests/library/EngineBlock/Test/Arp/AttributeReleasePolicyEnforcerTest.php b/tests/library/EngineBlock/Test/Arp/AttributeReleasePolicyEnforcerTest.php index 22c0ca7515..2a0a238222 100644 --- a/tests/library/EngineBlock/Test/Arp/AttributeReleasePolicyEnforcerTest.php +++ b/tests/library/EngineBlock/Test/Arp/AttributeReleasePolicyEnforcerTest.php @@ -18,8 +18,9 @@ use OpenConext\EngineBlock\Metadata\AttributeReleasePolicy; use PHPUnit\Framework\TestCase; +use Psr\Log\NullLogger; -class EngineBlock_Test_Arp_AttributeReleasePolicyEnforcer extends TestCase +class EngineBlock_Test_Arp_AttributeReleasePolicyEnforcerTest extends TestCase { /** * @var EngineBlock_Arp_AttributeReleasePolicyEnforcer @@ -29,6 +30,7 @@ class EngineBlock_Test_Arp_AttributeReleasePolicyEnforcer extends TestCase public function setUp(): void { $this->_arpEnforcer = new EngineBlock_Arp_AttributeReleasePolicyEnforcer(); + EngineBlock_ApplicationSingleton::getInstance()->setLogInstance(new NullLogger()); } public function testEnforceNullArp() @@ -120,8 +122,8 @@ protected function _doEnforceArp($arp, $responseAttributes = array()) { $responseAttributes = empty($responseAttributes) ? $this->_responseAttributes() : $responseAttributes; return $this->_arpEnforcer->enforceArp( - $arp === null ? null : new AttributeReleasePolicy($arp), - $responseAttributes + $responseAttributes, + $arp === null ? null : new AttributeReleasePolicy($arp) ); } diff --git a/tests/library/EngineBlock/Test/Attributes/Validator/TypeTest.php b/tests/library/EngineBlock/Test/Attributes/Validator/TypeTest.php index 10ce4b67d4..20fe9011d4 100644 --- a/tests/library/EngineBlock/Test/Attributes/Validator/TypeTest.php +++ b/tests/library/EngineBlock/Test/Attributes/Validator/TypeTest.php @@ -21,19 +21,19 @@ class EngineBlock_Test_TypeTest extends TestCase { /** - * @dataProvider validAttributesProvider * * @param $attributeName * @param $options * @param $attributes */ + #[\PHPUnit\Framework\Attributes\DataProvider('validAttributesProvider')] public function testAttributeValidates($attributeName, $options, $attributes) { $validator = new EngineBlock_Attributes_Validator_Type($attributeName, $options); $this->assertTrue($validator->validate($attributes)); } - public function validAttributesProvider() + public static function validAttributesProvider() { return array( array( diff --git a/tests/library/EngineBlock/Test/Corto/Filter/Command/AttributeAggregatorTest.php b/tests/library/EngineBlock/Test/Corto/Filter/Command/AttributeAggregatorTest.php index dfbdc97bc1..5412b4909f 100644 --- a/tests/library/EngineBlock/Test/Corto/Filter/Command/AttributeAggregatorTest.php +++ b/tests/library/EngineBlock/Test/Corto/Filter/Command/AttributeAggregatorTest.php @@ -26,14 +26,13 @@ use OpenConext\EngineBlockBundle\AttributeAggregation\AttributeAggregationClientInterface; use OpenConext\EngineBlockBundle\AttributeAggregation\Dto\Response; use OpenConext\EngineBlock\Http\Exception\HttpException; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; use SAML2\Assertion; use SAML2\AuthnRequest; use SAML2\Response as SAMLResponse; -/** - * @group AttributeAggregation - */ +#[\PHPUnit\Framework\Attributes\Group('AttributeAggregation')] class EngineBlock_Test_Corto_Filter_Command_AttributeAggregatorTest extends TestCase { use MockeryPHPUnitIntegration; @@ -145,6 +144,7 @@ public function testAggregatorNotCalledWhenNoAttributesConfigured() $this->assertTrue($aggregationNotConfiguredLogged, 'Logging that no attributes are configured in ARP for aggregation'); } + #[DoesNotPerformAssertions] public function testAggregatorIsCalledWhenArpCorrectlyConfigured() { $client = Mockery::mock(AttributeAggregationClientInterface::class); @@ -306,6 +306,7 @@ public function testAggregatorStripsIdpAttributesIfAggregatorHasNoResults() $this->assertEquals([], $command->getResponseAttributes()); } + #[DoesNotPerformAssertions] public function testAggregatorCalledWhenThereAreNonIdpSources() { $client = Mockery::mock(AttributeAggregationClientInterface::class); diff --git a/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateAllowedConnectionTest.php b/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateAllowedConnectionTest.php index 41e579f842..fa21557415 100644 --- a/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateAllowedConnectionTest.php +++ b/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateAllowedConnectionTest.php @@ -22,6 +22,7 @@ use Monolog\Logger; use OpenConext\EngineBlock\Metadata\Entity\IdentityProvider; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; use SAML2\Assertion; use SAML2\Response; @@ -72,6 +73,7 @@ public function testItShouldRunInNormalConditions() $verifier->execute(); } + #[DoesNotPerformAssertions] public function testItShouldRunInNormalConditionsWithTrustedProxy() { $verifier = new EngineBlock_Corto_Filter_Command_ValidateAllowedConnection(); diff --git a/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateMfaAuthnContextClassRefTest.php b/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateMfaAuthnContextClassRefTest.php index 7329eb1619..84840f42ad 100644 --- a/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateMfaAuthnContextClassRefTest.php +++ b/tests/library/EngineBlock/Test/Corto/Filter/Command/ValidateMfaAuthnContextClassRefTest.php @@ -25,6 +25,7 @@ use OpenConext\EngineBlock\Metadata\Entity\IdentityProvider; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; use OpenConext\EngineBlock\Metadata\MfaEntityCollection; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; use SAML2\Assertion; use SAML2\AuthnRequest; @@ -49,6 +50,7 @@ class EngineBlock_Test_Corto_Filter_Command_ValidateMfaAuthnContextClassRefTest */ private $request; private $server; + private ServiceProvider $sp; public function setUp(): void { @@ -70,6 +72,7 @@ public function setUp(): void ; } + #[DoesNotPerformAssertions] public function testNoConfiguredMfaCombinationShouldPass() { $response = $this->createTestResponse('urn:oasis:names:tc:SAML:2.0:ac:classes:Password'); @@ -287,7 +290,6 @@ private function setCoin(AbstractRole $role, $key, $name) $object = new ReflectionClass($role); $property = $object->getProperty('coins'); - $property->setAccessible(true); $property->setValue($role, $coins); } } diff --git a/tests/library/EngineBlock/Test/Corto/Model/ConsentTest.php b/tests/library/EngineBlock/Test/Corto/Model/ConsentTest.php index f30a72dc94..47f34bf9ec 100644 --- a/tests/library/EngineBlock/Test/Corto/Model/ConsentTest.php +++ b/tests/library/EngineBlock/Test/Corto/Model/ConsentTest.php @@ -19,7 +19,7 @@ use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; use PHPUnit\Framework\TestCase; -class EngineBlock_Corto_Model_Consent_Test extends TestCase +class EngineBlock_Corto_Model_ConsentTest extends TestCase { private $consentDisabled; private $consent; diff --git a/tests/library/EngineBlock/Test/Corto/Module/Service/ProcessConsentTest.php b/tests/library/EngineBlock/Test/Corto/Module/Service/ProcessConsentTest.php index 0bb4976f83..a7e53b6da1 100644 --- a/tests/library/EngineBlock/Test/Corto/Module/Service/ProcessConsentTest.php +++ b/tests/library/EngineBlock/Test/Corto/Module/Service/ProcessConsentTest.php @@ -30,8 +30,10 @@ use SAML2\Response; use SAML2\XML\saml\Issuer; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Twig\Environment; class EngineBlock_Test_Corto_Module_Service_ProcessConsentTest extends TestCase { @@ -167,7 +169,7 @@ public function testResponseIsSent() { private function mockProxyServer() { // Mock twig, a dependency of proxy server - $twigMock = Phake::mock(Twig_Environment::class); + $twigMock = Phake::mock(Environment::class); // Mock proxy server $_SERVER['HTTP_HOST'] = 'test-host'; @@ -287,8 +289,12 @@ private function mockProcessingStateHelper() $this->sessionMock->setSessionData(['_sf2_attributes' => $sessionData]); - $session = new Session($this->sessionMock); - return new ProcessingStateHelper($session); + $request = new Request(); + $request->setSession(new Session($this->sessionMock)); + $stack = new RequestStack(); + $stack->push($request); + + return new ProcessingStateHelper($stack); } diff --git a/tests/library/EngineBlock/Test/Corto/Module/Service/ProvideConsentTest.php b/tests/library/EngineBlock/Test/Corto/Module/Service/ProvideConsentTest.php index 5696c48860..10e78a8d7e 100644 --- a/tests/library/EngineBlock/Test/Corto/Module/Service/ProvideConsentTest.php +++ b/tests/library/EngineBlock/Test/Corto/Module/Service/ProvideConsentTest.php @@ -36,8 +36,10 @@ use SAML2\XML\saml\Issuer; use SAML2\XML\saml\NameID; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Twig\Environment; class EngineBlock_Test_Corto_Module_Service_ProvideConsentTest extends TestCase { @@ -58,7 +60,7 @@ class EngineBlock_Test_Corto_Module_Service_ProvideConsentTest extends TestCase /** @var EngineBlock_Corto_ProxyServer */ private $proxyServerMock; - /** @var Twig_Environment */ + /** @var Environment */ private $twig; /** @var AuthenticationStateHelperInterface|Mock */ @@ -171,7 +173,7 @@ public function testConsentIsSkippedWhenDisabledPerSp() private function mockProxyServer() { // Mock twig, a dependency of proxy server - $twigMock = Phake::mock(Twig_Environment::class); + $twigMock = Phake::mock(Environment::class); // Mock proxy server /** @var EngineBlock_Corto_ProxyServer $proxyServerMock */ $proxyServerMock = Phake::partialMock('EngineBlock_Corto_ProxyServer', $twigMock); @@ -314,7 +316,7 @@ private function mockAuthStateHelper() private function mockTwig() { - $mock = Phake::mock(\Twig\Environment::class); + $mock = Phake::mock(Environment::class); Phake::when($mock) ->render(Phake::anyParameters()) ->thenReturn(''); @@ -367,8 +369,12 @@ private function mockProcessingStateHelper() $this->sessionMock->setSessionData(['_sf2_attributes' => $sessionData]); - $session = new Session($this->sessionMock); - return new ProcessingStateHelper($session); + $request = new Request(); + $request->setSession(new Session($this->sessionMock)); + $stack = new RequestStack(); + $stack->push($request); + + return new ProcessingStateHelper($stack); } private function mockHttpRequest() @@ -394,7 +400,6 @@ private function setCoin(ServiceProvider $sp, $key, $name) $object = new \ReflectionClass($sp); $property = $object->getProperty('coins'); - $property->setAccessible(true); $property->setValue($sp, $coins); } } diff --git a/tests/library/EngineBlock/Test/Corto/ProxyServerTest.php b/tests/library/EngineBlock/Test/Corto/ProxyServerTest.php index 49750aa489..f1a7add364 100644 --- a/tests/library/EngineBlock/Test/Corto/ProxyServerTest.php +++ b/tests/library/EngineBlock/Test/Corto/ProxyServerTest.php @@ -22,6 +22,7 @@ use PHPUnit\Framework\TestCase; use SAML2\AuthnRequest; use Surfnet\SamlBundle\Signing\KeyPair; +use Twig\Environment; /** * Note: this Test only tests setting of NameIDFormat, add other tests if required @@ -30,7 +31,7 @@ class EngineBlock_Test_Corto_ProxyServerTest extends TestCase { use MockeryPHPUnitIntegration; - public function testNameIDFormatIsNotSetByDefault() + public function testDefaultNameIDPolicy() { $proxyServer = $this->factoryProxyServer(); @@ -44,40 +45,7 @@ public function testNameIDFormatIsNotSetByDefault() ); $nameIdPolicy = $enhancedRequest->getNameIdPolicy(); - - $this->assertNotContains( - 'Format', - array_keys($nameIdPolicy), - 'The NameIDPolicy should not contain the key "Format"', - false, - true, - true - ); - } - - public function testAllowCreateIsSet() - { - $proxyServer = $this->factoryProxyServer(); - - $originalRequest = $this->factoryOriginalRequest(); - $identityProvider = $proxyServer->getRepository()->fetchIdentityProviderByEntityId('testIdp'); - /** @var AuthnRequest $enhancedRequest */ - $enhancedRequest = EngineBlock_Saml2_AuthnRequestFactory::createFromRequest( - $originalRequest, - $identityProvider, - $proxyServer - ); - - $nameIdPolicy = $enhancedRequest->getNameIdPolicy(); - - $this->assertContains( - 'AllowCreate', - array_keys($nameIdPolicy), - 'The NameIDPolicy should contain the key "AllowCreate"', - false, - true, - true - ); + $this->assertSame(['AllowCreate' => true], $nameIdPolicy); } public function testNameIDFormatIsSetFromRemoteMetaData() @@ -99,9 +67,7 @@ public function testNameIDFormatIsSetFromRemoteMetaData() $this->assertEquals($nameIdPolicy['Format'], 'fooFormat'); } - /** - * @dataProvider provideKeyExpectations - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideKeyExpectations')] public function testGetSigningCertificates(?string $keyOverride, bool $force, string $expectedResult) { $keys = [ @@ -128,7 +94,7 @@ private function buildKeyPair(string $key, string $cert): EngineBlock_X509_KeyPa ); } - public function provideKeyExpectations() + public static function provideKeyExpectations() { return [ 'force default signing key' => [null, true, 'default'], @@ -150,7 +116,7 @@ private function factoryOriginalRequest() private function factoryProxyServer() { - $twig = Mockery::mock(Twig_Environment::class); + $twig = Mockery::mock(Environment::class); $proxyServer = new EngineBlock_Corto_ProxyServer($twig); $proxyServer->setRepository(new InMemoryMetadataRepository( diff --git a/tests/library/EngineBlock/Test/Corto/XmlToArrayTest.php b/tests/library/EngineBlock/Test/Corto/XmlToArrayTest.php index 799faba121..1ed90d9293 100644 --- a/tests/library/EngineBlock/Test/Corto/XmlToArrayTest.php +++ b/tests/library/EngineBlock/Test/Corto/XmlToArrayTest.php @@ -32,13 +32,13 @@ class EngineBlock_Test_Corto_Module_XMlToArrayTest extends TestCase public function testNamespacedAttributes() { $hash = EngineBlock_Corto_XmlToArray::xml2array( -<< test -SAML +SAML_WRAP ); @@ -220,9 +220,7 @@ public function testAttributeValueIsSkippedWhenEmpty() $this->assertEquals($expectedArray, $xmlConverter->attributesToArray($attributes)); } - /** - * @dataProvider xmlInputProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('xmlInputProvider')] public function testXmlToArray($xmlFile, $phpFile) { $xmlInput = file_get_contents($xmlFile); @@ -231,9 +229,7 @@ public function testXmlToArray($xmlFile, $phpFile) $this->assertEquals($expectedPhpOutput, EngineBlock_Corto_XmlToArray::xml2array($xmlInput)); } - /** - * @dataProvider xmlOutputProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('xmlOutputProvider')] public function testArrayToXml($phpFile, $xmlFile) { $phpInput = require $phpFile; @@ -247,7 +243,7 @@ public function testArrayToXml($phpFile, $xmlFile) * * @return array */ - public function xmlInputProvider() + public static function xmlInputProvider() { $testCasesDir = new DirectoryIterator(TEST_RESOURCES_DIR . '/xml-to-array'); @@ -272,7 +268,7 @@ public function xmlInputProvider() * * @return array */ - public function xmlOutputProvider() + public static function xmlOutputProvider() { $testCasesDir = new DirectoryIterator(TEST_RESOURCES_DIR . '/xml-to-array'); diff --git a/tests/library/EngineBlock/Test/Saml2/AuthnRequestAnnotationDecoratorTest.php b/tests/library/EngineBlock/Test/Saml2/AuthnRequestAnnotationDecoratorTest.php index 20b15ac51e..192b651cb1 100644 --- a/tests/library/EngineBlock/Test/Saml2/AuthnRequestAnnotationDecoratorTest.php +++ b/tests/library/EngineBlock/Test/Saml2/AuthnRequestAnnotationDecoratorTest.php @@ -35,7 +35,7 @@ public function testToString() $annotatedRequest->setDebug(); $this->assertEquals( - '{"sspMessage":"\n\n","keyId":null,"wasSigned":false,"debug":true,"unsolicited":false,"transparent":false,"deliverByBinding":null}', + '{"sspMessage":"\n\n","deliverByBinding":null,"keyId":null,"wasSigned":false,"debug":true,"unsolicited":false,"transparent":false}', $annotatedRequest->__toString() ); } @@ -82,4 +82,19 @@ public function test_retrieve_loa_obligations_multiple_matches() $this->assertTrue(is_array($obligations)); $this->assertCount(2, $obligations); } + + public function test_relaystate_persists_through_serialization() + { + $request = new AuthnRequest(); + $request->setId('RS1'); + $request->setIssueInstant(0); + $request->setRelayState('ss:mem:relay-123'); + + $decorator = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($request); + + $serialized = serialize($decorator); + $restored = unserialize($serialized); + + $this->assertEquals('ss:mem:relay-123', $restored->getRelayState(), 'RelayState should survive serialization'); + } } diff --git a/tests/library/EngineBlock/Test/Saml2/NameIdResolverTest.php b/tests/library/EngineBlock/Test/Saml2/NameIdResolverTest.php index b21bd1245d..228d62336b 100644 --- a/tests/library/EngineBlock/Test/Saml2/NameIdResolverTest.php +++ b/tests/library/EngineBlock/Test/Saml2/NameIdResolverTest.php @@ -28,9 +28,8 @@ /** * Tests for EngineBlock_Log - * - * @group saml2 */ +#[\PHPUnit\Framework\Attributes\Group('saml2')] class EngineBlock_Test_Saml2_NameIdResolverTest extends TestCase { use MockeryPHPUnitIntegration; diff --git a/tests/library/EngineBlock/Test/Saml2/ResponseAnnotationDecoratorTest.php b/tests/library/EngineBlock/Test/Saml2/ResponseAnnotationDecoratorTest.php new file mode 100644 index 0000000000..1dfc40d3e2 --- /dev/null +++ b/tests/library/EngineBlock/Test/Saml2/ResponseAnnotationDecoratorTest.php @@ -0,0 +1,39 @@ +setId('RS1'); + $response->setIssueInstant(Utils::xsDateTimeToTimestamp('2023-01-01T00:00:00Z')); + $response->setRelayState('ss:mem:response-relay-456'); + + $decorator = new EngineBlock_Saml2_ResponseAnnotationDecorator($response); + + $serialized = serialize($decorator); + $restored = unserialize($serialized); + + $this->assertEquals('ss:mem:response-relay-456', $restored->getRelayState(), 'RelayState should survive serialization in Response'); + } + +} diff --git a/tests/library/EngineBlock/Test/Validator/UriTest.php b/tests/library/EngineBlock/Test/Validator/UriTest.php index 215902d64f..d44d365900 100644 --- a/tests/library/EngineBlock/Test/Validator/UriTest.php +++ b/tests/library/EngineBlock/Test/Validator/UriTest.php @@ -36,15 +36,13 @@ public function setUp(): void $this->validator = new EngineBlock_Validator_Uri(); } - /** - * @dataProvider validUriProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('validUriProvider')] public function testUriValidates($uri) { $this->assertTrue($this->validator->validate($uri)); } - public function validUriProvider() + public static function validUriProvider() { return array( array('http://example.com'), // Pretty standard http url diff --git a/tests/library/EngineBlock/Test/Validator/UrnTest.php b/tests/library/EngineBlock/Test/Validator/UrnTest.php index 5ed4a8758d..dd4c4401d6 100644 --- a/tests/library/EngineBlock/Test/Validator/UrnTest.php +++ b/tests/library/EngineBlock/Test/Validator/UrnTest.php @@ -33,23 +33,19 @@ public function setUp(): void $this->validator = new EngineBlock_Validator_Urn(); } - /** - * @dataProvider validUrnProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('validUrnProvider')] public function testUrnValidates($urn) { $this->assertTrue($this->validator->validate($urn)); } - /** - * @dataProvider invalidUrnProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidUrnProvider')] public function testUrnValidationFails($invalidUrn) { $this->assertFalse($this->validator->validate($invalidUrn)); } - public function validUrnProvider() + public static function validUrnProvider() { yield ['urn:collab:person:example.org:jdoe']; yield ['urn:mace:dir:entitlement:common-lib-terms']; @@ -61,7 +57,7 @@ public function validUrnProvider() yield ['urn:group:team#fragment']; } - public function invalidUrnProvider() + public static function invalidUrnProvider() { yield ['abcdefg']; yield ['urn:collab:%0']; diff --git a/tests/phpunit.xml b/tests/phpunit.xml index dba0abea9f..662a1f5503 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -1,10 +1,21 @@ - + + unit @@ -14,27 +25,28 @@ library - controllers functional - - - ../src - ../library - - - + + + + + + + + + src + library + + - - - + + + + - - - - diff --git a/tests/unit/OpenConext/EngineBlock/Assert/AssertionTest.php b/tests/unit/OpenConext/EngineBlock/Assert/AssertionTest.php index 1ca20a5bc6..12241ea708 100644 --- a/tests/unit/OpenConext/EngineBlock/Assert/AssertionTest.php +++ b/tests/unit/OpenConext/EngineBlock/Assert/AssertionTest.php @@ -23,11 +23,9 @@ class AssertionTest extends TestCase { - /** - * @test - * @group EngineBlock - * @group Assertion - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function non_empty_strings_are_valid() { $this->expectNotToPerformAssertions(); @@ -37,14 +35,14 @@ public function non_empty_strings_are_valid() } /** - * @test - * @group EngineBlock - * @group Assertion * - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString() * * @param mixed $value */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function not_strings_or_empty_strings_are_invalid($value) { $this->expectException(InvalidArgumentException::class); @@ -52,11 +50,9 @@ public function not_strings_or_empty_strings_are_invalid($value) Assertion::nonEmptyString($value, 'value'); } - /** - * @test - * @group EngineBlock - * @group Assertion - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function a_missing_key_makes_the_assertion_fail() { $this->expectException(InvalidArgumentException::class); @@ -67,11 +63,9 @@ public function a_missing_key_makes_the_assertion_fail() Assertion::keysExist($actualData, $requiredKeys); } - /** - * @test - * @group EngineBlock - * @group Assertion - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function keys_exists_assertion_succeeds_if_all_required_keys_are_present_() { $requiredKeys = ['a', 'b', 'c']; @@ -89,12 +83,10 @@ public function keys_exists_assertion_succeeds_if_all_required_keys_are_present_ $this->assertFalse($exceptionCaught, 'When all required keys are present, no exception should be thrown'); } - /** - * @test - * @group EngineBlock - * @group Assertion - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString - */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function valid_hashing_algorithm_only_accepts_non_empty_strings($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); @@ -102,11 +94,9 @@ public function valid_hashing_algorithm_only_accepts_non_empty_strings($notStrin Assertion::validHashingAlgorithm($notStringOrEmptyString); } - /** - * @test - * @group EngineBlock - * @group Assertion - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function an_invalid_hashing_algorithm_causes_the_assertion_to_throw_an_exception() { $this->expectException(InvalidArgumentException::class); @@ -114,12 +104,10 @@ public function an_invalid_hashing_algorithm_causes_the_assertion_to_throw_an_ex Assertion::validHashingAlgorithm('invalid'); } - /** - * @test - * @group EngineBlock - * @group Assertion - * @dataProvider validHashingAlgorithmProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('validHashingAlgorithmProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Assertion')] + #[\PHPUnit\Framework\Attributes\Test] public function existing_hashing_algorithms_are_considered_valid($validHashingAlgorithm) { $exceptionCaught = false; @@ -132,7 +120,7 @@ public function existing_hashing_algorithms_are_considered_valid($validHashingAl $this->assertFalse($exceptionCaught, 'A valid hashing algorithm should not cause an exception to be thrown'); } - public function validHashingAlgorithmProvider() + public static function validHashingAlgorithmProvider() { return array_map(function ($algorithm) { return [$algorithm]; diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Dto/ConsentTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Dto/ConsentTest.php index 4cc0f8c49d..30f4050cca 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Dto/ConsentTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Dto/ConsentTest.php @@ -79,12 +79,10 @@ private function createServiceProvider(array $organizations = [], $omitDisplayNa return $serviceProvider; } - /** - * @test - * @group EngineBlock - * @group Authentication - * @group Dto - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Group('Dto')] + #[\PHPUnit\Framework\Attributes\Test] public function all_values_are_serialized_to_json() { $serviceProvider = $this->createServiceProvider(); @@ -125,9 +123,7 @@ public function all_values_are_serialized_to_json() $this->assertEquals($serviceProvider->organizationPt->displayName, $json['organization_display_name']['pt']); } - /** - * @dataProvider provideOrganizations - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideOrganizations')] public function test_display_name_of_organizations_works_as_intended( array $organizations, array $expectations, @@ -153,12 +149,10 @@ public function test_display_name_of_organizations_works_as_intended( $this->assertEquals($expectations['pt'], $json['pt'], $errorMessage); } - /** - * @test - * @group EngineBlock - * @group Authentication - * @group Dto - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Group('Dto')] + #[\PHPUnit\Framework\Attributes\Test] public function display_name_falls_back_to_name_if_display_name_is_empty() { $serviceProvider = $this->createServiceProvider([], false); @@ -187,12 +181,10 @@ public function display_name_falls_back_to_name_if_display_name_is_empty() $this->assertEquals($serviceProvider->nameNl, $json['service_provider']['display_name']['nl']); } - /** - * @test - * @group EngineBlock - * @group Authentication - * @group Dto - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Group('Dto')] + #[\PHPUnit\Framework\Attributes\Test] public function display_name_falls_back_to_entity_id_if_name_is_empty() { $serviceProvider = $this->createServiceProvider([], true); @@ -220,7 +212,7 @@ public function display_name_falls_back_to_entity_id_if_name_is_empty() $this->assertEquals($serviceProvider->entityId, $json['service_provider']['display_name']['nl']); } - public function provideOrganizations() + public static function provideOrganizations() { $displayNameEn = 'Organization display name EN'; $nameEn = 'Organization name EN'; @@ -297,7 +289,6 @@ private function setCoin(ServiceProvider $sp, $key, $name) $coins = Coins::fromJson($jsonData); $property = new \ReflectionProperty(ServiceProvider::class, 'coins'); - $property->setAccessible(true); $property->setValue(null, $coins); } } diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonIdTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonIdTest.php index 3357ccd5d4..d46b84ef33 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonIdTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonIdTest.php @@ -23,11 +23,9 @@ class CollabPersonIdTest extends TestCase { - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_predictable_collab_person_id_is_generated_with_at_signs_replaced_with_underscores() { $schacHomeOrganizationValue = 'openconext.org'; @@ -47,13 +45,13 @@ public function a_predictable_collab_person_id_is_generated_with_at_signs_replac } /** - * @test - * @group EngineBlock - * @group Authentication - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $notStringOrEmptyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function collab_person_id_must_be_a_non_empty_string($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); @@ -62,13 +60,13 @@ public function collab_person_id_must_be_a_non_empty_string($notStringOrEmptyStr } /** - * @test - * @group EngineBlock - * @group Authentication - * @dataProvider invalidNameSpaceProvider * * @param string $wronglyNamespaced */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidNameSpaceProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function collab_person_id_must_start_with_the_correct_namespace($wronglyNamespaced) { $this->expectException(InvalidArgumentException::class); @@ -79,7 +77,7 @@ public function collab_person_id_must_start_with_the_correct_namespace($wronglyN /** * @return array */ - public function invalidNameSpaceProvider() + public static function invalidNameSpaceProvider() { $user = ':openconext:unique-user-id'; @@ -90,11 +88,9 @@ public function invalidNameSpaceProvider() ]; } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function collab_person_id_must_not_be_longer_than_the_maximum_allowed_number_of_characters() { $namespaceLength = strlen(CollabPersonId::URN_NAMESPACE); @@ -117,11 +113,9 @@ public function collab_person_id_must_not_be_longer_than_the_maximum_allowed_num $this->assertTrue($exceptionCaughtAtConstruction($aboveLimit)); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function collab_person_id_can_be_retrieved() { $collabPersonIdValue = CollabPersonId::URN_NAMESPACE . ':openconext:unique-user-id'; @@ -131,11 +125,9 @@ public function collab_person_id_can_be_retrieved() $this->assertEquals($collabPersonIdValue, $collabPersonId->getCollabPersonId()); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function collab_person_ids_are_only_equal_if_created_with_the_same_value() { $firstId = CollabPersonId::URN_NAMESPACE . ':openconext:unique-user-id'; @@ -149,11 +141,9 @@ public function collab_person_ids_are_only_equal_if_created_with_the_same_value( $this->assertFalse($base->equals($different)); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_collab_person_id_can_be_cast_to_string() { $collabPersonIdValue = CollabPersonId::URN_NAMESPACE . ':openconext:unique-user-id'; diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonUuidTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonUuidTest.php index fd641480c0..fc2fd76afa 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonUuidTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Value/CollabPersonUuidTest.php @@ -25,13 +25,13 @@ class CollabPersonUuidTest extends TestCase { /** - * @test - * @group EngineBlock - * @group Authentication - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $notStringOrEmptyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function uuid_must_be_a_non_empty_string($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); @@ -39,11 +39,9 @@ public function uuid_must_be_a_non_empty_string($notStringOrEmptyString) new CollabPersonUuid($notStringOrEmptyString); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function uuid_must_be_a_valid_uuid() { $this->expectException(InvalidArgumentException::class); @@ -51,11 +49,9 @@ public function uuid_must_be_a_valid_uuid() new CollabPersonUuid('not a valid uuid'); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function the_uuid_can_be_retrieved() { $uuid = (string) Uuid::uuid4(); @@ -65,11 +61,9 @@ public function the_uuid_can_be_retrieved() $this->assertEquals($uuid, $collabPersonUuid->getUuid()); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function collab_person_uuids_are_equal_when_they_have_the_same_value() { $uuid = (string) Uuid::uuid4(); @@ -82,11 +76,9 @@ public function collab_person_uuids_are_equal_when_they_have_the_same_value() $this->assertFalse($base->equals($different)); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_collab_person_uuid_can_be_cast_to_string() { $collabPersonUuid = new CollabPersonUuid((string) Uuid::uuid4()); diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Value/ConsentTypeTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Value/ConsentTypeTest.php index a6da1239a5..6e32cbdc3d 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Value/ConsentTypeTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Value/ConsentTypeTest.php @@ -25,15 +25,15 @@ class ConsentTypeTest extends TestCase { /** - * @test - * @group EngineBlock - * @group Authentication - * @group Value * - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $invalid */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Group('Value')] + #[\PHPUnit\Framework\Attributes\Test] public function cannot_be_other_than_implicit_or_explicit($invalid) { $this->expectException(InvalidArgumentException::class); @@ -41,12 +41,10 @@ public function cannot_be_other_than_implicit_or_explicit($invalid) new ConsentType($invalid); } - /** - * @test - * @group EngineBlock - * @group Authentication - * @group Value - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Group('Value')] + #[\PHPUnit\Framework\Attributes\Test] public function different_consent_types_are_not_equal() { $explicit = ConsentType::explicit(); @@ -56,12 +54,10 @@ public function different_consent_types_are_not_equal() $this->assertFalse($implicit->equals($explicit)); } - /** - * @test - * @group EngineBlock - * @group Authentication - * @group Value - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Group('Value')] + #[\PHPUnit\Framework\Attributes\Test] public function same_type_of_consent_types_are_equal() { $explicit = ConsentType::explicit(); diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Value/KeyIdTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Value/KeyIdTest.php index 8ddecad4d6..7befec6fe7 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Value/KeyIdTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Value/KeyIdTest.php @@ -24,13 +24,13 @@ class KeyIdTest extends TestCase { /** - * @test - * @group EngineBlock - * @group Authentication - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $notStringOrEmptyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function key_id_must_be_a_non_empty_string($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); @@ -38,11 +38,9 @@ public function key_id_must_be_a_non_empty_string($notStringOrEmptyString) new KeyId($notStringOrEmptyString); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function key_id_can_be_retrieved() { $keyIdValue = '20160403'; @@ -52,11 +50,9 @@ public function key_id_can_be_retrieved() $this->assertEquals($keyIdValue, $keyId->getKeyId()); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function key_ids_are_only_equal_if_created_with_the_same_value() { $firstId = '20160403'; @@ -70,11 +66,9 @@ public function key_ids_are_only_equal_if_created_with_the_same_value() $this->assertFalse($base->equals($different)); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_key_id_can_be_cast_to_string() { $keyId = new KeyId('20160403'); diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Value/SchacHomeOrganizationTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Value/SchacHomeOrganizationTest.php index 22c04b286f..4367376950 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Value/SchacHomeOrganizationTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Value/SchacHomeOrganizationTest.php @@ -24,13 +24,13 @@ class SchacHomeOrganizationTest extends TestCase { /** - * @test - * @group EngineBlock - * @group Authentication - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $notStringOrEmptyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function schac_home_organization_must_be_a_non_empty_string($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); @@ -38,11 +38,9 @@ public function schac_home_organization_must_be_a_non_empty_string($notStringOrE new SchacHomeOrganization($notStringOrEmptyString); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function schac_home_organization_can_be_retrieved() { $schacHomeOrganizationValue = 'OpenConext.org'; @@ -52,11 +50,9 @@ public function schac_home_organization_can_be_retrieved() $this->assertSame($schacHomeOrganizationValue, $schacHomeOrganization->getSchacHomeOrganization()); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function schac_home_organization_equality_is_determined_based_on_value() { $base = new SchacHomeOrganization('OpenConext.org'); @@ -67,11 +63,9 @@ public function schac_home_organization_equality_is_determined_based_on_value() $this->assertFalse($base->equals($different)); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_schac_home_organization_can_be_cast_to_string() { $schacHomeOrganization = new SchacHomeOrganization('OpenConext.org'); diff --git a/tests/unit/OpenConext/EngineBlock/Authentication/Value/UidTest.php b/tests/unit/OpenConext/EngineBlock/Authentication/Value/UidTest.php index d22af98b86..94a2cb432d 100644 --- a/tests/unit/OpenConext/EngineBlock/Authentication/Value/UidTest.php +++ b/tests/unit/OpenConext/EngineBlock/Authentication/Value/UidTest.php @@ -24,13 +24,13 @@ class UidTest extends TestCase { /** - * @test - * @group EngineBlock - * @group Authentication - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $notStringOrEmptyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function uid_must_be_a_non_empty_string($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); @@ -38,11 +38,9 @@ public function uid_must_be_a_non_empty_string($notStringOrEmptyString) new Uid($notStringOrEmptyString); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function uid_can_be_retrieved() { $uidValue = md5('foobar'); @@ -52,11 +50,9 @@ public function uid_can_be_retrieved() $this->assertSame($uidValue, $uid->getUid()); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function uid_equality_is_determined_based_on_value() { $base = new Uid('some:uid'); @@ -67,11 +63,9 @@ public function uid_equality_is_determined_based_on_value() $this->assertFalse($base->equals($different)); } - /** - * @test - * @group EngineBlock - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_uid_can_be_cast_to_string() { $uid = new Uid('some:uid'); diff --git a/tests/unit/OpenConext/EngineBlock/Driver/File/FileStorageDriverTest.php b/tests/unit/OpenConext/EngineBlock/Driver/File/FileStorageDriverTest.php index ed547ae316..d9a98095ab 100644 --- a/tests/unit/OpenConext/EngineBlock/Driver/File/FileStorageDriverTest.php +++ b/tests/unit/OpenConext/EngineBlock/Driver/File/FileStorageDriverTest.php @@ -21,6 +21,7 @@ use Mockery as m; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use OpenConext\EngineBlock\Exception\InvalidArgumentException; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; class FileStorageDriverTest extends TestCase @@ -28,67 +29,64 @@ class FileStorageDriverTest extends TestCase use MockeryPHPUnitIntegration; /** - * @test - * @group EngineBlock - * @group Driver * - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $notStringOrEmptyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function filepath_must_be_a_non_empty_string($notStringOrEmptyString) { $this->expectException(InvalidArgumentException::class); - new FileStorageDriver(m::mock('OpenConext\EngineBlock\Driver\File\FileHandler'), $notStringOrEmptyString); + new FileStorageDriver(m::mock(\OpenConext\EngineBlock\Driver\File\FileHandler::class), $notStringOrEmptyString); } /** - * @test - * @group EngineBlock - * @group Driver * - * @dataProvider \OpenConext\TestDataProvider::notString * * @param mixed $notString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function data_to_save_must_be_a_string($notString) { $this->expectException(InvalidArgumentException::class); - $storage = new FileStorageDriver(m::mock('OpenConext\EngineBlock\Driver\File\FileHandler'), '/some/path'); + $storage = new FileStorageDriver(m::mock(\OpenConext\EngineBlock\Driver\File\FileHandler::class), '/some/path'); $storage->save($notString); } - /** - * @test - * @group EngineBlock - * @group Driver - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] + #[DoesNotPerformAssertions] public function data_is_written_unmodified_to_file() { $data = 'FooBarBaz'; $filePath = '/some/file/path'; - $fileHandlerMock = m::mock('OpenConext\EngineBlock\Driver\File\FileHandler'); + $fileHandlerMock = m::mock(\OpenConext\EngineBlock\Driver\File\FileHandler::class); $fileHandlerMock->shouldReceive('writeTo')->withArgs([$data, $filePath]); $storage = new FileStorageDriver($fileHandlerMock, $filePath); $storage->save($data); } - /** - * @test - * @group EngineBlock - * @group Driver - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function data_is_read_from_file_and_returned_unmodified() { $data = 'FooBarBaz'; $filePath = '/some/file/path'; - $fileHandlerMock = m::mock('OpenConext\EngineBlock\Driver\File\FileHandler'); + $fileHandlerMock = m::mock(\OpenConext\EngineBlock\Driver\File\FileHandler::class); $fileHandlerMock->shouldReceive('readFrom')->withArgs([$filePath])->andReturn($data); $storage = new FileStorageDriver($fileHandlerMock, $filePath); diff --git a/tests/unit/OpenConext/EngineBlock/Driver/File/FilesystemAdapterTest.php b/tests/unit/OpenConext/EngineBlock/Driver/File/FilesystemAdapterTest.php index 6599fece1d..4a9b42d85a 100644 --- a/tests/unit/OpenConext/EngineBlock/Driver/File/FilesystemAdapterTest.php +++ b/tests/unit/OpenConext/EngineBlock/Driver/File/FilesystemAdapterTest.php @@ -30,67 +30,63 @@ class FilesystemAdapterTest extends TestCase use MockeryPHPUnitIntegration; /** - * @test - * @group EngineBlock - * @group Driver * - * @dataProvider \OpenConext\TestDataProvider::notString * * @param mixed $nonString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function data_to_write_to_file_must_be_a_string($nonString) { - $filesystemAdapter = new FilesystemAdapter(m::mock('\Symfony\Component\Filesystem\Filesystem')); + $filesystemAdapter = new FilesystemAdapter(m::mock(\Symfony\Component\Filesystem\Filesystem::class)); $this->expectException(InvalidArgumentException::class); $filesystemAdapter->writeTo($nonString, '/some/path'); } /** - * @test - * @group EngineBlock - * @group Driver * - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * * @param mixed $nonStringOrEmtpyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function in_order_to_write_given_filepath_must_be_a_string($nonStringOrEmtpyString) { - $filesystemAdapter = new FilesystemAdapter(m::mock('\Symfony\Component\Filesystem\Filesystem')); + $filesystemAdapter = new FilesystemAdapter(m::mock(\Symfony\Component\Filesystem\Filesystem::class)); $this->expectException(InvalidArgumentException::class); $filesystemAdapter->writeTo('data-to-write', $nonStringOrEmtpyString); } - /** - * @test - * @group EngineBlock - * @group Driver - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function an_exception_thrown_by_filesystem_when_writing_is_converted_to_an_engineblock_exception() { - $filesystemMock = m::mock('\Symfony\Component\Filesystem\Filesystem'); - $filesystemMock->shouldReceive('dumpFile')->andThrow('Symfony\Component\Filesystem\Exception\IOException'); + $filesystemMock = m::mock(\Symfony\Component\Filesystem\Filesystem::class); + $filesystemMock->shouldReceive('dumpFile')->andThrow(\Symfony\Component\Filesystem\Exception\IOException::class); $filesystemAdapter = new FilesystemAdapter($filesystemMock); try { $filesystemAdapter->writeTo('data-to-write', '/some/path'); } catch (Exception $exception) { - $this->assertInstanceOf('\OpenConext\EngineBlock\Exception\RuntimeException', $exception); - $this->assertInstanceOf('Symfony\Component\Filesystem\Exception\IOException', $exception->getPrevious()); + $this->assertInstanceOf(\OpenConext\EngineBlock\Exception\RuntimeException::class, $exception); + $this->assertInstanceOf(\Symfony\Component\Filesystem\Exception\IOException::class, $exception->getPrevious()); } } - /** - * @test - * @group EngineBlock - * @group Driver - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function attempting_to_read_data_from_a_non_existent_file_fails() { - $filesystemMock = m::mock('\Symfony\Component\Filesystem\Filesystem'); + $filesystemMock = m::mock(\Symfony\Component\Filesystem\Filesystem::class); $filesystemMock->shouldReceive('exists')->andReturn(false); $filesystemAdapter = new FilesystemAdapter($filesystemMock); @@ -99,14 +95,12 @@ public function attempting_to_read_data_from_a_non_existent_file_fails() $filesystemAdapter->readFrom('/does/not/exist'); } - /** - * @test - * @group EngineBlock - * @group Driver - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Driver')] + #[\PHPUnit\Framework\Attributes\Test] public function attempting_to_read_data_from_a_file_that_is_not_readable_fails() { - $filesystemMock = m::mock('\Symfony\Component\Filesystem\Filesystem'); + $filesystemMock = m::mock(\Symfony\Component\Filesystem\Filesystem::class); $filesystemMock->shouldReceive('exists')->andReturn(true); $filesystemAdapter = new FilesystemAdapter($filesystemMock); diff --git a/tests/unit/OpenConext/EngineBlock/Exception/IndexOutOfBoundsExceptionTest.php b/tests/unit/OpenConext/EngineBlock/Exception/IndexOutOfBoundsExceptionTest.php index 17a5795740..001d48c803 100644 --- a/tests/unit/OpenConext/EngineBlock/Exception/IndexOutOfBoundsExceptionTest.php +++ b/tests/unit/OpenConext/EngineBlock/Exception/IndexOutOfBoundsExceptionTest.php @@ -25,11 +25,9 @@ class IndexOutOfBoundsExceptionTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlock - * @group Exception - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Exception')] + #[\PHPUnit\Framework\Attributes\Test] public function too_low_creates_an_exception_with_a_known_format_message() { $invalidIndex = -1; @@ -37,18 +35,16 @@ public function too_low_creates_an_exception_with_a_known_format_message() $exception = IndexOutOfBoundsException::tooLow($invalidIndex, $minimumIndex); - $this->assertInstanceOf('\OpenConext\EngineBlock\Exception\IndexOutOfBoundsException', $exception); + $this->assertInstanceOf(\OpenConext\EngineBlock\Exception\IndexOutOfBoundsException::class, $exception); $this->assertSame( sprintf('Index "%d" is lower than the minimum index "%d"', $invalidIndex, $minimumIndex), $exception->getMessage() ); } - /** - * @test - * @group EngineBlock - * @group Exception - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Exception')] + #[\PHPUnit\Framework\Attributes\Test] public function a_too_low_index_has_the_invalid_index_and_minimum_index_not_maximum_index() { $invalidIndex = -1; @@ -61,11 +57,9 @@ public function a_too_low_index_has_the_invalid_index_and_minimum_index_not_maxi $this->assertNull($exception->getMaximumIndex()); } - /** - * @test - * @group EngineBlock - * @group Exception - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Exception')] + #[\PHPUnit\Framework\Attributes\Test] public function too_high_creates_an_exception_with_a_known_format_message() { $invalidIndex = 5; @@ -73,18 +67,16 @@ public function too_high_creates_an_exception_with_a_known_format_message() $exception = IndexOutOfBoundsException::tooHigh($invalidIndex, $maximumIndex); - $this->assertInstanceOf('\OpenConext\EngineBlock\Exception\IndexOutOfBoundsException', $exception); + $this->assertInstanceOf(\OpenConext\EngineBlock\Exception\IndexOutOfBoundsException::class, $exception); $this->assertSame( sprintf('Index "%d" is higher than the maximum index "%d"', $invalidIndex, $maximumIndex), $exception->getMessage() ); } - /** - * @test - * @group EngineBlock - * @group Exception - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Exception')] + #[\PHPUnit\Framework\Attributes\Test] public function a_too_high_index_has_the_invalid_index_and_maximum_index_not_minimum_index() { $invalidIndex = 5; diff --git a/tests/unit/OpenConext/EngineBlock/Http/HttpClientTest.php b/tests/unit/OpenConext/EngineBlock/Http/HttpClientTest.php index 57db638909..9e257ae3a0 100644 --- a/tests/unit/OpenConext/EngineBlock/Http/HttpClientTest.php +++ b/tests/unit/OpenConext/EngineBlock/Http/HttpClientTest.php @@ -50,11 +50,9 @@ class HttpClientTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function data_from_a_resource_can_be_read() { $data = 'My first resource'; @@ -72,11 +70,9 @@ public function data_from_a_resource_can_be_read() $this->assertEquals($data, $response); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function malformed_json_causes_a_malformed_response_exception_when_reading() { $malformedJson = '{'; @@ -92,11 +88,9 @@ public function malformed_json_causes_a_malformed_response_exception_when_readin $client->read('/give-me/malformed-json'); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function null_is_returned_when_the_response_status_code_is_404_when_reading() { $mockHandler = new MockHandler([ @@ -113,11 +107,9 @@ public function null_is_returned_when_the_response_status_code_is_404_when_readi ); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function an_access_denied_exception_is_thrown_if_the_response_status_code_is_403_when_reading() { $mockHandler = new MockHandler([ @@ -131,11 +123,9 @@ public function an_access_denied_exception_is_thrown_if_the_response_status_code $client->read('give-me/403'); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function data_from_a_resource_can_be_posted() { $data = 'Received data'; @@ -152,11 +142,9 @@ public function data_from_a_resource_can_be_posted() $this->assertEquals($data, $response); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function malformed_json_causes_a_malformed_response_exception_when_posting() { $malformedJson = '{'; @@ -172,11 +160,9 @@ public function malformed_json_causes_a_malformed_response_exception_when_postin $client->post('/post-and-give-me/malformed-json', 'Post body'); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function null_is_returned_when_the_response_status_code_is_404_when_posting() { $mockHandler = new MockHandler([ @@ -193,11 +179,9 @@ public function null_is_returned_when_the_response_status_code_is_404_when_posti ); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function an_access_denied_exception_is_thrown_if_the_response_status_code_is_403_when_posting() { $mockHandler = new MockHandler([ diff --git a/tests/unit/OpenConext/EngineBlock/Http/JsonResponseParserTest.php b/tests/unit/OpenConext/EngineBlock/Http/JsonResponseParserTest.php index fc975fb55b..0aed86884f 100644 --- a/tests/unit/OpenConext/EngineBlock/Http/JsonResponseParserTest.php +++ b/tests/unit/OpenConext/EngineBlock/Http/JsonResponseParserTest.php @@ -27,13 +27,10 @@ class JsonResponseParserTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Http - * @group Json - * - * @dataProvider \OpenConext\TestDataProvider::notString() - */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notString')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function json_response_to_parse_must_be_a_string($nonString) { $this->expectException(InvalidArgumentException::class); @@ -42,11 +39,9 @@ public function json_response_to_parse_must_be_a_string($nonString) JsonResponseParser::parse($nonString); } - /** - * @test - * @group Http - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function an_exception_is_thrown_if_the_json_is_malformed() { $this->expectException(InvalidJsonException::class); diff --git a/tests/unit/OpenConext/EngineBlock/Http/ResourcePathFormatterTest.php b/tests/unit/OpenConext/EngineBlock/Http/ResourcePathFormatterTest.php index 6630c1bd46..2cd0a446d3 100644 --- a/tests/unit/OpenConext/EngineBlock/Http/ResourcePathFormatterTest.php +++ b/tests/unit/OpenConext/EngineBlock/Http/ResourcePathFormatterTest.php @@ -27,13 +27,13 @@ class ResourcePathFormatterTest extends TestCase use MockeryPHPUnitIntegration; /** - * @test - * @group EngineBlock - * @group Http * - * @dataProvider \OpenConext\TestDataProvider::notString() * @param $nonString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function resource_path_formats_can_only_be_strings($nonString) { $this->expectException(InvalidArgumentException::class); @@ -42,11 +42,9 @@ public function resource_path_formats_can_only_be_strings($nonString) ResourcePathFormatter::format($nonString, []); } - /** - * @test - * @group EngineBlock - * @group Http - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Http')] + #[\PHPUnit\Framework\Attributes\Test] public function resource_parameters_are_formatted_correctly() { $resourcePathFormat = 'resource/%s/%d'; diff --git a/tests/unit/OpenConext/EngineBlock/Logger/AuthenticationLoggerTest.php b/tests/unit/OpenConext/EngineBlock/Logger/AuthenticationLoggerTest.php index 5591238444..127306920f 100644 --- a/tests/unit/OpenConext/EngineBlock/Logger/AuthenticationLoggerTest.php +++ b/tests/unit/OpenConext/EngineBlock/Logger/AuthenticationLoggerTest.php @@ -39,11 +39,10 @@ class AuthenticationLoggerTest extends TestCase * are actually very valuable: they are used for statistical purpose. Other * tools depend on the format and contents of the log. Therefor it is worth * to write such a test to ensure compatibility. - * - * @test - * @group EngineBlock - * @group Logger */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function the_logged_context_contains_all_required_information() { // raw data so we can compare later on @@ -79,7 +78,7 @@ public function the_logged_context_contains_all_required_information() 'engine_sso_endpoint_used' => $ssoEndpointUsed ]; - $mockLogger = m::mock('\Psr\Log\LoggerInterface'); + $mockLogger = m::mock(\Psr\Log\LoggerInterface::class); $mockLogger ->shouldReceive('info') ->withArgs([ @@ -123,11 +122,9 @@ public function the_logged_context_contains_all_required_information() ); } - /** - * @test - * @group EngineBlock - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function the_logged_context_contains_all_enriched_information() { // raw data so we can compare later on @@ -165,7 +162,7 @@ public function the_logged_context_contains_all_enriched_information() 'response_attributes' => ['label' => 'attributeValue'] ]; - $mockLogger = m::mock('\Psr\Log\LoggerInterface'); + $mockLogger = m::mock(\Psr\Log\LoggerInterface::class); $mockLogger ->shouldReceive('info') ->withArgs([ diff --git a/tests/unit/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatterTest.php b/tests/unit/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatterTest.php index 83e44b0125..96863a685a 100644 --- a/tests/unit/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatterTest.php +++ b/tests/unit/OpenConext/EngineBlock/Logger/Formatter/AdditionalInfoFormatterTest.php @@ -27,11 +27,9 @@ class AdditionalInfoFormatterTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlock - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function additional_info_is_added_for_an_engineblock_exception() { $exception = new EngineBlock_Exception('message', EngineBlock_Exception::CODE_EMERGENCY); @@ -50,11 +48,9 @@ public function additional_info_is_added_for_an_engineblock_exception() ); } - /** - * @test - * @group EngineBlock - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function additional_info_is_added_for_engineblock_exception_when_batch_formatting() { $exception = new EngineBlock_Exception('message'); @@ -73,11 +69,9 @@ public function additional_info_is_added_for_engineblock_exception_when_batch_fo ); } - /** - * @test - * @group EngineBlock - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function additional_info_is_not_added_for_non_engineblock_exceptions() { $exception = new Exception('message'); diff --git a/tests/unit/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrErrorLevelActivationStrategyFactoryTest.php b/tests/unit/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrErrorLevelActivationStrategyFactoryTest.php index 6b2d2275d8..1fec2ccae5 100644 --- a/tests/unit/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrErrorLevelActivationStrategyFactoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Logger/Handler/FingersCrossed/ManualOrErrorLevelActivationStrategyFactoryTest.php @@ -23,11 +23,9 @@ class ManualOrErrorLevelActivationStrategyFactoryTest extends TestCase { - /** - * @test - * @group EngineBlock - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function factory_creates_a_manual_or_decorated_activation_strategy() { $this->expectNotToPerformAssertions(); @@ -35,15 +33,14 @@ public function factory_creates_a_manual_or_decorated_activation_strategy() } /** - * @test - * @group EngineBlock - * @group Logger - * - * @dataProvider configurationDataProvider * * @param array $config * @param string $expectedExceptionMessageContains */ + #[\PHPUnit\Framework\Attributes\DataProvider('configurationDataProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function configuration_is_validated(array $config, $expectedExceptionMessageContains) { $this->expectException(InvalidArgumentException::class); @@ -52,7 +49,7 @@ public function configuration_is_validated(array $config, $expectedExceptionMess ManualOrErrorLevelActivationStrategyFactory::createActivationStrategy($config); } - public function configurationDataProvider() + public static function configurationDataProvider() { return [ 'no action level' => [ diff --git a/tests/unit/OpenConext/EngineBlock/Logger/Message/AdditionalInfoTest.php b/tests/unit/OpenConext/EngineBlock/Logger/Message/AdditionalInfoTest.php index 8c8746cbeb..97bfbf7b3a 100644 --- a/tests/unit/OpenConext/EngineBlock/Logger/Message/AdditionalInfoTest.php +++ b/tests/unit/OpenConext/EngineBlock/Logger/Message/AdditionalInfoTest.php @@ -26,11 +26,9 @@ final class AdditionalInfoTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlock - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function message_has_correct_severity() { $exception = new EngineBlock_Exception('message', EngineBlock_Exception::CODE_ALERT); diff --git a/tests/unit/OpenConext/EngineBlock/Logger/Processor/RequestIdProcessorTest.php b/tests/unit/OpenConext/EngineBlock/Logger/Processor/RequestIdProcessorTest.php index ee6af3dffe..09458c0c30 100644 --- a/tests/unit/OpenConext/EngineBlock/Logger/Processor/RequestIdProcessorTest.php +++ b/tests/unit/OpenConext/EngineBlock/Logger/Processor/RequestIdProcessorTest.php @@ -27,17 +27,15 @@ class RequestIdProcessorTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlock - * @group Request - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Request')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function request_id_is_added_to_the_record() { $requestIdValue = 'some_request_id'; - $requestIdGenerator = m::mock('OpenConext\EngineBlock\Request\RequestIdGenerator'); + $requestIdGenerator = m::mock(\OpenConext\EngineBlock\Request\RequestIdGenerator::class); $requestIdGenerator->shouldReceive('generateRequestId') ->once() ->andReturn($requestIdValue); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/DiscoveryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/DiscoveryTest.php index 6911ed26c0..cd9ab873ef 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/DiscoveryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/DiscoveryTest.php @@ -29,9 +29,7 @@ public function test_successful_create(): void $this->assertNotNull($discovery); } - /** - * @dataProvider localeValueArrayProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('localeValueArrayProvider')] public function test_validates_localized_names(array $names, string $expectedExceptionMessage = null): void { $this->expectException(InvalidDiscoveryException::class); @@ -40,9 +38,7 @@ public function test_validates_localized_names(array $names, string $expectedExc Discovery::create($names, [], null); } - /** - * @dataProvider localeValueArrayProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('localeValueArrayProvider')] public function test_validates_localized_keywords(array $keywords, string $expectedExceptionMessage): void { $this->expectException(InvalidDiscoveryException::class); @@ -51,7 +47,7 @@ public function test_validates_localized_keywords(array $keywords, string $expec Discovery::create([], $keywords, null); } - public function localeValueArrayProvider(): array + public static function localeValueArrayProvider(): array { return [ 'non-string locale key' => [ diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Entity/IdentityProviderTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Entity/IdentityProviderTest.php index 936c10623e..675620d1d9 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Entity/IdentityProviderTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Entity/IdentityProviderTest.php @@ -32,3 +32,4 @@ public function testInstantiation() $this->assertEquals($entityId, $idp->entityId); } } + diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Entity/ServiceProviderTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Entity/ServiceProviderTest.php index be465505b3..076bbb66ee 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Entity/ServiceProviderTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Entity/ServiceProviderTest.php @@ -45,9 +45,8 @@ public function testInstantiation() * 3. display name in english * 4. name in english * 5. entityID (should never happen) - * - * @dataProvider displayNameProvider */ + #[\PHPUnit\Framework\Attributes\DataProvider('displayNameProvider')] public function testGetDisplayName(string $entityId, ?string $displayNameEn, ?string $nameEn, ?string $displayNameLocale, ?string $nameLocale, string $locale, $outcome) { $sp = $this->createServiceProvider( @@ -70,9 +69,8 @@ public function testGetDisplayName(string $entityId, ?string $displayNameEn, ?st * 3. english organization display name * 4. english organization name * 5. empty string (will be set to the locale-specific variant of 'unknown' in the template) - * - * @dataProvider organizationNameProvider */ + #[\PHPUnit\Framework\Attributes\DataProvider('organizationNameProvider')] public function testGetOrganizationName(string $entityId, ?string $orgDisplayNameEn, ?string $orgNameEn, ?string $orgDisplayNameNl, ?string $orgNameNl, string $locale, $outcome) { $orgEn = new Organization($orgNameEn, $orgDisplayNameEn, $entityId); @@ -98,7 +96,7 @@ public function testGetOrganizationName(string $entityId, ?string $orgDisplayNam * * @return string[][] */ - public function displayNameProvider() + public static function displayNameProvider() { return [ ['https://entityId.fake', 'JohnnyEnglish', 'English', 'JohnnyEnglish', 'English', 'en', 'JohnnyEnglish'], @@ -123,7 +121,7 @@ public function displayNameProvider() * * @return string[][] */ - public function organizationNameProvider() + public static function organizationNameProvider() { return [ ['https://entityId.fake', 'JohnnyEnglish', 'English', 'JohnnyDutch', 'Dutch', 'en', 'JohnnyEnglish'], diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/AbstractEntityTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/AbstractEntity.php similarity index 99% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/AbstractEntityTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/AbstractEntity.php index 465aca3ce2..c806329fb2 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/AbstractEntityTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/AbstractEntity.php @@ -38,7 +38,7 @@ use ReflectionClass; use ReflectionProperty; -abstract class AbstractEntityTest extends TestCase +abstract class AbstractEntity extends TestCase { /** * Create an instance which could be used by decorators @@ -349,7 +349,6 @@ protected function getOrmEntityIdentityProviderMock(array $values): IdentityProv foreach($values as $key => $value){ $reflectionProperty = $reflection->getProperty($key); - $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($entity, $value); } @@ -367,7 +366,6 @@ protected function getOrmEntityServiceProviderMock(array $values): ServiceProvid foreach($values as $key => $value){ $reflectionProperty = $reflection->getProperty($key); - $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($entity, $value); } @@ -542,7 +540,7 @@ private function getMethods($className, $skipMethods = []) if (!$method->isStatic() && !in_array($method->getName(), $skipMethods)) { if ($method->getDocComment()) { preg_match('/@return (.*)\n/', $method->getDocComment(), $matches); - $results[$method->getName()] = $matches[1]; + $results[$method->getName()] = isset($matches[1]) ? $matches[1] : null; } elseif ($method->getReturnType()) { $returnType = $method->getReturnType()->getName(); $results[$method->getName()] = $returnType; @@ -578,6 +576,10 @@ private function getGettersFromMethodNames(array $methodNames) continue; } + if ($name === '__sleep') { + continue; + } + $results[$name] = $type; } diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/IdentityProviderEntityTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/IdentityProviderEntity.php similarity index 96% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/IdentityProviderEntityTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/IdentityProviderEntity.php index f4f6a14b52..730407b3eb 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/IdentityProviderEntityTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/IdentityProviderEntity.php @@ -17,9 +17,9 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Adapter; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; -class IdentityProviderEntityTest extends AbstractEntityTest +class IdentityProviderEntity extends AbstractEntity { /** * This test will test if all methods work diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/ServiceProviderEntityTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/ServiceProviderEntity.php similarity index 98% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/ServiceProviderEntityTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/ServiceProviderEntity.php index 5db3c7612e..c460113a87 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/ServiceProviderEntityTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Adapter/ServiceProviderEntity.php @@ -18,9 +18,9 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Adapter; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; -class ServiceProviderEntityTest extends AbstractEntityTest +class ServiceProviderEntity extends AbstractEntity { /** * This test will test if all methods work diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineBlockServiceProviderTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineBlockServiceProvider.php similarity index 78% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineBlockServiceProviderTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineBlockServiceProvider.php index 69a47c8ed5..5a2b7b32a1 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineBlockServiceProviderTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineBlockServiceProvider.php @@ -18,7 +18,7 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Decorator; use EngineBlock_Attributes_Metadata as AttributesMetadata; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\IndexedService; use OpenConext\EngineBlock\Metadata\RequestedAttribute; use OpenConext\EngineBlock\Metadata\X509\X509Certificate; @@ -26,7 +26,7 @@ use OpenConext\EngineBlockBundle\Url\UrlProvider; use SAML2\Constants; -class EngineBlockServiceProviderTest extends AbstractEntityTest +class EngineBlockServiceProvider extends AbstractEntity { /** * @var \PHPUnit\Framework\MockObject\MockObject|UrlProvider @@ -44,15 +44,20 @@ protected function setUp(): void public function test_methods() { $adapter = $this->createServiceProviderAdapter(); + $matcher = $this->exactly(1); - $this->urlProvider->expects($this->exactly(1)) + $this->urlProvider->expects($matcher) ->method('getUrl') - ->withConsecutive( - // ACS: EngineBlockServiceProvider::getAssertionConsumerServices - ['authentication_sp_consume_assertion', false, null, null] - ) ->willReturnOnConsecutiveCalls( - // ACS - 'acsLocation' + ->willReturnCallback( + function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('authentication_sp_consume_assertion', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'acsLocation'; + } + } ); $certificateMock = $this->createMock(X509Certificate::class); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProvider.php similarity index 69% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProvider.php index bec2697d42..7d14a91fd1 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProvider.php @@ -17,7 +17,7 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Decorator; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\Adapter\IdentityProviderEntity; use OpenConext\EngineBlock\Metadata\Service; use OpenConext\EngineBlock\Metadata\X509\X509Certificate; @@ -25,8 +25,12 @@ use OpenConext\EngineBlockBundle\Url\UrlProvider; use SAML2\Constants; -class EngineblockIdentityProviderTest extends AbstractEntityTest +class EngineblockIdentityProvider extends AbstractEntity { + public function __construct() + { + parent::__construct(static::class); + } /** * @var \PHPUnit\Framework\MockObject\MockObject */ @@ -61,20 +65,25 @@ protected function setUp(): void public function test_methods() { $this->adapter = $this->createIdentityProviderAdapter(); - - $this->urlProvider->expects($this->exactly(2)) - ->method('getUrl') - ->withConsecutive( - // SLO: EngineBlockIdentityProvider::getSingleLogoutService - ['authentication_logout', false, null, null], - // SSO: EngineBlockIdentityProvider::getSingleSignOnServices - ['authentication_idp_sso', false, 'default', null] - ) ->willReturnOnConsecutiveCalls( - // SLO - 'sloLocation', - // SSO - 'ssoLocation' - ); + $matcher = $this->exactly(2); + + $this->urlProvider->expects($matcher) + ->method('getUrl')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('authentication_logout', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'sloLocation'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('authentication_idp_sso', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame('default', $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'ssoLocation'; + } + }); $decorator = new EngineBlockIdentityProvider($this->adapter, 'default', $this->keyPairMock, $this->urlProvider); @@ -120,15 +129,20 @@ public function test_return_null_for_slo_service_if_child_has_no_slo_service_set public function test_do_not_add_entity_id_hash_to_service_url_for_sso_service_if_eb_self() { $this->adapter = $this->createIdentityProviderAdapter(); + $matcher = $this->exactly(1); - $this->urlProvider->expects($this->exactly(1)) + $this->urlProvider->expects($matcher) ->method('getUrl') - ->withConsecutive( - // SSO: EngineBlockIdentityProvider::getSingleSignOnServices - ['authentication_idp_sso', false, 'default', null] // we would expect the fourth paremeter to be null and not 'entity-id' becasue we are EB - ) ->willReturnOnConsecutiveCalls( - // SSO - 'ssoLocation' + ->willReturnCallback( + function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('authentication_idp_sso', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame('default', $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'ssoLocation'; + } + } // we would expect the fourth paremeter to be null and not 'entity-id' becasue we are EB ); $decorator = new EngineBlockIdentityProvider($this->adapter, 'default', $this->keyPairMock, $this->urlProvider); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderInformationTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderInformation.php similarity index 70% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderInformationTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderInformation.php index f00a8c26ee..8c12aa8f90 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderInformationTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockIdentityProviderInformation.php @@ -18,38 +18,42 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Decorator; use OpenConext\EngineBlock\Metadata\ContactPerson; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration; use OpenConext\EngineBlock\Metadata\Logo; use OpenConext\EngineBlock\Metadata\Organization; -use Symfony\Component\Translation\TranslatorInterface; -class EngineblockIdentityProviderInformationTest extends AbstractEntityTest +class EngineblockIdentityProviderInformation extends AbstractEntity { + public function __construct() + { + parent::__construct(static::class); + } public function test_methods() { $adapter = $this->createIdentityProviderAdapter(); - $translator = $this->createMock(TranslatorInterface::class); - $translator->expects($this->at(0)) - ->method('trans') - ->with('suite_name') - ->willReturn('test-suite'); - - $translator->expects($this->at(1)) - ->method('trans') - ->with('metadata_organization_name') - ->willReturn('configuredOrganizationName'); - - $translator->expects($this->at(2)) - ->method('trans') - ->with('metadata_organization_displayname') - ->willReturn('configuredOrganizationDisplayName'); - - $translator->expects($this->at(3)) - ->method('trans') - ->with('metadata_organization_url') - ->willReturn('configuredOrganizationUrl'); + $translator = $this->createMock(\Symfony\Contracts\Translation\TranslatorInterface::class); + $matcher = $this->exactly(4); + $translator->expects($matcher) + ->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('suite_name', $parameters[0]); + return 'test-suite'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('metadata_organization_name', $parameters[0]); + return 'configuredOrganizationName'; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertSame('metadata_organization_displayname', $parameters[0]); + return 'configuredOrganizationDisplayName'; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertSame('metadata_organization_url', $parameters[0]); + return 'configuredOrganizationUrl'; + } + }); $configuration = new EngineBlockConfiguration( $translator, diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockServiceProviderInformationTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockServiceProviderInformation.php similarity index 70% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockServiceProviderInformationTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockServiceProviderInformation.php index b717e9cf76..7808e208ca 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockServiceProviderInformationTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/EngineblockServiceProviderInformation.php @@ -18,39 +18,42 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Decorator; use OpenConext\EngineBlock\Metadata\ContactPerson; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration; use OpenConext\EngineBlock\Metadata\Logo; use OpenConext\EngineBlock\Metadata\Organization; -use Symfony\Component\Translation\TranslatorInterface; -class EngineblockServiceProviderInformationTest extends AbstractEntityTest +class EngineblockServiceProviderInformation extends AbstractEntity { - + public function __construct() + { + parent::__construct(static::class); + } public function test_methods() { $adapter = $this->createServiceProviderAdapter(); - $translator = $this->createMock(TranslatorInterface::class); - $translator->expects($this->at(0)) - ->method('trans') - ->with('suite_name') - ->willReturn('test-suite'); - - $translator->expects($this->at(1)) - ->method('trans') - ->with('metadata_organization_name') - ->willReturn('configuredOrganizationName'); - - $translator->expects($this->at(2)) - ->method('trans') - ->with('metadata_organization_displayname') - ->willReturn('configuredOrganizationDisplayName'); - - $translator->expects($this->at(3)) - ->method('trans') - ->with('metadata_organization_url') - ->willReturn('configuredOrganizationUrl'); + $translator = $this->createMock(\Symfony\Contracts\Translation\TranslatorInterface::class); + $matcher = $this->exactly(4); + $translator->expects($matcher) + ->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('suite_name', $parameters[0]); + return 'test-suite'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('metadata_organization_name', $parameters[0]); + return 'configuredOrganizationName'; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertSame('metadata_organization_displayname', $parameters[0]); + return 'configuredOrganizationDisplayName'; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertSame('metadata_organization_url', $parameters[0]); + return 'configuredOrganizationUrl'; + } + }); $configuration = new EngineBlockConfiguration( $translator, diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ProxiedIdentityProviderTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ProxiedIdentityProvider.php similarity index 68% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ProxiedIdentityProviderTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ProxiedIdentityProvider.php index 0b95e55791..f2bfd0c3e9 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ProxiedIdentityProviderTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ProxiedIdentityProvider.php @@ -18,7 +18,7 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Decorator; use OpenConext\EngineBlock\Metadata\ContactPerson; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\Adapter\IdentityProviderEntity; use OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration; use OpenConext\EngineBlock\Metadata\Service; @@ -26,9 +26,8 @@ use OpenConext\EngineBlock\Metadata\X509\X509KeyPair; use OpenConext\EngineBlockBundle\Url\UrlProvider; use SAML2\Constants; -use Symfony\Component\Translation\TranslatorInterface; -class ProxiedIdentityProviderTest extends AbstractEntityTest +class ProxiedIdentityProvider extends AbstractEntity { /** * @var \PHPUnit\Framework\MockObject\MockObject @@ -100,26 +99,27 @@ public function test_methods() private function createConfiguration(): EngineBlockConfiguration { - $translator = $this->createMock(TranslatorInterface::class); - $translator->expects($this->at(0)) - ->method('trans') - ->with('suite_name') - ->willReturn('test-suite'); - - $translator->expects($this->at(1)) - ->method('trans') - ->with('metadata_organization_name') - ->willReturn('configuredOrganizationName'); - - $translator->expects($this->at(2)) - ->method('trans') - ->with('metadata_organization_displayname') - ->willReturn('configuredOrganizationDisplayName'); - - $translator->expects($this->at(3)) - ->method('trans') - ->with('metadata_organization_url') - ->willReturn('configuredOrganizationUrl'); + $translator = $this->createMock(\Symfony\Contracts\Translation\TranslatorInterface::class); + $matcher = $this->exactly(4); + $translator->expects($matcher) + ->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('suite_name', $parameters[0]); + return 'test-suite'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('metadata_organization_name', $parameters[0]); + return 'configuredOrganizationName'; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertSame('metadata_organization_displayname', $parameters[0]); + return 'configuredOrganizationDisplayName'; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertSame('metadata_organization_url', $parameters[0]); + return 'configuredOrganizationUrl'; + } + }); $configuration = new EngineBlockConfiguration( $translator, @@ -136,14 +136,19 @@ private function createConfiguration(): EngineBlockConfiguration private function configureUrlProvider(): void { - $this->urlProvider->expects($this->exactly(1)) + $matcher = $this->exactly(1); + $this->urlProvider->expects($matcher) ->method('getUrl') - ->withConsecutive( - // SSO: EngineBlockIdentityProvider::getSingleSignOnServices - ['authentication_idp_sso', false, null, 'entity-id'] - )->willReturnOnConsecutiveCalls( - // SSO - 'proxiedSsoLocation' + ->willReturnCallback( + function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('authentication_idp_sso', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame('entity-id', $parameters[3]); + return 'proxiedSsoLocation'; + } + } ); } } diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ServiceProviderStepupTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ServiceProviderStepup.php similarity index 76% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ServiceProviderStepupTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ServiceProviderStepup.php index 98ba41f28e..e423d0262b 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ServiceProviderStepupTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Decorator/ServiceProviderStepup.php @@ -18,7 +18,7 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Decorator; use EngineBlock_Attributes_Metadata as AttributesMetadata; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\IndexedService; use OpenConext\EngineBlock\Metadata\RequestedAttribute; use OpenConext\EngineBlock\Metadata\X509\X509Certificate; @@ -26,7 +26,7 @@ use OpenConext\EngineBlockBundle\Url\UrlProvider; use SAML2\Constants; -class ServiceProviderStepupTest extends AbstractEntityTest +class ServiceProviderStepup extends AbstractEntity { /** @@ -44,15 +44,20 @@ protected function setUp(): void public function test_methods() { $adapter = $this->createServiceProviderAdapter(); + $matcher = $this->exactly(1); - $this->urlProvider->expects($this->exactly(1)) + $this->urlProvider->expects($matcher) ->method('getUrl') - ->withConsecutive( - // ACS: ServiceProviderStepup::getAssertionConsumerServices - ['authentication_stepup_consume_assertion', false, null, null] - ) ->willReturnOnConsecutiveCalls( - // ACS - 'acsLocation' + ->willReturnCallback( + function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('authentication_stepup_consume_assertion', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'acsLocation'; + } + } ); $certificateMock = $this->createMock(X509Certificate::class); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/IdentityProviderFactoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/IdentityProviderFactory.php similarity index 72% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/IdentityProviderFactoryTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/IdentityProviderFactory.php index 809ec179ad..886f19f553 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/IdentityProviderFactoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/IdentityProviderFactory.php @@ -20,7 +20,7 @@ use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use OpenConext\EngineBlock\Metadata\ContactPerson; use OpenConext\EngineBlock\Metadata\Entity\IdentityProvider; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\Adapter\IdentityProviderEntity; use OpenConext\EngineBlock\Metadata\Factory\IdentityProviderEntityInterface; use OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration; @@ -32,7 +32,7 @@ use SAML2\Constants; use Symfony\Component\Translation\TranslatorInterface; -class IdentityProviderFactoryTest extends AbstractEntityTest +class IdentityProviderFactory extends AbstractEntity { use MockeryPHPUnitIntegration; @@ -53,7 +53,7 @@ class IdentityProviderFactoryTest extends AbstractEntityTest */ private $urlProvider; /** - * @var \PHPUnit\Framework\MockObject\MockObject|TranslatorInterface + * @var \PHPUnit\Framework\MockObject\MockObject|\Symfony\Contracts\Translation\TranslatorInterface */ private $translator; @@ -62,7 +62,7 @@ public function setUp(): void $this->keyPairFactory = $this->createMock(KeyPairFactory::class); $this->configuration = $this->createMock(EngineBlockConfiguration::class); $this->urlProvider = $this->createMock(UrlProvider::class); - $this->translator = $this->createMock(TranslatorInterface::class); + $this->translator = $this->createMock(\Symfony\Contracts\Translation\TranslatorInterface::class); $this->factory = new IdentityProviderFactory($this->keyPairFactory, $this->configuration, $this->urlProvider); } @@ -71,8 +71,6 @@ public function test_create_entity_from() { $entity = $this->factory->createEngineBlockEntityFrom( 'entityID', - 'ssoLocation', - 'default' ); $this->assertInstanceOf(IdentityProviderEntityInterface::class, $entity); @@ -88,25 +86,28 @@ public function test_create_proxy_from_entity() public function test_create_idp_entity_from_entity_properties() { - $this->translator->expects($this->at(0)) - ->method('trans') - ->with('suite_name') - ->willReturn('test-suite'); - - $this->translator->expects($this->at(1)) - ->method('trans') - ->with('metadata_organization_name') - ->willReturn('configuredOrganizationName'); - - $this->translator->expects($this->at(2)) - ->method('trans') - ->with('metadata_organization_displayname') - ->willReturn('configuredOrganizationDisplayName'); - - $this->translator->expects($this->at(3)) - ->method('trans') - ->with('metadata_organization_url') - ->willReturn('configuredOrganizationUrl'); + // Replaced deprecated $this->at(n) expectations with a single batched expectation + $matcher = $this->exactly(4); + // Replaced deprecated $this->at(n) expectations with a single batched expectation + $this->translator->expects($matcher) + ->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('suite_name', $parameters[0]); + return 'test-suite'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('metadata_organization_name', $parameters[0]); + return 'configuredOrganizationName'; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertSame('metadata_organization_displayname', $parameters[0]); + return 'configuredOrganizationDisplayName'; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertSame('metadata_organization_url', $parameters[0]); + return 'configuredOrganizationUrl'; + } + }); $this->configuration = new EngineBlockConfiguration( $this->translator, @@ -139,15 +140,20 @@ public function test_create_idp_entity_from_entity_properties() ContactPerson::from('technical', 'configuredOrganizationName', 'Support', 'configuredSupportMail'), ContactPerson::from('administrative', 'configuredOrganizationName', 'Support', 'configuredSupportMail'), ]; + $matcher = $this->exactly(1); - $this->urlProvider->expects($this->exactly(1)) + $this->urlProvider->expects($matcher) ->method('getUrl') - ->withConsecutive( - // SSO: EngineBlockIdentityProvider::getSingleSignOnServices - ['authentication_idp_sso', false, 'default', 'entity-id'] - ) ->willReturnOnConsecutiveCalls( - // SSO - 'proxiedSsoLocation' + ->willReturnCallback( + function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('authentication_idp_sso', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame('default', $parameters[2]); + $this->assertSame('entity-id', $parameters[3]); + return 'proxiedSsoLocation'; + } + } ); $supportedNameIdFormats = [ @@ -172,7 +178,7 @@ public function test_create_idp_entity_from_entity_properties() $overrides['contactPersons'] = $contactPersons; // EngineBlockIdentityProvider - $overrides['certificates'] = [$this->certificateMock]; + $overrides['certificates'] = [null]; $overrides['supportedNameIdFormats'] = $supportedNameIdFormats; $overrides['singleSignOnServices'] = [new Service('proxiedSsoLocation', Constants::BINDING_HTTP_REDIRECT)]; $overrides['singleLogoutService'] = new Service(null, null); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/ServiceProviderFactoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/ServiceProviderFactory.php similarity index 79% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/ServiceProviderFactoryTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/ServiceProviderFactory.php index ef4eefaa0b..6054b64c06 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/ServiceProviderFactoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Factory/ServiceProviderFactory.php @@ -23,7 +23,7 @@ use OpenConext\EngineBlock\Metadata\Coins; use OpenConext\EngineBlock\Metadata\ContactPerson; use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\ServiceProviderEntityInterface; use OpenConext\EngineBlock\Metadata\Factory\ValueObject\EngineBlockConfiguration; use OpenConext\EngineBlock\Metadata\IndexedService; @@ -39,9 +39,8 @@ use PHPUnit\Framework\MockObject\MockObject; use RobRichards\XMLSecLibs\XMLSecurityKey; use SAML2\Constants; -use Symfony\Component\Translation\TranslatorInterface; -class ServiceProviderFactoryTest extends AbstractEntityTest +class ServiceProviderFactory extends AbstractEntity { /** * @var ServiceProviderFactory @@ -91,7 +90,7 @@ public function setUp(): void $this->entityIdOverride ); - $this->translator = $this->createMock(TranslatorInterface::class); + $this->translator = $this->createMock(\Symfony\Contracts\Translation\TranslatorInterface::class); } public function test_create_engineblock_entity_from() @@ -114,25 +113,26 @@ public function test_create_stepup_entity_from() public function test_eb_properties() { - $this->translator->expects($this->at(0)) - ->method('trans') - ->with('suite_name') - ->willReturn('test-suite'); - - $this->translator->expects($this->at(1)) - ->method('trans') - ->with('metadata_organization_name') - ->willReturn('configuredOrganizationName'); - - $this->translator->expects($this->at(2)) - ->method('trans') - ->with('metadata_organization_displayname') - ->willReturn('configuredOrganizationDisplayName'); - - $this->translator->expects($this->at(3)) - ->method('trans') - ->with('metadata_organization_url') - ->willReturn('configuredOrganizationUrl'); + $matcher = $this->exactly(4); + $this->translator->expects($matcher) + ->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('suite_name', $parameters[0]); + return 'test-suite'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('metadata_organization_name', $parameters[0]); + return 'configuredOrganizationName'; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertSame('metadata_organization_displayname', $parameters[0]); + return 'configuredOrganizationDisplayName'; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertSame('metadata_organization_url', $parameters[0]); + return 'configuredOrganizationUrl'; + } + }); $this->configuration = new EngineBlockConfiguration( $this->translator, @@ -159,20 +159,25 @@ public function test_eb_properties() ]; $this->attributes->method('getRequestedAttributes') ->willReturn($attributes); - - $this->urlProvider->expects($this->exactly(2)) - ->method('getUrl') - ->withConsecutive( - // EntityId: EngineBlockServiceProvider::getEntityId - ['metadata_sp', false, null, null], - // ACS: EngineBlockServiceProvider::getAssertionConsumerService - ['authentication_sp_consume_assertion', false, null, null] - )->willReturnOnConsecutiveCalls( - // EntityId - 'EbEntityId', - // ACS - 'proxiedAcsLocation' - ); + $matcher = $this->exactly(2); + + $this->urlProvider->expects($matcher) + ->method('getUrl')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('metadata_sp', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'EbEntityId'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('authentication_sp_consume_assertion', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'proxiedAcsLocation'; + } + }); $this->factory = new ServiceProviderFactory( $this->attributes, @@ -286,25 +291,26 @@ public function test_eb_properties() public function test_stepup_properties() { - $this->translator->expects($this->at(0)) - ->method('trans') - ->with('suite_name') - ->willReturn('test-suite'); - - $this->translator->expects($this->at(1)) - ->method('trans') - ->with('metadata_organization_name') - ->willReturn('configuredOrganizationName'); - - $this->translator->expects($this->at(2)) - ->method('trans') - ->with('metadata_organization_displayname') - ->willReturn('configuredOrganizationDisplayName'); - - $this->translator->expects($this->at(3)) - ->method('trans') - ->with('metadata_organization_url') - ->willReturn('configuredOrganizationUrl'); + $matcher = $this->exactly(4); + $this->translator->expects($matcher) + ->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('suite_name', $parameters[0]); + return 'test-suite'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('metadata_organization_name', $parameters[0]); + return 'configuredOrganizationName'; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertSame('metadata_organization_displayname', $parameters[0]); + return 'configuredOrganizationDisplayName'; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertSame('metadata_organization_url', $parameters[0]); + return 'configuredOrganizationUrl'; + } + }); $this->configuration = new EngineBlockConfiguration( $this->translator, @@ -331,21 +337,26 @@ public function test_stepup_properties() ]; $this->attributes->method('getRequestedAttributes') ->willReturn($attributes); - - - $this->urlProvider->expects($this->exactly(2)) - ->method('getUrl') - ->withConsecutive( - // EntityId - ['metadata_stepup', false, null, null], - // ACS: ServiceProvider::getAssertionConsumerService - ['authentication_stepup_consume_assertion', false, null, null] - )->willReturnOnConsecutiveCalls( - // EntityId - 'StepupEntityId', - // ACS - 'proxiedAcsLocation' - ); + $matcher = $this->exactly(2); + + + $this->urlProvider->expects($matcher) + ->method('getUrl')->willReturnCallback(function (...$parameters) use ($matcher) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('metadata_stepup', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'StepupEntityId'; + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertSame('authentication_stepup_consume_assertion', $parameters[0]); + $this->assertSame(false, $parameters[1]); + $this->assertSame(null, $parameters[2]); + $this->assertSame(null, $parameters[3]); + return 'proxiedAcsLocation'; + } + }); $this->factory = new ServiceProviderFactory( $this->attributes, diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockIdentityProviderMetadataTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockIdentityProviderMetadata.php similarity index 94% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockIdentityProviderMetadataTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockIdentityProviderMetadata.php index b320e3b586..74f988d6e6 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockIdentityProviderMetadataTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockIdentityProviderMetadata.php @@ -18,15 +18,19 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Helper; use Mockery; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\Adapter\IdentityProviderEntity; use OpenConext\EngineBlock\Metadata\Organization; use OpenConext\EngineBlock\Metadata\Service; use OpenConext\EngineBlock\Metadata\X509\X509Certificate; use OpenConext\EngineBlockBundle\Localization\LanguageSupportProvider; -class EngineBlockIdentityProviderMetadataTest extends AbstractEntityTest +class EngineBlockIdentityProviderMetadata extends AbstractEntity { + public function __construct() + { + parent::__construct(static::class); + } use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; /** * @var LanguageSupportProvider diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockServiceProviderMetadataTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockServiceProviderMetadata.php similarity index 95% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockServiceProviderMetadataTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockServiceProviderMetadata.php index b8b9c43d4b..b74d25f3d7 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockServiceProviderMetadataTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/EngineBlockServiceProviderMetadata.php @@ -17,7 +17,7 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Helper; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\Adapter\ServiceProviderEntity; use OpenConext\EngineBlock\Metadata\IndexedService; use Mockery; @@ -25,8 +25,12 @@ use OpenConext\EngineBlock\Metadata\X509\X509Certificate; use OpenConext\EngineBlockBundle\Localization\LanguageSupportProvider; -class EngineBlockServiceProviderMetadataTest extends AbstractEntityTest +class EngineBlockServiceProviderMetadata extends AbstractEntity { + public function __construct() + { + parent::__construct(static::class); + } /** * @var LanguageSupportProvider */ diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/IdentityProviderNameFallbackHelperTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/IdentityProviderNameFallbackHelper.php similarity index 94% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/IdentityProviderNameFallbackHelperTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/IdentityProviderNameFallbackHelper.php index 3a3a71cb8b..aaddf13220 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/IdentityProviderNameFallbackHelperTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/Helper/IdentityProviderNameFallbackHelper.php @@ -17,10 +17,10 @@ namespace OpenConext\EngineBlock\Metadata\Factory\Helper; -use OpenConext\EngineBlock\Metadata\Factory\AbstractEntityTest; +use OpenConext\EngineBlock\Metadata\Factory\AbstractEntity; use OpenConext\EngineBlock\Metadata\Factory\Adapter\IdentityProviderEntity; -class IdentityProviderNameFallbackHelperTest extends AbstractEntityTest +class IdentityProviderNameFallbackHelper extends AbstractEntity { /** * @var IdentityProviderEntity|null diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/IdentityProviderEntityInterfaceTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/IdentityProviderEntityInterface.php similarity index 96% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/IdentityProviderEntityInterfaceTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/IdentityProviderEntityInterface.php index 960c914a9e..bfaf7e0202 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/IdentityProviderEntityInterfaceTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/IdentityProviderEntityInterface.php @@ -17,7 +17,7 @@ namespace OpenConext\EngineBlock\Metadata\Factory; -class IdentityProviderEntityInterfaceTest extends AbstractEntityTest +class IdentityProviderEntityInterface extends AbstractEntity { /** * This test will test if all parameters in the old mutable entity are implemented diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ServiceProviderEntityinterfaceTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ServiceProviderEntityinterface.php similarity index 92% rename from tests/unit/OpenConext/EngineBlock/Metadata/Factory/ServiceProviderEntityinterfaceTest.php rename to tests/unit/OpenConext/EngineBlock/Metadata/Factory/ServiceProviderEntityinterface.php index f23402d0d6..34618fd16b 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ServiceProviderEntityinterfaceTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ServiceProviderEntityinterface.php @@ -17,8 +17,12 @@ namespace OpenConext\EngineBlock\Metadata\Factory; -class ServiceProviderEntityinterfaceTest extends AbstractEntityTest +class ServiceProviderEntityinterface extends AbstractEntity { + public function __construct() + { + parent::__construct(static::class); + } /** * This test will test if all parameters in the old mutable entity are implemented */ diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfigurationTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfigurationTest.php index a2bc6b1622..f18cba6256 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfigurationTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/Factory/ValueObject/EngineBlockConfigurationTest.php @@ -37,7 +37,7 @@ public function test_configuration_creation() $orgName = 'OpenestConext Company'; $orgDisplayName = 'OpenestConext Company Inc.'; - $translator = m::mock(TranslatorInterface::class); + $translator = m::mock(\Symfony\Contracts\Translation\TranslatorInterface::class); $translator ->shouldReceive('trans') ->with('suite_name')->once() diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/LoaRepositoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/LoaRepositoryTest.php index 79e70aa74a..9f1242f29d 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/LoaRepositoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/LoaRepositoryTest.php @@ -69,9 +69,7 @@ public function test_the_getter_only_returns_eb_loas() } } - /** - * @dataProvider provideInvalidConfig - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideInvalidConfig')] public function test_it_raises_exceptions_when_constructed_with_invalid_configuration( $config, $expectedExceptionMessage @@ -91,7 +89,7 @@ private function getValidConfigAsArray() ]; } - public function provideInvalidConfig() + public static function provideInvalidConfig() { return [ [[10 => ['engineBlock' => 'loa1', 'gateway' => 'loa1']], 'Both the engineblock and gateway keys must be present in every LoA mapping.'], diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/LoaTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/LoaTest.php index fe1671d7b9..99cb080eb1 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/LoaTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/LoaTest.php @@ -24,9 +24,7 @@ class LoaTest extends TestCase { - /** - * @dataProvider provideValidLoaParameters - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideValidLoaParameters')] public function test_loa_happy_flow(int $level, string $identifier, $expectationDescription) { $loa = Loa::create($level, $identifier); @@ -35,18 +33,14 @@ public function test_loa_happy_flow(int $level, string $identifier, $expectation $this->assertEquals($identifier, $loa->getIdentifier(), $expectationDescription); } - /** - * @dataProvider provideInvalidLoaParameters - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideInvalidLoaParameters')] public function test_loa_sad_flow($level, $identifier, $expectedException) { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage($expectedException); Loa::create($level, $identifier); } - /** - * @dataProvider provideErrorneousLoaParameters - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideErrorneousLoaParameters')] public function test_loa_errors($level, $identifier) { $this->expectException(TypeError::class); @@ -78,7 +72,7 @@ public function test_loa_can_be_compared_to_other_loa() $this->assertFalse($loa1->levelIsHigherOrEqualTo($loa3)); } - public function provideValidLoaParameters() + public static function provideValidLoaParameters() { return [ [10, 'https://vm.openconext.nl/loa1', 'A level 1 LoA'], @@ -88,7 +82,7 @@ public function provideValidLoaParameters() ]; } - public function provideInvalidLoaParameters() + public static function provideInvalidLoaParameters() { return [ [0, 'https://vm.openconext.nl/loa1', 'Please provide a valid level. Acceptable LoA levels are "10, 15, 20, 30"'], @@ -99,7 +93,7 @@ public function provideInvalidLoaParameters() ]; } - public function provideErrorneousLoaParameters() + public static function provideErrorneousLoaParameters() { return [ [9999999999999999999999999999, 'https://vm.openconext.nl/loa1', 'The LoA level must be an integer value'], diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/LogoTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/LogoTest.php index bfb77da2ee..2394119763 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/LogoTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/LogoTest.php @@ -26,8 +26,8 @@ class LogoTest extends TestCase { /** * @param string $json - * @dataProvider provideCorrectJson */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideCorrectJson')] public function test_create_logo_from_json_happy_flow(string $json): void { $jsonData = json_decode($json, true); @@ -48,8 +48,8 @@ public function test_create_logo_from_json_happy_flow(string $json): void /** * @param string $json - * @dataProvider provideUrlMissingJson */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideUrlMissingJson')] public function test_create_logo_from_json_requires_url(string $json): void { self::expectException(MduiRuntimeException::class); @@ -75,7 +75,7 @@ public function test_primary_language_is_en() } - public function provideCorrectJson() + public static function provideCorrectJson() { return [ 'all data present' => ['{"url": "https://logo.example.com/logo.gif", "height": 12, "width": 50}'], @@ -87,7 +87,7 @@ public function provideCorrectJson() ]; } - public function provideUrlMissingJson() + public static function provideUrlMissingJson() { return [ 'url not present' => ['{"height": 12, "width": 50}'], diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepositoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepositoryTest.php index 67844bf8fb..8be5d50106 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepositoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/CachedDoctrineMetadataRepositoryTest.php @@ -22,15 +22,17 @@ use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface; use OpenConext\EngineBlock\Metadata\MetadataRepository\Visitor\VisitorInterface; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; class CachedDoctrineMetadataRepositoryTest extends TestCase { use MockeryPHPUnitIntegration; + #[DoesNotPerformAssertions] public function testMethodsCallsAreProxied() { - $doctrineRepository = Mockery::mock('OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository'); + $doctrineRepository = Mockery::mock(\OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository::class); $doctrineRepository->shouldReceive('findIdentityProviderByEntityId'); $doctrineRepository->shouldReceive('findServiceProviderByEntityId'); $doctrineRepository->shouldReceive('findIdentityProviderByEntityId'); @@ -51,7 +53,7 @@ public function testMethodsCallsAreProxied() public function testFetchIdentityProviderThrowExceptions() { - $doctrineRepository = Mockery::mock('OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository'); + $doctrineRepository = Mockery::mock(\OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository::class); $doctrineRepository->shouldReceive('findIdentityProviderByEntityId'); $this->expectException(EntityNotFoundException::class); @@ -62,7 +64,7 @@ public function testFetchIdentityProviderThrowExceptions() public function testFetchServiceProviderThrowExceptions() { - $doctrineRepository = Mockery::mock('OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository'); + $doctrineRepository = Mockery::mock(\OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository::class); $doctrineRepository->shouldReceive('findServiceProviderByEntityId'); $this->expectException(EntityNotFoundException::class); @@ -71,9 +73,10 @@ public function testFetchServiceProviderThrowExceptions() $repository->fetchServiceProviderByEntityId('test'); } + #[DoesNotPerformAssertions] public function testAppendVisitor() { - $doctrineRepository = Mockery::mock('OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository'); + $doctrineRepository = Mockery::mock(\OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository::class); $doctrineRepository->shouldReceive('appendVisitor'); $repository = new CachedDoctrineMetadataRepository($doctrineRepository); @@ -82,9 +85,10 @@ public function testAppendVisitor() ); } + #[DoesNotPerformAssertions] public function testAppendFilter() { - $doctrineRepository = Mockery::mock('OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository'); + $doctrineRepository = Mockery::mock(\OpenConext\EngineBlock\Metadata\MetadataRepository\DoctrineMetadataRepository::class); $doctrineRepository->shouldReceive('appendFilter'); $repository = new CachedDoctrineMetadataRepository($doctrineRepository); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataRepositoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataRepositoryTest.php index 6827fa852d..e71381bdfb 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataRepositoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/DoctrineMetadataRepositoryTest.php @@ -31,21 +31,21 @@ class DoctrineMetadataRepositoryTest extends TestCase public function testFindIdentityProviders() { - $mockQueryBuilder = Mockery::mock('Doctrine\ORM\QueryBuilder'); + $mockQueryBuilder = Mockery::mock(\Doctrine\ORM\QueryBuilder::class); $mockQueryBuilder ->shouldReceive('getQuery->execute') ->andReturn([new IdentityProvider('https://idp.entity.com')]); - $mockSpRepository = Mockery::mock('Doctrine\ORM\EntityRepository'); - $mockIdpRepository = Mockery::mock('Doctrine\ORM\EntityRepository'); + $mockSpRepository = Mockery::mock(\Doctrine\ORM\EntityRepository::class); + $mockIdpRepository = Mockery::mock(\Doctrine\ORM\EntityRepository::class); $mockIdpRepository ->shouldReceive('getClassName') - ->andReturn('OpenConext\EngineBlock\Metadata\Entity\IdentityProvider') + ->andReturn(\OpenConext\EngineBlock\Metadata\Entity\IdentityProvider::class) ->shouldReceive('createQueryBuilder') ->andReturn($mockQueryBuilder); $repository = new DoctrineMetadataRepository( - Mockery::mock('Doctrine\ORM\EntityManager'), + Mockery::mock(\Doctrine\ORM\EntityManager::class), $mockSpRepository, $mockIdpRepository ); @@ -55,7 +55,7 @@ public function testFindIdentityProviders() public function testFindIdentityProvidersVisitor() { - $mockQueryBuilder = Mockery::mock('Doctrine\ORM\QueryBuilder'); + $mockQueryBuilder = Mockery::mock(\Doctrine\ORM\QueryBuilder::class); $mockQueryBuilder ->shouldReceive('getQuery->execute') ->andReturn([ @@ -63,16 +63,16 @@ public function testFindIdentityProvidersVisitor() new IdentityProvider('https://unconnected.entity.com') ]); - $mockSpRepository = Mockery::mock('Doctrine\ORM\EntityRepository'); - $mockIdpRepository = Mockery::mock('Doctrine\ORM\EntityRepository'); + $mockSpRepository = Mockery::mock(\Doctrine\ORM\EntityRepository::class); + $mockIdpRepository = Mockery::mock(\Doctrine\ORM\EntityRepository::class); $mockIdpRepository ->shouldReceive('getClassName') - ->andReturn('OpenConext\EngineBlock\Metadata\Entity\IdentityProvider') + ->andReturn(\OpenConext\EngineBlock\Metadata\Entity\IdentityProvider::class) ->shouldReceive('createQueryBuilder') ->andReturn($mockQueryBuilder); $repository = new DoctrineMetadataRepository( - Mockery::mock('Doctrine\ORM\EntityManager'), + Mockery::mock(\Doctrine\ORM\EntityManager::class), $mockSpRepository, $mockIdpRepository ); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/FilterCollectionTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/FilterCollectionTest.php index 8eb1f7a908..1707d8684c 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/FilterCollectionTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/FilterCollectionTest.php @@ -29,14 +29,14 @@ class FilterCollectionTest extends TestCase public function testFilterRoleFailure() { $mockFilter = Mockery::mock( - 'OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface' + \OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface::class ); $mockFilter->shouldReceive('filterRole')->andReturnNull(); $mockFilter->shouldReceive('__toString')->andReturn('MockFilter'); $mockRole = Mockery::mock( - 'OpenConext\EngineBlock\Metadata\Entity\AbstractRole' + \OpenConext\EngineBlock\Metadata\Entity\AbstractRole::class ); $collection = new CompositeFilter(); @@ -49,19 +49,19 @@ public function testFilterRoleFailure() public function testFilterExport() { $mockFilter = Mockery::mock( - 'OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface' + \OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface::class ); $mockFilter->shouldReceive('toQueryBuilder'); $collection = new CompositeFilter(); $collection->add($mockFilter); - $queryBuilderMock = Mockery::mock('Doctrine\ORM\QueryBuilder'); + $queryBuilderMock = Mockery::mock(\Doctrine\ORM\QueryBuilder::class); $this->assertEquals( $queryBuilderMock, $collection->toQueryBuilder( $queryBuilderMock, - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider' + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class ) ); } diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveOtherWorkflowStatesFilterTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveOtherWorkflowStatesFilterTest.php index 05d7788575..3360f4ae5f 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveOtherWorkflowStatesFilterTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/Filter/RemoveOtherWorkflowStatesFilterTest.php @@ -25,44 +25,44 @@ use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; -class RemoveOtherWorkflowStatesTest extends TestCase +class RemoveOtherWorkflowStatesFilterTest extends TestCase { use MockeryPHPUnitIntegration; public function testRemoveOtherWorkflowState() { $prodSp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://prod.sp.example.edu', 'workflowState' => ServiceProvider::WORKFLOW_STATE_PROD) ); $filter = new RemoveOtherWorkflowStatesFilter($prodSp, 'idp', 'sp'); $prodIdp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://prod.idp.example.edu', 'workflowState' => ServiceProvider::WORKFLOW_STATE_PROD) ); $this->assertNotNull($filter->filterRole($prodIdp)); $testIdp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://test.idp.example.edu', 'workflowState' => ServiceProvider::WORKFLOW_STATE_PROD) ); $this->assertNotNull($filter->filterRole($testIdp)); $prodSp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://prod.sp.example.edu', 'workflowState' => ServiceProvider::WORKFLOW_STATE_PROD) ); $this->assertNotNull($filter->filterRole($prodSp)); $testSp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://test.sp.example.edu', 'workflowState' => ServiceProvider::WORKFLOW_STATE_TEST) ); $this->assertNull($filter->filterRole($testSp)); $buggyIdp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://buggy.idp.example.edu', 'workflowState' => '') ); $this->assertNull($filter->filterRole($buggyIdp)); @@ -76,12 +76,12 @@ public function testLogging() ->with('Dissimilar workflow states (OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\RemoveOtherWorkflowStatesFilter -> prodaccepted)'); $prodSp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://prod.sp.example.edu', 'workflowState' => ServiceProvider::WORKFLOW_STATE_PROD) ); $filter = new RemoveOtherWorkflowStatesFilter($prodSp, 'idp', 'sp'); $buggyIdp = Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\ServiceProvider', + \OpenConext\EngineBlock\Metadata\Entity\ServiceProvider::class, array('entityId' => 'https://buggy.idp.example.edu', 'workflowState' => '') ); $this->assertNull($filter->filterRole($buggyIdp, $mockLogger)); diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/InMemoryMetadataRepositoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/InMemoryMetadataRepositoryTest.php index c88fdbc8ee..87e581f4a4 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/InMemoryMetadataRepositoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/MetadataRepository/InMemoryMetadataRepositoryTest.php @@ -30,7 +30,7 @@ * Class MetadataRepositoryTest * @package OpenConext\EngineBlock\Metadata\MetadataRepository */ -class MetadataRepositoryTest extends TestCase +class InMemoryMetadataRepositoryTest extends TestCase { const MOCK_IDP_NAME = 'https://idp.example.edu'; @@ -108,7 +108,7 @@ public function testFilterApplication() $repository = $this->getFilledRepository(); $mockFilter = Mockery::mock( - 'OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface' + \OpenConext\EngineBlock\Metadata\MetadataRepository\Filter\FilterInterface::class ); $mockFilter->shouldReceive('filterRole')->andReturnNull(); $repository->appendFilter($mockFilter); @@ -132,7 +132,7 @@ public function testVisitorApplication() $repository = $this->getFilledRepository(); $visitor = Mockery::mock( - 'OpenConext\EngineBlock\Metadata\MetadataRepository\Visitor\VisitorInterface' + \OpenConext\EngineBlock\Metadata\MetadataRepository\Visitor\VisitorInterface::class ); $visitor->shouldReceive('visitIdentityProvider')->andReturnUsing( function (IdentityProvider $idp) { @@ -160,7 +160,7 @@ private function getFilledRepository() $repository = new InMemoryMetadataRepository( array( Utils::instantiate( - 'OpenConext\EngineBlock\Metadata\Entity\IdentityProvider', + \OpenConext\EngineBlock\Metadata\Entity\IdentityProvider::class, array( 'entityId' => 'https://idp1.example.edu', 'schacHomeOrganization'=> 'idp1.example.edu' diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/MfaEntityFactoryTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/MfaEntityFactoryTest.php index a90363e9a4..a563341e17 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/MfaEntityFactoryTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/MfaEntityFactoryTest.php @@ -39,9 +39,7 @@ public function test_it_distinguishes_between_regular_and_transparent_entities_f $this->assertInstanceOf(MfaEntity::class, MfaEntityFactory::fromJson($data)); } - /** - * @dataProvider provideInvalidJsonData - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideInvalidJsonData')] public function test_from_json_factory_method_performs_input_validation($data, $expectedMessage) { $this->expectException(\InvalidArgumentException::class); @@ -49,7 +47,7 @@ public function test_from_json_factory_method_performs_input_validation($data, $ MfaEntityFactory::fromJson($data); } - public function provideInvalidJsonData() + public static function provideInvalidJsonData() { yield [['entityId' => null, 'level' => 'transparent_authn_context'], 'MFA entityId must be of type string']; yield [['entityId' => 0, 'level' => 'transparent_authn_context'], 'MFA entityId must be of type string']; diff --git a/tests/unit/OpenConext/EngineBlock/Metadata/X509/X509PublicKeyTest.php b/tests/unit/OpenConext/EngineBlock/Metadata/X509/X509PublicKeyTest.php index 24b23b7f3b..9e73b16495 100644 --- a/tests/unit/OpenConext/EngineBlock/Metadata/X509/X509PublicKeyTest.php +++ b/tests/unit/OpenConext/EngineBlock/Metadata/X509/X509PublicKeyTest.php @@ -21,11 +21,12 @@ use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use PHPUnit\Framework\TestCase; -class X509KeyTest extends TestCase +class X509PublicKeyTest extends TestCase { use MockeryPHPUnitIntegration; private $filePath; + private string $filePath2; public function setUp(): void { diff --git a/tests/unit/OpenConext/EngineBlock/Request/RequestIdTest.php b/tests/unit/OpenConext/EngineBlock/Request/RequestIdTest.php index 7087af1fd2..faaa58b1a6 100644 --- a/tests/unit/OpenConext/EngineBlock/Request/RequestIdTest.php +++ b/tests/unit/OpenConext/EngineBlock/Request/RequestIdTest.php @@ -26,16 +26,14 @@ class RequestIdTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlock - * @group Request - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Request')] + #[\PHPUnit\Framework\Attributes\Test] public function request_id_is_unchanged_after_first_retrieval() { $generatedId = 'generated_id'; - $requestIdGenerator = m::mock('OpenConext\EngineBlock\Request\RequestIdGenerator'); + $requestIdGenerator = m::mock(\OpenConext\EngineBlock\Request\RequestIdGenerator::class); $requestIdGenerator->shouldReceive('generateRequestId') ->once() ->andReturn($generatedId); diff --git a/tests/unit/OpenConext/EngineBlock/Service/ConsentServiceTest.php b/tests/unit/OpenConext/EngineBlock/Service/ConsentServiceTest.php index b5f42497c4..9e77de6c2d 100644 --- a/tests/unit/OpenConext/EngineBlock/Service/ConsentServiceTest.php +++ b/tests/unit/OpenConext/EngineBlock/Service/ConsentServiceTest.php @@ -24,6 +24,7 @@ use OpenConext\EngineBlock\Authentication\Repository\ConsentRepository; use OpenConext\EngineBlock\Authentication\Value\CollabPersonId; use OpenConext\EngineBlock\Authentication\Value\CollabPersonUuid; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -63,11 +64,10 @@ public function setUp(): void ); } - /** - * @test - * @group EngineBlock - * @group Consent - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Consent')] + #[\PHPUnit\Framework\Attributes\Test] + #[DoesNotPerformAssertions] public function remove_consent_by_collab_person_id_and_sp_entity_id() { $this->consentRepository->shouldReceive('deleteOneFor') diff --git a/tests/unit/OpenConext/EngineBlock/Service/DeprovisionServiceTest.php b/tests/unit/OpenConext/EngineBlock/Service/DeprovisionServiceTest.php index fa4de9943c..4d19051400 100644 --- a/tests/unit/OpenConext/EngineBlock/Service/DeprovisionServiceTest.php +++ b/tests/unit/OpenConext/EngineBlock/Service/DeprovisionServiceTest.php @@ -29,6 +29,7 @@ use OpenConext\EngineBlockBundle\Authentication\Entity\ServiceProviderUuid; use OpenConext\EngineBlockBundle\Authentication\Repository\SamlPersistentIdRepository; use OpenConext\EngineBlockBundle\Authentication\Repository\ServiceProviderUuidRepository; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; class DeprovisionServiceTest extends TestCase @@ -73,11 +74,9 @@ public function setUp(): void ); } - /** - * @test - * @group EngineBlock - * @group Deprovision - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function read_returns_all_user_data() { $this->userDirectory->shouldReceive('findUserBy') @@ -137,11 +136,9 @@ public function read_returns_all_user_data() $this->assertEquals(['data' => 'consent3'], $result[2]['value'][2]); } - /** - * @test - * @group EngineBlock - * @group Deprovision - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function read_returns_empty_result_for_unknown_user() { $this->userDirectory->shouldReceive('findUserBy') @@ -162,11 +159,9 @@ public function read_returns_empty_result_for_unknown_user() $this->assertEmpty($result); } - /** - * @test - * @group EngineBlock - * @group Deprovision - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] public function read_returns_user_data_without_consent_or_persistent_id() { $this->userDirectory->shouldReceive('findUserBy') @@ -206,11 +201,10 @@ public function read_returns_user_data_without_consent_or_persistent_id() $this->assertEmpty($result[2]['value']); } - /** - * @test - * @group EngineBlock - * @group Deprovision - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Group('Deprovision')] + #[\PHPUnit\Framework\Attributes\Test] + #[DoesNotPerformAssertions] public function delete_deprovisions_all_user_data() { $this->userDirectory->shouldReceive('findUserBy') diff --git a/tests/unit/OpenConext/EngineBlock/Service/MfaHelperTest.php b/tests/unit/OpenConext/EngineBlock/Service/MfaHelperTest.php index 71c2a27e7a..8af75f0e61 100644 --- a/tests/unit/OpenConext/EngineBlock/Service/MfaHelperTest.php +++ b/tests/unit/OpenConext/EngineBlock/Service/MfaHelperTest.php @@ -44,10 +44,8 @@ public function setUp(): void $this->mfaHelper = new MfaHelper($logger, $this->repo); } - /** - * @test - * @group EngineBlock - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Test] public function happy_flow() { $spEntityId = 'arbitrarySpEntityId'; @@ -57,10 +55,8 @@ public function happy_flow() self::assertTrue($isTransparent); } - /** - * @test - * @group EngineBlock - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Test] public function not_transparent_mfa_entity() { $spEntityId = 'arbitrarySpEntityId'; @@ -70,10 +66,8 @@ public function not_transparent_mfa_entity() self::assertFalse($isTransparent); } - /** - * @test - * @group EngineBlock - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Test] public function not_an_mfa_entity() { $spEntityId = 'arbitrarySpEntityId'; @@ -83,10 +77,8 @@ public function not_an_mfa_entity() self::assertFalse($isTransparent); } - /** - * @test - * @group EngineBlock - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Test] public function idp_not_found() { $spEntityId = 'arbitrarySpEntityId'; diff --git a/tests/unit/OpenConext/EngineBlock/Service/ReleaseAsEnforcerTest.php b/tests/unit/OpenConext/EngineBlock/Service/ReleaseAsEnforcerTest.php index 72cbadda65..810a445865 100644 --- a/tests/unit/OpenConext/EngineBlock/Service/ReleaseAsEnforcerTest.php +++ b/tests/unit/OpenConext/EngineBlock/Service/ReleaseAsEnforcerTest.php @@ -38,9 +38,7 @@ protected function tearDown(): void m::close(); } - /** - * @dataProvider enforceDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('enforceDataProvider')] public function testEnforce($attributes, $releaseAsOverrides, $expectedResult, $expectedLogMessages) { foreach ($expectedLogMessages as $message) { @@ -57,9 +55,7 @@ public function testEnforce($attributes, $releaseAsOverrides, $expectedResult, $ } - /** - * @dataProvider enforceDataProviderWarnings - */ + #[\PHPUnit\Framework\Attributes\DataProvider('enforceDataProviderWarnings')] public function testEnforceImpossible($attributes, $releaseAsOverrides, $expectedResult, $expectedLogMessage) { $this->logger->shouldReceive('warning')->with($expectedLogMessage); @@ -67,7 +63,7 @@ public function testEnforceImpossible($attributes, $releaseAsOverrides, $expecte $this->assertEquals($expectedResult, $result); } - public function enforceDataProvider() + public static function enforceDataProvider() { return [ 'single attribute override' => [ @@ -206,7 +202,7 @@ public function enforceDataProvider() ]; } - public function enforceDataProviderWarnings() + public static function enforceDataProviderWarnings() { return [ 'targeted attribute value is set to null in assertion' => [ @@ -234,7 +230,7 @@ public function enforceDataProviderWarnings() "urn:mace:dir:attribute-def:givenName" => ["Ad"], "urn:mace:dir:attribute-def:mail" => ["ad@example.com"] ], - 'expectedLogMessages' => 'Releasing "urn:mace:dir:attribute-def:eduPersonTargetedId" as "UserName" is not possible, value for "urn:mace:dir:attribute-def:eduPersonTargetedId" is null' + 'expectedLogMessage' => 'Releasing "urn:mace:dir:attribute-def:eduPersonTargetedId" as "UserName" is not possible, value for "urn:mace:dir:attribute-def:eduPersonTargetedId" is null' ], ]; } diff --git a/tests/unit/OpenConext/EngineBlock/Service/SsoNotificationServiceTest.php b/tests/unit/OpenConext/EngineBlock/Service/SsoNotificationServiceTest.php index edc88dd0af..00dbe2c0fc 100644 --- a/tests/unit/OpenConext/EngineBlock/Service/SsoNotificationServiceTest.php +++ b/tests/unit/OpenConext/EngineBlock/Service/SsoNotificationServiceTest.php @@ -24,8 +24,8 @@ use OpenConext\EngineBlock\Metadata\MetadataRepository\InMemoryMetadataRepository; use Phake; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Monolog\Logger; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Tests\Logger; class SsoNotificationServiceTest extends TestCase { @@ -85,10 +85,8 @@ public function setUp(): void )); } - /** - * @test - * @group SsoNotification - */ + #[\PHPUnit\Framework\Attributes\Group('SsoNotification')] + #[\PHPUnit\Framework\Attributes\Test] public function test_get_sso_cookie() { $this->request->cookies->add([ 'ssonot' => $this->cookieValue ]); @@ -98,10 +96,8 @@ public function test_get_sso_cookie() } - /** - * @test - * @group SsoNotification - */ + #[\PHPUnit\Framework\Attributes\Group('SsoNotification')] + #[\PHPUnit\Framework\Attributes\Test] public function test_handle_sso_notification() { $this->request->cookies->add([ 'ssonot' => $this->cookieValue ]); @@ -111,10 +107,8 @@ public function test_handle_sso_notification() $this->assertEquals($this->idpEntityId, $entityId); } - /** - * @test - * @group SsoNotification - */ + #[\PHPUnit\Framework\Attributes\Group('SsoNotification')] + #[\PHPUnit\Framework\Attributes\Test] public function test_handle_unknown_idp() { $this->request->cookies->add([ 'ssonot' => $this->getStandardCookieValue($this->idpEntityId . "test") ]); @@ -124,10 +118,8 @@ public function test_handle_unknown_idp() Phake::verify($this->loggerMock)->warning(Phake::anyParameters()); } - /** - * @test - * @group SsoNotification - */ + #[\PHPUnit\Framework\Attributes\Group('SsoNotification')] + #[\PHPUnit\Framework\Attributes\Test] public function test_invalid_encryption_key() { $ssoNotificationService = new SsoNotificationService( @@ -144,10 +136,8 @@ public function test_invalid_encryption_key() Phake::verify($this->loggerMock)->warning(Phake::anyParameters()); } - /** - * @test - * @group SsoNotification - */ + #[\PHPUnit\Framework\Attributes\Group('SsoNotification')] + #[\PHPUnit\Framework\Attributes\Test] public function test_invalid_json() { $data = "{\"url\":\"$this->idpUrl\"}"; diff --git a/tests/unit/OpenConext/EngineBlock/Service/SsoSessionServiceTest.php b/tests/unit/OpenConext/EngineBlock/Service/SsoSessionServiceTest.php index 9b61942ce2..bedf590fb9 100644 --- a/tests/unit/OpenConext/EngineBlock/Service/SsoSessionServiceTest.php +++ b/tests/unit/OpenConext/EngineBlock/Service/SsoSessionServiceTest.php @@ -20,8 +20,8 @@ use Phake; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Monolog\Logger; use Symfony\Component\HttpFoundation\ParameterBag; -use Symfony\Component\HttpKernel\Tests\Logger; class SsoSessionServiceTest extends TestCase { @@ -53,10 +53,8 @@ public function setUp(): void ); } - /** - * @test - * @group SsoSessionCookie - */ + #[\PHPUnit\Framework\Attributes\Group('SsoSessionCookie')] + #[\PHPUnit\Framework\Attributes\Test] public function test_set_sso_session_cookie() { $cookieMock = Phake::mock(ParameterBag::class); @@ -74,10 +72,8 @@ public function test_set_sso_session_cookie() ); } - /** - * @test - * @group SsoSessionCookie - */ + #[\PHPUnit\Framework\Attributes\Group('SsoSessionCookie')] + #[\PHPUnit\Framework\Attributes\Test] public function test_set_sso_session_cookie_invalid_cookie_resets() { $cookieMock = Phake::mock(ParameterBag::class); @@ -95,10 +91,8 @@ public function test_set_sso_session_cookie_invalid_cookie_resets() ); } - /** - * @test - * @group SsoSessionCookie - */ + #[\PHPUnit\Framework\Attributes\Group('SsoSessionCookie')] + #[\PHPUnit\Framework\Attributes\Test] public function test_set_multiple_sso_session_cookies() { $cookieMock = Phake::mock(ParameterBag::class); @@ -116,10 +110,8 @@ public function test_set_multiple_sso_session_cookies() ); } - /** - * @test - * @group SsoSessionCookie - */ + #[\PHPUnit\Framework\Attributes\Group('SsoSessionCookie')] + #[\PHPUnit\Framework\Attributes\Test] public function test_set_multiple_sso_session_cookies_no_duplicates() { $cookieMock = Phake::mock(ParameterBag::class); @@ -137,10 +129,8 @@ public function test_set_multiple_sso_session_cookies_no_duplicates() ); } - /** - * @test - * @group SsoSessionCookie - */ + #[\PHPUnit\Framework\Attributes\Group('SsoSessionCookie')] + #[\PHPUnit\Framework\Attributes\Test] public function test_remove_sso_session_cookie() { $this->ssoQueryService->clearSsoSessionCookie(); diff --git a/tests/unit/OpenConext/EngineBlock/Stepup/StepupDecisionTest.php b/tests/unit/OpenConext/EngineBlock/Stepup/StepupDecisionTest.php index c09ec962ae..6074b8c7b2 100644 --- a/tests/unit/OpenConext/EngineBlock/Stepup/StepupDecisionTest.php +++ b/tests/unit/OpenConext/EngineBlock/Stepup/StepupDecisionTest.php @@ -37,13 +37,13 @@ class StepupDecisionTest extends TestCase use MockeryPHPUnitIntegration; /** - * @test - * @group Stepup - * @dataProvider stepupCoinsAndExpectedResultProvider * * @param array $input * @param array $expectedResult */ + #[\PHPUnit\Framework\Attributes\DataProvider('stepupCoinsAndExpectedResultProvider')] + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_correct_stepup_decision_should_be_made_based_on_a_coin_data( $input, $expectedResult @@ -118,7 +118,7 @@ private function buildMockRepository($input) return $repo; } - public function stepupCoinsAndExpectedResultProvider() + public static function stepupCoinsAndExpectedResultProvider() { return [ 'Use no stepup if no coins set for IdP and SP (do not allow no stepup)' => [[null, null, [], [], false], [false, '', false]], @@ -140,19 +140,19 @@ public function stepupCoinsAndExpectedResultProvider() 'Use highest PdP LoA if multiple PdP LoA set (allow no stepup)' => [['', '', [], ['loa30', 'loa20'], true], [true, 'loa30', true]], 'Use highest PdP LoA if multiple PdP LoA set in different order (allow no stepup)' => [['', '', [], ['loa30', 'loa20'], true], [true, 'loa30', true]], - 'Allow AuthnRequest (SP) LoA1, but take no action' => [['', '', [$this->buildLoa('loa10')], [], true], [false, 'loa10', false]], - 'Use AuthnRequest (SP) LoA if SP LoA is lower' => [['loa20', '', [$this->buildLoa('loa30')], [], true], [true, 'loa30', true]], - 'Use IdP LoA if IdP LoA is highest and AuthnRequest (SP) LoA set (allow no stepup)' => [['', 'loa30', [$this->buildLoa('loa20')], [], true], [true, 'loa30', true]], - 'Use PdP LoA if AuthnRequest (SP) LoA set (allow no stepup)' => [['', '', [$this->buildLoa('loa30')], [], true], [true, 'loa30', true]], - 'Use highest AuthnRequest (SP) LoA if multiple LoA set (allow no stepup)' => [['', '', [$this->buildLoa('loa30'), $this->buildLoa('loa20')], [], true], [true, 'loa30', true]], - 'Use highest AuthnRequest (SP) LoA if multiple LoA set (authn + pdp) in different order (allow no stepup)' => [['', '', [$this->buildLoa('loa20'), $this->buildLoa('loa30')], ['loa20'], true], [true, 'loa30', true]], + 'Allow AuthnRequest (SP) LoA1, but take no action' => [['', '', [self::buildLoa('loa10')], [], true], [false, 'loa10', false]], + 'Use AuthnRequest (SP) LoA if SP LoA is lower' => [['loa20', '', [self::buildLoa('loa30')], [], true], [true, 'loa30', true]], + 'Use IdP LoA if IdP LoA is highest and AuthnRequest (SP) LoA set (allow no stepup)' => [['', 'loa30', [self::buildLoa('loa20')], [], true], [true, 'loa30', true]], + 'Use PdP LoA if AuthnRequest (SP) LoA set (allow no stepup)' => [['', '', [self::buildLoa('loa30')], [], true], [true, 'loa30', true]], + 'Use highest AuthnRequest (SP) LoA if multiple LoA set (allow no stepup)' => [['', '', [self::buildLoa('loa30'), self::buildLoa('loa20')], [], true], [true, 'loa30', true]], + 'Use highest AuthnRequest (SP) LoA if multiple LoA set (authn + pdp) in different order (allow no stepup)' => [['', '', [self::buildLoa('loa20'), self::buildLoa('loa30')], ['loa20'], true], [true, 'loa30', true]], 'Use highest LoA from many options (allow no stepup)' => [['loa20', 'loa30', [], ['loa20', 'loa20', 'loa30'], true], [true, 'loa30', true]], - 'Use highest LoA from many different options (allow no stepup)' => [['loa30', 'loa20', [$this->buildLoa('loa20'), $this->buildLoa('loa20'), $this->buildLoa('loa30')], [], true], [true, 'loa30', true]], + 'Use highest LoA from many different options (allow no stepup)' => [['loa30', 'loa20', [self::buildLoa('loa20'), self::buildLoa('loa20'), self::buildLoa('loa30')], [], true], [true, 'loa30', true]], ]; } - private function buildLoa(string $loaLevel): Loa + private static function buildLoa(string $loaLevel): Loa { $matches = []; preg_match_all('/\d+/', $loaLevel, $matches); diff --git a/tests/unit/OpenConext/EngineBlock/Stepup/StepupEndpointTest.php b/tests/unit/OpenConext/EngineBlock/Stepup/StepupEndpointTest.php index 0ef81a35dd..83b24b8136 100644 --- a/tests/unit/OpenConext/EngineBlock/Stepup/StepupEndpointTest.php +++ b/tests/unit/OpenConext/EngineBlock/Stepup/StepupEndpointTest.php @@ -26,10 +26,8 @@ class StepupEndpointTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_should_be_successful_populated() { $fileLocation = __DIR__ . '/../../../../resources/key/engineblock.crt'; @@ -40,40 +38,32 @@ public function the_sfo_endpoint_object_should_be_successful_populated() $this->assertSame($fileLocation, $endpoint->getKeyFile()); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_entityId_should_not_throw_an_exception_on_initialization_when_invalid() { $endpoint = new StepupEndpoint(null, 'https://sso-location', 'tests/resources/key/engineblock.crt'); $this->assertInstanceOf(StepupEndpoint::class, $endpoint); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_ssoLocation_should_not_throw_an_exception_on_initialization_when_invalid() { $endpoint = new StepupEndpoint('entity-id', null, 'tests/resources/key/engineblock.crt'); $this->assertInstanceOf(StepupEndpoint::class, $endpoint); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_keyFile_should_not_throw_an_exception_on_initialization_when_invalid() { $endpoint = new StepupEndpoint('entity-id', 'https://sso-location', null); $this->assertInstanceOf(StepupEndpoint::class, $endpoint); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_entityId_should_be_a_string() { $this->expectException(InvalidStepupConfigurationException::class); @@ -83,10 +73,8 @@ public function the_sfo_endpoint_object_entityId_should_be_a_string() $endpoint->getEntityId(); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_ssoLocation_should_be_a_string() { $this->expectException(InvalidStepupConfigurationException::class); @@ -96,10 +84,8 @@ public function the_sfo_endpoint_object_ssoLocation_should_be_a_string() $endpoint->getSsoLocation(); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_keyFile_should_be_a_string() { $this->expectException(InvalidStepupConfigurationException::class); @@ -109,10 +95,8 @@ public function the_sfo_endpoint_object_keyFile_should_be_a_string() $endpoint->getKeyFile(); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_keyFile_should_be_a_file() { $this->expectException(InvalidStepupConfigurationException::class); @@ -123,12 +107,12 @@ public function the_sfo_endpoint_object_keyFile_should_be_a_file() } /** - * @dataProvider availableMethodProvider - * @test - * @group Stepup * * @param string $methodName */ + #[\PHPUnit\Framework\Attributes\DataProvider('availableMethodProvider')] + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_sfo_endpoint_object_mmethods_should_throw_an_exception_when_not_validated($methodName) { $this->expectException(InvalidStepupConfigurationException::class); @@ -138,7 +122,7 @@ public function the_sfo_endpoint_object_mmethods_should_throw_an_exception_when_ $endpoint->$methodName(); } - public function availableMethodProvider() { + public static function availableMethodProvider() { $methods = []; $class = new \ReflectionClass(StepupEndpoint::class); foreach ($class->getMethods() as $method) { diff --git a/tests/unit/OpenConext/EngineBlock/Stepup/StepupGatewayLoaMappingTest.php b/tests/unit/OpenConext/EngineBlock/Stepup/StepupGatewayLoaMappingTest.php index 144c755d8c..75e05c2b72 100644 --- a/tests/unit/OpenConext/EngineBlock/Stepup/StepupGatewayLoaMappingTest.php +++ b/tests/unit/OpenConext/EngineBlock/Stepup/StepupGatewayLoaMappingTest.php @@ -31,10 +31,8 @@ class StepupGatewayLoaMappingTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_stepup_loa_mapping_object_should_be_successful_populated() { $mapping = [ @@ -84,10 +82,8 @@ public function the_stepup_loa_mapping_object_should_be_successful_populated() $stepupLoaMapping->transformToGatewayLoa(Loa::create(20, 'loa2')); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_stepup_loa_mapping_object_should_successful_map_back() { $mapping = [ @@ -145,10 +141,8 @@ public function the_stepup_loa_mapping_object_should_successful_map_back() $this->assertSame('ebLoa3', $stepupLoaMapping->transformToEbLoa($gwLoa3)->getIdentifier()); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_stepup_loa_mapping_object_should_return_an_exception_when_unable_to_map_back() { $mapping = [ @@ -183,10 +177,8 @@ public function the_stepup_loa_mapping_object_should_return_an_exception_when_un $stepupLoaMapping->transformToEbLoa(Loa::create(20, 'loa2')); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_mapping_must_be_valid_no_duplicates_allowed() { $mapping = [ @@ -219,10 +211,8 @@ public function the_mapping_must_be_valid_no_duplicates_allowed() new StepupGatewayLoaMapping($mapping, 'gatewayLoa1', $loaRepository); } - /** - * @test - * @group Stepup - */ + #[\PHPUnit\Framework\Attributes\Group('Stepup')] + #[\PHPUnit\Framework\Attributes\Test] public function the_mapping_must_be_valid_no_duplicates_in_gw_config_allowed() { $mapping = [ diff --git a/tests/unit/OpenConext/EngineBlock/Validator/AcsRequestValidatorTest.php b/tests/unit/OpenConext/EngineBlock/Validator/AcsRequestValidatorTest.php index f8c4397f13..f4ebadbf20 100644 --- a/tests/unit/OpenConext/EngineBlock/Validator/AcsRequestValidatorTest.php +++ b/tests/unit/OpenConext/EngineBlock/Validator/AcsRequestValidatorTest.php @@ -43,9 +43,7 @@ public function setUp(): void $_SERVER = []; } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_get() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -57,9 +55,7 @@ public function test_happy_flow_get() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_post() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -71,9 +67,7 @@ public function test_happy_flow_post() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_patch_method_is_not_supported() { $this->expectException(InvalidRequestMethodException::class); @@ -86,9 +80,7 @@ public function test_patch_method_is_not_supported() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_missing_saml_argument_on_post() { $this->expectException(MissingParameterException::class); @@ -101,9 +93,7 @@ public function test_missing_saml_argument_on_post() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_missing_saml_argument_on_get() { $this->expectException(MissingParameterException::class); diff --git a/tests/unit/OpenConext/EngineBlock/Validator/SamlBindingValidatorTest.php b/tests/unit/OpenConext/EngineBlock/Validator/SamlBindingValidatorTest.php index 672caa78df..f91888eab1 100644 --- a/tests/unit/OpenConext/EngineBlock/Validator/SamlBindingValidatorTest.php +++ b/tests/unit/OpenConext/EngineBlock/Validator/SamlBindingValidatorTest.php @@ -43,9 +43,7 @@ public function setUp(): void $_SERVER = []; } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_get() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -59,9 +57,7 @@ public function test_happy_flow_get() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_post() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -75,14 +71,13 @@ public function test_happy_flow_post() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_post_binding_is_not_supported() { $this->expectException(InvalidBindingException::class); $this->expectExceptionMessage('No SAMLRequest or SAMLResponse parameter was found in the HTTP'); + $_SERVER['REQUEST_METHOD'] = ''; // Prevent Warning: Undefined array key "REQUEST_METHOD" in /var/www/html/vendor/simplesamlphp/saml2/src/SAML2/Binding.php on line 69 $request = m::mock(Request::class); $request ->shouldReceive('getMethod') @@ -91,9 +86,7 @@ public function test_post_binding_is_not_supported() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_used_invalid_binding() { $this->expectException(InvalidBindingException::class); @@ -112,9 +105,7 @@ public function test_used_invalid_binding() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_used_unsupported_binding() { $this->expectException(InvalidBindingException::class); diff --git a/tests/unit/OpenConext/EngineBlock/Validator/SamlResponseValidatorTest.php b/tests/unit/OpenConext/EngineBlock/Validator/SamlResponseValidatorTest.php index e483cf1c17..61bbd77932 100644 --- a/tests/unit/OpenConext/EngineBlock/Validator/SamlResponseValidatorTest.php +++ b/tests/unit/OpenConext/EngineBlock/Validator/SamlResponseValidatorTest.php @@ -40,9 +40,7 @@ public function setUp(): void $_SERVER = []; } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -57,9 +55,8 @@ public function test_happy_flow() /** * A SAML response without Assertion is not validated, and will be investigated in greater detail when processing * the response. - * - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_assertion_less_saml_responses_are_passsed() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -74,9 +71,8 @@ public function test_assertion_less_saml_responses_are_passsed() /** * A SAML response without Assertion is not validated, and will be investigated in greater detail when processing * the response. - * - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_encrypted_assertion_saml_responses_are_passsed() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -98,9 +94,8 @@ public function test_encrypted_assertion_saml_responses_are_passsed() * valid reference, but is not covered by the signature computation. * * See the audit report for more details, but review the h01_response.xml to see how this was exploitable. - * - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_tampering_with_saml_response_is_rejected() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -115,8 +110,8 @@ public function test_tampering_with_saml_response_is_rejected() /** * EngineBlock currently only allows SAMLResponses with one assertion. - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_two_assertions_are_disallowed() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -131,8 +126,8 @@ public function test_two_assertions_are_disallowed() /** * The SignedInfo element should be the first child of the Signature element. - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_the_signed_info_element_must_be_first_child_of_signature() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -147,9 +142,8 @@ public function test_the_signed_info_element_must_be_first_child_of_signature() /** * The Reference element URI attribute should refer to the Assertion ID it is part of. - * - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_the_reference_uri_should_match_assertion_id() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -166,9 +160,8 @@ public function test_the_reference_uri_should_match_assertion_id() /** * The second child of the signature element should be the signature value element - * - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_signed_value_should_be_signatures_second_child() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -183,8 +176,8 @@ public function test_signed_value_should_be_signatures_second_child() /** * Using multiple SignedInfo elements in a Signature is not allowed - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_only_one_signed_info_element_should_be_permitted() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -199,9 +192,8 @@ public function test_only_one_signed_info_element_should_be_permitted() /** * Only the SAMLResponse POST parameter is used to receive a SAMLResponse - * - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_reads_saml_response_from_post() { $_SERVER['REQUEST_METHOD'] = 'POST'; @@ -217,8 +209,8 @@ public function test_reads_saml_response_from_post() /** * Other input validators should have already picked this up. * HTTP Redirect binding is not allowed. - * @backupGlobals enabled */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_reads_saml_response_from_post_http_binding_not_processed() { $_SERVER['REQUEST_METHOD'] = 'GET'; diff --git a/tests/unit/OpenConext/EngineBlock/Validator/SsoRequestValidatorTest.php b/tests/unit/OpenConext/EngineBlock/Validator/SsoRequestValidatorTest.php index b49e0d7898..9ac386de33 100644 --- a/tests/unit/OpenConext/EngineBlock/Validator/SsoRequestValidatorTest.php +++ b/tests/unit/OpenConext/EngineBlock/Validator/SsoRequestValidatorTest.php @@ -43,9 +43,7 @@ public function setUp(): void $_SERVER = []; } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_get() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -57,9 +55,7 @@ public function test_happy_flow_get() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_post() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -71,9 +67,7 @@ public function test_happy_flow_post() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_post_binding_is_not_supported() { $this->expectException(InvalidRequestMethodException::class); @@ -86,9 +80,7 @@ public function test_post_binding_is_not_supported() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_missing_saml_argument_on_post() { $this->expectException(MissingParameterException::class); @@ -101,9 +93,7 @@ public function test_missing_saml_argument_on_post() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_missing_saml_argument_on_get() { $this->expectException(MissingParameterException::class); diff --git a/tests/unit/OpenConext/EngineBlock/Validator/UnsolicitedSsoRequestValidatorTest.php b/tests/unit/OpenConext/EngineBlock/Validator/UnsolicitedSsoRequestValidatorTest.php index 21f550e19e..44eabfbf42 100644 --- a/tests/unit/OpenConext/EngineBlock/Validator/UnsolicitedSsoRequestValidatorTest.php +++ b/tests/unit/OpenConext/EngineBlock/Validator/UnsolicitedSsoRequestValidatorTest.php @@ -42,9 +42,7 @@ public function setUp(): void $_SERVER = []; } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_happy_flow_get() { // Under the hood, the Binding::getCurrentBinding method is used, which directly reads from the super globals @@ -56,9 +54,7 @@ public function test_happy_flow_get() $this->assertTrue($this->validator->isValid($request)); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_post_is_not_allowed() { $this->expectException(RuntimeException::class); @@ -71,9 +67,7 @@ public function test_post_is_not_allowed() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_put_binding_is_not_supported() { $this->expectException(RuntimeException::class); @@ -86,9 +80,7 @@ public function test_put_binding_is_not_supported() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_malformed_argument() { $this->expectException(RuntimeException::class); @@ -102,9 +94,7 @@ public function test_malformed_argument() $this->validator->isValid($request); } - /** - * @backupGlobals enabled - */ + #[\PHPUnit\Framework\Attributes\BackupGlobals(true)] public function test_missing_argument() { $this->expectException(RuntimeException::class); diff --git a/tests/unit/OpenConext/EngineBlock/Xml/MetadataRendererTest.php b/tests/unit/OpenConext/EngineBlock/Xml/MetadataRendererTest.php index 77a82bcd84..ad8329c644 100644 --- a/tests/unit/OpenConext/EngineBlock/Xml/MetadataRendererTest.php +++ b/tests/unit/OpenConext/EngineBlock/Xml/MetadataRendererTest.php @@ -39,6 +39,7 @@ use OpenConext\EngineBlock\Metadata\X509\X509PrivateKey; use OpenConext\EngineBlock\Service\TimeProvider\TimeProvider; use OpenConext\EngineBlockBundle\Localization\LanguageSupportProvider; +use OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Spaceless; use PHPUnit\Framework\TestCase; use RobRichards\XMLSecLibs\XMLSecEnc; use RobRichards\XMLSecLibs\XMLSecurityDSig; @@ -49,6 +50,7 @@ use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Component\Translation\TranslatorInterface; use Twig\Environment; +use Twig\Loader\FilesystemLoader; class MetadataRendererTest extends TestCase { @@ -66,10 +68,8 @@ protected function setUp(): void parent::setUp(); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function the_metadata_factory_should_return_valid_signed_xml_for_idp() { $ssoLocation = 'https://example.com/sso'; @@ -107,10 +107,8 @@ public function the_metadata_factory_should_return_valid_signed_xml_for_idp() $this->validateSchema($xml); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function the_metadata_factory_should_return_valid_signed_xml_for_sp() { $assertionConsumerServices[] = new IndexedService( @@ -160,10 +158,8 @@ public function the_metadata_factory_should_return_valid_signed_xml_for_sp() $this->validateSchema($xml); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function the_metadata_factory_should_return_valid_signed_xml_for_idps_of_sp() { $ssoLocation = 'https://example.com/sso'; @@ -223,10 +219,8 @@ public function the_metadata_factory_should_return_valid_signed_xml_for_idps_of_ $this->validateSchema($xml); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function modified_metadata_should_not_pass_signature_validation() { $assertionConsumerServices[] = new IndexedService( @@ -256,10 +250,8 @@ public function modified_metadata_should_not_pass_signature_validation() $this->assertFalse($this->validateXml($xml)); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function metadata_add_all_requested_attributes() { $xml = $this->metadataRenderer->fromServiceProviderEntity($this->buildSp(), 'default'); @@ -270,10 +262,8 @@ public function metadata_add_all_requested_attributes() $this->assertStringContainsString($this->getRequestedAttributeXml('attribute3', false), $xml); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function metadata_add_required_requested_attributes() { $this->metadataRenderer = $this->buildMetadataRenderer('required'); @@ -286,10 +276,8 @@ public function metadata_add_required_requested_attributes() $this->assertStringNotContainsString($this->getRequestedAttributeXml('attribute3', false), $xml); } - /** - * @test - * @group Metadata - */ + #[\PHPUnit\Framework\Attributes\Group('Metadata')] + #[\PHPUnit\Framework\Attributes\Test] public function metadata_add_no_requested_attributes() { $this->metadataRenderer = $this->buildMetadataRenderer('none'); @@ -314,11 +302,11 @@ private function buildMetadataRenderer(string $addRequestedAttributes) $samlIdGenerator->method('generate') ->willReturn('EB_metadata'); - $twigLoader = new \Twig_Loader_Filesystem(); + $twigLoader = new FilesystemLoader(); $twigLoader->addPath($basePath . '/theme/openconext/templates/modules', 'theme'); $environment = new Environment($twigLoader); - $translator = m::mock(TranslatorInterface::class); + $translator = m::mock(\Symfony\Contracts\Translation\TranslatorInterface::class); $translator ->shouldReceive('trans') ->andReturnUsing(function($key) { @@ -328,6 +316,8 @@ private function buildMetadataRenderer(string $addRequestedAttributes) $translatorExtension = new TranslationExtension($translator); $environment->addExtension($translatorExtension); + $environment->addExtension(new Spaceless()); + $keyPairFactory = $this->createMock(KeyPairFactory::class); $keyPairFactory ->method('buildFromIdentifier') diff --git a/tests/unit/OpenConext/EngineBlockBridge/Authentication/Repository/UserDirectoryAdapterTest.php b/tests/unit/OpenConext/EngineBlockBridge/Authentication/Repository/UserDirectoryAdapterTest.php index 965d2ea454..47a37e5ba3 100644 --- a/tests/unit/OpenConext/EngineBlockBridge/Authentication/Repository/UserDirectoryAdapterTest.php +++ b/tests/unit/OpenConext/EngineBlockBridge/Authentication/Repository/UserDirectoryAdapterTest.php @@ -51,16 +51,16 @@ public function setUp(): void $this->logger = m::mock(LoggerInterface::class); // the amount of logging is not really relevant. - $this->logger->shouldReceive('debug')->between(0, 1000); + $this->logger->shouldReceive('debug'); } /** - * @test - * @group EngineBlockBridge - * @group Authentication - * @dataProvider noUidValueProvider * @param array $invalidAttributes */ + #[\PHPUnit\Framework\Attributes\DataProvider('noUidValueProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function identification_of_a_user_requires_uid_value_to_be_set_as_attribute($invalidAttributes) { $userDirectoryAdapter = new UserDirectoryAdapter( @@ -73,7 +73,7 @@ public function identification_of_a_user_requires_uid_value_to_be_set_as_attribu $userDirectoryAdapter->identifyUser($invalidAttributes); } - public function noUidValueProvider() + public static function noUidValueProvider() { return [ 'no uid' => [ @@ -97,12 +97,12 @@ public function noUidValueProvider() } /** - * @test - * @group EngineBlockBridge - * @group Authentication - * @dataProvider noSchacHomeOrganizationValueProvider * @param array $invalidAttributes */ + #[\PHPUnit\Framework\Attributes\DataProvider('noSchacHomeOrganizationValueProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function identification_of_a_user_requires_schacHomeOrganization_value_to_be_set_as_attribute($invalidAttributes) { $userDirectoryAdapter = new UserDirectoryAdapter( @@ -115,7 +115,7 @@ public function identification_of_a_user_requires_schacHomeOrganization_value_to $userDirectoryAdapter->identifyUser($invalidAttributes); } - public function noSchacHomeOrganizationValueProvider() + public static function noSchacHomeOrganizationValueProvider() { return [ 'no schacHomeOrganization' => [ @@ -138,11 +138,9 @@ public function noSchacHomeOrganizationValueProvider() ]; } - /** - * @test - * @group EngineBlockBridge - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function registering_a_user_results_in_a_valid_user() { $uid = 'homer@invalid.org'; @@ -179,11 +177,9 @@ public function registering_a_user_results_in_a_valid_user() ); } - /** - * @test - * @group EngineBlockBridge - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function when_attempting_to_find_a_non_existent_user_null_is_returned() { $collabPersonId = $this->getCollabPersonId(); @@ -204,11 +200,9 @@ public function when_attempting_to_find_a_non_existent_user_null_is_returned() $this->assertNull($result); } - /** - * @test - * @group EngineBlockBridge - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_user_is_returned_when_attempting_to_find_an_existing_user() { $collabPersonId = $this->getCollabPersonId(); @@ -230,11 +224,9 @@ public function a_user_is_returned_when_attempting_to_find_an_existing_user() $this->assertSame($expected, $result); } - /** - * @test - * @group EngineBlockBridge - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_for_removal_removes_the_user_from_the_database_backend() { $collabPersonId = $this->getCollabPersonId(); @@ -252,11 +244,9 @@ public function a_request_for_removal_removes_the_user_from_the_database_backend $userDirectoryAdapter->deleteUserWith($collabPersonId); } - /** - * @test - * @group EngineBlockBridge - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_for_removal_also_removes_the_user_from_the_user_directory_if_enabled() { $collabPersonId = $this->getCollabPersonId(); diff --git a/tests/unit/OpenConext/EngineBlockBridge/Logger/AuthenticationLoggerAdapterTest.php b/tests/unit/OpenConext/EngineBlockBridge/Logger/AuthenticationLoggerAdapterTest.php index 563131c1d1..4b16799985 100644 --- a/tests/unit/OpenConext/EngineBlockBridge/Logger/AuthenticationLoggerAdapterTest.php +++ b/tests/unit/OpenConext/EngineBlockBridge/Logger/AuthenticationLoggerAdapterTest.php @@ -39,11 +39,9 @@ class AuthenticationLoggerAdapterTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlockBridge - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function arguments_are_converted_correctly() { $serviceProviderEntityId = 'SpEntityId'; @@ -101,11 +99,9 @@ public function arguments_are_converted_correctly() ); } - /** - * @test - * @group EngineBlockBridge - * @group Logger - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBridge')] + #[\PHPUnit\Framework\Attributes\Group('Logger')] + #[\PHPUnit\Framework\Attributes\Test] public function arguments_with_log_attributes_are_converted_correctly() { $serviceProviderEntityId = 'SpEntityId'; diff --git a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/AttributeAggregationClientTest.php b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/AttributeAggregationClientTest.php index feb6d6e3ed..a2f65884a1 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/AttributeAggregationClientTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/AttributeAggregationClientTest.php @@ -29,16 +29,12 @@ use OpenConext\EngineBlockBundle\AttributeAggregation\Dto\Response; use PHPUnit\Framework\TestCase; -/** - * @group AttributeAggregation - */ +#[\PHPUnit\Framework\Attributes\Group('AttributeAggregation')] class AttributeAggregationClientTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function an_attributeaggregation_client_parses_the_aggregator_response() { $request = Request::from( diff --git a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/AttributeRuleTest.php b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/AttributeRuleTest.php index b8f02b2884..d2543e7d1b 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/AttributeRuleTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/AttributeRuleTest.php @@ -24,43 +24,33 @@ use OpenConext\EngineBlockBundle\AttributeAggregation\Dto\AttributeRule; use PHPUnit\Framework\TestCase; -/** - * @group AttributeAggregation - */ +#[\PHPUnit\Framework\Attributes\Group('AttributeAggregation')] class AttributeRuleTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function rule_name_must_be_set() { $this->expectException(InvalidArgumentException::class); AttributeRule::from(null, 'value', 'source'); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function rule_value_must_be_set() { $this->expectException(InvalidArgumentException::class); AttributeRule::from('name', null, 'source'); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function rule_source_must_be_set() { $this->expectException(InvalidArgumentException::class); AttributeRule::from('name', 'value', null); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function rules_are_created_from_arp() { $rules = AttributeRule::fromArp( diff --git a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/RequestTest.php b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/RequestTest.php index 385e0e28d8..b1319cde32 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/RequestTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/RequestTest.php @@ -24,16 +24,12 @@ use OpenConext\EngineBlockBundle\AttributeAggregation\Dto\Request; use PHPUnit\Framework\TestCase; -/** - * @group AttributeAggregation - */ +#[\PHPUnit\Framework\Attributes\Group('AttributeAggregation')] class RequestTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function request_serializes_to_aa_api_format() { $request = Request::from( @@ -90,9 +86,7 @@ public function request_serializes_to_aa_api_format() $this->assertEquals($expectedJson, $actualJson); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function request_serializes_to_aa_api_format_filters_non_string_values() { $request = Request::from( @@ -145,36 +139,28 @@ public function request_serializes_to_aa_api_format_filters_non_string_values() $this->assertEquals($expectedJson, $actualJson); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function request_subject_must_be_set() { $this->expectException(InvalidArgumentException::class); Request::from('sp-entity-id', 'idp-entity-id',NULL, [], []); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function request_sp_entity_id_must_be_set() { $this->expectException(InvalidArgumentException::class); Request::from(NULL, 'idp-entity-id', 'subject-id', [], []); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function request_idp_entity_id_must_be_set() { $this->expectException(InvalidArgumentException::class); Request::from('sp-entity-id', NULL, 'subject-id', [], []); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function request_attributes_must_be_of_type_dto() { $this->expectException(InvalidArgumentException::class); diff --git a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/ResponseTest.php b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/ResponseTest.php index 47a9b54596..fd17628b69 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/ResponseTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/AttributeAggregation/Dto/ResponseTest.php @@ -24,16 +24,12 @@ use OpenConext\EngineBlockBundle\Exception\InvalidAttributeAggregationResponseException; use PHPUnit\Framework\TestCase; -/** - * @group AttributeAggregation - */ +#[\PHPUnit\Framework\Attributes\Group('AttributeAggregation')] class ResponseTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function response_contains_parsed_aggregated_attributes() { $response = Response::fromData([ @@ -53,18 +49,14 @@ public function response_contains_parsed_aggregated_attributes() $this->assertInstanceOf(AggregatedAttribute::class, $response->attributes[0]); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function response_data_must_be_an_array() { $this->expectException(InvalidAttributeAggregationResponseException::class); Response::fromData(NULL); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function response_attribute_must_have_a_name() { $this->expectException(InvalidAttributeAggregationResponseException::class); @@ -76,9 +68,7 @@ public function response_attribute_must_have_a_name() ]); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function response_attribute_must_have_values_property() { $this->expectException(InvalidAttributeAggregationResponseException::class); @@ -90,9 +80,7 @@ public function response_attribute_must_have_values_property() ]); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function response_attribute_must_have_a_source() { $this->expectException(InvalidAttributeAggregationResponseException::class); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationLoopGuardTest.php b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationLoopGuardTest.php index e878c7d60e..11ee67b9c0 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationLoopGuardTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationLoopGuardTest.php @@ -32,10 +32,8 @@ class AuthenticationLoopGuardTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function authentication_loop_guard_determines_that_it_is_in_a_loop() { $maximumNumberOfAuthenticationProceduresAllowed = 1; @@ -76,10 +74,8 @@ public function authentication_loop_guard_determines_that_it_is_in_a_loop() ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function authentication_loop_guard_determines_that_it_is_not_in_a_loop() { $maximumNumberOfAuthenticationProceduresAllowed = 2; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMapTest.php b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMapTest.php index 86203c6fbc..54872c8b5d 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMapTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureMapTest.php @@ -31,10 +31,8 @@ class AuthenticationProcedureMapTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function a_new_map_is_returned_when_an_authentication_procedure_is_added_to_an_authentication_procedures_map() { $someServiceProvider = new Entity(new EntityId('some.serviceprovider.example'), EntityType::SP()); @@ -67,10 +65,8 @@ public function a_new_map_is_returned_when_an_authentication_procedure_is_added_ ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_map_can_be_filtered_by_authentications_on_behalf_of_a_given_service_provider_returning_a_new_map() { $someServiceProvider = new Entity(new EntityId('some.serviceprovider.example'), EntityType::SP()); @@ -96,10 +92,8 @@ public function an_authentication_procedure_map_can_be_filtered_by_authenticatio ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_map_can_be_filtered_by_completed_procedures_since_a_given_time_returning_a_new_map() { $someServiceProvider = new Entity(new EntityId('some.serviceprovider.example'), EntityType::SP()); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureTest.php b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureTest.php index bccb3be831..e502ddbe75 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationProcedureTest.php @@ -30,10 +30,8 @@ class AuthenticationProcedureTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_started_on_behalf_of_the_same_service_provider_as_given() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -48,10 +46,8 @@ public function an_authentication_procedure_is_started_on_behalf_of_the_same_ser ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_started_on_behalf_of_a_different_service_provider_as_given() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -67,10 +63,8 @@ public function an_authentication_procedure_is_started_on_behalf_of_a_different_ ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_authenticated_at_the_same_identity_provider_as_given() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -88,10 +82,8 @@ public function an_authentication_procedure_is_authenticated_at_the_same_identit ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_authenticated_at_the_different_identity_provider_as_given() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -110,10 +102,8 @@ public function an_authentication_procedure_is_authenticated_at_the_different_id ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_not_completed_at_all() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -130,10 +120,8 @@ public function an_authentication_procedure_is_not_completed_at_all() ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_not_completed_after_the_time_given() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -154,10 +142,8 @@ public function an_authentication_procedure_is_not_completed_after_the_time_give ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_completed_after_the_time_given() { $serviceProvider = new Entity(new EntityId('my.service-provider.example'), EntityType::SP()); @@ -178,10 +164,8 @@ public function an_authentication_procedure_is_completed_after_the_time_given() ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_equals_the_same_authentication_procedure() { $serviceProvider = new Entity(new EntityId('some.service-provider.example'), EntityType::SP()); @@ -201,10 +185,8 @@ public function an_authentication_procedure_equals_the_same_authentication_proce $this->assertTrue($authenticationProceduresAreEqual, 'The same authentication procedures should be equal'); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_does_not_equal_an_authentication_procedure_with_another_service_provider() { $serviceProvider = new Entity(new EntityId('some.service-provider.example'), EntityType::SP()); @@ -229,10 +211,8 @@ public function an_authentication_procedure_does_not_equal_an_authentication_pro ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_does_not_equal_an_authentication_procedure_without_an_identity_provider() { $serviceProvider = new Entity(new EntityId('some.service-provider.example'), EntityType::SP()); @@ -255,10 +235,8 @@ public function an_authentication_procedure_does_not_equal_an_authentication_pro ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_does_not_equal_an_authentication_procedure_with_another_identity_provider() { $serviceProvider = new Entity(new EntityId('some.service-provider.example'), EntityType::SP()); @@ -283,10 +261,8 @@ public function an_authentication_procedure_does_not_equal_an_authentication_pro ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_does_not_equal_an_authentication_procedure_with_another_date_of_completion() { $serviceProvider = new Entity(new EntityId('some.service-provider.example'), EntityType::SP()); @@ -310,10 +286,8 @@ public function an_authentication_procedure_does_not_equal_an_authentication_pro ); } - /** - * @test - * @group AuthenticationState - */ + #[\PHPUnit\Framework\Attributes\Group('AuthenticationState')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_does_not_equal_an_authentication_procedure_without_a_date_of_completion() { $serviceProvider = new Entity(new EntityId('some.service-provider.example'), EntityType::SP()); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationStateTest.php b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationStateTest.php index ea5f9a55c2..39c01ec30f 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationStateTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Authentication/AuthenticationStateTest.php @@ -31,10 +31,8 @@ class AuthenticationStateTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_cannot_be_authenticated_if_it_has_not_been_started() { $authenticationLoopGuard = new AuthenticationLoopGuard(5, 30, 20); @@ -49,10 +47,8 @@ public function an_authentication_procedure_cannot_be_authenticated_if_it_has_no $authenticationState->authenticatedAt('_00000000-0000-0000-0000-000000000000', $identityProvider); } - /** - * @test - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_cannot_be_completed_if_it_has_not_been_started() { $authenticationLoopGuard = new AuthenticationLoopGuard(5, 30, 20); @@ -65,10 +61,8 @@ public function an_authentication_procedure_cannot_be_completed_if_it_has_not_be $authenticationState->completeCurrentProcedure('_00000000-0000-0000-0000-000000000000'); } - /** - * @test - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_cannot_be_completed_if_it_has_not_been_authenticated() { $authenticationLoopGuard = new AuthenticationLoopGuard(5, 30, 20); @@ -84,10 +78,8 @@ public function an_authentication_procedure_cannot_be_completed_if_it_has_not_be $authenticationState->completeCurrentProcedure($requestId); } - /** - * @test - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_can_be_completed_multiple_times() { $authenticationLoopGuard = new AuthenticationLoopGuard(5, 30, 20); @@ -106,10 +98,8 @@ public function an_authentication_procedure_can_be_completed_multiple_times() self::assertTrue($authenticationState->isAuthenticated()); } - /** - * @test - * @group Authentication - */ + #[\PHPUnit\Framework\Attributes\Group('Authentication')] + #[\PHPUnit\Framework\Attributes\Test] public function an_authentication_procedure_is_not_authenticated_before_consent() { $authenticationLoopGuard = new AuthenticationLoopGuard(5, 30, 20); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Authentication/Service/SamlResponseHelperTest.php b/tests/unit/OpenConext/EngineBlockBundle/Authentication/Service/SamlResponseHelperTest.php index cb725a2b37..42420a1a5e 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Authentication/Service/SamlResponseHelperTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Authentication/Service/SamlResponseHelperTest.php @@ -102,7 +102,8 @@ public function test_create_authn_failed_response() * Test if the issuer was set correctly * @var SimpleXMLElement $issuer */ - $responseResponse = array_pop($responseXml->xpath('/samlp:Response')); + $samlResponse = $responseXml->xpath('/samlp:Response'); + $responseResponse = array_pop($samlResponse); self::assertEquals($responseResponse['InResponseTo'], $requestId); self::assertEquals($responseResponse['Destination'], 'https://sp.example.org/assertion/consumer'); @@ -110,15 +111,18 @@ public function test_create_authn_failed_response() * Test if the issuer was set correctly * @var SimpleXMLElement $issuer */ - $responseIssuer = array_pop($responseXml->xpath('/samlp:Response/saml:Issuer')); + $issuerResponse = $responseXml->xpath('/samlp:Response/saml:Issuer'); + $responseIssuer = array_pop($issuerResponse); self::assertEquals($responseIssuer, $issuer->getValue()); /** * Test if the codes are correctly copied from the original saml failed response * @var SimpleXMLElement $code */ - $responseCode = array_pop($responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode')); - $responseSubCode = array_pop($responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode/samlp:StatusCode')); + $statusCode = $responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode'); + $innerStatusCode = $responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode/samlp:StatusCode'); + $responseCode = array_pop($statusCode); + $responseSubCode = array_pop($innerStatusCode); self::assertEquals($responseCode['Value'], 'testCode'); self::assertEquals($responseSubCode['Value'], 'testSubCode'); } @@ -176,7 +180,8 @@ public function test_create_authn_failed_response_transparent() * Test if the issuer was set correctly * @var SimpleXMLElement $issuer */ - $responseResponse = array_pop($responseXml->xpath('/samlp:Response')); + $samlResponse = $responseXml->xpath('/samlp:Response'); + $responseResponse = array_pop($samlResponse); self::assertEquals($responseResponse['InResponseTo'], $requestId); self::assertEquals($responseResponse['Destination'], 'https://sp.example.org/assertion/consumer'); @@ -184,22 +189,23 @@ public function test_create_authn_failed_response_transparent() * Test if the issuer was set correctly * @var SimpleXMLElement $issuer */ - $responseIssuer = array_pop($responseXml->xpath('/samlp:Response/saml:Issuer')); + $issuerResponse = $responseXml->xpath('/samlp:Response/saml:Issuer'); + $responseIssuer = array_pop($issuerResponse); self::assertEquals($responseIssuer, $originalSpEntityId); /** * Test if the codes are correctly copied from the original saml failed response * @var SimpleXMLElement $code */ - $responseCode = array_pop($responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode')); - $responseSubCode = array_pop($responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode/samlp:StatusCode')); + $statusResponseCode = $responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode'); + $innerStatusResponseCode = $responseXml->xpath('/samlp:Response/samlp:Status/samlp:StatusCode/samlp:StatusCode'); + $responseCode = array_pop($statusResponseCode); + $responseSubCode = array_pop($innerStatusResponseCode); self::assertEquals($responseCode['Value'], 'testCode'); self::assertEquals($responseSubCode['Value'], 'testSubCode'); } - /** - * @dataProvider provideAcuData - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideAcuData')] public function test_get_acu(array $inputAcus, string $expectedAcu): void { $spEntityId = 'https://existing.example.org'; @@ -212,7 +218,7 @@ public function test_get_acu(array $inputAcus, string $expectedAcu): void self::assertEquals($expectedAcu, $this->helper->getAcu($spEntityId)); } - public function provideAcuData(): array + public static function provideAcuData(): array { $acuLocation0 = 'https://sp.example.org/assertion/consumer'; $acuLocation1 = 'https://sp.example.org/assertion/consumer-1'; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfigurationTest.php b/tests/unit/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfigurationTest.php index 606756af1a..33c0e863d6 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfigurationTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Configuration/ErrorFeedbackConfigurationTest.php @@ -21,7 +21,7 @@ use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use PHPUnit\Framework\TestCase; use Mockery as m; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ErrorFeedbackConfigurationTest extends TestCase { @@ -39,11 +39,9 @@ protected function setUp(): void $this->translator = m::mock(TranslatorInterface::class); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function a_link_can_be_queried_for_presence() { $this->boostrapWikiTranslations([ @@ -59,11 +57,9 @@ public function a_link_can_be_queried_for_presence() $this->assertFalse($errorFeedbackConfiguration->hasWikiLink('not-configured')); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function a_link_can_be_retrieved() { $this->boostrapWikiTranslations([ @@ -75,11 +71,9 @@ public function a_link_can_be_retrieved() $this->assertSame('https://support/no-session-found', $noSessionFound); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function an_idp_empty_wiki_link_configuration_can_be_provided() { $this->boostrapWikiTranslations([ @@ -91,11 +85,9 @@ public function an_idp_empty_wiki_link_configuration_can_be_provided() $this->assertFalse($errorFeedbackConfiguration->hasWikiLink('clock-issue')); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function an_idp_contact_page_can_be_tested() { $this->boostrapIdpTranslations([ @@ -112,11 +104,9 @@ public function an_idp_contact_page_can_be_tested() $this->assertSame('', $errorFeedbackConfiguration->getIdpContactShortLabel('no-session-found')); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function an_idp_empty_contact_page_configuration_can_provided() { $this->boostrapIdpTranslations([ diff --git a/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureConfigurationTest.php b/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureConfigurationTest.php index a68f9b5bf1..50766c5ce7 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureConfigurationTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureConfigurationTest.php @@ -28,16 +28,14 @@ class FeatureConfigurationTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function all_features_must_be_an_instance_of_feature() { $features = [ - 'some.feature' => new Feature('some.feature', true), - 'other.feature' => new Feature('other.feature', false), + 'some.feature' => true, + 'other.feature' => false, 'foo' => new stdClass() ]; @@ -46,16 +44,14 @@ public function all_features_must_be_an_instance_of_feature() new FeatureConfiguration($features); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function all_features_must_have_a_string_key() { $features = [ - 'some.feature' => new Feature('some.feature', true), - 1 => new Feature('other.feature', false), + 'some.feature' => true, + 1 => false, ]; $this->expectException(InvalidArgumentException::class); @@ -63,16 +59,14 @@ public function all_features_must_have_a_string_key() new FeatureConfiguration($features); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function a_feature_can_be_queried_for_presence() { $features = [ - 'some.feature' => new Feature('some.feature', true), - 'other.feature' => new Feature('other.feature', false) + 'some.feature' => true, + 'other.feature' => false ]; $featureConfiguration = new FeatureConfiguration($features); @@ -82,16 +76,14 @@ public function a_feature_can_be_queried_for_presence() $this->assertFalse($featureConfiguration->hasFeature('not.configured')); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function a_feature_is_correctly_reported_to_be_enabled() { $features = [ - 'some.feature' => new Feature('some.feature', true), - 'disabled.feature' => new Feature('disabled.feature', false) + 'some.feature' => true, + 'disabled.feature' => false ]; $featureConfiguration = new FeatureConfiguration($features); @@ -100,16 +92,14 @@ public function a_feature_is_correctly_reported_to_be_enabled() $this->assertFalse($featureConfiguration->isEnabled('disabled.feature')); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function querying_whether_a_not_configured_feature_is_enabled_causes_an_exception_to_be_thrown() { $features = [ - 'some.feature' => new Feature('some.feature', true), - 'other.feature' => new Feature('other.feature', false) + 'some.feature' => true, + 'other.feature' => false ]; $featureConfiguration = new FeatureConfiguration($features); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureTest.php b/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureTest.php index 40b02d33ba..0ca45777c7 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Configuration/FeatureTest.php @@ -27,12 +27,12 @@ class FeatureTest extends TestCase use MockeryPHPUnitIntegration; /** - * @test - * @group EngineBlockBundle - * @group Configuration - * @dataProvider \OpenConext\TestDataProvider::notStringOrEmptyString * @param mixed $notStringOrEmtpyString */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notStringOrEmptyString')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function feature_key_is_required_to_be_a_non_empty_string($notStringOrEmtpyString) { $this->expectException(InvalidArgumentException::class); @@ -41,12 +41,12 @@ public function feature_key_is_required_to_be_a_non_empty_string($notStringOrEmt } /** - * @test - * @group EngineBlockBundle - * @group Configuration - * @dataProvider \OpenConext\TestDataProvider::notBoolean * @param mixed $notBoolean */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notBoolean')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function is_enabled_must_be_a_boolean($notBoolean) { $this->expectException(InvalidArgumentException::class); @@ -54,11 +54,9 @@ public function is_enabled_must_be_a_boolean($notBoolean) new Feature('some.feature', $notBoolean); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function an_feature_created_as_enabled_is_enabled() { $feature = new Feature('some.feature', true); @@ -66,11 +64,9 @@ public function an_feature_created_as_enabled_is_enabled() $this->assertTrue($feature->isEnabled()); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function an_feature_created_as_disabled_is_disabled() { $feature = new Feature('some.feature', false); @@ -78,11 +74,9 @@ public function an_feature_created_as_disabled_is_disabled() $this->assertFalse($feature->isEnabled()); } - /** - * @test - * @group EngineBlockBundle - * @group Configuration - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Configuration')] + #[\PHPUnit\Framework\Attributes\Test] public function the_feature_key_can_be_retrieved() { $featureKey = 'some.feature.key'; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Controller/AttributeReleasePolicyControllerTest.php b/tests/unit/OpenConext/EngineBlockBundle/Controller/AttributeReleasePolicyControllerTest.php index 1e1ce38d68..810f3267d6 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Controller/AttributeReleasePolicyControllerTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Controller/AttributeReleasePolicyControllerTest.php @@ -30,27 +30,34 @@ use OpenConext\EngineBlockBundle\Http\Exception\BadApiRequestHttpException; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Security\Core\User\UserInterface; class AttributeReleasePolicyControllerTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group AttributeReleasePolicy - * @group AuthorizationChecker - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('AuthorizationChecker')] + #[\PHPUnit\Framework\Attributes\Test] public function access_is_denied_for_unauthorized_requests() { - $this->expectException(ApiAccessDeniedHttpException::class, 'ROLE_API_USER_PROFILE'); + $this->expectException(ApiAccessDeniedHttpException::class); $metadataService = $this->createDummyMetadataService(); $arpEnforcer = new EngineBlock_Arp_AttributeReleasePolicyEnforcer(); $authorizationChecker = $this->mockAuthorizationCheckerDenyingAccessToProfile(); - $arpController = new AttributeReleasePolicyController($authorizationChecker, $metadataService, $arpEnforcer); + $arpController = new AttributeReleasePolicyController( + $this->mockTokenStorage(), + $authorizationChecker, + $metadataService, + $arpEnforcer + ); $request = new Request(); $request->setMethod(Request::METHOD_POST); @@ -58,11 +65,9 @@ public function access_is_denied_for_unauthorized_requests() $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_that_cannot_be_decoded_as_an_array_is_invalid() { $this->expectException(BadApiRequestHttpException::class); @@ -71,18 +76,17 @@ public function a_request_that_cannot_be_decoded_as_an_array_is_invalid() $request = $this->createRequestWithContent('null'); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_that_does_not_contain_the_entity_ids_key_is_invalid() { $this->expectException(BadApiRequestHttpException::class); @@ -91,18 +95,17 @@ public function a_request_that_does_not_contain_the_entity_ids_key_is_invalid() $request = $this->createRequestWithContent('{}'); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_that_does_not_have_an_array_of_entity_ids_is_invalid() { $this->expectException(BadApiRequestHttpException::class); @@ -111,18 +114,17 @@ public function a_request_that_does_not_have_an_array_of_entity_ids_is_invalid() $request = $this->createRequestWithContent('{"entityIds": "some-entity-id"}'); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_that_does_not_contain_any_entity_ids_is_invalid() { $this->expectException(BadApiRequestHttpException::class); @@ -131,18 +133,17 @@ public function a_request_that_does_not_contain_any_entity_ids_is_invalid() $request = $this->createRequestWithContent('{"entityIds": []}'); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_that_does_not_contain_the_attributes_key_is_invalid() { $this->expectException(BadApiRequestHttpException::class); @@ -151,18 +152,17 @@ public function a_request_that_does_not_contain_the_attributes_key_is_invalid() $request = $this->createRequestWithContent('{"entityIds": ["some-entity-id"]}'); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function a_request_that_does_not_have_a_json_object_of_attributes_is_invalid() { $this->expectException(BadApiRequestHttpException::class); @@ -171,18 +171,17 @@ public function a_request_that_does_not_have_a_json_object_of_attributes_is_inva $request = $this->createRequestWithContent('{"entityIds": ["some-entity-id"], "attributes": "some-attribute"}'); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function attributes_should_have_strings_as_keys() { $this->expectException(BadApiRequestHttpException::class); @@ -193,18 +192,17 @@ public function attributes_should_have_strings_as_keys() ); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - * @group Json - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Group('Json')] + #[\PHPUnit\Framework\Attributes\Test] public function attributes_should_have_an_array_of_values() { $this->expectException(BadApiRequestHttpException::class); @@ -215,17 +213,16 @@ public function attributes_should_have_an_array_of_values() ); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); $arpController->applyArpAction($request); } - /** - * @test - * @group AttributeReleasePolicy - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Test] public function the_same_attributes_are_returned_as_given_if_no_service_provider_is_found() { $serializedJsonRequest = json_encode([ @@ -248,7 +245,8 @@ public function the_same_attributes_are_returned_as_given_if_no_service_provider $request = $this->createRequestWithContent($serializedJsonRequest); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $this->createDummyMetadataService(), new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); @@ -258,10 +256,8 @@ public function the_same_attributes_are_returned_as_given_if_no_service_provider $this->assertSame($expectedResponse, $response->getContent()); } - /** - * @test - * @group AttributeReleasePolicy - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Test] public function the_same_attributes_are_returned_as_given_if_no_arp_is_found() { $someEntityId = 'some-entity-id'; @@ -296,7 +292,8 @@ public function the_same_attributes_are_returned_as_given_if_no_arp_is_found() $metadataServiceWithServiceProviders = new MetadataService($metadataRepository); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $metadataServiceWithServiceProviders, new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); @@ -305,10 +302,8 @@ public function the_same_attributes_are_returned_as_given_if_no_arp_is_found() $this->assertSame($expectedResponse, $response->getContent()); } - /** - * @test - * @group AttributeReleasePolicy - */ + #[\PHPUnit\Framework\Attributes\Group('AttributeReleasePolicy')] + #[\PHPUnit\Framework\Attributes\Test] public function only_attributes_specified_in_arp_are_released() { $someEntityId = 'some-entity-id'; @@ -360,7 +355,8 @@ public function only_attributes_specified_in_arp_are_released() $metadataServiceWithServiceProviders = new MetadataService($metadataRepository); $arpController = new AttributeReleasePolicyController( - $this->mockAuthorizationCheckerGrantingAccessToProfile(), + $this->mockTokenStorage(), + $this->mockAccessGrantingDecisionManager(), $metadataServiceWithServiceProviders, new EngineBlock_Arp_AttributeReleasePolicyEnforcer ); @@ -369,30 +365,34 @@ public function only_attributes_specified_in_arp_are_released() $this->assertSame($expectedResponse, $response->getContent()); } - /** - * @return AuthorizationCheckerInterface - */ - public function mockAuthorizationCheckerGrantingAccessToProfile() + private function mockAccessGrantingDecisionManager(): AccessDecisionManagerInterface + { + $accessDecisionManager = $this->createMock(AccessDecisionManagerInterface::class); + $accessDecisionManager->method('decide')->willReturn(true); + + return $accessDecisionManager; + } + + private function mockTokenStorage(): TokenStorageInterface { - $authorizationChecker = Mockery::mock(AuthorizationCheckerInterface::class); - $authorizationChecker->shouldReceive('isGranted') - ->with('ROLE_API_USER_PROFILE') - ->andReturn(true); + $token = $this->createMock(TokenInterface::class); + $token->method('getUser')->willReturn($this->createMock(UserInterface::class)); - return $authorizationChecker; + $mock = $this->createMock(TokenStorageInterface::class); + $mock->method('getToken')->willReturn($token); + return $mock; } + /** * @return AuthorizationCheckerInterface */ - public function mockAuthorizationCheckerDenyingAccessToProfile() + public function mockAuthorizationCheckerDenyingAccessToProfile(): AccessDecisionManagerInterface { - $authorizationChecker = Mockery::mock(AuthorizationCheckerInterface::class); - $authorizationChecker->shouldReceive('isGranted') - ->with('ROLE_API_USER_PROFILE') - ->andReturn(false); + $accessDecisionManager = $this->createMock(AccessDecisionManagerInterface::class); + $accessDecisionManager->method('decide')->willReturn(false); - return $authorizationChecker; + return $accessDecisionManager; } /** diff --git a/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdTypeTest.php b/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdTypeTest.php index 14d06416e3..de1985864b 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdTypeTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonIdTypeTest.php @@ -18,7 +18,7 @@ namespace OpenConext\EngineBlockBundle\Doctrine\Type; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -33,7 +33,7 @@ class CollabPersonIdTypeTest extends TestCase use MockeryPHPUnitIntegration; /** - * @var MySqlPlatform + * @var MySQLPlatform */ private $platform; @@ -49,14 +49,12 @@ public static function setUpBeforeClass(): void public function setUp(): void { - $this->platform = new MySqlPlatform(); + $this->platform = new MySQLPlatform(); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_null_value_remains_null_in_to_sql_conversion() { $collabPersonIdType = Type::getType(CollabPersonIdType::NAME); @@ -66,11 +64,9 @@ public function a_null_value_remains_null_in_to_sql_conversion() $this->assertNull($value); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_collab_person_id_value_is_converted_to_the_correct_database_format() { $collabPersonIdType = Type::getType(CollabPersonIdType::NAME); @@ -83,12 +79,10 @@ public function a_collab_person_id_value_is_converted_to_the_correct_database_fo $this->assertEquals($collabPersonId, $output); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - * @dataProvider invalidPhpValueProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidPhpValueProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function an_invalid_value_causes_an_exception_upon_conversion_to_database_value($invalidValue) { $collabPersonIdType = Type::getType(CollabPersonIdType::NAME); @@ -100,7 +94,7 @@ public function an_invalid_value_causes_an_exception_upon_conversion_to_database /** * @return array */ - public function invalidPhpValueProvider() + public static function invalidPhpValueProvider() { return array_merge( TestDataProvider::notNull(), @@ -110,11 +104,9 @@ public function invalidPhpValueProvider() ); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_null_value_remains_null_when_converting_from_db_to_php_value() { $collabPersonIdType = Type::getType(CollabPersonIdType::NAME); @@ -124,11 +116,9 @@ public function a_null_value_remains_null_when_converting_from_db_to_php_value() $this->assertNull($value); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_non_null_value_is_converted_to_a_collab_person_id() { $collabPersonIdType = Type::getType(CollabPersonIdType::NAME); @@ -140,11 +130,9 @@ public function a_non_null_value_is_converted_to_a_collab_person_id() $this->assertEquals(new CollabPersonId($input), $output); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function an_invalid_database_value_causes_an_exception_upon_conversion() { $collabPersonIdType = Type::getType(CollabPersonIdType::NAME); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidTypeTest.php b/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidTypeTest.php index 37fbe12952..dd6be10001 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidTypeTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Doctrine/Type/CollabPersonUuidTypeTest.php @@ -18,7 +18,7 @@ namespace OpenConext\EngineBlockBundle\Doctrine\Type; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -32,7 +32,7 @@ class CollabPersonUuidTypeTest extends TestCase use MockeryPHPUnitIntegration; /** - * @var MySqlPlatform + * @var MySQLPlatform */ private $platform; @@ -48,14 +48,12 @@ public static function setUpBeforeClass(): void public function setUp(): void { - $this->platform = new MySqlPlatform(); + $this->platform = new MySQLPlatform(); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_null_value_remains_null_in_to_sql_conversion() { $collabPersonUuidType = Type::getType(CollabPersonUuidType::NAME); @@ -65,11 +63,9 @@ public function a_null_value_remains_null_in_to_sql_conversion() $this->assertNull($value); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_collab_person_uuid_value_is_converted_to_the_correct_format() { $collabPersonUuidType = Type::getType(CollabPersonUuidType::NAME); @@ -82,12 +78,10 @@ public function a_collab_person_uuid_value_is_converted_to_the_correct_format() $this->assertEquals($uuid, $output); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - * @dataProvider invalidPhpValueProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidPhpValueProvider')] + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function an_invalid_value_causes_an_exception_upon_conversion_to_database_value($invalidValue) { $collabPersonUuidType = Type::getType(CollabPersonUuidType::NAME); @@ -99,7 +93,7 @@ public function an_invalid_value_causes_an_exception_upon_conversion_to_database /** * @return array */ - public function invalidPhpValueProvider() + public static function invalidPhpValueProvider() { return array_merge( TestDataProvider::notNull(), @@ -110,11 +104,9 @@ public function invalidPhpValueProvider() ); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_null_value_remains_null_when_converting_from_db_to_php_value() { $collabPersonUuidType = Type::getType(CollabPersonUuidType::NAME); @@ -124,11 +116,9 @@ public function a_null_value_remains_null_when_converting_from_db_to_php_value() $this->assertNull($value); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function a_non_null_value_is_converted_to_a_collab_person_uuid() { $collabPersonUuidType = Type::getType(CollabPersonUuidType::NAME); @@ -140,11 +130,9 @@ public function a_non_null_value_is_converted_to_a_collab_person_uuid() $this->assertTrue((new CollabPersonUuid($uuid))->equals($output)); } - /** - * @test - * @group EngineBlockBundle - * @group Doctrine - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlockBundle')] + #[\PHPUnit\Framework\Attributes\Group('Doctrine')] + #[\PHPUnit\Framework\Attributes\Test] public function an_invalid_database_value_causes_an_exception_upon_conversion() { $collabPersonUuidType = Type::getType(CollabPersonUuidType::NAME); diff --git a/tests/unit/OpenConext/EngineBlockBundle/EventListener/ExecutionTimeTrackerEventListenerTest.php b/tests/unit/OpenConext/EngineBlockBundle/EventListener/ExecutionTimeTrackerEventListenerTest.php index cad38d2f21..897426471b 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/EventListener/ExecutionTimeTrackerEventListenerTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/EventListener/ExecutionTimeTrackerEventListenerTest.php @@ -30,10 +30,8 @@ class ExecutionTimeTrackerEventListenerTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_tracker_is_tracking_when_it_has_been_started() { $stopwatch = Mockery::mock(Stopwatch::class); @@ -54,10 +52,8 @@ public function execution_time_tracker_is_tracking_when_it_has_been_started() $this->assertTrue($isTracking); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_tracker_is_not_tracking_when_it_has_not_been_started() { $stopwatch = Mockery::mock(Stopwatch::class); @@ -73,10 +69,8 @@ public function execution_time_tracker_is_not_tracking_when_it_has_not_been_star $this->assertFalse($isTracking); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function exceeding_of_execution_time_is_determined_correctly() { $executionTimeInMilliseconds = 10; @@ -137,10 +131,8 @@ public function exceeding_of_execution_time_is_determined_correctly() ); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function how_much_time_remains_until_a_given_time_that_is_longer_than_the_current_execution_time_is_reached_is_calculated_correctly() { $longerTimeInMilliseconds = 1000; @@ -168,10 +160,8 @@ public function how_much_time_remains_until_a_given_time_that_is_longer_than_the $this->assertEquals($longerTimeInMilliseconds, $timeRemaining->getExecutionTime()); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function there_is_no_time_remaining_until_a_given_time_that_is_the_same_as_the_current_execution_time() { $sameTimeInMilliseconds = 10; @@ -198,10 +188,8 @@ public function there_is_no_time_remaining_until_a_given_time_that_is_the_same_a $this->assertEquals(ExecutionTime::of(0), $timeRemaining); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function there_is_no_time_remaining_until_a_given_time_that_is_shorter_than_the_current_execution_time() { $currentExecutionTimeInMilliseconds = 10; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Exception/ArtTest.php b/tests/unit/OpenConext/EngineBlockBundle/Exception/ArtTest.php index fe50f2bdc2..168a1020d7 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Exception/ArtTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Exception/ArtTest.php @@ -28,19 +28,15 @@ class ArtTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group art - */ + #[\PHPUnit\Framework\Attributes\Group('art')] + #[\PHPUnit\Framework\Attributes\Test] public function art_code_is_numeric() { $this->assertTrue(is_numeric(Art::forException(new Exception)), 'Expected numeric Art code'); } - /** - * @test - * @group art - */ + #[\PHPUnit\Framework\Attributes\Group('art')] + #[\PHPUnit\Framework\Attributes\Test] public function art_code_is_distinct_per_exception_type() { $art1 = new Exception(); @@ -49,10 +45,8 @@ public function art_code_is_distinct_per_exception_type() $this->assertNotEquals($art1, $art2, 'Expected different art code for different exception type'); } - /** - * @test - * @group art - */ + #[\PHPUnit\Framework\Attributes\Group('art')] + #[\PHPUnit\Framework\Attributes\Test] public function art_code_is_distinct_per_message() { $art1 = new Exception('one'); @@ -62,13 +56,13 @@ public function art_code_is_distinct_per_message() } /** - * @test - * @group art - * @dataProvider artCodeWithStrippedVariables * * @param Exception $exception * @param int $expectedArtCode */ + #[\PHPUnit\Framework\Attributes\DataProvider('artCodeWithStrippedVariables')] + #[\PHPUnit\Framework\Attributes\Group('art')] + #[\PHPUnit\Framework\Attributes\Test] public function exception_translates_to_art_code_with_variables_stripped(Exception $exception, $expectedArtCode) { $this->assertEquals( @@ -77,7 +71,7 @@ public function exception_translates_to_art_code_with_variables_stripped(Excepti ); } - public function artCodeWithStrippedVariables() + public static function artCodeWithStrippedVariables() { $artCode = Art::forException( new Exception('This is a \'good\' message') diff --git a/tests/unit/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactoryTest.php b/tests/unit/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactoryTest.php index b59b0b66b2..603c4fb290 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactoryTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Http/Cookies/CookieFactoryTest.php @@ -26,9 +26,7 @@ class CookieFactoryTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function returns_the_cookie() { $now = new DateTimeImmutable(); @@ -45,9 +43,7 @@ public function returns_the_cookie() $this->assertFalse($actual->isSecure()); } - /** - * @test - */ + #[\PHPUnit\Framework\Attributes\Test] public function sets_the_expiry_time() { $now = new DateTimeImmutable(); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/AttributeTest.php b/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/AttributeTest.php index 1b7a19bc8b..b48ae68c0e 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/AttributeTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/AttributeTest.php @@ -27,10 +27,8 @@ class AttributeTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function an_attribute_without_a_datatype_is_serialized_correctly() { $attribute = new Attribute; @@ -49,10 +47,8 @@ public function an_attribute_without_a_datatype_is_serialized_correctly() $this->assertEquals($expectedSerializedAttribute, $actualSerializedAttribute); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function an_attribute_with_a_datatype_is_serialized_correctly() { $attribute = new Attribute; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/RequestTest.php b/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/RequestTest.php index 3035dd091e..7ae10d07b2 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/RequestTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/RequestTest.php @@ -35,6 +35,8 @@ class RequestTest extends TestCase private $validIdpEntityId; private $validSpEntityId; private $validResponseAttributes; + private string $validRemoteIp; + private string $validClientId; public function setUp(): void { @@ -48,10 +50,8 @@ public function setUp(): void $this->validRemoteIp = '2001:610:0:8010::213'; } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_requests_response_attribute_keys_must_be_strings() { $this->expectException(InvalidArgumentException::class); @@ -72,12 +72,9 @@ public function a_pdp_requests_response_attribute_keys_must_be_strings() ); } - /** - * @test - * @group Pdp - * - * @dataProvider \OpenConext\TestDataProvider::notArray() - */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notArray')] + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_requests_response_attribute_values_must_be_arrays($nonArray) { $this->expectException(InvalidArgumentException::class); @@ -97,10 +94,8 @@ public function a_pdp_requests_response_attribute_values_must_be_arrays($nonArra ); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_request_is_built_correctly() { $resourceAttributeValues = [ @@ -128,10 +123,8 @@ public function a_pdp_request_is_built_correctly() $this->assertEquals($expectedRequest, $actualRequest); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_request_is_serialized_correctly() { $fixturePath = __DIR__.'/../fixture/request.json'; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/ResponseTest.php b/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/ResponseTest.php index efab7b5c33..d1be765e8b 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/ResponseTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Pdp/Dto/ResponseTest.php @@ -36,13 +36,11 @@ class ResponseTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_response_without_a_response_key_is_invalid() { - $this->expectException('\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException'); + $this->expectException(\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException::class); $this->expectExceptionMessage('Key: Response was not found in the PDP response'); $responseJson = file_get_contents(__DIR__ . '/../fixture/invalid/response_without_response_key.json'); @@ -50,13 +48,11 @@ public function a_pdp_response_without_a_response_key_is_invalid() Response::fromData(json_decode($responseJson, true)); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_response_without_a_response_key_as_an_array_is_invalid() { - $this->expectException('\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException'); + $this->expectException(\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException::class); $this->expectExceptionMessage('Response is not an array'); $responseJson = file_get_contents(__DIR__ . '/../fixture/invalid/response_without_response_array.json'); @@ -64,13 +60,11 @@ public function a_pdp_response_without_a_response_key_as_an_array_is_invalid() Response::fromData(json_decode($responseJson, true)); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_response_with_an_empty_response_is_invalid() { - $this->expectException('\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException'); + $this->expectException(\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException::class); $this->expectExceptionMessage('No response data found'); $responseJson = file_get_contents(__DIR__ . '/../fixture/invalid/response_with_empty_response.json'); @@ -78,13 +72,11 @@ public function a_pdp_response_with_an_empty_response_is_invalid() Response::fromData(json_decode($responseJson, true)); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_response_without_a_status_is_invalid() { - $this->expectException('\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException'); + $this->expectException(\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException::class); $this->expectExceptionMessage('Key: Status was not found in the PDP response'); $responseJson = file_get_contents(__DIR__ . '/../fixture/invalid/response_without_status_key.json'); @@ -92,13 +84,11 @@ public function a_pdp_response_without_a_status_is_invalid() Response::fromData(json_decode($responseJson, true)); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_response_without_a_policy_identifier_is_invalid() { - $this->expectException('\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException'); + $this->expectException(\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException::class); $this->expectExceptionMessage('Key: PolicyIdentifier was not found in the PDP response'); $responseJson = file_get_contents(__DIR__ . '/../fixture/invalid/response_without_policy_identifier_key.json'); @@ -106,13 +96,11 @@ public function a_pdp_response_without_a_policy_identifier_is_invalid() Response::fromData(json_decode($responseJson, true)); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_response_without_a_decision_is_invalid() { - $this->expectException('\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException'); + $this->expectException(\OpenConext\EngineBlockBundle\Exception\InvalidPdpResponseException::class); $this->expectExceptionMessage('Key: Decision was not found in the PDP response'); $responseJson = file_get_contents(__DIR__ . '/../fixture/invalid/response_without_decision_key.json'); @@ -121,13 +109,12 @@ public function a_pdp_response_without_a_decision_is_invalid() } /** - * @test - * @group Pdp - * - * @dataProvider pdpResponseProvider * @param string $fixtureName * @param Response $expectedResponse */ + #[\PHPUnit\Framework\Attributes\DataProvider('pdpResponseProvider')] + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function pdp_responses_are_deserialized_correctly($fixtureName, $expectedResponse) { $responseString = file_get_contents(__DIR__.'/../fixture/response_'. $fixtureName . '.json'); @@ -141,17 +128,17 @@ public function pdp_responses_are_deserialized_correctly($fixtureName, $expected ); } - public function pdpResponseProvider() + public static function pdpResponseProvider() { return [ - 'Decision: Deny' => ['deny', $this->buildDenyResponse()], - 'Decision: Permit' => ['permit', $this->buildPermitResponse()], - 'Decision: NotApplicable' => ['not_applicable', $this->buildNotApplicableResponse()], - 'Decision: Indeterminate' => ['indeterminate', $this->buildIndeterminateResponse()], + 'Decision: Deny' => ['deny', self::buildDenyResponse()], + 'Decision: Permit' => ['permit', self::buildPermitResponse()], + 'Decision: NotApplicable' => ['not_applicable', self::buildNotApplicableResponse()], + 'Decision: Indeterminate' => ['indeterminate', self::buildIndeterminateResponse()], ]; } - private function buildDenyResponse() + private static function buildDenyResponse() { $response = new Response; @@ -198,7 +185,7 @@ private function buildDenyResponse() return $response; } - private function buildPermitResponse() + private static function buildPermitResponse() { $response = new Response; @@ -230,7 +217,7 @@ private function buildPermitResponse() return $response; } - private function buildNotApplicableResponse() + private static function buildNotApplicableResponse() { $response = new Response; @@ -249,7 +236,7 @@ private function buildNotApplicableResponse() return $response; } - private function buildIndeterminateResponse() + private static function buildIndeterminateResponse() { $response = new Response; diff --git a/tests/unit/OpenConext/EngineBlockBundle/Pdp/PdpClientTest.php b/tests/unit/OpenConext/EngineBlockBundle/Pdp/PdpClientTest.php index 476de0d345..c84ce4d82d 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Pdp/PdpClientTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Pdp/PdpClientTest.php @@ -32,12 +32,9 @@ class PdpClientTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group Pdp - * - * @dataProvider pdpResponseNameProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('pdpResponseNameProvider')] + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_pdp_client_gives_policy_decisions_based_on_pdp_responses_to_pdp_requests($responseName) { $pdpRequest = Request::from('clientid', 'subject', 'idp', 'sp', [], '10.11.12.13'); @@ -55,7 +52,7 @@ public function a_pdp_client_gives_policy_decisions_based_on_pdp_responses_to_pd $this->assertInstanceOf(PolicyDecision::class, $policyDecision); } - public function pdpResponseNameProvider() + public static function pdpResponseNameProvider() { return [ ['deny'], diff --git a/tests/unit/OpenConext/EngineBlockBundle/Pdp/PolicyDecisionTest.php b/tests/unit/OpenConext/EngineBlockBundle/Pdp/PolicyDecisionTest.php index 4ed604f5dc..3fea60fbe1 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Pdp/PolicyDecisionTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Pdp/PolicyDecisionTest.php @@ -30,13 +30,12 @@ class PolicyDecisionTest extends TestCase use MockeryPHPUnitIntegration; /** - * @test - * @group Pdp - * - * @dataProvider pdpResponseAndExpectedPermissionProvider * @param $responseName * @param $expectedPermission */ + #[\PHPUnit\Framework\Attributes\DataProvider('pdpResponseAndExpectedPermissionProvider')] + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function the_correct_policy_decision_should_be_made_based_on_a_pdp_response( $responseName, $expectedPermission @@ -49,10 +48,8 @@ public function the_correct_policy_decision_should_be_made_based_on_a_pdp_respon $this->assertEquals($expectedPermission, $decision->permitsAccess()); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_deny_policys_localized_messages_are_parsed_correctly() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_deny.json'), true); @@ -70,10 +67,8 @@ public function a_deny_policys_localized_messages_are_parsed_correctly() $this->assertEquals($expectedDenyMessageNl, $denyMessageNl); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_deny_policys_localized_deny_message_correctly_falls_back_to_the_default_locale_if_the_given_locale_was_not_found() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_deny.json'), true); @@ -90,10 +85,8 @@ public function a_deny_policys_localized_deny_message_correctly_falls_back_to_th } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_deny_policy_with_idp_specific_message_is_parsed_correctly() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_deny_idp_specific.json'), true); @@ -117,10 +110,8 @@ public function a_deny_policy_with_idp_specific_message_is_parsed_correctly() } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function an_indeterminate_policys_status_message_is_acquired_correctly() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_indeterminate.json'), true); @@ -138,13 +129,11 @@ public function an_indeterminate_policys_status_message_is_acquired_correctly() $this->assertEquals($expectedStatusMessage, $statusMessage); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_status_message_cannot_be_acquired_from_a_policy_that_has_none() { - $this->expectException('\OpenConext\EngineBlock\Exception\RuntimeException'); + $this->expectException(\OpenConext\EngineBlock\Exception\RuntimeException::class); $this->expectExceptionMessage('No status message found'); $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_deny.json'), true); @@ -154,10 +143,8 @@ public function a_status_message_cannot_be_acquired_from_a_policy_that_has_none( $decision->getStatusMessage(); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_localized_deny_message_cannot_be_acquired_if_the_chosen_and_the_default_locale_are_not_present() { $nonPresentLocale = 'de'; @@ -177,10 +164,8 @@ public function a_localized_deny_message_cannot_be_acquired_if_the_chosen_and_th $decision->getLocalizedDenyMessage($nonPresentLocale, $nonPresentDefaultLocale); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_localized_deny_message_cannot_be_acquired_from_a_policy_decision_that_does_not_have_one() { $this->expectException('RuntimeException'); @@ -193,10 +178,8 @@ public function a_localized_deny_message_cannot_be_acquired_from_a_policy_decisi $decision->getLocalizedDenyMessage('en'); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_response_without_obligations_has_no_obligations() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_permit.json'), true); @@ -205,10 +188,8 @@ public function a_response_without_obligations_has_no_obligations() $this->assertNull($response->obligations); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_response_with_obligation_has_obligations() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_permit_obligation.json'), true); @@ -229,10 +210,8 @@ public function a_response_with_obligation_has_obligations() $this->assertEquals($expected_attributeAssignment, $response->obligations[0]->attributeAssignments[0]); } - /** - * @test - * @group Pdp - */ + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function a_response_with_multiple_obligations_has_obligations() { $responseJson = json_decode(file_get_contents(__DIR__ . '/fixture/response_permit_obligations.json'), true); @@ -255,13 +234,12 @@ public function a_response_with_multiple_obligations_has_obligations() } /** - * @test - * @group Pdp - * - * @dataProvider pdpResponseAndExpectedLoaProvider * @param $responseName * @param $expectedLoa */ + #[\PHPUnit\Framework\Attributes\DataProvider('pdpResponseAndExpectedLoaProvider')] + #[\PHPUnit\Framework\Attributes\Group('Pdp')] + #[\PHPUnit\Framework\Attributes\Test] public function the_correct_loa_obligations_should_be_given_based_on_a_pdp_response( $responseName, $expectedLoa @@ -274,7 +252,7 @@ public function the_correct_loa_obligations_should_be_given_based_on_a_pdp_respo $this->assertEquals($expectedLoa, $decision->getStepupObligations()); } - public function pdpResponseAndExpectedPermissionProvider() + public static function pdpResponseAndExpectedPermissionProvider() { return [ 'Deny response does not permit access' => ['deny', false], @@ -286,7 +264,7 @@ public function pdpResponseAndExpectedPermissionProvider() ]; } - public function pdpResponseAndExpectedLoaProvider() + public static function pdpResponseAndExpectedLoaProvider() { return [ 'Not applicable response without obgligation yields empty list' => ['not_applicable', []], diff --git a/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/MetadataTest.php b/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/MetadataTest.php index 9561d9013d..e46ba3e3a5 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/MetadataTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/MetadataTest.php @@ -39,7 +39,7 @@ class MetadataTest extends TestCase private $metadataDefinition; /** - * @var TranslatorInterface + * @var \Symfony\Contracts\Translation\TranslatorInterface */ private $translator; @@ -48,17 +48,16 @@ protected function setUp(): void // Note that this unit tests depends on a real EngingeBlock_EngineBlock_Attributes_Metadata instance from the // Di container. $this->metadataDefinition = \EngineBlock_ApplicationSingleton::getInstance()->getDiContainer()->getAttributeMetadata(); - $this->translator = m::mock(TranslatorInterface::class); + $this->translator = m::mock(\Symfony\Contracts\Translation\TranslatorInterface::class); $this->metadata = new Metadata($this->metadataDefinition, $this->translator); } /** * This test uses the tests/resources/config/attributes-fixture.json fixture * @see \EngineBlock_Application_TestDiContainer::getAttributeMetadata - * - * @test - * @group EngineBlock */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Test] public function sort_by_display_order_favors_ordered_items_ungrouped() { // norEduPersonBirthDate is an unordered item, should be sorted at the bottom @@ -81,10 +80,8 @@ public function sort_by_display_order_favors_ordered_items_ungrouped() $this->assertEquals($expectedOrder, array_keys($ordered['idp'])); } - /** - * @test - * @group EngineBlock - */ + #[\PHPUnit\Framework\Attributes\Group('EngineBlock')] + #[\PHPUnit\Framework\Attributes\Test] public function sort_by_display_order_favors_ordered_items_grouped() { // norEduPersonBirthDate is an unordered item, should be sorted at the bottom diff --git a/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/SpacelessTest.php b/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/SpacelessTest.php new file mode 100644 index 0000000000..ee47fa848f --- /dev/null +++ b/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/SpacelessTest.php @@ -0,0 +1,50 @@ +extension = new Spaceless(); + } + + public function testItRemovesWhitespaceBetweenTags(): void + { + $input = "
\n
text "; + $expected = '
text '; + $this->assertSame($expected, $this->extension->spaceless($input)); + } + + public function testItReturnsEmptyStringForNull(): void + { + $this->assertSame('', $this->extension->spaceless(null)); + } + + public function testItTrimsOuterWhitespace(): void + { + $input = "

a

b

"; + $expected = '

a

b

'; + $this->assertSame($expected, $this->extension->spaceless($input)); + } +} + diff --git a/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/WayfTest.php b/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/WayfTest.php index 43e8f58987..85ad48ec9a 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/WayfTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Twig/Extensions/Extension/WayfTest.php @@ -37,7 +37,7 @@ class WayfTest extends TestCase protected function setUp(): void { $this->requestStack = $this->createMock(RequestStack::class); - $this->translator = $this->createMock(TranslatorInterface::class); + $this->translator = $this->createMock(\Symfony\Contracts\Translation\TranslatorInterface::class); $this->wayf = new Wayf($this->requestStack, $this->translator); } @@ -101,9 +101,7 @@ public static function previousSelectionProvider(): array ]; } - /** - * @dataProvider previousSelectionProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('previousSelectionProvider')] public function testGetConnectedIdpsWithPreviousSelection(string $storedCookieValue, string $expectedName) { // Create a mock request with cookie diff --git a/tests/unit/OpenConext/EngineBlockBundle/Value/ExecutionTimeTest.php b/tests/unit/OpenConext/EngineBlockBundle/Value/ExecutionTimeTest.php index 7fbfc70d23..c42ef9a0bb 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Value/ExecutionTimeTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Value/ExecutionTimeTest.php @@ -27,12 +27,9 @@ class ExecutionTimeTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @test - * @group execution-time - * - * @dataProvider \OpenConext\TestDataProvider::notInteger() - */ + #[\PHPUnit\Framework\Attributes\DataProviderExternal(\OpenConext\TestDataProvider::class, 'notInteger')] + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_in_milliseconds_can_only_be_an_integer($notInteger) { $this->expectException(InvalidArgumentException::class); @@ -40,10 +37,8 @@ public function execution_time_in_milliseconds_can_only_be_an_integer($notIntege ExecutionTime::of($notInteger); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_equals_a_given_other_execution_time() { $executionTime = ExecutionTime::of(1); @@ -54,10 +49,8 @@ public function execution_time_equals_a_given_other_execution_time() $this->assertTrue($areExecutionTimesTheSame); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_does_not_equal_a_given_other_execution_time() { $executionTime = ExecutionTime::of(1); @@ -68,10 +61,8 @@ public function execution_time_does_not_equal_a_given_other_execution_time() $this->assertFalse($areExecutionTimesTheSame); } - /** - * @test - * @group execution-time - */ + #[\PHPUnit\Framework\Attributes\Group('execution-time')] + #[\PHPUnit\Framework\Attributes\Test] public function execution_time_is_converted_to_microseconds() { $executionTime = ExecutionTime::of(1); diff --git a/tests/unit/OpenConext/EngineBlockBundle/Value/FeedbackInformationTest.php b/tests/unit/OpenConext/EngineBlockBundle/Value/FeedbackInformationTest.php index b7f4da382d..e1db3cc6e7 100644 --- a/tests/unit/OpenConext/EngineBlockBundle/Value/FeedbackInformationTest.php +++ b/tests/unit/OpenConext/EngineBlockBundle/Value/FeedbackInformationTest.php @@ -26,9 +26,7 @@ class FeedbackInformationTest extends TestCase { use MockeryPHPUnitIntegration; - /** - * @dataProvider attributePredictions - */ + #[\PHPUnit\Framework\Attributes\DataProvider('attributePredictions')] public function test_attr_safe_key_is_returned($identifier, $input, $expectation) { $feedbackInfo = new FeedbackInformation($input, 'Test value'); @@ -40,7 +38,7 @@ public function test_attr_safe_key_is_returned($identifier, $input, $expectation ); } - public function attributePredictions() + public static function attributePredictions() { return [ ['with whitespace', 'my attribute', 'my-attribute'], diff --git a/theme/base/templates/layouts/scripts/default.html.twig b/theme/base/templates/layouts/scripts/default.html.twig index 440c63c0ff..d9847d2a36 100644 --- a/theme/base/templates/layouts/scripts/default.html.twig +++ b/theme/base/templates/layouts/scripts/default.html.twig @@ -12,13 +12,13 @@ {% block title %}{{ defaultTitle }}{% endblock %} - {% block stylesheets %}{% spaceless %} + {% block stylesheets %}{% apply spaceless %} - {% endspaceless %}{% endblock %} + {% endapply %}{% endblock %} {% block nojs %}{% endblock %} diff --git a/theme/base/templates/layouts/scripts/language-switcher.html.twig b/theme/base/templates/layouts/scripts/language-switcher.html.twig index e58fa2e12a..6260b9b2ee 100644 --- a/theme/base/templates/layouts/scripts/language-switcher.html.twig +++ b/theme/base/templates/layouts/scripts/language-switcher.html.twig @@ -15,11 +15,11 @@ {% else %}
    - {% for locale in supportedLocales() %}{% spaceless %} + {% for locale in supportedLocales() %}{% apply spaceless %}
  • {{ locale | upper}}
  • - {% endspaceless %}{% endfor %} + {% endapply %}{% endfor %}
{% endif %} {% endmacro form %} diff --git a/theme/base/templates/layouts/scripts/notConverted.twig b/theme/base/templates/layouts/scripts/notConverted.twig index 959522099b..a408c4064d 100644 --- a/theme/base/templates/layouts/scripts/notConverted.twig +++ b/theme/base/templates/layouts/scripts/notConverted.twig @@ -3,9 +3,9 @@ {% block title %}{{ parent() }}{% if pageTitle is defined %} - {{ pageTitle }} {% endif %}{% endblock %} {% block containerClasses %}l-container wide{% endblock %} -{% block stylesheets %}{% spaceless %} +{% block stylesheets %}{% apply spaceless %} -{% endspaceless %}{% endblock %} +{% endapply %}{% endblock %} {% block header %} {% include '@theme/Default/Partials/notConverted/header.html.twig' %} diff --git a/theme/base/templates/modules/Authentication/View/Metadata/idp.xml.twig b/theme/base/templates/modules/Authentication/View/Metadata/idp.xml.twig index 1aae7a165f..1640ab71ee 100644 --- a/theme/base/templates/modules/Authentication/View/Metadata/idp.xml.twig +++ b/theme/base/templates/modules/Authentication/View/Metadata/idp.xml.twig @@ -1,4 +1,4 @@ -{% spaceless %} +{% apply spaceless %} @@ -30,4 +30,4 @@ {% endif %} -{% endspaceless %} +{% endapply %} diff --git a/theme/base/templates/modules/Authentication/View/Metadata/idps.xml.twig b/theme/base/templates/modules/Authentication/View/Metadata/idps.xml.twig index c2bef6b5f9..7cc000ed03 100644 --- a/theme/base/templates/modules/Authentication/View/Metadata/idps.xml.twig +++ b/theme/base/templates/modules/Authentication/View/Metadata/idps.xml.twig @@ -1,4 +1,4 @@ -{% spaceless %} +{% apply spaceless %} {% for metadata in metadataCollection %} @@ -33,4 +33,4 @@ {% endfor %} -{% endspaceless %} +{% endapply %} diff --git a/theme/base/templates/modules/Authentication/View/Proxy/Partials/Consent/Attributes/tooltip.html.twig b/theme/base/templates/modules/Authentication/View/Proxy/Partials/Consent/Attributes/tooltip.html.twig index 759b670c39..fd5039678a 100644 --- a/theme/base/templates/modules/Authentication/View/Proxy/Partials/Consent/Attributes/tooltip.html.twig +++ b/theme/base/templates/modules/Authentication/View/Proxy/Partials/Consent/Attributes/tooltip.html.twig @@ -13,7 +13,7 @@ } %} - {% spaceless %} + {% apply spaceless %} - {% endspaceless %} + {% endapply %} {% endif %} diff --git a/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/idp/idpList.html.twig b/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/idp/idpList.html.twig index e7eb6da332..b21ba191a0 100644 --- a/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/idp/idpList.html.twig +++ b/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/idp/idpList.html.twig @@ -1,12 +1,12 @@ {% set cutoffMet = cutoffPointForShowingUnfilteredIdps < idpList|length %} -{% spaceless %} +{% apply spaceless %}
    -{% endspaceless %} +{% endapply %} {# First show all connected Idps #} {% for idp in idpList %} {% if idp['connected'] is defined and idp['connected'] %} diff --git a/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/preselection.html.twig b/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/preselection.html.twig index 42f965b1a4..f8489a3134 100644 --- a/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/preselection.html.twig +++ b/theme/base/templates/modules/Authentication/View/Proxy/Partials/WAYF/preselection.html.twig @@ -4,14 +4,14 @@ {{ 'wayf_your_accounts'|trans }} - {% spaceless %} + {% apply spaceless %}
    - {% endspaceless %} + {% endapply %} diff --git a/theme/base/templates/modules/Authentication/View/Proxy/form.html.twig b/theme/base/templates/modules/Authentication/View/Proxy/form.html.twig index 333c87801c..0f27f48b2c 100644 --- a/theme/base/templates/modules/Authentication/View/Proxy/form.html.twig +++ b/theme/base/templates/modules/Authentication/View/Proxy/form.html.twig @@ -13,9 +13,9 @@ - {% block stylesheets %}{% spaceless %} + {% block stylesheets %}{% apply spaceless %} - {% endspaceless %}{% endblock %} + {% endapply %}{% endblock %}
    diff --git a/theme/base/templates/modules/Default/View/Error/error.html.twig b/theme/base/templates/modules/Default/View/Error/error.html.twig index 04ee1f09b5..f2a657674c 100644 --- a/theme/base/templates/modules/Default/View/Error/error.html.twig +++ b/theme/base/templates/modules/Default/View/Error/error.html.twig @@ -1,9 +1,9 @@ {% extends '@themeLayouts/scripts/notConverted.twig' %} {% import "@themeLayouts/scripts/language-switcher.html.twig" as languageSwitcher %} -{% block stylesheets %}{% spaceless %} +{% block stylesheets %}{% apply spaceless %} -{% endspaceless %}{% endblock %} +{% endapply %}{% endblock %} {% set feedbackInfoMap = feedbackInfo().data %} {% set hideHeader = true %} @@ -77,7 +77,7 @@

    {{ 'error_help_desc'|trans }}

    - {% spaceless %}{% include "@theme/Default/View/Error/partial/footer.html.twig" %}{% endspaceless %} + {% apply spaceless %}{% include "@theme/Default/View/Error/partial/footer.html.twig" %}{% endapply %} {% endblock %} diff --git a/theme/base/templates/modules/Default/View/Error/method-not-allowed.html.twig b/theme/base/templates/modules/Default/View/Error/method-not-allowed.html.twig index 8df5637b02..2f50ab069f 100644 --- a/theme/base/templates/modules/Default/View/Error/method-not-allowed.html.twig +++ b/theme/base/templates/modules/Default/View/Error/method-not-allowed.html.twig @@ -15,7 +15,7 @@ {{ 'error_405_desc'|trans({'%requestMethod%': requestMethod, '%uri%': uri,'%allowedMethods%': allowedMethods}) }} - {% spaceless %}{% include "@theme/Default/View/Error/partial/footer.html.twig" %}{% endspaceless %} + {% apply spaceless %}{% include "@theme/Default/View/Error/partial/footer.html.twig" %}{% endapply %} {% endblock %} diff --git a/theme/base/templates/modules/Default/View/Error/not-found.html.twig b/theme/base/templates/modules/Default/View/Error/not-found.html.twig index 67373a8d46..1f7e8d40e6 100644 --- a/theme/base/templates/modules/Default/View/Error/not-found.html.twig +++ b/theme/base/templates/modules/Default/View/Error/not-found.html.twig @@ -15,7 +15,7 @@ {{ 'error_404_desc'|trans }} - {% spaceless %}{% include "@theme/Default/View/Error/partial/footer.html.twig" %}{% endspaceless %} + {% apply spaceless %}{% include "@theme/Default/View/Error/partial/footer.html.twig" %}{% endapply %} {% endblock %} diff --git a/theme/openconext/templates/layouts/scripts/default.html.twig b/theme/openconext/templates/layouts/scripts/default.html.twig index d83d0edaed..a1d87c8183 100644 --- a/theme/openconext/templates/layouts/scripts/default.html.twig +++ b/theme/openconext/templates/layouts/scripts/default.html.twig @@ -10,9 +10,9 @@ - {% block stylesheets %}{% spaceless %} + {% block stylesheets %}{% apply spaceless %} - {% endspaceless %}{% endblock %} + {% endapply %}{% endblock %}