diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 557eda9c29893..f860984a52f0c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | 7.4 for features / 6.4, 7.2, or 7.3 for bug fixes +| Branch? | 7.4 for features / 6.4, 7.3 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no diff --git a/.github/expected-missing-return-types.diff b/.github/expected-missing-return-types.diff index 679740ed3a33c..2f801bca938d5 100644 --- a/.github/expected-missing-return-types.diff +++ b/.github/expected-missing-return-types.diff @@ -7,6 +7,16 @@ git checkout src/Symfony/Contracts/Service/ResetInterface.php (echo "$head" && echo && git diff -U2 src/ | grep '^index ' -v) > .github/expected-missing-return-types.diff git checkout composer.json src/ +diff --git a/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php b/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php +--- a/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php ++++ b/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php +@@ -21,5 +21,5 @@ trait RuntimeLoaderProvider + * @return void + */ +- protected function registerTwigRuntimeLoader(Environment $environment, FormRenderer $renderer) ++ protected function registerTwigRuntimeLoader(Environment $environment, FormRenderer $renderer): void + { + $loader = $this->createMock(RuntimeLoaderInterface::class); diff --git a/src/Symfony/Component/BrowserKit/AbstractBrowser.php b/src/Symfony/Component/BrowserKit/AbstractBrowser.php --- a/src/Symfony/Component/BrowserKit/AbstractBrowser.php +++ b/src/Symfony/Component/BrowserKit/AbstractBrowser.php @@ -177,6 +187,23 @@ diff --git a/src/Symfony/Component/DependencyInjection/Extension/PrependExtensio - public function prepend(ContainerBuilder $container); + public function prepend(ContainerBuilder $container): void; } +diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php +--- a/src/Symfony/Component/DomCrawler/Crawler.php ++++ b/src/Symfony/Component/DomCrawler/Crawler.php +@@ -405,5 +405,5 @@ class Crawler implements \Countable, \IteratorAggregate + * @throws \InvalidArgumentException When current node is empty + */ +- public function closest(string $selector): ?self ++ public function closest(string $selector): ?static + { + if (!$this->nodes) { +@@ -646,5 +646,5 @@ class Crawler implements \Countable, \IteratorAggregate + * @return array|static + */ +- public function evaluate(string $xpath): array|self ++ public function evaluate(string $xpath): array|static + { + if (null === $this->document) { diff --git a/src/Symfony/Component/Emoji/EmojiTransliterator.php b/src/Symfony/Component/Emoji/EmojiTransliterator.php --- a/src/Symfony/Component/Emoji/EmojiTransliterator.php +++ b/src/Symfony/Component/Emoji/EmojiTransliterator.php @@ -610,6 +637,23 @@ diff --git a/src/Symfony/Component/VarDumper/Dumper/DataDumperInterface.php b/sr - public function dump(Data $data); + public function dump(Data $data): ?string; } +diff --git a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php +--- a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php ++++ b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php +@@ -49,5 +49,5 @@ trait VarDumperTestTrait + * @return void + */ +- public function assertDumpEquals(mixed $expected, mixed $data, int $filter = 0, string $message = '') ++ public function assertDumpEquals(mixed $expected, mixed $data, int $filter = 0, string $message = ''): void + { + $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); +@@ -57,5 +57,5 @@ trait VarDumperTestTrait + * @return void + */ +- public function assertDumpMatchesFormat(mixed $expected, mixed $data, int $filter = 0, string $message = '') ++ public function assertDumpMatchesFormat(mixed $expected, mixed $data, int $filter = 0, string $message = ''): void + { + $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); diff --git a/src/Symfony/Contracts/Translation/LocaleAwareInterface.php b/src/Symfony/Contracts/Translation/LocaleAwareInterface.php --- a/src/Symfony/Contracts/Translation/LocaleAwareInterface.php +++ b/src/Symfony/Contracts/Translation/LocaleAwareInterface.php diff --git a/.github/patch-types.php b/.github/patch-types.php index 9e4f12c6dfa76..0a25ef95af146 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -1,5 +1,7 @@ getMethods() as $method) { if ( $method->getReturnType() - || str_contains($method->getDocComment(), '@return') + || (str_contains($method->getDocComment(), '@return') && str_contains($method->getDocComment(), 'resource')) || '__construct' === $method->getName() || '__destruct' === $method->getName() || '__clone' === $method->getName() || $method->getDeclaringClass()->getName() !== $class - || str_contains($method->getDeclaringClass()->getName(), '\\Test\\') + || str_contains($method->getDeclaringClass()->getName(), '\\Tests\\') + || str_contains($method->getDeclaringClass()->getName(), '\\Test\\') && str_starts_with($method->getName(), 'test') ) { continue; } @@ -98,6 +90,7 @@ class_exists($class); if ($missingReturnTypes) { echo \count($missingReturnTypes)." missing return types on interfaces\n\n"; echo implode("\n", $missingReturnTypes); + echo "\n"; exit(1); } diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a2a3f8853882a..cee9ae50b1d2c 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -251,7 +251,7 @@ jobs: git diff --exit-code src/ || (echo '::error::Run "php .github/sync-translations.php" to fix XLIFF files.' && exit 1) - name: Run tests - run: ./phpunit --group integration -v + run: ./phpunit --group integration env: INTEGRATION_FTP_URL: 'ftp://test:test@localhost' REDIS_HOST: 'localhost:16379' @@ -267,12 +267,3 @@ jobs: KAFKA_BROKER: 127.0.0.1:9092 POSTGRES_HOST: localhost PGBOUNCER_HOST: localhost:6432 - - #- name: Run HTTP push tests - # if: matrix.php == '8.2' - # run: | - # [ -d .phpunit ] && mv .phpunit .phpunit.bak - # wget -q https://github.com/symfony/binary-utils/releases/download/v0.1/vulcain_0.1.3_Linux_x86_64.tar.gz -O - | tar xz && mv vulcain /usr/local/bin - # docker run --rm -e COMPOSER_ROOT_VERSION -v $(pwd):/app -v $(which composer):/usr/local/bin/composer -v $(which vulcain):/usr/local/bin/vulcain -w /app php:8.1-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push - # sudo rm -rf .phpunit - # [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit diff --git a/.github/workflows/intl-data-tests.yml b/.github/workflows/intl-data-tests.yml index 193b3dd1df14d..08fb8d1dd092c 100644 --- a/.github/workflows/intl-data-tests.yml +++ b/.github/workflows/intl-data-tests.yml @@ -84,7 +84,11 @@ jobs: run: uconv -V && php -i | grep 'ICU version' - name: Run intl-data tests - run: ./phpunit --group intl-data -v + run: | + ./phpunit --group intl-data --exclude-group intl-data-isolate + ./phpunit --group intl-data --filter testWhenEnvVarNotSet + ./phpunit --group intl-data --filter testWhenEnvVarSetFalse + ./phpunit --group intl-data --filter testWhenEnvVarSetTrue - name: Test intl-data with compressed data run: | @@ -96,7 +100,7 @@ jobs: ./phpunit src/Symfony/Component/Intl - name: Run Emoji tests - run: ./phpunit src/Symfony/Component/Emoji -v + run: ./phpunit src/Symfony/Component/Emoji - name: Test Emoji with compressed data run: | diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index 5de320ee91c0e..83879f3ae1d19 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -32,7 +32,7 @@ jobs: uses: shivammathur/setup-php@v2 with: coverage: "none" - php-version: "7.2" + php-version: "8.1" - name: Lint - run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e /Attribute/ -e /Extension/ -e /Metadata/ -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait -e SymfonyExtension | parallel -j 4 php -l {} + run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e /Attribute/ -e /Extension/ -e /Metadata/ -e ForV8 -e ForV9 -e ConstraintLogicTrait -e SymfonyExtension | parallel -j 4 php -l {} diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 33a5f58b44c6a..73e88be66a250 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-24.04 env: - php-version: '8.2' + php-version: '8.4' steps: - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -43,17 +43,13 @@ jobs: ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" export COMPOSER_ROOT_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -P -o '[0-9]+\.[0-9]+').x-dev composer remove --dev --no-update --no-interaction symfony/phpunit-bridge - composer require --no-progress --ansi --no-plugins psalm/phar:@stable phpunit/phpunit:^9.6 php-http/discovery psr/event-dispatcher mongodb/mongodb jetbrains/phpstorm-stubs + composer require --no-progress --ansi --no-plugins psalm/phar:@stable phpunit/phpunit:^11.5 php-http/discovery psr/event-dispatcher mongodb/mongodb jetbrains/phpstorm-stubs - name: Generate Psalm baseline run: | git checkout composer.json git checkout -m ${{ github.base_ref }} - # @todo intersection types are broken in Psalm - # @see https://github.com/vimeo/psalm/issues/7520 - sed -i 's/Uuid&/Uuid|/' src/Symfony/Component/Uid/Factory/TimeBasedUuidFactory.php - sed -i 's/Interface&/Interface|/' src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MigratingSessionHandler.php ./vendor/bin/psalm.phar --set-baseline=.github/psalm/psalm.baseline.xml --no-progress git checkout -m FETCH_HEAD diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index ca6b82974d22d..d830e38d4694e 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -27,7 +27,7 @@ jobs: matrix: include: - php: '8.2' - - php: '8.2' + - php: '8.4' mode: high-deps - php: '8.2' mode: low-deps @@ -75,7 +75,7 @@ jobs: ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json" echo COLUMNS=120 >> $GITHUB_ENV - echo PHPUNIT="$(pwd)/phpunit --exclude-group tty,benchmark,intl-data,integration,transient" >> $GITHUB_ENV + echo PHPUNIT="$(pwd)/phpunit --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group integration --exclude-group transient" >> $GITHUB_ENV echo COMPOSER_UP='composer update --no-progress --ansi'$([[ "${{ matrix.mode }}" != low-deps ]] && echo ' --ignore-platform-req=php+') >> $GITHUB_ENV SYMFONY_VERSIONS=$(git ls-remote -q --heads | cut -f2 | grep -o '/[1-9][0-9]*\.[0-9].*' | sort -V) @@ -131,11 +131,11 @@ jobs: fi # Legacy tests are skipped when deps=high and when the current branch version has not the same major version number as the next one - [[ "${{ matrix.mode }}" = high-deps && $SYMFONY_VERSION = *.4 ]] && echo LEGACY=,legacy >> $GITHUB_ENV || true + [[ "${{ matrix.mode }}" = high-deps && $SYMFONY_VERSION = *.4 ]] && echo LEGACY=" --exclude-group legacy" >> $GITHUB_ENV || true echo SYMFONY_VERSION=$SYMFONY_VERSION >> $GITHUB_ENV echo COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev >> $GITHUB_ENV - echo SYMFONY_REQUIRE=">=$([ '${{ matrix.mode }}' = low-deps ] && echo 5.4 || echo $SYMFONY_VERSION)" >> $GITHUB_ENV + echo SYMFONY_REQUIRE=">=$([ '${{ matrix.mode }}' = low-deps ] && echo 6.4 || echo $SYMFONY_VERSION)" >> $GITHUB_ENV [[ "${{ matrix.mode }}" = *-deps ]] && mv composer.json.phpunit composer.json || true - name: Install dependencies @@ -153,9 +153,10 @@ jobs: run: | patch -sp1 < .github/expected-missing-return-types.diff git add . + sed -i 's/ *"\*\*\/Tests\/",//' composer.json composer install -q --optimize-autoloader || composer install --optimize-autoloader SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.2' php .github/patch-types.php - git checkout src/Symfony/Contracts/Service/ResetInterface.php + git checkout composer.json src/Symfony/Contracts/Service/ResetInterface.php SYMFONY_PATCH_TYPE_DECLARATIONS='force=2&php=8.2' php .github/patch-types.php # ensure the script is idempotent git checkout src/Symfony/Contracts/Service/ResetInterface.php git diff --exit-code @@ -196,19 +197,19 @@ jobs: fi if [[ "${{ matrix.mode }}" = low-deps ]]; then - echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT'" + echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT --do-not-fail-on-deprecation'" exit 0 fi # matrix.mode = high-deps - echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP && $PHPUNIT$LEGACY'" || X=1 + echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP && $PHPUNIT$LEGACY --do-not-fail-on-deprecation'" || X=1 # get a list of the patched components (relies on .github/build-packages.php being called in the previous step) PATCHED_COMPONENTS=$(git diff --name-only src/ | grep composer.json || true) - # for 6.4 LTS, checkout and test previous major with the patched components (only for patched components) - if [[ $PATCHED_COMPONENTS && $SYMFONY_VERSION = 6.4 ]]; then + # for 7.4 LTS, checkout and test previous major with the patched components (only for patched components) + if [[ $PATCHED_COMPONENTS && $SYMFONY_VERSION = 7.4 ]]; then export FLIP='^' SYMFONY_VERSION=$(echo $SYMFONY_VERSION | awk '{print $1 - 1}') echo -e "\\n\\e[33;1mChecking out Symfony $SYMFONY_VERSION and running tests with patched components as deps\\e[0m" @@ -221,7 +222,7 @@ jobs: echo "::group::install phpunit" ./phpunit install echo "::endgroup::" - echo "$PATCHED_COMPONENTS" | parallel -j +3 "_run_tests {} 'cd {} && rm composer.lock vendor/ -Rf && $COMPOSER_UP && $PHPUNIT$LEGACY'" || X=1 + echo "$PATCHED_COMPONENTS" | parallel -j +3 "_run_tests {} 'cd {} && rm composer.lock vendor/ -Rf && $COMPOSER_UP && $PHPUNIT --exclude-group tty,benchmark,intl-data,integration,transient,legacy'" || X=1 fi fi @@ -249,12 +250,12 @@ jobs: mkdir -p /opt/php/lib echo memory_limit=-1 > /opt/php/lib/php.ini - ./build/php/bin/php ./phpunit --colors=always src/Symfony/Component/Process + ./phpunit install + ./build/php/bin/php ./phpunit src/Symfony/Component/Process - - name: Run PhpUnitBridge tests with PHPUnit 11 + - name: Run PhpUnitBridge tests with PHPUnit 9.6 if: '! matrix.mode' + env: + SYMFONY_PHPUNIT_VERSION: '9.6' run: | ./phpunit src/Symfony/Bridge/PhpUnit - env: - SYMFONY_PHPUNIT_VERSION: '11.3' - SYMFONY_DEPRECATIONS_HELPER: 'disabled' diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e0a663386beee..f9d28586b1299 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -12,7 +12,7 @@ permissions: contents: read jobs: - windows: + windows-minimal-exts: name: x86 / minimal-exts / lowest-php defaults: @@ -23,7 +23,6 @@ jobs: env: COMPOSER_NO_INTERACTION: '1' - SYMFONY_DEPRECATIONS_HELPER: 'strict' ANSICON: '121x90 (121x90)' SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: '1' @@ -45,38 +44,17 @@ jobs: mkdir c:\php && cd c:\php iwr -outf php.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.2.0-Win32-vs16-x86.zip 7z x php.zip -y >nul - cd ext - iwr -outf php_apcu.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.22-8.2-ts-vs16-x86.zip - 7z x php_apcu.zip -y >nul - iwr -outf php_igbinary.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_igbinary-3.2.16-8.2-ts-vs16-x86.zip - 7z x php_igbinary.zip -y >nul - iwr -outf php_redis.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-6.0.0-dev-8.2-ts-vs16-x86.zip - 7z x php_redis.zip -y >nul - cd .. - Copy php.ini-development php.ini-min - "memory_limit=-1" >> php.ini-min - "serialize_precision=-1" >> php.ini-min - "max_execution_time=1200" >> php.ini-min - "post_max_size=2047M" >> php.ini-min - "upload_max_filesize=2047M" >> php.ini-min - "date.timezone=`"America/Los_Angeles`"" >> php.ini-min - "extension_dir=ext" >> php.ini-min - "extension=php_xsl.dll" >> php.ini-min - "extension=php_mbstring.dll" >> php.ini-min - Copy php.ini-min php.ini-max - "zend_extension=php_opcache.dll" >> php.ini-max - "opcache.enable_cli=1" >> php.ini-max - "extension=php_openssl.dll" >> php.ini-max - "extension=php_apcu.dll" >> php.ini-max - "extension=php_igbinary.dll" >> php.ini-max - "extension=php_redis.dll" >> php.ini-max - "apc.enable_cli=1" >> php.ini-max - "extension=php_intl.dll" >> php.ini-max - "extension=php_fileinfo.dll" >> php.ini-max - "extension=php_pdo_sqlite.dll" >> php.ini-max - "extension=php_curl.dll" >> php.ini-max - "extension=php_sodium.dll" >> php.ini-max - Copy php.ini-max php.ini + Copy php.ini-development php.ini + "memory_limit=-1" >> php.ini + "serialize_precision=-1" >> php.ini + "max_execution_time=1200" >> php.ini + "post_max_size=2047M" >> php.ini + "upload_max_filesize=2047M" >> php.ini + "date.timezone=`"America/Los_Angeles`"" >> php.ini + "extension_dir=ext" >> php.ini + "extension=php_xsl.dll" >> php.ini + "extension=php_mbstring.dll" >> php.ini + "extension=php_openssl.dll" >> php.ini cd ${{ github.workspace }} iwr -outf composer.phar https://getcomposer.org/download/latest-stable/composer.phar @@ -98,36 +76,113 @@ jobs: php phpunit install - - name: Install memurai-developer - run: | - choco install --no-progress memurai-developer - - - name: Run tests (minimal extensions) - if: always() && steps.setup.outcome == 'success' + - name: Run tests run: | $env:Path = 'c:\php;' + $env:Path - $env:SYMFONY_PHPUNIT_SKIPPED_TESTS = 'phpunit.skipped' $x = 0 - Copy c:\php\php.ini-min c:\php\php.ini Remove-Item -Path src\Symfony\Bridge\PhpUnit -Recurse mv src\Symfony\Component\HttpClient\phpunit.xml.dist src\Symfony\Component\HttpClient\phpunit.xml - php phpunit src\Symfony --exclude-group tty,benchmark,intl-data,network,transient-on-windows || ($x = 1) + php phpunit src\Symfony --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group network --exclude-group transient-on-windows || ($x = 1) # HttpClient tests need to run separately, they block when run with other components' tests concurrently php phpunit src\Symfony\Component\HttpClient || ($x = 1) exit $x + windows-all-extensions: + name: x86 / all extensions / lowest-php + + defaults: + run: + shell: pwsh + + runs-on: windows-2022 + + env: + COMPOSER_NO_INTERACTION: '1' + ANSICON: '121x90 (121x90)' + SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: '1' + + steps: + - name: Setup Git + run: | + git config --global core.autocrlf false + git config --global user.email "" + git config --global user.name "Symfony" + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Setup PHP + run: | + $env:Path = 'c:\php;' + $env:Path + mkdir c:\php && cd c:\php + iwr -outf php.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.2.0-Win32-vs16-x86.zip + 7z x php.zip -y >nul + cd ext + iwr -outf php_apcu.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.22-8.2-ts-vs16-x86.zip + 7z x php_apcu.zip -y >nul + iwr -outf php_igbinary.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_igbinary-3.2.16-8.2-ts-vs16-x86.zip + 7z x php_igbinary.zip -y >nul + iwr -outf php_redis.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-6.2.0-8.2-ts-vs16-x86.zip + 7z x php_redis.zip -y >nul + cd .. + Copy php.ini-development php.ini + "memory_limit=-1" >> php.ini + "serialize_precision=-1" >> php.ini + "max_execution_time=1200" >> php.ini + "post_max_size=2047M" >> php.ini + "upload_max_filesize=2047M" >> php.ini + "date.timezone=`"America/Los_Angeles`"" >> php.ini + "extension_dir=ext" >> php.ini + "extension=php_xsl.dll" >> php.ini + "extension=php_mbstring.dll" >> php.ini + "zend_extension=php_opcache.dll" >> php.ini + "opcache.enable_cli=1" >> php.ini + "extension=php_openssl.dll" >> php.ini + "extension=php_apcu.dll" >> php.ini + "extension=php_igbinary.dll" >> php.ini + "extension=php_redis.dll" >> php.ini + "apc.enable_cli=1" >> php.ini + "extension=php_intl.dll" >> php.ini + "extension=php_fileinfo.dll" >> php.ini + "extension=php_pdo_sqlite.dll" >> php.ini + "extension=php_curl.dll" >> php.ini + "extension=php_sodium.dll" >> php.ini + cd ${{ github.workspace }} + iwr -outf composer.phar https://getcomposer.org/download/latest-stable/composer.phar + + - name: Install dependencies + id: setup + run: | + $env:Path = 'c:\php;' + $env:Path + mkdir $env:APPDATA\Composer && Copy .github\composer-config.json $env:APPDATA\Composer\config.json + + $env:SYMFONY_VERSION=(Select-String -CaseSensitive -Pattern " VERSION =" -SimpleMatch -Path src/Symfony/Component/HttpKernel/Kernel.php | Select Line | Select-String -Pattern "([0-9][0-9]*\.[0-9])").Matches.Value + $env:COMPOSER_ROOT_VERSION=$env:SYMFONY_VERSION + ".x-dev" + + php .github/build-packages.php HEAD^ $env:SYMFONY_VERSION src\Symfony\Bridge\PhpUnit + php composer.phar update --no-progress --ansi + + - name: Install PHPUnit + run: | + $env:Path = 'c:\php;' + $env:Path + + php phpunit install + + - name: Install memurai-developer + run: | + choco install --no-progress memurai-developer + - name: Run tests - if: always() && steps.setup.outcome == 'success' run: | $env:Path = 'c:\php;' + $env:Path - $env:SYMFONY_PHPUNIT_SKIPPED_TESTS = 'phpunit.skipped' $x = 0 - Copy c:\php\php.ini-max c:\php\php.ini - php phpunit src\Symfony --exclude-group tty,benchmark,intl-data,network,transient-on-windows || ($x = 1) + php phpunit src\Symfony --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group network --exclude-group transient-on-windows --requires-php-extension apcu --requires-php-extension curl --requires-php-extension fileinfo --requires-php-extension igbinary --requires-php-extension intl --requires-php-extension openssl --requires-php-extension pdo_sqlite --requires-php-extension redis --requires-php-extension sodium || ($x = 1) # HttpClient tests need to run separately, they block when run with other components' tests concurrently - php phpunit src\Symfony\Component\HttpClient || ($x = 1) + php phpunit src\Symfony\Component\HttpClient --requires-php-extension curl --requires-php-extension openssl || ($x = 1) exit $x diff --git a/.gitignore b/.gitignore index 0c37517192aba..61ade23d815fb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ composer.lock phpunit.xml .php-cs-fixer.cache .php-cs-fixer.php +.phpunit.cache .phpunit.result.cache composer.phar package.tar diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index d31af1aab2e20..8b9add611eb0a 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -28,14 +28,12 @@ ]; return (new PhpCsFixer\Config()) - // @see https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/pull/7777 ->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()) ->setRules([ - '@PHP71Migration' => true, - '@PHPUnit75Migration:risky' => true, + '@PHP81Migration' => true, // take lowest version from `git grep -h '"php"' **/composer.json | uniq | sort` + '@PHPUnit91Migration:risky' => true, // take version from src/Symfony/Bridge/PhpUnit/phpunit.xml.dist#L4 '@Symfony' => true, '@Symfony:risky' => true, - 'phpdoc_var_annotation_correct_order' => true, 'protected_to_private' => false, 'header_comment' => [ 'header' => implode('', $fileHeaderParts), @@ -47,6 +45,7 @@ '/s', ]), ], + 'php_unit_attributes' => true, ]) ->setRiskyAllowed(true) ->setFinder( @@ -60,25 +59,13 @@ 'Symfony/Component/Emoji/Resources/', 'Symfony/Component/Intl/Resources/data/', ]) - // explicit tests for ommited @param type, against `no_superfluous_phpdoc_tags` - ->notPath('Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php') - ->notPath('Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php') // Support for older PHPunit version - ->notPath('Symfony/Bridge/PhpUnit/SymfonyTestsListener.php') ->notPath('#Symfony/Bridge/PhpUnit/.*Mock\.php#') ->notPath('#Symfony/Bridge/PhpUnit/.*Legacy#') - // explicit trigger_error tests - ->notPath('Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php') - // stop removing spaces on the end of the line in strings - ->notPath('Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php') // disable to not apply `native_function_invocation` rule, as we explicitly break it for testability reason, ref https://github.com/symfony/symfony/pull/59195 ->notPath('Symfony/Component/Mailer/Transport/NativeTransportFactory.php') // auto-generated proxies - ->notPath('Symfony/Component/Cache/Traits/RelayProxy.php') - ->notPath('Symfony/Component/Cache/Traits/Redis5Proxy.php') - ->notPath('Symfony/Component/Cache/Traits/Redis6Proxy.php') - ->notPath('Symfony/Component/Cache/Traits/RedisCluster5Proxy.php') - ->notPath('Symfony/Component/Cache/Traits/RedisCluster6Proxy.php') + ->notPath('#Symfony/Component/Cache/Traits/Re.*Proxy\.php#') // svg ->notPath('Symfony/Component/ErrorHandler/Resources/assets/images/symfony-ghost.svg.php') // HTML templates diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ac9a78cee91b3..270f687f39032 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,6 +14,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alexandre Daubois (alexandre-daubois) - Grégoire Pineau (lyrixx) - Thomas Calvet (fancyweb) + - Oskar Stark (oskarstark) - Christophe Coevoet (stof) - Wouter de Jong (wouterj) - Jordi Boggiano (seldaek) @@ -24,6058 +25,6085 @@ The Symfony Connect username in parenthesis allows to get more information - Ryan Weaver (weaverryan) - Jérémy DERUSSÉ (jderusse) - Jules Pietri (heah) - - Oskar Stark (oskarstark) + - Yonel Ceruto (yonelceruto) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) - Jakub Zalas (jakubzalas) - - Yonel Ceruto (yonelceruto) - HypeMC (hypemc) + - Jérôme Tamarelle (gromnan) - Hugo Hamon (hhamon) - Tobias Nyholm (tobias) - - Jérôme Tamarelle (gromnan) - Antoine Lamirault (alamirault) - Samuel ROZE (sroze) - Pascal Borreli (pborreli) - Romain Neutron - Kevin Bond (kbond) - Joseph Bielawski (stloyd) - - Drak (drak) + - Matthias Schmidt - Abdellatif Ait boudad (aitboudad) + - Drak (drak) - Lukas Kahwe Smith (lsmith) + - Mathias Arlaud (mtarld) - Hamza Amrouche (simperfit) - Martin Hasoň (hason) - - Mathias Arlaud (mtarld) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler - Jan Schädlich (jschaedl) - Mathieu Lechat (mat_the_cat) - - Simon André (simonandre) - Vincent Langlet (deviling) + - Simon André (simonandre) - Matthias Pigulla (mpdude) - Gabriel Ostrolucký (gadelat) - Jonathan Wage (jwage) + - Mathieu Santostefano (welcomattic) - Valentin Udaltsov (vudaltsov) - Grégoire Paris (greg0ire) - Alexandre Salomé (alexandresalome) - William DURAND - Dany Maillard (maidmaid) - - Diego Saint Esteben (dosten) - - Gábor Egyed (1ed) - - Francis Besset (francisbesset) - - Alexander Mols (asm89) - stealth35 ‏ (stealth35) - Eriksen Costa + - Gábor Egyed (1ed) + - Diego Saint Esteben (dosten) + - Alexander Mols (asm89) + - Francis Besset (francisbesset) - Pierre du Plessis (pierredup) - Titouan Galopin (tgalopin) - - Mathieu Santostefano (welcomattic) - Tomasz Kowalczyk (thunderer) + - Alexander Schranz (alexander-schranz) - David Maicher (dmaicher) - Bulat Shakirzyanov (avalanche123) - - Alexander Schranz (alexander-schranz) - - Miha Vrhovnik (mvrhov) - - Iltar van der Berg - Gary PEGEOT (gary-p) - - Saša Stamenković (umpirsky) + - Iltar van der Berg + - Miha Vrhovnik (mvrhov) - Allison Guilhem (a_guilhem) + - Saša Stamenković (umpirsky) - Mathieu Piot (mpiot) - Vasilij Duško (staff) - - Sarah Khalil (saro0h) - Laurent VOULLEMIER (lvo) + - Sarah Khalil (saro0h) - Konstantin Kudryashov (everzet) - - Bilal Amarni (bamarni) + - Tomas Norkūnas (norkunas) - Guilhem N (guilhemn) - - Eriksen Costa + - Bilal Amarni (bamarni) - Ruud Kamphuis (ruudk) + - Eriksen Costa - Vladimir Reznichenko (kalessil) - Florin Patan (florinpatan) - Henrik Bjørnskov (henrikbjorn) - Peter Rehm (rpet) - - Tomas Norkūnas (norkunas) + - matlec - David Buchmann (dbu) - Jáchym Toušek (enumag) - Andrej Hudec (pulzarraider) - Eric Clemmons (ericclemmons) - Hubert Lenoir (hubert_lenoir) - Christian Raue - - Michel Weimerskirch (mweimerskirch) - - Matthias Schmidt - Douglas Greenshields (shieldo) - - Issei Murasawa (issei_m) + - Michel Weimerskirch (mweimerskirch) - Alex Pott + - Issei Murasawa (issei_m) - Arnout Boks (aboks) - Denis (yethee) + - Antoine Makdessi (amakdessi) - Baldini - - Fran Moreno (franmomu) - Frank A. Fiebig (fafiebig) - - Antoine Makdessi (amakdessi) - - Dariusz Górecki (canni) - - Henrik Westphal (snc) + - Fran Moreno (franmomu) - Charles Sarrazin (csarrazi) - - Massimiliano Arione (garak) + - Henrik Westphal (snc) + - Dariusz Górecki (canni) - Ener-Getick - - Graham Campbell (graham) + - Massimiliano Arione (garak) + - Santiago San Martin (santysisi) - Joel Wurtz (brouznouf) - - Brandon Turner + - Graham Campbell (graham) - Luis Cordova (cordoval) - Tugdual Saunier (tucksaun) - - Lee McDermott - Phil E. Taylor (philetaylor) + - Lee McDermott + - Brandon Turner - Julien Falque (julienfalque) - - Konstantin Myakshin (koc) - Bart van den Burg (burgov) + - Toni Uebernickel (havvg) - Jordan Alliot (jalliot) - - Daniel Holmes (dholmes) - Vasilij Dusko | CREATION - - Toni Uebernickel (havvg) - - Valtteri R (valtzu) - - Yanick Witschi (toflar) + - Konstantin Myakshin (koc) + - Daniel Holmes (dholmes) - Théo FIDRY + - soyuka - John Wards (johnwards) - - Antoine Hérault (herzult) + - Yanick Witschi (toflar) + - Valtteri R (valtzu) - Konstantin.Myakshin - - Maxime STEINHAUSSER - - Rokas Mikalkėnas (rokasm) - - Tac Tacelosky (tacman1123) + - Antoine Hérault (herzult) - Arnaud Le Blanc (arnaud-lb) - - matlec - Jeroen Spee (jeroens) + - Tac Tacelosky (tacman1123) + - Maxime STEINHAUSSER - Sebastiaan Stok (sstok) + - Rokas Mikalkėnas (rokasm) + - Jacob Dreesen (jdreesen) - Brice BERNARD (brikou) - - Peter Kokot (peterkokot) + - gnito-org - Jérôme Vasseur (jvasseur) - Chris Wilkinson (thewilkybarkid) + - Peter Kokot (peterkokot) - Tim Nagel (merk) - - Jacob Dreesen (jdreesen) - - gnito-org - - Michal Piotrowski - - marc.weistroff + - Nicolas Philippe (nikophil) - Lars Strojny (lstrojny) + - Michal Piotrowski - Vladimir Tsykun (vtsykun) - - Nicolas Philippe (nikophil) - - Włodzimierz Gajda (gajdaw) + - marc.weistroff - Javier Spagnoletti (phansys) + - Włodzimierz Gajda (gajdaw) - Adrien Brault (adrienbrault) - - soyuka - Florent Morselli (spomky_) - - Colin Frei + - Florian Voutzinos (florianv) - Przemysław Bogusz (przemyslaw-bogusz) + - Colin Frei - Teoh Han Hui (teohhanhui) - - Florian Voutzinos (florianv) - - Maxime Helias (maxhelias) + - Alexander Schwenn (xelaris) + - Fabien Pennequin (fabienpennequin) + - Gregor Harlan (gharlan) - Paráda József (paradajozsef) - - Baptiste Clavié (talus) - Maximilian Beckers (maxbeckers) - - Alexander Schwenn (xelaris) + - Maxime Helias (maxhelias) - Dāvis Zālītis (k0d3r1s) - Gordon Franke (gimler) - - Fabien Pennequin (fabienpennequin) - - Vasilij Dusko - - Michael Babker (mbabker) - - Christopher Hertel (chertel) - - Hugo Alliaume (kocal) + - Baptiste Clavié (talus) - Joshua Thijssen + - Michael Babker (mbabker) + - Vasilij Dusko + - Daniel Wehner (dawehner) - jeremyFreeAgent (jeremyfreeagent) + - Hugo Alliaume (kocal) + - Christopher Hertel (chertel) - Malte Schlüter (maltemaltesich) - Alexis Lefebvre - - Daniel Wehner (dawehner) - - Andreas Schempp (aschempp) - - Eric GELOEN (gelo) - - Gabriel Caruso - - Smaine Milianni (ismail1432) - François-Xavier de Guillebon (de-gui_f) - OGAWA Katsuhiro (fivestar) - - Robert Schönthal (digitalkaoz) + - Stefano Sala (stefano.sala) - Ion Bazan (ionbazan) - - Jhonny Lidfors (jhonne) + - Gabriel Caruso + - Andreas Schempp (aschempp) - Niels Keurentjes (curry684) - - Stefano Sala (stefano.sala) - - Gregor Harlan (gharlan) - - Sebastian Hörl (blogsh) - - Hidenori Goto (hidenorigoto) - - Jonathan Scheiber (jmsche) - - Anthony MARTIN - - Tigran Azatyan (tigranazatyan) - - Florent Mata (fmata) - - Arnaud Kleinpeter (nanocom) - - Juti Noppornpitak (shiroyuki) + - Smaine Milianni (ismail1432) + - Jhonny Lidfors (jhonne) + - Eric GELOEN (gelo) + - Robert Schönthal (digitalkaoz) - David Prévot (taffit) - Guilherme Blanco (guilhermeblanco) + - Anthony MARTIN + - Bob van de Vijver (bobvandevijver) - Thomas Landauer (thomas-landauer) + - Jonathan Scheiber (jmsche) + - Tigran Azatyan (tigranazatyan) - Daniel Gomes (danielcsgomes) - - Alessandro Chitolina (alekitto) - - jwdeitch + - Sebastian Hörl (blogsh) + - Arnaud Kleinpeter (nanocom) + - Florent Mata (fmata) + - Hidenori Goto (hidenorigoto) + - Juti Noppornpitak (shiroyuki) - Rafael Dohms (rdohms) + - Alessandro Chitolina (alekitto) - Pablo Godel (pgodel) + - Roman Martinuk (a2a4) + - Antonio J. García Lagar (ajgarlag) + - Fritz Michael Gschwantner (fritzmg) - Saif Eddin Gmati (azjezz) - - Jan Rosier (rosier) - Richard van Laak (rvanlaak) + - jwdeitch - Farhad Safarov (safarov) - - Roman Martinuk (a2a4) - - Tomas Votruba (tomas_votruba) - - Arman Hosseini (arman) + - Jan Rosier (rosier) + - Kévin THERAGE (kevin_therage) - Andréia Bohner (andreia) + - Simon Berger + - Tom Van Looy (tvlooy) + - Vyacheslav Pavlov + - Matthieu Napoli (mnapoli) - Sokolov Evgeniy (ewgraf) - - Albert Casademont (acasademont) + - Stiven Llupa (sllupa) + - Jérôme Parmentier (lctrs) + - Tomas Votruba (tomas_votruba) + - Roland Franssen - Jérémy Derussé - - Matthieu Napoli (mnapoli) - - Richard Shank (iampersistent) + - Ben Davies (bendavies) + - Albert Casademont (acasademont) - Ahmed TAILOULOUTE (ahmedtai) - - Bob van de Vijver (bobvandevijver) + - Arman Hosseini (arman) - George Mponos (gmponos) - - Fritz Michael Gschwantner (fritzmg) - - Roland Franssen - - Vyacheslav Pavlov - - Jérôme Parmentier (lctrs) - - Simon Berger - - Tom Van Looy (tvlooy) - - Alessandro Lai (jean85) + - Richard Shank (iampersistent) + - Gocha Ossinkine (ossinkine) + - Oleg Voronkovich + - Jonathan Ingram - Daniel Burger + - Antonio Pauletich (x-coder264) + - Alessandro Lai (jean85) + - Michał Pipa (michal.pipa) + - Matthieu Ouellette-Vachon (maoueh) + - Philipp Wahala (hifi) + - Romain Monteil (ker0x) - Jannik Zschiesche - Jesse Rushlow (geeshoe) - - Marco Pivetta (ocramius) - - Vincent Touzet (vincenttouzet) - - Antonio Pauletich (x-coder264) + - Sergey (upyx) + - YaFou + - Dawid Nowak + - Olivier Dolbeau (odolbeau) + - Indra Gunawan (indragunawan) + - Fabien Bourigault (fbourigault) + - Guillaume (guill) + - GDIBass - Samuel NELA (snela) - - Tyson Andre - Clemens Tolboom - - Philipp Wahala (hifi) - - Matthieu Ouellette-Vachon (maoueh) - - Gocha Ossinkine (ossinkine) - - Stiven Llupa (sllupa) - - Fabien Bourigault (fbourigault) - - Jonathan Ingram - - Ben Davies (bendavies) + - Amal Raghav (kertz) + - Vincent Touzet (vincenttouzet) + - Wouter J + - Tyson Andre - Rouven Weßling (realityking) - - Olivier Dolbeau (odolbeau) - - Sergey (upyx) + - Marco Pivetta (ocramius) - Artur Kotyrba - 77web - - Wouter J - - Romain Monteil (ker0x) - - GDIBass - - Dawid Nowak - - YaFou - - Oleg Voronkovich - - Guillaume (guill) - - Amal Raghav (kertz) - - Michał Pipa (michal.pipa) - - Marko Kaznovac (kaznovac) - - wkania - - Sergey Linnik (linniksa) - - Michael Voříšek - Arnaud PETITPAS (apetitpa) - - Asis Pattisahusiwa - - zairig imad (zairigimad) - - Alex Hofbauer (alexhofbauer) - - Michael Käfer (michael_kaefer) - - Nate Wiebe (natewiebe13) - Quynh Xuan Nguyen (seriquynh) - - D (denderello) - Anthony GRASSIOT (antograssiot) - Mario A. Alvarez Garcia (nomack84) - - Christian Scheb - - Indra Gunawan (indragunawan) - - Colin O'Dell (colinodell) + - Daniel Espendiller + - Nate Wiebe (natewiebe13) + - Mikael Pajunen + - Alan Poulain (alanpoulain) + - Clément JOBEILI (dator) + - Warnar Boekkooi (boekkooi) + - Justin Hileman (bobthecow) + - Marek Štípek (maryo) - Thomas Rabaix (rande) - - Martin Hujer (martinhujer) + - Asis Pattisahusiwa + - wkania - Dmitrii Chekaliuk (lazyhammer) - - Vincent AUBERT (vincent) + - Alex Hofbauer (alexhofbauer) + - Marko Kaznovac (kaznovac) + - Victor Bocharsky (bocharsky_bw) - Chi-teck - - Aleksandar Jakovljevic (ajakov) + - Dorian Villet (gnutix) + - Colin O'Dell (colinodell) + - Andreas Möller (localheinz) + - Sébastien Alfaiate (seb33300) + - Vincent AUBERT (vincent) + - zairig imad (zairigimad) + - Sergey Linnik (linniksa) + - DQNEO + - Martin Hujer (martinhujer) + - Michael Käfer (michael_kaefer) + - Michael Voříšek + - James Halsall (jaitsu) + - D (denderello) - Larry Garfield (crell) + - Aleksandar Jakovljevic (ajakov) - Richard Miller - - Warnar Boekkooi (boekkooi) - - Justin Hileman (bobthecow) + - Christian Scheb - Baptiste Leduc (korbeil) - - Daniel Espendiller - - James Halsall (jaitsu) - - DQNEO - - Clément JOBEILI (dator) - - Sébastien Alfaiate (seb33300) - - Marek Štípek (maryo) - - Andreas Möller (localheinz) - - Mikael Pajunen - - Dorian Villet (gnutix) - - Victor Bocharsky (bocharsky_bw) - - Stepan Anchugov (kix) - - Filippo Tessarotto (slamdunk) - - Timo Bakx (timobakx) - - Markus Fasselt (digilist) - - Denis Brumann (dbrumann) - - Andreas Hucks (meandmymonkey) - - Nikolay Labinskiy (e-moe) - - Santiago San Martin (santysisi) - - bronze1man - - Pierre Minnieur (pminnieur) - - Bastien Jaillot (bastnic) + - Stadly - Andre Rømcke (andrerom) + - Noel Guilbert (noel) + - Martin Schuhfuß (usefulthink) + - Benjamin Dulau (dbenjamin) - Guilliam Xavier - - sun (sun) - - Leo Feyer - Giorgio Premi + - Quentin Devos + - apetitpa + - Denis Brumann (dbrumann) + - Andreas Hucks (meandmymonkey) + - Timo Bakx (timobakx) - Mathieu Lemoine (lemoinem) - - Stadly - - Ruben Gonzalez (rubenrua) - Remon van de Kamp - - Patrick Landolt (scube) + - Leo Feyer + - Markus Fasselt (digilist) - Bram Leeda (bram123) - - Christian Schmidt - - Noel Guilbert (noel) - - apetitpa - - Karoly Gossler (connorhu) - - Alan Poulain (alanpoulain) + - Nikolay Labinskiy (e-moe) + - Bastien Jaillot (bastnic) + - bronze1man + - Filippo Tessarotto (slamdunk) - mcfedr (mcfedr) - - Benjamin Dulau (dbenjamin) + - Christian Schmidt - Loick Piera (pyrech) - - Martin Schuhfuß (usefulthink) - - Quentin Devos - - François Pluchino (francoispluchino) + - Pierre Minnieur (pminnieur) + - Ruben Gonzalez (rubenrua) + - Karoly Gossler (connorhu) + - Stepan Anchugov (kix) + - sun (sun) + - Patrick Landolt (scube) + - Sven Paulus (subsven) + - Wojciech Kania - Maciej Malarz (malarzm) - Edi Modrić (emodric) - - Mantis Development - - Sven Paulus (subsven) - - Dustin Whittle (dustinwhittle) - - Priyadi Iman Nurcahyo (priyadi) + - jeff - Arjen van der Meijden - - Florian Lonqueu-Brochard (florianlb) - - Jonathan H. Wage - - Yassine Guedidi (yguedidi) - - Tristan Darricau (tristandsensio) - - John Kary (johnkary) - - fd6130 (fdtvui) - - Jan Sorgalla (jsor) + - Julien Brochet + - Timothée Barray (tyx) + - Evert Harmeling (evertharmeling) + - Thomas Lallement (raziel057) + - Michele Orselli (orso) - Jérémie Augustin (jaugustin) + - Yassine Guedidi (yguedidi) + - Maxime Veber (nek-) + - Marcel Beerta (mazen) + - henrikbjorn + - Priyadi Iman Nurcahyo (priyadi) - Oleg Andreyev (oleg.andreyev) + - Jeroen Noten (jeroennoten) + - Dustin Whittle (dustinwhittle) - Võ Xuân Tiến (tienvx) - - Evert Harmeling (evertharmeling) - - Julien Brochet - - Joe Bennett (kralos) - Peter Kruithof (pkruithof) - - Pascal Montoya - - Wojciech Kania - - jeff - - Michele Orselli (orso) - - Timothée Barray (tyx) - - Maxime Veber (nek-) + - Jonathan H. Wage - Marcin Sikoń (marphi) - - Thomas Lallement (raziel057) + - Michael Lee (zerustech) + - Jan Sorgalla (jsor) + - François Pluchino (francoispluchino) + - Dmitrii Poddubnyi (karser) + - Hugo Monteiro (monteiro) + - fd6130 (fdtvui) + - Tristan Darricau (tristandsensio) - Leszek Prabucki (l3l0) - - Jeroen Noten (jeroennoten) - - henrikbjorn - - Antonio J. García Lagar (ajgarlag) + - Valentine Boineau (valentineboineau) + - Joe Bennett (kralos) + - Florian Lonqueu-Brochard (florianlb) - Rui Marinho (ruimarinho) + - Mantis Development + - John Kary (johnkary) - François Zaninotto (fzaninotto) - - Hugo Monteiro (monteiro) - - Valentine Boineau (valentineboineau) - - Michael Lee (zerustech) - - Marcel Beerta (mazen) - - Dmitrii Poddubnyi (karser) - - jdhoek - - Philipp Cordes (corphi) - - Sullivan SENECHAL (soullivaneuh) - - Sylvain Fabre (sylfabre) - - Michel Roca (mroca) + - Pascal Montoya + - Félix Labrecque (woodspire) + - Alexander Kotynia (olden) + - Daniel Gorgan + - Joseph Rouff (rouffj) + - Jordan Samouh (jordansamouh) + - Iker Ibarguren (ikerib) + - Eugene Leonovich (rybakit) + - Lynn van der Berg (kjarli) + - Marc Weistroff (futurecat) + - Pierre-Yves Lebecq (pylebecq) + - Daniel Tschinder + - David Badura (davidbadura) + - Christian Schmidt + - Adam Prager (padam87) + - Benoît Burnichon (bburnichon) + - Roman Ring (inori) + - Patrick McDougle (patrick-mcdougle) + - Uwe Jäger (uwej711) + - Thomas Adam - Chekote - - maxime.steinhausser + - Michaël Perrin (michael.perrin) + - Xavier Montaña Carreras (xmontana) + - Arjen Brouwer (arjenjb) + - Xavier Perez + - Aurélien Pillevesse (aurelienpillevesse) + - BoShurik + - Philipp Cordes (corphi) + - Zan Baldwin (zanbaldwin) - Rob Frawley 2nd (robfrawley) - - Tim Goudriaan (codedmonkey) - - Elnur Abdurrakhimov (elnur) - javaDeveloperKid - - Aurélien Pillevesse (aurelienpillevesse) - - Ray - Anderson Müller - - Daniel Tschinder + - jdhoek + - Kyle + - Bob den Otter (bopp) + - Marvin Petker - Hidde Wieringa (hiddewie) + - Romaric Drigon (romaricdrigon) - Manuel Reinhard (sprain) + - Sylvain Fabre (sylfabre) - Adrian Rudnik (kreischweide) + - dFayet + - Sullivan SENECHAL (soullivaneuh) - Nikita Konstantinov (unkind) - Matthieu Lempereur (mryamous) - - Uwe Jäger (uwej711) + - Arnt Gulbrandsen + - Michel Roca (mroca) + - Renan (renanbr) + - Ray + - roman joly (eltharin) + - Benjamin Leveque (benji07) + - Emanuele Panzeri (thepanz) - Jurica Vlahoviček (vjurica) - - Eugene Leonovich (rybakit) - - Zan Baldwin (zanbaldwin) - - Fabien S (bafs) - - Joseph Rouff (rouffj) - - Xavier Perez - - Roman Ring (inori) - - Xavier Montaña Carreras (xmontana) - - Bob den Otter (bopp) - - Félix Labrecque (woodspire) - - Marvin Petker - - GordonsLondon - - David Badura (davidbadura) - - Michaël Perrin (michael.perrin) - - Thomas Adam - - Romaric Drigon (romaricdrigon) - - Pierre-Yves Lebecq (pylebecq) + - maxime.steinhausser - Dariusz Ruminski - - Danny Berger (dpb587) - - Daniel Gorgan - - Benjamin Leveque (benji07) - Michał (bambucha15) - - Marc Weistroff (futurecat) - - Renan (renanbr) - - dFayet + - Danny Berger (dpb587) + - Alif Rachmawadi - Thomas Schulz (king2500) - Francois Zaninotto - - Christian Schmidt - - Arjen Brouwer (arjenjb) - - Alexander Kotynia (olden) - - Arnt Gulbrandsen - - BoShurik - - Adam Prager (padam87) - - Benoît Burnichon (bburnichon) - - Lynn van der Berg (kjarli) - - Alif Rachmawadi - - Jordan Samouh (jordansamouh) - - Kyle - - Iker Ibarguren (ikerib) - - Patrick McDougle (patrick-mcdougle) + - GordonsLondon + - Tim Goudriaan (codedmonkey) + - Elnur Abdurrakhimov (elnur) + - Fabien S (bafs) - Chris Smith (cs278) - Anton Chernikov (anton_ch1989) - - Sergey Belyshkin (sbelyshkin) - - Warxcell (warxcell) - - jaugustin - - Dominique Bongiraud - - Florian Klein (docteurklein) - Damien Alexandre (damienalexandre) - - Bertrand Zuchuat (garfield-fr) - - Baptiste Lafontaine (magnetik) - - Robert Kiss (kepten) - - Serkan Yildiz (srknyldz) - - Alex Rock (pierstoval) + - jaugustin + - Marco Petersen (ocrampete16) + - Ismael Ambrosi (iambrosi) + - Sébastien Lavoie (lavoiesl) + - corradogrimoldi + - Tiago Ribeiro (fixe) + - Pascal Luna (skalpa) + - Aurelijus Valeiša (aurelijus) + - Vilius Grigaliūnas - Alexandre Quercia (alquerci) - - Matthieu Auger (matthieuauger) - - Andrew Moore (finewolf) - - Mathieu Rochette (mathroc) - - Marcos Sánchez - - Jordane VASPARD (elementaire) - - Pavel Batanov (scaytrase) - - Thomas Bisignani (toma) - - Andrii Bodnar + - Josip Kruslin (jkruslin) + - Manuel Kießling (manuelkiessling) + - Lee Rowlands + - Raphaël Geffroy (raphael-geffroy) - Simon Podlipsky (simpod) - - Emanuele Panzeri (thepanz) - - janschoenherr - - Kim Hemsø Rasmussen (kimhemsoe) - - Loïc Frémont (loic425) + - a.dmitryuk + - Dominique Bongiraud + - Warxcell (warxcell) + - Wodor Wodorski + - realmfoo + - Maximilian Reichel (phramz) + - Baptiste Lafontaine (magnetik) + - Christopher Davis (chrisguitarguy) + - Jack Worman (jworman) + - Alex Rock (pierstoval) + - Serkan Yildiz (srknyldz) + - Blanchon Vincent (blanchonvincent) + - Ben Hakim + - Sergey Belyshkin (sbelyshkin) + - Christian Schmidt - Samaël Villette (samadu61) - - Pascal Luna (skalpa) - - Marc Morera (mmoreram) + - Bertrand Zuchuat (garfield-fr) + - rudy onfroy (ronfroy) + - Marcos Sánchez + - Yoann RENARD (yrenard) + - Matthieu Auger (matthieuauger) + - Andrew Moore (finewolf) + - Thomas Tourlourat (armetiz) + - Philippe SEGATORI (tigitz) + - Herberto Graca + - Francesc Rosàs (frosas) + - Frank de Jonge + - Florian Klein (docteurklein) + - Joppe De Cuyper (joppedc) - Cédric Anne + - Michael Hirschler (mvhirsch) + - Bohan Yang (brentybh) + - Grégoire Passault (gregwar) + - SiD (plbsid) + - Raul Fraile (raulfraile) + - Jordane VASPARD (elementaire) + - Mathieu Rochette (mathroc) - Wouter Van Hecke - - Beau Simensen (simensen) + - Kim Hemsø Rasmussen (kimhemsoe) + - Pavel Batanov (scaytrase) + - Alexey Kopytko (sanmai) + - Jerzy Zawadzki (jzawadzki) + - Andrii Bodnar - Michael Holm (hollo) - - Blanchon Vincent (blanchonvincent) - - Christian Schmidt + - Karoly Negyesi (chx) + - Jan Decavele (jandc) + - Andrey Esaulov (andremaha) - Atsuhiro KUBO (iteman) + - Craig Duncan (duncan3dc) - Emanuele Gaspari (inmarelibero) - - Ben Hakim - - Marco Petersen (ocrampete16) - - Lee Rowlands - - Christopher Davis (chrisguitarguy) - - Gustavo Piltcher - - Bohan Yang (brentybh) - - Jan Decavele (jandc) - - Jerzy Zawadzki (jzawadzki) - - Aurelijus Valeiša (aurelijus) + - Robert Kiss (kepten) + - Magnus Nordlander (magnusnordlander) + - Dane Powell - Emmanuel BORGES - - Craig Duncan (duncan3dc) - - Manuel Kießling (manuelkiessling) + - Benjamin Morel + - Marc Morera (mmoreram) - Gabor Toth (tgabi333) - - Joppe De Cuyper (joppedc) - - Karoly Negyesi (chx) - - Vilius Grigaliūnas - - Philippe SEGATORI (tigitz) - - Sébastien Lavoie (lavoiesl) - - Michael Hirschler (mvhirsch) - - realmfoo + - Loïc Frémont (loic425) + - Pierre Ambroise (dotordu) + - janschoenherr + - Beau Simensen (simensen) + - Ivan Kurnosov + - Gustavo Piltcher - Stepan Tanasiychuk (stfalcon) - - Raphaël Geffroy (raphael-geffroy) - - Herberto Graca - - Ismael Ambrosi (iambrosi) + - Thomas Bisignani (toma) - renanbr - - Grégoire Passault (gregwar) - - roman joly (eltharin) - - Andrey Esaulov (andremaha) - - Frank de Jonge - - Josip Kruslin (jkruslin) - - Kévin THERAGE (kevin_therage) - - Ivan Kurnosov - - Pierre Ambroise (dotordu) - - rudy onfroy (ronfroy) - - Maximilian Reichel (phramz) - - Francesc Rosàs (frosas) - - Benjamin Morel - - Tiago Ribeiro (fixe) - Sebastien Morel (plopix) - - Magnus Nordlander (magnusnordlander) - - Dane Powell - - Thomas Tourlourat (armetiz) - - SiD (plbsid) - - Alexey Kopytko (sanmai) - - Raul Fraile (raulfraile) - - Jack Worman (jworman) - - Yoann RENARD (yrenard) - - Wodor Wodorski - - Pavel Volokitin (pvolok) - - Ivan Mezinov - - Erin Millard - - Hamza Makraz (makraz) - - Zmey - - Artem (artemgenvald) - - ivan - - Lukáš Holeczy (holicz) - - SUMIDA, Ippei (ippey_s) - - Thierry T (lepiaf) - - Lorenz Schori - - Jeremy Livingston (jeremylivingston) - - Nicolas LEFEVRE (nicoweb) - - Roumen Damianoff - - Urinbayev Shakhobiddin (shokhaa) - - Ahmed Raafat - - Islam Israfilov (islam93) - - Thomas Royer (cydonia7) - - Harm van Tilborg (hvt) - - Haralan Dobrev (hkdobrev) - - Gonzalo Vilaseca (gonzalovilaseca) - - Francesco Levorato - - smoench - - Asmir Mustafic (goetas) - - Tobias Sjösten (tobiassjosten) - - Mateusz Sip (mateusz_sip) - - C (dagardner) + - Dimitri Gritsajuk (ottaviano) + - Rhodri Pugh (rodnaph) - Dalibor Karlović - - Vitaliy Zakharov (zakharovvi) - - Inal DJAFAR (inalgnu) - - Gyula Sallai (salla) - - Johann Pardanaud - - Hendrik Luup (hluup) - - Pierre Rineau - - mondrake (mondrake) - - Martin Herndl (herndlm) - - Yaroslav Kiliba - - Dmytro Borysovskyi (dmytr0) + - Clara van Miert + - Eric Masoero (eric-masoero) + - Urinbayev Shakhobiddin (shokhaa) - Pavel Kirpitsov (pavel-kirpichyov) - - Thomas Perez (scullwm) + - Joe Lencioni + - Pierre Rineau + - Pavel Volokitin (pvolok) + - ShinDarth + - Kirill chEbba Chebunin + - Jakub Kucharovic (jkucharovic) + - Ahmed Raafat + - Philippe Segatori - Gwendolen Lynch - - Felix Labrecque + - Grzegorz (Greg) Zdanowski (kiler129) + - Thomas Perez (scullwm) + - Yaroslav Kiliba + - Raffaele Carelle + - ivan + - Anthon Pang (robocoder) + - Vitalii Ekert (comrade42) + - Kieran Brahney + - Sanpi (sanpi) + - Lorenz Schori + - Alex (aik099) + - Thierry T (lepiaf) - FORT Pierre-Louis (plfort) - - Terje Bråten - - Tarmo Leppänen (tarlepp) - - Jakub Kucharovic (jkucharovic) + - Hamza Makraz (makraz) + - Vladyslav Loboda + - Gonzalo Vilaseca (gonzalovilaseca) + - Diego Agulló (aeoris) - Daniel STANCU - - Kristen Gilden - - Robbert Klarenbeek (robbertkl) - - Eric Masoero (eric-masoero) - - Vitalii Ekert (comrade42) - - Clara van Miert - - hossein zolfi (ocean) - - James Gilliland (neclimdul) - - Kirill chEbba Chebunin - - Nathanael Noblet (gnat) - - ShinDarth - - giulio de donato (liuggio) - - Marek Kalnik (marekkalnik) - - Matthias Althaus (althaus) - Eduardo Gulias (egulias) + - Vincent Chalamon + - Vyacheslav Salakhutdinov (megazoll) - Cătălin Dan (dancatalin) - - Dimitri Gritsajuk (ottaviano) - - Daniel Tschinder - - Stéphane PY (steph_py) - - BrokenSourceCode - - Alex (aik099) - - Rhodri Pugh (rodnaph) - - Grzegorz (Greg) Zdanowski (kiler129) + - flack (flack) + - Christophe L. (christophelau) + - Hassan Amouhzi + - Johann Pardanaud + - Kev + - Asmir Mustafic (goetas) + - Ivan Mezinov - Pol Dellaiera (drupol) + - Islam Israfilov (islam93) + - vladimir.reznichenko + - Nicolas LEFEVRE (nicoweb) + - smoench + - Issam Raouf (iraouf) + - Thomas Royer (cydonia7) + - Vadim Kharitonov (vadim) - Clément Gautier (clementgautier) - - Kieran Brahney - - Sanpi (sanpi) - - Fabien Villepinte - - Vyacheslav Salakhutdinov (megazoll) + - Kai + - C (dagardner) + - BrokenSourceCode + - Endre Fejes + - Laszlo Korte + - Mateusz Sip (mateusz_sip) + - mondrake (mondrake) + - Tarmo Leppänen (tarlepp) + - Michele Locati + - Hendrik Luup (hluup) + - Pablo Lozano (arkadis) - Greg Thornton (xdissent) - - Alex Bowers - - Gasan Guseynov (gassan) - - Philipp Kräutli (pkraeutli) - - Kev - - kor3k kor3k (kor3k) - - Costin Bereveanu (schniper) - - Maksym Slesarenko (maksym_slesarenko) + - James Gilliland (neclimdul) + - Felix Labrecque + - Ben Scott (bpscott) + - hubert lecorche (hlecorche) + - Roumen Damianoff + - Alain Hippolyte (aloneh) + - Ricard Clau (ricardclau) + - Zmey - Marc Biorklund (mbiork) - - Michele Locati - Arthur de Moulins (4rthem) - - Tobias Naumann (tna) - - Daniel Beyer - - Ivan Sarastov (isarastov) - - flack (flack) - - Shein Alexey - - Joe Lencioni - - vladimir.reznichenko + - Jan Böhmer - Albert Jessurum (ajessu) - - Kai - - Grenier Kévin (mcsky_biig) - - Xavier HAUSHERR - - Alessandro Desantis - - hubert lecorche (hlecorche) - - Vladyslav Loboda - - Marc Morales Valldepérez (kuert) + - Maksym Slesarenko (maksym_slesarenko) - Karel Souffriau - - Vadim Kharitonov (vadim) + - Marc Morales Valldepérez (kuert) + - Tobias Naumann (tna) + - Terje Bråten + - Francesco Levorato + - Dmytro Borysovskyi (dmytr0) + - Matthias Althaus (althaus) + - Kristen Gilden + - SUMIDA, Ippei (ippey_s) - Oscar Cubo Medina (ocubom) - - Alain Hippolyte (aloneh) - - Christophe L. (christophelau) - - Julien Galenski (ruian) - - Ben Scott (bpscott) - - Pablo Lozano (arkadis) - - Laszlo Korte - - Diego Agulló (aeoris) - Valmonzo - - Matthew Lewinski (lewinski) - - Soner Sayakci - - Jan Böhmer - - Hassan Amouhzi - - a.dmitryuk - - Yannick Ihmels (ihmels) - - Endre Fejes - - Vincent Chalamon - - Philippe Segatori - - Raffaele Carelle + - Grenier Kévin (mcsky_biig) - Link1515 - - Anthon Pang (robocoder) + - Ivan Sarastov (isarastov) + - kor3k kor3k (kor3k) + - Erin Millard + - Daniel Beyer + - Robbert Klarenbeek (robbertkl) - Thibaut Cheymol (tcheymol) - - Ricard Clau (ricardclau) - - Issam Raouf (iraouf) - - Christoph Mewes (xrstf) - - Koen Reiniers (koenre) - - Kurt Thiemann - - Gijs van Lammeren - - ilyes kooli (skafandri) - - Alireza Mirsepassi (alirezamirsepassi) - - Sebastian Bergmann - - Giso Stallenberg (gisostallenberg) - - Adam Harvey - - Nadim AL ABDOU (nadim) - - Matthew Grasmick - - Pablo Díez (pablodip) - - Romain Gautier (mykiwi) - - Sergio Santoro - - Jonas Elfering + - Yannick Ihmels (ihmels) + - Martin Herndl (herndlm) + - Haralan Dobrev (hkdobrev) + - Gasan Guseynov (gassan) + - Nathanael Noblet (gnat) + - Tobias Sjösten (tobiassjosten) + - Xavier HAUSHERR + - Fabien Villepinte + - Stéphane PY (steph_py) + - Matthew Lewinski (lewinski) + - Daniel Tschinder + - giulio de donato (liuggio) + - Harm van Tilborg (hvt) + - Alessandro Desantis + - Marek Kalnik (marekkalnik) + - Alex Bowers + - Vitaliy Zakharov (zakharovvi) + - Artem (artemgenvald) + - Costin Bereveanu (schniper) + - Inal DJAFAR (inalgnu) + - Jeremy Livingston (jeremylivingston) + - hossein zolfi (ocean) + - Shein Alexey + - Gyula Sallai (salla) + - Soner Sayakci + - Philipp Kräutli (pkraeutli) + - Lukáš Holeczy (holicz) + - Julien Galenski (ruian) + - Andrii Dembitskyi + - Benjamin (yzalis) + - Tri Pham (phamuyentri) + - Marcos Rezende (rezende79) + - Boris Vujicic (boris.vujicic) + - Marcin Chyłek (songoq) + - Chris Sedlmayr (catchamonkey) + - Anthony Ferrara + - Steffen Roßkamp - nikos.sotiropoulos - - Yoshio HANAWA - - Eduardo Oliveira (entering) - - Oleksii Zhurbytskyi - - Bahman Mehrdad (bahman) - - Bilge - - Trent Steel (trsteel88) - - Barry vd. Heuvel (barryvdh) - - Ricardo Oliveira (ricardolotr) - - Jonathan Johnson (jrjohnson) - - Nicolas Dewez (nicolas_dewez) - - Antonin CLAUZIER (0x346e3730) - - Jeroen Thora (bolle) - - Marek Zajac - - Markus Lanthaler (lanthaler) - - Greg ORIOL - - Leevi Graham (leevigraham) - - Zbigniew Malcherczyk (ferror) - - Roy Van Ginneken (rvanginneken) - - Nathan Dench (ndenc2) - - Denis Kulichkin (onexhovia) - - Adam Szaraniec - - Anatoly Pashin (b1rdex) - - Soufian EZ ZANTAR (soezz) - - Patrick Reimers (preimers) - - BENOIT POLASZEK (bpolaszek) - - Marvin Feldmann (breyndotechse) - - Evan S Kaufman (evanskaufman) - - mcben - - Klaus Silveira (klaussilveira) - - Roberto Espinoza (respinoza) + - Restless-ET + - Jonas Elfering + - Matthias Krauser (mkrauser) + - Desjardins Jérôme (jewome62) + - Peter Bowyer (pbowyer) + - Antonio Jose Cerezo (ajcerezo) + - Mathias STRASSER (roukmoute) + - Florian Merle (florian-merle) + - Fabrice Bernhard (fabriceb) + - Johan Vlaar (johjohan) + - Andrew Udvare (audvare) + - François Dume (franek) + - Robert-Jan de Dreu + - Michel Salib (michelsalib) + - simon chrzanowski (simonch) + - Jerzy Lekowski (jlekowski) - Rob Bast - - Grummfy (grummfy) + - William Arslett (warslett) + - Arnaud De Abreu (arnaud-deabreu) + - Evan S Kaufman (evanskaufman) + - Krzysztof Piasecki (krzysztek) + - Denis Gorbachev (starfall) - Jérôme Vieilledent (lolautruche) - - Roman Anasal - - Filip Procházka (fprochazka) - - Sergey Panteleev - - Gigino Chianese (sajito) - - Remi Collet - - Piotr Kugla (piku235) - - Vicent Soria Durá (vicentgodella) - - Anthony Ferrara - - tim - - Ioan Negulescu + - Jannik Zschiesche + - Mark Challoner (markchalloner) + - Brian King + - Jonas Flodén (flojon) + - Arkadius Stefanski (arkadius) + - Gildas Quéméner (gquemener) + - Benjamin Zaslavsky (tiriel) + - Trent Steel (trsteel88) + - Shakhobiddin - Jakub Škvára (jskvara) - - Andrew Udvare (audvare) - - siganushka (siganushka) + - Ilija Tovilo (ilijatovilo) + - Ben Roberts (benr77) + - Zbigniew Malcherczyk (ferror) + - Tobias Bönner - Quentin Schuler (sukei) - - Dariusz Ruminski - Matthieu Bontemps + - Lescot Edouard (idetox) + - Toni Rudolf (toooni) - Erik Trapman - - De Cock Xavier (xdecock) + - Kurt Thiemann + - Martin Kirilov (wucdbm) + - Grummfy (grummfy) + - Berny Cantos (xphere81) + - Marcin Michalski (marcinmichalski) + - Petr Duda (petrduda) + - Christoph Mewes (xrstf) + - Yi-Jyun Pan + - Markus Staab + - Ben Ramsey (ramsey) + - Alexandru Furculita (afurculita) + - Stefan Gehrig (sgehrig) + - Disquedur + - Manuel de Ruiter (manuel) + - Miro Michalicka + - Hans Mackowiak + - Joachim Løvgaard (loevgaard) + - Angelov Dejan (angelov) + - Norbert Orzechowicz (norzechowicz) + - Neil Peyssard (nepey) + - quentin neyrat (qneyrat) + - Romain Gautier (mykiwi) + - Eugene Wissner + - Ivan Rey (ivanrey) + - Nate (frickenate) + - Roy Van Ginneken (rvanginneken) + - Artem Stepin (astepin) + - Sergio Santoro + - Thomas Talbot (ioni) - Scott Arciszewski - - R. Achmad Dadang Nur Hidayanto (dadangnh) + - Arturs Vonda + - Ziumin + - Tobias Weichart + - Sander Toonen (xatoo) + - Niklas Fiekas + - battye + - Jérôme Macias (jeromemacias) - Bhavinkumar Nakrani (bhavin4u) - Matthijs van den Bos (matthijs) - - Peter Bowyer (pbowyer) - - Markus S. (staabm) - - John Bafford (jbafford) - - PatNowak - - Samuele Lilli (doncallisto) - - Chad Sikorra (chadsikorra) - - William Arslett (warslett) - - Dave Hulbert (dave1010) - - Marcin Chyłek (songoq) - - Krzysztof Piasecki (krzysztek) - - Oleksiy (alexndlm) - - Denis Gorbachev (starfall) - - Jerzy Lekowski (jlekowski) - - François Dume (franek) - - Pavel Popov (metaer) - - Fabrice Bernhard (fabriceb) - - Lenard Palko - - Jaik Dean (jaikdean) - - Nils Adermann (naderman) - - Joachim Løvgaard (loevgaard) - - Tavo Nieves J (tavoniievez) + - Judicaël RUFFIEUX (axanagor) + - DerManoMann + - W0rma + - Erkhembayar Gantulga (erheme318) + - Philipp Rieber (bicpi) + - Ariel Ferrandini (aferrandini) + - Mohammad Emran Hasan (phpfour) + - Jérémy DECOOL (jdecool) + - Roman Anasal - Vadim Borodavko (javer) - - Maximilian Zumbansen - - Anton Bakai + - Chad Sikorra (chadsikorra) - Tom Klingenberg - - Gábor Fási - - Gawain Lynch (gawain) - - Ivan Rey (ivanrey) - - Nate (frickenate) - - Stefan Kruppa + - Benoit Galati (benoitgalati) + - Filip Procházka (fprochazka) + - Jérémy M (th3mouk) - Jacek Jędrzejewski (jacek.jedrzejewski) - - Shakhobiddin - - sasezaki - - Dawid Pakuła (zulusx) - - Dominik Zogg + - AnneKir + - Maarten de Boer (mdeboer) + - Petrisor Ciprian Daniel + - Marcin Szepczynski (czepol) + - Yoshio HANAWA + - R. Achmad Dadang Nur Hidayanto (dadangnh) + - ReenExe + - Klaus Silveira (klaussilveira) + - Alireza Mirsepassi (alirezamirsepassi) + - Maxime Pinot (maximepinot) + - lancergr + - Ivan Nikolaev (destillat) + - Chris Tanaskoski (devristo) + - Jonathan Johnson (jrjohnson) + - Korvin Szanto + - Soufian EZ ZANTAR (soezz) + - Gigino Chianese (sajito) + - Valentin Jonovs + - NickSdot + - Erik Saunier (snickers) + - Maximilian Ruta (deltachaos) + - Dmitriy Mamontov (mamontovdmitriy) + - Maxim Dovydenok (dovydenok-maxim) - M. Vondano - - Florian Rey (nervo) - - Rodrigo Borrego Bernabé (rodrigobb) - - Marcos Rezende (rezende79) - - Petr Duda (petrduda) - - Martin Morávek (keeo) - - Steven Surowiec (steves) - - Shawn Iwinski - - mmokhi - - Kevin McBride - - Ryan - - Alexander Deruwe (aderuwe) - - Hans Mackowiak - - M. (mbontemps) - - Ned Schwartz - - Daniel Tiringer - - Ilija Tovilo (ilijatovilo) - - Sander Toonen (xatoo) - - Guilherme Ferreira + - Mokhtar Tlili (sf-djuba) + - Asier Illarramendi (doup) + - Krasimir Bosilkov (kbosilkov) + - De Cock Xavier (xdecock) - Zach Badgett (zachbadgett) + - Miroslav Šustek (sustmi) + - Joshua Nye + - Daniel Tiringer + - Dennis Fridrich (dfridrich) + - Greg ORIOL + - Tavo Nieves J (tavoniievez) + - Remi Collet + - Sam Fleming (sam_fleming) + - Axel Guckelsberger (guite) + - Pablo Díez (pablodip) + - Adam Harvey + - Denis Kulichkin (onexhovia) + - Oleksii Zhurbytskyi - Loïc Faugeron - - Miro Michalicka + - Rodrigo Borrego Bernabé (rodrigobb) + - Nils Adermann (naderman) + - siganushka (siganushka) + - Ned Schwartz + - Oleksiy (alexndlm) + - Eduardo Oliveira (entering) + - Ryan + - Markus S. (staabm) + - John Bafford (jbafford) + - mmokhi + - Michael Moravec + - Gábor Fási + - Dariusz Ruminski + - Dirk Pahl (dirkaholic) + - Ioan Negulescu + - Pavel Popov (metaer) + - Sergey Melesh (sergex) - Aurélien Fredouelle - - Pavel Campr (pcampr) - - Forfarle (forfarle) - - Yi-Jyun Pan - - Tobias Weichart - - Maxime Pinot (maximepinot) - - AnneKir - - W0rma - - Jonas Flodén (flojon) - - Disquedur - - Andrii Dembitskyi - - Geoffrey Tran (geoff) - - Jannik Zschiesche - - Bernd Stellwag - - Jan Ole Behrens (deegital) - - Markus Staab - BASAK Semih (itsemih) - - Ariel Ferrandini (aferrandini) - - Johnny Robeson (johnny) - - Robert-Jan de Dreu - - Petrisor Ciprian Daniel - - Vitaliy Tverdokhlib (vitaliytv) - - Marcin Michalski (marcinmichalski) - - Cédric Lombardot (cedriclombardot) - - Krasimir Bosilkov (kbosilkov) - - Luc Vieillescazes (iamluc) - - Andrew M-Y (andr) - - Faizan Akram Dar (faizanakram) - - Martin Kirilov (wucdbm) - - Dirk Pahl (dirkaholic) - - Arkadius Stefanski (arkadius) - - Kamil Kokot (pamil) - - Raulnet - - simon chrzanowski (simonch) - - Chris Sedlmayr (catchamonkey) - - Arnaud POINTET (oipnet) - - Mathias STRASSER (roukmoute) - - Erik Saunier (snickers) - - Jérémy DECOOL (jdecool) - - DerManoMann - - Jérémy REYNAUD (babeuloula) - - Judicaël RUFFIEUX (axanagor) - - Andy Palmer (andyexeter) + - Fabian Lange (codingfabian) - Dries Vints - - Boris Vujicic (boris.vujicic) - - Vlad Gregurco (vgregurco) - - Artem Stepin (astepin) - - Martijn Cuppens - - Asier Illarramendi (doup) - - Brayden Williams (redstar504) - - Maarten de Boer (mdeboer) - - Jérôme Tanghe (deuchnord) - - Benjamin Cremer (bcremer) - - vagrant - - Stefan Gehrig (sgehrig) - - Arturs Vonda - - Desjardins Jérôme (jewome62) - - Claude Khedhiri (ck-developer) + - M. (mbontemps) + - lenar - Laurent Masforné (heisenberg) - - Maxim Dovydenok (dovydenok-maxim) - - Ioan Ovidiu Enache (ionutenache) - - Ivan Nikolaev (destillat) - Emanuele Iannone - - Angelov Dejan (angelov) - - Tri Pham (phamuyentri) - - lancergr + - Martin Morávek (keeo) + - Jan Schumann + - Maelan LE BORGNE - AKeeman (akeeman) - - Sergey Melesh (sergex) - - Arnaud De Abreu (arnaud-deabreu) - - Jérémy M (th3mouk) - - Erkhembayar Gantulga (erheme318) - - Neil Peyssard (nepey) + - Luc Vieillescazes (iamluc) + - Quentin Dequippe (qdequippe) + - Bernd Stellwag + - kylekatarnls (kylekatarnls) + - Matthew Grasmick + - Kevin McBride + - Nadim AL ABDOU (nadim) + - Kamil Kokot (pamil) + - Piotr Kugla (piku235) + - Koen Reiniers (koenre) - Gunnstein Lye (glye) - - Toni Rudolf (toooni) - - Lescot Edouard (idetox) - - Andreas Hennings - - Matthias Krauser (mkrauser) + - Vicent Soria Durá (vicentgodella) + - Roberto Espinoza (respinoza) + - Maximilian Zumbansen + - Lenard Palko + - Bilge + - Benjamin Georgeault (wedgesama) + - Belhassen Bouchoucha (crownbackend) + - ilyes kooli (skafandri) + - Jeanmonod David (jeanmonod) + - Andrew M-Y (andr) + - boombatower + - Patrick Reimers (preimers) + - Marek Zajac - Kevin Saliou (kbsali) - - Mark Challoner (markchalloner) - - Florian Merle (florian-merle) - - Niklas Fiekas - - Mohammad Emran Hasan (phpfour) + - Geoffrey Tran (geoff) + - Alex Bakhturin + - Guilherme Ferreira + - Forfarle (forfarle) + - Jan van Thoor (janvt) + - Vlad Gregurco (vgregurco) + - Sergey Panteleev - Greg Anderson - - Markus Bachmann (baachi) - - Jan Schumann - - Dmitriy Mamontov (mamontovdmitriy) - - Benjamin Georgeault (wedgesama) - - Dennis Fridrich (dfridrich) - - Benjamin Zaslavsky (tiriel) - - Gildas Quéméner (gquemener) - - Restless-ET - - Mokhtar Tlili (sf-djuba) - - Ziumin - - Maelan LE BORGNE - - Berny Cantos (xphere81) - - PHAS Developer - - Thomas Talbot (ioni) - - Christian Gripp (core23) + - Matthew Smeets + - Gawain Lynch (gawain) + - Alexander Deruwe (aderuwe) + - vagrant + - Barry vd. Heuvel (barryvdh) + - Markus Lanthaler (lanthaler) + - Ricardo Oliveira (ricardolotr) + - Nicolas Dewez (nicolas_dewez) + - Dawid Pakuła (zulusx) - geoffrey - - Alexandru Furculita (afurculita) - - Johan Vlaar (johjohan) - - Chris Tanaskoski (devristo) - - quentin neyrat (qneyrat) - - Brian King - - Nicolas Rigaud - - Marcin Szepczynski (czepol) - - Valentin Jonovs - - Ben Ramsey (ramsey) - - Tobias Bönner - - Steffen Roßkamp - - Benjamin (yzalis) - - Ben Roberts (benr77) - - Antonio Jose Cerezo (ajcerezo) + - Dave Hulbert (dave1010) + - Andrey Astakhov (aast) + - Pavel Campr (pcampr) + - PHAS Developer + - Johnny Robeson (johnny) + - Gijs van Lammeren + - Sebastian Bergmann - Webnet team (webnet) - Ahmed Ghanem (ahmedghanem00) + - Cédric Lombardot (cedriclombardot) + - Claude Khedhiri (ck-developer) + - BENOIT POLASZEK (bpolaszek) + - Steven Surowiec (steves) + - tim + - Dominik Zogg + - Florian Rey (nervo) + - Andreas Hennings + - Marvin Feldmann (breyndotechse) + - Stefan Kruppa - Andrey Lebedev (alebedev) - - Jeanmonod David (jeanmonod) - - Benoit Galati (benoitgalati) - - Quentin Dequippe (qdequippe) - - Matthew Smeets - - Michael Moravec - - Andrey Astakhov (aast) - - Eugene Wissner - - Norbert Orzechowicz (norzechowicz) - - lenar - - Xavier HAUSHERR + - Arnaud POINTET (oipnet) + - Faizan Akram Dar (faizanakram) + - Martijn Cuppens + - Ioan Ovidiu Enache (ionutenache) + - Kevin van Sonsbeek (kevin_van_sonsbeek) + - Giso Stallenberg (gisostallenberg) + - Antonin CLAUZIER (0x346e3730) + - Anton Bakai + - PatNowak - Matheo Daninos (mathdns) - - battye + - Markus Bachmann (baachi) + - Raulnet + - Vitaliy Tverdokhlib (vitaliytv) + - Christian Gripp (core23) - Max Baldanza - Steven RENAUX (steven_renaux) - - Philipp Rieber (bicpi) - - Manuel de Ruiter (manuel) - - Michel Salib (michelsalib) - - Jérôme Macias (jeromemacias) - - Axel Guckelsberger (guite) - - Alex Bakhturin - - Belhassen Bouchoucha (crownbackend) - - Sam Fleming (sam_fleming) - - Joshua Nye - - boombatower - - ReenExe - - Fabian Lange (codingfabian) - - kylekatarnls (kylekatarnls) - - Miroslav Šustek (sustmi) - - Jan van Thoor (janvt) + - Adam Szaraniec + - Nathan Dench (ndenc2) + - Leevi Graham (leevigraham) + - Jaik Dean (jaikdean) + - Xavier HAUSHERR + - Samuele Lilli (doncallisto) + - Jérémy REYNAUD (babeuloula) + - Jeroen Thora (bolle) + - mcben + - Anatoly Pashin (b1rdex) + - Bahman Mehrdad (bahman) + - Nicolas Rigaud + - Brayden Williams (redstar504) + - Benjamin Cremer (bcremer) + - Shawn Iwinski + - sasezaki + - Jérôme Tanghe (deuchnord) + - Andy Palmer (andyexeter) + - Jan Ole Behrens (deegital) + - Stefan Warman (warmans) + - Jay Klehr + - Eric COURTIAL + - Adrian Günter (adrianguenter) + - Mikhail Yurasov (mym) + - Brunet Laurent (lbrunet) + - Elan Ruusamäe (glen) + - louismariegaborit + - Mior Muhammad Zaki (crynobone) + - Denis Zunke (donalberto) + - vitaliytv + - Ворожцов Максим (myks92) + - Gert de Pagter + - Arno Geurts + - Masterklavi + - Vincent CHALAMON + - Franck RANAIVO-HARISOA (franckranaivo) + - Christophe V. (cvergne) + - Zhuravlev Alexander (scif) + - Ian Jenkins (jenkoian) + - Shin Ohno (ganchiku) + - skmedix (skmedix) + - Johannes Klauss (cloppy) + - Reen Lokum + - Kay Wei + - Korvin Szanto + - Andreas Erhard (andaris) + - Mathias Brodala (mbrodala) + - Robert Gruendler (pulse00) + - Fabian Vogler (fabian) + - Tristan Roussel + - Sébastien Despont (bouillou) + - Florian Wolfsjaeger (flowolf) + - Matthieu Bontemps - Alexandre Parent - Sofien Naas - - Daniel Badura - - Loïc Ovigne (oviglo) - - Brajk19 + - Stéphan Kochen + - ampaze + - Ramunas Pabreza (doobas) + - Carlos Pereira De Amorim (epitre) + - DUPUCH (bdupuch) + - Benjamin Laugueux + - Rostyslav Kinash + - Jan Kramer + - Kyle Evans (kevans91) + - aegypius + - Adam + - Dennis Væversted (srnzitcom) + - Thomas Trautner (thomastr) + - Jesper Noordsij + - Ilia (aliance) + - nathanpage + - Cyril Pascal (paxal) + - Christophe Villeger (seragan) + - Damien Fa - Dustin Dobervich (dustin10) - - Martijn Evers - Roger Guasch (rogerguasch) - - Vladimir Varlamov (iamvar) - - DT Inier (gam6itko) - - Luis Tacón (lutacon) - - Dmitrii Tarasov (dtarasov) - - Philipp Kolesnikov - - Sebastian Marek (proofek) - - zenmate - - Malte Müns - - Rodrigo Aguilera - - Aurimas Niekis (gcds) - - andrey1s - - Fabien Salles (blacked) - - Sem Schidler (xvilo) - - Benjamin Schoch (bschoch) - - Rostyslav Kinash - - Marc Abramowitz - - Rimas Kudelis - - Christophe V. (cvergne) - - Mardari Dorel (dorumd) - - Vincent Simonin - - Pierrick VIGNAND (pierrick) - - aaa2000 (aaa2000) - - Andrew Neil Forster (krciga22) - - Stefan Warman (warmans) - - Tristan Maindron (tmaindron) - - Behnoush Norouzali (behnoush) - - Marko H. Tamminen (gzumba) + - Sergey Zolotov (enleur) + - wanxiangchwng + - Arjan Keeman - Wesley Lancel - - katario - - Ivo Bathke (ivoba) - - Ke WANG (yktd26) + - Oleksandr Barabolia (oleksandrbarabolia) - 243083df - - Luca Saba (lucasaba) - - Lukas Mencl - - Emil Einarsson - - Mickaël Isaert (misaert) - - David Molineus - - Gregor Nathanael Meyer (spackmat) - - Florent Viel (luxifer) - - Anton A. Sumin - - Don Pinkster - - Miquel Rodríguez Telep (mrtorrent) - - Andreas Erhard (andaris) - - alexandre.lassauge - - Guillaume Aveline - - Israel J. Carberry + - Sherin Bloemendaal + - Jayson Xu (superjavason) + - Vitaliy Ryaboy (vitaliy) + - StefanoTarditi + - abdul malik ikhsan (samsonasik) + - grizlik + - Maxim Tugaev (tugmaks) + - Alexander Dmitryuk (coden1) + - Oliver Hoff + - Jordan Deitch + - Mike Meier (mykon) + - Derek ROTH + - Christian Stoller (naitsirch) + - Stéphane Escandell (sescandell) + - Sascha Dens (saschadens) + - Yuriy Vilks (igrizzli) + - Rustam Bakeev (nommyde) + - Quentin Dreyer (qkdreyer) + - Mátyás Somfai (smatyas) - Michael Devery (mickadoo) - - Tamás Nagy (t-bond) - - Kieran - - Robin van der Vleuten (robinvdvleuten) - - Kien Nguyen - - Sergey Kolodyazhnyy (skolodyazhnyy) - - umpirski + - RJ Garcia + - Ivan Kurnosov + - Benoît Merlet (trompette) + - Rimas Kudelis + - Pierrick VIGNAND (pierrick) - Quentin de Longraye (quentinus95) - - Chris Heng (gigablah) - - Mickaël Buliard (mbuliard) - - Michael Roterman (wtfzdotnet) - - Morten Wulff (wulff) - - Jan Nedbal - - Cornel Cruceru (amne) - - Richard Bradley - - Jan Walther (janwalther) - - rtek - - Adrien Jourdier (eclairia) - - Florian Pfitzer (marmelatze) - - Alaattin Kahramanlar (alaattin) - - Ivan Grigoriev (greedyivan) - - ornicar - - Johann Saunier (prophet777) - - Kevin SCHNEKENBURGER - - Geordie - - Tim Düsterhus - - Antoine Corcy - - Ahmed Ashraf (ahmedash95) - - Gert Wijnalda (cinamo) - - Aurimas Niekis (aurimasniekis) - - Sascha Grossenbacher (berdir) - - nathanpage - - _sir_kane (waly) - - Robin Lehrmann - - Thomas P - - Steve Grunwell - - Stephan Vock (glaubinix) - - Jaroslav Kuba - - Kristijan Kanalaš (kristijan_kanalas_infostud) - - Benjamin Zikarsky (bzikarsky) - - Rodrigo Méndez (rodmen) - - Oriol Viñals - - michaelwilliams - - Maks 3w (maks3w) + - Tony Tran + - Martijn Evers + - “Filip - sl_toto (sl_toto) - - Sascha Dens (saschadens) - - Renan Gonçalves (renan_saddam) - - Matt Janssen + - Alexandre Dupuy (satchette) + - Michel Hunziker + - Oriol Viñals + - Carl Casbolt (carlcasbolt) + - Nahuel Cuesta (ncuesta) + - Jeroen Fiege (fieg) + - Seb Koelen + - Dmitry Parnas (parnas) + - Jose Gonzalez + - AndrolGenhald + - Ruben Gonzalez (rubenruateltek) + - katario + - Michael Piecko (michael.piecko) + - Ana Raro + - Andrii Dembitskyi + - Edvin Hultberg + - Wouter van der Loop (toppy-hennie) + - Eric Abouaf (neyric) - Marek Pietrzak (mheki) - - “Filip - - Tristan Roussel - - RJ Garcia - - Jawira Portugal (jawira) - - Joschi Kuphal - - Oliver Hoff - - Simon Watiau (simonwatiau) - - Benjamin Grandfond (benjamin) - - Simon Schick (simonsimcity) - - Ruben Jacobs (rubenj) - - Toon Verwerft (veewee) - - Delf Tonder (leberknecht) - - Thomas Ploch - - Niklas Keller - - Douglas Hammond (wizhippo) + - Pierre Vanliefland (pvanliefland) + - Alex Xandra Albert Sim + - Bastien THOMAS + - Ivan Menshykov + - Lorenzo Millucci (lmillucci) + - Daniel Alejandro Castro Arellano (lexcast) + - Simon Leblanc (leblanc_simon) + - Travis Carden (traviscarden) + - Simon Schick (simonsimcity) + - Matt Johnson (gdibass) + - Paweł Niedzielski (steveb) + - Sylvain BEISSIER (sylvain-beissier) + - radar3301 + - Oriol Viñals + - Christopher Hall (mythmakr) - Cameron Porter + - Benjamin Grandfond (benjamin) + - umpirski + - Johann Saunier (prophet777) - Hossein Bukhamsin + - frost-nzcr4 + - Rootie + - Matthew Davis (mdavis1982) + - Loïc Chardonnet + - Paulo Ribeiro (paulo) + - Mickaël Isaert (misaert) + - Fred Cox + - arai + - Wu (wu-agriconomie) + - Andrew Tchircoff (andrewtch) + - Matthieu Calie (matth--) + - Simon Watiau (simonwatiau) + - Julien DIDIER (juliendidier) + - Toni Peric (tperic) + - Vladimir Valikayev + - Maxime COLIN (maximecolin) - Christian Sciberras (uuf6429) - - Thomas Nunninger - - origaminal - - Matteo Beccati (matteobeccati) - - Vitaliy Ryaboy (vitaliy) - - Kevin (oxfouzer) - - Paweł Wacławczyk (pwc) - - Oleg Zinchenko (cystbear) - - Baptiste Meyer (meyerbaptiste) - - Tales Santos (tsantos84) - - Evan Villemez - - Alexander Miehe - - Morgan Auchede - - fzerorubigd - - Tiago Brito (blackmx) - - Gintautas Miselis (naktibalda) - - Richard van den Brand (ricbra) - - develop - - Adrien Lucas (adrienlucas) - - Mark Sonnabaum - - Chris Jones (magikid) - - Massimiliano Braglia (massimilianobraglia) - - Alexandre parent - - Jakub Podhorsky (podhy) - - Jean-Baptiste GOMOND (mjbgo) - - Dmytro Boiko (eagle) - - Daniël Brekelmans (dbrekelmans) - - Andreas Leathley (iquito) - - Richard Quadling - - James Hudson (mrthehud) - - Roland Franssen :) - - Raphaëll Roussel - - Simon Heimberg (simon_heimberg) - - Sergey Zolotov (enleur) - - Benoît Bourgeois (bierdok) - - Michael Lutz - - jochenvdv - - Andrew Codispoti - - mweimerskirch + - Christin Gruber (christingruber) + - Noah Heck (myesain) + - Davide Borsatto (davide.borsatto) + - Arturas Smorgun (asarturas) + - Josiah (josiah) + - Ian Irlen + - Tamas Szijarto - Sebastian Grodzicki (sgrodzicki) - - Jan Kramer - - Oriol Viñals - - Jay Klehr - - Reedy + - Kien Nguyen + - Antoine Corcy + - Sander De la Marche (sanderdlm) + - Dave Marshall (davedevelopment) + - Ondrej Exner + - Paul Kamer (pkamer) + - Gabrielle Langer - Simo Heinonen (simoheinonen) - - Arturas Smorgun (asarturas) - - Aleksandr Volochnev (exelenz) - - grizlik - - Thijs-jan Veldhuizen (tjveldhuizen) - - wanxiangchwng - - Grinbergs Reinis (shima5) - - Vladimir Luchaninov (luchaninov) - - NanoSector - - bogdan - - Michael Piecko (michael.piecko) - - Julien DIDIER (juliendidier) - - Toni Peric (tperic) + - Steve Grunwell + - Casper Valdemar Poulsen + - Sebastian Blum + - Simon Terrien (sterrien) + - Sergey Yastrebov + - COMBROUSE Dimitri + - Claudio Zizza + - alexpozzi + - Andrew Neil Forster (krciga22) + - Gábor Tóth + - Asier Etxebeste + - Jakub Kulhan (jakubkulhan) + - James Michael DuPont - Wybren Koelmans (wybren_koelmans) - - Davide Borsatto (davide.borsatto) - - radar3301 - - Jelle Raaijmakers (gmta) - - Roberto Nygaard - - Vitaliy Zhuk (zhukv) - - mwsaz - - zenas1210 - - Gert de Pagter - - Jason Woods - - Andrii Popov (andrii-popov) - - Ворожцов Максим (myks92) - - Randy Geraads - - Kevin van Sonsbeek (kevin_van_sonsbeek) - - Mohamed Gamal - - Eric COURTIAL - - Xesxen - - Arun Philip - - flip111 - - Baldur Rensch (brensch) - - Pascal Helfenstein + - den + - Pavlo Pelekh (pelekh) + - Baptiste Meyer (meyerbaptiste) + - Michał Jusięga + - Jan Nedbal + - stoccc + - Israel J. Carberry + - Dominik Ulrich + - Richard Quadling + - Harry Walter (haswalt) + - andrey1s + - Shahriar56 - Jesper Skytte (greew) - - Stéphan Kochen + - Alexandre parent - Petar Obradović - - Konstantin Grachev (grachevko) - - Alex (garrett) + - wicliff wolda (wickedone) + - Gert Wijnalda (cinamo) + - _sir_kane (waly) + - Andrew Codispoti + - Roland Franssen :) + - Maksim Kotlyar (makasim) + - Aurimas Niekis (aurimasniekis) + - Tomasz Ignatiuk + - Cornel Cruceru (amne) - yclian - - David Marín Carreño (davefx) - - Tarjei Huse (tarjei) - - Paweł Niedzielski (steveb) - - stoccc + - Youssef Benhssaien (moghreb) + - Anton A. Sumin + - Carlos Quintana + - Tristan Maindron (tmaindron) + - Marco Lipparini (liarco) + - SpacePossum + - Stéphane Delprat + - Achilles Kaloeridis (achilles) + - Besnik Br + - Florian Pfitzer (marmelatze) + - Thijs-jan Veldhuizen (tjveldhuizen) + - Benedikt Lenzen (demigodcode) + - Roy de Vos Burchart + - Volodymyr Panivko + - Xav` (xavismeh) + - Behnoush Norouzali (behnoush) + - Jordi Sala Morales (jsala) - Jiri Barous - - Simon Mönch - - Vladyslav Petrovych - - Robert Fischer (sandoba) - - Jörn Lang - - Amr Ezzat (amrezzat) - - Maksim Kotlyar (makasim) - - arai - - Carl Casbolt (carlcasbolt) + - Guillaume Aveline + - ouardisoft + - Delf Tonder (leberknecht) - Simon (kosssi) - - Derek ROTH - - Benjamin Laugueux - - Jose Gonzalez - - Moshe Weitzman (weitzman) - - Loïc Chardonnet - - Carson Full (carsonfull) - - Sergey Yastrebov - - Alex Xandra Albert Sim - - Mathias Brodala (mbrodala) - - Travis Carden (traviscarden) - - Besnik Br - - Sherin Bloemendaal - - Jonathan (jlslew) - - Claudio Zizza - - aegypius - - Ilia (aliance) - - COMBROUSE Dimitri - - Dave Marshall (davedevelopment) - - Jakub Kulhan (jakubkulhan) - - Shaharia Azam - - avorobiev - - Gerben Oolbekkink - - Gladhon - - Maximilian.Beckers - - skmedix (skmedix) - - Shin Ohno (ganchiku) - - Gabrielle Langer - - Lctrs - - Alex Kalineskou - - Calin Mihai Pristavu - - Evan Shaw - - Grégoire Penverne (gpenverne) - - Venu + - Tamás Nagy (t-bond) + - Nicole Cordes (ichhabrecht) + - Jaroslav Kuba + - Malte Blättermann + - Raphaëll Roussel + - James Hudson (mrthehud) + - zenas1210 + - Johnson Page (jwpage) + - Vladimir Luchaninov (luchaninov) + - Andreas Braun + - Guillaume Verstraete + - Emil Masiakowski + - Kristijan Kanalaš (kristijan_kanalas_infostud) + - Stephan Vock (glaubinix) + - Loïc Beurlet - Ryan Hendrickson - - Damien Fa - - Jonatan Männchen - - Carlos Buenosvinos (carlosbuenosvinos) - - Dennis Hotson - - Lars Vierbergen (vierbergenlars) - - Sander De la Marche (sanderdlm) - - Gálik Pál - - Marco Lipparini (liarco) - - Korvin Szanto - - Xav` (xavismeh) - - Barney Hanlon - - Adrian Günter (adrianguenter) - - Jordan Deitch - - Thorry84 - - Romanavr - - Seb Koelen - - Hidde Boomsma (hboomsma) - - Eric Abouaf (neyric) - - Daniel González (daniel.gonzalez) + - benjaminmal + - Vitaliy Zhuk (zhukv) + - Marc Laporte + - Kristof Van Cauwenbergh (kristofvc) + - Stefano Degenkamp (steef) + - Luis Tacón (lutacon) + - Ruben Jacobs (rubenj) + - Tony Malzhacker + - Nguyen Xuan Quynh + - marie - Ondrej Machulda (ondram) - - Alexander Grimalovsky (flying) - - Yosmany Garcia (yosmanyga) - - Thomas Durand - - Guillaume Verstraete - - izzyp - - Fabien LUCAS (flucas2) - - Jon Dufresne - - Oliver Hader - - Gustavo Falco (gfalco) - - Josiah (josiah) - - Thomas Trautner (thomastr) - - Dennis Væversted (srnzitcom) - - Jason Tan (jt2k) - - AndrolGenhald + - Pedro Miguel Maymone de Resende (pedroresende) + - Max Rath (drak3) + - Tinjo Schöni + - Dmytro Boiko (eagle) + - Baptiste CONTRERAS + - Stephan Vierkant (svierkant) + - EStyles (insidestyles) + - Massimiliano Braglia (massimilianobraglia) + - Chris Jones (magikid) + - Gennady Telegin + - jochenvdv + - datibbaw + - julien57 + - Evan Shaw + - Jeremiasz Major + - Franco Traversaro (belinde) + - Douglas Hammond (wizhippo) + - Thibault Buathier (gwemox) + - Thomas Nunninger + - Amr Ezzat (amrezzat) + - Jérôme Tamarelle (jtamarelle-prismamedia) + - Matteo Beccati (matteobeccati) + - Adrien Wilmet (adrienfr) + - Romanavr + - Lars Vierbergen (vierbergenlars) + - Richard Bradley + - Tim Düsterhus + - Grégoire Penverne (gpenverne) + - Reinier Kip - Thibault Richard (t-richard) - - Asier Etxebeste - - Matt Robinson (inanimatt) - - Alexander Li (aweelex) - - Edvin Hultberg - - shubhalgupta - - Felds Liscia (felds) + - Geoffrey Brier (geoffrey-brier) + - Daisuke Ohata + - Adán Lobato (adanlobato) + - Jake (jakesoft) + - Julien Fredon + - Ivan Grigoriev (greedyivan) + - Oleg Zinchenko (cystbear) - Benjamin Lebon - - Andrew Hilobok (hilobok) - - Noah Heck (myesain) - - Benoît Merlet (trompette) - - Christian Soronellas (theunic) - - Volodymyr Panivko - - Patrick Allaert - - Kristof Van Cauwenbergh (kristofvc) - - kick-the-bucket - - fedor.f - - Jeremiasz Major - - Trevor North - - Degory Valentine - - Laurent Bassin (lbassin) - - Jeroen Fiege (fieg) + - Sébastien JEAN (sebastien76) + - Arnaud Frézet + - Julien Tattevin (jutattevin) + - Philipp Keck + - Robert Fischer (sandoba) + - Nikita Nefedov (nikita2206) + - Egor Taranov - Martin (meckhardt) - - Wu (wu-agriconomie) + - Matt Robinson (inanimatt) + - Andrew Hilobok (hilobok) + - Francis Turmel (fturmel) + - Kagan Balga (kagan-balga) + - Paul Oms + - Malte Müns + - Rodrigo Aguilera + - Aurimas Niekis (gcds) + - ywisax + - Fabien LUCAS (flucas2) + - Philippe Segatori + - michaelwilliams + - Benjamin Zikarsky (bzikarsky) + - Glodzienski - Marcel Hernandez - - Evan C + - Johnny Peck (johnnypeck) + - Henry Snoek (snoek09) + - Rodrigo Méndez (rodmen) + - Simon Mönch + - Julien Maulny + - Randy Geraads + - Cristoforo Cervino (cristoforocervino) + - Fabien Salles (blacked) + - Yosmany Garcia (yosmanyga) + - James Hemery + - Jean Pasdeloup + - James Johnston + - Fractal Zombie + - Gennadi Janzen + - Vladyslav Petrovych + - Richard Henkenjohann (richardhj) + - Carson Full (carsonfull) + - Felds Liscia (felds) + - Maximilian Bösing + - VJ + - Pierre Hennequart + - Maximilian.Beckers + - Alex Kalineskou + - Matt Janssen + - Brajk19 + - John Bohn (jbohn) + - hugovms + - Cyril Quintin (cyqui) + - Maksim Muruev + - Mardari Dorel (dorumd) + - Rafał Wrzeszcz (rafalwrzeszcz) + - Tarjei Huse (tarjei) + - aaa2000 (aaa2000) + - zenmate + - Robin Lehrmann + - Reedy + - Ricky Su (ricky) + - Terje Bråten + - Sebastian Marek (proofek) + - Simeon Kolev (simeon_kolev9) + - Andreas Leathley (iquito) + - Reyo Stallenberg (reyostallenberg) + - Martins Sipenko + - Geordie + - Gregor Nathanael Meyer (spackmat) + - Sem Schidler (xvilo) + - Sebastian Paczkowski (sebpacz) + - Simon Heimberg (simon_heimberg) + - Degory Valentine + - Jon Gotlin (jongotlin) + - David Molineus + - Lukas Mencl + - Christian Soronellas (theunic) + - Jörn Lang + - Pedro Casado (pdr33n) + - Mickaël Andrieu (mickaelandrieu) + - shubhalgupta + - Benoît Bourgeois (bierdok) + - Jason Woods + - Sofiane HADDAG (sofhad) - Geert De Deckere + - Julie Hourcade (juliehde) + - Patrick Dawkins (pjcdawkins) + - DT Inier (gam6itko) + - Tales Santos (tsantos84) - buffcode - - abdul malik ikhsan (samsonasik) - - Glodzienski - - Ivan Menshykov - Sinan Eldem (sineld) + - Daniel Cestari + - Balazs Csaba + - noniagriconomie + - Marcos Gómez Vilches (markitosgv) + - Philipp Kolesnikov + - Denis Charrier (brucewouaigne) + - Andreas Lutro (anlutro) + - Xavier Leune (xleune) + - Andrew Berry + - Sebastian Krebs + - Andrey Sevastianov + - mfettig + - Jean-Baptiste GOMOND (mjbgo) + - Mark Sonnabaum + - Bastien DURAND (deamon) + - Xavier Briand (xavierbriand) + - stlrnz + - Roberto Nygaard + - avorobiev + - Guilherme Augusto Henschel + - Michael Lutz + - fzerorubigd + - wuchen90 + - Jakub Podhorsky (podhy) + - Benjamin Schoch (bschoch) + - develop + - Niklas Keller + - Noémi Salaün (noemi-salaun) + - Vincent Simonin + - Pavol Tuka + - Sébastien Santoro (dereckson) + - Florent Destremau (florentdestremau) + - Alexander Grimalovsky (flying) + - Ana Raro + - Dhananjay Goratela + - Julien Turby + - Paweł Wacławczyk (pwc) + - Marko Petrovic + - mwsaz + - Åsmund Garfors + - Gerard van Helden (drm) + - Adrian Nguyen (vuphuong87) + - mweimerskirch + - bogdan + - Ilya Levin (ilyachase) + - Shaharia Azam + - Kevin SCHNEKENBURGER + - Daniel Badura + - Barney Hanlon + - Gerben Oolbekkink + - Nykopol (nykopol) - Krzysztof Łabuś (crozin) - - Xavier Lacot (xavier) - - Maxim Tugaev (tugmaks) - - Denis Zunke (donalberto) - - Adrien Roches (neirda24) - - Nicolas Dousson - - Olivier Maisonneuve - - Christian Stoller (naitsirch) - - Bálint Szekeres + - Kuba Werłos (kuba) - Andrei C. (moldman) - - Mike Meier (mykon) + - Florent Viel (luxifer) + - Bozhidar Hristov + - vladimir.panivko + - Brad Jones + - Calin Mihai Pristavu - Vincent Composieux (eko) - - VJ - - Jordi Sala Morales (jsala) - - Tamas Szijarto - - stlrnz - - Quentin Dreyer (qkdreyer) - - Vincent CHALAMON - - Sébastien JEAN (sebastien76) - - Adrien Wilmet (adrienfr) - - Pedro Miguel Maymone de Resende (pedroresende) - - Johnny Peck (johnnypeck) - - Gerard van Helden (drm) - - Cyril Quintin (cyqui) - - Franco Traversaro (belinde) - - Tomasz Ignatiuk - - Francis Turmel (fturmel) - - Kagan Balga (kagan-balga) - - Nikita Nefedov (nikita2206) - - Alex Bacart - - StefanoTarditi - - ampaze - - Cyril Pascal (paxal) - - Pedro Casado (pdr33n) - - acoulton - - Guilherme Augusto Henschel - - Tomasz Kusy - - DemigodCode - - fago - Jan Prieser - - Johannes Klauss (cloppy) - - Maximilian Bösing - - Matt Johnson (gdibass) - - Zhuravlev Alexander (scif) - - Stefano Degenkamp (steef) - - James Michael DuPont - - Tinjo Schöni - - Jake (jakesoft) - - Rustam Bakeev (nommyde) - - Ivan Kurnosov - - DUPUCH (bdupuch) - - Christopher Hall (mythmakr) - - Patrick Dawkins (pjcdawkins) - - Artur Eshenbrener - - Florian Wolfsjaeger (flowolf) - - Paul Kamer (pkamer) + - Lctrs + - Natsuki Ikeguchi + - Hany el-Kerdany - MrMicky - - Rafał Wrzeszcz (rafalwrzeszcz) - - Reyo Stallenberg (reyostallenberg) - - Thibault Buathier (gwemox) - - Nguyen Xuan Quynh - - Dennis Langen (nijusan) - - Andreas Lutro (anlutro) - - Christin Gruber (christingruber) - - Francisco Alvarez (sormes) - - Martin Parsiegla (spea) - - Manuel Alejandro Paz Cetina - - Rootie - - Denis Charrier (brucewouaigne) - - Roy Klutman (royklutman) - - Nicole Cordes (ichhabrecht) - - Matthieu Calie (matth--) - - Ulumuddin Cahyadi Yunus (joenoez) - - alexpozzi - - NickSdot - - Youssef Benhssaien (moghreb) - - Mario Ramundo (rammar) - - David Romaní - - Sofiane HADDAG (sofhad) - - Casper Valdemar Poulsen - - Andrew Berry - - Tony Malzhacker - - Loïc Beurlet - - mfettig - - John Bohn (jbohn) - - hugovms + - Oliver Hader + - Gintautas Miselis (naktibalda) + - Ivo Bathke (ivoba) + - Chris Heng (gigablah) + - johan Vlaar - Ben - - Andrew Tchircoff (andrewtch) - - Natsuki Ikeguchi - - Jesper Noordsij - - Adán Lobato (adanlobato) + - Venu + - acoulton + - Mihai Stancu + - fedor.f - Neil Ferreira + - Gálik Pál + - Nicolas Dousson + - Thomas Durand + - Dennis Hotson + - Jonatan Männchen + - Philipp Scheit (pscheit) - Matthieu Mota (matthieumota) - - Maksim Muruev - - datibbaw - - Daniel Alejandro Castro Arellano (lexcast) - - Ondrej Exner - - Masterklavi - - vladimir.panivko - - Sébastien Santoro (dereckson) - - Ian Irlen - - Marko Petrovic - - Matthieu Bontemps - - Stephan Vierkant (svierkant) + - Artur Eshenbrener + - Hidde Boomsma (hboomsma) + - Marc Abramowitz + - Andrii Popov (andrii-popov) + - Carlos Buenosvinos (carlosbuenosvinos) + - Gladhon + - Sergey Kolodyazhnyy (skolodyazhnyy) + - scyzoryck + - Jesper Noordsij + - Cosmin Sandu + - Thomas P + - Jason Tan (jt2k) + - David Marín Carreño (davefx) + - Alexander Li (aweelex) + - Morten Wulff (wulff) + - origaminal + - Xavier Lacot (xavier) + - Michael Roterman (wtfzdotnet) + - Mickaël Buliard (mbuliard) + - rtek + - Kieran + - Martin Parsiegla (spea) + - Manuel Alejandro Paz Cetina + - Alexander Miehe + - Ahmed Ashraf (ahmedash95) + - flip111 + - Baldur Rensch (brensch) + - ToshY + - Sascha Grossenbacher (berdir) + - Joschi Kuphal + - Trevor North + - Pierre-Emmanuel Tanguy (petanguy) + - Dragos Protung (dragosprotung) + - Jonas Elfering + - Gustavo Falco (gfalco) + - Alex Bogomazov (alebo) + - Jan Walther (janwalther) + - Simon DELICATA + - Thibaut THOUEMENT (thibaut_thouement) - Thiago Cordeiro (thiagocordeiro) - - Ana Raro + - Evan C - Koen Kuipers (koku) - - Ana Raro - - Dragos Protung (dragosprotung) - - Carlos Quintana + - Florian Hermann (fhermann) + - Kevin (oxfouzer) + - Alex Bacart + - Piotr Stankowski + - Arun Philip + - kick-the-bucket + - Morgan Auchede + - Chris Boden (cboden) + - Adrien Lucas (adrienlucas) + - Nico Haase + - Aleksandr Volochnev (exelenz) + - David Romaní + - Jonathan (jlslew) + - Grinbergs Reinis (shima5) + - Dennis Langen (nijusan) + - Patrick Allaert + - Ulumuddin Cahyadi Yunus (joenoez) + - Robin van der Vleuten (robinvdvleuten) + - Dmitrii Tarasov (dtarasov) + - Daniël Brekelmans (dbrekelmans) + - Luca Saba (lucasaba) + - Douglas Reith (douglas_reith) + - Daniel González (daniel.gonzalez) + - Krystian Marcisz (simivar) + - Adrien Jourdier (eclairia) + - Loïc Ovigne (oviglo) + - Francisco Alvarez (sormes) + - Bálint Szekeres + - Yi-Jyun Pan + - Vladimir Varlamov (iamvar) + - Olivier Maisonneuve + - Adrien Roches (neirda24) + - Bill Hance (billhance) + - Moshe Weitzman (weitzman) + - Thorry84 + - Toon Verwerft (veewee) + - Tiago Brito (blackmx) + - Mark Schmale (masch) + - Jacques MOATI (jmoati) + - David Fuhr + - Michiel Boeckaert (milio) + - DemigodCode + - Mario Ramundo (rammar) + - Alaattin Kahramanlar (alaattin) + - ornicar + - Laurent Bassin (lbassin) + - Miquel Rodríguez Telep (mrtorrent) - Mouad ZIANI (mouadziani) - - Jibé Barth (jibbarth) - - Dmitry Parnas (parnas) - - Brad Jones - - Ian Jenkins (jenkoian) - - Robert Gruendler (pulse00) - - Simon Terrien (sterrien) - - Sebastian Paczkowski (sebpacz) - - Nicolas de Marqué (nicola) - - Mikhail Yurasov (mym) - - Fabian Vogler (fabian) - - Brunet Laurent (lbrunet) - - Elan Ruusamäe (glen) - - Mior Muhammad Zaki (crynobone) - - Julie Hourcade (juliehde) - - Henry Snoek (snoek09) - - Wouter van der Loop (toppy-hennie) - - Adam - - johan Vlaar + - NanoSector + - Jon Dufresne + - Khoo Yong Jun + - Don Pinkster - Ivan + - Mohamed Gamal + - Emil Einarsson + - Jibé Barth (jibbarth) + - Joost van Driel (j92) + - Evan Villemez + - Alex (garrett) + - Konstantin Grachev (grachevko) + - izzyp - Jeroen van den Enden (endroid) + - Xesxen + - Tomasz Kusy + - Jelle Raaijmakers (gmta) + - Renan Gonçalves (renan_saddam) + - fago + - alexandre.lassauge + - Thomas Ploch + - Marko H. Tamminen (gzumba) + - Thomas Cochard (tcochard) + - Javier López (loalf) + - Pascal Helfenstein + - Richard van den Brand (ricbra) + - Ke WANG (yktd26) + - Roy Klutman (royklutman) + - Abhoryo + - Maxime Douailin + - Maks 3w (maks3w) - Mantas Var (mvar) - - Pierre Vanliefland (pvanliefland) - - Nico Haase - - frost-nzcr4 - - wuchen90 - - Philipp Scheit (pscheit) - - SpacePossum - - Arjan Keeman - - Arnaud Frézet - - Terje Bråten - - Sylvain BEISSIER (sylvain-beissier) - - Bozhidar Hristov - - Thibaut THOUEMENT (thibaut_thouement) - - Cosmin Sandu - - wicliff wolda (wickedone) - - Florent Destremau (florentdestremau) - - Stéphane Delprat - - Andreas Braun - - James Hemery - - Michiel Boeckaert (milio) - - Bastien DURAND (deamon) - - Daniel Cestari - - Mátyás Somfai (smatyas) - - ouardisoft - - Sebastian Krebs - - Mickaël Andrieu (mickaelandrieu) - - Daisuke Ohata - - Simon Leblanc (leblanc_simon) - - Paul Oms - - Egor Taranov - - Piotr Stankowski - - Bastien THOMAS - - Gábor Tóth - - Yuriy Vilks (igrizzli) - - Ramunas Pabreza (doobas) - - Achilles Kaloeridis (achilles) - - den - - Pierre-Emmanuel Tanguy (petanguy) - - Julien Maulny - - Gennadi Janzen - - Shahriar56 - - julien57 - - Fred Cox - - Simon DELICATA - - vitaliytv - - Franck RANAIVO-HARISOA (franckranaivo) - - Yi-Jyun Pan - - Philippe Segatori - - Jayson Xu (superjavason) - - Oleksandr Barabolia (oleksandrbarabolia) - - Sébastien Despont (bouillou) - - Maxime Douailin - - benjaminmal - - Dominik Ulrich - - Kay Wei - - Reen Lokum - - Michał Jusięga - - Marc Laporte - - Jean Pasdeloup - - Roy de Vos Burchart - - Jon Gotlin (jongotlin) - - Andrey Sevastianov - - James Johnston - - Joost van Driel (j92) - - Khoo Yong Jun - - Adrian Nguyen (vuphuong87) - - Julien Fredon - - Paulo Ribeiro (paulo) - - Sebastian Blum - - Matthew Davis (mdavis1982) - - Abhoryo - - Xavier Leune (xleune) - - Marcos Gómez Vilches (markitosgv) - - Baptiste CONTRERAS - - Julien Turby - - Lorenzo Millucci (lmillucci) - - Ricky Su (ricky) - - Cristoforo Cervino (cristoforocervino) - - scyzoryck - - Arno Geurts - - Florian Hermann (fhermann) - - Kyle Evans (kevans91) - - Max Rath (drak3) - - marie - - Stéphane Escandell (sescandell) - - Pavol Tuka - - Fractal Zombie - - Philipp Keck - - Noémi Salaün (noemi-salaun) - - Gennady Telegin - - Benedikt Lenzen (demigodcode) - - Alexandre Dupuy (satchette) - - Michel Hunziker - - Malte Blättermann - - Ilya Levin (ilyachase) - - Simeon Kolev (simeon_kolev9) - - Jonas Elfering - - Mihai Stancu - - louismariegaborit - - Nahuel Cuesta (ncuesta) - - Ruben Gonzalez (rubenruateltek) - - Chris Boden (cboden) - - Kuba Werłos (kuba) - - Johnson Page (jwpage) - - Jacques MOATI (jmoati) - - EStyles (insidestyles) - - Christophe Villeger (seragan) - - Harry Walter (haswalt) - - Krystian Marcisz (simivar) - - David Fuhr - - Hany el-Kerdany - - Dhananjay Goratela - - Åsmund Garfors - - Maxime COLIN (maximecolin) - - ywisax - - Javier López (loalf) - - Xavier Briand (xavierbriand) - - Douglas Reith (douglas_reith) - - Reinier Kip - - noniagriconomie - - Bill Hance (billhance) - - Jérôme Tamarelle (jtamarelle-prismamedia) - - Carlos Pereira De Amorim (epitre) - - Emil Masiakowski - - Geoffrey Brier (geoffrey-brier) - - Balazs Csaba - - Nykopol (nykopol) - - Tony Tran - - Alex Bogomazov (alebo) - - Martins Sipenko - - Michael Hüneburg - - root - - Vincent Chalnot - - Roeland Jago Douma - - Patrizio Bekerle - - Tom Maguire - - Mateusz Lerczak - - Tim Porter - - Richard Quadling - - Will Rowe - - Rainrider - - David Zuelke - - Adrian - - Oliver Eglseder - - neFAST - - Peter Gribanov - - zcodes - - Pierre Rineau - - Maxim Lovchikov - - adenkejawen - - Florent SEVESTRE (aniki-taicho) - - Jan Eichhorn (exeu) - - Georg Ringer (georgringer) - - Johan Wilfer (johanwilfer) - - Martin Mayer (martin) - - Ruud Seberechts - - ivelin vasilev - - John Nickell (jrnickell) - - Toby Griffiths (tog) - - Paul Le Corre - - Grzegorz Łukaszewicz (newicz) - - Nico Müller (nicomllr) - - Omar Yepez (oyepez003) - - carlos-ea - - Ashura - - Götz Gottwald - - Alessandra Lai - - timesince - - alangvazq - - Christoph Krapp - - Ernest Hymel - - Andrea Civita - - Nicolás Alonso - - Roman Tyshyk - - LoginovIlya - - andreyserdjuk - - Nick Chiu - - Thanh Trần - - Robert Campbell - - Matt Lehner - - Olexandr Kalaidzhy - - Helmut Januschka - - Hein Zaw Htet™ - - Ruben Kruiswijk - - Cosmin-Romeo TANASE - - Ferran Vidal - - Michael J - - sal-car - - youssef saoubou - - Joseph Maarek - - Alexander Menk - - timaschew - - Jelle Kapitein - - Jochen Mandl - - Asrorbek Sultanov - - Marin Nicolae - - Gerrit Addiks - - Buster Neece - - lerminou - - Jenne van der Meer - - Albert Prat - - Alessandro Loffredo - - Ian Phillips - - Carlos Tasada - - Remi Collet + - Jawira Portugal (jawira) + - Nicolas de Marqué (nicola) + - Mara Blaga + - Rick Prent + - Alexander Onatskiy + - Bruno Ziegler (sfcoder) + - Tom Newby (tomnewbyau) + - skalpa + - danilovict2 + - Peter Bouwdewijn + - Daniil Gentili + - v.shevelev + - rvoisin + - Mario Young + - Tomáš Polívka (draczris) + - BenjaminBeck + - Konstantin Bogomolov + - Marco + - Jack Wright + - Ener-Getick + - Pablo Borowicz + - Boullé William (williamboulle) + - Ryan Rud + - Ondřej Frei - Haritz - Matthieu Prat - - zors1 - - Peter Simoncic - - Adam Bramley - - thecaliskan - - Ahmad El-Bardan - - martijn - - mantulo - - Andrew Brown - - pdragun - - Erik van Wingerden - - Noel Light-Hilary - - Gilles Gauthier - - Filipe Guerra - - Jean Ragouin - - Gerben Wijnja - - Emre YILMAZ - - Rowan Manning - - qsz - - Marcos Labad - - Per Modin - - David Windell - - Frank Jogeleit - - Gabriel Birke - - Derek Bonner - - NothingWeAre - - Storkeus - - goabonga - - Vladislav Iurciuc - - Alan Chen - - Anton Zagorskii - - ging-dev - - Maerlyn + - Helmut Hummel (helhum) + - Mehdi Mabrouk (mehdidev) + - Bart Reunes (metalarend) + - Kamil Piwowarski (cyklista) + - Damon Jones (damon__jones) + - cilefen (cilefen) + - cthulhu + - Anne-Julia Seitz + - WaiSkats + - Stanislav Gamaiunov (happyproff) + - Rémi Leclerc + - Bermon Clément (chou666) + - Egor Gorbachev + - Citia (citia) + - Volker Killesreiter (ol0lll) + - Kamil Madejski (kmadejski) + - jack.thomas (jackthomasatl) + - Yasmany Cubela Medina (bitgandtter) + - Owen Gray (otis) - Robert Gurau - - Even André Fiskvik - - Agata - - dakur - - florian-michael-mast - - tourze - - Dario Guarracino - - sam-bee - - Vlad Dumitrache - - wetternest - - Valouleloup - - Pathpat - - Jaymin G - - robmro27 - - Vallel Blanco - - Alexis MARQUIS - - Ernesto Domato - - Matheus Gontijo - - Gerrit Drost - - Linnaea Von Lavia - - Javan Eskander - - Lenar Lõhmus - - MusikAnimal - - AlberT - - hainey - - Dominik Hajduk (dominikalp) - - gondo (gondo) - - Benjamin Franzke - - Pavinthan - - David Joos (djoos) - - Sylvain METAYER - - Dennis Smink (dsmink) - - ddebree - - Gyula Szucs - - Tomas Liubinas - - Jan Hort - - Klaas Naaijkens - - Bojan - - Rafał - - Adria Lopez (adlpz) - - Adrien Peyre (adpeyre) - - Alexandre Jardin (alexandre.jardin) - - Bart Brouwer (bartbrouwer) - - baron (bastien) - - Bastien Clément (bastienclement) - - Rosio (ben-rosio) - - Simon Paarlberg (blamh) - - Anne-Sophie Bachelard - - Masao Maeda (brtriver) - - Alexander Dmitryuk (coden1) - - Valery Maslov (coderberg) - - Damien Harper (damien.harper) - - Darius Leskauskas (darles) - - david perez (davidpv) - - Denis Klementjev (dklementjev) - - Dominik Pesch (dombn) - - Tomáš Polívka (draczris) - - Duncan de Boer (farmer-duck) - - Franz Liedke (franzliedke) - - Gaylord Poillon (gaylord_p) - - Javier Núñez Berrocoso (javiernuber) - - Hadrien Cren (hcren) - - Gusakov Nikita (hell0w0rd) - - Halil Hakan Karabay (hhkrby) - - Jaap van Otterdijk (jaapio) - - Jelle Bekker (jbekker) - - Dave Heineman (dheineman) - - Giovanni Albero (johntree) - - Mikhail Prosalov (mprosalov) - - Jorge Martin (jorgemartind) - - Kubicki Kamil (kubik) - - Ronny López (ronnylt) - - Joeri Verdeyen (jverdeyen) - - Kevin Herrera (kherge) - - guangwu - - Luis Ramón López López (lrlopez) - - Vladislav Nikolayev (luxemate) - - Martin Mandl (m2mtech) - - Mehdi Mabrouk (mehdidev) - - Bart Reunes (metalarend) - - Muriel (metalmumu) + - Colin Michoudet + - sebastian + - Ron Gähler (t-ronx) + - Guillermo Gisinger (t3chn0r) + - Sören Bernstein + - michael.kubovic + - Evgeny Anisiforov + - Jordi Llonch (jordillonch) + - julien_tempo1 (julien_tempo1) + - tarlepp + - Yoann Chocteau (kezaweb) + - Jeroen de Graaf + - Chris Shennan (chrisshennan) + - Abdouni Karim (abdounikarim) + - nietonfir + - Ikhsan Agustian + - raplider - Michael Pohlers (mick_the_big) + - Franck Ranaivo-Harisoa + - Jeremiah VALERIE + - Minna N + - Aaron Somi + - Elías (eliasfernandez) + - kshida + - Vladislav Vlastovskiy (vlastv) + - Valentin Barbu (jimie) + - Roman Igoshin (masterro) + - Antal Áron (antalaron) + - John VanDeWeghe + - Jordan Hoff + - Aurelijus Rožėnas + - Beno!t POLASZEK + - hamza + - Nicolas Appriou + - vlechemin + - Janusz Jabłoński (yanoosh) + - Tayfun Aydin + - kaywalker + - joris de wit (jdewit) + - znerol + - Matthew Covey + - Nicolas Bondoux (nsbx) + - zors1 + - Tobias Genberg (lorceroth) + - Martijn Croonen + - Andy Stanberry + - Schvoy Norbert (schvoy) + - Ondřej Frei + - Luis Pabon (luispabon) + - Anthony Ferrara + - rchoquet + - Amine Yakoubi + - Benoit Mallo + - Simon Bouland (bouland) + - Floran Brutel (notFloran) (floran) + - Christian Neff (secondtruth) + - povilas + - ollie harridge (ollietb) + - Courcier Marvin (helyakin) + - Radoslaw Kowalewski + - Abdelilah Jabri + - Ioana Hazsda (ioana-hazsda) + - MrNicodemuz + - demeritcowboy + - Marcus Stöhr (dafish) + - Fabien D. (fabd) + - Tristan Kretzer + - Jacek Wilczyński (jacekwilczynski) + - Alexandru Năstase + - Sergey Fedotov + - Konstantin Scheumann + - Mario Blažek (marioblazek) + - pizzaminded + - Fraller Balázs (fracsi) + - Jorge Maiden (jorgemaiden) + - EdgarPE + - George Yiannoulopoulos - Misha Klomp (mishaklomp) - mlpo (mlpo) + - Oliver Hoff + - Olivier Scherler (oscherler) + - Marco Wansinck (mwansinck) + - mamazu + - Tomáš Korec (tomkorec) + - natechicago + - Geoff - Marcel Pociot (mpociot) - - Ulrik Nielsen (mrbase) - - Marek Šimeček (mssimi) - - Cayetano Soriano Gallego (neoshadybeat) - - Artem (nexim) + - Camille Islasse + - Josef Hlavatý + - Jan Marek (janmarek) + - fh-github@fholzhauer.de + - Marek Víger (freezy) + - Vladimir Sazhin + - lol768 + - Andoni Larzabal (andonilarz) + - Alexandre Pavy + - Boris Betzholz + - mshavliuk + - boulei_n + - Kacper Gunia (cakper) + - djordy + - Adrian Olek (adrianolek) + - Stewart Malik + - Mark Pedron (markpedron) + - mikocevar + - Ibrahim Bougaoua + - Laurens Laman + - Hugo Fonseca (fonsecas72) + - Marc Duboc (icemad) + - Lesueurs Frédéric (fredlesueurs) + - Greg Szczotka (greg606) + - Attila Szeremi + - Pablo Ogando Ferreira + - Hoffmann András + - Adam Klvač + - Mei Gwilym (meigwilym) + - Victor Garcia + - Frankie Wittevrongel + - Plamen Mishev (pmishev) - Olivier Laviale (olvlvl) + - Viacheslav Sychov + - Julien Pauli + - Christoph Kappestein + - Ivan Tse + - Menno Holtkamp - Pierre Gasté (pierre_g) - - Pablo Monterde Perez (plebs) - - Pierre-Olivier Vares (povares) - - Jimmy Leger (redpanda) - - Julius (sakalys) - - Dmitry (staratel) - - Marcin Szepczynski (szepczynski) - - Simone Di Maulo (toretto460) - - Cyrille Jouineau (tuxosaurus) - - Florian Morello - - Wim Godden (wimg) - - Yorkie Chadwick (yorkie76) - - Maxime Aknin (3m1x4m) - - Lauris Binde (laurisb) - - Zakaria AMMOURA (zakariaamm) - - Shrey Puranik - - Pavel Barton + - Quentin Favrie + - Matthias Derer + - Brian Freytag + - Lucas Matte + - Success Go + - fmarchalemisys + - Arend Hummeling + - Joseph FRANCLIN + - Oussama Elgoumri + - Andreas Forsblom (aforsblo) + - Mo Di (modi) + - Henne Van Och (hennevo) + - Muharrem Demirci (mdemirci) + - Peter Zwosta + - Nathan DIdier (icz) + - Babichev Maxim (rez1dent3) + - Markus Ramšak + - Andrew Zhilin (zhil) + - Andrew Carter (andrewcarteruk) + - fabi + - Rares Vlaseanu (raresvla) + - Ser5 + - vltrof + - Matteo Giachino (matteosister) + - Gregório Bonfante Borba (bonfante) + - ChrisC - michal - - GuillaumeVerdon + - Michael Telgmann + - Jody Mickey (jwmickey) + - Ismo Vuorinen + - Thomas Hanke + - Sami Mussbach + - Jan Vernarsky + - Aarón Nieves Fernández + - Grégory Pelletier (ip512) + - Ahto Türkson + - Erfan Bahramali - valmonzo - Dmitry Danilson - - Marien Fressinaud - - ureimers - - akimsko - - Youpie - - Jason Stephens - - Korvin Szanto - - Taylan Kasap - - Michael Orlitzky - - Nicolas A. Bérard-Nault - - Quentin Favrie - - Matthias Derer - - Francois Martin - - Saem Ghani - - Kévin - - Stefan Oderbolz - - Tamás Szigeti - - Gabriel Moreira - - Alexey Popkov - - ChS - - Jannik Zschiesche - - Alexis MARQUIS - - Joseph Deray - - Damian Sromek - - Evgeniy Tetenchuk - - Sjoerd Adema - - Kai Eichinger - - Evgeniy Koval - - Lars Moelleken - - dasmfm - - Karel Syrový - - Claas Augner - - Mathias Geat - - neodevcode - - Angel Fernando Quiroz Campos (angelfqc) - - Arnaud Buathier (arnapou) - - Curtis (ccorliss) - - chesteroni (chesteroni) - - Mauricio Lopez (diaspar) - - HADJEDJ Vincent (hadjedjvincent) - - Ismail Asci (ismailasci) - - Jeffrey Moelands (jeffreymoelands) - - Ondřej Mirtes (mirtes) - - vladyslavstartsev - - ToshY - - Paulius Jarmalavičius (pjarmalavicius) - - Ramon Ornelas (ramonornela) - - helmi - - Sylvain Lorinet - - Ruslan Zavacky (ruslanzavacky) - - Jakub Caban (lustmored) - - Stefano Cappellini (stefano_cappellini) - - Till Klampaeckel (till) - - Tobias Weinert (tweini) - - Wotre + - Juan Mrad + - Julien Moulin (lizjulien) + - Mauro Foti (skler) + - Ninos + - Markus Staab + - Daniel Strøm + - Michaël VEROUX + - Julia + - Kamil Szalewski (szal1k) + - Piotr Antosik (antek88) + - Thibaut Chieux + - mwos + - Aydin Hassan + - Thomas Baumgartner (shoplifter) + - Pablo Monterde Perez (plebs) + - Danil + - Valentin + - wetternest + - ffd000 + - Zlatoslav Desyatnikov + - Valouleloup + - Pathpat + - Vedran Mihočinec (v-m-i) + - Mathieu Ledru (matyo91) + - Willem Verspyck + - Mike Gladysch + - Martynas Narbutas + - Timothée BARRAY + - jack.shpartko + - Simon Asika + - Asrorbek Sultanov + - ondrowan + - Kevin Auivinet + - Nicolas Eeckeloo (neeckeloo) + - Blackfelix + - Vincent AMSTOUTZ (vincent_amstz) + - tsufeki + - tamcy + - Bruno BOUTAREL + - Xesau + - Ahmed EBEN HASSINE (famas23) + - Peter Breuls + - Chansig + - Roman Orlov + - Simon Ackermann + - Elías Fernández + - Jakub Simon + - Samael tomas + - Thibaut Arnoud (thibautarnoud) + - Jonas Hünig + - Mehrdad + - neghmurken + - stefan.r + - Kevin Jansen + - Danilo Silva + - Máximo Cuadros (mcuadros) + - Fabrice Locher + - Paweł Stasicki + - Kirill Saksin + - Mike Milano (mmilano) - Sepehr Lajevardi - - George Bateman - - Xavier HAUSHERR - - Edwin Hageman - - Mantas Urnieža - - temperatur - - Paul Andrieux - - Sezil - - misterx - - Cas - - Vincent Godé - - Ivo Valchev - - Michael Steininger - - Nardberjean - - Dylan - - ghazy ben ahmed - - Karolis - - Myke79 - - jersoe - - Brian Debuire - - Eric Grimois - - Christian Schiffler - - Piers Warmers - - Pavol Tuka - - klyk50 - - Colin Michoudet - - jc - - BenjaminBeck - - Aurelijus Rožėnas - - Beno!t POLASZEK - - Armando - - Jordan Hoff - - znerol - - Christian Eikermann - - Sergei Shitikov + - uncaught + - Benjamin Dos Santos + - Clément Bertillon (skigun) + - Jochen Bayer (jocl) + - Richard van Velzen + - Peter Culka + - Anamarija Papić (anamarijapapic) + - Staormin + - Oleg Sedinkin (akeylimepie) + - Guillaume Royer + - Kevin Decherf + - Kuzia + - Pavel Golovin (pgolovin) + - Ignacio Alveal + - bahram + - Ruud Seberechts + - ivelin vasilev + - Brian Graham (incognito) + - wallach-game + - Asrorbek (asrorbek) + - Gerrit Addiks + - Andrea Sprega (asprega) + - taiiiraaa + - Gunnar Lium (gunnarlium) + - Jakub Vrána + - Nil Borodulia + - Felix Eymonot (hyanda) + - Joshua Behrens (joshuabehrens) + - Jean-Christophe Cuvelier [Artack] + - Wouter Diesveld + - André Laugks - Steffen Keuper - - Jens Schulze - - Tema Yud - - Olatunbosun Egberinde - - Jiri Korenek - - Alexis Lefebvre - - Johannes - - Dominic Tubach - - Andras Debreczeni - - sarah-eit - - rhel-eo - - patrick-mcdougle - - Vladimir Sazhin - - lol768 - - Michel Bardelmeijer - - Menno Holtkamp - - Tomas Kmieliauskas - - Dariusz Czech - - Ikko Ashimine - - Alexandru Bucur - - Erwin Dirks - - cmfcmf - - Markus Ramšak - - Billie Thompson - - Philipp - - jamogon - - Tom Hart - - Vyacheslav Slinko - - Benjamin Laugueux - - Jakub Chábek - - Johannes - - Jörg Rühl - - George Dietrich - - jannick-holm - - wesleyh - - Ser5 - - Michael Hudson-Doyle - - Matthew Burns - - Daniel Bannert - - Karim Miladi - - Michael Genereux - - Greg Korba - - Camille Islasse - - Tyler Stroud - - Clemens Krack - - Bruno Baguette - - Jack Wright - - MrNicodemuz - - demeritcowboy - - Paweł Tomulik - - Eric J. Duran - - omerida - - Anatol Belski - - Blackfelix - - Pavel Witassek - - Michal Forbak - - Drew Butler - - Alexey Berezuev - - pawel-lewtak - - Pierrick Charron - - Steve Müller - - Andras Ratz - - Benjamin RICHARD - - andreabreu98 - - Jérémie Broutier - - Marcus - - gechetspr - - brian978 - - Michael Schneider - - n-aleha - - Richard Čepas - - Talha Zekeriya Durmuş - - Javier - - Alexis BOYER - - bch36 - - Kaipi Yann - - wiseguy1394 - - adam-mospan - - AUDUL - - Steve Hyde - - AbdelatifAitBara - - nerdgod - - Sam Williams - - Ettore Del Negro - - Guillaume Aveline - - Adrian Philipp - - James Michael DuPont - - Simone Ruggieri - - Kasperki - - dima-gr - - Daniel Strøm - - Rodolfo Ruiz - - tsilefy - - Enrico - - Adrien Foulon - - Sylvain Just - - Ryan Rud - - vlechemin - - Brian Corrigan - - Ladislav Tánczos - - Brian Freytag - - Skorney - - Lucas Matte - - Success Go - - fmarchalemisys - - MGatner - - mieszko4 - - Steve Preston - - ibasaw - - Wojciech Skorodecki - - Neophy7e - - Evert Jan Hakvoort - - rewrit3 - - Filippos Karailanidis - - David Ronchaud - - A. Pauly - - Chris McGehee - - Shaun Simmons - - Bogdan - - Pierre-Louis LAUNAY - - Arseny Razin - - Benjamin Rosenberger - - Michael Gwynne - - Eduardo Conceição - - changmin.keum - - Jon Cave - - Sébastien HOUZE - - Abdulkadir N. A. - - Markus Klein - - Adam Klvač - - Bruno Nogueira Nascimento Wowk - - Tomanhez - - satalaondrej - - jonmldr - - Yevgen Kovalienia - - Lebnik - - Shude - - RTUnreal - - Richard Hodgson - - Sven Fabricius - - Ondřej Führer + - Arthur Woimbée + - Ricardo de Vries (ricardodevries) + - Victor Truhanovich (victor_truhanovich) + - Patryk Kozłowski + - Arman - Sema + - Imangazaliev Muhammad (imangazaliev) + - Jose Manuel Gonzalez (jgonzalez) + - alifanau + - tamirvs + - John Nickell (jrnickell) + - Claudiu Cristea - Ayke Halder - Thorsten Hallwas - Brian Freytag - - Arend Hummeling - - Joseph FRANCLIN - Marco Pfeiffer + - Jonathan Poston + - Aurélien Fontaine + - Alberto Pirovano (geezmo) + - RFreij + - Pascal Woerde (pascalwoerde) + - pkowalczyk + - Richard Čepas + - Yannick Vanhaeren (yvh) + - Mathieu TUDISCO (mathieutu) + - Andreas Frömer + - Sam Ward + - Hans N. Hjort + - Lance McNearney + - Junaid Farooq (junaidfarooq) + - takashiraki + - Rutger Hertogh + - Diego Sapriza + - excelwebzone + - Nikita Starshinov (biji) + - Rafał Treffler + - Sorin Pop (sorinpop) + - Valentin + - Yurun + - Matthew Donadio + - Sébastien Decrême (sebdec) + - Marc Torres - Alex Nostadt - Michael Squires - - Egor Gorbachev - Julian Krzefski - Derek Stephen McLean - Norman Soetbeer - - zorn - - Yuriy Potemkin - - Emilie Lorenzo - - enomotodev - - Vincent - - Benjamin Long - - Fabio Panaccione - - Kévin Gonella - - Ben Miller - - Peter Gribanov - - Matteo Galli - - Bart Ruysseveldt - - Ash014 - - kwiateusz - - Nowfel2501 - - Ilya Bulakh - - David Soria Parra - - Arrilot - - Dawid Nowak - - Simon Frost - - Gert de Pagter - - Sergiy Sokolenko - - Harry Wiseman - - Cantepie - - llupa - - djama - - detinkin - - Loenix - - Ahmed Abdulrahman - - Penny Leach - - Kevin Mian Kraiker - - Yurii K - - Richard Trebichavský - - g123456789l - - Mark Ogilvie - - Jonathan Vollebregt - - oscartv - - Michal Čihař - - parhs - - Emilien Escalle - - jwaguet - - Diego Campoy - - Oncle Tom - - Sam Anthony - - Christian Stocker - - Oussama Elgoumri - - David Lima - - Steve Marvell - - Lesnykh Ilia - - Shyim - - darnel - - Nicolas - - Sergio Santoro - - tirnanog06 - - Andrejs Leonovs - - Alfonso Fernández García - - phc - - Дмитрий Пацура - - Signor Pedro - - Lin Lu - - RFreij - - Matthias Larisch - - Maxime P - - Sean Templeton - - Willem Mouwen - - db306 - - Bohdan Pliachenko - - Dr. Gianluigi "Zane" Zanettini - - Michaël VEROUX - - Julia - - arduanov - - Fabien + - Jared Farrish + - Moritz Borgmann (mborgmann) + - Volker (skydiablo) + - Eduardo Conceição + - Pierre-Louis LAUNAY + - Arseny Razin + - Benjamin Rosenberger + - Michael Gwynne + - AnotherSymfonyUser (arderyp) + - Vitalii + - Christian Eikermann + - Rénald Casagraude (rcasagraude) + - Koray Zorluoglu + - Artem (digi) + - Ken Marfilla (marfillaster) + - Jelizaveta Lemeševa (broken_core) + - Jacek Kobus (jackks) + - AlberT - David Courtey (david-crty) - Martin Komischke + - Peter Potrowl + - Ilya Biryukov (ibiryukov) + - Alexander McCullagh (mccullagh) + - MGDSoft - Yendric - - Loïc Vernet (coil) - - ADmad - - Gerard Berengue Llobera (bere) - - Hugo Posnic - - Nicolas Roudaire - - Marc Jauvin - - Matthias Meyer - - Temuri Takalandze (abgeo) - - Bernard van der Esch (adeptofvoltron) - - Andreas Forsblom (aforsblo) - - Aleksejs Kovalovs (aleksejs1) - - Alex Olmos (alexolmos) - - Robin Kanters (anddarerobin) - - Antoine (antoinela_adveris) - - Juan Ases García (ases) - - Siragusa (asiragusa) - - Daniel Basten (axhm3a) - - Albert Bakker (babbert) - - Benedict Massolle (bemas) - - Ronny (big-r) - - Bernd Matzner (bmatzner) - - Vladimir Vasilev (bobahvas) - - Anton (bonio) - - Bram Tweedegolf (bram_tweedegolf) - - Brandon Kelly (brandonkelly) - - Choong Wei Tjeng (choonge) - - Bermon Clément (chou666) - - Citia (citia) - - Kousuke Ebihara (co3k) - - Christoph Vincent Schaefer (cvschaefer) - - Kamil Piwowarski (cyklista) - - Damon Jones (damon__jones) - - David Gorges (davidgorges) - - Alexandre Fiocre (demos77) - - Gustavo Adrian - - Chris Shennan (chrisshennan) - - Abdouni Karim (abdounikarim) - - Łukasz Giza (destroyer) - - Dušan Kasan (dudo1904) - - Joao Paulo V Martins (jpjoao) - - Sebastian Landwehr (dword123) - - Adel ELHAIBA (eadel) - - Julien Manganne (juuuuuu) - - Damián Nohales (eagleoneraptor) - - Gerry Vandermaesen (gerryvdm) - - Elliot Anderson (elliot) - - Yohan Giarelli (frequence-web) - - Erwan Nader (ernadoo) - - Ian Littman (iansltx) - - Fabien D. (fabd) - - Carsten Eilers (fnc) - - Sorin Gitlan (forapathy) - - Fraller Balázs (fracsi) - - Jorge Maiden (jorgemaiden) - - Lesueurs Frédéric (fredlesueurs) - - Arash Tabrizian (ghost098) - - Greg Szczotka (greg606) - - Nathan DIdier (icz) - - Vladislav Krupenkin (ideea) - - Peter Orosz (ill_logical) - - Ilia Lazarev (ilzrv) - - Imangazaliev Muhammad (imangazaliev) - - wesign (inscrutable01) - - j0k (j0k) - - joris de wit (jdewit) - - JG (jege) - - Jose Manuel Gonzalez (jgonzalez) - - Pierre-Chanel Gauthier (kmecnin) - - Joachim Krempel (jkrempel) - - Joshua Behrens (joshuabehrens) + - Curtis (ccorliss) + - chesteroni (chesteroni) + - Alan Scott + - Konrad Mohrfeldt + - Quentin Moreau (sheitak) + - Andrey Ryaguzov + - Ladislav Tánczos + - Louis-Proffit + - Michał Dąbrowski (defrag) + - “teerasak” + - Yannick Warnier (ywarnier) + - wivaku + - Peter van Dommelen + - Tim van Densen + - Dmitrii Lozhkin + - Charles Sanquer (csanquer) + - Sander Marechal + - Andrzej + - Cédric Lahouste (rapotor) + - Kevin Nadin (kevinjhappy) + - Raphael Davaillaud + - J Bruni + - Frederik Schwan + - Abdiel Carrazana (abdielcs) + - Gennadi Janzen + - SenTisso + - Manatsawin Hanmongkolchai + - Gunther Konig + - Pavel Witassek + - alanzarli + - vlakoff + - Gavin Staniforth + - alex + - MGatner + - Dalibor Karlović + - Paul Matthews + - Luis Muñoz + - kurozumi (kurozumi) + - Malte Schlüter + - Antoine Beyet + - Michal Gebauer + - Jakub Kisielewski + - steveYeah + - Lucas Bustamante + - Žan V. Dragan + - tomasz-kusy + - Nicolas Séverin + - Joel Marcey + - Daniel Tschinder + - zolikonta + - Guillem Fondin (guillemfondin) + - Artem Kolesnikov (tyomo4ka) + - Gustavo Adrian + - André Laugks + - error56 + - darnel + - Dominic Tubach + - Andras Debreczeni + - sarah-eit + - jean pasqualini (darkilliant) + - Bart Baaten + - Gerhard Seidel (gseidel) + - René Landgrebe + - Daniel Bartoníček + - Vacheslav Silyutin + - Linas Ramanauskas + - joris + - Dan Kadera + - Roeland Jago Douma + - Bartłomiej Zając + - Jitendra Adhikari (adhocore) + - Giuseppe Arcuti + - Giorgio Premi + - Zacharias Luiten + - Dan Ionut Dumitriu (danionut90) + - Zuruuh + - Emre Akinci (emre) + - Berat Doğan + - Julius Kiekbusch + - Ahmed HANNACHI (tiecoders) + - WoutervanderLoop.nl + - Sebastian Ionescu + - Patrizio Bekerle + - Tom Maguire + - David Szkiba + - Gilles Gauthier + - Malcolm Fell (emarref) + - Shaun Simmons + - Thomas Counsell + - Toro Hill + - aetxebeste + - Tomas Kmieliauskas + - Andrew Coulton + - Roberto Guido + - Mathieu Dewet (mdewet) + - Patrick Berenschot + - Jakub Sacha + - Arend Hummeling + - Juliano Petronetto + - Max Voloshin (maxvoloshin) + - Raul Rodriguez (raul782) + - Camille Baronnet + - David Soms + - Zakaria AMMOURA (zakariaamm) + - casdal + - Wouter Ras + - Simon Neidhold + - Vincent Chalamon + - Nei Rauni Santos (nrauni) + - Radosław Benkel + - Laurent Clouet + - Ganesh Chandrasekaran (gxc4795) + - Sezil + - boite + - jersoe + - Loïc Vernet (coil) + - Péter Buri (burci) + - Frederic Godfrin + - Toby Griffiths (tog) + - Paul Le Corre + - Nico Müller (nicomllr) + - Yann Rabiller (einenlum) + - Marek Binkowski + - baron (bastien) + - Kevin Dew + - Pierre Sv (rrr63) + - Eno Mullaraj (emullaraj) - Justin Rainbow (jrainbow) - - JuntaTom (juntatom) + - insekticid + - Sergey Novikov (s12v) + - Adam Bramley + - thecaliskan + - goohib + - Geoffrey Monte (numerogeek) + - k-sahara + - Matthieu + - jannick-holm + - Matthew Burns + - Daniel Bannert - Ismail Faizi (kanafghan) - - Karolis Daužickas (kdauzickas) - - Kérian MONTES-MORIN (kerianmm) - - Krzysztof Menżyk (krymen) - - Nicholas Byfleet (nickbyfleet) - - Ala Eddine Khefifi (nayzo) - - Kenjy Thiébault (kthiebault) - - Matt Ketmo (mattketmo) - - samuel laulhau (lalop) - - Matt Drollette (mdrollette) - - Laurent Bachelier (laurentb) - - Adam Monsen (meonkeys) - - Luís Cobucci (lcobucci) - - Aurimas Rimkus (patrikas) - - Petr Jaroš (petajaros) - - Seyedramin Banihashemi (ramin) - - Mehdi Achour (machour) - - Jérémy (libertjeremy) - - Mamikon Arakelyan (mamikon) - - Philipp Hoffmann (philipphoffmann) - - Daniel Perez Pinazo (pitiflautico) - - scourgen hung (scourgen) - - Mark Schmale (masch) - - Moritz Borgmann (mborgmann) - - Ralf Kühnel (ralfkuehnel) - - Marco Wansinck (mwansinck) - - Mike Milano (mmilano) + - Simon / Yami + - Maciej Paprocki (maciekpaprocki) + - Ross Tuck + - Arkadiusz Rzadkowolski (flies) + - Marcos Quesada (marcos_quesada) + - Shrey Puranik + - Axel Venet + - Kévin Gonella + - Ben Miller + - markusu49 + - Marin Bînzari (spartakusmd) + - Stefanos Psarras (stefanos) + - Roger Webb + - kwiateusz + - Ahmad El-Bardan + - mantulo + - Pavel Barton + - Christian Weiske + - Sjoerd Adema + - Kai Eichinger + - Philip Frank + - Peter Orosz (ill_logical) + - voodooism + - Troy McCabe + - Goran (gog) + - upchuk + - Gyula Szucs + - Tomas Liubinas + - Lars Moelleken + - Dmitrii Baranov + - Nowfel2501 + - James Cowgill + - Ilya Bulakh + - Muhammad Aakash + - Mark Spink + - Alberto Aldegheri + - Oncle Tom + - Pieter Jordaan + - Christian Rishøj + - Daniel Iwaniec + - Thomas Dutrion (theocrite) + - Alexandre Jardin (alexandre.jardin) + - Christian + - Viktor Novikov (nowiko) + - Marcel Berteler + - Christoph Krapp + - Christopher Georg (sky-chris) + - Robert Meijers + - Olexandr Kalaidzhy + - Irmantas Šiupšinskas (irmantas) + - Alan Chen + - Cyril Vermandé (cyve) + - Adoni Pavlakis (adoni) + - Nicolas Le Goff (nlegoff) + - Tero Alén (tero) + - Anton Zagorskii + - Will Donohoe + - Rik van der Heijden + - Erwin Dirks + - Bastien Clément (bastienclement) + - Gerrit Drost + - Billie Thompson + - Kaipi Yann + - Tomanhez + - Konrad + - Bouke Haarsma + - cay89 + - Dcp (decap94) + - Julien Bianchi (jubianchi) + - Cas + - William Pinaud (docfx) + - Jason Schilling (chapterjason) + - Camille Dejoye (cdejoye) + - Verlhac Gaëtan (viviengaetan) + - Flavian Sierk + - klyk50 + - Walther Lalk + - Vincent Godé + - Michael + - Valentin + - Daniel Londero (dlondero) + - aim8604 + - ZiYao54 + - HellFirePvP + - Conrad Kleinespel (conradk) + - Silas Joisten (silasjoisten) - Guillaume Lajarige (molkobain) - - Diego Aguiar (mollokhan) - - Steffen Persch (n3o77) - - emilienbouard (neime) - - Nicolas Bondoux (nsbx) - - Cedric Kastner (nurtext) - - ollie harridge (ollietb) - - Pawel Szczepanek (pauluz) - - Sebastian Busch (sebu) - - Philippe Degeeter (pdegeeter) - - PLAZANET Pierre (pedrotroller) - - Christian López Espínola (penyaskito) - - Pavel Golovin (pgolovin) - - Alex Carol (picard89) - - Igor Tarasov (polosatus) - - Maksym Pustynnikov (pustynnikov) - - Ramazan APAYDIN (rapaydin) - - Babichev Maxim (rez1dent3) - - Sergey Stavichenko (sergey_stavichenko) - - Andrea Giuliano (shark) - - André Filipe Gonçalves Neves (seven) - - Schuyler Jager (sjager) - - craigmarvelley - - Ángel Guzmán Maeso (shakaran) - - Bruno Ziegler (sfcoder) - - Tom Newby (tomnewbyau) - - Verlhac Gaëtan (viviengaetan) - - Şəhriyar İmanov (shehriyari) - - Roman Tymoshyk (tymoshyk) - - Volker (skydiablo) - - Julien Sanchez (sumbobyboys) - - Ron Gähler (t-ronx) - - Guillermo Gisinger (t3chn0r) - - Tomáš Korec (tomkorec) - - Andrew Clark (tqt_andrew_clark) - - Aaron Piotrowski (trowski) - - David Lumaye (tux1124) - - Moritz Kraft (userfriendly) - - Víctor Mateo (victormateo) - - Vincent MOULENE (vints24) - - David Grüner (vworldat) - - Eugene Babushkin (warl) - - Wouter Sioen (wouter_sioen) - - Xavier Amado (xamado) - - Jesper Søndergaard Pedersen (zerrvox) - - Florent Cailhol - - Konrad - - Kevin Weber + - Andrei Igna + - Thomas Ploch + - Kristen Gilden + - Simone Di Maulo (toretto460) + - luffy1727 + - Andrew Brown + - divinity76 + - Pavol Tuka + - Armando + - pdragun + - Tito Costa + - Vladislav Rastrusny (fractalizer) + - Vlad Gapanovich (gapik) + - Ilia Sergunin (maranqz) + - Daniel Richter (richtermeister) + - Kim Laï Trinh + - Tobias Weinert (tweini) + - Stanislau Kviatkouski (7-zete-7) - Kovacs Nicolas - - eminjk - Stano Turza + - cmfcmf + - Philipp + - Jonathan Gough + - Tom Hart + - Vyacheslav Slinko - Antoine Leblanc - - Andre Johnson - - MaPePeR - - Andreas Streichardt - - Alexandre Segura - - Marco Pfeiffer - - Vivien - - Pascal Hofmann - - david-binda - - smokeybear87 - - damaya - - szymek - - Marc Bennewitz - - Adam Elsodaney (archfizz) - - Carl Julian Sauter - - Dionysis Arvanitis - - Alexandru Năstase - - Sergey Fedotov - - Gabriel Solomon (gabrielsolomon) - - Konstantin Scheumann - - Josef Hlavatý - - Michael - - fh-github@fholzhauer.de - - rogamoore - - AbdElKader Bouadjadja - - ddegentesh - - DSeemiller - - Jan Emrich - - Anne-Julia Seitz - - mindaugasvcs - - Mark Topper - - Xavier REN - - Kevin Meijer - - max - - Ahmad Mayahi (ahmadmayahi) - - Mohamed Karnichi (amiral) - - Andrew Carter (andrewcarteruk) - - Gregório Bonfante Borba (bonfante) - - Bogdan Rancichi (devck) - - Daniel Kolvik (dkvk) - - Marc Lemay (flug) - - Courcier Marvin (helyakin) - - Henne Van Och (hennevo) - - Muharrem Demirci (mdemirci) - - Evgeny Z (meze) - - Aleksandar Dimitrov (netbull) - - Pierre-Henry Soria 🌴 (pierrehenry) - - Pierre Geyer (ptheg) - - Thomas BERTRAND (sevrahk) - - Vladislav (simpson) - - Marin Bînzari (spartakusmd) - - Stefanos Psarras (stefanos) - - Matej Žilák (teo_sk) - - Vladislav Vlastovskiy (vlastv) - - Yannick Vanhaeren (yvh) - - Ignacio Alveal - - Kevin Verschaeve (keversc) - - RENAUDIN Xavier (xorrox) - - Pontus Mårdnäs - - Ryan Linnit - - Sebastian Göttschkes (sgoettschkes) - - es - - David Szkiba - - Vladimir Pakhomchik - - drublic - - Simon / Yami - - Maciej Paprocki (maciekpaprocki) - - Abdelhakim ABOULHAJ - - PatrickRedStar - - Gary Houbre (thegarious) - - Zan Baldwin (zanderbaldwin) - - Thomas Cochard (tcochard) - - Mark Pedron (markpedron) - - Guillaume Loulier (guikingone) - - Ricardo de Vries (ricardodevries) - - Tristan Bessoussa (sf_tristanb) - - Alessandro Tagliapietra (alex88) - - Aaron Scherer (aequasi) - - Chris Maiden (matason) - - Michal Trojanowski - - Quentin Moreau (sheitak) - - Stefan Kruppa - - Julien Boudry - - insekticid - - Romain Pierre - - alexpods - - dantleech - - Jontsa - - JK Groupe - - cgonzalez - - Raphael Davaillaud - - Radosław Kowalewski - - Dmitry Hordinky - - William Pinaud (docfx) - - Paul Ferrett - - MightyBranch - - victor-prdh - - Jeremy Benoist - - Miloš Milutinović - - pizzaminded - - johnstevenson + - Yann (yann_eugone) + - InbarAbraham + - Jason Desrosiers + - Stefan Kleff (stefanxl) + - Sander Goossens (sandergo90) + - Thomas Bibb + - Luis Ramirez (luisdeimos) + - Gerard + - Knallcharge + - Botond Dani (picur) + - Tom Corrigan (tomcorrigan) + - 🦅KoNekoD + - Lukas Naumann + - Vladimir Chernyshev (volch) + - Safonov Nikita (ns3777k) + - Leonid Terentyev + - Rene de Lima Barbosa (renedelima) + - Andrea Giuliano (shark) + - Brian Debuire + - Shane Preece (shane) + - Stephan Wentz (temp) + - amcastror + - Tristan Pouliquen + - Dan Patrick (mdpatrick) + - Ben Gamra Housseine (hbgamra) + - Darryl Hein (xmmedia) + - Trevor N. Suarez (rican7) + - Pierre-Olivier Vares (povares) + - Simon Paarlberg (blamh) + - Christian Wahler (christian) + - Jelte Steijaert (jelte) + - Klaus Purer + - Jean-Guilhem Rouel (jean-gui) + - Albin Kerouaton + - David de Boer (ddeboer) + - Dušan Kasan (dudo1904) + - j4nr6n (j4nr6n) + - remieuronews - Roromix - - Nathaniel Catchpole - - gauss - - Per Sandström (per) - - azine - - Goran Juric - - heccjj - - Igor Plantaš + - ivan + - Tom Panier (neemzy) + - Diego Aguiar (mollokhan) + - Steffen Persch (n3o77) - Arkalo2 - - Jiri Falis - - taiiiraaa - - Ali Tavafi - - Dmitriy Tkachenko (neka) - - Peter Zwosta - - Jeroen De Dauw (jeroendedauw) - - Wing - - Kai Dederichs - - Andrii Dembitskyi - - Enrico Schultz - - tpetry - - Nikita Sklyarov - - Dmitriy Derepko - - ondrowan - - Ninos + - Krzysztof Pyrkosz + - ncou + - Ian Carroll + - Dennis Fehr + - Max Summe + - Ettore Del Negro + - Keri Henare (kerihenare) + - Andre Eckardt (korve) - Dmitry Simushev - - Juraj Surman - - Wang Jingyu - - JustDylan23 - - DaikiOnodera - - Aleksey Prilipko - - Victor - - Andreas Allacher - - Dan Kadera - - Christian Morgan - - Alexis - - withbest - - Abdelilah Jabri - - Ben Johnson - - Mickael Perraud - - Frank Schulze (xit) - - soyuka - - Yann LUCAS (drixs6o9) - - Farhad Hedayatifard - - Vincent Chalamon - - Nicolas Appriou - - Sorin Pop (sorinpop) - - Stewart Malik - - Alan ZARLI - - Renan Taranto (renan-taranto) - - Valérian Galliat - - Stefan Graupner (efrane) - - Charly Goblet (_mocodo) - - Anton Dyshkant - - Adrien Chinour - - Jiří Bok - - Thomas Jarrand - - Baptiste Leduc (bleduc) - - Piotr Zajac - - Patrick Kaufmann - - Ismail Özgün Turan (dadeather) - - Rafael Villa Verde - - Zoran Makrevski (zmakrevski) - - Kirill Nesmeyanov (serafim) - - Gemorroj (gemorroj) - - Reece Fowell (reecefowell) - - Htun Htun Htet (ryanhhh91) - - Guillaume Gammelin - - Elías Fernández - - d-ph - - Samael tomas - - Mahmoud Mostafa (mahmoud) - - Damien Fernandes - - Mateusz Żyła (plotkabytes) - - Jean-Christophe Cuvelier [Artack] - - Rene de Lima Barbosa (renedelima) + - Bernat Llibre Martín (bernatllibre) + - downace + - Robin Duval (robin-duval) + - pf + - elattariyassine + - Filipe Guerra + - Jean Ragouin - Rikijs Murgs - - Mikkel Paulson - - WoutervanderLoop.nl - - Yewhen Khoptynskyi (khoptynskyi) - - Mihail Krasilnikov (krasilnikovm) - - Alex Vo (votanlean) - - Jonas Claes - - iamvar - - Amaury Leroux de Lens (amo__) - - Piergiuseppe Longo - - Nicolas Lemoine - - Christian Jul Jensen - - Valentin Barbu (jimie) - - Lukas Kaltenbach - - Daniel Iwaniec - - Alexandre GESLIN - - The Whole Life to Learn - - Pierre Tondereau - - Joel Lusavuvu (enigma97) - - kurozumi (kurozumi) - - Liverbool (liverbool) - - Aurélien MARTIN - - Malte Schlüter - - Jules Matsounga (hyoa) - - Nicolas Attard (nicolasattard) - - Jérôme Nadaud (jnadaud) - - Frank Naegler - - Sam Malone - - Ha Phan (haphan) - - Chris Jones (leek) - - neghmurken - - stefan.r - - Florian Cellier - - xaav - - Alexandre Tranchant (alexandre_t) - - Ahmed Abdou - - shreyadenny - - Pieter - - Kevin Auivinet - - ergiegonzaga - - Leonid Terentyev - - Luciano Mammino (loige) - - Radosław Benkel - - Laurent Clouet - - Dennis Tobar - - Ganesh Chandrasekaran (gxc4795) - - Michael Tibben - - Icode4Food (icode4food) - - Hallison Boaventura (hallisonboaventura) - - Billie Thompson - - Mas Iting - - Thomas Ferney (thomasf) - - Grégoire Hébert (gregoirehebert) - - Louis-Proffit - - Albion Bame (abame) - - Ferenczi Krisztian (fchris82) - - Guillaume Smolders (guillaumesmo) - - Iliya Miroslavov Iliev (i.miroslavov) - - Sander Marechal - - Ivan Nemets - - Franz Wilding (killerpoke) - - Artyum Petrov - - Oleg Golovakhin (doc_tr) - - Bert ter Heide (bertterheide) - - Kevin Nadin (kevinjhappy) - - jean pasqualini (darkilliant) - - Safonov Nikita (ns3777k) - - Mei Gwilym (meigwilym) - - Jitendra Adhikari (adhocore) - - Kevin Jansen - - Nicolas Martin (cocorambo) - - Tom Panier (neemzy) - - luffy1727 - - LHommet Nicolas (nicolaslh) - - fabios - - eRIZ - - Sander Coolen (scoolen) - - Vic D'Elfant (vicdelfant) - - Amirreza Shafaat (amirrezashafaat) - - Maarten Nusteling (nusje2000) - - Gordienko Vladislav - - Peter van Dommelen - - Ahmed EBEN HASSINE (famas23) - - Hubert Moreau (hmoreau) - - Marvin Butkereit - - dantleech - - Anton Babenko (antonbabenko) - - Chris de Kok - - Eduard Bulava (nonanerz) - - Damien Fayet (rainst0rm) - - Andreas Kleemann (andesk) - - Valentin - - Dalibor Karlović - - Nicolas Valverde - - Eric Krona - - Alex Plekhanov - - Igor Timoshenko (igor.timoshenko) - - Hryhorii Hrebiniuk - - Pierre-Emmanuel CAPEL - - Mario Blažek (marioblazek) - - Manuele Menozzi - - Ashura - - Yevhen Sidelnyk - - “teerasak” - - Irmantas Šiupšinskas (irmantas) - - Benoit Mallo - - Charles-Henri Bruyand - - Danilo Silva - - Giuseppe Campanelli - - Konstantin S. M. Möllers (ksmmoellers) - - Ken Stanley - - ivan - - Zachary Tong (polyfractal) - - linh - - Oleg Krasavin (okwinza) - - Jure (zamzung) - - Michael Nelson - - Nsbx - - hamza - - Kajetan Kołtuniak (kajtii) - - Dan (dantleech) - - Artem (digi) - - Sander Goossens (sandergo90) - - Rudy Onfroy - - DerManoMann - - MatTheCat - - Erfan Bahramali - - boite - - tamar peled - - Sergei Gorjunov - - tamirvs - - Silvio Ginter - - David Wolter (davewww) - - Peter Culka - - Arman - - MGDSoft - - Abdiel Carrazana (abdielcs) - - alanzarli - - joris - - Anna Filina (afilina) - - Vadim Tyukov (vatson) - - Yannick - - Gabi Udrescu - - Adamo Crespi (aerendir) - - Sortex - - chispita - - Wojciech Sznapka - - Emmanuel Dreyfus - - Luis Pabon (luispabon) - - boulei_n - - Shaun Simmons - - Ariel J. Birnbaum - - Patrick Luca Fazzi (ap3ir0n) - - Tim Lieberman - - Danijel Obradović - - Pablo Borowicz - - Ben Oman - - Ondřej Frei - - Bruno Rodrigues de Araujo (brunosinister) - - Máximo Cuadros (mcuadros) - - Jacek Wilczyński (jacekwilczynski) - - Christoph Kappestein - - Camille Baronnet - - EXT - THERAGE Kevin - - julien.galenski - - Florian Guimier - - Maxime PINEAU - - Igor Kokhlov (verdet) - - Christian Neff (secondtruth) - - Chris Tiearney - - Oliver Hoff - - Minna N - - andersmateusz - - Laurent Moreau - - Faton (notaf) - - Tom Houdmont - - mark burdett - - Piotr Antosik (antek88) - - Laurent G. (laurentg) - - Ville Mattila + - Benjamin Pick + - Stas Soroka (stasyan) + - Stefan Hüsges (tronsha) + - Pierre Geyer (ptheg) + - Dmitry Hordinky + - Aurimas Rimkus (patrikas) + - Théo DELCEY + - orlovv + - sal-car + - tadas + - Jake Bishop (yakobeyak) + - psampaz (psampaz) - Jean-Baptiste Nahan - - SOEDJEDE Felix (fsoedjede) - - Thomas Decaux - Mert Simsek (mrtsmsk0) - - Nicolas Macherey - - Asil Barkin Elik (asilelik) - - Nacho Martin (nacmartin) - - Bhujagendra Ishaya - - gr8b - - Guido Donnari - - Markus Baumer - - Jérôme Dumas - - Georgi Georgiev - - Norbert Schultheisz - - otsch - - Christophe Meneses (c77men) - - Jeremy David (jeremy.david) - - adnen chouibi - - Andrei O - - Łukasz Chruściel (lchrusciel) - - Max Beutel - - Jordi Rejas - - Troy McCabe - - gstapinato - - gr1ev0us - - Léo VINCENT - - mlazovla - - Alejandro Diaz Torres - - Bradley Zeggelaar - - Karl Shea - - Bouke Haarsma - - Valentin - - Nathan Sepulveda - - Jan Vernieuwe (vernija) - - Antanas Arvasevicius - - Adam Kiss - - Pierre Dudoret - - Thomas - - j.schmitt - - Maximilian Berghoff (electricmaxxx) - - Volker Killesreiter (ol0lll) - - Evgeny Anisiforov - - Tristan Pouliquen - - Dominic Luidold - - Thomas Bibaut - - Thibaut Chieux - - mwos - - Aydin Hassan - - Vedran Mihočinec (v-m-i) - - Jonathan Poston - - Sébastien Lévêque (legenyes) - - Rafał Treffler - - Ken Marfilla (marfillaster) - - Sergey Novikov (s12v) - - Arkadiusz Rzadkowolski (flies) - - creiner - - Marcos Quesada (marcos_quesada) + - Kevin Verschaeve (keversc) + - Chris de Kok + - Albert Ganiev (helios-ag) + - Arnaud CHASSEUX + - GuillaumeVerdon + - Andrea Ruggiero (pupax) + - Rein Baarsma (solidwebcode) + - tante kinast (tante) + - Tim Strehle + - Sébastien COURJEAN + - Tischoi + - Ivan Pepelko (pepelko) + - Marvin Butkereit + - Andriy Prokopenko (sleepyboy) + - Sven Fabricius + - Jaymin G + - robmro27 + - Eric Stern + - Guillaume BRETOU (guiguiboy) + - Manuele Menozzi + - Grzegorz Łukaszewicz (newicz) + - Mark de Haan (markdehaan) + - Maxime Corteel (mcorteel) + - Mathieu MARCHOIS (mmar) + - Ernesto Domato + - Matheus Gontijo + - Abudarham Yuval + - Beth Binkovitz + - adhamiamirhossein + - Anthony Moutte + - mousezheng + - karolsojko + - Stan Jansen (stanjan) + - Paul L McNeely (mcneely) + - Soner Sayakci + - emilienbouard (neime) + - Aleksandr Dankovtsev + - Maciej Schmidt + - tatankat + - Cláudio Cesar + - Sven Nolting + - Lesnykh Ilia + - Shyim + - nuncanada + - Neophy7e + - Emilien Escalle + - jwaguet + - Flinsch + - Maxime P + - Sean Templeton + - db306 + - Sylvain METAYER + - Steve Preston + - Omar Yepez (oyepez003) + - Przemysław Piechota (kibao) + - Ibon Conesa (ibonkonesa) + - Sergey Fokin (tyraelqp) + - Storkeus + - Pavel Stejskal (spajxo) + - ddegentesh + - DSeemiller + - Piet Steinhart + - Cesar Scur (cesarscur) + - Nikita Popov (nikic) + - nuryagdy mustapayev (nueron) + - Igor Plantaš + - Klaas Naaijkens + - Bojan + - Rafał + - Damien Fernandes - Jan Pintr - - Jean-Guilhem Rouel (jean-gui) - - ProgMiner - - remieuronews - - Christian - - Matthew (mattvick) - - MARYNICH Mikhail (mmarynich-ext) - - Viktor Novikov (nowiko) - - Paul Mitchum (paul-m) + - Starfox64 + - Florent Cailhol + - Dmitri Petmanson + - David Négrier (moufmouf) + - Ruben Jansen + - Reda DAOUDI + - Ruud Arentsen + - Saem Ghani + - Warwick + - Daniel Kolvik (dkvk) + - tsilefy + - Peter Gribanov + - Bart Brouwer (bartbrouwer) + - Anna Filina (afilina) + - Yannick + - Gabi Udrescu + - Enrico + - Adrien Foulon + - Sylvain Just + - andreybolonin1989@gmail.com - Angel Koilov (po_taka) - - Marek Binkowski - - Max Grigorian (maxakawizard) - - allison guilhem - - benatespina (benatespina) - - Denis Kop - - Fabrice Locher - - Konstantin Chigakov - - Kamil Szalewski (szal1k) - - Yoann MOROCUTTI - - Ivan Yivoff - - jfcixmedia - - Martijn Evers - - Alexander Onatskiy - - Philipp Fritsche - - Léon Gersen - - tarlepp - - Giuseppe Arcuti - - Dustin Wilson - - Saif Eddin G - - Claus Due (namelesscoder) - - Alexandru Patranescu - - ju1ius - - Denis Golubovskiy (bukashk0zzz) - - Serge (nfx) - - Oksana Kozlova (oksanakozlova) - - Mikkel Paulson - - Dan Wilga - - Jon Green (jontjs) - - Michał Strzelecki - - Marcin Chwedziak - - Bert Ramakers - - Alex Demchenko - - Hugo Fonseca (fonsecas72) - - Marc Duboc (icemad) - - Martynas Narbutas - - Timothée BARRAY - - Nilmar Sanchez Muguercia - - Pierre LEJEUNE (darkanakin41) - - Bailey Parker - - curlycarla2004 - - Javier Ledezma - - Antanas Arvasevicius - - Kris Kelly - - Eddie Abou-Jaoude (eddiejaoude) - - Haritz Iturbe (hizai) - - Rutger Hertogh - - Diego Sapriza - - Joan Cruz - - inspiran - - Richard van Velzen - - Cristobal Dabed - - Daniel Mecke (daniel_mecke) - - Serhii Polishchuk (spolischook) - - Tadas Gliaubicas (tadcka) - - Thanos Polymeneas (thanos) - - Atthaphon Urairat - - Benoit Garret - - Maximilian Ruta (deltachaos) - - Jakub Sacha - - Julius Kiekbusch - - Kamil Musial - - Lucas Bustamante - - Olaf Klischat - - orlovv - - Adrian Olek (adrianolek) - - EdgarPE - - Claude Dioudonnat - - Jonathan Hedstrom - - Peter Smeets (darkspartan) - - Julien Bianchi (jubianchi) - - Michael Dawart (mdawart) - - Robert Meijers - - Tijs Verkoyen - - James Sansbury - - hjkl - - Thijs Reijgersberg - - Nicolas Jourdan (nicolasjc) - - Florian Heller - - Evgeny Efimov (edefimov) - - Oleksii Svitiashchuk - - Péter Buri (burci) - - Yann Rabiller (einenlum) - - Alexander Cheprasov - Andrew Tch - - Peter Trebaticky - - Rodrigo Díez Villamuera (rodrigodiez) - - Brad Treloar - - Nicolas Sauveur (baishu) - - pritasil - - Abderrahman DAIF (death_maker) - - Stephen Clouse - - e-ivanov - - Nathanaël Martel (nathanaelmartel) - - Benjamin Dos Santos - - GagnarTest (gagnartest) - - Jochen Bayer (jocl) - - Tomas Javaisis - - HellFirePvP - - Constantine Shtompel - - VAN DER PUTTE Guillaume (guillaume_vdp) - - Patrick Carlo-Hickman - - Bruno MATEU - - Jeremy Bush - - Lucas Bäuerle - - Laurens Laman - - Thomason, James - - Dario Savella - - Gordienko Vladislav - - Joas Schilling - - Ener-Getick - - Markus Thielen - - Moza Bogdan (bogdan_moza) - - Viacheslav Sychov - - Zuruuh - - Helmut Hummel (helhum) - - Matt Brunt - - David Vancl - - Carlos Ortega Huetos - - jack.thomas (jackthomasatl) - - John VanDeWeghe - - kaiwa - - Charles Sanquer (csanquer) - - Albert Ganiev (helios-ag) - - Neil Katin - - Oleg Mifle - - David Otton - - V1nicius00 - - Will Donohoe - - Takashi Kanemoto (ttskch) - - peter - - Andoni Larzabal (andonilarz) - - Tugba Celebioglu - - Yann (yann_eugone) - - Jeroen de Boer - - Staormin - - Oleg Sedinkin (akeylimepie) - - Dan Brown - - Jérémy Jourdin (jjk801) - - David de Boer (ddeboer) - - BRAMILLE Sébastien (oktapodia) - - maxime.perrimond - - Guillem Fondin (guillemfondin) - - Markkus Millend - - Artem Kolesnikov (tyomo4ka) - - Gustavo Adrian - - Jorrit Schippers (jorrit) - - Matthias Neid - - danilovict2 - - Kuzia - - spdionis - - rchoquet - - v.shevelev - - rvoisin - - gitlost - - Taras Girnyk - - Simon Mönch - - Barthold Bos - - cthulhu - - Wolfgang Klinger (wolfgangklingerplan2net) - - Rémi Leclerc - - Jan Vernarsky - - Ionut Cioflan - - John Edmerson Pizarra - - Sergio - - Jonas Hünig - - Mehrdad - - Amine Yakoubi - - Eno Mullaraj (emullaraj) - - Arnaud CHASSEUX + - david perez (davidpv) + - Duncan de Boer (farmer-duck) + - Harald Tollefsen + - PabloKowalczyk + - Dmytro Dzubenko + - Cedrick Oka + - Serhiy Lunak (slunak) + - Jeroen Bouwmans + - Shiro + - Łukasz Makuch + - Arne Groskurth + - pthompson + - georaldc + - Simon Müller (boscho) + - Steeve Titeca (stiteca) + - Simone Fumagalli (hpatoio) + - Peter Dietrich (xosofox) + - Cyrille Jouineau (tuxosaurus) + - Maxime Aknin (3m1x4m) + - Lauris Binde (laurisb) + - Albion Bame (abame) - Eduardo García Sanz (coma) - - Makdessi Alex - - Dmitrii Baranov - - fduch (fduch) - - Aleksei Lebedev - - dlorek - - Stuart Fyfe - - Jason Schilling (chapterjason) - - Yannick - - Camille Dejoye (cdejoye) - - Pawel Smolinski - - Nathan PAGE (nathix) - - Nicolas Fabre (nfabre) - - Arnaud - - Klaus Purer - - Vladimir Mantulo (mantulo) - - Dmitrii Lozhkin - - Radoslaw Kowalewski - - Marion Hurteau (marionleherisson) - - Gilles Doge (gido) - - Oscar Esteve (oesteve) - - Sobhan Sharifi (50bhan) - - Peter Potrowl - - abulford - - Ilya Vertakov - - Brooks Boyd - - Axel Venet - - Roger Webb - - Yury (daffox) - - John Espiritu (johnillo) - - Tomasz (timitao) - - Nguyen Tuan Minh (tuanminhgp) - - Oxan van Leeuwen - - pkowalczyk - - dbrekelmans - - Mykola Zyk - - Soner Sayakci - - Max Voloshin (maxvoloshin) - - Raul Rodriguez (raul782) - - Piet Steinhart - - mousezheng - - mshavliuk - - Rémy LESCALLIER - - Kacper Gunia (cakper) - - Derek Lambert (dlambert) - - Peter Thompson (petert82) - - Victor Macko (victor_m) - - error56 - - Felicitus - - Jorge Vahldick (jvahldick) - - Krzysztof Przybyszewski (kprzybyszewski) - - Boullé William (williamboulle) - - Bart Baaten - - Clement Herreman (clemherreman) - - Frederic Godfrin - - Dalibor Karlović - - Paul Matthews - - Jakub Kisielewski - - Vacheslav Silyutin - - Aleksandr Dankovtsev - - Maciej Zgadzaj - - David Legatt (dlegatt) - - Alain Flaus (halundra) - - Arthur Woimbée - - tsufeki - - Théo DELCEY - - Philipp Strube - - Wim Hendrikx - - Andrii Serdiuk (andreyserdjuk) - - dangkhoagms (dangkhoagms) - - Jesper Noordsij - - Dan Ionut Dumitriu (danionut90) - - Evgeny (disparity) - - Floran Brutel (notFloran) (floran) - - Vladislav Rastrusny (fractalizer) - - Vlad Gapanovich (gapik) - - nyro (nyro) - - Konstantin Bogomolov - - Marco - - Marc Torres - - Mark Spink - - Alberto Aldegheri - - Cesar Scur (cesarscur) - - Cyril Vermandé (cyve) - - Daniele Orru' (danydev) - - Raul Garcia Canet (juagarc4) - - Dmitri Petmanson - - Tobias Stöckler - - Alexandre Melard - - Rafał Toboła - - Dominik Schwind (dominikschwind) - - Stefano A. (stefano93) - - PierreRebeilleau - - AlbinoDrought - - Sergey Yuferev - - Monet Emilien - - voodooism - - Mario Young - - cybernet (cybernet2u) - - martkop26 - - Orestis - - Raphaël Davaillaud - - Pablo Schläpfer - - Sander Hagen - - Alexander Menk - - Agustin Gomes - - Peter Jaap Blaakmeer - - Prasetyo Wicaksono (jowy) - - cilefen (cilefen) - - Mo Di (modi) - - ConneXNL - - Victor Truhanovich (victor_truhanovich) - - Adam Wójs (awojs) - - Tomasz Szymczyk (karion) - - Christian Rishøj - - Nikos Charalampidis - - Caligone - - Ismail Turan - - Patrick Berenschot - - SuRiKmAn - - matze - - Xavier RENAUDIN - - Christian Wahler (christian) - - Jelte Steijaert (jelte) - - Maxime AILLOUD (mailloud) - - David Négrier (moufmouf) - - Quique Porta (quiqueporta) - - Tobias Feijten (tobias93) - - mohammadreza honarkhah - - Jessica F Martinez - - paullallier - - Artem Oliinyk (artemoliynyk) - - Andrea Quintino (dirk39) - - Andreas Heigl (heiglandreas) - - Alex Vasilchenko - - sez-open - - fruty - - Aharon Perkel - - Justin Reherman (jreherman) - - Miłosz Guglas (miloszowi) - - Rubén Calvo (rubencm) - - Abdul.Mohsen B. A. A - - Cédric Girard - - Robert Worgul - - Swen van Zanten - - Malaney J. Hill - - Robert Korulczyk - - Patryk Kozłowski - - Alexandre Pavy - - Zander Baldwin - Tim Ward - - Jeffrey Cafferata (jcidnl) - - Adiel Cristo (arcristo) - - Andrei Igna + - BiaDd + - Olatunbosun Egberinde + - Alexis Lefebvre + - Johannes - Christian Flach (cmfcmf) - - Marcin Nowak - - Mark van den Berg - - Fabian Kropfhamer (fabiank) - - Junaid Farooq (junaidfarooq) + - Bogdan Rancichi (devck) + - Willem Mouwen + - Ikko Ashimine + - Alexandre GESLIN + - Dariusz Ruminski + - Eduard Morcinek + - ShiraNai7 + - RichardGuilland + - Mykola Zyk + - Grégoire Hébert (gregoirehebert) + - AbdElKader Bouadjadja - Pavel Starosek (octisher) - - Oriol Mangas Abellan (oriolman) + - Emre YILMAZ + - Christian Kolb + - David Soria Parra + - changmin.keum + - Sébastien HOUZE + - popnikos + - Kasper Hansen + - Saem Ghani + - Szymon Kamiński (szk) + - Stefan Koopmanschap - Tatsuya Tsuruoka - omniError - - László GÖRÖG - - djordy - - Mihai Nica (redecs) - - Adam Prickett - - Luke Towers - - Wojciech Zimoń - - Vladimir Melnik - - Anton Kroshilin - - Pierre Tachoire - - Juan Traverso - - Dawid Sajdak - - Maxime THIRY - - Norman Soetbeer - - Ludek Stepan - - Benjamin BOUDIER - - Frederik Schwan + - Stuart Fyfe + - TheMhv + - Benoit Garret + - Vincent LEFORT (vlefort) + - Valentin Nazarov + - fduch (fduch) + - Kris Buist + - Kevin Weber + - Juan Luis (juanlugb) + - Andrew (drew) + - Gautier Deuette + - Tito Miguel Costa (titomiguelcosta) + - andrey-tech + - Tobias Feijten (tobias93) + - Nicolas Badey (nico-b) + - Carl Julian Sauter + - Mikko Pesari + - jdcook + - Kenjy Thiébault (kthiebault) + - Yury (daffox) + - Markus Tacker + - Juan Miguel Besada Vidal (soutlink) + - samuel laulhau (lalop) + - Matt Drollette (mdrollette) + - Talha Zekeriya Durmuş + - Michal Forbak + - John Edmerson Pizarra + - Taylan Kasap + - Michael Orlitzky + - Juraj Surman + - heccjj + - Florian Guimier + - Laurent Bachelier (laurentb) + - Adam Monsen (meonkeys) + - Nathan PAGE (nathix) + - Florent Blaison (orkin) + - Andrei O + - Łukasz Chruściel (lchrusciel) + - Jordi Rejas + - mlievertz + - Takashi Kanemoto (ttskch) + - peter + - g123456789l + - Roman Tymoshyk (tymoshyk) + - Normunds + - Yuri Karaban + - Jan Hort + - Stephanie Trumtel (einahp) + - Walter Doekes + - Thomas Rothe + - Alessandra Lai + - timesince + - alangvazq + - Ernest Hymel + - Andrea Civita + - Kévin Gomez (kevin) + - Rafael Villa Verde + - Albert Bakker (babbert) + - Adamo Crespi (aerendir) + - Karim Miladi + - Aryel Tupinamba (dfkimera) + - Julius (sakalys) + - Jörn Lang + - Alan ZARLI + - Bertalan Attila + - Abdouarrahmane FOUAD (fabdouarrahmane) + - Rowan Manning + - Jakub Janata (janatjak) + - Joeri Verdeyen (jverdeyen) + - Ruslan Zavacky (ruslanzavacky) + - Jakub Caban (lustmored) + - Stefano Cappellini (stefano_cappellini) + - Bruno MATEU + - Juanmi Rodriguez Cerón + - Joseph Maarek + - Alexander Menk + - Ville Mattila + - Buster Neece + - Adam + - Albert Prat + - Johannes + - Yuriy Potemkin + - Nicolás Alonso + - Roman Tyshyk + - LoginovIlya + - Hossein Hosni + - Emilie Lorenzo + - Alessandro Loffredo + - Seyedramin Banihashemi (ramin) + - Jakub Chábek + - Dmitriy Tkachenko (neka) + - Johannes + - Andre Johnson + - MaPePeR + - Andreas Streichardt + - jamogon + - david-binda + - rogamoore + - Christoph König (chriskoenig) + - Valérian Galliat + - Jeremy Bush + - Fred Cox + - Lucas Bäuerle + - Jeremy Benoist + - Frédéric G. Marand (fgm) + - rhel-eo + - Thijs Reijgersberg + - Vallel Blanco + - Yannick Bensacq (cibou) + - Sander Hagen + - Yevhen Sidelnyk + - Volodymyr Kupriienko (greeflas) + - Renato Mendes Figueiredo + - Andrew Clark (tqt_andrew_clark) + - Aaron Piotrowski (trowski) + - David Lumaye (tux1124) + - Arnaud Buathier (arnapou) + - czachor + - Johan + - Jörg Rühl + - Pierre LEJEUNE (darkanakin41) + - Guillaume Loulier (guikingone) + - Dmytro Pigin (dotty) + - Bailey Parker + - curlycarla2004 + - Daniele Orru' (danydev) + - Thomas BERTRAND (sevrahk) + - Dr. Gianluigi "Zane" Zanettini + - Tristan Bessoussa (sf_tristanb) + - Vladislav (simpson) + - ConneXNL + - Rémi Blaise + - Zander Baldwin + - izenin + - Lebnik + - Bohdan Pliachenko + - Francisco Facioni (fran6co) + - Markus + - agaktr + - Till Klampaeckel (till) + - Nicholas Ruunu (nicholasruunu) + - Pierre Rebeilleau (pierrereb) + - Hugo Posnic + - Nicolas Roudaire + - Barthold Bos + - Mathias Geat + - neodevcode + - Emmanuel Vella (emmanuel.vella) + - Oleksii Bulba + - Guillaume LECERF + - Raul Garcia Canet (juagarc4) + - Tobias Stöckler + - Dustin Wilson + - withbest + - Joe Springe + - Abdelhakim ABOULHAJ + - Pieter + - Kamil Musial + - Jeremiah VALERIE - Aaron Stephens (astephens) - Craig Menning (cmenning) - Balázs Benyó (duplabe) - - Erika Heidi Reinaldo (erikaheidi) + - Ema Panz + - Mauricio Lopez (diaspar) + - Ismail Asci (ismailasci) + - Rafał Muszyński (rafmus90) + - Anthony Tenneriello + - Athorcis + - Thierry Marianne + - David Windell + - Frank Jogeleit + - Benny Born + - Arrilot + - Dan (dantleech) + - Makdessi Alex + - Mikkel Paulson + - Paul Ferrett + - Joachim Krempel (jkrempel) + - Freek Van der Herten (freekmurze) + - Matthias Bilger + - Tom Kaminski + - Abdulkadir N. A. + - Emmanuel Dreyfus + - Ilya Vertakov + - Brooks Boyd + - Markus Klein + - Bruno Nogueira Nascimento Wowk + - Jan Emrich + - paullallier + - Artem Oliinyk (artemoliynyk) + - Andrea Quintino (dirk39) + - Andrew Marcinkevičius (ifdattic) + - Neil Katin + - Oleg Mifle + - David Otton + - Andreas Heigl (heiglandreas) + - Dawid Nowak - William Thomson (gauss) - - Javier Espinosa (javespi) - - Marc J. Schmidt (marcjs) - - František Maša - - Sebastian Schwarz - - Flohw - - karolsojko - - Saem Ghani - - Marco Jantke - - Maks Rafalko (bornfree) - - alifanau - - Claudiu Cristea - - Jonathan Gough - - Samy D (dinduks) - - Zacharias Luiten - - Clément LEFEBVRE (nemoneph) - - Sebastian Utz - - Adrien Gallou (agallou) - - twifty - - Andrea Sprega (asprega) - - Conrad Kleinespel (conradk) - - Viktor Bajraktar (njutn95) - - Walter Dal Mut (wdalmut) - - abluchet - - Ruud Arentsen - - Harald Tollefsen - - PabloKowalczyk - - Matthieu - - Arend-Jan Tetteroo - - Albin Kerouaton - - sebastian - - Mbechezi Nawo - - wivaku - - Markus Reinhold - - steveYeah - - Asrorbek (asrorbek) - - Ross Tuck - - Keri Henare (kerihenare) - - Andre Eckardt (korve) - - Cédric Lahouste (rapotor) - - Samuel Vogel (samuelvogel) - - Osayawe Ogbemudia Terry (terdia) - - Berat Doğan - - Christian Kolb - - Guillaume LECERF - - Alan Scott - - markusu49 - - Juanmi Rodriguez Cerón - - Andy Raines - - François Poguet - - Anthony Ferrara - - Geoffrey Pécro (gpekz) - - Klaas Cuvelier (kcuvelier) - - Flavien Knuchel (knuch) - - Mathieu TUDISCO (mathieutu) - - Dmytro Dzubenko - - Martijn Croonen - - Peter Ward - - Steve Frécinaux - - Constantine Shtompel - - Jules Lamur - - Volodymyr Kupriienko (greeflas) - - Renato Mendes Figueiredo - - Sagrario Meneses - - Illia Antypenko (aivus) - - Vašek Purchart (vasek-purchart) - - xdavidwu - - Alexander Pasichnik (alex_brizzz) - - Raphaël Droz - - Antal Áron (antalaron) - - Dominik Ritter (dritter) - - ShiraNai7 - - Cedrick Oka - - Guillaume Sainthillier (guillaume-sainthillier) - - Ivan Pepelko (pepelko) - - Janusz Jabłoński (yanoosh) - - Jens Hatlak - - Fleuv - - Tayfun Aydin - - Łukasz Makuch - - Arne Groskurth - - pthompson - - Ilya Chekalsky - - Ostrzyciel - - George Giannoulopoulos - - Thibault G - - Luis Ramirez (luisdeimos) - - Ilia Sergunin (maranqz) - - Daniel Richter (richtermeister) - - Sandro Hopf (senaria) - - ChrisC - - André Laugks - - jack.shpartko - - Mathieu Ledru (matyo91) - - Willem Verspyck - - Kim Laï Trinh - - Johan de Ruijter - - InbarAbraham - - Jason Desrosiers - - m.chwedziak - - marbul - - Andreas Frömer - - Jeroen Bouwmans - - Bikal Basnet - - Philip Frank - - David Brooks - - Lance McNearney - - Jelizaveta Lemeševa (broken_core) - - Daniel Rotter (danrot) - - jprivet-dev - - Ilya Biryukov (ibiryukov) - - Frank Neff (fneff) - - Ema Panz - - Roma (memphys) - - Dale.Nash - - Jozef Môstka (mostkaj) - - Daniel Tschinder - - Wojciech Błoszyk (wbloszyk) - - Florian Caron (shalalalala) - - Serhiy Lunak (slunak) - - Martin Pärtel - - Giorgio Premi - - Tom Corrigan (tomcorrigan) - - abunch - - 🦅KoNekoD - - Lukas Naumann - - Mikko Pesari - - Krzysztof Pyrkosz - - ncou - - Ian Carroll - - Dennis Fehr - - jdcook - - Daniel Kay (danielkay-cp) - - Matt Daum (daum) - - Malcolm Fell (emarref) - - Alberto Pirovano (geezmo) - - inwebo veritas (inwebo) - - Pascal Woerde (pascalwoerde) - - Pete Mitchell (peterjmit) - - phuc vo (phucwan) - - Luis Galeas - - CDR - - Bogdan Scordaliu - - Sven Scholz - - Frédéric Bouchery (fbouchery) - - Jacek Kobus (jackks) - - Patrick Daley (padrig) - - Phillip Look (plook) - - Foxprodev - - Artfaith - - Tom Kaminski + - Phil Davis + - Alex Vasilchenko + - Brieuc Thomas - developer-av - - Max Summe - - DidierLmn - - Pedro Silva - - Ivan Tse - - Chihiro Adachi (chihiro-adachi) - - Clément R. (clemrwan) - - Yoann Chocteau (kezaweb) - - Jeroen de Graaf - - Emmanuel Vella (emmanuel.vella) - - Hossein Hosni - - Marcus Stöhr (dafish) - - Ulrik McArdle - - BiaDd - - Jay Severson - - Oleksii Bulba - - Raphaëll Roussel - - Ramon Cuñat - - mboultoureau - - AnotherSymfonyUser (arderyp) - - Vitalii - - Tadcka - - Bárbara Luz - - Abudarham Yuval - - Beth Binkovitz - - adhamiamirhossein - - Maxim Semkin - - Gonzalo Míguez - - Jan Vernarsky - - Fabian Haase - - roog - - parinz1234 - - seho-nl + - Malte Wunsch (maltewunsch) - Romain Geissler - - Viktoriia Zolotova - - Tomaz Ahlin - - Nasim - - Randel Palu - - Anamarija Papić (anamarijapapic) - - Daniel González Zaballos (dem3trio) - - Przemysław Piechota (kibao) + - tamar peled + - Maxim Lovchikov + - Laurent G. (laurentg) + - John Espiritu (johnillo) + - dakur + - Wotre + - Alexandru Bucur + - Alexis BOYER + - Adrian Philipp + - James Michael DuPont + - DidierLmn + - Kasperki + - Javier Alfonso Bellota de Frutos + - Matthias Meyer + - carlos-ea + - Temuri Takalandze (abgeo) + - David Legatt (dlegatt) + - A. Pauly + - Nicolas A. Bérard-Nault + - Karolis Daužickas (kdauzickas) + - Bernard van der Esch (adeptofvoltron) + - Aleksejs Kovalovs (aleksejs1) + - Chris McGehee + - Tomasz (timitao) - Giuseppe Petraroli (gpetraroli) - - Ibon Conesa (ibonkonesa) - - Nikita Popov (nikic) - - nuryagdy mustapayev (nueron) + - Stéphane Seng (stephaneseng) + - Julien Manganne (juuuuuu) + - Matt Ketmo (mattketmo) + - Pierre Foresi (pforesi) + - karl.rixon + - Alexander Kurilo (kamazee) + - Claus Due (namelesscoder) - Carsten Nielsen (phreaknerd) - Valérian Lepeule (vlepeule) - - Vincent Vermeulen - - Stefan Moonen - - Robert Meijers - - Emirald Mateli - - René Kerner - - Michael Olšavský - - upchuk - - Tony Vermeiren (tony) - - Adrien Samson (adriensamson) - - Samuel Gordalina (gordalina) - - Nicolas Eeckeloo (neeckeloo) - - Andriy Prokopenko (sleepyboy) - - Dariusz Ruminski - - Starfox64 - - Ivo Valchev - - Thomas Hanke - - ffd000 - - Zlatoslav Desyatnikov - - Wickex - - tuqqu - - Wojciech Gorczyca - - Ahmad Al-Naib - - Neagu Cristian-Doru (cristian-neagu) - - Mathieu Morlon (glutamatt) - - NIRAV MUKUNDBHAI PATEL (niravpatel919) - - Owen Gray (otis) - - Sébastien Decrême (sebdec) - - Timothy Anido (xanido) - - Mara Blaga - - Rick Prent - - skalpa - - Bartłomiej Zając - - Pieter Jordaan - - Tournoud (damientournoud) + - Stephen Lewis (tehanomalousone) + - Thanos Polymeneas (thanos) + - Sergey Stavichenko (sergey_stavichenko) + - Matej Žilák (teo_sk) + - satalaondrej + - Arek Bochinski + - Ostrzyciel + - George Giannoulopoulos + - VojtaB + - Vašek Purchart (vasek-purchart) + - Vic D'Elfant (vicdelfant) + - Amirreza Shafaat (amirrezashafaat) - Michael Dowling (mtdowling) - - Romain - - Karlos Presumido (oneko) - - Pierre Foresi (pforesi) - - Bart Wach - - Jos Elstgeest - - Kirill Lazarev - - Joe - - BilgeXA - - mmokhi - - Serhii Smirnov - - Robert Queck - - Peter Bouwdewijn - - Kurt Thiemann - - Daniil Gentili - - Thomas Counsell - - Pierre Grimaud (pgrimaud) - - Eduard Morcinek - - Wouter Diesveld - - Sebastian Ionescu - - Thomas Ploch - - Matěj Humpál - - Kristen Gilden - - Nico Hiort af Ornäs - - Eddy - - Felipy Amorim (felipyamorim) - - Amine Matmati - - Kasper Hansen - - Benny Born - - Thomas Boileau (tboileau) - - caalholm - - Hugo Sales - - Nouhail AL FIDI (alfidi) - - Michael Lively (mlivelyjr) - - Abderrahim (phydev) - - Attila Bukor (r1pp3rj4ck) - - Mickael GOETZ - - Alexander Janssen (tnajanssen) - - Thomas Chmielowiec (chmielot) - - Jānis Lukss + - Iwan van Staveren (istaveren) + - Dominik Pesch (dombn) - Julien BERNARD - - Michael Zangerle - - rkerner - - Alex Silcock - - Raphael Hardt - - Ivan Nemets - - Dave Long - - Qingshan Luo - - Matthew J Mucklo - - AnrDaemon - - SnakePin - - Matthew Covey - - Tristan Kretzer - - Adriaan Zonnenberg - - Charly Terrier (charlypoppins) - - Dcp (decap94) - - Emre Akinci (emre) - - Rachid Hammaoui (makmaoui) - - psampaz (psampaz) - - Andrea Ruggiero (pupax) - - Stan Jansen (stanjan) - - Maxwell Vandervelde - - karstennilsen - - kaywalker - - Robert Kopera - - Jody Mickey (jwmickey) - - Victor Prudhomme - - Wouter Ras - - Simon Neidhold - - Patrik Patie Gmitter - - j4nr6n (j4nr6n) - - Gil Hadad - - Stelian Mocanita (stelian) - - Valentin VALCIU - - Franck Ranaivo-Harisoa - - Jeremiah VALERIE - - Alexandre Beaujour - - Martins Eglitis - - Grégoire Rabasse - - Cas van Dongen - - George Yiannoulopoulos - - Kevin Dew - - James Cowgill - - Žan V. Dragan - - sensio - - Julien Menth (cfjulien) - - Nicolas Schwartz (nicoschwartz) - - Tim Jabs (rubinum) - - Schvoy Norbert (schvoy) - - Aurélien Fontaine - - Stéphane Seng (stephaneseng) - - Benhssaein Youssef - - Benoit Leveque - - bill moll - - chillbram - - Benjamin Bender - - PaoRuby - - Holger Lösken - - Bizley - - Jared Farrish - - karl.rixon - - Konrad Mohrfeldt - - Lance Chen + - Drew Butler + - Luciano Mammino (loige) + - Tamás Szigeti + - DerStoffel + - Thomas Boileau (tboileau) + - Carlos Tasada + - tinect (tinect) + - Sebastian Göttschkes (sgoettschkes) + - mieszko4 + - Mamikon Arakelyan (mamikon) + - Oz (import) + - Bernhard Rusch + - David Stone + - Vincent Bouzeran + - Matt Farmer + - Benoit Lévêque (benoit_leveque) + - Mihai Nica (redecs) + - Nouhail AL FIDI (alfidi) + - Michael Lively (mlivelyjr) + - Jules Matsounga (hyoa) + - Bikal Basnet + - David Brooks + - Jiri Falis + - Kérian MONTES-MORIN (kerianmm) + - Tobias Speicher + - rewrit3 + - Peter Bex - Ciaran McNulty (ciaranmcnulty) - Dominik Piekarski (dompie) - - Andrew (drew) - - Rares Sebastian Moldovan (raresmldvn) - - Gautier Deuette - - dsech - - wallach-game - - Gilbertsoft - - Matthias Bilger - - tadas - - Bastien Picharles - - Linas Ramanauskas - - Martin Schophaus (m_schophaus_adcada) - - Olivier Scherler (oscherler) - - mamazu - - Marek Víger (freezy) - - Keith Maika - - izenin - - Mephistofeles - - Oleh Korneliuk + - David Joos (djoos) + - Dennis Smink (dsmink) + - Sebastian Utz - Emmanuelpcg - - Rini Misini - - Attila Szeremi - - Pablo Ogando Ferreira - - Hoffmann András - - LubenZA - - Victor Garcia - - Juan Mrad - - Denis Yuzhanin - - k-sahara - - Flavian Sierk - - Rik van der Heijden - - Thomas Beaujean - - alireza - - Michael Bessolov - - sauliusnord - - Zdeněk Drahoš - - Dan Harper - - moldcraft - - Marcin Kruk - - Antoine Bellion (abellion) - - Ramon Kleiss (akathos) - - Alexey Buyanow (alexbuyanow) - - Antonio Peric-Mazar (antonioperic) - - Bjorn Twachtmann (dotbjorn) - - Goran (gog) - - Wahyu Kristianto (kristories) - - Tobias Genberg (lorceroth) - - Nicolas Badey (nico-b) - - Florent Blaison (orkin) - - Flo Gleixner (redflo) - - Romain Jacquart (romainjacquart) - - Shane Preece (shane) - - Stephan Wentz (temp) - - Johannes Goslar - - Mike Gladysch - - Geoff - - georaldc - - wusuopu - - Markus Staab - - Peter Potrowl - - Juliano Petronetto - - povilas - - Martynas Sudintas (martiis) - - Marie Minasyan (marie.minassyan) - - Gavin Staniforth - - Anton Sukhachev (mrsuh) - - bahram - - Gunnar Lium (gunnarlium) - - Pavlo Pelekh (pelekh) - - Nikita Starshinov (biji) - - andreybolonin1989@gmail.com - - Kirk Madera - - Alex Teterin (errogaht) - - Stefan Kleff (stefanxl) - - Boris Betzholz - - Marcel Siegert - - Kélian Bousquet (kells) - - RichardGuilland - - Sergey Fokin (tyraelqp) - - Pavel Stejskal (spajxo) - - Arnau González - - ryunosuke - - Tiago Garcia (tiagojsag) - - TheMhv - - Eviljeks - - everyx - - Richard Heine - - Francisco Facioni (fran6co) - - Stanislav Gamaiunov (happyproff) - - Iwan van Staveren (istaveren) - - Alexander McCullagh (mccullagh) - - Paul L McNeely (mcneely) - - Povilas S. (povilas) - - Laurent Negre (raulnet) + - Iain Cambridge + - Pierre Rineau + - Jochen Mandl + - Viet Pham + - Max Grigorian (maxakawizard) + - michalmarcinkowski + - cybernet (cybernet2u) + - Pierre Grimaud (pgrimaud) + - sez-open + - Robert Campbell + - Matt Lehner + - Helmut Januschka + - Hein Zaw Htet™ + - fruty + - Aharon Perkel + - Aleksandar Dimitrov (netbull) + - Pierre-Henry Soria 🌴 (pierrehenry) + - Alexis + - Michael Genereux + - Vincent Vermeulen + - Thomas Jarrand + - abunch + - Marek Šimeček (mssimi) + - Patrick Luca Fazzi (ap3ir0n) + - David Zuelke + - Adrian + - Oliver Eglseder + - Marcin Chwedziak + - Mark Topper + - Xavier REN + - Faton (notaf) + - martijn + - Sergei Shitikov + - Jens Schulze + - Jessica F Martinez + - Tema Yud + - Kevin Meijer + - Juan Traverso + - Jonny Schmid (schmidjon) + - Christian Stocker + - Jon Green (jontjs) + - Alexander Janssen (tnajanssen) + - Vladimir Vasilev (bobahvas) + - Anton (bonio) + - spdionis + - Thibault G - Victoria Quirante Ruiz (victoria) - Evrard Boulou - pborreli - - Ibrahim Bougaoua - - Eric Caron - - GurvanVgx - - 2manypeople - - Thomas Bibb - - Athorcis - - Szymon Kamiński (szk) - - Stefan Koopmanschap - - George Sparrow - - Chris Tickner - - Toro Hill - - Matt Farmer - - Benoit Lévêque (benoit_leveque) - - André Laugks - - aetxebeste - - Andrew Coulton - - Roberto Guido - - Wouter de Wild - - mikocevar - - ElisDN - - Vitali Tsyrkin - - Juga Paazmaya - - Alexandre Segura - - afaricamp - - Josef Cech - - riadh26 - - AntoineDly - - Konstantinos Alexiou - - Andrii Boiko - - Dilek Erkut - - Harold Iedema - - WaiSkats - - Morimoto Ryosuke - - Ikhsan Agustian - - raplider - - Simon Bouland (bouland) - - Christoph König (chriskoenig) - - Dmytro Pigin (dotty) - - Abdouarrahmane FOUAD (fabdouarrahmane) - - Jakub Janata (janatjak) + - Constantine Shtompel + - pawel-lewtak + - Pierrick Charron + - Steve Müller + - Ferran Vidal + - Michael J + - Gary Houbre (thegarious) + - damaya + - Marc Bennewitz + - Pierre-Chanel Gauthier (kmecnin) + - Kirill Roskolii + - Gonzalo Míguez + - adenkejawen + - Dmitry (staratel) + - Flavien Knuchel (knuch) + - jonmldr + - Peter Ward + - andreyserdjuk + - martkop26 + - Alex Olmos (alexolmos) + - Andriy + - Taylor Otwell + - Cédric Girard + - Raphaël Davaillaud + - Martin Mandl (m2mtech) + - David Gorges (davidgorges) + - Gustavo Adrian + - Alexander Bauer (abauer) + - kaiwa + - Ian Littman (iansltx) + - chispita + - Wojciech Sznapka + - Nathan Sepulveda + - Olaf Klischat + - Jeffrey Cafferata (jcidnl) + - Iliya Miroslavov Iliev (i.miroslavov) + - Gert de Pagter + - Sergiy Sokolenko + - Karel Syrový + - Claas Augner + - Houziaux mike + - Ariel J. Birnbaum + - Angel Fernando Quiroz Campos (angelfqc) + - Charles-Henri Bruyand + - Giuseppe Campanelli + - Sam Anthony + - David Lima + - azine + - Bart Ruysseveldt + - Alexandre Tranchant (alexandre_t) + - Steve Marvell + - thib92 + - Thibaut Salanon + - Jan Vernarsky + - Rudolf Ratusiński + - Hans Höchtl (hhoechtl) + - Peter Thompson (petert82) + - Fabian Haase + - parinz1234 + - seho-nl + - Erika Heidi Reinaldo (erikaheidi) + - Yevgen Kovalienia + - James Sansbury + - Sam Malone + - Kai Dederichs + - Cantepie + - Derek Bonner + - Krzysztof Menżyk (krymen) + - Nicholas Byfleet (nickbyfleet) + - Pontus Mårdnäs + - Arkadiusz Kondas (itcraftsmanpl) + - Viktoriia Zolotova + - Abderrahim (phydev) + - Attila Bukor (r1pp3rj4ck) + - Mickael GOETZ + - Andreas + - Ulugbek Miniyarov + - neFAST + - Martynas Sudintas (martiis) + - Georg Ringer (georgringer) + - Eric Caron + - Stefan Oderbolz + - Steve Frécinaux + - Rémy LESCALLIER + - Alexey Popkov + - qzylalala + - Ali Tavafi + - Tony Vermeiren (tony) + - Tom Houdmont + - es + - Wickex + - Ala Eddine Khefifi (nayzo) + - NothingWeAre + - goabonga + - Maciej Zgadzaj + - Alexandru Patranescu + - Derek Lambert (dlambert) + - Gabriel Birke + - Daniele Cesarini (ijanki) + - ju1ius + - gstapinato + - Matthias Neid + - Javier Espinosa (javespi) + - Ilia Lazarev (ilzrv) + - Klaas Cuvelier (kcuvelier) + - JustDylan23 + - Dennis Tobar + - Javan Eskander + - Gordienko Vladislav + - arduanov + - Lenar Lõhmus + - Guillaume Sainthillier (guillaume-sainthillier) + - MusikAnimal + - Richard Quadling + - Pete Mitchell (peterjmit) + - phuc vo (phucwan) - Jm Aribau (jmaribau) - Matthew Foster (mfoster) - - Tobias Speicher - Paul Seiffert (seiffert) - - Vasily Khayrulin (sirian) - - Stas Soroka (stasyan) - - Thomas Dubuffet (thomasdubuffet) - - Stefan Hüsges (tronsha) - - Jake Bishop (yakobeyak) - - Dan Blows - - popnikos - - Matt Wells - - Nicolas Appriou - - Javier Alfonso Bellota de Frutos - - stloyd - - Tito Costa - - Andreas - - Ulugbek Miniyarov - - Antoine Beyet - - Michal Gebauer - - Gerhard Seidel (gseidel) - - René Landgrebe - - Phil Davis - - Houziaux mike - - Thiago Melo - - Gleb Sidora - - Thomas Chmielowiec - - David Stone - - Giorgio Premi - - Jovan Perovic (jperovic) - - Pablo Maria Martelletti (pmartelletti) - - Sander van der Vlugt (stranding) - - Sebastian Drewer-Gutland (sdg) - - casdal - - Waqas Ahmed - - Bert Hekman - - Luis Muñoz - - Matthew Donadio - - Kris Buist - - Phobetor - - Eric Schildkamp - - Yoann MOROCUTTI - - d.huethorst - - Markus - - DerStoffel - - agaktr - - Janusz Mocek - - Johannes - - Mostafa - - kernig - - shdev - - Andrey Ryaguzov - - Gennadi Janzen - - SenTisso - - Peter Bex - - Manatsawin Hanmongkolchai - - Gunther Konig - - Joe Springe - - Jesper Noordsij - - Jeremiah VALERIE - - Flinsch - - Maciej Schmidt - - botbotbot - - tatankat - - Cláudio Cesar - - Sven Nolting - - Timon van der Vorm - - nuncanada - - František Bereň - - G.R.Dalenoort - - Mike Francis + - GurvanVgx + - marbul + - Abderrahman DAIF (death_maker) + - Robert Worgul + - Simon Frost + - Constantine Shtompel + - Diego Campoy - Adrien Moiruad - - Nil Borodulia - - Vladimir Khramtsov (chrome) - - Adam Katz - - Julius Beckmann (h4cc) - - Almog Baku (almogbaku) - - Boris Grishenko (arczinosek) - - Arrakis (arrakis) - - Andrey Helldar - - Danil Khaliullin (bifidokk) - - Lorenzo Adinolfi (loru88) - - Benjamin Schultz (bschultz) - - Christian Grasso (chris54721) - - Gerd Christian Kunze (derdu) - - Stephanie Trumtel (einahp) - - Denys Voronin (hurricane) + - Swen van Zanten + - Marcus + - Gemorroj (gemorroj) + - Reece Fowell (reecefowell) + - Julien ARBEY + - Bert Ramakers + - Michael Bessolov + - mmokhi + - ProgMiner - Ionel Scutelnicu (ionelscutelnicu) - - Juan Gonzalez Montes (juanwilde) - - Kamil Madejski (kmadejski) - - Mathieu Dewet (mdewet) - - none (nelexa) - - Nicolas Tallefourtané (nicolab) - - Botond Dani (picur) - - Rémi Faivre (rfv) - - Radek Wionczek (rwionczek) - - tinect (tinect) - - Nick Stemerdink - - Bernhard Rusch - - David Stone - - Vincent Bouzeran - - Ruben Jansen - - Thibaut Salanon - - Romain Dorgueil - - Christopher Parotat - - Dennis Haarbrink - - Daniel Kozák - - Urban Suppiger - - Julien JANVIER (jjanvier) - - Karim Cassam Chenaï (ka) - - Ahmed Shamim Hassan (me_shaon) - - Mikko Ala-Fossi - - Marcello Mönkemeyer (marcello-moenkemeyer) - - Michal Kurzeja (mkurzeja) - - nietonfir - - Nikola Svitlica (thecelavi) - - Nicolas Bastien (nicolas_bastien) - - Sjors Ottjes - - VojtaB - - Andy Stanberry - - Felix Marezki - - Normunds - - Yuri Karaban - - Walter Doekes - - Thomas Rothe - - Edwin - - Troy Crawford - - Kirill Roskolii - - Jeroen van den Nieuwenhuisen - - Andriy - - Taylor Otwell - - Ph3nol - - alefranz - - David Barratt - - Andrea Giannantonio - - Pavel.Batanov - - avi123 - - Pavel Prischepa - - Philip Dahlstrøm - - Pierre Schmitz - - Sami Mussbach - - qzylalala - - alsar - - Aarón Nieves Fernández - - Ahto Türkson - - Paweł Stasicki - - Kirill Saksin - - Shiro - - Reda DAOUDI - - michalmarcinkowski - - Warwick - - Chris - - Farid Jalilov - - Christiaan Wiesenekker - - Nicolas Pion - - Ariful Alam - - Florent Olivaud - - Foxprodev - - Eric Hertwig - - JakeFr - - Oliver Klee - - Niels Robin-Aubertin - - Simon Sargeant - - efeen - - Jan Christoph Beyer - - Muhammed Akbulut - - Nathanael d. Noblet - - Daniel Tiringer - - Rénald Casagraude (rcasagraude) - - Xesau - - Koray Zorluoglu - - Steeve Titeca (stiteca) - - Roy-Orbison - - Aaron Somi - - Elías (eliasfernandez) - - kshida - - Yasmany Cubela Medina (bitgandtter) - - Brian Graham (incognito) - - Michał Dąbrowski (defrag) - - Aryel Tupinamba (dfkimera) - - Hans Höchtl (hhoechtl) - - Jeremy Benoist - - Kevin Vergauwen (innocenzo) - - Alessio Baglio (ioalessio) - - Johannes Müller (johmue) - - Jordi Llonch (jordillonch) - - julien_tempo1 (julien_tempo1) - - Roman Igoshin (masterro) - - Nicholas Ruunu (nicholasruunu) - - Pierre Rebeilleau (pierrereb) - - Milos Colakovic (project2481) - - Raphael de Almeida (raphaeldealmeida) - - Mohammad Ali Sarbanha (sarbanha) - - Sergii Dolgushev (sergii-swds) - - Thomas Citharel (tcit) - - Alex Niedre - - evgkord - - Helmer Aaviksoo - - Roman Orlov - - Simon Ackermann - - Andreas Allacher - - VolCh - - Alexey Popkov - - Gijs Kunze - - Artyom Protaskin - - Steven Dubois - - Yurun - - ged15 - - Simon Asika - - Daan van Renterghem - - Raito Akehanareru (raito) - - Valmont Pehaut-Pietri (valmonzo) - - Bálint Szekeres - - amcastror - - Bram Van der Sype (brammm) - - Guile (guile) - - Mark Beech (jaybizzle) - - Julien Moulin (lizjulien) - - Mauro Foti (skler) - - Thibaut Arnoud (thibautarnoud) - - Yannick Warnier (ywarnier) - - Jörn Lang - - Kevin Decherf - - Paul LE CORRE - - Christian Weiske - - Maria Grazia Patteri - - dened - - muchafm - - Dmitry Korotovsky - - Michael van Tricht - - ReScO - - Tim Strehle - - Sébastien COURJEAN - - cay89 - - Sam Ward - - Hans N. Hjort - - Marko Vušak - - Walther Lalk - - Adam - - vltrof - - Ismo Vuorinen - - Markus Staab - - Valentin - - Gerard - - Sören Bernstein - - michael.kubovic - - devel - - Iain Cambridge - - Artem Lopata - - Viet Pham - - Alan Bondarchuk - - Pchol + - Signor Pedro + - Robin Kanters (anddarerobin) + - Jérémie Broutier + - Luis Galeas + - Bogdan Scordaliu + - Dominic Luidold + - Thomas Bibaut + - Wojciech Zimoń + - Nikita Sklyarov - Benjamin Ellis + - Evgeniy Koval + - Rodrigo Díez Villamuera (rodrigodiez) + - Adria Lopez (adlpz) + - Malaney J. Hill + - Frank Naegler + - jfcixmedia + - Artem (nexim) - Shamimul Alam + - xdavidwu + - Raphaël Droz + - François Poguet + - Nathaniel Catchpole + - Johan de Ruijter + - Tugba Celebioglu + - Matt Brunt + - Jon Cave - Cyril HERRERA + - szymek + - Justin Reherman (jreherman) + - Abdul.Mohsen B. A. A + - nerdgod - dropfen - RAHUL K JHA - - Andrey Chernykh - - Edvinas Klovas - - Drew Butler - - Peter Breuls - - Chansig - - Kevin EMO - - Tischoi - - Sergii Dolgushev (serhey) - - divinity76 - - Amin Hosseini (aminh) + - DaikiOnodera + - The Whole Life to Learn + - Antoine (antoinela_adveris) + - Pawel Szczepanek (pauluz) + - Sebastian Busch (sebu) + - Christian López Espínola (penyaskito) + - Anton Kroshilin + - sabruss + - SnakePin + - Bram Tweedegolf (bram_tweedegolf) + - Norman Soetbeer + - Dave Heineman (dheineman) + - Benjamin Franzke + - Pierre Tachoire + - Oleg Golovakhin (doc_tr) + - andreabreu98 + - Viktor Bajraktar (njutn95) + - Maxime PINEAU + - Igor Kokhlov (verdet) + - Kevin Herrera (kherge) + - matze + - Peter Trebaticky + - Nicolas Fabre (nfabre) + - Jiří Bok + - Chris Jones (leek) + - Alexis MARQUIS + - Florian Cellier + - shreyadenny + - Adam Elsodaney (archfizz) + - Dionysis Arvanitis + - Vitali Tsyrkin + - Gabriel Moreira + - Josef Cech + - Enrico Schultz + - Xavier RENAUDIN + - Johan Wilfer (johanwilfer) + - xaav + - Ruben Kruiswijk + - Cosmin-Romeo TANASE + - tuqqu + - Romain Jacquart (romainjacquart) + - Alex Vo (votanlean) + - hainey + - Arash Tabrizian (ghost098) - vdauchy - - Andreas Hasenack - - J Bruni - - vlakoff - - Anthony Tenneriello - - thib92 - - Yiorgos Kalligeros - - Rudolf Ratusiński - - Bertalan Attila - - Arek Bochinski - - Rafael Tovar - - AmsTaFF (amstaff) - - Simon Müller (boscho) - - Yannick Bensacq (cibou) - - Cyrille Bourgois (cyrilleb) - - Damien Vauchel (damien_vauchel) - - Dmitrii Fedorenko (dmifedorenko) - - Frédéric G. Marand (fgm) - - Freek Van der Herten (freekmurze) - - Luca Genuzio (genuzio) - - Ioana Hazsda (ioana-hazsda) - - Jan Marek (janmarek) - - Mark de Haan (markdehaan) - - Maxime Corteel (mcorteel) - - Mathieu MARCHOIS (mmar) - - Nei Rauni Santos (nrauni) - - Geoffrey Monte (numerogeek) - - Martijn Boers (plebian) - - Plamen Mishev (pmishev) - - fabi - - Rares Vlaseanu (raresvla) - - Trevor N. Suarez (rican7) - - Clément Bertillon (skigun) - - Ahmed HANNACHI (tiecoders) - - Rein Baarsma (solidwebcode) - - tante kinast (tante) - - Stephen Lewis (tehanomalousone) - - Vincent LEFORT (vlefort) - - Andrew Marcinkevičius (ifdattic) - - Dan Patrick (mdpatrick) - - Ben Gamra Housseine (hbgamra) - - Darryl Hein (xmmedia) - - Wim Molenberghs (wimm) - - David Christmann - - Walid BOUGHDIRI (walidboughdiri) - - Marcel Berteler - - sdkawata - - Frederik Schmitt - - Peter van Dommelen - - Tim van Densen - - Andrzej - - tomasz-kusy - - Rémi Blaise - - Nicolas Séverin - - patrickmaynard - - Houssem - - Joel Marcey - - zolikonta - - Daniel Bartoníček - - Grégory Pelletier (ip512) - - natechicago - - Julien Pauli - - Juan Miguel Besada Vidal (soutlink) - - Tomáš Votruba - - Ross Motley (rossmotley) - - Cedric BERTOLINI (alsciende) - - Lyubomir Grozdanov (lubo13) - - Grayson Koonce - - Simone Fumagalli (hpatoio) - - Peter Dietrich (xosofox) - - Brandon Antonio Lorenzo - - Rafał Muszyński (rafmus90) - - Thierry Marianne - - Brieuc Thomas - - Ole Rößner (basster) - - Jonny Schmid (schmidjon) - - Antonio Mansilla - - Johan - - Michael Simonson (mikes) - - Jordan de Laune (jdelaune) - - Michał Marcin Brzuchalski (brzuchal) - - César Suárez (csuarez) - - Thomas Dutrion (theocrite) - - Daniele Cesarini (ijanki) - - Silas Joisten (silasjoisten) - - uncaught - - Boris Medvedev - - Alexander Bauer (abauer) - - Nicolas ASSING (nicolasassing) - - Maksym Romanowski (maxromanovsky) - - Juan Luis (juanlugb) - - robin.de.croock - - Frankie Wittevrongel - - Ondřej Frei - - excelwebzone - - Martin Auswöger - - Vladimir Sadicov (xtech) - - Andrew Zhilin (zhil) - - Valentin Nazarov - - Guillaume Royer - - Arend Hummeling - - sabruss - - Knallcharge - - gndk - - Markus Tacker - - Fabian Steiner (fabstei) - - Arkadiusz Kondas (itcraftsmanpl) - - Alexander Kurilo (kamazee) - - Lars Ambrosius Wallenborn (larsborn) - - Malte Wunsch (maltewunsch) - - Matteo Giachino (matteosister) - - Thomas Baumgartner (shoplifter) - - Vladimir Chernyshev (volch) - - Oz (import) - - Felix Eymonot (hyanda) - - Stanislau Kviatkouski (7-zete-7) - - Christopher Georg (sky-chris) - - tamcy - - Yohann Tilotti - - Muhammad Aakash - - Anthony Moutte - - Adoni Pavlakis (adoni) - - Nicolas Le Goff (nlegoff) - - Tero Alén (tero) - - Daniel Londero (dlondero) - - Ryan Rogers - - Stephen - - aim8604 - - ZiYao54 - - Eric Stern - - Guillaume BRETOU (guiguiboy) - - Artiom - - Bruno BOUTAREL - - Jakub Simon - - Bernat Llibre Martín (bernatllibre) - - Zayan Goripov - - downace - - Robin Duval (robin-duval) - - Ivo - - pf - - elattariyassine - - Joris Garonian (grifx) - - Tito Miguel Costa (titomiguelcosta) - - goohib - - andrey-tech - - dinitrol - - Jérémy CROMBEZ (jeremy) - - mlievertz - - Benjamin Paap (benjaminpaap) - - Uladzimir Tsykun - - Fred Cox + - Dominik Hajduk (dominikalp) + - Marien Fressinaud + - Jesper Søndergaard Pedersen (zerrvox) + - Amaury Leroux de Lens (amo__) + - Kirill Lazarev + - Ivan Nemets + - Benhssaein Youssef + - gondo (gondo) + - Adrien Chinour + - eRIZ + - David Vancl + - Maxim Semkin + - Yoann MOROCUTTI + - Wim Godden (wimg) + - cgonzalez + - Mehdi Achour (machour) + - Alex Plekhanov + - Yorkie Chadwick (yorkie76) + - V1nicius00 + - Matteo Galli + - afaricamp + - Rudy Onfroy + - Thomas Chmielowiec + - Kélian Bousquet (kells) + - David Stone + - Waqas Ahmed + - Jorrit Schippers (jorrit) + - Karim Cassam Chenaï (ka) + - Denis Golubovskiy (bukashk0zzz) + - Fleuv + - Franz Liedke (franzliedke) + - Liverbool (liverbool) + - Ashura + - Götz Gottwald + - Piotr Zajac + - Nick Chiu + - Thanh Trần + - Gaylord Poillon (gaylord_p) + - Almog Baku (almogbaku) + - MightyBranch + - Rachid Hammaoui (makmaoui) + - Boris Grishenko (arczinosek) + - Ash014 + - Jérémy (libertjeremy) + - Alexandre Fiocre (demos77) + - drublic + - Patrik Patie Gmitter + - JuntaTom (juntatom) + - Serge (nfx) + - Geoffrey Pécro (gpekz) + - Andras Ratz + - Romain Dorgueil + - Karlos Presumido (oneko) + - Christopher Parotat + - Rafael Tovar + - Dennis Haarbrink + - Ahmed Shamim Hassan (me_shaon) + - oscartv + - JakeFr + - Oliver Klee + - Jules Lamur + - mark burdett + - mindaugasvcs - Ksaveras Šakys (xawiers) - Lin Clark - RevZer0 (rav) - - Yura Uvarov (zim32) + - JK Groupe + - Agustin Gomes + - Andreas Allacher + - Brad Treloar + - parhs + - jc + - Alexey Popkov + - soyuka + - dened + - Arnaud + - Marcel Siegert + - Gijs Kunze + - Antonio Mansilla + - Zan Baldwin (zanderbaldwin) + - BRAMILLE Sébastien (oktapodia) + - Vincent + - Jan Vernieuwe (vernija) + - maxime.perrimond + - Michael Dawart (mdawart) + - Vladimir Mantulo (mantulo) + - Wim Hendrikx + - Andrii Serdiuk (andreyserdjuk) + - PaoRuby + - Holger Lösken + - George Bateman + - riadh26 + - AntoineDly + - Damian Sromek + - Mark Ogilvie + - Jonathan Vollebregt + - Johannes Goslar + - allison guilhem + - Troy Crawford + - Arend-Jan Tetteroo - Dan Finnie - - Nerijus Arlauskas (nercury) - - Clément - Philipp Kretzschmar - - Jairo Pastor + - Rafał Toboła + - Dominik Schwind (dominikschwind) + - Stefano A. (stefano93) + - Léo VINCENT + - mlazovla + - Alejandro Diaz Torres + - SuRiKmAn + - Jimmy Leger (redpanda) + - Damien Harper (damien.harper) + - Konstantin Chigakov + - qsz + - devel + - Rémi Faivre (rfv) + - Radek Wionczek (rwionczek) + - Alexander Pasichnik (alex_brizzz) + - Martijn Boers (plebian) + - Pchol + - Florent SEVESTRE (aniki-taicho) + - Sylvain Lorinet + - Jan Eichhorn (exeu) + - Konstantinos Alexiou + - Mikkel Paulson + - moldcraft + - Juan Ases García (ases) + - Gerben Wijnja + - Siragusa (asiragusa) + - Bradley Zeggelaar - rtek - - Kévin Gomez (kevin) - - Sébastien HOUZÉ - - BrokenSourceCode - - Robert-Jan de Dreu - - simbera - - Peter Schultz - - Wissame MEKHILEF - - Mihai Stancu - - shreypuranik - - Koalabaerchen - - alex - - gedrox - - Pedro Magalhães (pmmaga) - - Ari Pringle (apringle) - - Dan Ordille (dordille) - - Juan M Martínez - - Matt Fields - - Lajos Veres (vlajos) - - toxxxa - - Kai Eichinger - - Antonio Angelino - - CarolienBEER - - Tammy D - - Kevin Frantz - - bokonet - - Sébastien Armand (khepin) - - Richard Henkenjohann (richardhj) - - 蝦米 - - klemens - - Lane Shukhov - - Dennis Jaschinski (d.jaschinski) - - Martin Eckhardt - - André Matthies - - ttomor - - Gavin (gavin-markup) - - Evgeny Ruban - - Florian Bogey - - Soha Jin - - Alexander Zogheb - - Rich Sage - - sualko - - koyolgecen - - James Mallison - - BT643 - - M.Wiesner - - Erdal G - - Daniel Siepmann - - Alaa AttyaMohamed (alaaattya) - - atmosf3ar - - aziz benmallouk (aziz403) - - Rob Meijer (robmeijer) - - Bruno Ferme Gasparin (bfgasparin) - - silver-dima - - Ldiro - - Nick Winfield - - Raphaël Geffroy - - Asma Drissi (adrissi) - - Egor Ushakov (erop) - - Janusz Slota (janusz.slota) - - Szymon Skowroński (skowi) - - Thomas Le Duc (viper) - - Artur Butov (vuras) - - Neal Brooks (nealio82) - - Fabian Spillner (fspillner) - - SirRFI - - Jérôme Poskin (moinax) - - z38 - - lacatoire - - Bill Israel - - Armen Mkrtchyan (iamtankist) - - RisingSunLight - - unknown - - Sam Korn - - Surfoo (surfoo) - - dcramble - - Anthony Rey (sydney_o9) - - Daniel Felix (danielfellix) - - Janosch Oltmanns (janosch_oltmanns) - - Christian - - Giuseppe Attardi - - Walter Nuñez - - Bart van Raaij (bartvanraaij) - - David Paz (davidmpaz) - - Markus Tacker - - Kim Wüstkamp (kimwuestkamp) - - tchap - - Benjamin Bourot - - Chris McMacken (chrism) - - Benjamin Lazarecki (benjaminlazarecki) - - matt smith (dr-matt-smith2) - - Kane Menicou (kane-menicou) - - Stéphane Paul BENTZ (spbentz) - - KaroDidi - - CJDennis - - Olivier Toussaint (cinquante) - - Raul C - - Cristi Contiu (cristi-contiu) - - Tim - - Marcel Korpel - - Yaroslav Yaremenko - - Justin Liiper (liiper) - - Al-Saleh KEITA - - Dan Michael O. Heggø (danmichaelo) - - Laurens Laman (laulaman) - - Joe Hans Robles Martínez (joebuntu) - - Florian Körner (koernerws) - - Agustín Pacheco Di Santi - - d.syph.3r - - Hyunmin Kim (kigguhholic) - - Alexis Urien (axi35) - - Marek Bartoš - - Markus Tacker - - Thomas P - - Jeroen - - Aymeric Mayeux (aymdev) - - Kamil Pešek (kamil_pesek) - - Nicolas Clavaud (nclavaud) - - Aaron Valandra - - Myystigri - - Guillaume Sarramegna - - Kristof (jockri) - - Jérémy Crapet - - Ahmed Lebbada (sidux) - - Alexis Lefebvre - - Alex Theobold - - Abdellah EL GHAILANI (aelghailani) - - Benjamin D. (benito103e) - - Mark Badolato (mbadolato) - - Tsimafei Charniauski (varloc2000) - - Sherin Bloemendaal - - laurent negre - - Beno!t POLASZEK - - Mario Martinez (chichibek) - - Florian Bastien (fbastien) - - Maik Penz - - Brooks Van Buren (brooksvb) - - Axel K. - - Ivan Yivoff - - wouthoekstra - - Paul Waring - - Brice Lalu (bricelalu) - - Alexandre Castelain (calex_92) - - Rafał Mnich (rafalmnich-msales) - - Andrei Karpilin (karpilin) - - Julien Dephix - - Mathieu - - Jade Xau - - Thomas Berends - - Nils Freigang (pueppiblue) - - Juan Manuel Fernandez (juanmf) - - Ben Glassman (bglassman) - - unknown - - Pierre Maraître (balamung) - - Kolyunya (kolyunya) - - Daniel Kesselberg (kesselb) - - MarcomTeam - - gitomato - - Thibault Pelloquin (thibault_pelloquin) - - Heaven31415 - - Pavel Máca - - Michael Sheakoski - - Patrick Bielen - - Emir Beganović (emirb) - - Tim Stamp - - Daniel Parejo Muñoz (xdaizu) - - Florian-B - - Guillaume Rossignol - - Marcin Sekalski - - Wouter J - - Kai Eichinger (kai_eichinger) - - Matthew Loberg (mloberg) - - xuni - - timothymctim - - tuanalumi - - ayacoo - - Kevin Lot - - Andrea Cristaudo - - Romain - - Jochem Klaver - - Aalaap Ghag (aalaap) - - Eric Poe (ericpoe) - - Giancarlos Salas (giansalex) - - Gauthier Gilles - - Julien Ferchaud (guns17) - - Pedro Junior (vjnrv) - - Max R (maxr) - - xamgreen - - Igor - - Michal Zuber - - Lyrkan - - Maxime Cornet (elysion) - - Arvydas K - - Chris Thompson (toot) - - Carl Schwan - - Vince (zhbzhb) - - Hamza Hanafi - - Bogdan Olteanu - - Nurlan Alekberov - - Jérôme Nadaud - - entering - - OИUЯd da silva - - Clément MICHELET (chiendelune) - - Erison silva (eerison) - - Sarim Khan (gittu) - - Jakub Szcześniak (jakubszczesniak) - - JohnyProkie (john_prokie) - - Krzysztof Daniel (krzysdan) - - Mitchel (mitch) - - Pierre Joube (pierrejoube) - - Zairig Imad - - Romain Biard (rbiard) - - Nik Spijkerman - - Luka Žitnik - - Eugene Wolfson - - Danielle Suurlant (dsuurlant) - - Julien Deniau (jdeniau) - - van truong PHAN (vantruongphan) - - Alex Luneburg - - MohamedElKadaoui - - iqfoundry - - Lauri - - Thomas Ploch - - Franklin LIA - - autiquet axel - - Florentin Garnier - - Alex Wybraniec - - Paweł Farys - - Carlton Dickson (carltondickson) - - Christopher Hoult (choult) - - Clemens Krack (ckrack) - - George Pogosyan (gp) - - Joshua (suabahasa) - - Jean-Baptiste Delhommeau (jbdelhommeau) - - Kristian Zondervan (krizon) - - Mathias Geat (maffibk) - - Alex Brims (outspaced) - - Joel Doyle (oylex) - - Pau Oliveras (poliveras) - - Shane Archer (sarcher) - - Leanna Pelham (leannapelham) - - Stefan Doorn (stefandoorn) - - M E (ttc) - - Christophe Deliens (cdeliens) - - Tony Tran (tony-tran) - - Alden Weddleton (wnedla) - - Patryk Miedziaszczyk - - Michael Lenahan - - Giacomo Moscardini - - Kris - - Dustin Meiner - - Arc Tod - - Max Schindler (chucky2305) - - Kai (kai_dederichs) - - SamanShafigh - - Andrii Mishchenko (krlove) - - KULDIP PIPALIYA (kuldipem) - - Taiwo A (tiwiex) - - Tobias Olry (tolry) - - Maxime Douailin - - Chris Taylor - - Andy Dawson - - Jason Grimes - - jonasarts - - Salah MEHARGA - - Marvin Hinz - - Jacek Jędrzejewski - - chapterjason - - mohamed - - rodmar35 - - Krzysztof Lament - - Euge Starr - - Steve Nebes - - jms85 - - M.Eng. René Schwarz - - Shawn Dellysse - - Steve - - Rico Neitzel - - Alessio Pierobon (alepsys) - - Andrey Bolonin - - robert Parker - - ampt . (ampt) - - Philippe Mine (dispositif) - - Favian Ioel Poputa (favianioel) - - Fernando Aguirre Larios (ingaguirrel) - - Javi H. Gil (javibilbo) - - Jean-Marie Lamodière (jmlamo) - - XitasoChris - - kenjis (kenjis) - - Kevin Archer (kevarch) - - Žilvinas Kuusas (kuusas) - - Mostefa Medjahed (mostefa) - - Andrianovah nirina randriamiamina (novah) - - Nicolas Potier (npotier) - - Ejamine - - moon-watcher - - Paweł Skotnicki (pskt) - - Andrey (quiss) - - Robert Saylor (rsaylor) - - Rubén Rubio Barrera (rubenrubiob) - - Rick van Laarhoven (rvanlaarhoven) - - Therage Kevin - - Saad Tazi (saadtazi) - - Sasha Matejic (smatejic) - - Yopai - - Souhail (souhail_5) - - Valentin Ferriere (choomz) - - JakeFr - - Rémi T'JAMPENS (tjamps) - - venu (venu) - - Nicolas Dievart (youri) - - Zaid Rashwani (zrashwani) - - authentictech - - Jordan Lev - - James (acidjames) - - Pierre Galvez (shafan_dev) - - Ulrich Völkel (udev) - - Nebojša Kamber - - Stepan Mednikov - - Uri Goldshtein - - Vyacheslav Pavlov - - Pierre de Soos - - Johnny Peck - - Mario Young - - Cangit - - TrueGit - - Tim Kuijsten - - Dennis Benkert - - Nicola Pietroluongo - - Charcosset Johnny - - Hmache Abdellah - - ABRAHAM Morgan - - Lucas Mlsna - - RickieL - - Xavier Laviron - - Severin J - - Julien (mewt) - - Alexander O'Neill - - Jürgen - - Bruno Vitorino - - Daniel Werner (powerdan) - - Lukáš Brzák (rapemer) - - adursun - - Alihasana SHAIKALAUDDEEN - - Darmen Amanbayev - - Leonel Machava - - javaDeveloperKid - - Syedi Hasan - - Tom Nguyen - - Yngve Høiseth - - dawidpierzchalski - - Steve Wasiura - - Muhammad Nasir Rahimi - - Rick Pastoor - - Gun5m0k3 - - Gilles Taupenas - - Brian Gallagher - - MarvinBlstrli - - Marichez Pierre (chtipepere) - - Danny Kopping (dannykopping) - - Krzysztof Lechowski (kshishkin) - - Andras Ratz (ghostika) - - Michael Sivolobov (astronomer) - - Quentin Stoeckel (chteuchteu) - - Rafael Gil (cybervoid) - - Cyril VERLOOP (cyrilverloop) - - Ivan Kosheliev (dfyz) - - Duane Gran (duanegran) - - Thomas Decaux (ebuildy) - - Fred Jiles (fredjiles) - - Glen Jaguin (gl3n) - - Joshua Dickerson (groundup) - - Julio (gugli100) - - Dan Finnie - - Yassine Fikri (yassinefikri) - - Hector Hurtarte (hectorh30) - - Oliver Forral (intrepion) - - Jack Delin (jackdelin) - - Jean-Luc MATHIEU (jls2933) - - Josh Taylor (josher) - - Kevin Robatel (kevinrob) - - Keefe Kwan (kkwan) - - Piotr Gołębiewski (loostro) - - Maxime Morlet (maxicom) - - Ana Cicconi - - Mohamed Ettaki TALBI (takman) - - Michał Kurcewicz (mkurc1) - - nencho nencho (nencho) - - pbijl (pbijl) - - Patrick Maynard - - rahul (rahul) - - bouffard (shinmen33) - - Kevin Carmody (skinofstars) - - Tomasz Tybulewicz (tybulewicz) - - Vlad Ghita (vghita) - - Ahmed El Moden - - Unlikenesses - - Ousmane NDIAYE - - Erlang Parasu (erlangparasu) - - Pieter Oliver - - Viacheslav Demianov (sdem) - - David ALLIX (weba2lix) - - Carlos Granados - - kirill-oficerov - - aliber4079 - - ptrm04 - - Jeroen Deviaene - - Marc Verney - - Goran Grbic (tpojka) - - Marcin Sękalski (senkal) - - Frédéric Planté - - Alexandr Podgorbunschih (apodgorbunschih) - - Thomas Kappel - - Charles EDOU NZE - - Daichi Kamemoto (yudoufu) - - Oliver Stark (oliver.stark) - - gnito-org - - Marc Verney - - alexmart - - Daniël Brekelmans - - Loïc Salanon - - Mathias STRASSER - - Navid Salehi (nvdsalehi) - - armin-github - - Jerome Gangneux - - Denis Brumann - - Daryl Gubler (dev88) - - Dorian Sarnowski (dorian) - - Viktor Linkin (adrenalinkin) - - Stephen Ostrow (isleshocky77) - - Thijs Feryn - - Ionut Enache - - Conrad Pankoff - - Stefan hr Berder - - Micheal Cottingham (micheal) - - Dylan Delobel (dylandelobel) - - Shiraz (zpine) - - Edgar Brunet - - Jeff Zohrab - - CvekCoding - - Philippe Milot - - Gilles Gauthier - - Eöras - - lacpandore - - Emilio de la Torre (emiliodelatorrea) - - Terje Bråten - - Marcin Muszynski - - Robin Delbaere (rdelbaere) - - Albert Moreno - - Moroine Bentefrit - - Romain Petit - - Fabien Bourigault - - Daniele D'Angeli (erlangb) - - mervinmcdougall - - Olivier Acmos (olivier_acmos) - - mccullagh - - technetium - - Dimitri Labouesse - - Tyler King - - Piotr Grabski-Gradziński (piotrgradzinski) - - Iqbal Malik (iqbal_malik89) - - Lucas CHERIFI (kasifi) - - hidde.wieringa - - Peter Bottenberg - - Sofien NAAS - - Freerich Bäthge (freerich) - - Lopton - - MarkPedron - - JhonnyL - - grelu - - Russell Flynn (rooster) - - Malte Blättermann - - Lander Vanderstraeten - - Florian Moser - - Éric - - Arnaud Lejosne - - larsborn - - Steve Clay (mrclay) - - Pierre Pélisset (ppelisset) - - Tarjei Huse (symfony_cloud) - - Damien Fayet - - Lucas Mlsna - - Philippe Gamache (philippegamache) - - Cyanat - - Terje Bråten - - Vincent Chareunphol (devoji) - - Francisco Corrales Morales - - Florian CAVASIN - - Nic Wortel (nicwortel) - - Masaharu Suizu - - Luděk Uiberlay (ne0) - - Dominic Luechinger - - jsarracco - - Shevelev Vladimir (shevelev_vladimir) - - LiVsI - - Jalen Muller (jalenwasjere) - - Marc Straube - - Louis-Arnaud - - Adam Prancz (praad) - - Hubert Moutot (youbs) - - Jan Grubenbecher - - Younes OUASSI (youassi) - - kolossa - - eric fernance (ericrobert) - - Alexandre Balmes (pocky) - - Aaron Baker - - SquareInnov - - dellamowica - - Caliendo Julien - - Damien Tournoud - - Eike Send - - Robin Brisa - - Kevin Boyd - - Raistlfiren - - Daniel Klein - - Bruce Phillips - - LICKEL Gaetan (cilaginept) - - Jacek (opcode) - - Baptiste Pizzighini (bpizzi) - - David D. (comxd) - - Tristan Pouliquen (tristanpouliquen) - - PululuK - - Jens Hassler - - Hylke - - Simon Schubert (simon-schubert) - - avanwieringen - - j00seph - - Ivan Nemets - - Benjamin Laugueux - - sgautier - - Kevin Mark - - Marijn Huizendveld - - Denis Brumann - - Alexandre GESLIN (rednaxe) - - Grzegorz Dembowski (gdembowski) - - Ramzi Abdelaziz (ramzi_a) - - PéCé - - Jess - - Matt Janssen - - Camille Jouan (ca-jou) - - Kerrial (kez) - - Lambert Beekhuis (lambertb) - - Nassim LOUNADI - - pamuche - - zuhair-naqvi - - Miguel Vilata (adder) - - Vladislav Lezhnev (livsi) - - Mark Smith (zfce) - - Michel Valdrighi (michelv) - - Martin Czerwinski - - Clayton - - Wojciech Sznapka - - Ludovic REUS - - David Desberg - - Adam Mikolaj (mausino) - - harcod - - cancelledbit - - Claude Ramseyer (phenix789) - - Gaurish Sharma - - Prathap - - sblaut - - Kirill Kotov - - BorodinDemid - - iamdto (iamdto) - - David Lumaye - - Pavel Shirmanov (genzo) - - Rodrigo Capilé (rcapile) - - Quentin Fahrner (renrhaf) - - James Isaac - - Pedro Piedade - - Edym Komlan BEDY (youngmustes) - - Xbird - - Milan Pavkovic - - Jonczyk - - Mbechezi Mlanawo - - Florimond Manca - - Ladislav Kubes - - bpiepiora - - Robert Brian Gottier - - Susheel Thapa - - Андрей - - Vincent Brouté - - Hugo Clergue - - Timo Tewes - - Dries Vints - - Piotr Stankowski - - Oliver Kossin - - Robert - - Alan Farquharson - - Bill Surgenor - - Pierre Arnissolle (arnissolle) - - Szilágyi Károly Bálint - - 6e0d0a - - Terence Eden - - Peter - - Mathias STRASSER - - Inori - - Artur - - ismail mezrani (imezrani) - - Luca Suriano (lucas05) - - michael schouman (metalmini) - - Hideki Okajima (okazy) - - Ronan Pozzi (treenity) - - Jeremiah Dodds - - Fabian Becker - - Tim Herlaud - - Michael Witten (micwit) - - r-ant-2468 - - Prisacari Dmitrii - - Stephen Clouse - - fguimier - - Mykola Martynov (mykola) - - Timo Haberkern (thaberkern) - - Damien DE SOUSA (dades) - - Valyaev Ilya (rumours86) - - Dan Barrett (yesdevnull) - - Robin C - - Wouter - - Mathieu Capdeville - - Florian VANHECKE - - Zombaya - - Tim Jabs - - JT Smith - - Rudy Onfroy - - Patrick PawseyVale - - Michaël Dieudonné - - Ilya Bakhlin - - analogic - - lucchese-pd - - Philippe Villiers - - LavaSlider - - Aikaterine Tsiboukas - - New To Vaux - - Guillermo Quinteros (guquinteros) - - Hex Titan (hextitan) - - Norio Suzuki (suzuki) - - Michael COULLERET (20uf) - - Tristan LE GACQUE (tristanlegacque) - - Jérémy Halin - - Scott - - fishbone1 - - lajosthiel - - pgorod - - E Ciotti - - Jeroen - - elescot - - vihuarar - - Tom Troyer - - Sébastien FUCHS - - Vilius Grigaliūnas - - Chloé B. - - Manuel Andreo Garcia - - cirrosol - - matthieudelmas - - Ahmed Abdou (ahmedaraby) - - Calin Pristavu (calinpristavu) - - Hatem Ben (hatemben) - - Robin Cawser (robcaw) - - Jorisros (jorisros) - - Michael Dwyer (kalifg) - - Mohamed YOUNES (medunes) - - Manuele Menozzi (mmenozzi) - - Robert Went (robwent) - - Greg (kl3sk) - - scottwarren - - Michael Klein (monbro) - - Christoph Wieseke - - Przemek Maszczynski - - Sam Hudson - - piet - - Petar Petković - - stormoPL - - Bartosz Tomczak - - A goazil - - Felix Stein - - Wojciech Kania - - Ian Gilfillan - - sakul95 - - R1n0x - - Stéphane P - - rogamoore - - Jorge Sepulveda - - Lauri - - Simon Appelt - - broiniac - - Peter Hauke - - Fabian Freiburg - - Léo PLANUS - - Hari K T (harikt) - - Michel Chowanski (migo) - - M#3 - - ymc-sise - - DKravtsov - - Alexandr Kalenyuk - - Andreas Schönefeldt - - Sorin Dumitrescu (sfdumi) - - artf - - Alireza Rahmani Khalili (alireza_rahmani) - - Maxim (big-shark) - - Dirk Luijk (dirkluijk) - - Adam Lee Conlin (hades200082) - - Petru Szemereczki (hktr92) - - Jan Heller (jahller) - - Tobias Berge - - Jérémie Samson (jsamson) - - Pascal de Vink (pascaldevink) - - A S M Sadiqul Islam (sadiq) - - Emil Santi (emilius) - - Darien - - Cédric Spalvieri (skwi) - - Damien Chedan (tcheud) - - Valter Carneiro da Silva Junior (valterjrdev) - - Gabriel Birke (chiborg) - - BETARI Amine (amine_ezpublish) - - Tyler Sommer (veonik) - - chance garcia - - Antonio de la Vega - - Archie Vasyatkin - - Brian - - Ben Thomas - - Grégory Quatannens (gscorpio) - - Corentin - - Jan Klan (janklan) - - Jonathan - - Peter Gasser - - Jorick - - Jamal Youssefi - - Volen Davidov - - CaDJoU - - Mohameth - - Dilantha Nanayakkara - - wazz42 - - Brendan - - Massimo Giagnoni (mgiagnoni) - - Michael Phillips - - Brandon Mueller (fatmuemoo) - - LEFLOCH Jean-François (katsenkatorz) - - Luuk Scholten (lscholten) - - Matt Trask (matthewtrask) - - Paul Rijke (parijke) - - Anthony FACHAUX - - Paul Ferrett (paulf) - - Ronan Guilloux (ronan) - - David Ward (roverwolf) - - helmi dridi - - Marco Woehr - - Ali Sunjaya - - iarro - - Clément Barbaza - - Alexander Diebler - - Tom Egan - - Peter - - Dean Clatworthy - - Zoltan Toth-Czifra - - Juan Riquelme - - Mike Zukowsky - - Quentin Boulard - - vmarquez - - Talita Kocjan Zager (paxyknox) - - Sander Bol - - Son Tung PHAM - - Volker Thiel - - Raggok - - Benoît - - marco-pm - - VladZernov - - Julien RAVIA - - Robert Nagy - - Angelo Melonas (angelomelonas) - - nasaralla - - Rosemary Orchard - - Bruno Baguette (tournesol) - - Jean Pasdeloup - - Fabrice GARES (fabrice_g) - - Oliver Kossin - - Ignacio Aguirre - - German Bortoli (germanaz0) - - Patrik Csak - - Julien BENOIT - - Jason Aller (jraller) - - Ka (Karim Cassam Chenaï) - - e-weimann - - Greg Somers - - Andrej Rypo - - Matthias Noback (mnoback) - - heddi.nabbisen - - Marius-Liviu Balan (liv_romania) - - Brent Shaffer (bshaffer) - - Exalyon - - Maciej Łebkowski (mlebkowski) - - Javad Adib - - Jonas Wouters - - Lee Jorgensen (profmoriarty) - - Julien Gidel - - Ivan Gantsev - - Richard Perez (riperez) - - Antonio Spinelli - - Ross Deane (rossdeane) - - Pavel Jurecka - - Joel Clermont (jclermont) - - Brandin Chiu - - Sébastien Rogier (srogier) - - Arnaud Pflieger - - Roy Templeman - - Tobias Schmidt (tobias-schmidt) - - ehibes - - Jean-Philippe Dépigny - - Christian Weyand (weyandch) - - Romaxx - - I. Fournier - - Daan van Renterghem - - Alex Coventry - - Ali Yousefi (aliyousefi) - - lbraconnier2 - - ghertko - - Francis Hilaire - - vgmaarten - - Godfrey Laswai - - Stefan Topfstedt - - Nathan Vonnahme - - Quentin Brunet - - Robert Freigang (robertfausk) - - faissaloux - - oyerli - - Guillaume Ponty - - Jan Pieper - - Chris Johnson - - Tommi - - b0nd0 - - andybeak - - Pierre-Jean Leger - - vindby23 - - Damien - - Florian Blond (fblond) - - Christophe Willemsen (kwattro) - - guidokritz - - sofany - - FindAPattern - - Tom Haskins-Vaughan - - Kevin R - - Lance Bailey - - Dorozhko Anton - - Jonathan Clark - - Giulio Lastra - - Ed Poulain - - wiese - - Nietono - - Mahdi Maghrooni - - Vimal Gorasiya - - Baptiste Langlade - - Gasmi Mohamed (mohamed_gasmi) - - Angelo Galleja (ga.n) - - TavoNiievez - - Michele Carino - - Gustavo Henrique Mascarenhas Machado - - jfhovinne - - Thomas from api.video - - guiditoito - - Francois CONTE - - Danny van Wijk (dannyvw) - - Rick Ogden - - Tomáš Tibenský - - Ivan Ternovtsiy - - Thomas Lemaire - - Adamo Crespi - - Christopher Vrooman - - de l'Hamaide - - xelan - - Henrik Christensen - - João Paulo Vieira da Silva - - rayrigam - - ipatiev - - Xavier Coureau - - George Zankevich - - David Frerich - - Kris - - Linas Merkevicius - - Peter Majmesku - - srich387 - - Giuseppe Petraroli - - IamBeginnerC - - Yassine Hadj messaoud - - Oliver THEBAULT - - Arnaud - - Thomas Talbot - - Aurélien Thieriot - - abarke - - Benjamin Dos Santos - - Christopher Cardea - - ackerman - - RiffFred - - Idziak - - Krzysztof Nizioł - - alex00ds - - Michaël Mordefroy - - cvdwel - - Rafael Torres - - Ruben Petrosjan - - Filip Telążka - - Edward Kim - - Markus Mauksch - - Marko Mijailovic - - Théophile Helleboid - chtitux - - Vladimir Jimenez - - Daniel Wendler - - Kacper Gunia - - Arne - - Julien Humbert - - Rob Gagnon - - Nebojša Kamber - - pfleu - - Pouyan Azari - - Claudio Zizza - - Casey Heagerty - - kraksoft - - Claudio Galdiolo - - runephilosof-abtion - - zeggel - - Erik Trapman - - nicofrand - - markspare - - decima - - PHAS Developer - - Jonathan Cox - - Andrii Volin (angy_v) - - Florian Cellier (kark) - - Vincent Jousse - - jerzy-dudzic - - Szymon Dudziak - - Mario Alberto - - Ali Zahedi (aliz9271) - - Michel ANTOINE (antoin_m) - - Roman Martinuk - - bram vogelaar (attachmentgenie) - - Baptiste Pottier (baptistepottier) - - Benoît WERY (benoitwery) - - Boolean Type (boolean_type) - - Boris Sondagh (botris) - - Mickaël Bourgier (chapa) - - Cliff Odijk (cmodijk) - - Colin DeCarlo (colindecarlo) - - Andrew Martynjuk (crayd) - - Doug Smith (dcsmith) - - Jan Schütze (dracoblue) - - Damian Zabawa (dz) - - Dmitriy Fishman (fishmandev) - - Georgiana Gligor (gbtekkie) - - oussama khachiai (geekdos) - - Gonzalo Alonso (gonzakpo) - - Daniel Kucharski (inspiran) - - Maxime Doutreluingne (maxdoutreluingne) - - Ashen one (berbadger) - - Jay Williams (jaywilliams) - - Jelmer Snoeck (jelmersnoeck) - - Jeroen v.d. Gulik (jeroen) - - Janne Vuori (jimzalabim) - - Kane Menicou (kane_menicou) - - Dmitry Kolesnikov (kastaneda) - - Tommy Quissens (quisse) - - Arnaud B (krevindiou) - - Loïc Sapone (loic_sapone) - - Kostas Loupasakis (loupax) - - Markus Thielen (mathielen) - - Mehmet Gökalp (mehgokalp) - - gertdepagter - - Cyril Krylatov - - Michal Landsman - - Oleksandr Savchenko (asavchenko) - - Michael Smith (michaelesmith) - - Ryszard Piotrowski (richardpi) - - Ludwig Ruderstaller (rufinus) - - Nuno Ferreira (nunojsferreira) - - Nuno Pereira (nunopereira) - - Oliver Davies (opdavies) - - ousmane NDIAYE (ousmane) - - Pierre-Yves Dick (pyrrah) - - Paulo Rodrigues Pinto (regularjack) - - Richard Perez (richardpq) - - Slaven (sbacelic) - - Urs Kobald (scopeli) - - Maximilian Ruta - - James Seconde (secondejk) - - Matthew Setter (settermjd) - - Stéphane HULARD (shulard) - - Simon Rolland (sim07) - - Simon Berton (simonberton11) - - Giovanni Gioffreda (tapeworm) - - Thierry Geindre (tgeindre) - - Daniel Ancuta (whisller) - - ameotoko - - Andrey Lukin (wtorsi) - - Yannick ROGER (yannickroger) - - Danilo Sanchi (danilo.sanchi) - - Markus Virtanen - - Sebastian Klaus - - Zamir Memmedov (zamir10) - - Eric Tucker - - Frank J. Gómez - - Alex Savkov - - Andy Truong - - Etilawin - - Pedro Cordeiro - - Michael Staatz - - Rick Burgess - - Christian Oellers - - Guilherme Donato - - NicolasPion - - Tomasz Ducin (tkoomzaaskz) - - Epskampie - - Joppe de Cuyper - - Jose R. Prieto - - Raphaël Riehl - - jakumi - - Vico Dambeck - - Christophe Boucaut - - yositani2002 - - Danny - - runawaycoin - - lusavuvu - - Raphael Michel - - Samuel Wicky - - Petr Kessler - - Florian Belhomme - - KosticDusan4D - - linuxprocess - - Jon Eastman - - François MARTIN - - Chris8934 - - Postal (postal) - - Peter WONG - - Robert Koller (robob4him) - - Mickaël Blondeau (mickael-blondeau) - - Hossein Vakili - - partulaj - - Rami Dridi - - Ahmed Bouras - - Martijn Zijlstra - - Vadim Bondarenko - - Justas Bieliauskas - - Aurélien MARTIN - - Kilian Schrenk - - Andreas Larssen - - Alex-D (alexd) - - saf (asd435) - - Benoît Durand (bdurand) - - Chase Noel (chasen) - - Roman (grn-it) - - Filip Grzonkowski (grzonu) - - Jason McCallister (jasonmccallister) - - Eugene Dounar - - Qiangjun Ran (jungle) - - michael kimsal (kimsal) - - Liang Jin Chao (leunggamciu) - - Vincent Terraillon (lou-terrailloune) - - Vladimir Schmidt (morgen) - - Linas Linartas (linas_linartas) - - Timur Murtukov (murtukov) - - Nikola Kuzmanović (nkuzman) - - Eirik Alfstad Johansen (nmeirik) - - Chabbert Philippe (philippechab) - - Konstantin (phrlog) - - Rodrigo Rigotti Mammano (rodrigorigotti) - - Yosip Curiel (snake77se) - - Stefan Grootscholten (stefan_grootscholten) - - Matthieu Braure (taliesin) - - Prakash Thapa (thapame) - - Arnaud VEBER (veberarnaud) - - Sarah-eit - - sebgarwood-gl - - Lacy (200ok) - - Serge Velikanov - - Richard Miller - - Christian Kolb (liplex) - - Thomas BILLARD - - Pascal MONTOYA (pmontoya) - - Julien EMMANUEL - - Dominik Pietrzak - - Jordan Bradford - - renepupil - - wadjeroudi - - Eliú Timaná - - Andrey Melnikov - - Vincent - - fb-erik - - Quentin Thiaucourt (quentint) - - Ala Eddine khefifi - - Cosmic Mac - - Thibaut Leneveu - - Oliver Adria - - Walkoss - - Andrey Tkachenko - - AntoineRoue - - Jules Lamur - - Virginia Meijer - - Jannik - - Pierre Spring - - Crushnaut - - Shaun Simmons (simshaun) - - andrecadete - - David Schmidt - - Cesare - - fernandokarpinski - - Jordi Freixa Serrabassa - - Kiel Goodman - - Constantin Ross - - sebpacz - - Josef Vitu - - Paul Coudeville - - Jarosław Jakubowski (egger1991) - - Paweł Małolepszy (pmalolepszy) - - Guillaume MOREL - - Émile PRÉVOT - - xavierkaitha94 - - obsirdian - - Mickael GOETZ - - Valentin GRAGLIA - - figaw - - ThamiSadouk - - Charly - - phiamo - - Gytis Šk - - Илья - - Arnaud Lemercier - - Anani Ananiev - - Egidijus Girčys (egircys) - - DerStoffel - - Marek Szymeczko - - clément larrieu - - Ante Crnogorac - - Mike Bissett - - Epari Siva Kumar - - Matthias - - Giovanni Toraldo - - Andreas - - Halil Özgür - - Christopher - - illusionOfParadise - - niebaron - - Works Chan - - jordanjix - - dearaujoj - - Valerio Colella - - Robert Treacy (robwasripped) - - David Harding - - mocrates - - Andrei Petre - - Art Matsak - - asartalo - - Kevin Wojniak - - Volodymyr Stelmakh - - Morf - - Jan Myszkier - - manseuk - - Philipp Bräutigam - - tikoutare - - Kanat Gailimov - - Micha Alt - - Grégory SURACI - - Paweł Farys - - Punt - - Rafa Couto - - Gabriel Theron - - Ian Mustafa - - Thierry Goettelmann - - Sven Luijten - - Brendan Lawton - - Nikita - - Luca Lorenzini - - wbob - - Evgeniy Gavrilov - - Al Bunch - - Clorr - - Daniele Ambrosino - - tobiasoort + - Aaron Scherer (aequasi) + - Dan Blows + - Brandon Kelly (brandonkelly) + - Choong Wei Tjeng (choonge) + - Marcin Kruk + - Nicolas Bastien (nicolas_bastien) + - Artyum Petrov + - Thomason, James + - Walter Dal Mut (wdalmut) + - abluchet + - youssef saoubou + - Kousuke Ebihara (co3k) + - bch36 + - Taras Girnyk + - wiseguy1394 + - adam-mospan + - Harry Wiseman + - ADmad + - Łukasz Giza (destroyer) + - Vladimir Sadicov (xtech) + - 2manypeople + - Ramon Kleiss (akathos) + - Bizley + - Felicitus + - dangkhoagms (dangkhoagms) + - Jesper Noordsij + - Thiago Melo + - Gleb Sidora + - Jovan Perovic (jperovic) + - Alexandre Beaujour + - Oriol Mangas Abellan (oriolman) + - Joao Paulo V Martins (jpjoao) + - Carsten Eilers (fnc) + - Sébastien HOUZÉ + - Sebastian Landwehr (dword123) + - Adel ELHAIBA (eadel) + - Damián Nohales (eagleoneraptor) + - Sorin Gitlan (forapathy) + - Gerry Vandermaesen (gerryvdm) + - Per Sandström (per) + - Ionut Cioflan + - Yannick + - Adam Katz + - Julius Beckmann (h4cc) + - Adrien Samson (adriensamson) + - Hubert Moreau (hmoreau) + - Mantas Urnieža + - Lars Ambrosius Wallenborn (larsborn) + - Elliot Anderson (elliot) + - Bjorn Twachtmann (dotbjorn) + - timaschew + - Pablo Maria Martelletti (pmartelletti) + - temperatur + - Chris Tiearney + - Pierre Tondereau + - Wouter de Wild + - ElisDN + - Joe + - BilgeXA + - Roma (memphys) + - Yohan Giarelli (frequence-web) + - Gil Hadad + - Samy D (dinduks) + - Piers Warmers + - BrokenSourceCode + - llupa + - Patrick Daley (padrig) + - Phillip Look (plook) + - Oksana Kozlova (oksanakozlova) + - Emirald Mateli + - Julien JANVIER (jjanvier) + - Marcello Mönkemeyer (marcello-moenkemeyer) + - Rodolfo Ruiz + - Valery Maslov (coderberg) + - Darius Leskauskas (darles) + - Stefan Moonen + - Benedict Massolle (bemas) + - Guido Donnari + - Cedric BERTOLINI (alsciende) + - Sander van der Vlugt (stranding) + - iamvar + - Markus Baumer + - Jérôme Dumas + - Georgi Georgiev + - otsch + - Christophe Meneses (c77men) + - Jeremy David (jeremy.david) + - Maria Grazia Patteri + - muchafm + - Michael van Tricht + - Ronny (big-r) + - detinkin + - Loenix + - tourze + - Ahmed Abdulrahman + - Penny Leach + - Dan Wilga + - zorn + - Joris Garonian (grifx) + - Samuel Vogel (samuelvogel) + - Osayawe Ogbemudia Terry (terdia) + - Ferenczi Krisztian (fchris82) + - Guillaume Smolders (guillaumesmo) + - Benjamin Paap (benjaminpaap) + - Thomas Chmielowiec (chmielot) + - PatrickRedStar + - Jairo Pastor + - Fabian Kropfhamer (fabiank) + - Martin Pärtel + - Ulrik McArdle + - Hugo Sales + - G.R.Dalenoort + - Mike Francis + - Ivo Valchev + - Oxan van Leeuwen + - Michal Čihař + - Rosio (ben-rosio) + - Marie Minasyan (marie.minassyan) + - Anton Sukhachev (mrsuh) + - Antanas Arvasevicius + - Maxwell Vandervelde + - Kevin Mian Kraiker + - Peter Simoncic + - Wojciech Gorczyca + - Ahmad Al-Naib + - Vladislav Iurciuc + - ging-dev + - Maerlyn + - Neagu Cristian-Doru (cristian-neagu) + - Mathieu Morlon (glutamatt) + - DerManoMann + - Tyler Stroud + - Clemens Krack + - Adam Kiss + - scourgen hung (scourgen) + - Sander Coolen (scoolen) + - Jontsa + - Ángel Guzmán Maeso (shakaran) + - Victor Prudhomme + - Tomasz Szymczyk (karion) + - Nikos Charalampidis + - Caligone + - Peter Jaap Blaakmeer + - ibasaw + - Alexander Menk + - Philippe Degeeter (pdegeeter) + - Gerard Berengue Llobera (bere) + - Charly Goblet (_mocodo) + - Quique Porta (quiqueporta) + - Robert Korulczyk + - Bruno Baguette + - nyro (nyro) + - Peter Schultz + - Wissame MEKHILEF + - Mihai Stancu + - Koalabaerchen + - René Kerner + - Michael Olšavský + - Antanas Arvasevicius + - Eddie Abou-Jaoude (eddiejaoude) + - hjkl + - dlorek + - Jeroen De Dauw (jeroendedauw) + - Ivan Nemets + - Lukas Kaltenbach + - Remi Collet + - Benjamin RICHARD + - Zdeněk Drahoš + - Dariusz Czech + - fabios + - Maksym Romanowski (maxromanovsky) + - ReScO + - Ole Rößner (basster) + - brian978 + - Stelian Mocanita (stelian) + - Wing + - Javier Núñez Berrocoso (javiernuber) + - Eddy + - Chris Maiden (matason) + - Daniel Basten (axhm3a) + - omerida + - Rini Misini + - Maxime THIRY + - Victor + - tpetry + - Mikhail Prosalov (mprosalov) + - Mephistofeles + - Oleh Korneliuk + - everyx + - Richard Heine + - Frank Neff (fneff) + - Yann LUCAS (drixs6o9) + - Vasily Khayrulin (sirian) + - Povilas S. (povilas) + - Paweł Tomulik + - Eric J. Duran + - Anatol Belski + - Mahmoud Mostafa (mahmoud) + - Ben Oman + - Jay Severson + - Ramazan APAYDIN (rapaydin) + - Htun Htun Htet (ryanhhh91) + - Denis Yuzhanin + - wesign (inscrutable01) + - j0k (j0k) + - JG (jege) + - Farhad Hedayatifard + - Shaun Simmons + - PierreRebeilleau + - Sergii Dolgushev (serhey) + - Sebastian Schwarz + - Foxprodev + - Artfaith + - VAN DER PUTTE Guillaume (guillaume_vdp) + - Guillaume Gammelin + - Wolfgang Klinger (wolfgangklingerplan2net) + - Jeffrey Moelands (jeffreymoelands) + - Giovanni Albero (johntree) + - Nasim + - Tadcka + - Bárbara Luz + - Bastien Picharles + - Randel Palu + - Clément LEFEBVRE (nemoneph) + - Patrick Carlo-Hickman + - Timon van der Vorm + - Shude + - Vladislav Krupenkin (ideea) + - Pablo Schläpfer + - Erik van Wingerden + - adnen chouibi + - Vladimir Pakhomchik + - Mickael Perraud + - Alex Silcock + - Frédéric Bouchery (fbouchery) + - Raphael Hardt + - Kurt Thiemann + - Linnaea Von Lavia + - Qingshan Luo + - Arrakis (arrakis) + - Andrey Helldar + - Danil Khaliullin (bifidokk) + - Saif Eddin G + - Michał Marcin Brzuchalski (brzuchal) + - Thomas Dubuffet (thomasdubuffet) + - Dominik Ritter (dritter) + - Paul Andrieux + - Ralf Kühnel (ralfkuehnel) + - Adam Prickett + - Luke Towers + - Alexandre Melard + - Brandon Antonio Lorenzo + - Nicolas + - Alex Demchenko + - Fabien + - Sergio Santoro + - Michael Simonson (mikes) + - Samuel Gordalina (gordalina) + - Bogdan + - Keith Maika + - Bram Van der Sype (brammm) + - Norbert Schultheisz + - Ross Motley (rossmotley) + - Jérôme Nadaud (jnadaud) + - Robert Meijers + - Thomas Beaujean + - František Maša + - Asil Barkin Elik (asilelik) + - alsar + - Nacho Martin (nacmartin) + - Miłosz Guglas (miloszowi) + - Rubén Calvo (rubencm) + - Bhujagendra Ishaya + - dinitrol + - Jens Hatlak + - Giorgio Premi + - Jos Elstgeest + - Artyom Protaskin + - Daniel Kozák + - Urban Suppiger + - Mikko Ala-Fossi + - Dawid Sajdak + - RENAUDIN Xavier (xorrox) + - alireza + - PLAZANET Pierre (pedrotroller) + - Daan van Renterghem + - Raito Akehanareru (raito) + - Valmont Pehaut-Pietri (valmonzo) + - misterx + - Ivo Valchev + - Michael Steininger + - Masao Maeda (brtriver) + - Maxime AILLOUD (mailloud) + - Eric Krona + - Alex Teterin (errogaht) + - Sam Williams + - tirnanog06 + - Evgeny Z (meze) + - George Dietrich + - Benjamin Laugueux + - Stephen + - Stefan Kruppa + - Petr Jaroš (petajaros) + - Dylan + - ghazy ben ahmed + - Anton Dyshkant + - Michael Nelson + - gr8b + - Paul LE CORRE + - Yiorgos Kalligeros + - max + - ureimers + - akimsko + - Youpie + - Moritz Kraft (userfriendly) + - Daniel Tiringer + - Javier Ledezma + - Steven Dubois + - Michel Bardelmeijer + - guangwu + - Ben Johnson + - Joas Schilling + - Bruno Rodrigues de Araujo (brunosinister) + - Martins Eglitis + - Grégoire Rabasse + - Cas van Dongen + - David Christmann + - stloyd + - Joel Lusavuvu (enigma97) + - Morimoto Ryosuke + - Mbechezi Nawo + - Moza Bogdan (bogdan_moza) + - Artem Lopata + - dantleech + - Andreas Allacher + - VolCh + - Clement Herreman (clemherreman) + - Aleksei Lebedev + - Roy-Orbison + - George Sparrow + - Chris Tickner + - Chris + - Farid Jalilov + - Christiaan Wiesenekker + - Evgeny (disparity) + - Jeremy Benoist + - Marko Vušak + - Igor Timoshenko (igor.timoshenko) + - Hryhorii Hrebiniuk + - Pierre-Emmanuel CAPEL + - Konstantin S. M. Möllers (ksmmoellers) + - Jordan de Laune (jdelaune) + - Wim Molenberghs (wimm) + - Zachary Tong (polyfractal) + - Boris Medvedev + - Radosław Kowalewski + - Hadrien Cren (hcren) + - Ha Phan (haphan) + - Daniel González Zaballos (dem3trio) + - Florian Morello + - Denis Klementjev (dklementjev) + - Ahmed Abdou + - Kirk Madera + - Andrey Chernykh + - Markus Reinhold + - AmsTaFF (amstaff) + - Pawel Smolinski + - EXT - THERAGE Kevin + - Ashura + - Martin Mayer (martin) + - Renan Taranto (renan-taranto) + - Victor Macko (victor_m) + - Wojciech Skorodecki + - Evert Jan Hakvoort + - Filippos Karailanidis + - Philipp Hoffmann (philipphoffmann) + - zcodes + - László GÖRÖG + - Nicolas Appriou + - alexpods + - Piergiuseppe Longo + - Nicolas Lemoine + - Christian Jul Jensen + - Michal Kurzeja (mkurzeja) + - Sergei Gorjunov + - victor-prdh + - Romain Pierre + - Dmitry Korotovsky + - Guile (guile) + - Wang Jingyu + - Mark Beech (jaybizzle) + - Vladislav Nikolayev (luxemate) + - Cristobal Dabed + - Patrick Kaufmann + - Gusakov Nikita (hell0w0rd) + - Andy Raines + - Aleksey Prilipko + - Dan Brown + - Marc Jauvin + - Halil Hakan Karabay (hhkrby) + - Jaap van Otterdijk (jaapio) + - Walid BOUGHDIRI (walidboughdiri) + - Frederik Schmitt + - Joseph Deray + - mohammadreza honarkhah + - Ondřej Mirtes (mirtes) + - Nardberjean + - Nick Stemerdink + - linh + - Muriel (metalmumu) + - Xavier HAUSHERR + - Nicolas Schwartz (nicoschwartz) + - Simon Mönch + - Ludek Stepan + - Sergio + - Benjamin BOUDIER + - Bernd Matzner (bmatzner) + - Jelle Kapitein + - František Bereň + - Dmitriy Derepko + - Eduard Bulava (nonanerz) + - dantleech + - Marco Jantke + - Maks Rafalko (bornfree) + - Baptiste Leduc (bleduc) + - Tim Jabs (rubinum) + - LubenZA + - enomotodev + - CDR + - Joan Cruz + - Dale.Nash + - Jozef Môstka (mostkaj) + - botbotbot + - none (nelexa) + - Thomas Decaux + - florian-michael-mast + - Nicolas Tallefourtané (nicolab) + - Ph3nol + - simbera + - Ramon Ornelas (ramonornela) + - helmi + - Alessio Baglio (ioalessio) + - djama + - SOEDJEDE Felix (fsoedjede) + - avi123 + - Daniel Perez Pinazo (pitiflautico) + - Alexey Berezuev + - AlbinoDrought + - Vladimir Khramtsov (chrome) + - Wojciech Błoszyk (wbloszyk) + - Jure (zamzung) + - Dan Harper + - Juga Paazmaya + - Alexandre Segura + - Yura Uvarov (zim32) + - Charly Terrier (charlypoppins) + - sdkawata + - Lorenzo Adinolfi (loru88) + - Atthaphon Urairat + - d-ph + - David Wolter (davewww) + - Carlos Ortega Huetos + - Nicolas Martin (cocorambo) + - Tomaz Ahlin + - creiner + - Sebastian Drewer-Gutland (sdg) + - Bert Hekman + - Marc Lemay (flug) + - Peter van Dommelen + - Richard Trebichavský + - MARYNICH Mikhail (mmarynich-ext) + - Paul Mitchum (paul-m) + - Gabriel Solomon (gabrielsolomon) + - Marcin Nowak + - Noel Light-Hilary + - Ian Phillips + - Jelle Bekker (jbekker) + - Sébastien Lévêque (legenyes) + - Michał Strzelecki + - Christian Grasso (chris54721) + - Marcin Szepczynski (szepczynski) + - Gina Peter Banyard + - Miloš Milutinović + - Myke79 + - Kris Kelly + - Kévin + - Alexis MARQUIS + - inwebo veritas (inwebo) + - wesleyh + - Mark van den Berg + - Dennis Jaschinski (d.jaschinski) + - Michael Hudson-Doyle + - Guillaume Aveline + - Nathanaël Martel (nathanaelmartel) + - Felix Marezki + - Evgeny Efimov (edefimov) + - Oleksii Svitiashchuk + - Adiel Cristo (arcristo) + - Matěj Humpál + - Nico Hiort af Ornäs + - Nguyen Tuan Minh (tuanminhgp) + - Michael Schneider + - n-aleha + - Alexander Cheprasov + - Alexandre Segura + - Jason Stephens + - Martin Schophaus (m_schophaus_adcada) + - Tijs Verkoyen + - Ivo + - Karl Shea + - Adam Wójs (awojs) + - eminjk + - Vivien + - Tournoud (damientournoud) + - Marcos Labad + - Per Modin + - Javier + - patrickmaynard + - Houssem + - Şəhriyar İmanov (shehriyari) + - Pascal Hofmann + - smokeybear87 + - Wahyu Kristianto (kristories) + - Benoit Leveque + - Benjamin Bender + - sauliusnord + - Erwan Nader (ernadoo) + - Anton Babenko (antonbabenko) + - Even André Fiskvik + - Maarten Nusteling (nusje2000) + - Gordienko Vladislav + - Sobhan Sharifi (50bhan) + - Vaidas Lažauskas + - Felipy Amorim (felipyamorim) + - ssilatel + - Simone Ruggieri + - wusuopu + - Peter Smeets (darkspartan) + - caalholm + - Kevin EMO + - karstennilsen + - Pavinthan + - Alain Flaus (halundra) + - Mihail Krasilnikov (krasilnikovm) + - Bart Wach + - Andrejs Leonovs + - Martijn Evers + - Pedro Magalhães (pmmaga) + - Nikola Svitlica (thecelavi) + - Alfonso Fernández García + - phc + - craigmarvelley + - Franz Wilding (killerpoke) + - Amin Hosseini (aminh) + - gr1ev0us + - Mateusz Lerczak + - Nicolas Pion + - Ariful Alam + - Florent Olivaud + - Mateusz Żyła (plotkabytes) + - Ismail Özgün Turan (dadeather) + - Foxprodev + - Jan Pintr + - Matthew (mattvick) + - gedrox + - dima-gr + - Kai Eichinger + - CarolienBEER + - Vincent Chalnot + - Denis Kop + - inspiran + - Alessandro Tagliapietra (alex88) + - Fabian Steiner (fabstei) + - gndk + - Uladzimir Tsykun + - Agata + - Adrien Gallou (agallou) + - Dario Guarracino + - Nerijus Arlauskas (nercury) + - Clément + - Jonas Claes + - AnrDaemon + - sam-bee + - Eric Hertwig + - Niels Robin-Aubertin + - Jorge Vahldick (jvahldick) + - Ryan Rogers + - Danijel Obradović + - Martin Auswöger + - Christian Morgan + - Anne-Sophie Bachelard + - Julien Sanchez (sumbobyboys) + - Simon Sargeant + - Edwin + - Víctor Mateo (victormateo) + - Vincent MOULENE (vints24) + - ChS + - robin.de.croock + - Michael Tibben + - Ahmad Mayahi (ahmadmayahi) + - johnstevenson + - Mohamed Karnichi (amiral) + - Julien Boudry + - Michael Hüneburg + - Jeroen de Boer + - Matthew J Mucklo + - Jannik Zschiesche + - Дмитрий Пацура + - Matthias Larisch + - Lance Chen + - Nicolas Attard (nicolasattard) + - Robert-Jan de Dreu + - ddebree + - Phobetor + - Eric Schildkamp + - Francois Martin + - HADJEDJ Vincent (hadjedjvincent) + - Karolis + - Jiri Korenek + - d.huethorst + - Lin Lu + - dsech + - Daniel Mecke (daniel_mecke) + - Ilya Chekalsky + - Pierre Dudoret + - Thomas + - Philipp Strube + - Michal Trojanowski + - Frank Schulze (xit) + - Artiom + - Skorney + - Cedric Kastner (nurtext) + - Antoine Bellion (abellion) + - Arnau González + - Benjamin Schultz (bschultz) + - Gerd Christian Kunze (derdu) + - 蝦米 + - klemens + - César Suárez (csuarez) + - Bert ter Heide (bertterheide) + - efeen + - Lane Shukhov + - Krzysztof Przybyszewski (kprzybyszewski) + - Matt Fields + - Lajos Veres (vlajos) + - toxxxa + - Stefan Graupner (efrane) + - Nsbx + - Amine Matmati + - patrick-mcdougle + - Pedro Silva + - Cyrille Bourgois (cyrilleb) + - Damien Vauchel (damien_vauchel) + - Eric Grimois + - Christian Schiffler + - Jan Christoph Beyer + - Muhammed Akbulut + - Nathanael d. Noblet + - root + - Ulrik Nielsen (mrbase) + - Ivan Tse + - Nicolas Macherey + - Ari Pringle (apringle) + - chillbram + - Will Rowe + - Andrii Boiko + - Dilek Erkut + - Harold Iedema + - Janusz Mocek + - Mostafa + - ergiegonzaga + - Mas Iting + - Nicolas Jourdan (nicolasjc) + - Serhii Polishchuk (spolischook) + - Orestis + - Flohw + - Evgeniy Tetenchuk + - Claude Dioudonnat + - MatTheCat + - Tim Porter + - Jérémy CROMBEZ (jeremy) + - Tomas Javaisis + - Thomas Ferney (thomasf) + - Ken Stanley + - vladyslavstartsev + - Tim Lieberman + - Paulius Jarmalavičius (pjarmalavicius) + - Jorge Martin (jorgemartind) + - Kubicki Kamil (kubik) + - Max Beutel + - benatespina (benatespina) + - Yohann Tilotti + - Oscar Esteve (oesteve) + - Romain + - Dave Long + - bill moll + - Marco Pfeiffer + - Milos Colakovic (project2481) + - Raphael de Almeida (raphaeldealmeida) + - Laurent Negre (raulnet) + - Adriaan Zonnenberg + - Brian Corrigan + - Mohammad Ali Sarbanha (sarbanha) + - GagnarTest (gagnartest) + - Zayan Goripov + - Martin Eckhardt + - André Matthies + - ttomor + - Gavin (gavin-markup) + - Evgeny Ruban + - Florian Bogey + - Soha Jin + - Alexander Zogheb + - Rich Sage + - sualko + - koyolgecen + - Rares Sebastian Moldovan (raresmldvn) + - Dan Ordille (dordille) + - Juan M Martínez + - Tammy D + - Kevin Frantz + - bokonet + - Sébastien Armand (khepin) + - Alex Carol (picard89) + - Igor Tarasov (polosatus) + - Matt Wells + - RTUnreal + - Helmer Aaviksoo + - Richard Hodgson + - Jeroen van den Nieuwenhuisen + - Dmitrii Fedorenko (dmifedorenko) + - Luca Genuzio (genuzio) + - Raphaëll Roussel + - Andreas Hasenack + - Oleg Krasavin (okwinza) + - Ismail Turan + - Yurii K + - Markkus Millend + - Gilles Doge (gido) + - Illia Antypenko (aivus) + - Kajetan Kołtuniak (kajtii) + - Serhii Smirnov + - Robert Queck + - gitlost + - Silvio Ginter + - ryunosuke + - Gilbertsoft + - Lyubomir Grozdanov (lubo13) + - Maksym Pustynnikov (pustynnikov) + - Markus Thielen + - Florian Heller + - Ronny López (ronnylt) + - Greg Korba + - Grayson Koonce + - Vladimir Melnik + - Sergii Dolgushev (sergii-swds) + - Thomas Citharel (tcit) + - Alex Niedre + - evgkord + - Valentin VALCIU + - Sortex + - julien.galenski + - Flo Gleixner (redflo) + - Jānis Lukss + - Haritz Iturbe (hizai) + - alefranz + - David Barratt + - Alan Bondarchuk + - Andrea Giannantonio + - Pavel.Batanov + - Michael Zangerle + - rkerner + - andersmateusz + - Laurent Moreau + - Marc J. Schmidt (marcjs) + - Prasetyo Wicaksono (jowy) + - Rainrider + - Chihiro Adachi (chihiro-adachi) + - Clément R. (clemrwan) + - j.schmitt + - Maximilian Berghoff (electricmaxxx) + - shreypuranik + - Edvinas Klovas + - Ondřej Führer + - kernig + - shdev + - Drew Butler + - Denys Voronin (hurricane) + - sensio + - Julien Menth (cfjulien) + - Nicolas Sauveur (baishu) + - pritasil + - Stephen Clouse + - e-ivanov + - Sven Scholz + - Peter Gribanov + - Yewhen Khoptynskyi (khoptynskyi) + - Johannes Müller (johmue) + - Juan Gonzalez Montes (juanwilde) + - Nicolas ASSING (nicolasassing) + - AUDUL + - Steve Hyde + - AbdelatifAitBara + - Antonio Angelino + - Florian Caron (shalalalala) + - Robert Kopera + - Jérémy Jourdin (jjk801) + - m.chwedziak + - Marion Hurteau (marionleherisson) + - roog + - abulford + - Daniel Rotter (danrot) + - jprivet-dev + - gechetspr + - Sergey Yuferev + - David Grüner (vworldat) + - Monet Emilien + - Adrien Peyre (adpeyre) + - Timothy Anido (xanido) + - gauss + - twifty + - Tiago Garcia (tiagojsag) + - Pavel Prischepa + - Eviljeks + - Markus Staab + - Peter Potrowl + - Jonathan Hedstrom + - Billie Thompson + - Andreas Kleemann (andesk) + - Marin Nicolae + - ged15 + - Philip Dahlstrøm + - Pierre Schmitz + - Kevin Vergauwen (innocenzo) + - Eugene Babushkin (warl) + - Wouter Sioen (wouter_sioen) + - Tadas Gliaubicas (tadcka) + - lerminou + - Vadim Tyukov (vatson) + - Daniel Kay (danielkay-cp) + - LHommet Nicolas (nicolaslh) + - Jenne van der Meer + - Ryan Linnit + - Goran Juric + - Alexey Buyanow (alexbuyanow) + - Cayetano Soriano Gallego (neoshadybeat) + - Luís Cobucci (lcobucci) + - Edwin Hageman + - dasmfm + - Nilmar Sanchez Muguercia + - Damien Fayet (rainst0rm) + - Dalibor Karlović + - Antonio Peric-Mazar (antonioperic) + - Nicolas Valverde + - Sagrario Meneses + - dbrekelmans + - Ramon Cuñat + - mboultoureau + - Ivan Yivoff + - Icode4Food (icode4food) + - Aurélien MARTIN + - Christoph Vincent Schaefer (cvschaefer) + - Luis Ramón López López (lrlopez) + - Sjors Ottjes + - David Ronchaud + - Tomáš Votruba + - Philipp Fritsche + - Matt Daum (daum) + - Léon Gersen + - Sandro Hopf (senaria) + - Benjamin Long + - Hallison Boaventura (hallisonboaventura) + - Fabio Panaccione + - André Filipe Gonçalves Neves (seven) + - Schuyler Jager (sjager) + - Dario Savella + - maxperei + - Zoran Makrevski (zmakrevski) + - Kirill Nesmeyanov (serafim) + - Vlad Dumitrache + - Xavier Amado (xamado) + - Bálint Szekeres + - Yoann MOROCUTTI + - NIRAV MUKUNDBHAI PATEL (niravpatel919) + - Adrien + - Mimi + - Arend Hummeling (arend) + - Leevi Graham + - Axel Barlet + - ahmetkun + - Victor DITTIERE (fuzip) + - Maksym Hubar (nrgone) + - Masaharu Suizu + - Luděk Uiberlay (ne0) + - Dominic Luechinger + - jsarracco + - Joppe de Cuyper + - yositani2002 + - David D. (comxd) + - Tristan Pouliquen (tristanpouliquen) + - Tim Herlaud + - Markus Tacker + - Marek Nocoń + - Wagner Nicolas (n1c01a5) + - Kevin T'Syen (noscope) + - Paweł Tekliński + - Marcus Stöhr + - Fabien Schurter + - Alexander Vorobiev (avorobiev) + - Vladyslav Riabchenko + - Aldo Zarza (azarzag) + - Jean-François Lépine (halleck45) + - Maarten de Keizer (maartendekeizer) + - Alexandre Gérault (alexandre-gerault) - Tymoteusz Motylewski - fdarre - - Zenobius - - Mbechezi Mlanawo - - David McKay - - ipf - - Andrii Sukhoi - - Cory Becker - - Florian Moser - - Kolja Zuelsdorf - - MWJeff - - Andrius Ulinskas (andriusulins) - - Nico - - kruglikov - - Kevin Raynel - - DanielEScherzer - - Jay-Way - - Felipe Martins - - Lee Boynton - - Jeremy Emery - - beejaz - - tmihalik - - Steve Winter - - pcky - - Parthasarathi GK - - m_hikage - - norfil - - adreeun - - Giulio De Donato - - Sylvain Lelièvre - - Michaël Perrin - - Chris Halbert - - temenb - - Luc - - damienleduc - - Carwyn Moore - - Nico Schoenmaker + - Григорий + - Zéfyx + - CaDJoU + - Julien Gidel + - Ivan Gantsev + - mervinmcdougall + - Jordan Aubert (jordanaubert) + - Danny Witting + - morrsky + - Nathan Vonnahme + - Nelson da Costa + - Jens Hassler + - Hylke + - Simon Schubert (simon-schubert) + - j00seph + - Ivan Nemets - Kevin - - GiveMeAllYourCats - - Matthew Thomas - - wkania - - EtienneHosman - - Matt Kirwan - - Daniel Kozák - - z38 - - Bartek Nowotarski - - mimol91 - - Daniel Santana - - Marius Balčytis - - Rick West - - Richard Hoar - - Reza - - Slobodan Stanic - - Alex Salguero - - manoakys - - Roberto Lombi - - Łukasz Korczewski - - rklaver - - Joe Thielen - - marcusesa - - Pierre Trollé - - Daniele Orler - - Cyril Mouttet (placid2000) - - Robert Parker (yamiko_ninja) + - Filip Telążka + - Vladimir Jimenez + - Artur 'Wodor' Wielogorski + - Shamil Nunhuck (shamil) + - Shevelev Vladimir (shevelev_vladimir) + - Marc Straube + - Bart Heyrman + - Norman Soetbeer (battlerattle) + - Fabien Lasserre (fbnlsr) + - Hendrik Pilz (hendrikpilz) + - Krzysztof Ilnicki (poh) + - Michele Carino + - Charcosset Johnny + - Francesco Abeni + - Matthias Noback (mnoback) + - Talita Kocjan Zager (paxyknox) + - John Doe + - sgautier + - Michael Cullum (unknownbliss) + - belghiti idriss (belghiti) + - Sebastian G. (bestog) + - Valerio Colella + - Daniel Wendler + - Kacper Gunia + - Arne + - Rémy Issard + - hanneskaeufler + - Egor Ushakov (erop) + - jfhovinne + - Thomas P + - Jeroen + - Romain Biard (rbiard) + - Jonathan Holvey + - Grégory Quatannens (gscorpio) + - BETARI Amine (amine_ezpublish) + - Sorin Dumitrescu (sfdumi) + - Maxime Douailin + - Daniel Klein + - David Lumaye + - A goazil + - Grzegorz Dembowski (gdembowski) + - Dennis Bijsterveld (bijsterdee) - Patrik Pacin - - Piotr Strugacz - - René Backhaus - - Kieran Black - - guesmiii - - Danny Witting - - morrsky + - Bartłomiej Zając (bzajac) + - jivot + - progga - Thibaut Selingue - Dukagjin Surdulli - - Max R + - bouffard (shinmen33) + - Mathieu + - Jorick + - Patrik Csak + - Julien Humbert + - Rob Gagnon + - Nebojša Kamber + - Thomas Talbot + - Boolean Type (boolean_type) + - Urs Kobald (scopeli) + - Hari K T (harikt) + - Michael COULLERET (20uf) + - Timo Haberkern (thaberkern) + - Robert Koller (robob4him) + - Alexandru Furculita ♻ + - Hmache Abdellah + - concilioinvest + - Paweł Czyżewski + - Catalin Criste (catalin) + - Med Ghaith Sellami + - Catalin Minovici (catalin_minovici) + - Carlos Zuniga (charlieman) + - Christiaan Baartse (christiaan) - Etshy - E Demirtas - antoinediligent + - Bob D'Ercole + - Erwann MEST (_kud) + - ipf + - Sebastian Blum (sebiblum) + - V. K. (cn007b) + - David Ward (roverwolf) + - MarvinBlstrli + - Dalius Kalvaitis (daliuskal) + - runephilosof-abtion + - iamdto (iamdto) + - Jeroen Seegers + - Nehal Gajjar + - jmangarret + - YummYume + - Leanna Pelham + - twisted1919 + - fbuchlak + - Ricardo Rentería + - Sven Petersen + - Derek Roth (derekroth) - Geert Clerx - - Maciej Kosiarski - - royswale - fberthereau - - Mark Fischer, Jr - - muxator - Franz Holzinger - Julian Wagner - Deepak Kumar + - Joe Hans Robles Martínez (joebuntu) + - Yoan Bernabeu + - Colin Poushay (poush) + - Vancoillie + - optior + - Pierre Maraître (balamung) + - Kerrial (kez) + - Lambert Beekhuis (lambertb) + - pamuche + - Bert Van de Casteele + - Daniel Kesselberg (kesselb) + - MarcomTeam + - gitomato + - Iqbal Malik (iqbal_malik89) + - Abdelilah Boudi (devsf3) + - Timotheus Israel (dieisraels) + - Mohameth + - Mark Brennand (activeingredient) + - Adrián Ríos (adridev) + - Kolja Zuelsdorf + - Alexandre GESLIN (rednaxe) + - Denis Brumann + - Francisco Corrales Morales + - Jason Bouffard (jpb0104) + - Katharina Floh (katharina-floh) + - Heaven31415 + - markspare + - Vincent Jousse + - jerzy-dudzic + - Rafael Gil (cybervoid) + - Davor Plehati (dplehati) + - Oussama GHAIEB (oussama_tn) + - Daniel Kozák + - atmosf3ar + - Clément Barbaza + - Christoph Grabenstein + - Benoit Jouhaud (bjouhaud) + - David + - matheo + - Andries van den Berg (ansien12) + - Christophe Deliens (cdeliens) + - Alexander O'Neill + - Jürgen + - Bruno Vitorino + - juliendidier + - Matt Janssen + - Alex Ghiban (drew7721) + - Cyril VERLOOP (cyrilverloop) + - Ivan Kosheliev (dfyz) + - Duane Gran (duanegran) + - Szymon Dudziak + - Turdaliev Nursultan (nurolopher) + - Louis-Arnaud + - Gonzalo Alonso (gonzakpo) + - Chase Noel (chasen) - Nikolai Plath + - Krzysztof Nizioł + - Roman (grn-it) + - Andrey Tkachenko + - AntoineRoue + - Jules Lamur + - mocrates + - Andrei Petre + - Gabriel Bugeaud + - Rylix + - Arthur Hazebroucq + - Pim van Gurp + - Erik (erikroelofs) + - sebio + - Fayez Naccache (fnash) + - Frank Stelzer (frastel) + - Adam Prancz (praad) + - Josenilton Junior (zavarock) + - Benjamin Bourot - jeanhadrien + - Gabriel Théron (g.theron) + - Simon Perdrisat (gagarine) + - Kristijan Stipić (stipic) + - Marie CHARLES (mariecharles) + - ABRAHAM Morgan + - Lucas Mlsna + - Marko Kunic (kunicmarko20) + - Csaba Maulis (senki) + - Simone Gentili (sensorario) + - Yoann B (yoann) + - mark2016 + - Halil Özgür + - Christopher + - Marichez Pierre (chtipepere) + - Anthony FACHAUX + - Tim Werdin + - Kévin LE LOUËR + - Ali Sunjaya + - Marvin Butkereit + - Barun + - Tristan Darricau + - Fanny Gautier + - Christophe Debruel (krike06) + - Yaroslav Kiliba + - Vladislav Lezhnev (livsi) + - Florian-B + - Daniel F. (ragtek) + - Wouter J + - tuanalumi + - ayacoo + - Olivier Revollat (o_revollat) + - javaDeveloperKid + - Syedi Hasan + - dawidpierzchalski + - Kevin Lot + - Andrea Cristaudo + - Baptiste Pottier (baptistepottier) + - Benoît WERY (benoitwery) + - Patrick Mota (ganon4) + - Reinier Butôt + - Arnaud Pflieger + - Nico + - Boris Sondagh (botris) + - Mickaël Bourgier (chapa) + - Robin Willig (dragonito) + - Aalaap Ghag (aalaap) + - Eric Poe (ericpoe) + - Giancarlos Salas (giansalex) + - xamgreen + - Michal Zuber + - Mark Smith (zfce) + - Thomas Botton (skeud) + - Théophile Helleboid - chtitux + - Omer Karadagli (omer) + - Tom Grandy - Felix Schnabel - - Kevin Wojniak - - Pierre Bobiet - - Tobias Hermann + - Pierre Joye (pierre) + - Bastien70 + - Babar Al-Amin (babar) + - Benjamin D. (benito103e) + - Sherin Bloemendaal + - Krzysztof Daniel (krzysdan) + - Patryk Miedziaszczyk + - pbijl (pbijl) + - copilot-swe-agent[bot] + - Patrick Maynard + - Terje Bråten + - Philippe Gamache (philippegamache) + - Cyanat + - Lucas CHERIFI (kasifi) + - David Rolston (gizmola) + - Vadym (rvadym) + - Victor Melnik (gremlin) + - Grzegorz Balcewicz (gbalcewicz) + - Guillaume Sylvestre (gsylvestre) + - Sander Verkuil (sander-verkuil) + - Fabien (fabiencambournac) + - Florian Körner (koernerws) + - Stephan + - Michel Valdrighi (michelv) + - David Desberg + - New To Vaux + - Tajh Leitso (tajh) + - Roman Martinuk - Greg Pluta - - Dmitriy - Michał Wujas - - Marco Barberis - - homersimpsons - - Tobias Sette - - Katharina Störmer - - Javier Espinoza - - Pierre + - vindby23 + - Hugo Nicolas (jacquesdurand) + - SquareInnov + - Milan Pavkovic + - Sven Scholz + - DOEO + - Guillaume PARIS (gparis) + - Xavier Laviron (norival) + - Plamen + - Iv Po + - Greg Berger + - Carlos Sánchez (carlossg00) + - Issam KHADIRI (ikhadiri) + - Roger Webb (webb.roger) + - Tommy Quissens (quisse) + - Janko Diminic (jankod) + - Frédéric Lesueurs + - Matthieu Renard + - Jonas De Keukelaere + - Luc Hidalgo (luchidalgo) + - Julien Dubois + - Eugene Dounar + - Artur Butov (vuras) + - Ousmane NDIAYE + - Ondrej Vana (kachnitel) + - Marchegay (xaviermarcheay) + - Maxime Steinhausser + - sblaut + - Jonathan Lee (jclee2) + - Nico Th. Stolz (jeireff) + - Jose F. Calcerrada (jfcalcerrada) + - Jibé (jibe0123) + - Mickael GOETZ + - Muhammad Nasir Rahimi + - romain + - Brendan + - Rob + - Ka (Karim Cassam Chenaï) + - Sebastian Kuhlmann (zebba) + - Kélian Bousquet + - apiotrowski + - Pierre Maraitre + - Johan de Jager (dejagersh) + - Raphaël Geffroy + - Faizan Shaikh + - ondra + - Antonio Jesús + - Belgacem TLILI (belgacem) + - Jérémy Jarrié (gagnar) + - Savvas Alexandrou (savvasal) + - Peter + - Kirill Kotov + - Pieter Oliver + - Louis Racicot (lord_stan) + - Pol Romans (snamor) + - Reza Rabbani + - Poulette Christophe (totof6942) + - norfil + - Olivier Bacs (obax) + - Dorthe Luebbert (luebbert42) + - Vince (zhbzhb) + - Bogdan Olteanu + - Nurlan Alekberov + - Erlang Parasu (erlangparasu) + - Peter WONG + - Neal Brooks (nealio82) + - Aymeric Mayeux (aymdev) + - Kamil Pešek (kamil_pesek) + - seangallavan + - Nic Wortel (nicwortel) + - Patrick Bielen + - Ben Glassman (bglassman) + - Thomas Berends + - Philip Ardery + - David ALLIX (weba2lix) + - BorodinDemid + - Ana Cicconi + - Nassim LOUNADI + - Alexpts (alexpts) + - Valentin Silvestre (vasilvestre) + - Spomky + - vesselind + - Joseph Bielawski + - Yannick + - Nieck Moorman + - Igor + - James (acidjames) + - Gilles Taupenas + - Valentin GRAGLIA + - Florian + - Brian Gallagher - Karin van den Berg - Dhanushka Samarakoon - Philipp Christen + - Jerome Gangneux + - Denis Brumann + - Russell Flynn (rooster) + - avanwieringen + - Jonczyk + - bpiepiora + - Tim Jabs + - Ben Thomas + - Krzysztof Lechowski (kshishkin) + - Danny Kopping (dannykopping) + - Corentin + - Angelo Melonas (angelomelonas) + - nasaralla + - zuhair-naqvi - Serhii Polishchuk - - Alex Kyriakidis - - Ali Arfeen - - sebio - Lamari Alaa - - jpache - - Nelson da Costa - - Med Ghaith Sellami - - Jake Bell + - sander Haanstra (milosa) + - jean-marie leroux (jmleroux) + - skipton-io + - Thao Nguyen (thaowitkam) + - Lukáš Brzák (rapemer) + - Daniel Werner (powerdan) + - Adam Szaraniec (mimol) + - Thomas from api.video + - xelan + - Lorenzo Ruozzi (lruozzi9) + - Murilo Lobato (murilolobato) + - James Cryer (jrcryer) + - Jacob Dreesen + - Leonel Machava + - Nicolas Lœuillet (nicosomb) + - Vincent Chareunphol (devoji) + - Marijn Huizendveld + - Thomas Decaux (ebuildy) - Lars - - VisionPages - - Seikilos - - CodyFortenberry - - nietonfir - - Hugo Locurcio - - Romain GRELET - - Andréas Hanss + - Fred Jiles (fredjiles) + - Egidijus Girčys (egircys) + - Julian (c33s) + - Ryan Castle (ryancastle) + - Chad Meyers (nobodyfamous) + - Tim Stamp + - Emir Beganović (emirb) + - Henrik Christensen + - ipatiev - sr972 + - xuni + - Edson Medina + - Roy Templeman + - Erison silva (eerison) + - Sarim Khan (gittu) + - Justin Liiper (liiper) + - asartalo + - Abdellatif Derbel (abdellatif) + - Xavier Coureau + - George Zankevich + - David Frerich + - Peter Majmesku + - Guillaume HARARI (guillaumeharari) + - Sven Zissner (svenzissner) + - KalleV + - Christopher Tatro + - Aurélien ADAM (aadam) + - Андрей + - Oliver Kossin + - Robert + - Damian Zabawa (dz) + - Tobias Schmidt (tobias-schmidt) + - Jakub Szcześniak (jakubszczesniak) + - JohnyProkie (john_prokie) + - Olivier Toussaint (cinquante) + - wouthoekstra + - Romain + - Eugene Wolfson + - Pierre Arnissolle (arnissolle) + - Jordan Lev + - Mathias STRASSER + - hidde.wieringa + - Georgiana Gligor (gbtekkie) + - Steve Winter + - pcky + - Parthasarathi GK + - asandjivy + - Dmitriy + - Glen Jaguin (gl3n) + - Danielle Suurlant (dsuurlant) + - Mitchel (mitch) + - Denis Rendler + - Vincent Brouté + - Kevin Boyd + - Terence Eden + - Peter + - chance garcia + - Robert Nagy + - I. Fournier + - Daan van Renterghem + - Adamo Crespi + - Christopher Vrooman + - Jevgenijus Andrijankinas + - Harry van der Valk + - pavemaksim + - aykin + - joelindix + - Freerich Bäthge (freerich) + - Lopton + - Marco Barberis + - Joshua Dickerson (groundup) + - Julio (gugli100) + - Dan Finnie + - Gaurish Sharma + - Luca Suriano (lucas05) + - de l'Hamaide + - Frank J. Gómez + - Jason McCallister (jasonmccallister) + - Oliver Adria + - Walkoss + - Grant Gaudet + - bdujon + - Simon BLUM (simonblum) + - Myystigri + - Sam Hudson + - Vitaliy Zurian + - Hector Hurtarte (hectorh30) + - oussama khachiai (geekdos) + - Chris Thompson (toot) + - michael schouman (metalmini) + - Hamza Hanafi + - Cesare + - rahul (rahul) + - van truong PHAN (vantruongphan) + - MohamedElKadaoui + - iqfoundry + - Lauri + - Paulius Masiliūnas (pauliuz) + - figaw + - Charly + - Kenan Kahrić (kahric) + - cancelledbit + - Quentin Boulard + - Josef Vitu + - Paul Coudeville + - Steve Wasiura + - Daniel Kucharski (inspiran) + - Denys Pasishnyi (dpcat237) + - Rafael Mello (merorafael) + - Franklin LIA + - autiquet axel + - Postal (postal) + - Kobe Vervoort (kobevervoort) + - Konrad pap (konrados) + - Tom Schwiha (tomschwiha) + - Sander Bol + - Marc Michot (eclae) + - Elliot + - Herbert Muehlburger + - Ben Glassman (benglass) + - Ashen one (berbadger) + - Jay Williams (jaywilliams) + - Jelmer Snoeck (jelmersnoeck) + - Joshua Morse (joshuamorse) + - Kevin Mark + - Florentin Garnier + - imam harir (luxferoo) + - Joachim Martin (michaoj) + - Pierre + - Florent DESPIERRES (fdespierres) + - Fabien Papet + - Alessandro Podo + - Thomas Miceli (tomus) + - srich387 + - Jeroen v.d. Gulik (jeroen) + - Dmitry Kolesnikov (kastaneda) + - Arnaud B (krevindiou) + - Mehmet Gökalp (mehgokalp) + - Martin Bens + - Hideki Okajima (okazy) + - Giuseppe Petraroli + - IamBeginnerC + - Yassine Hadj messaoud + - Daniel West (silverbackdan) + - Xavier Laviron + - Michel D'HOOGE (mdhooge) + - Son Tung PHAM + - Raggok + - Benoît + - marco-pm + - Yair Silbermintz (mrglass) + - Alex Wybraniec + - Paweł Farys + - Carlton Dickson (carltondickson) + - Piotr Grabski-Gradziński (piotrgradzinski) + - dellamowica + - Alan Farquharson + - Oliver Forral (intrepion) + - Jack Delin (jackdelin) + - Jean-Luc MATHIEU (jls2933) + - Maxime Morlet (maxicom) + - Rosemary Orchard + - Szilágyi Károly Bálint + - Ilya Bakhlin + - analogic + - William JEHANNE (william_jehanne) + - mhor (mhor) + - richardudovich + - Antonio de la Vega + - Volker Thiel + - Jean-Baptiste Delhommeau (jbdelhommeau) + - Jan Pieper + - Jonathan Cox + - Rick Burgess + - Oliver Davies (opdavies) + - Christian Weyand (weyandch) + - Francis Hilaire + - vgmaarten + - Stefan Topfstedt + - ousmane NDIAYE (ousmane) + - Pedro Piedade + - m_hikage + - Giulio De Donato + - Chris Bitler + - Laurent Marquet + - pathmissing + - Thomas Talbot + - Pierre-Yves Dick (pyrrah) + - Paulo Rodrigues Pinto (regularjack) + - Richard Perez (richardpq) + - Kristian Zondervan (krizon) + - Joel Doyle (oylex) + - Sylvain Lelièvre + - Michaël Perrin + - Chris Halbert + - temenb + - Raúl Continente (raulconti) + - Adil YASSINE ✌️ (sf2developer) + - Michiel Missotten (zenklys) + - ptrm04 + - Jeroen Deviaene + - Michael Lenahan + - Giacomo Moscardini + - Valantis Koutsoumpos - Adam Duffield - - Harry van der Valk - - pavemaksim - - aykin - - joelindix - - denniskoenigComparon - - Vitaliy Zurian + - Pau Oliveras (poliveras) + - Shane Archer (sarcher) + - M#3 + - Julien (mewt) + - Guillaume Lasset + - kenjis (kenjis) + - damienleduc + - Carwyn Moore - Иван - Ozan Akman - Benjamin Porquet - Alex Oroshchuk + - Michael H + - Axel Vankrunkelsven + - Andrey Bolonin + - Leanna Pelham (leannapelham) + - Gauthier Gilles + - Ala Eddine khefifi + - MWJeff + - Kieran Black + - guesmiii + - nietonfir + - Hugo Locurcio + - Alessio Barnini + - Martijn Gastkemper (martijngastkemper) + - Martin Černý + - SamanShafigh + - Denis (ruff3d) + - Andrii Mishchenko (krlove) + - KULDIP PIPALIYA (kuldipem) + - Ronan Pozzi (treenity) + - Maciej Kosiarski + - CHARBONNIER (cyrus) + - Augustin Chateau (gus3000) + - Stefan Doorn (stefandoorn) + - Jonathan Finch + - Gianluca Farinelli (rshelter) + - Soltész Balázs + - Hugo Locurcio + - silver-dima + - matt smith (dr-matt-smith2) + - Pierre Joube (pierrejoube) + - Jeremiah Dodds + - MarkPedron + - Arnaud Lemercier + - Anani Ananiev + - Paweł Małolepszy (pmalolepszy) + - Fabian Becker + - Amitay Horwitz (amitayh) + - Manel Sellés (manelselles) + - Veltar + - Peter Bottenberg + - Nicola Pietroluongo + - Oliver Stark (oliver.stark) - Pjotr Savitski - Jean-David Daviet + - gnito-org + - Richard Hoar + - adursun + - Olivier Acmos (olivier_acmos) + - kolossa + - Thomas (razbounak) + - denniskoenigComparon + - Mathieu Capdeville + - ahinkle + - Reio Remma + - Zoltan Toth-Czifra + - Juan Riquelme + - Maciej Łebkowski (mlebkowski) + - Javad Adib + - Jonas Wouters + - Rick Ogden + - micter59 + - Tomáš Tibenský + - Vincent Terraillon (lou-terrailloune) + - Thibaut Leneveu + - andybeak + - Virginia Meijer + - Ante Crnogorac + - Florian Moser + - Sylvain + - David McKay + - clément larrieu + - Mike Bissett + - Epari Siva Kumar + - Matthias + - Andreas + - illusionOfParadise + - azielinski + - Michael Witten (micwit) + - r-ant-2468 + - Karsten Gohm (kasn) + - Kik Minev (kikminev) + - Fabian Spillner (fspillner) + - Jérôme Poskin (moinax) + - lacatoire + - Armen Mkrtchyan (iamtankist) + - Sylvester Saracevas (saracevas) + - Maximilien BERNARD (mb3rnard) + - Marius Büscher (mbuescher) + - niebaron + - Works Chan + - jordanjix + - Nico Hiort af Ornäs + - Alexandre Balmes (pocky) + - Caliendo Julien + - Matheus Pedroso + - Tony Tran (tony-tran) + - Morgan Thibert (o0morgan0ol) + - Levin + - Mark Deanil Vicente (dvincent3) + - Ilya Antipenko + - karzz + - Markus Frühauf + - Damien Carrier (mirakusan) + - Nassim + - Enzo Santamaria + - unknown - Olivier Lechevalier - Leny BERNARD - - Michael H - - Hocdoc - - Gabriel Bugeaud - - Mikhail Kamarouski + - Jon Eastman - Sergey Belyshkin - Cellophile - Gaetan Rouseyrol - scriptibus + - jpache + - dearaujoj + - Patrick PawseyVale + - lucchese-pd + - Philippe Villiers + - Marek Szymeczko + - Saidou GUEYE + - Pavel Bezdverniy + - Tamás Molnár (moltam) + - Mathias STRASSER - Jace25 - Sylvain Ferlac - Kamil Breguła - - kevin - - Gennadi Janzen - - András Debreczeni - - Mustafa Ehsan Alokozay - Marco - - Artem Henvald + - Alden Weddleton (wnedla) + - Kevin + - Vladimir + - Ldiro + - JhonnyL + - James Seconde (secondejk) + - Kilian Riou (redheness) - Nikita Nyatin - David Baucum - - Jeroen Seegers - - Rémi Andrieux (pimolo) - - Veltar - - Matheus Pedroso + - Carlos Jimenez (saphyel) + - Aleksandr Frolov (thephilosoft) + - GiveMeAllYourCats + - Matthew Thomas + - VladZernov + - damien-louis + - Raphael Michel + - HONORE HOUNWANOU (mercuryseries) + - Jérémy BLONDEAU (jblondeau2) + - Philippe Mine (dispositif) + - Marek Brieger (polmabri) + - Lluis Toyos (tolbier) + - Taiwo A (tiwiex) + - Tobias Olry (tolry) + - Chris Taylor + - Matthew Setter (settermjd) + - chapterjason + - Florian Cellier (kark) + - Andras Ratz (ghostika) + - Mart Kop + - Yakov Lipkovich + - Fabien Bourigault + - Ezequiel Esnaola + - Sam Korn + - Surfoo (surfoo) + - t.le-gacque + - Hex Titan (hextitan) + - Tsimafei Charniauski (varloc2000) + - Beno!t POLASZEK + - Florian Bastien (fbastien) + - rodmar35 + - Krzysztof Lament + - Euge Starr + - Steve + - Artur + - Robin Brisa + - Romain GRELET + - Vladimir Gavrylov + - radnan + - Robert Treacy (robwasripped) + - David Harding + - Kevin Wojniak + - hector prats (jovendigital) + - Yopai + - Alexander Kim + - Axel K. + - Christopher + - BooleanType + - Julien Deniau (jdeniau) + - Alex Luneburg + - Max Schindler (chucky2305) + - Norio Suzuki (suzuki) + - Tristan LE GACQUE (tristanlegacque) + - Scott + - Charles EDOU NZE + - mccullagh + - Stéphane HULARD (shulard) + - Simon Rolland (sim07) + - Simon Berton (simonberton11) + - Giovanni Gioffreda (tapeworm) + - Thierry Geindre (tgeindre) + - Eduardo Thomas Perez del Postigo (aruku) + - Marcus Schwarz + - Robert Parker (yamiko) + - Jan De Coster + - Rico Neitzel + - Alessio Pierobon (alepsys) + - Damien DE SOUSA (dades) + - Claudio Zizza + - zeggel + - Evgeniy Gavrilov + - Rémy Vuong (rvuong) + - Andrey Lukin (wtorsi) + - Yannick ROGER (yannickroger) + - Edoardo Rivello (erivello) + - Malte N (hice3000) + - Elias Van Ootegem + - Aurélien MARTIN + - fishbone1 + - Tomi Saarinen (tomis) + - Dries Vints + - Kilian Schrenk + - Andreas Larssen + - phiamo + - Gytis Šk + - Matt Kirwan + - royswale + - Egidijus Gircys + - Epskampie + - Markus Virtanen + - Ross Deane (rossdeane) + - Dimitri Labouesse + - Tyler King + - Darien Hager + - Mathieu Ducrot (mathieu-ducrot) + - Adam W (axzx) + - Francisco Calderón (fcalderon) - marcagrio - - Gilles Fabio - - Kélian Bousquet - - TheSidSpears - - Ezequiel Esnaola - - GNi33 + - Quentin Brunet + - Kevin Archer (kevarch) + - adreeun + - E Ciotti + - Jeroen + - Vladimir Jimenez + - Iker Ibarguren + - Linus Karlsson + - Jason Johnstone + - ismail BASKIN + - Sergey Falinsky (falinsky) + - Florian Semm (floriansemm) + - Gabriel Pillet (tentacode) + - Pooyan Khanjankhani + - Jannes Drijkoningen (jannesd) + - Rick Kuipers + - moon-watcher + - Tim Krase + - Kendrick + - Bastien Picharles (kleinast) + - Tommi - Andrew Cherabaev - Alexandre Bertrand - - peaceant - - Mohsen - - adreeun + - Alejandro García Rodríguez (alejgarciarodriguez) + - Alfonso Machado Benito (almacbe) + - Amine Matmati (aminemat) + - Nils Freigang (pueppiblue) + - Matthew Ratzke (flyboarder) + - samson daniel (samayo) + - SirRFI + - Tomasz Ducin (tkoomzaaskz) + - Raphaël Riehl - MaharishiCanada - GoT - - Jesús Miguel Benito Calzada (beni0888) - - jdevinemt - - Piotr Potrawiak - - Yann Klis - - Christoph Schmidt + - unknown + - Hans Allis (hansallis) + - Jorge Luis Betancourt (jorgelbg) + - James Mallison + - BT643 + - Ahmed Siouani (ahsio) + - Christian + - Giuseppe Attardi + - Favian Ioel Poputa (favianioel) + - Aleksander Cyrkulewski (martyshka) + - Katharina Störmer + - Maurice Svay (mauricesvay) + - Lorenzo Milesi (maxxer) + - Viacheslav Demianov (sdem) + - AntoJ (merguezzz) + - Sethunath K (sethunath) + - Woody Gilk (shadowhand) + - Shambhu Kumar (shambhu384) + - Open Orchestra (open-orchestra) + - Shiraz (zpine) + - Edgar Brunet + - Bram van Leur (bvleur) + - Jeff Zohrab + - CvekCoding + - Philippe Milot + - Leonard Simonse + - John Williams + - Gilles Gauthier + - Eöras + - lacpandore + - Emilio de la Torre (emiliodelatorrea) + - Terje Bråten + - Marcin Muszynski + - Romain Petit + - helmi dridi + - Marco Woehr + - Yuri Tkachenko (tamtamchik) + - Simon Van Accoleyen (simonvanacco) + - Slava Belokurski (slavchoo) + - Loïc Salanon + - LiVsI + - Marius Adam + - kempha + - Alexey Pyltsyn (lex111) + - jakumi + - Vico Dambeck + - Christophe Boucaut + - Nadim AL ABDOU + - Mateusz Anders + - Wanne Van Camp + - Anand (anandagra) + - Andrew D Battye (andrew_battye) + - Stefan Blanke (stedekay) + - Nicolae Astefanoaie (stelu26) + - Arnaud Lejosne + - Kris + - b0nd0 + - Damien + - larsborn + - Paris mikael (stood) + - Stanislav Zakharov (strannik) + - Carsten Blüm (bluem) + - Markus Mauksch + - Rhodri Pugh + - Fabien Bourigault + - Sven (svdv22) + - Atchia Mohammad Annas Yacoob (annas-atchia) + - Quentin Fahrner (renrhaf) + - Shaun Simmons (simshaun) - zeroUno - Mickaël - jenyak - Jan Richter - - Pinchon Karim - - Arndt H. Ziegler - - Xavier - - matteopoile - - dpfaffenbauer + - z38 + - Xbird + - matthieudelmas + - Dirk Luijk (dirkluijk) + - Adam Lee Conlin (hades200082) + - Alexander Diebler + - Tom Egan + - Julien BENOIT + - Pierre-Emmanuel CAPEL (pecapel) + - Alex Coventry + - vihuarar + - Chloé B. + - Manuel Andreo Garcia + - runawaycoin + - lusavuvu + - Ali Yousefi (aliyousefi) + - Jan Schütze (dracoblue) + - Jasperator - Oleg Zinchenko - - Menachem Korf + - Edward Kim + - Sarah-eit + - sebgarwood-gl + - Émile PRÉVOT + - Rafa Couto + - Gabriel Theron + - Thierry Goettelmann + - Gennadi Janzen + - András Debreczeni + - Mustafa Ehsan Alokozay - proArtex - fplante - Ruslan - Nelu Buga - - Rylix - - Arthur Hazebroucq - - JHGitty - - Pedro Gimenez - - Johan de Jager - - Thierry Thuon + - Daniel Garzon (arko) + - Jan Grubenbecher + - Elbert van de Put + - cirrosol + - Houssem ZITOUN + - Michael Dwyer (kalifg) + - Fernando Aguirre Larios (ingaguirrel) + - Morf + - Jan Myszkier + - manseuk + - Philipp Bräutigam + - tikoutare + - Menachem Korf - Stephan Dee - Shamsi Babakhanov - Charles Winebrinner + - Jeroen + - Marius-Liviu Balan (liv_romania) + - Micheal Cottingham (micheal) + - Michelle Sanver (michellesanver) + - S Berder + - Félix Fouillet + - Tobias Berchtold + - Mark Challoner + - Manuele Menozzi (mmenozzi) + - lajosthiel + - Robert Went (robwent) + - Micha Alt + - wkania + - EtienneHosman + - z38 + - Thibaud BARDIN (irvyne) + - Greg (kl3sk) + - Jean Pasdeloup + - Daniel Siepmann + - valepu + - laurent negre + - Mathias Geat (maffibk) + - Alex Brims (outspaced) + - Shawn Dellysse + - Souhail (souhail_5) + - Tom Nguyen + - Yngve Høiseth + - Manuel Transfeld + - Sacha Durand (sacha_durand) + - Francesco Tassi (ftassi) + - Frédéric Planté + - heddi.nabbisen + - Jalen + - Augustin Delaporte + - Hubert Moutot (youbs) + - Robert Brian Gottier + - Christoph Wieseke + - Travis Yang (oopsfrogs) + - Alireza Rahmani Khalili (alireza_rahmani) + - German Bortoli (germanaz0) + - e-weimann + - Greg Somers + - Martin Czerwinski + - Lee Jorgensen (profmoriarty) + - Erwan Richard (erichard) + - Damien Tournoud + - Aymen Bouchekoua (nightfox) + - Samuel Wicky + - Petr Kessler + - Florian Belhomme + - Pierre MORADEI + - Zac Sturgess (zsturgess) + - guiditoito + - Thomas Lemaire + - nicofrand + - Hossein Vakili + - Lacy (200ok) + - xavierkaitha94 + - Nicolas Potier (npotier) + - Dmitriy Fishman (fishmandev) + - Artem Henvald + - Kevin Warrington + - Peyman Mohamadpour + - linuxprocess + - Aaron Edmonds (aedmonds) + - Jérôme (ajie62) - timo002 - Xavier RIGAL - Enache Codrut - - Vladimir Jimenez - mismailzai - - radnan - - Iker Ibarguren - Bartek Chmura - - Alessio Barnini - - Nicolas Mugnier - - Nitaco - Alex Normand - Fouad - Lucas Pussacq - Alexandre HUON - - apiotrowski - - vladyslavstartsev - - Christian Alexander Wolf - - Vladimir Gavrylov + - yanickj + - Christopher Moll + - Yannick (yannickdurden) + - Tom Maaswinkel (thedevilonline) + - Dmitry Vapelnik (dvapelnik) + - Fatih Ergüven (erguven) + - benti + - Petar Petković + - stormoPL - rschillinger - - The Phrenologist (phreno) - - tabbi89 - - John Spaetzel - - Harald Leithner - - Reinier Butôt + - Bartosz Tomczak + - Felix Stein + - Manuel Agustín Ordóñez (manuel_agustin) + - Kevin Pires (takiin) + - Yoan Arnaudov (nacholibre) + - Rubén Rubio Barrera (rubenrubiob) + - Rick van Laarhoven (rvanlaarhoven) + - grelu + - Mickaël Blondeau (mickael-blondeau) + - Sasha Matejic (smatejic) + - Raphaël Davaillaud + - Dilantha Nanayakkara + - wazz42 + - Michael Phillips + - RickieL + - LEFLOCH Jean-François (katsenkatorz) + - abarke + - Benjamin Dos Santos + - Christopher Cardea + - ackerman + - RiffFred + - Guillaume Sarramegna + - Julian Mallett (jxmallett) + - Ian Gilfillan + - sakul95 + - Benjamin Clay (ternel) + - Kristof (jockri) + - Ahmed Lebbada (sidux) + - Bartek Nowotarski + - mimol91 + - Rick Pastoor - Levi Durfee + - Julien Bonnier (jbonnier) + - Florian Blond (fblond) - Willem Stuursma-Ruwen - Théo FIDRY - - Benj - - Maximilian Bosch - - richardmiller + - Jon Cave + - Marwâne (beamop) + - Pascal MONTOYA (pmontoya) + - Matt Trask (matthewtrask) + - Paul Rijke (parijke) + - Thijs Feryn + - Tim Jabs + - LucileDT + - Alexey Bakulin (bakulinav) + - Fabrice GARES (fabrice_g) + - Danny + - LICKEL Gaetan (cilaginept) + - Toni Conca (tonic) + - Attila Egyed (tsm) + - Johan de Jager + - Steve Clay (mrclay) + - Yann Klis + - Geert Eltink + - Martin Melka + - Marcin Sekalski + - Agustín Pacheco Di Santi + - Alexis Urien (axi35) + - partulaj + - Rami Dridi + - Ahmed Bouras + - Martijn Zijlstra + - Salah MEHARGA + - Marvin Hinz + - Andrey (quiss) + - Volodymyr Stelmakh + - Saad Tazi (saadtazi) + - OИUЯd da silva + - Zbigniew Czapran (zczapran) + - Navid Salehi (nvdsalehi) + - armin-github + - Therage Kevin + - Pierre Pélisset (ppelisset) + - Tarjei Huse (symfony_cloud) + - Xavier + - Malte Blättermann + - Lander Vanderstraeten + - Florian Moser + - Éric + - Clayton + - Wojciech Sznapka + - Ludovic REUS + - Ahmed Abdou (ahmedaraby) + - Cliff Odijk (cmodijk) + - Godfrey Laswai - David - Sakulbl - - Elbert van de Put + - Julien RAVIA + - Punt + - Josh Freeman (viion) - antonioortegajr + - Michael Smith (michaelesmith) + - Etilawin + - venu (venu) + - Nicolas Dievart (youri) + - François MARTIN + - Ludwig Bayerl (lbayerl) + - fernandokarpinski + - R1n0x + - Idziak + - Diego Gullo (bizmate) + - Kanat Gailimov + - Stéphane P + - rogamoore + - Vivien Tedesco (vivient) + - Daniel (voodooprograms) + - WILLEMS Laurent (willemsl) + - Lenkov Michail (alchimik) + - Oleksandr Savchenko (asavchenko) - Florian Rusch + - dcramble + - sebpacz + - Paweł Farys + - Pierre Bobiet + - Piotr Potrawiak + - Jorge Sepulveda + - broiniac + - Peter Hauke + - Fabian Freiburg + - Willem-Jan Zijderveld (wjzijderveld) + - Leonardo Losoviz (leoloso) + - Ricardo Peters (listerical) + - Justas Bieliauskas + - Alex-D (alexd) + - Christian Alexander Wolf + - Markus Weiland (advancingu) - zulkris - Dzamir - Boris Shevchenko - - Kevin Warrington - - Peyman Mohamadpour - - Quentin ADADAIN - - Andrei + - Sait KURT (deswa) + - ifiroth + - Walter Nuñez + - Patrik Gmitter (patie) + - Marius Balčytis + - Maximilian + - Zaid Rashwani (zrashwani) + - Pierre Galvez (shafan_dev) + - Ulrich Völkel (udev) + - Nebojša Kamber + - The Phrenologist (phreno) + - Stepan Mednikov + - Robin + - Gary Kovar + - Michel Chowanski (migo) + - KosticDusan4D - Robin Gloster - Bram de Smidt - - Zahir Saad Bouzid - - Jonathan Holvey + - Evan Owens + - Filip Grzonkowski (grzonu) + - Qiangjun Ran (jungle) + - Liang Jin Chao (leunggamciu) + - Andrej Rypo + - Anthony Sterling (anthonysterling) + - Łukasz Bownik (arkasian) + - Ondřej Vodáček + - Goran Grbic (tpojka) + - Benjamin Lazarecki (benjaminlazarecki) + - Michael Klein (monbro) + - Jean Pasqualini + - sofany + - FindAPattern + - Tom Haskins-Vaughan + - Uri Goldshtein + - Vyacheslav Pavlov + - Pierre de Soos + - Johnny Peck + - Mario Young + - Fabien Bourigault + - Arnaud Salvucci (arnucci) + - xthiago (xthiago) + - Karel (xwb) + - vladyslavstartsev - pavdovlatov - - Linus Karlsson - - Jason Johnstone - - Pim van Gurp - - Szurovecz János - - Υоаnn B - - Adiel Cristo - - BrnvrlUoeey - - beachespecially - - mbehboodian - - Sascha Egerer - - Martin Černý - - Yves ASTIER - - Dmitri Perunov - - Daniel Karp - - Laurent Marquet - - Jure Žitnik + - Wojciech Kania + - ymc-sise + - DKravtsov + - Jeremy Emery + - Piotr Strugacz + - Luka Žitnik + - Jason Grimes + - saf (asd435) + - Mohd Shakir Zakaria (mohdshakir) + - Cangit + - TrueGit + - Tim Kuijsten + - Dennis Benkert + - Alexis Lefebvre + - Alex Theobold + - Jerome Guilbot (papy_danone) + - Daniël Brekelmans + - Adiel Cristo + - BrnvrlUoeey + - beachespecially + - Brendan Lawton + - Nikita + - M.Wiesner + - Daniel LIma (yourwebmaker) + - Yuriy Sergeev (youser) + - Eike Send + - Bruce Phillips + - Robin Cawser (robcaw) + - Alexandr Kalenyuk + - Brandon Mueller (fatmuemoo) + - Thomas BILLARD + - Ziad Jammal (ziadjammal) + - muxator + - babache + - zan-vseved + - manu-sparheld + - Maximilian Bosch + - richardmiller + - Oliver THEBAULT + - Arnaud + - Mario Alberto - Bruno Casali - Kevin de Heer - fullbl + - Dorian Sarnowski (dorian) + - Viktor Linkin (adrenalinkin) + - Stephen Ostrow (isleshocky77) + - Ali Zahedi (aliz9271) + - Michel ANTOINE (antoin_m) + - Pavel Nemchenko (nemoipaha) + - Jose R. Prieto + - Chabbert Philippe (philippechab) + - Jérémie Samson (jsamson) + - scottwarren + - Romain Norberg + - Niels Vermaut (nielsvermaut) + - roga + - obsirdian + - Gus + - Tobias Sette + - Iulian Popa (iulyanp) + - AmalricBzh + - Alexander Dubovskoy + - hamzabas + - Leo + - sirprize + - VosKoen + - Danil Pyatnitsev (pyatnitsev) + - KaroDidi + - eric fernance (ericrobert) + - Timo Tewes + - yordandv + - mehlichmeyer + - Jens Pliester + - Szurovecz János + - Υоаnn B + - Francois CONTE + - Pouyan Azari + - Sylvain Combes (sylvaincombes) - Christian Heinrich + - Dmitri Perunov + - Rick West + - Alihasana SHAIKALAUDDEEN + - makmaoui + - Cosmin Mihai Sandu (cosminsandu) + - Sergey Podgornyy (sergey_podgornyy) + - Marcel Serra Julià (serrajm) + - Andrea Bergamasco (vjandrea) + - Mrtn Schndlr + - Cassian Assael (crozet) + - Jacek Jędrzejewski + - Benjamin Sureau + - Konstantin (phrlog) + - Rodrigo Rigotti Mammano (rodrigorigotti) + - Cédric Spalvieri (skwi) + - Dmitry Vishin (wishmaster) + - Rutger - Jose Diaz - kohkimakimoto - - Faizan Shaikh + - Tim Glabisch + - Jan + - Andreas Schönefeldt + - VelvetMirror + - Dorozhko Anton + - Jonathan Clark + - Giulio Lastra + - Ed Poulain + - wiese + - Stéphane Paul BENTZ (spbentz) + - Krap + - Stefan Grootscholten (stefan_grootscholten) + - Matthieu Braure (taliesin) + - Prakash Thapa (thapame) + - Valter Carneiro da Silva Junior (valterjrdev) + - Tyler Sommer (veonik) + - Archie Vasyatkin + - Brian + - Sven Luijten + - Slobodan Stanic + - Alexandre Mallet (woprrr) - Frederik Schubert - Stacy Horton - Sébastien Lourseau - Nathan Giesbrecht - Sebastian Bergmann - - Paweł Tekliński + - Alex Kyriakidis + - Kevin Papst + - Mynyx + - David Vigo + - Sam Jarrett + - Robert + - Pierre Spring + - andrecadete + - David Schmidt + - Art Matsak + - Dynèsh Hassanaly (dynesh) + - 6e0d0a + - Jan Klan (janklan) + - Jonathan + - Jamal Youssefi + - Volen Davidov + - Alfonso M. García Astorga (alfonsomga) + - José María Sanchidrián (sanmar) + - martin05 + - Noel + - Julien Dephix + - Lukas W + - beram (beram) + - Avindra Goolcharan + - Alaa AttyaMohamed (alaaattya) + - Mike Zukowsky + - Oliver Kossin + - Ignacio Aguirre + - Anthony Rey (sydney_o9) + - Florent + - Marko Mijailovic + - Colin DeCarlo (colindecarlo) + - Andrew Martynjuk (crayd) + - Doug Smith (dcsmith) + - wbob + - Daniele Ambrosino + - Zahir Saad Bouzid + - Lucas Nothnagel (scriptibus) + - Christian Oellers + - Guilherme Donato + - Nick Winfield + - Asma Drissi (adrissi) + - Daniel Santana + - Janusz Slota (janusz.slota) + - Szymon Skowroński (skowi) + - Thomas Le Duc (viper) + - Rob Meijer (robmeijer) + - revollat + - RisingSunLight - Michaël Demeyer - AdrianBorodziuk - - Edwin - - ruslan-fidesio - - mvanmeerbeck - - phoefnagel - - ioanok - - Chris Bitler - - Mihail Kyosev (php_lamer) - - Alexey Rogachev - - Thomas LEZY - - Matěj Humpál + - peaceant + - Mohsen + - Sudhakar Krishnan + - Michaël Perrin - Gintautas - guangle - - Kwadz + - Denis Dudarev + - Jesús Miguel Benito Calzada (beni0888) + - Lauri + - Alex Salguero + - manoakys + - Roberto Lombi + - Arnaud VEBER (veberarnaud) + - Serge Velikanov + - Richard Miller + - Lucian Tugui (luciantugui) + - Mehdi Tazi (mehditazi9) + - Joe Mizzi (themizzi) + - Thomas Lomas (tomlomas) + - ioanok + - Kevin + - Kevin + - Christian Schaefer (caefer) + - Hugo Casabella (casahugo) + - Charles Pourcel (ch.pourcel) + - Alexey Rogachev + - Matthieu Danet (matthieu-tmk) + - Varun Agrawal (varunagw) + - Marc Wustrack (muffe) + - Laurent Marquet + - marcusesa + - Bart van Raaij (bartvanraaij) + - Kim Wüstkamp (kimwuestkamp) + - Chris McMacken (chrism) + - Pierre Trollé + - Piotr Stankowski + - Adam Boardman (boardyuk) + - Thomas Choquet (tchoquet) + - Adrien LUCAS + - Baptiste Fotia (zak39) + - Ruud Kamphuis + - Ivan Yivoff + - Paul Waring + - Jarek Ikaniewicz + - Mitchell + - Timon F. (timon) + - Denis-Florin Rendler + - alex00ds + - Jess + - Jochem Klaver + - David Paz (davidmpaz) + - tchap + - Dominik Pietrzak + - wadjeroudi + - Eliú Timaná + - Andrey Melnikov + - Vincent + - Michaël Mordefroy + - cvdwel + - Lucas Mlsna + - Titouan B + - IlhamiD + - Gyula Szabó (szabogyula) + - Joe Thielen + - Jake Bell + - Gilles Fabio + - Steve Nebes + - jms85 + - authentictech + - LavaSlider + - Sam Hudson + - Baptiste Langlade + - Chris Johnson + - Kris + - Jannik + - Jarosław Jakubowski (egger1991) + - Linas Merkevicius + - Nazar Mammedov + - pecapel + - Sylvain Blondeau + - Maelan LE BORGNE (maelanleborgne) + - jmsche + - danjamin + - Remi + - JakeFr + - Žilvinas Kuusas (kuusas) + - XitasoChris + - Andrii Sukhoi + - Happy (ha99ys) + - Kamil Kuzminski (qzminski) + - jdevinemt + - Cristiano Cattaneo (ccattaneo) + - kruglikov + - Kevin Raynel + - tmihalik + - Reza + - Nietono + - Angelo Galleja (ga.n) + - TavoNiievez + - Ionut Enache + - Conrad Pankoff + - Maxime Douailin + - Tomasz Tybulewicz (tybulewicz) + - Vlad Ghita (vghita) + - Ahmed El Moden + - Unlikenesses + - kirill-oficerov + - aliber4079 + - Bruno Vitorino + - Christoph Schmidt + - tabbi89 + - John Spaetzel + - Harald Leithner + - Jure Žitnik - Gergely Pap - - sparrowek - - Travis Carden - - Guillaume Lasset + - Julien Janvier + - Jérémy LEHERPEUR (amenophis) + - Thomas Rudolph (holloway) + - Nik G (iiirxs) + - Francisco Javier Aceituno (javiacei) + - Jo Meuwis (jo_meuwis) + - Luca Lorenzini + - Joel Costa (joelrfcosta) + - lobodol (lobodol) + - LOUVEL Mathieu (louvelmathieu) + - Maikel Ortega Hernández (maikeloh) + - Sam Van der Borght (samvdb) + - Paulius Podolskis (wsuff) - Léo - berbeflo - Dmytro Bazavluk - - ismail BASKIN - Simon Epskamp - Theo Tzaferis - - Mantas Varatiejus - - Josh Kalderimis - - kallard1 - - Alexander Dubovskoy - - hamzabas - - Leo - - sirprize - - VosKoen - - ubick - - Aurélien Morvan - - timglabisch - - Deng Zhi Cheng - - alexsaalberg049 - - Dincho Todorov + - snroki + - Jalen Muller (jalenwasjere) + - Simon + - LesRouxDominerontLeMonde + - Michael Staatz + - Jade Xau + - Maxim Spivakovksy (lazyants) + - CJDennis + - Marcel Korpel + - Marko Kaznovac - Mohammad - Richard Tuin (rtuin) - Gabriel Albuquerque - - John Doe - Sven Liefgen - Greg Berger - Alex Soyer + - Josh Taylor (josher) + - Piotr Gołębiewski (loostro) + - Marcin Sękalski (senkal) + - Behram ÇELEN (behram) + - Dan Tormey (dstormey) + - Jacek (opcode) + - PululuK + - technetium + - Benjamin Laugueux + - kallard1 + - Yaroslav Yaremenko + - Maximilian Ruta + - Lucas Courot (lucascourot) + - Edwin + - ruslan-fidesio - Clément + - miqrogroove + - Tobias Berge + - Julien Ferchaud (guns17) + - Pedro Junior (vjnrv) + - Gun5m0k3 + - Carl Schwan + - Claude Ramseyer (phenix789) + - Prathap + - entering + - Christian Kolb (liplex) - Massimo Ruggirello + - Michael Petri (michaelpetri) + - norbert-n + - Wolfgang Weintritt (wolwe) + - Benoît Durand (bdurand) + - Robert Parker (yamiko_ninja) + - Dustin Meiner + - Cory Becker + - Jérémy Crapet + - Mohamed YOUNES (medunes) + - Stephen Clouse + - JT Smith - Artem Ostretsov - - ondra - - Antonio Jesús - Nextpage - Robert Podwika - - Julien Janvier - - Dan Zera - - Elliot - - Francesco Abeni - - Denis Dudarev - - Rémy Issard - - hanneskaeufler - - progga - - Jevgenijus Andrijankinas - - concilioinvest - - Paweł Czyżewski - - Richard Lynskey - - Clement Ridoret - - Bob D'Ercole - - Erwann MEST (_kud) - - Abdellatif Derbel (abdellatif) - - Remi - - Mark Brennand (activeingredient) - - Adrián Ríos (adridev) - - Aaron Edmonds (aedmonds) - - Jérôme (ajie62) - - Alejandro García Rodríguez (alejgarciarodriguez) - - Alfonso Machado Benito (almacbe) - - Jérémy LEHERPEUR (amenophis) - - Amine Matmati (aminemat) - - Anand (anandagra) - - Andrew D Battye (andrew_battye) - - Atchia Mohammad Annas Yacoob (annas-atchia) - - Alexey Bakulin (bakulinav) - - Andries van den Berg (ansien12) - - Anthony Sterling (anthonysterling) - - Łukasz Bownik (arkasian) - - Arnaud Salvucci (arnucci) + - lbraconnier2 + - Panda INC (pandalowry) + - Daniel Santana + - DerStoffel + - elescot + - Tom Troyer + - Sébastien FUCHS + - Vilius Grigaliūnas + - M.Eng. René Schwarz + - Jorisros (jorisros) + - Daniel Parejo Muñoz (xdaizu) + - Mostefa Medjahed (mostefa) + - Crushnaut + - Daniele D'Angeli (erlangb) + - Richard Perez (riperez) + - Antonio Spinelli + - Ian Mustafa - Andrey Shark (astery) - - Alexander Vorobiev (avorobiev) - - Aldo Zarza (azarzag) - - Babar Al-Amin (babar) - - Norman Soetbeer (battlerattle) - - Fabien Lasserre (fbnlsr) - - Behram ÇELEN (behram) - - Belgacem TLILI (belgacem) - - belghiti idriss (belghiti) - - Mathieu - - Sebastian G. (bestog) - - Clément Notin - - Dennis Bijsterveld (bijsterdee) - - Adam Boardman (boardyuk) - - Bartłomiej Zając (bzajac) - - Alistair (phiali) - - Catalin Criste (catalin) - - Alexander Kim - - Jean Pasqualini - - Catalin Minovici (catalin_minovici) - - Carlos Zuniga (charlieman) - - Christiaan Baartse (christiaan) - - V. K. (cn007b) - - Cosmin Mihai Sandu (cosminsandu) - - Kristof Coomans (cyberwolf) - - CHARBONNIER (cyrus) - - Dalius Kalvaitis (daliuskal) - - Davi Tavares Alexandre (davialexandre) - - David Negreira Rios (davidn) - - Derek Roth (derekroth) - - Abdelilah Boudi (devsf3) - - Timotheus Israel (dieisraels) - - Davor Plehati (dplehati) - - Alex Ghiban (drew7721) - - Dan Tormey (dstormey) - - Dmitry Vapelnik (dvapelnik) - - Marc Michot (eclae) - - Fatih Ergüven (erguven) - - Erwan Richard (erichard) - - Benjamin Toussaint - - Erik (erikroelofs) - - Sergey Falinsky (falinsky) - - Florian Semm (floriansemm) - - Fayez Naccache (fnash) - - Frank Stelzer (frastel) - - Gabriel Théron (g.theron) - - Simon Perdrisat (gagarine) - - Jérémy Jarrié (gagnar) - - Patrick Mota (ganon4) - - David Rolston (gizmola) - - Vadym (rvadym) - - Benjamin Hubert (gouaille) - - Greg Box (gregfriedrice) - - Victor Melnik (gremlin) - - Grzegorz Balcewicz (gbalcewicz) - - Guillaume Sylvestre (gsylvestre) - - Guillaume HARARI (guillaumeharari) - - Augustin Chateau (gus3000) - - Houssem ZITOUN - - Vladyslav Riabchenko - - Cristiano Cattaneo (ccattaneo) - - Daniel Platt (hackzilla) - - ABOULHAJ Abdelhakim (hakim_aboulhaj) - - Hans Stevens (hansstevens) - - Thomas Rudolph (holloway) - - Nik G (iiirxs) - - Tim Werdin - - Hugo Nicolas (jacquesdurand) - - Janko Diminic (jankod) - - Jonathan Lee (jclee2) - - Nico Th. Stolz (jeireff) - - Jose F. Calcerrada (jfcalcerrada) - - Jibé (jibe0123) - - jean-marie leroux (jmleroux) - - Joan Teixido (joanteixi) - - Joshua Morse (joshuamorse) - - James Cryer (jrcryer) - - Julien Chaumond (julien_c) - - Julius (julius1) - - rs - - Kenan Kahrić (kahric) - - Karsten Gohm (kasn) - - Kik Minev (kikminev) - - Kobe Vervoort (kobevervoort) - - Philip Ardery - - Konrad pap (konrados) - - Vincent AMSTOUTZ (vincent_amstz) - - Korstiaan de Ridder (korstiaan) - - Leonardo Losoviz (leoloso) - - Ricardo Peters (listerical) - - lobodol (lobodol) - - Louis Racicot (lord_stan) - - LOUVEL Mathieu (louvelmathieu) - - Maikel Ortega Hernández (maikeloh) - - imam harir (luxferoo) - - Joachim Martin (michaoj) - - Kevin Papst - - Pierre Maraitre - - Kévin LE LOUËR - - Marko Kunic (kunicmarko20) - - Eduardo Thomas Perez del Postigo (aruku) - - Paulius Masiliūnas (pauliuz) + - Pavel Jurecka + - renepupil + - Sébastien Rogier (srogier) + - Yohann Durand (yohann-durand) + - Rafael Torres + - Ruben Petrosjan + - Michael Grinko + - David Negreira Rios (davidn) + - Jean-Philippe Dépigny + - Julien Chaumond (julien_c) - Fabian Becker - - seangallavan - Maninder Singh (maninder) - - Rémy Vuong (rvuong) - - Manuel Agustín Ordóñez (manuel_agustin) - - Martijn Gastkemper (martijngastkemper) - - samson daniel (samayo) - - Martin Ninov (martixy) - - Manuel Transfeld - - Aleksander Cyrkulewski (martyshka) - - Sam Van der Borght (samvdb) - - Matthieu Danet (matthieu-tmk) - - Carlos Jimenez (saphyel) - - Maurice Svay (mauricesvay) - - Lorenzo Milesi (maxxer) - - Sylvester Saracevas (saracevas) - - Maximilien BERNARD (mb3rnard) - - Marius Büscher (mbuescher) - - Sebastián Poliak (sebastianlpdb) - Mindaugas Liubinas (meandog) - - AntoJ (merguezzz) - - Csaba Maulis (senki) - - Simone Gentili (sensorario) - - Sergey Podgornyy (sergey_podgornyy) - - Marcel Serra Julià (serrajm) - - Sethunath K (sethunath) - - Woody Gilk (shadowhand) + - Mahdi Maghrooni + - Vimal Gorasiya + - Baptiste Langlade + - Alessandro Podo + - Michał Szczech (miisieq) + - Danilo Sanchi (danilo.sanchi) + - Matijn Woudt + - Michael Y Kopinsky (mkopinsky) + - Cadot.eu & Co. + - Matthieu Lempereur (matthieulempereur) + - Bruno Baguette (tournesol) + - Gabriel Birke (chiborg) + - Bill Surgenor + - Léo PLANUS + - Ian Kevin Irlen (kevinirlen) + - Nicolas GIRAUD (niconoe) + - Romain Card + - Ilya Bakhlin Lebedev + - Al-Saleh KEITA + - Stephan Savoundararadj (lkolndeep) + - Paweł Skotnicki (pskt) + - Robert Saylor (rsaylor) + - OrangeVinz (orangevinz) + - Mantas Varatiejus + - Josh Kalderimis + - Lee Boynton + - Richard Lynskey + - Clement Ridoret + - Dan Michael O. Heggø (danmichaelo) + - Laurens Laman (laulaman) + - Hamza Makraz + - alexsaalberg049 + - Dincho Todorov + - fridde + - timothymctim + - Guillaume Rossignol + - Linas Linartas (linas_linartas) + - Carlos Reig (statu) + - James Isaac + - Bruno Ferme Gasparin (bfgasparin) + - Thomas Ploch + - Felipe Martins + - René Backhaus + - Dawid Królak (taavit) + - Aurélien Thieriot + - Kane Menicou (kane-menicou) + - Severin J + - Steven + - Konstantin Tjuterev (kostiklv) + - Loïc Caillieux (loic.caillieux) + - Lyrkan + - A S M Sadiqul Islam (sadiq) + - Rudy Onfroy + - Slaven (sbacelic) + - jonasarts + - fb-erik - Wil Moore (wilmoore) - - Shambhu Kumar (shambhu384) - - Yuri Tkachenko (tamtamchik) - - Simon Van Accoleyen (simonvanacco) - - Slava Belokurski (slavchoo) - - Pol Romans (snamor) - - Steven Chen (squazic) - - Stefan Blanke (stedekay) - - Nicolae Astefanoaie (stelu26) - - Paris mikael (stood) - - Stanislav Zakharov (strannik) - - Sven (svdv22) - - Patrik Gmitter (patie) - - Sven Zissner (svenzissner) - - Artur 'Wodor' Wielogorski - - Jeroen - - Panda INC (pandalowry) - - Kevin Pires (takiin) - - Björn Fromme (bjo3rn) - - Gabriel Pillet (tentacode) - - Toni Conca (tonic) - - Tom Schuermans (tschuermans) - - Attila Egyed (tsm) + - Mohammed Rhamnia (rmed19) + - Daniel Ancuta (whisller) + - tobiasoort + - Илья + - Al Bunch + - Julius (julius1) + - Paul Ferrett (paulf) + - Ronan Guilloux (ronan) + - NicolasPion + - Toni Peric + - Matěj Humpál + - Kwadz + - Luke Kysow + - Clément MICHELET (chiendelune) + - Julien "Nayte" Robic + - d.syph.3r + - Pavel Máca + - Michael Sheakoski + - Boissinot (pierreboissinotlephare) + - Grégory SURACI + - Vincent Le Biannic + - Darmen Amanbayev - Unai Roldán (unairoldan) - - Varun Agrawal (varunagw) - - Josh Freeman (viion) - - Marvin Butkereit - - Vivien Tedesco (vivient) - - skipton-io - - Daniel (voodooprograms) - - WILLEMS Laurent (willemsl) - - Willem-Jan Zijderveld (wjzijderveld) + - GNi33 + - Aikaterine Tsiboukas + - Hatem Ben (hatemben) + - Benjamin Hubert (gouaille) + - Korstiaan de Ridder (korstiaan) + - Dan Zera + - Denis Soriano (dsoriano) + - Jan Christoph Beyer + - Laurent Moreau (laulibrius) + - Robin Weller + - Benjamin Zaslavsky + - Nico Schoenmaker + - Baptiste Pizzighini (bpizzi) + - Łukasz Pior (piorek) + - Kevin Carmody (skinofstars) + - Peter Gasser + - PéCé + - Camille Jouan (ca-jou) + - Miguel Vilata (adder) + - Raistlfiren + - Kevin Wojniak + - Tobias Hermann + - Mohamed Ettaki TALBI (takman) + - Pavel Shirmanov (genzo) + - Rodrigo Capilé (rcapile) + - João Paulo Vieira da Silva + - Dennis de Best (monsteroreo) + - Andrii Volin (angy_v) + - Loïc Sapone (loic_sapone) + - Kostas Loupasakis (loupax) + - Max R + - Cosmic Mac + - Rémi Andrieux (pimolo) + - Sela + - Kane Menicou (kane_menicou) + - Eric Tucker + - Ross Cousens + - Nelson da Costa + - VisionPages + - Seikilos + - CodyFortenberry + - Andréas Hanss + - Florimond Manca + - oyerli + - Giovanni Toraldo + - Michaël Dieudonné + - ismail mezrani (imezrani) + - Christophe Meneses + - Mark (markchicobaby) + - Metfan (metfan) + - Christopher Hoult (choult) + - Clemens Krack (ckrack) + - George Pogosyan (gp) + - Vladimir Schmidt (morgen) + - Sebastián Poliak (sebastianlpdb) + - Tom Schuermans (tschuermans) + - Alexandr Podgorbunschih (apodgorbunschih) + - Daichi Kamemoto (yudoufu) + - Marc Verney + - Brandin Chiu + - TheSidSpears + - Abdellah EL GHAILANI (aelghailani) + - Mark Badolato (mbadolato) + - Kai (kai_dederichs) + - Ejamine + - Raul C + - Thomas Kappel + - Jarvis Stubblefield (ballisticpain) + - robert Parker + - ampt . (ampt) + - Dr. Balazs Zatik + - Milan (milan) + - Niklas + - Mykola Martynov (mykola) + - Nicolas Mugnier + - mohamed + - Daryl Gubler (dev88) + - Quentin ADADAIN + - michael kimsal (kimsal) + - Antoine Durieux (adurieux) + - Gasmi Mohamed (mohamed_gasmi) + - Christophe Willemsen (kwattro) + - Joel Clermont (jclermont) + - Brent Shaffer (bshaffer) + - ThomasGallet + - Phil Moorhouse (lazymanc) + - Pierre-Jean Leger + - unknown + - Ramzi Abdelaziz (ramzi_a) + - Davi Tavares Alexandre (davialexandre) + - Erdal G + - Luuk Scholten (lscholten) + - Bryan J. Agee + - Jérémy Jumeau (jeremyjumeau) + - Daniel Platt (hackzilla) + - ABOULHAJ Abdelhakim (hakim_aboulhaj) + - Hans Stevens (hansstevens) + - Maxime Cornet (elysion) + - Jason Aller (jraller) + - Carlos Granados + - Adoni Pavlakis + - ghertko + - Tim Hovius (timhovius) + - Jérôme Nadaud + - Cyril Mouttet (placid2000) + - Ladislav Kubes + - Sofien NAAS + - Inori + - vmarquez + - Patrick McAndrew (patrick) + - Kirill Baranov (u_mulder) + - Artur Weigandt + - artf + - Maxim (big-shark) + - Petru Szemereczki (hktr92) + - Jan Heller (jahller) + - Roger Llopart Pla (lumbendil) + - Damien Chedan (tcheud) + - Nuno Pereira (nunopereira) + - Romaxx + - Douglas Naphas + - Zairig Imad + - Foksler (foksler) + - AlexKa + - Prisacari Dmitrii + - Evgeniy Guseletov (dark) + - gertdepagter + - Mbechezi Mlanawo + - pgorod + - Robert Freigang (robertfausk) + - faissaloux + - Maxime Doutreluingne (maxdoutreluingne) + - Paweł Krynicki (kryniol) + - Pinchon Karim + - Arndt H. Ziegler + - matteopoile + - JHGitty + - Thierry Thuon + - Jean-Marie Lamodière (jmlamo) + - Dan Barrett (yesdevnull) + - iarro + - Nitaco + - Valentin Ferriere (choomz) + - Vadim Bondarenko + - ehibes + - Phil Wright- Christie (philwc) + - Jordi Freixa Serrabassa + - Kiel Goodman + - Constantin Ross - Wojciech Międzybrodzki (wojciechem) - - Alexandre Mallet (woprrr) - - Paulius Podolskis (wsuff) - - xthiago (xthiago) - - Karel (xwb) - - Daniel LIma (yourwebmaker) - - Yuriy Sergeev (youser) - - Ziad Jammal (ziadjammal) - - Zsolt Javorszky (zsjavorszky) - - Ivan Zugec (zugec) - - Lukas W - - babache - - zan-vseved - - manu-sparheld - - ArlingtonHouse - - Gus - - Reza Rabbani - - yordandv - - mehlichmeyer - - Jens Pliester - - Benjamin Sureau - - Krap - - David Vigo - - KalleV - - Christopher Tatro - - Pooyan Khanjankhani - - Ellis Benjamin - - Sam Jarrett - - Sela - - Nelson da Costa - - Andrea Bergamasco (vjandrea) - - Axel Vankrunkelsven - - snroki - - jivot - - miqrogroove - - Oussama GHAIEB (oussama_tn) - - Thao Nguyen (thaowitkam) - - Christophe Meneses - - Sudhakar Krishnan - - Michaël Perrin - - Kevin - - Kevin - - Christian Schaefer (caefer) - - Hugo Casabella (casahugo) - - Charles Pourcel (ch.pourcel) - - Stephan Savoundararadj (lkolndeep) - - Jon Cave - - Travis Yang (oopsfrogs) - - Francisco Javier Aceituno (javiacei) - - Jo Meuwis (jo_meuwis) - - Joel Costa (joelrfcosta) - - Maxim Spivakovksy (lazyants) - - Lucian Tugui (luciantugui) - - Mehdi Tazi (mehditazi9) - - Michał (mleczakm) - - Gyula Szabó (szabogyula) - - Tomas Nemeikšis (niumis) - - tamir van-spier (tamirvs) - - Joe Mizzi (themizzi) - - Thomas Lomas (tomlomas) - - Kristijan Stipić (stipic) - - Poulette Christophe (totof6942) + - Kristof Coomans (cyberwolf) + - Greg Box (gregfriedrice) - Omar Brahimi (omarbrahimi) - - Sebastian Blum (sebiblum) - - makmaoui - - Olivier Revollat (o_revollat) - - juliendidier - - Michael Cullum (unknownbliss) - - Vincent Amstoutz - - Aurélien ADAM (aadam) + - Luc + - guidokritz + - Timur Murtukov (murtukov) + - John Ballinger + - Bob van de Vijver + - Yosip Curiel (snake77se) + - Kevin R + - Lance Bailey + - Zamir Memmedov (zamir10) + - Joan Teixido (joanteixi) + - Mihail Kyosev (php_lamer) + - Andrei + - Nicolas Hart (nclshart) + - Daniel Degasperi (ddegasperi) + - Sascha Egerer + - Dmytro + - Jacob Tobiasz (jakubtobiasz) + - Ben Huebscher (huebs) + - fguimier + - mojzis - Arnaud Thibaudet (kojiro) - - Alessandro Podo - - Fabien Schurter - - Michał Szczech (miisieq) - - Carlos Reig (statu) - - Nico Hiort af Ornäs - - Ian Kevin Irlen (kevinirlen) - - ifiroth - - Jordan Aubert (jordanaubert) - - Nicolas GIRAUD (niconoe) - - Romain Card - - Ilya Bakhlin Lebedev - - Alessandro Podo - - Hamza Makraz - - Pierre MORADEI - - Julien "Nayte" Robic - - Niklas - - Turdaliev Nursultan (nurolopher) - - Shamil Nunhuck (shamil) + - Damien Fayet + - Nicolas Clavaud (nclavaud) + - Florian CAVASIN + - Pedro Nofuentes (pedronofuentes) + - Andrianovah nirina randriamiamina (novah) - Bart Vanderstukken (sneakyvv) - - Spomky - - Thomas Choquet (tchoquet) - - Marcus Stöhr - - Denis Rendler - - Simon Daigre (simondgre) - - Markus Weiland (advancingu) - - Matheo D - - romain - - Jacob Tobiasz (jakubtobiasz) - - Maxime Douailin - - Jean-François Lépine (halleck45) - - Sait KURT (deswa) - - Maarten de Keizer (maartendekeizer) - - Marwâne (beamop) - - Jannes Drijkoningen (jannesd) - - Kilian Riou (redheness) - - Alexandre Gérault (alexandre-gerault) - - Thomas Choquet (chqthomas3) - - Григорий - - Barun - - Zéfyx - - Pierre Sv (rrr63) - - Denis Soriano (dsoriano) - - Laurent Marquet - - Daniel Garzon (arko) - - Kevin T'Syen (noscope) - - Nehal Gajjar - - jmangarret - - norbert-n - - Vladimir - - Thomas (razbounak) - - Aymen Bouchekoua (nightfox) - - Jan - - Augustin Delaporte - - asandjivy - - YummYume - - Leanna Pelham - - Daniel F. (ragtek) - - Adrien LUCAS - - twisted1919 - - fbuchlak - - Kevin - - Mrtn Schndlr - - Ricardo Rentería - - Sven Petersen - - Yoan Bernabeu - - Simon Riedmeier (simonsolutions) - - Steven DUBOIS (stevenn) - - Colin Poushay (poush) - - Hugo Seigle - - Hendrik Pilz (hendrikpilz) - - Rick Kuipers - - Vancoillie - - optior - - Christoph Grabenstein - - Benoit Jouhaud (bjouhaud) - - David - - matheo - - Jan Christoph Beyer - - Josenilton Junior (zavarock) - - kempha - - Simon - - Marie CHARLES (mariecharles) - - Matijn Woudt - - Valentin GARET (vgaret) - - Nicolas Rigaud - - Jonathan Huteau (jonht) - - Pierre Joye (pierre) - - lucbu - - Bastien70 - - Zbigniew Czapran (zczapran) - - Sander Verkuil (sander-verkuil) - - Fabien (fabiencambournac) - - VelvetMirror - - Bryan J. Agee - - Niels Vermaut (nielsvermaut) - - Fabien Papet - - yoye - - Игорь Дмитриевич Чунихин (6insanes) - - Stephan - - Krzysztof Ilnicki (poh) - - Cassian Assael (crozet) - - Matthew Ratzke (flyboarder) - - Sven Scholz - - Guillaume PARIS (gparis) - - Xavier Laviron (norival) - - Michael Grinko - - Phil Wright- Christie (philwc) - - Edson Medina - - Denys Pasishnyi (dpcat237) - - Plamen - - (H)eDoCode - - Maximilian - - Iv Po - - Greg Berger - - Frédéric Lesueurs - - Matthieu Renard - - Jonas De Keukelaere - - Luc Hidalgo (luchidalgo) - - Julien Dubois - - Ondrej Vana (kachnitel) - - Marchegay (xaviermarcheay) - - Maxime Steinhausser - - Bart Heyrman - - Morgan Thibert (o0morgan0ol) - - Baptiste Fotia (zak39) - - LesRouxDominerontLeMonde - - Yoann B (yoann) - - Johan de Jager (dejagersh) - - Jacob Dreesen + - Deng Zhi Cheng + - Gustavo Henrique Mascarenhas Machado + - Markus Thielen (mathielen) + - Adam Mikolaj (mausino) + - Javi H. Gil (javibilbo) + - Jacob Mather (jmather) + - Darien + - Thomas LEZY + - Stefan hr Berder + - Robin C + - Javier Espinoza + - Bill Israel + - mvanmeerbeck + - phoefnagel + - Guillaume MOREL + - Patrick Bußmann + - Ayyoub BOUMYA (aybbou) + - Jérémy Halin + - Aaron Baker + - Benj + - mbehboodian + - Rafał Mnich (rafalmnich-msales) + - Mathieu + - Julien EMMANUEL + - Janne Vuori (jimzalabim) + - Michał Kurcewicz (mkurc1) + - nencho nencho (nencho) + - Kai Eichinger (kai_eichinger) + - Matthew Loberg (mloberg) + - Ryszard Piotrowski (richardpi) + - Ludwig Ruderstaller (rufinus) + - Nuno Ferreira (nunojsferreira) + - Michael Sivolobov (astronomer) + - Joshua (suabahasa) + - Steven DUBOIS (stevenn) + - Hugo Seigle + - rayrigam + - piet + - Simon Riedmeier (simonsolutions) + - Koen van Wijnen (infotracer) + - Robin Delbaere (rdelbaere) + - Daniel Felix (danielfellix) + - Susheel Thapa - Marco Polichetti - - Joe + - Albert Moreno + - Pedro Gimenez + - Ahmed Raafat (luffy14) + - Jorick Pepin (jorick) + - Sebastian Klaus + - Massimo Giagnoni (mgiagnoni) + - Thibault Pelloquin (thibault_pelloquin) + - Mario Martinez (chichibek) + - Maik Penz + - Zsolt Javorszky (zsjavorszky) + - Aaron Valandra + - Slava Fomin II (s-fomin) + - Markus Tacker + - Andrei Chugunov + - Jan G. (jan) + - Dimitar + - Abdellah Ramadan (abdellahrk) + - Arthur Hazebroucq + - Wouter + - Jonathan Huteau (jonht) - Jérémy CROMBEZ - - Raphaël Davaillaud - - vesselind - - Joseph Bielawski - - Yannick - - Nieck Moorman - - John Ballinger - - Bob van de Vijver - - github-actions[bot] - - Nicolas Lœuillet (nicosomb) - - Antoine Durieux (adurieux) - - Roger Webb (webb.roger) - - sander Haanstra (milosa) - - Denis (ruff3d) - - Pierre-Emmanuel CAPEL (pecapel) - - Lucas Courot (lucascourot) - - Pavel Nemchenko (nemoipaha) - - Jerome Guilbot (papy_danone) - - Adam - - Ahmed Siouani (ahsio) - - matthieu88160 - - Grant Gaudet - - bdujon - - Simon BLUM (simonblum) - - Tom Schwiha (tomschwiha) - - Thomas Miceli (tomus) + - Marek Bartoš + - Pedro Cordeiro + - sparrowek + - Nikola Kuzmanović (nkuzman) + - Eirik Alfstad Johansen (nmeirik) - stehled - healdropper - - Sebastian Kuhlmann (zebba) - - Saidou GUEYE - - Yoan Arnaudov (nacholibre) - - Florian - - Michael Petri (michaelpetri) - - Levin - - Mark Deanil Vicente (dvincent3) - - Laurent Moreau (laulibrius) - - Robin Weller - - Benjamin Zaslavsky - - Mart Kop - - Ruud Kamphuis - - Dmytro - - Yakov Lipkovich - - Fabien Bourigault - - Leonard Simonse - - Rhodri Pugh - - Tristan Darricau - - John Williams - - Nadim AL ABDOU - - Mateusz Anders - - Wanne Van Camp - - Jasperator - - anton - - Marius Adam + - Steven Chen (squazic) + - Martin Ninov (martixy) + - Yves ASTIER + - harcod + - beejaz + - Brice Lalu (bricelalu) + - Alexandre Castelain (calex_92) + - Michal Landsman + - Alex Savkov + - Alistair (phiali) + - Clément Notin + - Erik Trapman + - Guillaume Ponty + - amelie le coz (amelielcz) + - decima + - alexmart + - Juan Manuel Fernandez (juanmf) + - Epskampie + - Daniele Orler + - Casey Heagerty + - kraksoft - Vladimir Jimenez - - Robin - - Gary Kovar - - Jalen - - Tomi Saarinen (tomis) - - Issam KHADIRI (ikhadiri) - - Wagner Nicolas (n1c01a5) - - Lorenzo Ruozzi (lruozzi9) - - Marko Kaznovac - - DOEO - - Marc Wustrack (muffe) - - Loïc Caillieux (loic.caillieux) - - Alexey Pyltsyn (lex111) - - benti - - Dennis de Best (monsteroreo) - - Ludwig Bayerl (lbayerl) - - Carlos Sánchez (carlossg00) - - Darien Hager - - Jérémy Jumeau (jeremyjumeau) - - Paweł Krynicki (kryniol) - - Tamás Molnár (moltam) - - Robin Willig (dragonito) - - Robert Parker (yamiko) - - Pedro Nofuentes (pedronofuentes) - - mojzis - - Fanny Gautier - - Alexey Samara - - gong023 - - Jan Dorsman - - xaav - - Aurelijus Banelis (aurelijusb) - - Christophe Debruel (krike06) + - g@8vue.com + - Keefe Kwan (kkwan) + - rs + - Mbechezi Mlanawo + - Łukasz Korczewski + - Joe + - Thomas Choquet (chqthomas3) + - htmlshaman1 + - Ivan Zugec (zugec) + - Petr (rottenwood) + - ameotoko + - (H)eDoCode + - Abdelkader Bouadjadja (medinae) + - Игорь Дмитриевич Чунихин (6insanes) + - github-actions[bot] + - Alexander Marinov + - Manoj Kumar - shkkmo - - Yaroslav Kiliba - - Tony Cosentino + - Dan Abrey + - Emil Santi (emilius) + - Dean Clatworthy + - timglabisch + - yoye + - Edym Komlan BEDY (youngmustes) + - ArlingtonHouse + - Eduardo Gulias Davis + - Ali Arfeen + - kevin + - Arvydas K + - Calin Pristavu (calinpristavu) + - Maxime Nicole + - aziz benmallouk (aziz403) + - Andrius Ulinskas (andriusulins) + - David Zuelke (dzuelke) + - Brooks Van Buren (brooksvb) + - Michał (mleczakm) + - Tomas Nemeikšis (niumis) + - tamir van-spier (tamirvs) + - Travis Carden + - Valyaev Ilya (rumours86) + - Przemek Maszczynski + - Björn Fromme (bjo3rn) + - Pascal de Vink (pascaldevink) + - Moroine Bentefrit + - Markus Mauksch + - Dylan Delobel (dylandelobel) + - ubick + - Aurélien Morvan + - Daniel Karp + - Hyunmin Kim (kigguhholic) + - Marc Verney + - Thibault Gattolliat (crovitche) + - Cyril Lussiana + - Aurelijus Banelis (aurelijusb) + - Claudio Galdiolo + - Valentin GARET (vgaret) + - Guillermo Quinteros (guquinteros) + - Quentin Stoeckel (chteuchteu) + - Hugo Clergue + - Kevin Robatel (kevinrob) + - Janosch Oltmanns (janosch_oltmanns) + - Andrei Karpilin (karpilin) + - Kolyunya (kolyunya) + - Max R (maxr) + - PHAS Developer + - Cyril Krylatov + - Florent Destremau + - Marc Neuhaus (mneuhaus) + - Anton + - Arc Tod + - Clorr + - DanielEScherzer + - Exalyon + - Mikhail Kamarouski + - dpfaffenbauer + - Cristi Contiu (cristi-contiu) + - Tim + - Andy Truong + - pfleu + - Ivan Ternovtsiy + - Simon Daigre (simondgre) + - Matheo D + - Andy Dawson + - Rémi T'JAMPENS (tjamps) + - Danny van Wijk (dannyvw) + - Ellis Benjamin + - Jan Dorsman + - Nicolas Rigaud + - Adam + - matthieu88160 + - rklaver + - Daniel Haaker (dhaaker) - burki94 - - Kostya - - alexchuin - - Szyszewski - - Nils Silbernagel - - Adrien - - Andrei Chugunov - - Jan G. (jan) - - Ahmed Raafat (luffy14) - - azielinski - - Thibault Gattolliat (crovitche) - - Dimitar - - Florent Destremau - - Marc Neuhaus (mneuhaus) + - Alexey Samara + - gong023 + - xaav + - Jay-Way + - lucbu + - Jordan Bradford + - Hocdoc - Niklas Grießer - Cullen Walsh - - damien-louis + - Salavat Sitdikov (sitsalavat) + - Vincent Amstoutz - Olena Kirichok - - Julian Mallett (jxmallett) - - Romain Norberg - - Steven - - hector prats (jovendigital) - - Koen van Wijnen (infotracer) - - Michael Y Kopinsky (mkopinsky) - - Roger Llopart Pla (lumbendil) - - David Zuelke (dzuelke) - - Abdelkader Bouadjadja (medinae) - - Eduardo Gulias Davis - - Dmitry Vishin (wishmaster) - - Alfonso M. García Astorga (alfonsomga) - - José María Sanchidrián (sanmar) - - Diego Gullo (bizmate) - - martin05 - - Bruno Vitorino - - Noel - - beram (beram) - - Markus Mauksch - - Mitchell - - Avindra Goolcharan - - Florent - - roga - - Timon F. (timon) - - Denis-Florin Rendler - - Titouan B - - IlhamiD - - Alexander Marinov - - Manoj Kumar - - Nazar Mammedov - - Maxime Nicole - - pecapel - - Cadot.eu & Co. - Matthias Gutjahr (mattsches) - - Dan Abrey - - Matthieu Lempereur (matthieulempereur) - - Sylvain Blondeau - - Maelan LE BORGNE (maelanleborgne) - - jmsche - - Rutger - - Tim Glabisch - - g@8vue.com - - danjamin - - Ondřej Vodáček - - mark2016 - - Petr (rottenwood) - - Łukasz Pior (piorek) - - revollat - - Jorick Pepin (jorick) - - micter59 - - unknown - - Rob - - Tajh Leitso (tajh) - - Wolfgang Weintritt (wolwe) - - Bram van Leur (bvleur) - - BooleanType - - Luke Kysow - - Zac Sturgess (zsturgess) - - t.le-gacque - - Hugo Locurcio - - Mohd Shakir Zakaria (mohdshakir) - - Yohann Durand (yohann-durand) - - Konstantin Tjuterev (kostiklv) - - Alexandru Furculita ♻ - - amelie le coz (amelielcz) - - Thibaud BARDIN (irvyne) - - Jérémy BLONDEAU (jblondeau2) - - Adoni Pavlakis - - valepu - - Hans Allis (hansallis) - - Marek Brieger (polmabri) - - Lluis Toyos (tolbier) - - Jarvis Stubblefield (ballisticpain) - - Mathieu Ducrot (mathieu-ducrot) - - Daniel Santana - - Adam W (axzx) - - Francisco Calderón (fcalderon) - - HONORE HOUNWANOU (mercuryseries) - - yanickj - - Evan Owens - - S Berder - - Félix Fouillet - - Tobias Berchtold - - Pavel Bezdverniy - - Dr. Balazs Zatik - - Carsten Blüm (bluem) - - Omer Karadagli (omer) - - OrangeVinz (orangevinz) - - ThomasGallet - - Jarek Ikaniewicz - - Daniel Degasperi (ddegasperi) - - Milan (milan) - - Patrick Bußmann - - Kamil Kuzminski (qzminski) - - Happy (ha99ys) - - AlexKa - - Foksler (foksler) - - Sacha Durand (sacha_durand) - - Tom Grandy - - Epskampie - - Francesco Tassi (ftassi) - - Jason Bouffard (jpb0104) - - Katharina Floh (katharina-floh) - - Christopher - - Nicolas Hart (nclshart) - - Christopher Moll - - Gianluca Farinelli (rshelter) - - Jorge Luis Betancourt (jorgelbg) - - Yannick (yannickdurden) - - Dynèsh Hassanaly (dynesh) - - Tom Maaswinkel (thedevilonline) + - Simon Appelt - Thibault Miscoria (tmiscoria) - - Alexpts (alexpts) - - Michiel Missotten (zenklys) - - Benjamin Clay (ternel) - - Mark Challoner - - Jacob Mather (jmather) - - Fabien Bourigault - - Adil YASSINE ✌️ (sf2developer) - - Savvas Alexandrou (savvasal) - - Tim Jabs - - LucileDT - - Open Orchestra (open-orchestra) - - Salavat Sitdikov (sitsalavat) - - Iulian Popa (iulyanp) - - AmalricBzh - - htmlshaman1 - - Aleksandr Frolov (thephilosoft) - - Valantis Koutsoumpos - - Slava Fomin II (s-fomin) - - Raúl Continente (raulconti) - - Daniel West (silverbackdan) - - Martin Bens - - Robert - - Ross Cousens - - Murilo Lobato (murilolobato) - - Tim Krase - - Kendrick - - Bastien Picharles (kleinast) - - Metfan (metfan) - - Sylvain Combes (sylvaincombes) - - Daniel Haaker (dhaaker) - - Mark (markchicobaby) - - Lenkov Michail (alchimik) - - Florent DESPIERRES (fdespierres) - - Anton - - Cyril Lussiana - - Valentin Silvestre (vasilvestre) - - Vincent Le Biannic - - Adam Szaraniec (mimol) - - Abdellah Ramadan (abdellahrk) - - Tim Hovius (timhovius) - - Julian (c33s) - - Ryan Castle (ryancastle) - - Chad Meyers (nobodyfamous) - - Ben Huebscher (huebs) - - William JEHANNE (william_jehanne) - - mhor (mhor) - - richardudovich - - pathmissing - - Soltész Balázs - - Ben Glassman (benglass) - - Thomas Botton (skeud) - - Mohammed Rhamnia (rmed19) - - Thomas Talbot - - Douglas Naphas - - Ilya Antipenko - - karzz - - Markus Frühauf - - Damien Carrier (mirakusan) - - Nassim - - Enzo Santamaria - - Jonathan Finch - - Herbert Muehlburger - - Dawid Królak (taavit) - - Toni Peric - - Danil Pyatnitsev (pyatnitsev) - - Julien Bonnier (jbonnier) - - Geert Eltink - - Martin Melka - - Bert Van de Casteele - - Olivier Bacs (obax) - - Ayyoub BOUMYA (aybbou) - - Phil Moorhouse (lazymanc) - - Dorthe Luebbert (luebbert42) - - Sylvain - - Michelle Sanver (michellesanver) - - Rafael Mello (merorafael) - - Arthur Hazebroucq - - Michel D'HOOGE (mdhooge) - - Yair Silbermintz (mrglass) - - Patrick McAndrew (patrick) - - Kirill Baranov (u_mulder) - - Mynyx - - Artur Weigandt - - Baptiste Langlade - - Amitay Horwitz (amitayh) - - Manel Sellés (manelselles) - - ahinkle - - Lucas Nothnagel (scriptibus) - - Egidijus Gircys - - fridde - - Evgeniy Guseletov (dark) - - Edoardo Rivello (erivello) - - Malte N (hice3000) - - Elias Van Ootegem - - Boissinot (pierreboissinotlephare) - - Jan De Coster - - Sam Hudson - - Marcus Schwarz + - Nik Spijkerman + - Florian VANHECKE + - Zombaya + - Zenobius + - adreeun + - Mark Fischer, Jr + - bram vogelaar (attachmentgenie) + - ThamiSadouk + - M E (ttc) + - Yassine Fikri (yassinefikri) + - Younes OUASSI (youassi) + - Chris8934 + - Quentin Thiaucourt (quentint) + - homersimpsons + - Benjamin Toussaint + - anton + - Tony Cosentino + - Kostya + - alexchuin + - Szyszewski + - Nils Silbernagel diff --git a/UPGRADE-7.4.md b/UPGRADE-7.4.md new file mode 100644 index 0000000000000..74b9cb0f458db --- /dev/null +++ b/UPGRADE-7.4.md @@ -0,0 +1,231 @@ +UPGRADE FROM 7.3 to 7.4 +======================= + +Symfony 7.4 is a minor release. According to the Symfony release process, there should be no significant +backward compatibility breaks. Minor backward compatibility breaks are prefixed in this document with +`[BC BREAK]`, make sure your code is compatible with these entries before upgrading. +Read more about this in the [Symfony documentation](https://symfony.com/doc/7.4/setup/upgrade_minor.html). + +If you're upgrading from a version below 7.3, follow the [7.3 upgrade guide](UPGRADE-7.3.md) first. + +BrowserKit +---------- + + * Deprecate `AbstractBrowser::useHtml5Parser()`; Symfony 8 will unconditionally use the native HTML5 parser + +Cache +----- + + * Bump ext-redis to 6.2 and ext-relay to 0.11 minimum + +Console +------- + + * Deprecate `Symfony\Component\Console\Application::add()` in favor of `addCommand()` + +DependencyInjection +------------------- + + * Add argument `$target` to `ContainerBuilder::registerAliasForArgument()` + * Deprecate registering a service without a class when its id is a non-existing FQCN + +DoctrineBridge +-------------- + + * Deprecate `UniqueEntity::getRequiredOptions()` and `UniqueEntity::getDefaultOption()` + +DomCrawler +---------- + + * Disabling HTML5 parsing is deprecated; Symfony 8 will unconditionally use the native HTML5 parser + +FrameworkBundle +--------------- + + * Deprecate `Symfony\Bundle\FrameworkBundle\Console\Application::add()` in favor of `addCommand()` + +HtmlSanitizer +------------- + + * Use the native HTML5 parser when using PHP 8.4+ + * Deprecate `MastermindsParser`; use `NativeParser` instead + * [BC BREAK] `ParserInterface::parse()` can now return `\Dom\Node|\DOMNode|null` instead of just `\DOMNode|null` + * Add argument `$context` to `ParserInterface::parse()` + +HttpClient +---------- + + * Deprecate using amphp/http-client < 5 + +HttpFoundation +-------------- + + * Deprecate using `Request::sendHeaders()` after headers have already been sent; use a `StreamedResponse` instead + +HttpKernel +---------- + + * Deprecate implementing `__sleep/wakeup()` on kernels; use `__(un)serialize()` instead + * Deprecate implementing `__sleep/wakeup()` on data collectors; use `__(un)serialize()` instead + * Make `Profile` final and `Profiler::__sleep()` internal + +Mime +---- + + * Deprecate implementing `__sleep/wakeup()` on `AbstractPart` implementations; use `__(un)serialize()` instead + +Routing +------- + + * Deprecate class aliases in the `Annotation` namespace, use attributes instead + * Deprecate getters and setters in attribute classes in favor of public properties + +Security +-------- + + * Deprecate callable firewall listeners, extend `AbstractListener` or implement `FirewallListenerInterface` instead + * Deprecate `AbstractListener::__invoke` + * Deprecate `LazyFirewallContext::__invoke()` + +Serializer +---------- + + * Make `AttributeMetadata` and `ClassMetadata` final + * Deprecate class aliases in the `Annotation` namespace, use attributes instead + * Deprecate getters in attribute classes in favor of public properties + +String +------ + + * Deprecate implementing `__sleep/wakeup()` on string implementations + +Translation +----------- + + * Deprecate `TranslatableMessage::__toString` + +Validator +--------- + + * Deprecate implementing `__sleep/wakeup()` on `GenericMetadata` implementations; use `__(un)serialize()` instead + * Deprecate passing a list of choices to the first argument of the `Choice` constraint. Use the `choices` option instead + * Deprecate `getRequiredOptions()` and `getDefaultOption()` methods of the `All`, `AtLeastOneOf`, `CardScheme`, `Collection`, + `CssColor`, `Expression`, `Regex`, `Sequentially`, `Type`, and `When` constraints + * Deprecate evaluating options in the base `Constraint` class. Initialize properties in the constructor of the concrete constraint + class instead + + *Before* + + ```php + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + } + ``` + + *After* + + ```php + use Symfony\Component\Validator\Attribute\HasNamedArguments; + + class CustomConstraint extends Constraint + { + #[HasNamedArguments] + public function __construct( + public $option1 = null, + public $option2 = null, + ?array $groups = null, + mixed $payload = null, + ) { + parent::__construct(null, $groups, $payload); + } + } + ``` + + * Deprecate the `getRequiredOptions()` method of the base `Constraint` class. Use mandatory constructor arguments instead + + *Before* + + ```php + class CustomConstraint extends Constraint + { + public $option1; + public $option2; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + + public function getRequiredOptions() + { + return ['option1']; + } + } + ``` + + *After* + + ```php + use Symfony\Component\Validator\Attribute\HasNamedArguments; + + class CustomConstraint extends Constraint + { + #[HasNamedArguments] + public function __construct( + public $option1, + public $option2 = null, + ?array $groups = null, + mixed $payload = null, + ) { + parent::__construct(null, $groups, $payload); + } + } + ``` + * Deprecate the `normalizeOptions()` and `getDefaultOption()` methods of the base `Constraint` class without replacements; + overriding them in child constraint will not have any effects starting with Symfony 8.0 + * Deprecate passing an array of options to the `Composite` constraint class. Initialize the properties referenced with `getNestedConstraints()` + in child classes before calling the constructor of `Composite` + + *Before* + + ```php + class CustomCompositeConstraint extends Composite + { + public array $constraints = []; + + public function __construct(?array $options = null) + { + parent::__construct($options); + } + + protected function getCompositeOption(): string + { + return 'constraints'; + } + } + ``` + + *After* + + ```php + use Symfony\Component\Validator\Attribute\HasNamedArguments; + + class CustomCompositeConstraint extends Composite + { + #[HasNamedArguments] + public function __construct( + public array $constraints, + ?array $groups = null, + mixed $payload = null) + { + parent::__construct(null, $groups, $payload); + } + } + ``` diff --git a/composer.json b/composer.json index 20bcb49c4b782..f990302d7ea26 100644 --- a/composer.json +++ b/composer.json @@ -49,12 +49,13 @@ "psr/log": "^1|^2|^3", "symfony/contracts": "^3.6", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-grapheme": "~1.33", "symfony/polyfill-intl-icu": "~1.0", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php83": "^1.28", + "symfony/polyfill-php85": "^1.32", "symfony/polyfill-uuid": "^1.15" }, "replace": { @@ -156,7 +157,7 @@ "seld/jsonlint": "^1.10", "symfony/amphp-http-client-meta": "^1.0|^2.0", "symfony/mercure-bundle": "^0.3", - "symfony/phpunit-bridge": "^6.4|^7.0", + "symfony/phpunit-bridge": "^7.4|^8.0", "symfony/runtime": "self.version", "symfony/security-acl": "~2.8|~3.0", "symfony/webpack-encore-bundle": "^1.0|^2.0", @@ -167,6 +168,8 @@ }, "conflict": { "ext-psr": "<1.1|>=2", + "ext-redis": "<6.2", + "ext-relay": "<0.11", "amphp/amp": "<2.5", "async-aws/core": "<1.5", "doctrine/collections": "<1.8", diff --git a/phpunit b/phpunit index dafe2953a0aa6..816271533ee0b 100755 --- a/phpunit +++ b/phpunit @@ -6,7 +6,11 @@ if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) { exit(1); } if (!getenv('SYMFONY_PHPUNIT_VERSION')) { - putenv('SYMFONY_PHPUNIT_VERSION=9.6'); + if (\PHP_VERSION_ID >= 80300) { + putenv('SYMFONY_PHPUNIT_VERSION=12.3'); + } else { + putenv('SYMFONY_PHPUNIT_VERSION=11.5'); + } } if (!getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) { putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=deprecations=1'); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 27418b4002971..72aee6a3002db 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -46,7 +47,7 @@ - + ./src/Symfony/ @@ -65,28 +66,11 @@ ./src/Symfony/Component/*/*/vendor ./src/Symfony/Contracts/*/vendor - + - - - - - - - Cache\IntegrationTests - Symfony\Bridge\Doctrine\Middleware\Debug - Symfony\Bridge\Doctrine\Middleware\IdleConnection - Symfony\Component\Cache - Symfony\Component\Cache\Tests\Fixtures - Symfony\Component\Cache\Tests\Traits - Symfony\Component\Cache\Traits - Symfony\Component\Console - Symfony\Component\HttpFoundation - Symfony\Component\Uid - - - - - - + + + + + diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index 961a0965d3431..3caa01a002787 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.4 +--- + + * Deprecate `UniqueEntity::getRequiredOptions()` and `UniqueEntity::getDefaultOption()` + 7.3 --- diff --git a/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php b/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php index 2ac99ae110949..69b90a449a7ba 100644 --- a/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php +++ b/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php @@ -45,7 +45,7 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array foreach ($this->registry->getManagers() as $em) { // we need the directory no matter the proxy cache generation strategy if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) { - if (false === @mkdir($proxyCacheDir, 0777, true) && !is_dir($proxyCacheDir)) { + if (false === @mkdir($proxyCacheDir, 0o777, true) && !is_dir($proxyCacheDir)) { throw new \RuntimeException(\sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir)); } } elseif (!is_writable($proxyCacheDir)) { diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 83d8a85aed96d..fa62e27136175 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -153,7 +153,7 @@ protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \Re } if (!$bundleConfig['dir']) { - if (\in_array($bundleConfig['type'], ['staticphp', 'attribute'])) { + if (\in_array($bundleConfig['type'], ['staticphp', 'attribute'], true)) { $bundleConfig['dir'] = $bundleClassDir.'/'.$this->getMappingObjectDefaultName(); } else { $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingResourceConfigDirectory($bundleDir); @@ -225,7 +225,7 @@ protected function assertValidMappingConfiguration(array $mappingConfig, string throw new \InvalidArgumentException(\sprintf('Specified non-existing directory "%s" as Doctrine mapping source.', $mappingConfig['dir'])); } - if (!\in_array($mappingConfig['type'], ['xml', 'yml', 'php', 'staticphp', 'attribute'])) { + if (!\in_array($mappingConfig['type'], ['xml', 'yml', 'php', 'staticphp', 'attribute'], true)) { throw new \InvalidArgumentException(\sprintf('Can only configure "xml", "yml", "php", "staticphp" or "attribute" through the DoctrineBundle. Use your own bundle to configure other metadata drivers. You can register them by adding a new driver to the "%s" service definition.', $this->getObjectManagerElementName($objectManagerName.'_metadata_driver'))); } } diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php index ce748ad325978..9b2eef74307d4 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php @@ -48,7 +48,7 @@ public function __construct( $singleId = $this->associationIdReader->isSingleId(); $this->intId = $this->associationIdReader->isIntId(); } else { - $this->intId = $singleId && \in_array($idType, ['integer', 'smallint', 'bigint']); + $this->intId = $singleId && \in_array($idType, ['integer', 'smallint', 'bigint'], true); $this->associationIdReader = null; } diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index fd2e764f57c33..7428b4ec58534 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -61,13 +61,13 @@ public function getEntitiesByIds(string $identifier, array $values): array // Guess type $entity = current($qb->getRootEntities()); $metadata = $qb->getEntityManager()->getClassMetadata($entity); - if (\in_array($type = $metadata->getTypeOfField($identifier), ['integer', 'bigint', 'smallint'])) { + if (\in_array($type = $metadata->getTypeOfField($identifier), ['integer', 'bigint', 'smallint'], true)) { $parameterType = ArrayParameterType::INTEGER; // Filter out non-integer values (e.g. ""). If we don't, some // databases such as PostgreSQL fail. $values = array_values(array_filter($values, fn ($v) => (string) $v === (string) (int) $v || ctype_digit($v))); - } elseif (\in_array($type, ['ulid', 'uuid', 'guid'])) { + } elseif (\in_array($type, ['ulid', 'uuid', 'guid'], true)) { $parameterType = ArrayParameterType::STRING; // Like above, but we just filter out empty strings. diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index 36d2e33e4e091..a4b0e13a22fc1 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -134,7 +134,7 @@ public function guessMaxLength(string $class, string $property): ?ValueGuess return new ValueGuess($length, Guess::HIGH_CONFIDENCE); } - if (\in_array($ret[0]->getTypeOfField($property), [Types::DECIMAL, Types::FLOAT])) { + if (\in_array($ret[0]->getTypeOfField($property), [Types::DECIMAL, Types::FLOAT], true)) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } @@ -146,7 +146,7 @@ public function guessPattern(string $class, string $property): ?ValueGuess { $ret = $this->getMetadata($class); if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { - if (\in_array($ret[0]->getTypeOfField($property), [Types::DECIMAL, Types::FLOAT])) { + if (\in_array($ret[0]->getTypeOfField($property), [Types::DECIMAL, Types::FLOAT], true)) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php b/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php index 8207317803857..39f60320a5e9c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php @@ -16,6 +16,9 @@ use Doctrine\Persistence\Mapping\ClassMetadata; use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectRepository; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver; @@ -64,9 +67,8 @@ public function testResolveWithoutManager() $this->assertSame([], $resolver->resolve($request, $argument)); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testResolveWithNoIdAndDataOptional() { $manager = $this->createMock(ObjectManager::class); @@ -108,9 +110,7 @@ public function testResolveWithStripNulls() $this->assertSame([], $resolver->resolve($request, $argument)); } - /** - * @dataProvider idsProvider - */ + #[DataProvider('idsProvider')] public function testResolveWithId(string|int $id) { $manager = $this->createMock(ObjectManager::class); @@ -136,9 +136,7 @@ public function testResolveWithId(string|int $id) $this->assertSame([$object], $resolver->resolve($request, $argument)); } - /** - * @dataProvider idsProvider - */ + #[DataProvider('idsProvider')] public function testResolveWithIdAndTypeAlias(string|int $id) { $manager = $this->getMockBuilder(ObjectManager::class)->getMock(); @@ -251,9 +249,8 @@ public static function idsProvider(): iterable yield ['foo']; } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testResolveGuessOptional() { $manager = $this->createMock(ObjectManager::class); diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php index b64a1cc4475c6..7138e1721b516 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -15,6 +15,7 @@ use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector; use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder; @@ -148,9 +149,7 @@ public function testReset() $this->assertEquals([], $c->getQueries()); } - /** - * @dataProvider paramProvider - */ + #[DataProvider('paramProvider')] public function testCollectQueries($param, $types, $expected) { $queries = [ @@ -199,9 +198,7 @@ public function testCollectQueryWithNoParams() $this->assertTrue($collectedQueries['default'][1]['runnable']); } - /** - * @dataProvider paramProvider - */ + #[DataProvider('paramProvider')] public function testSerialization($param, array $types, $expected) { $queries = [ diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php index 75cc439cd9923..91ca76b14972b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension; @@ -145,9 +146,7 @@ public static function getAutomappingData() ]; } - /** - * @dataProvider getAutomappingData - */ + #[DataProvider('getAutomappingData')] public function testFixManagersAutoMappings(array $originalEm1, array $originalEm2, array $expectedEm1, array $expectedEm2) { $emConfigs = [ @@ -187,9 +186,7 @@ public static function providerBasicDrivers(): array ]; } - /** - * @dataProvider providerBasicDrivers - */ + #[DataProvider('providerBasicDrivers')] public function testLoadBasicCacheDriver(string $class, array $config, array $expectedCalls = []) { $container = $this->createContainer(); @@ -270,9 +267,7 @@ public static function providerBundles(): iterable yield ['NewXmlBundle', 'xml', '/config/doctrine']; } - /** - * @dataProvider providerBundles - */ + #[DataProvider('providerBundles')] public function testBundleAutoMapping(string $bundle, string $expectedType, string $dirSuffix) { $bundleDir = __DIR__.'/../Fixtures/Bundles/'.$bundle; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeObjectNoToStringIdEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeObjectNoToStringIdEntity.php index ee584fa45bdaa..ced4618e7de0c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeObjectNoToStringIdEntity.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/CompositeObjectNoToStringIdEntity.php @@ -22,12 +22,12 @@ class CompositeObjectNoToStringIdEntity public function __construct( #[ORM\Id] #[ORM\ManyToOne(cascade: ['persist'])] - #[ORM\JoinColumn(name: 'object_one_id', nullable: false)] + #[ORM\JoinColumn(name: 'object_one_id')] protected SingleIntIdNoToStringEntity $objectOne, #[ORM\Id] #[ORM\ManyToOne(cascade: ['persist'])] - #[ORM\JoinColumn(name: 'object_two_id', nullable: false)] + #[ORM\JoinColumn(name: 'object_two_id')] protected SingleIntIdNoToStringEntity $objectTwo, ) { } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleAssociationToIntIdEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleAssociationToIntIdEntity.php index 0373417b2c8bb..83dc1e2330592 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleAssociationToIntIdEntity.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleAssociationToIntIdEntity.php @@ -22,7 +22,7 @@ class SingleAssociationToIntIdEntity { public function __construct( #[Id, OneToOne(cascade: ['ALL'])] - #[JoinColumn(nullable: false)] + #[JoinColumn()] protected SingleIntIdNoToStringEntity $entity, #[Column(nullable: true)] diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index 017b327b8a6eb..bbbb7459f1b5d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -17,6 +17,7 @@ use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\Query; use Doctrine\ORM\QueryBuilder; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; @@ -111,9 +112,7 @@ public function testFilterNonIntegerValues() $loader->getEntitiesByIds('id', [1, '', 2, 3, 'foo', '9223372036854775808']); } - /** - * @dataProvider provideGuidEntityClasses - */ + #[DataProvider('provideGuidEntityClasses')] public function testFilterEmptyUuids(string $entityClass) { $em = DoctrineTestHelper::createTestEntityManager(); @@ -145,9 +144,7 @@ public function testFilterEmptyUuids(string $entityClass) $loader->getEntitiesByIds('id', ['71c5fd46-3f16-4abb-bad7-90ac1e654a2d', '', 'b98e8e11-2897-44df-ad24-d2627eb7f499']); } - /** - * @dataProvider provideUidEntityClasses - */ + #[DataProvider('provideUidEntityClasses')] public function testFilterUid(string $entityClass) { if (Type::hasType('uuid')) { @@ -188,9 +185,7 @@ public function testFilterUid(string $entityClass) $loader->getEntitiesByIds('id', ['71c5fd46-3f16-4abb-bad7-90ac1e654a2d', '', 'b98e8e11-2897-44df-ad24-d2627eb7f499']); } - /** - * @dataProvider provideUidEntityClasses - */ + #[DataProvider('provideUidEntityClasses')] public function testUidThrowProperException(string $entityClass) { if (Type::hasType('uuid')) { diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php index 930ee9994879e..b55ac9c0f3549 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php @@ -17,6 +17,7 @@ use Doctrine\ORM\Mapping\ManyToOneAssociationMapping; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser; use Symfony\Component\Form\Guess\Guess; @@ -25,9 +26,7 @@ class DoctrineOrmTypeGuesserTest extends TestCase { - /** - * @dataProvider requiredType - */ + #[DataProvider('requiredType')] public function testTypeGuesser(string $type, $expected) { $classMetadata = $this->createMock(ClassMetadata::class); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php index e010600c9165c..600374ee37d1b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php @@ -14,6 +14,7 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Framework\Attributes\Group; use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity; @@ -81,9 +82,8 @@ protected function setUp(): void /** * This test case is realistic in collection forms where each * row contains the same entity field. - * - * @group benchmark */ + #[Group('benchmark')] public function testCollapsedEntityField() { $this->setMaxRunningTime(1); @@ -98,9 +98,7 @@ public function testCollapsedEntityField() } } - /** - * @group benchmark - */ + #[Group('benchmark')] public function testCollapsedEntityFieldWithChoices() { $choices = $this->em->createQuery('SELECT c FROM '.self::ENTITY_CLASS.' c')->getResult(); @@ -117,9 +115,7 @@ public function testCollapsedEntityFieldWithChoices() } } - /** - * @group benchmark - */ + #[Group('benchmark')] public function testCollapsedEntityFieldWithPreferredChoices() { $choices = $this->em->createQuery('SELECT c FROM '.self::ENTITY_CLASS.' c')->getResult(); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index aa12fdb7752b0..a61da6dc5db04 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -16,6 +16,7 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension; use Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser; @@ -119,9 +120,7 @@ public function testInvalidClassOption() ]); } - /** - * @dataProvider choiceTranslationDomainProvider - */ + #[DataProvider('choiceTranslationDomainProvider')] public function testChoiceTranslationDomainIsDisabledByDefault($expanded) { $entity1 = new SingleIntIdEntity(1, 'Foo'); diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php index 4803e6acaf0af..3e94e03565b63 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -12,6 +12,8 @@ namespace Symfony\Bridge\Doctrine\Tests; use Doctrine\Persistence\ObjectManager; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Tests\Fixtures\DummyManager; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -49,11 +51,8 @@ public function testResetService() $this->assertFalse(isset($foo->bar)); } - /** - * @requires PHP 8.4 - * - * @dataProvider provideResetServiceWithNativeLazyObjectsCases - */ + #[DataProvider('provideResetServiceWithNativeLazyObjectsCases')] + #[RequiresPhp('8.4')] public function testResetServiceWithNativeLazyObjects(string $class) { $container = new $class(); @@ -107,7 +106,7 @@ public static function provideResetServiceWithNativeLazyObjectsCases(): iterable } /** - * When performing an entity manager lazy service reset, the reset operations may re-use the container + * When performing an entity manager lazy service reset, the reset operations may reuse the container * to create a "fresh" service: when doing so, it can happen that the "fresh" service is itself a proxy. * * Because of that, the proxy will be populated with a wrapped value that is itself a proxy: repeating diff --git a/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php index eb3acbba903a5..bebda88b63329 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Middleware/Debug/MiddlewareTest.php @@ -21,15 +21,15 @@ use Doctrine\DBAL\Statement; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\ORMSetup; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder; use Symfony\Bridge\Doctrine\Middleware\Debug\Middleware; use Symfony\Bridge\PhpUnit\ClockMock; use Symfony\Component\Stopwatch\Stopwatch; -/** - * @requires extension pdo_sqlite - */ +#[RequiresPhpExtension('pdo_sqlite')] class MiddlewareTest extends TestCase { private DebugDataHolder $debugDataHolder; @@ -61,16 +61,16 @@ private function init(bool $withStopwatch = true): void ], $config); $this->conn->executeQuery(<<init(); @@ -110,17 +108,15 @@ public function testWithoutBinding(callable $executeMethod) $this->assertGreaterThan(0, $debug[1]['executionMS']); } - /** - * @dataProvider provideExecuteMethod - */ + #[DataProvider('provideExecuteMethod')] public function testWithValueBound(callable $executeMethod) { $this->init(); $sql = <<conn->prepare($sql); $stmt->bindValue(1, 'product1'); @@ -140,17 +136,15 @@ public function testWithValueBound(callable $executeMethod) $this->assertGreaterThan(0, $debug[1]['executionMS']); } - /** - * @dataProvider provideExecuteMethod - */ + #[DataProvider('provideExecuteMethod')] public function testWithParamBound(callable $executeMethod) { $this->init(); $sql = <<getResourceFromString('mydata'); @@ -179,9 +173,7 @@ public static function provideEndTransactionMethod(): array ]; } - /** - * @dataProvider provideEndTransactionMethod - */ + #[DataProvider('provideEndTransactionMethod')] public function testTransaction(callable $endTransactionMethod, string $expectedEndTransactionDebug) { $this->init(); @@ -237,9 +229,7 @@ public static function provideExecuteAndEndTransactionMethods(): array ]; } - /** - * @dataProvider provideExecuteAndEndTransactionMethods - */ + #[DataProvider('provideExecuteAndEndTransactionMethods')] public function testGlobalDoctrineDuration(callable $sqlMethod, callable $endTransactionMethod) { $this->init(); @@ -263,9 +253,7 @@ public function testGlobalDoctrineDuration(callable $sqlMethod, callable $endTra $this->assertCount(4, $this->stopwatch->getEvent('doctrine')->getPeriods()); } - /** - * @dataProvider provideExecuteAndEndTransactionMethods - */ + #[DataProvider('provideExecuteAndEndTransactionMethods')] public function testWithoutStopwatch(callable $sqlMethod, callable $endTransactionMethod) { $this->init(false); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/DriverTest.php b/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/DriverTest.php index 010e1879a8ab4..89c0b0051fd75 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/DriverTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/DriverTest.php @@ -13,14 +13,13 @@ use Doctrine\DBAL\Driver as DriverInterface; use Doctrine\DBAL\Driver\Connection as ConnectionInterface; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Middleware\IdleConnection\Driver; class DriverTest extends TestCase { - /** - * @group time-sensitive - */ + #[Group('time-sensitive')] public function testConnect() { $driverMock = $this->createMock(DriverInterface::class); diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 2a5f337f2b0df..0eb842c9929ad 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -20,6 +20,9 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\ORM\ORMSetup; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy; @@ -30,7 +33,6 @@ use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumInt; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\EnumString; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Component\PropertyInfo\Type as LegacyType; use Symfony\Component\TypeInfo\Type; @@ -39,8 +41,6 @@ */ class DoctrineExtractorTest extends TestCase { - use ExpectUserDeprecationMessageTrait; - private function createExtractor(): DoctrineExtractor { $config = ORMSetup::createConfiguration(true); @@ -114,23 +114,28 @@ public function testTestGetPropertiesWithEmbedded() ); } - /** - * @group legacy - * - * @dataProvider legacyTypesProvider - */ - public function testExtractLegacy(string $property, ?array $type = null) + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('legacyTypesProvider')] + public function testExtractLegacy(string $property, ?callable $typeFactory = null) { + if (!class_exists(LegacyType::class)) { + $this->markTestSkipped('This test requires symfony/property-info < 8.0.'); + } + $this->expectUserDeprecationMessage('Since symfony/property-info 7.3: The "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getTypes()" method is deprecated, use "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getType()" instead.'); - $this->assertEquals($type, $this->createExtractor()->getTypes(DoctrineDummy::class, $property, [])); + $this->assertEquals(null !== $typeFactory ? $typeFactory() : null, $this->createExtractor()->getTypes(DoctrineDummy::class, $property, [])); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testExtractWithEmbeddedLegacy() { + if (!class_exists(LegacyType::class)) { + $this->markTestSkipped('This test requires symfony/property-info < 8.0.'); + } + $this->expectUserDeprecationMessage('Since symfony/property-info 7.3: The "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getTypes()" method is deprecated, use "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getType()" instead.'); $expectedTypes = [new LegacyType( @@ -148,11 +153,14 @@ public function testExtractWithEmbeddedLegacy() $this->assertEquals($expectedTypes, $actualTypes); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testExtractEnumLegacy() { + if (!class_exists(LegacyType::class)) { + $this->markTestSkipped('This test requires symfony/property-info < 8.0.'); + } + $this->expectUserDeprecationMessage('Since symfony/property-info 7.3: The "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getTypes()" method is deprecated, use "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getType()" instead.'); $this->assertEquals([new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, EnumString::class)], $this->createExtractor()->getTypes(DoctrineEnum::class, 'enumString', [])); @@ -162,32 +170,31 @@ public function testExtractEnumLegacy() $this->assertNull($this->createExtractor()->getTypes(DoctrineEnum::class, 'enumCustom', [])); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public static function legacyTypesProvider(): array { // DBAL 4 has a special fallback strategy for BINGINT (int -> string) if (!method_exists(BigIntType::class, 'getName')) { - $expectedBingIntType = [new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]; + $expectedBingIntType = fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]; } else { - $expectedBingIntType = [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]; + $expectedBingIntType = fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]; } return [ - ['id', [new LegacyType(LegacyType::BUILTIN_TYPE_INT)]], - ['guid', [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]], + ['id', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_INT)]], + ['guid', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]], ['bigint', $expectedBingIntType], - ['time', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'DateTime')]], - ['timeImmutable', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]], - ['dateInterval', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'DateInterval')]], - ['float', [new LegacyType(LegacyType::BUILTIN_TYPE_FLOAT)]], - ['decimal', [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]], - ['bool', [new LegacyType(LegacyType::BUILTIN_TYPE_BOOL)]], - ['binary', [new LegacyType(LegacyType::BUILTIN_TYPE_RESOURCE)]], - ['jsonArray', [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, false, null, true)]], - ['foo', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, true, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation')]], - ['bar', [new LegacyType( + ['time', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'DateTime')]], + ['timeImmutable', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable')]], + ['dateInterval', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'DateInterval')]], + ['float', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_FLOAT)]], + ['decimal', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)]], + ['bool', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_BOOL)]], + ['binary', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_RESOURCE)]], + ['jsonArray', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, false, null, true)]], + ['foo', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, true, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation')]], + ['bar', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, 'Doctrine\Common\Collections\Collection', @@ -195,7 +202,7 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], - ['indexedRguid', [new LegacyType( + ['indexedRguid', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, 'Doctrine\Common\Collections\Collection', @@ -203,7 +210,7 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_STRING), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], - ['indexedBar', [new LegacyType( + ['indexedBar', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, 'Doctrine\Common\Collections\Collection', @@ -211,7 +218,7 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_STRING), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], - ['indexedFoo', [new LegacyType( + ['indexedFoo', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, 'Doctrine\Common\Collections\Collection', @@ -219,7 +226,7 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_STRING), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation') )]], - ['indexedBaz', [new LegacyType( + ['indexedBaz', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, Collection::class, @@ -227,10 +234,10 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) )]], - ['simpleArray', [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, false, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_STRING))]], + ['simpleArray', fn () => [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, false, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_STRING))]], ['customFoo', null], ['notMapped', null], - ['indexedByDt', [new LegacyType( + ['indexedByDt', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, Collection::class, @@ -239,7 +246,7 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) )]], ['indexedByCustomType', null], - ['indexedBuz', [new LegacyType( + ['indexedBuz', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, Collection::class, @@ -247,7 +254,7 @@ public static function legacyTypesProvider(): array new LegacyType(LegacyType::BUILTIN_TYPE_STRING), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) )]], - ['dummyGeneratedValueList', [new LegacyType( + ['dummyGeneratedValueList', fn () => [new LegacyType( LegacyType::BUILTIN_TYPE_OBJECT, false, 'Doctrine\Common\Collections\Collection', @@ -264,9 +271,8 @@ public function testGetPropertiesCatchException() $this->assertNull($this->createExtractor()->getProperties('Not\Exist')); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testGetTypesCatchExceptionLegacy() { $this->expectUserDeprecationMessage('Since symfony/property-info 7.3: The "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getTypes()" method is deprecated, use "Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor::getType()" instead.'); @@ -300,9 +306,7 @@ public function testExtractEnum() $this->assertNull($this->createExtractor()->getType(DoctrineEnum::class, 'enumCustom')); } - /** - * @dataProvider typeProvider - */ + #[DataProvider('typeProvider')] public function testExtract(string $property, ?Type $type) { $this->assertEquals($type, $this->createExtractor()->getType(DoctrineDummy::class, $property, [])); diff --git a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/DoctrineDbalCacheAdapterSchemaListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/DoctrineDbalCacheAdapterSchemaListenerTest.php index e429dca192f6d..6ccfd1e222271 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/DoctrineDbalCacheAdapterSchemaListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/DoctrineDbalCacheAdapterSchemaListenerTest.php @@ -35,7 +35,7 @@ public function testPostGenerateSchema() $dbalAdapter = $this->createMock(DoctrineDbalAdapter::class); $dbalAdapter->expects($this->once()) ->method('configureSchema') - ->with($schema, $dbalConnection, fn () => true); + ->with($schema, $dbalConnection, $this->callback(fn () => true)); $subscriber = new DoctrineDbalCacheAdapterSchemaListener([$dbalAdapter]); $subscriber->postGenerateSchema($event); diff --git a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php index 6fd86a46c84e5..242db00019764 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php @@ -34,7 +34,7 @@ public function testPostGenerateSchemaLockPdo() $lockStore = $this->createMock(DoctrineDbalStore::class); $lockStore->expects($this->once()) ->method('configureSchema') - ->with($schema, fn () => true); + ->with($schema, $this->callback(fn () => true)); $subscriber = new LockStoreSchemaListener((static fn () => yield $lockStore)()); $subscriber->postGenerateSchema($event); diff --git a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/MessengerTransportDoctrineSchemaListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/MessengerTransportDoctrineSchemaListenerTest.php index 7321ddd30e814..feca2495e2acf 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/MessengerTransportDoctrineSchemaListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/MessengerTransportDoctrineSchemaListenerTest.php @@ -38,7 +38,7 @@ public function testPostGenerateSchema() $doctrineTransport = $this->createMock(DoctrineTransport::class); $doctrineTransport->expects($this->once()) ->method('configureSchema') - ->with($schema, $dbalConnection, fn () => true); + ->with($schema, $dbalConnection, $this->callback(fn () => true)); $otherTransport = $this->createMock(TransportInterface::class); $otherTransport->expects($this->never()) ->method($this->anything()); diff --git a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/PdoSessionHandlerSchemaListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/PdoSessionHandlerSchemaListenerTest.php index fce89261082c7..e10fbcafdabb6 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/PdoSessionHandlerSchemaListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/PdoSessionHandlerSchemaListenerTest.php @@ -34,7 +34,7 @@ public function testPostGenerateSchemaPdo() $pdoSessionHandler = $this->createMock(PdoSessionHandler::class); $pdoSessionHandler->expects($this->once()) ->method('configureSchema') - ->with($schema, fn () => true); + ->with($schema, $this->callback(fn () => true)); $subscriber = new PdoSessionHandlerSchemaListener($pdoSessionHandler); $subscriber->postGenerateSchema($event); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderPostgresTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderPostgresTest.php index 230ec78dc23cf..c960ca662aedd 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderPostgresTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderPostgresTest.php @@ -15,13 +15,12 @@ use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; use Doctrine\ORM\ORMSetup; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider; -/** - * @requires extension pdo_pgsql - * - * @group integration - */ +#[Group('integration')] +#[RequiresPhpExtension('pdo_pgsql')] class DoctrineTokenProviderPostgresTest extends DoctrineTokenProviderTest { public static function setUpBeforeClass(): void @@ -45,19 +44,19 @@ protected function bootstrapProvider(): DoctrineTokenProvider 'password' => 'password', ], $config); $connection->{method_exists($connection, 'executeStatement') ? 'executeStatement' : 'executeUpdate'}(<<<'SQL' - DROP TABLE IF EXISTS rememberme_token; -SQL + DROP TABLE IF EXISTS rememberme_token; + SQL ); $connection->{method_exists($connection, 'executeStatement') ? 'executeStatement' : 'executeUpdate'}(<<<'SQL' - CREATE TABLE rememberme_token ( - series CHAR(88) UNIQUE PRIMARY KEY NOT NULL, - value VARCHAR(88) NOT NULL, -- CHAR(88) adds spaces at the end - lastUsed TIMESTAMP NOT NULL, - class VARCHAR(100) NOT NULL, - username VARCHAR(200) NOT NULL - ); -SQL + CREATE TABLE rememberme_token ( + series CHAR(88) UNIQUE PRIMARY KEY NOT NULL, + value VARCHAR(88) NOT NULL, -- CHAR(88) adds spaces at the end + lastUsed TIMESTAMP NOT NULL, + class VARCHAR(100) NOT NULL, + username VARCHAR(200) NOT NULL + ); + SQL ); return new DoctrineTokenProvider($connection); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php index 2971f4d662089..1a9b4ae77987c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php @@ -14,14 +14,13 @@ use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; use Doctrine\ORM\ORMSetup; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Exception\TokenNotFoundException; -/** - * @requires extension pdo_sqlite - */ +#[RequiresPhpExtension('pdo_sqlite')] class DoctrineTokenProviderTest extends TestCase { public function testCreateNewToken() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php index 84b265ed6502c..76a01bdf88ed2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php @@ -14,6 +14,7 @@ use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SQLitePlatform; use Doctrine\DBAL\Types\Type; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Types\DatePointType; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php index b490d94f4263f..40f5a343380b3 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UlidTypeTest.php @@ -16,8 +16,10 @@ use Doctrine\DBAL\Platforms\MariaDBPlatform; use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SQLitePlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Types\UlidType; use Symfony\Component\Uid\AbstractUid; @@ -129,9 +131,7 @@ public function testGetName() $this->assertEquals('ulid', $this->type->getName()); } - /** - * @dataProvider provideSqlDeclarations - */ + #[DataProvider('provideSqlDeclarations')] public function testGetGuidTypeDeclarationSQL(AbstractPlatform $platform, string $expectedDeclaration) { $this->assertEquals($expectedDeclaration, $this->type->getSqlDeclaration(['length' => 36], $platform)); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php index f26e43ffe66b3..906ea11bd6442 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/UuidTypeTest.php @@ -16,8 +16,10 @@ use Doctrine\DBAL\Platforms\MariaDBPlatform; use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SQLitePlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Component\Uid\AbstractUid; @@ -140,9 +142,7 @@ public function testGetName() $this->assertEquals('uuid', $this->type->getName()); } - /** - * @dataProvider provideSqlDeclarations - */ + #[DataProvider('provideSqlDeclarations')] public function testGetGuidTypeDeclarationSQL(AbstractPlatform $platform, string $expectedDeclaration) { $this->assertEquals($expectedDeclaration, $this->type->getSqlDeclaration(['length' => 36], $platform)); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php index a3015722cea8d..8c1bb054f3264 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bridge\Doctrine\Tests\Validator\Constraints; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -61,9 +63,8 @@ public function testAttributeWithGroupsAndPaylod() self::assertSame(['some_group'], $constraint->groups); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValueOptionConfiguresFields() { $constraint = new UniqueEntity(['value' => 'email']); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 4f93768cddf7c..b532a3471ec73 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -17,6 +17,9 @@ use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociatedEntityDto; @@ -185,9 +188,8 @@ public function testValidateEntityWithPrivatePropertyAndProxyObject() $this->assertNoViolation(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateEntityWithPrivatePropertyAndProxyObjectDoctrineStyle() { $entity = new SingleIntIdWithPrivateNameEntity(1, 'Foo'); @@ -226,9 +228,8 @@ public function testValidateCustomErrorPath() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateCustomErrorPathDoctrineStyle() { $entity1 = new SingleIntIdEntity(1, 'Foo'); @@ -267,10 +268,8 @@ public function testValidateUniquenessWithNull() $this->assertNoViolation(); } - /** - * @dataProvider provideConstraintsWithIgnoreNullDisabled - * @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField - */ + #[DataProvider('provideConstraintsWithIgnoreNullDisabled')] + #[DataProvider('provideConstraintsWithIgnoreNullEnabledOnFirstField')] public function testValidateUniquenessWithIgnoreNullDisableOnSecondField(UniqueEntity $constraint) { $entity1 = new DoubleNameEntity(1, 'Foo', null); @@ -303,9 +302,7 @@ public static function provideConstraintsWithIgnoreNullDisabled(): iterable yield 'Named arguments' => [new UniqueEntity(message: 'myMessage', fields: ['name', 'name2'], em: 'foo', ignoreNull: false)]; } - /** - * @dataProvider provideConstraintsWithIgnoreNullEnabled - */ + #[DataProvider('provideConstraintsWithIgnoreNullEnabled')] public function testAllConfiguredFieldsAreCheckedOfBeingMappedByDoctrineWithIgnoreNullEnabled(UniqueEntity $constraint) { $entity1 = new SingleIntIdEntity(1, null); @@ -314,10 +311,8 @@ public function testAllConfiguredFieldsAreCheckedOfBeingMappedByDoctrineWithIgno $this->validator->validate($entity1, $constraint); } - /** - * @dataProvider provideConstraintsWithIgnoreNullEnabled - * @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField - */ + #[DataProvider('provideConstraintsWithIgnoreNullEnabled')] + #[DataProvider('provideConstraintsWithIgnoreNullEnabledOnFirstField')] public function testNoValidationIfFirstFieldIsNullAndNullValuesAreIgnored(UniqueEntity $constraint) { $entity1 = new DoubleNullableNameEntity(1, null, 'Foo'); @@ -414,9 +409,7 @@ public function testValidateUniquenessWithUnrewoundArray() $this->assertNoViolation(); } - /** - * @dataProvider resultTypesProvider - */ + #[DataProvider('resultTypesProvider')] public function testValidateResultTypes($entity1, $result) { $constraint = new UniqueEntity( @@ -817,9 +810,7 @@ public function testValidateUniquenessCause() ->assertRaised(); } - /** - * @dataProvider resultWithEmptyIterator - */ + #[DataProvider('resultWithEmptyIterator')] public function testValidateUniquenessWithEmptyIterator($entity, $result) { $constraint = new UniqueEntity( @@ -954,9 +945,8 @@ public function testValidateDTOUniqueness() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateDTOUniquenessDoctrineStyle() { $constraint = new UniqueEntity([ @@ -1017,9 +1007,8 @@ public function testValidateMappingOfFieldNames() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateMappingOfFieldNamesDoctrineStyle() { $constraint = new UniqueEntity([ @@ -1061,9 +1050,8 @@ public function testInvalidateDTOFieldName() $this->validator->validate($dto, $constraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidateDTOFieldNameDoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); @@ -1094,9 +1082,8 @@ public function testInvalidateEntityFieldName() $this->validator->validate($dto, $constraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidateEntityFieldNameDoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); @@ -1142,9 +1129,8 @@ public function testValidateDTOUniquenessWhenUpdatingEntity() ->assertRaised(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateDTOUniquenessWhenUpdatingEntityDoctrineStyle() { $constraint = new UniqueEntity([ @@ -1197,9 +1183,8 @@ public function testValidateDTOUniquenessWhenUpdatingEntityWithTheSameValue() $this->assertNoViolation(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateDTOUniquenessWhenUpdatingEntityWithTheSameValueDoctrineStyle() { $constraint = new UniqueEntity([ @@ -1251,9 +1236,8 @@ public function testValidateIdentifierMappingOfFieldNames() $this->assertNoViolation(); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testValidateIdentifierMappingOfFieldNamesDoctrineStyle() { $constraint = new UniqueEntity([ @@ -1311,9 +1295,8 @@ public function testInvalidateMissingIdentifierFieldName() $this->validator->validate($dto, $constraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testInvalidateMissingIdentifierFieldNameDoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); @@ -1361,9 +1344,8 @@ public function testUninitializedValueThrowException() $this->validator->validate($dto, $constraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testUninitializedValueThrowExceptionDoctrineStyle() { $this->expectExceptionMessage('Typed property Symfony\Bridge\Doctrine\Tests\Fixtures\Dto::$foo must not be accessed before initialization'); @@ -1404,9 +1386,8 @@ public function testEntityManagerNullObjectWhenDTO() $this->validator->validate($dto, $constraint); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testEntityManagerNullObjectWhenDTODoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php index 8b3494961d80b..969ec3180dee1 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\Tests\Validator; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Tests\Fixtures\BaseUser; @@ -175,9 +176,7 @@ public function testFieldMappingsConfiguration() $this->assertCount(0, $constraints); } - /** - * @dataProvider regexpProvider - */ + #[DataProvider('regexpProvider')] public function testClassValidator(bool $expected, ?string $classValidatorRegexp = null) { $doctrineLoader = new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), $classValidatorRegexp, false); @@ -214,7 +213,7 @@ public function testClassNoAutoMapping() /** @var PropertyMetadata[] $autoMappingExplicitlyEnabledMetadata */ $autoMappingExplicitlyEnabledMetadata = $classMetadata->getPropertyMetadata('autoMappingExplicitlyEnabled'); - $this->assertCount(1, $autoMappingExplicitlyEnabledMetadata[0]->constraints); + $this->assertCount(1, $autoMappingExplicitlyEnabledMetadata[0]->getConstraints()); $this->assertSame(AutoMappingStrategy::ENABLED, $autoMappingExplicitlyEnabledMetadata[0]->getAutoMappingStrategy()); } } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php index 59ab0aa2627d0..26ab883ed6a0f 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php @@ -66,18 +66,21 @@ public function __construct( trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); $options = array_merge($fields, $options ?? []); + $fields = null; } else { if (\is_array($options)) { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); + + $options['fields'] = $fields; + $fields = null; } else { - $options = []; + $options = null; } - - $options['fields'] = $fields; } parent::__construct($options, $groups, $payload); + $this->fields = $fields ?? $this->fields; $this->message = $message ?? $this->message; $this->service = $service ?? $this->service; $this->em = $em ?? $this->em; @@ -88,8 +91,15 @@ public function __construct( $this->identifierFieldNames = $identifierFieldNames ?? $this->identifierFieldNames; } + /** + * @deprecated since Symfony 7.4 + */ public function getRequiredOptions(): array { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/doctrine-bridge', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return ['fields']; } @@ -106,8 +116,15 @@ public function getTargets(): string|array return self::CLASS_CONSTRAINT; } + /** + * @deprecated since Symfony 7.4 + */ public function getDefaultOption(): ?string { + if (0 === \func_num_args() || func_get_arg(0)) { + trigger_deprecation('symfony/doctrine-bridge', '7.4', 'The %s() method is deprecated.', __METHOD__); + } + return 'fields'; } } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index bebf7276a99dc..88573442f2a92 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -25,24 +25,24 @@ "symfony/service-contracts": "^2.5|^3" }, "require-dev": { - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/doctrine-messenger": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4.6|^7.0.6", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/doctrine-messenger": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/form": "^7.2|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/type-info": "^7.1.8|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", "doctrine/collections": "^1.8|^2.0", "doctrine/data-fixtures": "^1.1|^2", "doctrine/dbal": "^3.6|^4", @@ -64,7 +64,7 @@ "symfony/property-info": "<6.4", "symfony/security-bundle": "<6.4", "symfony/security-core": "<6.4", - "symfony/validator": "<6.4" + "symfony/validator": "<7.4" }, "autoload": { "psr-4": { "Symfony\\Bridge\\Doctrine\\": "" }, diff --git a/src/Symfony/Bridge/Doctrine/phpunit.xml.dist b/src/Symfony/Bridge/Doctrine/phpunit.xml.dist index 0b1a67afd1249..ea9e034bcfa90 100644 --- a/src/Symfony/Bridge/Doctrine/phpunit.xml.dist +++ b/src/Symfony/Bridge/Doctrine/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,20 +28,11 @@ ./Tests ./vendor - + - - - - - - - Symfony\Bridge\Doctrine\Middleware\Debug - Symfony\Bridge\Doctrine\Middleware\IdleConnection - - - - - - + + + + + diff --git a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php index f47fa19e41845..9d2c8a596d5ac 100644 --- a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php +++ b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php @@ -63,15 +63,15 @@ protected function configure(): void ->addOption('date-format', null, InputOption::VALUE_REQUIRED, 'The date format', ConsoleFormatter::SIMPLE_DATE) ->addOption('filter', null, InputOption::VALUE_REQUIRED, 'An expression to filter log. Example: "level > 200 or channel in [\'app\', \'doctrine\']"') ->setHelp(<<<'EOF' -%command.name% starts a log server to display in real time the log -messages generated by your application: + %command.name% starts a log server to display in real time the log + messages generated by your application: - php %command.full_name% + php %command.full_name% -To filter the log messages using any ExpressionLanguage compatible expression, use the --filter option: + To filter the log messages using any ExpressionLanguage compatible expression, use the --filter option: -php %command.full_name% --filter="level > 200 or channel in ['app', 'doctrine']" -EOF + php %command.full_name% --filter="level > 200 or channel in ['app', 'doctrine']" + EOF ) ; } diff --git a/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php b/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php index 10632113a5e3d..a3ded57a7ac64 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php @@ -133,17 +133,17 @@ private function sendToElasticsearch(array $records): void ], ]); - $this->responses->attach($response); + $this->responses[$response] = null; $this->wait(false); } - public function __sleep(): array + public function __serialize(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup(): void + public function __unserialize(array $data): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } @@ -164,10 +164,10 @@ private function wait(bool $blocking): void continue; } if ($chunk->isLast()) { - $this->responses->detach($response); + unset($this->responses[$response]); } } catch (ExceptionInterface $e) { - $this->responses->detach($response); + unset($this->responses[$response]); error_log(\sprintf("Could not push logs to Elasticsearch:\n%s", (string) $e)); } } diff --git a/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php b/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php index 2a952abc350e2..6f72498525303 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Formatter/ConsoleFormatterTest.php @@ -13,15 +13,14 @@ use Monolog\Logger; use Monolog\LogRecord; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; use Symfony\Bridge\Monolog\Tests\RecordFactory; class ConsoleFormatterTest extends TestCase { - /** - * @dataProvider providerFormatTests - */ + #[DataProvider('providerFormatTests')] public function testFormat(array|LogRecord $record, $expectedMessage) { $formatter = new ConsoleFormatter(); diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php index 626c94ce0ccf8..a4c9420a9d434 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php @@ -13,6 +13,7 @@ use Monolog\Level; use Monolog\Logger; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; use Symfony\Bridge\Monolog\Handler\ConsoleHandler; @@ -46,9 +47,7 @@ public function testIsHandling() $this->assertFalse($handler->isHandling(RecordFactory::create()), '->isHandling returns false when no output is set'); } - /** - * @dataProvider provideVerbosityMappingTests - */ + #[DataProvider('provideVerbosityMappingTests')] public function testVerbosityMapping($verbosity, $level, $isHandling, array $map = []) { $output = $this->createMock(OutputInterface::class); diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php index 37f1e5f7a4ae1..594bc5d270c28 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php @@ -27,11 +27,11 @@ public function testHandle() $callCount = 0; $responseFactory = function ($method, $url, $options) use (&$callCount) { $body = << 404]], new ErrorLevelActivationStrategy(Level::Warning)); } - /** - * @dataProvider isActivatedProvider - */ + #[DataProvider('isActivatedProvider')] public function testIsActivated($url, $record, $expected) { $requestStack = new RequestStack(); diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php index 48a1347421c05..2d1779bd4bfd7 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/NotFoundActivationStrategyTest.php @@ -14,6 +14,7 @@ use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Level; use Monolog\LogRecord; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy; use Symfony\Bridge\Monolog\Tests\RecordFactory; @@ -23,9 +24,7 @@ class NotFoundActivationStrategyTest extends TestCase { - /** - * @dataProvider isActivatedProvider - */ + #[DataProvider('isActivatedProvider')] public function testIsActivated(string $url, array|LogRecord $record, bool $expected) { $requestStack = new RequestStack(); diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index 50a23a5876931..745686777d1ce 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -19,16 +19,16 @@ "php": ">=8.2", "monolog/monolog": "^3", "symfony/service-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/http-kernel": "^6.4|^7.0|^8.0" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/mailer": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symfony/mailer": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/console": "<6.4", diff --git a/src/Symfony/Bridge/Monolog/phpunit.xml.dist b/src/Symfony/Bridge/Monolog/phpunit.xml.dist index ab47262381599..dadc04efb1146 100644 --- a/src/Symfony/Bridge/Monolog/phpunit.xml.dist +++ b/src/Symfony/Bridge/Monolog/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md index 0b139af321f5d..579fd88af71cf 100644 --- a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.4 +--- + + * Add support for mocking the `strtotime()` function + 7.3 --- diff --git a/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php b/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php index 72ec51e053d73..61582425c5635 100644 --- a/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php +++ b/src/Symfony/Bridge/PhpUnit/ClassExistsMock.php @@ -62,7 +62,7 @@ public static function trait_exists($name, $autoload = true): bool return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \trait_exists($name, $autoload); } - public static function enum_exists($name, $autoload = true):bool + public static function enum_exists($name, $autoload = true): bool { $name = ltrim($name, '\\'); @@ -77,7 +77,7 @@ public static function register($class): void if (0 < strpos($class, '\\Tests\\')) { $ns = str_replace('\\Tests\\', '\\', $class); $mockedNs[] = substr($ns, 0, strrpos($ns, '\\')); - } elseif (0 === strpos($class, 'Tests\\')) { + } elseif (str_starts_with($class, 'Tests\\')) { $mockedNs[] = substr($class, 6, strrpos($class, '\\') - 6); } foreach ($mockedNs as $ns) { diff --git a/src/Symfony/Bridge/PhpUnit/ClockMock.php b/src/Symfony/Bridge/PhpUnit/ClockMock.php index 4cca8fc26cfc6..9a9c910e6dd1f 100644 --- a/src/Symfony/Bridge/PhpUnit/ClockMock.php +++ b/src/Symfony/Bridge/PhpUnit/ClockMock.php @@ -109,6 +109,18 @@ public static function hrtime($asNumber = false) return [(int) self::$now, (int) $ns]; } + /** + * @return false|int + */ + public static function strtotime(string $datetime, ?int $timestamp = null) + { + if (null === $timestamp) { + $timestamp = self::time(); + } + + return \strtotime($datetime, $timestamp); + } + public static function register($class): void { $self = static::class; @@ -117,7 +129,7 @@ public static function register($class): void if (0 < strpos($class, '\\Tests\\')) { $ns = str_replace('\\Tests\\', '\\', $class); $mockedNs[] = substr($ns, 0, strrpos($ns, '\\')); - } elseif (0 === strpos($class, 'Tests\\')) { + } elseif (str_starts_with($class, 'Tests\\')) { $mockedNs[] = substr($class, 6, strrpos($class, '\\') - 6); } foreach ($mockedNs as $ns) { @@ -161,6 +173,11 @@ function hrtime(\$asNumber = false) { return \\$self::hrtime(\$asNumber); } + +function strtotime(\$datetime, \$timestamp = null) +{ + return \\$self::strtotime(\$datetime, \$timestamp); +} EOPHP ); } diff --git a/src/Symfony/Bridge/PhpUnit/ConstraintTrait.php b/src/Symfony/Bridge/PhpUnit/ConstraintTrait.php index ceb60418ce81d..9090cc4c35611 100644 --- a/src/Symfony/Bridge/PhpUnit/ConstraintTrait.php +++ b/src/Symfony/Bridge/PhpUnit/ConstraintTrait.php @@ -14,12 +14,7 @@ use PHPUnit\Framework\Constraint\Constraint; $r = new \ReflectionClass(Constraint::class); -if ($r->getProperty('exporter')->isProtected()) { - trait ConstraintTrait - { - use Legacy\ConstraintTraitForV7; - } -} elseif (!$r->getMethod('evaluate')->hasReturnType()) { +if (!$r->getMethod('evaluate')->hasReturnType()) { trait ConstraintTrait { use Legacy\ConstraintTraitForV8; diff --git a/src/Symfony/Bridge/PhpUnit/CoverageListener.php b/src/Symfony/Bridge/PhpUnit/CoverageListener.php index 65d6aa9dc9dcc..c3fa8ec514970 100644 --- a/src/Symfony/Bridge/PhpUnit/CoverageListener.php +++ b/src/Symfony/Bridge/PhpUnit/CoverageListener.php @@ -29,7 +29,7 @@ class CoverageListener implements TestListener public function __construct(?callable $sutFqcnResolver = null, bool $warningOnSutNotFound = false) { $this->sutFqcnResolver = $sutFqcnResolver ?? static function (Test $test): ?string { - $class = \get_class($test); + $class = $test::class; $sutFqcn = str_replace('\\Tests\\', '\\', $class); $sutFqcn = preg_replace('{Test$}', '', $sutFqcn); @@ -46,7 +46,7 @@ public function startTest(Test $test): void return; } - $annotations = TestUtil::parseTestMethodAnnotations(\get_class($test), $test->getName(false)); + $annotations = TestUtil::parseTestMethodAnnotations($test::class, $test->getName(false)); $ignoredAnnotations = ['covers', 'coversDefaultClass', 'coversNothing']; @@ -86,11 +86,10 @@ public function startTest(Test $test): void private function addCoversForClassToAnnotationCache(Test $test, array $covers): void { $r = new \ReflectionProperty(TestUtil::class, 'annotationCache'); - $r->setAccessible(true); $cache = $r->getValue(); $cache = array_replace_recursive($cache, [ - \get_class($test) => [ + $test::class => [ 'covers' => $covers, ], ]); @@ -100,10 +99,9 @@ private function addCoversForClassToAnnotationCache(Test $test, array $covers): private function addCoversForDocBlockInsideRegistry(Test $test, array $covers): void { - $docBlock = Registry::getInstance()->forClassName(\get_class($test)); + $docBlock = Registry::getInstance()->forClassName($test::class); $symbolAnnotations = new \ReflectionProperty($docBlock, 'symbolAnnotations'); - $symbolAnnotations->setAccessible(true); // Exclude internal classes; PHPUnit 9.1+ is picky about tests covering, say, a \RuntimeException $covers = array_filter($covers, function (string $class) { diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index e59790886b38b..01bb6534364de 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -97,7 +97,7 @@ public static function collectDeprecations($outputFile) { $deprecations = []; $previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$previousErrorHandler) { - if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || false === strpos($msg, '" targeting switch is equivalent to "break'))) { + if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || !str_contains($msg, '" targeting switch is equivalent to "break'))) { if ($previousErrorHandler) { return $previousErrorHandler($type, $msg, $file, $line, $context); } @@ -129,7 +129,7 @@ public static function collectDeprecations($outputFile) */ public function handleError($type, $msg, $file, $line, $context = []) { - if ((\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || false === strpos($msg, '" targeting switch is equivalent to "break'))) || !$this->getConfiguration()->isEnabled()) { + if ((\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || !str_contains($msg, '" targeting switch is equivalent to "break'))) || !$this->getConfiguration()->isEnabled()) { return \call_user_func(self::getPhpUnitErrorHandler(), $type, $msg, $file, $line, $context); } diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php index 822e9800bf0ea..caf0b8259c92a 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php @@ -99,7 +99,7 @@ public function __construct(string $message, array $trace, string $file, bool $l $this->getOriginalFilesStack(); array_splice($this->originalFilesStack, 0, $j, [$this->triggeringFile]); - if (preg_match('/(?|"([^"]++)" that is deprecated|should implement method "(?:static )?([^:]++))/', $message, $m) || (false === strpos($message, '()" will return') && false === strpos($message, 'native return type declaration') && preg_match('/^(?:The|Method) "([^":]++)/', $message, $m))) { + if (preg_match('/(?|"([^"]++)" that is deprecated|should implement method "(?:static )?([^:]++))/', $message, $m) || (!str_contains($message, '()" will return') && !str_contains($message, 'native return type declaration') && preg_match('/^(?:The|Method) "([^":]++)/', $message, $m))) { $this->triggeringFile = (new \ReflectionClass($m[1]))->getFileName(); array_unshift($this->originalFilesStack, $this->triggeringFile); } @@ -137,7 +137,7 @@ public function __construct(string $message, array $trace, string $file, bool $l return; } - if (!isset($line['class'], $trace[$i - 2]['function']) || 0 !== strpos($line['class'], SymfonyTestsListenerFor::class)) { + if (!isset($line['class'], $trace[$i - 2]['function']) || !str_starts_with($line['class'], SymfonyTestsListenerFor::class)) { $this->originClass = isset($line['object']) ? \get_class($line['object']) : $line['class']; $this->originMethod = $line['function']; @@ -147,7 +147,7 @@ public function __construct(string $message, array $trace, string $file, bool $l $test = $line['args'][0] ?? null; if (($test instanceof TestCase || $test instanceof TestSuite) && ('trigger_error' !== $trace[$i - 2]['function'] || isset($trace[$i - 2]['class']))) { - $this->originClass = \get_class($test); + $this->originClass = $test::class; $this->originMethod = $test->getName(); } } @@ -159,7 +159,7 @@ private function lineShouldBeSkipped(array $line): bool } $class = $line['class']; - return 'ReflectionMethod' === $class || 0 === strpos($class, 'PHPUnit\\'); + return 'ReflectionMethod' === $class || str_starts_with($class, 'PHPUnit\\'); } public function originatesFromDebugClassLoader(): bool @@ -189,7 +189,7 @@ public function originatingClass(): string $class = $this->originClass; - return false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; + return str_contains($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; } public function originatingMethod(): string @@ -215,9 +215,9 @@ public function isLegacy(): bool $method = $this->originatingMethod(); $groups = class_exists(Groups::class, false) ? [new Groups(), 'groups'] : [Test::class, 'getGroups']; - return 0 === strpos($method, 'testLegacy') - || 0 === strpos($method, 'provideLegacy') - || 0 === strpos($method, 'getLegacy') + return str_starts_with($method, 'testLegacy') + || str_starts_with($method, 'provideLegacy') + || str_starts_with($method, 'getLegacy') || strpos($this->originClass, '\Legacy') || \in_array('legacy', $groups($this->originClass, $method), true); } @@ -228,10 +228,10 @@ public function isMuted(): bool return false; } if (isset($this->trace[1]['class'])) { - return 0 === strpos($this->trace[1]['class'], 'PHPUnit\\'); + return str_starts_with($this->trace[1]['class'], 'PHPUnit\\'); } - return false !== strpos($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR); + return str_contains($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR); } /** @@ -300,7 +300,7 @@ private function getPackage(string $path): string { $path = realpath($path) ?: $path; foreach (self::getVendors() as $vendorRoot) { - if (0 === strpos($path, $vendorRoot)) { + if (str_starts_with($path, $vendorRoot)) { $relativePath = substr($path, \strlen($vendorRoot) + 1); $vendor = strstr($relativePath, \DIRECTORY_SEPARATOR, true); if (false === $vendor) { @@ -326,7 +326,7 @@ private static function getVendors(): array self::$vendors[] = \dirname((new \ReflectionClass(DebugClassLoader::class))->getFileName()); } foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); $v = \dirname($r->getFileName(), 2); if (file_exists($v.'/composer/installed.json')) { @@ -341,7 +341,7 @@ private static function getVendors(): array } foreach ($paths as $path) { foreach (self::$vendors as $vendor) { - if (0 !== strpos($path, $vendor)) { + if (!str_starts_with($path, $vendor)) { self::$internalPaths[] = $path; } } @@ -371,13 +371,13 @@ private function getPathType(string $path): string return self::PATH_TYPE_UNDETERMINED; } foreach (self::getVendors() as $vendor) { - if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { + if (str_starts_with($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { return self::PATH_TYPE_VENDOR; } } foreach (self::$internalPaths as $internalPath) { - if (0 === strpos($realPath, $internalPath)) { + if (str_starts_with($realPath, $internalPath)) { return self::PATH_TYPE_SELF; } } @@ -389,7 +389,6 @@ public function toString(): string { $exception = new \Exception($this->message); $reflection = new \ReflectionProperty($exception, 'trace'); - $reflection->setAccessible(true); $reflection->setValue($exception, $this->trace); return ($this->originatesFromAnObject() ? 'deprecation triggered by '.$this->originatingClass().'::'.$this->originatingMethod().":\n" : '') diff --git a/src/Symfony/Bridge/PhpUnit/DnsMock.php b/src/Symfony/Bridge/PhpUnit/DnsMock.php index 84251c10d2d36..bc2ac1a8e4f34 100644 --- a/src/Symfony/Bridge/PhpUnit/DnsMock.php +++ b/src/Symfony/Bridge/PhpUnit/DnsMock.php @@ -170,7 +170,7 @@ public static function register($class): void if (0 < strpos($class, '\\Tests\\')) { $ns = str_replace('\\Tests\\', '\\', $class); $mockedNs[] = substr($ns, 0, strrpos($ns, '\\')); - } elseif (0 === strpos($class, 'Tests\\')) { + } elseif (str_starts_with($class, 'Tests\\')) { $mockedNs[] = substr($class, 6, strrpos($class, '\\') - 6); } foreach ($mockedNs as $ns) { diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV7.php b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV8.php similarity index 97% rename from src/Symfony/Bridge/PhpUnit/Legacy/CommandForV7.php rename to src/Symfony/Bridge/PhpUnit/Legacy/CommandForV8.php index 99a1e683525dd..ffeb2b81d4c4a 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV7.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CommandForV8.php @@ -19,7 +19,7 @@ /** * @internal */ -class CommandForV7 extends BaseCommand +class CommandForV8 extends BaseCommand { protected function createRunner(): BaseRunner { diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php b/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php deleted file mode 100644 index b132f473c547e..0000000000000 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ConstraintTraitForV7.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\PhpUnit\Legacy; - -use SebastianBergmann\Exporter\Exporter; - -/** - * @internal - */ -trait ConstraintTraitForV7 -{ - use ConstraintLogicTrait; - - /** - * @return bool|null - */ - public function evaluate($other, $description = '', $returnResult = false) - { - return $this->doEvaluate($other, $description, $returnResult); - } - - public function count(): int - { - return $this->doCount(); - } - - public function toString(): string - { - return $this->doToString(); - } - - protected function additionalFailureDescription($other): string - { - return $this->doAdditionalFailureDescription($other); - } - - protected function exporter(): Exporter - { - if (null === $this->exporter) { - $this->exporter = new Exporter(); - } - - return $this->exporter; - } - - protected function failureDescription($other): string - { - return $this->doFailureDescription($other); - } - - protected function matches($other): bool - { - return $this->doMatches($other); - } -} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ExpectDeprecationTraitForV8_4.php b/src/Symfony/Bridge/PhpUnit/Legacy/ExpectDeprecationTraitForV8_4.php index d15963520d6f2..95823c2c6ab11 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ExpectDeprecationTraitForV8_4.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/ExpectDeprecationTraitForV8_4.php @@ -22,7 +22,7 @@ trait ExpectDeprecationTraitForV8_4 public function expectDeprecation(): void { if (1 > \func_num_args() || !\is_string($message = func_get_arg(0))) { - throw new \InvalidArgumentException(sprintf('The "%s()" method requires the string $message argument.', __FUNCTION__)); + throw new \InvalidArgumentException(\sprintf('The "%s()" method requires the string $message argument.', __FUNCTION__)); } // Expected deprecations set by isolated tests need to be written to a file @@ -52,7 +52,7 @@ public function expectDeprecation(): void */ public function expectDeprecationMessage(string $message): void { - throw new \BadMethodCallException(sprintf('The "%s()" method is not supported by Symfony\'s PHPUnit Bridge ExpectDeprecationTrait, pass the message to expectDeprecation() instead.', __FUNCTION__)); + throw new \BadMethodCallException(\sprintf('The "%s()" method is not supported by Symfony\'s PHPUnit Bridge ExpectDeprecationTrait, pass the message to expectDeprecation() instead.', __FUNCTION__)); } /** @@ -60,6 +60,6 @@ public function expectDeprecationMessage(string $message): void */ public function expectDeprecationMessageMatches(string $regularExpression): void { - throw new \BadMethodCallException(sprintf('The "%s()" method is not supported by Symfony\'s PHPUnit Bridge ExpectDeprecationTrait.', __FUNCTION__)); + throw new \BadMethodCallException(\sprintf('The "%s()" method is not supported by Symfony\'s PHPUnit Bridge ExpectDeprecationTrait.', __FUNCTION__)); } } diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php deleted file mode 100644 index 8673bdc0a1d2b..0000000000000 --- a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\PhpUnit\Legacy; - -use PHPUnit\Framework\Error\Error; -use PHPUnit\Framework\Error\Notice; -use PHPUnit\Framework\Error\Warning; - -/** - * This trait is @internal. - */ -trait PolyfillTestCaseTrait -{ - /** - * @param string $messageRegExp - * - * @return void - */ - public function expectExceptionMessageMatches($messageRegExp) - { - $this->expectExceptionMessageRegExp($messageRegExp); - } - - /** - * @return void - */ - public function expectNotice() - { - $this->expectException(Notice::class); - } - - /** - * @param string $message - * - * @return void - */ - public function expectNoticeMessage($message) - { - $this->expectExceptionMessage($message); - } - - /** - * @param string $regularExpression - * - * @return void - */ - public function expectNoticeMessageMatches($regularExpression) - { - $this->expectExceptionMessageMatches($regularExpression); - } - - /** - * @return void - */ - public function expectWarning() - { - $this->expectException(Warning::class); - } - - /** - * @param string $message - * - * @return void - */ - public function expectWarningMessage($message) - { - $this->expectExceptionMessage($message); - } - - /** - * @param string $regularExpression - * - * @return void - */ - public function expectWarningMessageMatches($regularExpression) - { - $this->expectExceptionMessageMatches($regularExpression); - } - - /** - * @return void - */ - public function expectError() - { - $this->expectException(Error::class); - } - - /** - * @param string $message - * - * @return void - */ - public function expectErrorMessage($message) - { - $this->expectExceptionMessage($message); - } - - /** - * @param string $regularExpression - * - * @return void - */ - public function expectErrorMessageMatches($regularExpression) - { - $this->expectExceptionMessageMatches($regularExpression); - } -} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 486d3bf155440..5547a91a2bdad 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -57,7 +57,7 @@ public function __construct(array $mockedNamespaces = []) (new ExcludeList())->getExcludedDirectories(); ExcludeList::addDirectory(\dirname((new \ReflectionClass(__CLASS__))->getFileName(), 2)); } elseif (method_exists(Blacklist::class, 'addDirectory')) { - (new BlackList())->getBlacklistedDirectories(); + (new Blacklist())->getBlacklistedDirectories(); Blacklist::addDirectory(\dirname((new \ReflectionClass(__CLASS__))->getFileName(), 2)); } else { Blacklist::$blacklistedClassNames[__CLASS__] = 2; @@ -93,12 +93,12 @@ public function __construct(array $mockedNamespaces = []) } } - public function __sleep() + public function __serialize(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup() + public function __unserialize(array $data): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } @@ -124,7 +124,7 @@ public function startTestSuite($suite): void if (!$test instanceof TestCase) { continue; } - if (null === Test::getPreserveGlobalStateSettings(\get_class($test), $test->getName(false))) { + if (null === Test::getPreserveGlobalStateSettings($test::class, $test->getName(false))) { $test->setPreserveGlobalState(false); } } @@ -181,7 +181,7 @@ public function startTestSuite($suite): void continue; } if ($test instanceof TestCase - && isset($this->wasSkipped[\get_class($test)][$test->getName()]) + && isset($this->wasSkipped[$test::class][$test->getName()]) ) { $skipped[] = $test; } @@ -196,10 +196,10 @@ public function addSkippedTest($test, \Exception $e, $time): void if (0 < $this->state) { if ($test instanceof DataProviderTestSuite) { foreach ($test->tests() as $testWithDataProvider) { - $this->isSkipped[\get_class($testWithDataProvider)][$testWithDataProvider->getName()] = 1; + $this->isSkipped[$testWithDataProvider::class][$testWithDataProvider->getName()] = 1; } } else { - $this->isSkipped[\get_class($test)][$test->getName()] = 1; + $this->isSkipped[$test::class][$test->getName()] = 1; } } } @@ -214,15 +214,15 @@ public function startTest($test): void putenv('SYMFONY_EXPECTED_DEPRECATIONS_SERIALIZE='.tempnam(sys_get_temp_dir(), 'expectdeprec')); } - $groups = Test::getGroups(\get_class($test), $test->getName(false)); + $groups = Test::getGroups($test::class, $test->getName(false)); if (!$this->runsInSeparateProcess) { if (\in_array('time-sensitive', $groups, true)) { - ClockMock::register(\get_class($test)); + ClockMock::register($test::class); ClockMock::withClockMock(true); } if (\in_array('dns-sensitive', $groups, true)) { - DnsMock::register(\get_class($test)); + DnsMock::register($test::class); } } @@ -230,7 +230,7 @@ public function startTest($test): void return; } - $annotations = Test::parseTestMethodAnnotations(\get_class($test), $test->getName(false)); + $annotations = Test::parseTestMethodAnnotations($test::class, $test->getName(false)); if (isset($annotations['class']['expectedDeprecation'])) { $test->getTestResultObject()->addError($test, new AssertionFailedError('"@expectedDeprecation" annotations are not allowed at the class level.'), 0); @@ -268,14 +268,14 @@ public function endTest($test, $time): void DebugClassLoader::checkClasses(); } - $className = \get_class($test); + $className = $test::class; $groups = Test::getGroups($className, $test->getName(false)); if ($this->checkNumAssertions) { $assertions = \count(self::$expectedDeprecations) + $test->getNumAssertions(); if ($test->doesNotPerformAssertions() && $assertions > 0) { - $test->getTestResultObject()->addFailure($test, new RiskyTestError(sprintf('This test is annotated with "@doesNotPerformAssertions", but performed %s assertions', $assertions)), $time); - } elseif ($assertions === 0 && !$test->doesNotPerformAssertions() && $test->getTestResultObject()->noneSkipped()) { + $test->getTestResultObject()->addFailure($test, new RiskyTestError(\sprintf('This test is annotated with "@doesNotPerformAssertions", but performed %s assertions', $assertions)), $time); + } elseif (0 === $assertions && !$test->doesNotPerformAssertions() && $test->getTestResultObject()->noneSkipped()) { $test->getTestResultObject()->addFailure($test, new RiskyTestError('This test did not perform any assertions'), $time); } @@ -357,7 +357,6 @@ private function willBeIsolated(TestCase $test): bool } $r = new \ReflectionProperty($test, 'runTestInSeparateProcess'); - $r->setAccessible(true); return $r->getValue($test) ?? false; } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php index 7df7865d1c9be..95c354e184ecb 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\PhpUnit\Tests; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ClockMock; @@ -19,6 +20,7 @@ * * @covers \Symfony\Bridge\PhpUnit\ClockMock */ +#[CoversClass(ClockMock::class)] class ClockMockTest extends TestCase { public static function setUpBeforeClass(): void @@ -79,4 +81,9 @@ public function testHrTimeAsNumber() { $this->assertSame(1234567890125000000, hrtime(true)); } + + public function testStrToTime() + { + $this->assertSame(1234567890, strtotime('now')); + } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php index 99d4a4bcfcee8..9d6e26ed4e2b1 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php @@ -11,11 +11,10 @@ namespace Symfony\Bridge\PhpUnit\Tests; +use PHPUnit\Framework\Attributes\RequiresPhpunit; use PHPUnit\Framework\TestCase; -/** - * @requires PHPUnit < 10 - */ +#[RequiresPhpunit('<10')] class CoverageListenerTest extends TestCase { public function test() @@ -34,7 +33,7 @@ public function test() exec("$php $phpunit -c $dir/phpunit-with-listener.xml.dist $dir/tests/ --coverage-text --colors=never 2> /dev/null", $output); $output = implode("\n", $output); - if (false === strpos($output, 'FooCov')) { + if (!str_contains($output, 'FooCov')) { $this->addToAssertionCount(1); } else { $this->assertMatchesRegularExpression('/FooCov\n\s*Methods:\s+0.00%[^\n]+Lines:\s+0.00%/', $output); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php index 7eec02954c1ca..3faadf33d8f70 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/ConfigurationTest.php @@ -11,12 +11,15 @@ namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpunit; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Configuration; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\DeprecationGroup; use Symfony\Component\ErrorHandler\DebugClassLoader; +#[RequiresPhpunit('<10')] class ConfigurationTest extends TestCase { private $files; @@ -192,6 +195,7 @@ public static function provideItCanBeDisabled(): array /** * @dataProvider provideItCanBeDisabled */ + #[DataProvider('provideItCanBeDisabled')] public function testItCanBeDisabled(string $encodedString, bool $expectedEnabled) { $configuration = Configuration::fromUrlEncodedString($encodedString); @@ -238,6 +242,7 @@ public function testOutputIsNotVerboseInWeakMode() /** * @dataProvider provideDataForToleratesForGroup */ + #[DataProvider('provideDataForToleratesForGroup')] public function testToleratesForIndividualGroups(string $deprecationsHelper, array $deprecationsPerType, array $expected) { $configuration = Configuration::fromUrlEncodedString($deprecationsHelper); @@ -245,7 +250,7 @@ public function testToleratesForIndividualGroups(string $deprecationsHelper, arr $groups = $this->buildGroups($deprecationsPerType); foreach ($expected as $groupName => $tolerates) { - $this->assertSame($tolerates, $configuration->toleratesForGroup($groupName, $groups), sprintf('Deprecation type "%s" is %s', $groupName, $tolerates ? 'tolerated' : 'not tolerated')); + $this->assertSame($tolerates, $configuration->toleratesForGroup($groupName, $groups), \sprintf('Deprecation type "%s" is %s', $groupName, $tolerates ? 'tolerated' : 'not tolerated')); } } @@ -463,9 +468,6 @@ public function testExistingBaselineAndGeneration() $this->assertEquals(json_encode($expected, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES), file_get_contents($filename)); } - /** - * @requires PHPUnit < 10 - */ public function testBaselineGenerationWithDeprecationTriggeredByDebugClassLoader() { $filename = $this->createFile(); @@ -515,7 +517,7 @@ public function testBaselineFileException() $filename = $this->createFile(); unlink($filename); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('The baselineFile "%s" does not exist.', $filename)); + $this->expectExceptionMessage(\sprintf('The baselineFile "%s" does not exist.', $filename)); Configuration::fromUrlEncodedString('baselineFile='.urlencode($filename)); } @@ -529,7 +531,7 @@ public function testBaselineFileWriteError() $this->expectExceptionMessageMatches('/[Ff]ailed to open stream: Permission denied/'); set_error_handler(static function (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null): bool { - if ($errno & (E_WARNING | E_WARNING)) { + if ($errno & (\E_WARNING | \E_WARNING)) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); } @@ -595,7 +597,7 @@ public function testIgnoreFileException() $filename = $this->createFile(); unlink($filename); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('The ignoreFile "%s" does not exist.', $filename)); + $this->expectExceptionMessage(\sprintf('The ignoreFile "%s" does not exist.', $filename)); Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename)); } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationGroupTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationGroupTest.php index df746e5e38907..6b55820efb591 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationGroupTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationGroupTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationNoticeTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationNoticeTest.php index c0a88c443b4d7..fe4c456a6a82a 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationNoticeTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationNoticeTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler; use PHPUnit\Framework\TestCase; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php index 4c17a806b4281..337fbd1fb8992 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation; @@ -28,7 +29,7 @@ private static function getVendorDir() } foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); $vendorDir = \dirname($r->getFileName(), 2); if (file_exists($vendorDir.'/composer/installed.json') && @mkdir($vendorDir.'/myfakevendor/myfakepackage1', 0777, true)) { @@ -88,6 +89,7 @@ public function testItRulesOutFilesOutsideVendorsAsIndirect() /** * @dataProvider mutedProvider */ + #[DataProvider('mutedProvider')] public function testItMutesOnlySpecificErrorMessagesWhenTheCallingCodeIsInPhpunit($muted, $callingClass, $message) { $trace = $this->debugBacktrace(); @@ -170,6 +172,7 @@ public static function providerGetTypeDetectsSelf(): array /** * @dataProvider providerGetTypeDetectsSelf */ + #[DataProvider('providerGetTypeDetectsSelf')] public function testGetTypeDetectsSelf(string $expectedType, string $message, string $traceClass, string $file) { $trace = [ @@ -233,6 +236,7 @@ public static function providerGetTypeUsesRightTrace(): array /** * @dataProvider providerGetTypeUsesRightTrace */ + #[DataProvider('providerGetTypeUsesRightTrace')] public function testGetTypeUsesRightTrace(string $expectedType, string $message, array $trace) { $deprecation = new Deprecation( @@ -268,14 +272,13 @@ private static function removeDir($dir) public static function setUpBeforeClass(): void { foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); $v = \dirname($r->getFileName(), 2); if (file_exists($v.'/composer/installed.json')) { $loader = require $v.'/autoload.php'; $reflection = new \ReflectionClass($loader); $prop = $reflection->getProperty('prefixDirsPsr4'); - $prop->setAccessible(true); $currentValue = $prop->getValue($loader); self::$prefixDirsPsr4[] = [$prop, $loader, $currentValue]; $currentValue['Symfony\\Bridge\\PhpUnit\\'] = [realpath(__DIR__.'/../..')]; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/deprecation/deprecation.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/deprecation/deprecation.php index 92efd9500f973..0ea3e5c3fefe1 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/deprecation/deprecation.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/deprecation/deprecation.php @@ -1,3 +1,12 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + @trigger_error('I come from… afar! :D', \E_USER_DEPRECATED); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/AppService.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/AppService.php index 2b6cb316af143..b8f6dc258cf45 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/AppService.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/AppService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace App\Services; use acme\lib\SomeService; @@ -20,9 +29,9 @@ public function selfDeprecation(bool $useContracts = false) { $args = [__FUNCTION__, __FUNCTION__]; if ($useContracts) { - trigger_deprecation('App', '3.0', sprintf('%s is deprecated, use %s_new instead.', ...$args)); + trigger_deprecation('App', '3.0', \sprintf('%s is deprecated, use %s_new instead.', ...$args)); } else { - @trigger_error(sprintf('Since App 3.0: %s is deprecated, use %s_new instead.', ...$args), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Since App 3.0: %s is deprecated, use %s_new instead.', ...$args), \E_USER_DEPRECATED); } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/BarService.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/BarService.php index 868de5bd443db..5e0d66c09aa5d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/BarService.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/BarService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace App\Services; use acme\lib\ExtendsDeprecatedClassFromOtherVendor; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/ExtendsDeprecatedFromVendor.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/ExtendsDeprecatedFromVendor.php index b4305e0d08a55..2105c3ca0e33b 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/ExtendsDeprecatedFromVendor.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_app/ExtendsDeprecatedFromVendor.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace App\Services; use fcy\lib\DeprecatedClass; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/ExtendsDeprecatedClassFromOtherVendor.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/ExtendsDeprecatedClassFromOtherVendor.php index f748109dba135..600faca8a412d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/ExtendsDeprecatedClassFromOtherVendor.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/ExtendsDeprecatedClassFromOtherVendor.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace acme\lib; use fcy\lib\DeprecatedClass; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php index 26a3237e77941..e38211b1cb1f7 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/PhpDeprecation.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace acme\lib; class PhpDeprecation implements \Serializable diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/SomeService.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/SomeService.php index cc237e6146c23..6064426f69f75 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/SomeService.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/SomeService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace acme\lib; use bar\lib\AnotherService; @@ -10,9 +19,9 @@ public function deprecatedApi(bool $useContracts = false) { $args = [__FUNCTION__, __FUNCTION__]; if ($useContracts) { - trigger_deprecation('acme/lib', '3.0', sprintf('%s is deprecated, use %s_new instead.', ...$args)); + trigger_deprecation('acme/lib', '3.0', \sprintf('%s is deprecated, use %s_new instead.', ...$args)); } else { - @trigger_error(sprintf('Since acme/lib 3.0: %s is deprecated, use %s_new instead.', ...$args), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Since acme/lib 3.0: %s is deprecated, use %s_new instead.', ...$args), \E_USER_DEPRECATED); } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php index c6507d7f297f6..5784566cb9651 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + eval(<<<'EOPHP' namespace PHPUnit\Util; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php index 3c4471bcbe345..68db330c67c5d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + require_once __DIR__.'/composer/autoload_real.php'; return ComposerAutoloaderInitFake::getLoader(); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/bar/lib/AnotherService.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/bar/lib/AnotherService.php index 2e2f0f9b6b4b5..272418662e48d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/bar/lib/AnotherService.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/bar/lib/AnotherService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace bar\lib; class AnotherService @@ -8,9 +17,9 @@ public function deprecatedApi(bool $useContracts = false) { $args = [__FUNCTION__, __FUNCTION__]; if ($useContracts) { - trigger_deprecation('bar/lib', '3.0', sprintf('%s is deprecated, use %s_new instead.', ...$args)); + trigger_deprecation('bar/lib', '3.0', \sprintf('%s is deprecated, use %s_new instead.', ...$args)); } else { - @trigger_error(sprintf('Since bar/lib 3.0: %s is deprecated, use %s_new instead.', ...$args), \E_USER_DEPRECATED); + @trigger_error(\sprintf('Since bar/lib 3.0: %s is deprecated, use %s_new instead.', ...$args), \E_USER_DEPRECATED); } } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/composer/autoload_real.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/composer/autoload_real.php index 4b80d96c9bc5d..231ae4f5bcfd4 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/composer/autoload_real.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/composer/autoload_real.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + class ComposerLoaderFake { public function getPrefixes() @@ -27,7 +36,7 @@ public function loadClass($className) public function findFile($class) { foreach ($this->getPrefixesPsr4() as $prefix => $baseDirs) { - if (0 !== strpos($class, $prefix)) { + if (!str_starts_with($class, $prefix)) { continue; } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/fcy/lib/DeprecatedClass.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/fcy/lib/DeprecatedClass.php index f6672cea20400..16edcaf666f1b 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/fcy/lib/DeprecatedClass.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/fcy/lib/DeprecatedClass.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace fcy\lib; /** diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/autoload.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/autoload.php index c1c963926bd30..f1aec32cb774f 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/autoload.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/autoload.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + require_once __DIR__.'/composer/autoload_real.php'; return ComposerAutoloaderInitFakeBis::getLoader(); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/composer/autoload_real.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/composer/autoload_real.php index aabb103e4d04c..2a52065df313b 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/composer/autoload_real.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/composer/autoload_real.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + class ComposerLoaderFakeBis { public function getPrefixes() @@ -17,7 +26,7 @@ public function getPrefixesPsr4() public function loadClass($className) { foreach ($this->getPrefixesPsr4() as $prefix => $baseDirs) { - if (0 !== strpos($className, $prefix)) { + if (!str_starts_with($className, $prefix)) { continue; } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/foo/lib/SomeOtherService.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/foo/lib/SomeOtherService.php index 8ab3230724c06..d9c67b1c025f3 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/foo/lib/SomeOtherService.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor_bis/foo/lib/SomeOtherService.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace foo\lib; class SomeOtherService diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/generate_phar.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/generate_phar.php index 75125d510025c..df875111c0af0 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/generate_phar.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/generate_phar.php @@ -1,4 +1,13 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + $phar = new Phar(__DIR__.\DIRECTORY_SEPARATOR.'deprecation.phar', 0, 'deprecation.phar'); $phar->buildFromDirectory(__DIR__.\DIRECTORY_SEPARATOR.'deprecation'); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt index 1ead2ef4a4013..3048efbfab53a 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/php_deprecation_from_vendor_class.phpt @@ -1,7 +1,5 @@ --TEST-- Test that a PHP deprecation from a vendor class autoload is considered indirect. ---SKIPIF-- - --FILE-- expectDeprecation('foo'); @@ -39,6 +41,8 @@ public function testOne() * * @runInSeparateProcess */ + #[Group('legacy')] + #[RunInSeparateProcess] public function testOneInIsolation() { $this->expectDeprecation('foo'); @@ -50,6 +54,7 @@ public function testOneInIsolation() * * @group legacy */ + #[Group('legacy')] public function testMany() { $this->expectDeprecation('foo'); @@ -65,6 +70,7 @@ public function testMany() * * @expectedDeprecation foo */ + #[Group('legacy')] public function testOneWithAnnotation() { $this->expectDeprecation('bar'); @@ -80,6 +86,7 @@ public function testOneWithAnnotation() * @expectedDeprecation foo * @expectedDeprecation bar */ + #[Group('legacy')] public function testManyWithAnnotation() { $this->expectDeprecation('ccc'); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ExpectedDeprecationAnnotationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ExpectedDeprecationAnnotationTest.php index 1db5448c87621..a3112cf76f1f5 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ExpectedDeprecationAnnotationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ExpectedDeprecationAnnotationTest.php @@ -11,11 +11,11 @@ namespace Symfony\Bridge\PhpUnit\Tests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpunit; use PHPUnit\Framework\TestCase; -/** - * @requires PHPUnit < 10 - */ +#[RequiresPhpunit('<10')] final class ExpectedDeprecationAnnotationTest extends TestCase { /** @@ -25,6 +25,7 @@ final class ExpectedDeprecationAnnotationTest extends TestCase * * @expectedDeprecation foo */ + #[Group('legacy')] public function testOne() { @trigger_error('foo', \E_USER_DEPRECATED); @@ -38,6 +39,7 @@ public function testOne() * @expectedDeprecation foo * @expectedDeprecation bar */ + #[Group('legacy')] public function testMany() { @trigger_error('foo', \E_USER_DEPRECATED); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/FailTests/ExpectDeprecationTraitTestFail.php b/src/Symfony/Bridge/PhpUnit/Tests/FailTests/ExpectDeprecationTraitTestFail.php index 7bf40df6466df..10da25f4af5d8 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/FailTests/ExpectDeprecationTraitTestFail.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/FailTests/ExpectDeprecationTraitTestFail.php @@ -11,6 +11,9 @@ namespace Symfony\Bridge\PhpUnit\Tests\FailTests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpunit; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; @@ -19,9 +22,8 @@ * * This class is deliberately suffixed with *TestFail.php so that it is ignored * by PHPUnit. This test is designed to fail. See ../expectdeprecationfail.phpt. - * - * @requires PHPUnit < 10 */ +#[RequiresPhpunit('<10')] final class ExpectDeprecationTraitTestFail extends TestCase { use ExpectDeprecationTrait; @@ -31,6 +33,7 @@ final class ExpectDeprecationTraitTestFail extends TestCase * * @group legacy */ + #[Group('legacy')] public function testOne() { $this->expectDeprecation('foo'); @@ -44,6 +47,8 @@ public function testOne() * * @runInSeparateProcess */ + #[Group('legacy')] + #[RunInSeparateProcess] public function testOneInIsolation() { $this->expectDeprecation('foo'); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestNotRisky.php b/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestNotRisky.php index 8008287659e98..bd259a50ef8bb 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestNotRisky.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestNotRisky.php @@ -11,15 +11,15 @@ namespace Symfony\Bridge\PhpUnit\Tests\FailTests; +use PHPUnit\Framework\Attributes\RequiresPhpunit; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; /** * This class is deliberately suffixed with *TestRisky.php so that it is ignored * by PHPUnit. This test is designed to fail. See ../expectnotrisky.phpt. - * - * @requires PHPUnit < 10 */ +#[RequiresPhpunit('<10')] final class NoAssertionsTestNotRisky extends TestCase { use ExpectDeprecationTrait; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestRisky.php b/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestRisky.php index 5ec13753ec4a8..559b86b832d32 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestRisky.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/FailTests/NoAssertionsTestRisky.php @@ -11,15 +11,16 @@ namespace Symfony\Bridge\PhpUnit\Tests\FailTests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpunit; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; /** * This class is deliberately suffixed with *TestRisky.php so that it is ignored * by PHPUnit. This test is designed to fail. See ../expectrisky.phpt. - * - * @requires PHPUnit < 10 */ +#[RequiresPhpunit('<10')] final class NoAssertionsTestRisky extends TestCase { use ExpectDeprecationTrait; @@ -29,6 +30,7 @@ final class NoAssertionsTestRisky extends TestCase * * @group legacy */ + #[Group('legacy')] public function testOne() { $this->expectNotToPerformAssertions(); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php index d764638d04958..503d675b42844 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php @@ -9,11 +9,13 @@ * file that was distributed with this source code. */ +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; /** * @coversDefaultClass \DateTime */ +#[CoversClass(DateTime::class)] class CoversDefaultClassTest extends TestCase { public function test() diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php index e60ea97e57bbd..8e3cb0a7f96a7 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php @@ -9,11 +9,13 @@ * file that was distributed with this source code. */ +use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\TestCase; /** * @coversNothing */ +#[CoversNothing] class CoversNothingTest extends TestCase { public function test() diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php index f6d3406046d86..67ac74d7e00c7 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php @@ -9,13 +9,15 @@ * file that was distributed with this source code. */ +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +/** + * @covers \DateTime + */ +#[CoversClass(DateTime::class)] class CoversTest extends TestCase { - /** - * @covers \DateTime - */ public function test() { $this->assertTrue(true); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Metadata/AttributeReaderTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Metadata/AttributeReaderTest.php index b82a7acc16e4e..eb3a7765642b1 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Metadata/AttributeReaderTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Metadata/AttributeReaderTest.php @@ -11,20 +11,19 @@ namespace Symfony\Bridge\PhpUnit\Tests\Metadata; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\Attribute\DnsSensitive; use Symfony\Bridge\PhpUnit\Attribute\TimeSensitive; use Symfony\Bridge\PhpUnit\Metadata\AttributeReader; use Symfony\Bridge\PhpUnit\Tests\Metadata\Fixtures\FooBar; -/** - * @requires PHP 8.0 - */ -final class AttributeReaderTest extends TestCase +class AttributeReaderTest extends TestCase { /** * @dataProvider provideReadCases */ + #[DataProvider('provideReadCases')] public function testAttributesAreRead(string $method, string $attributeClass, array $expected) { $reader = new AttributeReader(); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php b/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php index 593e0b4e14342..aede756a586a3 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bridge\PhpUnit\Tests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; /** @@ -18,6 +20,7 @@ * * @requires extension ext-dummy */ +#[RequiresPhpExtension('ext-dummy')] final class OnlyExpectingDeprecationSkippedTest extends TestCase { /** @@ -27,6 +30,7 @@ final class OnlyExpectingDeprecationSkippedTest extends TestCase * * @expectedDeprecation unreachable */ + #[Group('legacy')] public function testExpectingOnlyDeprecations() { $this->fail('should never be ran.'); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php index 07fb9a2287f06..d86e2db65b41d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bridge\PhpUnit\Tests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpunit; +use PHPUnit\Framework\Exception; use PHPUnit\Framework\TestCase; /** @@ -19,9 +22,9 @@ * @group legacy * * @runTestsInSeparateProcesses - * - * @requires PHPUnit < 10 */ +#[RequiresPhpunit('<10')] +#[Group('legacy')] class ProcessIsolationTest extends TestCase { /** @@ -35,7 +38,7 @@ public function testIsolation() public function testCallingOtherErrorHandler() { - $this->expectException(\PHPUnit\Framework\Exception::class); + $this->expectException(Exception::class); $this->expectExceptionMessage('Test that PHPUnit\'s error handler fires.'); trigger_error('Test that PHPUnit\'s error handler fires.', \E_USER_WARNING); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/symfonyextensionnotregistered.phpt b/src/Symfony/Bridge/PhpUnit/Tests/symfonyextensionnotregistered.phpt index e66b677f772e9..0a140770ae41d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/symfonyextensionnotregistered.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/symfonyextensionnotregistered.phpt @@ -23,451 +23,451 @@ Expected deprecation with message "The "Symfony\Bridge\PhpUnit\Tests\Fixtures\sy %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testTimeMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testMicrotimeMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testSleepMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testUsleepMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDateMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGmdateMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testHrtimeMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testCheckdnsrrMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsCheckRecordMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGetmxrrMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetMxMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbyaddrMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynameMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testGethostbynamelMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered with data set "test class namespace" ('Symfony\Bridge\PhpUnit\Tests') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered%stest class namespace%s ('Symfony\Bridge\PhpUnit\Tests') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered with data set "namespace derived from test namespace" ('Symfony\Bridge\PhpUnit') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered%snamespace derived from test namespace%s ('Symfony\Bridge\PhpUnit') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered with data set "explicitly configured namespace" ('App') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered%sexplicitly configured namespace%s ('App') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered with data set "explicitly configured namespace through attribute on class" ('App\Foo') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered%sexplicitly configured namespace through attribute on class%s ('App\Foo') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d %s/.phpunit/phpunit-%s/phpunit:%d -%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered with data set "explicitly configured namespace through attribute on method" ('App\Bar') +%d) Symfony\Bridge\PhpUnit\Tests\SymfonyExtension::testDnsGetRecordMockIsRegistered%sexplicitly configured namespace through attribute on method%s ('App\Bar') Failed asserting that false is true. %s/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtension.php:%d diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/Command.php b/src/Symfony/Bridge/PhpUnit/TextUI/Command.php index 3cc158f6b8e72..9cf7b8f268d3f 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/Command.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/Command.php @@ -12,7 +12,7 @@ namespace Symfony\Bridge\PhpUnit\TextUI; if (version_compare(\PHPUnit\Runner\Version::id(), '9.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV7', 'Symfony\Bridge\PhpUnit\TextUI\Command'); + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV8', 'Symfony\Bridge\PhpUnit\TextUI\Command'); } else { class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV9', 'Symfony\Bridge\PhpUnit\TextUI\Command'); } diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index 4d9f7667da5c2..b4b348cb8d0a7 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -57,7 +57,7 @@ break; } // short option - if (0 === strpos($cliArgument, '-c')) { + if (str_starts_with($cliArgument, '-c')) { if ('-c' === $cliArgument && array_key_exists($cliArgumentIndex + 1, $argv)) { $phpunitConfigFilename = $getPhpUnitConfig($argv[$cliArgumentIndex + 1]); } else { @@ -97,11 +97,7 @@ } }; -if (\PHP_VERSION_ID >= 80000) { - $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '9.6') ?: '9.6'; -} else { - $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '8.5') ?: '8.5'; -} +$PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '9.6') ?: '9.6'; $MAX_PHPUNIT_VERSION = $getEnvVar('SYMFONY_MAX_PHPUNIT_VERSION', false); @@ -169,7 +165,7 @@ $prevCacheDir = getenv('COMPOSER_CACHE_DIR'); if ($prevCacheDir) { if (false === $absoluteCacheDir = realpath($prevCacheDir)) { - @mkdir($prevCacheDir, 0777, true); + @mkdir($prevCacheDir, 0o777, true); $absoluteCacheDir = realpath($prevCacheDir); } if ($absoluteCacheDir) { @@ -178,14 +174,14 @@ $prevCacheDir = false; } } -$SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml' : '')); +$SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'); $SYMFONY_PHPUNIT_REQUIRE = $getEnvVar('SYMFONY_PHPUNIT_REQUIRE', ''); $configurationHash = md5(implode(\PHP_EOL, [md5_file(__FILE__), $SYMFONY_PHPUNIT_REMOVE, $SYMFONY_PHPUNIT_REQUIRE, (int) $PHPUNIT_REMOVE_RETURN_TYPEHINT])); $PHPUNIT_VERSION_DIR = sprintf('phpunit-%s-%d', $PHPUNIT_VERSION, $PHPUNIT_REMOVE_RETURN_TYPEHINT); if (!file_exists("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit") || $configurationHash !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION_DIR.md5")) { // Build a standalone phpunit without symfony/yaml nor prophecy by default - @mkdir($PHPUNIT_DIR, 0777, true); + @mkdir($PHPUNIT_DIR, 0o777, true); chdir($PHPUNIT_DIR); if (file_exists("$PHPUNIT_VERSION_DIR")) { passthru(sprintf('\\' === \DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s 2> NUL' : 'rm -rf %s', escapeshellarg("$PHPUNIT_VERSION_DIR.old"))); @@ -240,9 +236,6 @@ if ($SYMFONY_PHPUNIT_REQUIRE) { $passthruOrFail("$COMPOSER require --no-update ".$SYMFONY_PHPUNIT_REQUIRE); } - if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { - $passthruOrFail("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); - } if (preg_match('{\^((\d++\.)\d++)[\d\.]*$}', $info['requires']['php'], $phpVersion) && version_compare($phpVersion[2].'99', \PHP_VERSION, '<')) { $passthruOrFail("$COMPOSER config platform.php \"$phpVersion[1].99\""); @@ -267,9 +260,8 @@ } $prevRoot = getenv('COMPOSER_ROOT_VERSION'); putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); - $q = '\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 80000 ? '"' : ''; // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS - $exit = proc_close(proc_open("$q$COMPOSER update --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); + $exit = proc_close(proc_open("$COMPOSER update --no-dev --prefer-dist --no-progress", [], $p, getcwd())); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); if ($prevCacheDir) { putenv("COMPOSER_CACHE_DIR=$prevCacheDir"); @@ -284,8 +276,6 @@ if ($PHPUNIT_REMOVE_RETURN_TYPEHINT) { $alteredCode = preg_replace('/^ ((?:protected|public)(?: static)? function \w+\(\)): void/m', ' $1', $alteredCode); } - $alteredCode = preg_replace('/abstract class TestCase[^\{]+\{/', '$0 '.\PHP_EOL." use \Symfony\Bridge\PhpUnit\Legacy\PolyfillTestCaseTrait;", $alteredCode, 1); - file_put_contents($alteredFile, $alteredCode); // Mutate Assert code $alteredCode = file_get_contents($alteredFile = './src/Framework/Assert.php'); @@ -293,30 +283,30 @@ file_put_contents($alteredFile, $alteredCode); file_put_contents('phpunit', <<<'EOPHP' -getExcludedDirectories(); - PHPUnit\Util\ExcludeList::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListPhpunit::class))->getFileName())); - class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\ExcludeList::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListSimplePhpunit::class))->getFileName())); -} elseif (method_exists(\PHPUnit\Util\Blacklist::class, 'addDirectory')) { - (new PHPUnit\Util\BlackList())->getBlacklistedDirectories(); - PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListPhpunit::class))->getFileName())); - class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListSimplePhpunit::class))->getFileName())); -} else { - PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyExcludeListPhpunit'] = 1; - PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyExcludeListSimplePhpunit'] = 1; -} + if (!class_exists(\SymfonyExcludeListPhpunit::class, false)) { + class SymfonyExcludeListPhpunit {} + } + if (method_exists(\PHPUnit\Util\ExcludeList::class, 'addDirectory')) { + (new PHPUnit\Util\Excludelist())->getExcludedDirectories(); + PHPUnit\Util\ExcludeList::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListPhpunit::class))->getFileName())); + class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\ExcludeList::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListSimplePhpunit::class))->getFileName())); + } elseif (method_exists(\PHPUnit\Util\Blacklist::class, 'addDirectory')) { + (new PHPUnit\Util\BlackList())->getBlacklistedDirectories(); + PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListPhpunit::class))->getFileName())); + class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListSimplePhpunit::class))->getFileName())); + } else { + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyExcludeListPhpunit'] = 1; + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyExcludeListSimplePhpunit'] = 1; + } -Symfony\Bridge\PhpUnit\TextUI\Command::main(); + Symfony\Bridge\PhpUnit\TextUI\Command::main(); -EOPHP + EOPHP ); } @@ -340,16 +330,7 @@ class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\Bla } chdir($oldPwd); -if ($PHPUNIT_VERSION < 8.0) { - $argv = array_filter($argv, function ($v) use (&$argc) { - if ('--do-not-cache-result' !== $v) { - return true; - } - --$argc; - - return false; - }); -} elseif (filter_var(getenv('SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE'), \FILTER_VALIDATE_BOOLEAN)) { +if (filter_var(getenv('SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE'), \FILTER_VALIDATE_BOOLEAN)) { $argv[] = '--do-not-cache-result'; ++$argc; } diff --git a/src/Symfony/Bridge/PhpUnit/bootstrap.php b/src/Symfony/Bridge/PhpUnit/bootstrap.php index 24d593406c87a..5540904749aa9 100644 --- a/src/Symfony/Bridge/PhpUnit/bootstrap.php +++ b/src/Symfony/Bridge/PhpUnit/bootstrap.php @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ -use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Deprecations\Deprecation; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler; @@ -35,19 +34,6 @@ if (class_exists(Deprecation::class)) { Deprecation::withoutDeduplication(); - - if (\PHP_VERSION_ID < 80000) { - // Ignore deprecations about the annotation mapping driver when it's not possible to move to the attribute driver yet - Deprecation::ignoreDeprecations('https://github.com/doctrine/orm/issues/10098'); - } -} - -if (!class_exists(AnnotationRegistry::class, false) && class_exists(AnnotationRegistry::class)) { - if (method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { - AnnotationRegistry::registerUniqueLoader('class_exists'); - } elseif (method_exists(AnnotationRegistry::class, 'registerLoader')) { - AnnotationRegistry::registerLoader('class_exists'); - } } if ( diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index de9101f796d73..d1e6c3ba0aefe 100644 --- a/src/Symfony/Bridge/PhpUnit/composer.json +++ b/src/Symfony/Bridge/PhpUnit/composer.json @@ -18,17 +18,13 @@ } ], "require": { - "php": ">=7.2.5 EVEN ON LATEST SYMFONY VERSIONS TO ALLOW USING", + "php": ">=8.1.0 EVEN ON LATEST SYMFONY VERSIONS TO ALLOW USING", "php": "THIS BRIDGE WHEN TESTING LOWEST SYMFONY VERSIONS.", - "php": ">=7.2.5" + "php": ">=8.1.0" }, "require-dev": { - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/error-handler": "^5.4|^6.4|^7.0", - "symfony/polyfill-php81": "^1.27" - }, - "conflict": { - "phpunit/phpunit": "<7.5|9.1.2" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4.3|^7.0.3|^8.0" }, "autoload": { "files": [ "bootstrap.php" ], diff --git a/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist b/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist index cde576e2c7536..7e310594fcad7 100644 --- a/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist +++ b/src/Symfony/Bridge/PhpUnit/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -19,7 +20,7 @@ - + ./ @@ -27,5 +28,5 @@ ./Tests ./vendor - + diff --git a/src/Symfony/Bridge/PsrHttpMessage/Factory/UploadedFile.php b/src/Symfony/Bridge/PsrHttpMessage/Factory/UploadedFile.php index 34d405856057f..258d8fddaf16b 100644 --- a/src/Symfony/Bridge/PsrHttpMessage/Factory/UploadedFile.php +++ b/src/Symfony/Bridge/PsrHttpMessage/Factory/UploadedFile.php @@ -62,7 +62,7 @@ public function move(string $directory, ?string $name = null): File throw new FileException(\sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, $e->getMessage()), 0, $e); } - @chmod($target, 0666 & ~umask()); + @chmod($target, 0o666 & ~umask()); return $target; } diff --git a/src/Symfony/Bridge/PsrHttpMessage/Tests/Factory/PsrHttpFactoryTest.php b/src/Symfony/Bridge/PsrHttpMessage/Tests/Factory/PsrHttpFactoryTest.php index f5b09c82beb68..bdb037788db63 100644 --- a/src/Symfony/Bridge/PsrHttpMessage/Tests/Factory/PsrHttpFactoryTest.php +++ b/src/Symfony/Bridge/PsrHttpMessage/Tests/Factory/PsrHttpFactoryTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; use Nyholm\Psr7\Factory\Psr17Factory; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; use Symfony\Component\HttpFoundation\BinaryFileResponse; @@ -35,9 +36,7 @@ protected function setUp(): void $this->tmpDir = sys_get_temp_dir(); } - /** - * @dataProvider provideFactories - */ + #[DataProvider('provideFactories')] public function testCreateRequest(PsrHttpFactory $factory) { $stdClass = new \stdClass(); @@ -137,9 +136,7 @@ private function createUploadedFile(string $content, string $originalName, strin return new UploadedFile($path, $originalName, $mimeType, $error, true); } - /** - * @dataProvider provideFactories - */ + #[DataProvider('provideFactories')] public function testCreateResponse(PsrHttpFactory $factory) { $response = new Response( diff --git a/src/Symfony/Bridge/PsrHttpMessage/Tests/Fixtures/App/Kernel.php b/src/Symfony/Bridge/PsrHttpMessage/Tests/Fixtures/App/Kernel.php index 1b72293419c59..6c738a47f21b5 100644 --- a/src/Symfony/Bridge/PsrHttpMessage/Tests/Fixtures/App/Kernel.php +++ b/src/Symfony/Bridge/PsrHttpMessage/Tests/Fixtures/App/Kernel.php @@ -50,7 +50,6 @@ protected function configureContainer(ContainerConfigurator $container): void 'router' => ['utf8' => true], 'secret' => 'for your eyes only', 'test' => true, - 'annotations' => false, 'http_method_override' => false, 'handle_all_throwables' => true, 'php_errors' => ['log' => true], diff --git a/src/Symfony/Bridge/PsrHttpMessage/Tests/Functional/CovertTest.php b/src/Symfony/Bridge/PsrHttpMessage/Tests/Functional/CovertTest.php index 23bdbb92b8c82..e5489745b1625 100644 --- a/src/Symfony/Bridge/PsrHttpMessage/Tests/Functional/CovertTest.php +++ b/src/Symfony/Bridge/PsrHttpMessage/Tests/Functional/CovertTest.php @@ -15,6 +15,7 @@ use Nyholm\Psr7\Response as Psr7Response; use Nyholm\Psr7\ServerRequest as Psr7Request; use Nyholm\Psr7\Stream as Psr7Stream; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -28,7 +29,7 @@ use Symfony\Component\HttpFoundation\Response; /** - * Test to convert a request/response back and forth to make sure we do not loose data. + * Test to convert a request/response back and forth to make sure we do not lose data. * * @author Tobias Nyholm */ @@ -41,9 +42,7 @@ protected function setUp(): void } } - /** - * @dataProvider requestProvider - */ + #[DataProvider('requestProvider')] public function testConvertRequestMultipleTimes(ServerRequestInterface|Request $request, HttpMessageFactoryInterface|HttpFoundationFactoryInterface $firstFactory, HttpMessageFactoryInterface|HttpFoundationFactoryInterface $secondFactory) { $temporaryRequest = $firstFactory->createRequest($request); @@ -151,9 +150,7 @@ public static function requestProvider(): array }, $psr7Requests)); } - /** - * @dataProvider responseProvider - */ + #[DataProvider('responseProvider')] public function testConvertResponseMultipleTimes(ResponseInterface|Response $response, HttpMessageFactoryInterface|HttpFoundationFactoryInterface $firstFactory, HttpMessageFactoryInterface|HttpFoundationFactoryInterface $secondFactory) { $temporaryResponse = $firstFactory->createResponse($response); diff --git a/src/Symfony/Bridge/PsrHttpMessage/composer.json b/src/Symfony/Bridge/PsrHttpMessage/composer.json index a34dfb1008e5e..9d64ac503c592 100644 --- a/src/Symfony/Bridge/PsrHttpMessage/composer.json +++ b/src/Symfony/Bridge/PsrHttpMessage/composer.json @@ -18,14 +18,15 @@ "require": { "php": ">=8.2", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" + "symfony/http-foundation": "^6.4|^7.0|^8.0" }, "require-dev": { - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", + "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6|^8.0", "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3" @@ -36,7 +37,8 @@ }, "config": { "allow-plugins": { - "php-http/discovery": false + "php-http/discovery": false, + "symfony/runtime": false } }, "autoload": { diff --git a/src/Symfony/Bridge/PsrHttpMessage/phpunit.xml.dist b/src/Symfony/Bridge/PsrHttpMessage/phpunit.xml.dist index fdfe483f56346..d3617f04980db 100644 --- a/src/Symfony/Bridge/PsrHttpMessage/phpunit.xml.dist +++ b/src/Symfony/Bridge/PsrHttpMessage/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index c145a7ef6310f..7b97cb5d80ba5 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -60,25 +60,25 @@ protected function configure(): void new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), ]) ->setHelp(<<<'EOF' -The %command.name% command outputs a list of twig functions, -filters, globals and tests. + The %command.name% command outputs a list of twig functions, + filters, globals and tests. - php %command.full_name% + php %command.full_name% -The command lists all functions, filters, etc. + The command lists all functions, filters, etc. - php %command.full_name% @Twig/Exception/error.html.twig + php %command.full_name% @Twig/Exception/error.html.twig -The command lists all paths that match the given template name. + The command lists all paths that match the given template name. - php %command.full_name% --filter=date + php %command.full_name% --filter=date -The command lists everything that contains the word date. + The command lists everything that contains the word date. - php %command.full_name% --format=json + php %command.full_name% --format=json -The command lists everything in a machine readable json format. -EOF + The command lists everything in a machine readable json format. + EOF ) ; } diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 77bc2b08c8775..b4db81f33aee9 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -57,25 +57,25 @@ protected function configure(): void ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') ->addOption('excludes', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Excluded directories', []) ->setHelp(<<<'EOF' -The %command.name% command lints a template and outputs to STDOUT -the first encountered syntax error. + The %command.name% command lints a template and outputs to STDOUT + the first encountered syntax error. -You can validate the syntax of contents passed from STDIN: + You can validate the syntax of contents passed from STDIN: - cat filename | php %command.full_name% - + cat filename | php %command.full_name% - -Or the syntax of a file: + Or the syntax of a file: - php %command.full_name% filename + php %command.full_name% filename -Or of a whole directory: + Or of a whole directory: - php %command.full_name% dirname + php %command.full_name% dirname -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% dirname --format=json -EOF + php %command.full_name% dirname --format=json + EOF ) ; } diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig index 49cd804398b5e..fc7289c8c3932 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig @@ -24,7 +24,7 @@ col-sm-2 {% block form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index f4e313b4756c8..bfb9d89aaeecc 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -94,7 +94,7 @@ {% set embed_label_classes = parent_label_class|split(' ')|filter(class => class in ['checkbox-inline', 'radio-inline']) %} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ embed_label_classes|join(' '))|trim}) -%} {% endif %} - {%- if label is not same as(false) and label is empty -%} + {%- if label is not same as(false) and not label -%} {%- if label_format is not empty -%} {%- set label = label_format|replace({ '%name%': name, @@ -129,7 +129,7 @@ {% block form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} @@ -199,7 +199,7 @@ {# Help #} {% block form_help -%} - {%- if help is not empty -%} + {%- if help -%} {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-block')|trim}) -%} {%- if translation_domain is same as(false) -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig index 990b324cb0d17..516d79938d6ac 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -25,7 +25,7 @@ col-sm-2 {{ block('fieldset_form_row') }} {%- else -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} @@ -40,7 +40,7 @@ col-sm-2 {% block fieldset_form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index 458cc6847ed8e..9681d4f81c0fc 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -283,7 +283,7 @@ {%- set element = 'fieldset' -%} {%- endif -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} <{{ element|default('div') }}{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> @@ -310,7 +310,7 @@ {# Help #} {% block form_help -%} - {%- if help is not empty -%} + {%- if help -%} {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' form-text text-muted')|trim}) -%} {{- block('form_help_content') -}} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig index 3c24166d48ad0..1d08cc5eb0e8a 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig @@ -28,7 +28,7 @@ {{ block('fieldset_form_row') }} {%- else -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} {%- set row_class = row_class|default(row_attr.class|default('mb-3')) -%} @@ -72,7 +72,7 @@ {% block fieldset_form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig index 17b28fc9ab8d6..d79c0af335779 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_5_layout.html.twig @@ -325,7 +325,7 @@ {%- set element = 'fieldset' -%} {%- endif -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} {%- set row_class = row_class|default(row_attr.class|default('mb-3')|trim) -%} @@ -367,7 +367,7 @@ {#- Hack to properly display help with input group -#} {%- set help_class = ' input-group-text' -%} {%- endif -%} - {%- if help is not empty -%} + {%- if help -%} {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ help_class ~ ' mb-0')|trim}) -%} {%- endif -%} {{- parent() -}} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 537849faebaa4..cbc18f6692503 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -226,7 +226,7 @@ {%- endblock range_widget %} {%- block button_widget -%} - {%- if label is empty -%} + {%- if not label -%} {%- if label_format is not empty -%} {% set label = label_format|replace({ '%name%': name, @@ -301,7 +301,7 @@ {%- endblock form_label -%} {%- block form_label_content -%} - {%- if label is empty -%} + {%- if not label -%} {%- if label_format is not empty -%} {% set label = label_format|replace({ '%name%': name, @@ -331,7 +331,7 @@ {# Help #} {% block form_help -%} - {%- if help is not empty -%} + {%- if help -%} {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-text')|trim}) -%} <{{ element|default('div') }} id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}> {{- block('form_help_content') -}} @@ -367,7 +367,7 @@ {%- block form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig index 00a51ab04bc28..f4f32f1b3ee18 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig @@ -2,7 +2,7 @@ {%- block form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig index 23e463e6822f0..d6f45e0e21833 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig @@ -261,7 +261,7 @@ {% set embed_label_classes = parent_label_class|split(' ')|filter(class => class in ['checkbox-inline', 'radio-inline']) %} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ embed_label_classes|join(' '))|trim}) -%} {% endif %} - {% if label is empty %} + {% if not label %} {%- if label_format is not empty -%} {% set label = label_format|replace({ '%name%': name, @@ -283,7 +283,7 @@ {% block form_row -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig index 7f31e70b796c0..0a7038cb09f70 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/tailwind_2_layout.html.twig @@ -45,7 +45,7 @@ {%- block checkbox_row -%} {%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('mb-6')) }) -%} {%- set widget_attr = {} -%} - {%- if help is not empty -%} + {%- if help -%} {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} {%- endif -%} diff --git a/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php b/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php index 52f84a7d8f23b..5aa37c8bd0fe7 100644 --- a/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php +++ b/src/Symfony/Bridge/Twig/Test/Traits/RuntimeLoaderProvider.php @@ -17,6 +17,9 @@ trait RuntimeLoaderProvider { + /** + * @return void + */ protected function registerTwigRuntimeLoader(Environment $environment, FormRenderer $renderer) { $loader = $this->createMock(RuntimeLoaderInterface::class); diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php index 0367f7704b684..697acffa106ca 100644 --- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php +++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bridge\Twig\Tests; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\AppVariable; use Symfony\Component\HttpFoundation\Request; @@ -31,9 +33,7 @@ protected function setUp(): void $this->appVariable = new AppVariable(); } - /** - * @dataProvider debugDataProvider - */ + #[DataProvider('debugDataProvider')] public function testDebug($debugFlag) { $this->appVariable->setDebug($debugFlag); @@ -56,9 +56,7 @@ public function testEnvironment() $this->assertEquals('dev', $this->appVariable->getEnvironment()); } - /** - * @runInSeparateProcess - */ + #[RunInSeparateProcess] public function testGetSession() { $request = $this->createMock(Request::class); @@ -192,18 +190,14 @@ public function testGetFlashesWithNoRequest() $this->assertEquals([], $this->appVariable->getFlashes()); } - /** - * @runInSeparateProcess - */ + #[RunInSeparateProcess] public function testGetFlashesWithNoSessionStarted() { $flashMessages = $this->setFlashMessages(false); $this->assertEquals($flashMessages, $this->appVariable->getFlashes()); } - /** - * @runInSeparateProcess - */ + #[RunInSeparateProcess] public function testGetFlashes() { $flashMessages = $this->setFlashMessages(); diff --git a/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php index 7ba828c667214..9390326609677 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/DebugCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Command\DebugCommand; use Symfony\Component\Console\Application; @@ -72,9 +73,7 @@ public function testMalformedTemplateName() $this->createCommandTester()->execute(['name' => '@foo']); } - /** - * @dataProvider getDebugTemplateNameTestData - */ + #[DataProvider('getDebugTemplateNameTestData')] public function testDebugTemplateName(array $input, string $output, array $paths) { $tester = $this->createCommandTester($paths); @@ -96,25 +95,24 @@ public static function getDebugTemplateNameTestData() 'input' => ['name' => 'base.html.twig'], 'output' => << ['vendors/twig-bundle/Resources/views/' => 'Twig'], ]; @@ -122,28 +120,27 @@ public static function getDebugTemplateNameTestData() 'input' => ['name' => '@App/foo.html.twig'], 'output' => << $defaultPaths, ]; @@ -151,23 +148,22 @@ public static function getDebugTemplateNameTestData() 'input' => ['name' => 'base.html.twig'], 'output' => << $defaultPaths, ]; @@ -175,29 +171,28 @@ public static function getDebugTemplateNameTestData() 'input' => ['name' => '@Twig/error.html.twig'], 'output' => << $defaultPaths, ]; @@ -205,22 +200,21 @@ public static function getDebugTemplateNameTestData() 'input' => ['name' => '@Twg/error.html.twig'], 'output' => << $defaultPaths, ]; @@ -228,28 +222,27 @@ public static function getDebugTemplateNameTestData() 'input' => ['name' => '@Twig/eror.html.twig'], 'output' => << $defaultPaths, ]; } @@ -294,9 +287,7 @@ public function testWithFilter() $this->assertNotSame($display1, $display2); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures'; @@ -304,7 +295,12 @@ public function testComplete(array $input, array $expectedSuggestions) $environment = new Environment($loader); $application = new Application(); - $application->add(new DebugCommand($environment, $projectDir, [], null, null)); + $command = new DebugCommand($environment, $projectDir, [], null, null); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } $tester = new CommandCompletionTester($application->find('debug:twig')); $suggestions = $tester->complete($input, 2); @@ -339,7 +335,12 @@ private function createCommandTester(array $paths = [], array $bundleMetadata = } $application = new Application(); - $application->add(new DebugCommand($environment, $projectDir, $bundleMetadata, $defaultPath, null)); + $command = new DebugCommand($environment, $projectDir, $bundleMetadata, $defaultPath, null); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } $command = $application->find('debug:twig'); return new CommandTester($command); diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php index 9e4e23a87e813..165119978872f 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bridge\Twig\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Command\LintCommand; use Symfony\Component\Console\Application; @@ -71,10 +74,10 @@ public function testLintFileCompileTimeException() } /** - * When deprecations are not reported by the command, the testsuite reporter will catch them so we need to mark the test as legacy. - * - * @group legacy + * When deprecations are not reported by the command, the testsuite reporter will catch them so we need to mark the test as ignoring deprecations. */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testLintFileWithNotReportedDeprecation() { $tester = $this->createCommandTester(); @@ -111,9 +114,7 @@ public function testLintFileWithMultipleReportedDeprecation() $this->assertStringContainsString('Filter "deprecated_filter" is deprecated', trim($tester->getDisplay())); } - /** - * @group tty - */ + #[Group('tty')] public function testLintDefaultPaths() { $tester = $this->createCommandTester(); @@ -150,9 +151,7 @@ public function testLintAutodetectsGithubActionEnvironment() } } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $tester = new CommandCompletionTester($this->createCommand()); @@ -179,7 +178,11 @@ private function createCommand(): Command $command = new LintCommand($environment); $application = new Application(); - $application->add($command); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } return $application->find('lint:twig'); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php index 28e8997a12e9f..171d13effbd65 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractDivLayoutTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\FormError; use Symfony\Component\Security\Csrf\CsrfToken; @@ -601,9 +602,7 @@ public function testLabelIsNotRenderedWhenSetToFalse() ); } - /** - * @dataProvider themeBlockInheritanceProvider - */ + #[DataProvider('themeBlockInheritanceProvider')] public function testThemeBlockInheritance($theme) { $view = $this->factory @@ -626,9 +625,7 @@ public static function themeBlockInheritanceProvider(): array ]; } - /** - * @dataProvider themeInheritanceProvider - */ + #[DataProvider('themeInheritanceProvider')] public function testThemeInheritance($parentTheme, $childTheme) { $child = $this->factory->createNamedBuilder('child', 'Symfony\Component\Form\Extension\Core\Type\FormType') diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php index 2f7410d1f7591..c7e30f24ae974 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/AbstractLayoutTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Bridge\Twig\Test\FormLayoutTestCase; use Symfony\Component\Form\Extension\Core\Type\PercentType; @@ -57,7 +58,9 @@ protected function getExtensions(): array protected function tearDown(): void { - \Locale::setDefault($this->defaultLocale); + if (isset($this->defaultLocale)) { + \Locale::setDefault($this->defaultLocale); + } } protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) @@ -2711,9 +2714,7 @@ public function testButtonWithTranslationParameters() ); } - /** - * @dataProvider submitFormNoValidateProvider - */ + #[DataProvider('submitFormNoValidateProvider')] public function testSubmitFormNoValidate(bool $validate) { $form = $this->factory->create(SubmitType::class, null, [ diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php index 01817ce597c5d..b182b59f67aa6 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\DumpExtension; use Symfony\Component\VarDumper\Cloner\VarCloner; @@ -22,9 +23,7 @@ class DumpExtensionTest extends TestCase { - /** - * @dataProvider getDumpTags - */ + #[DataProvider('getDumpTags')] public function testDumpTag($template, $debug, $expectedOutput, $expectedDumped) { $extension = new DumpExtension(new VarCloner()); @@ -62,9 +61,7 @@ public static function getDumpTags() ]; } - /** - * @dataProvider getDumpArgs - */ + #[DataProvider('getDumpArgs')] public function testDump($context, $args, $expectedOutput, $debug = true) { $extension = new DumpExtension(new VarCloner()); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/EmojiExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/EmojiExtensionTest.php index 492929a341e7d..61b2178b89a65 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/EmojiExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/EmojiExtensionTest.php @@ -11,19 +11,17 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\EmojiExtension; -/** - * @requires extension intl - */ +#[RequiresPhpExtension('intl')] class EmojiExtensionTest extends TestCase { - /** - * @testWith ["🅰️", ":a:"] - * ["🅰️", ":a:", "slack"] - * ["🅰", ":a:", "github"] - */ + #[TestWith(['🅰️', ':a:'])] + #[TestWith(['🅰️', ':a:', 'slack'])] + #[TestWith(['🅰', ':a:', 'github'])] public function testEmojify(string $expected, string $string, ?string $catalog = null) { $extension = new EmojiExtension(); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig b/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig index 2bd1b2cc6d50c..c5710377bdabe 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig +++ b/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig @@ -5,14 +5,14 @@ {%- endblock _text_id_widget %} {% block _names_entry_label -%} - {% if label is empty %} + {% if not label %} {%- set label = name|humanize -%} {% endif -%} {%- endblock _names_entry_label %} {% block _name_c_entry_label -%} - {% if label is empty %} + {% if not label %} {%- set label = name|humanize -%} {% endif -%} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 7c3742a7409b2..9fd5d4d564de0 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -69,11 +69,12 @@ public function testMoneyWidgetInIso() ; $this->assertSame(<<<'HTML' -
- -
-HTML - , trim($this->renderWidget($view))); +
+ +
+ HTML, + trim($this->renderWidget($view)) + ); } protected function getTemplatePaths(): array diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php index 5fdec71db05e9..16b0934f7c456 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -74,11 +74,12 @@ public function testMoneyWidgetInIso() ; $this->assertSame(<<<'HTML' -
- -
-HTML - , trim($this->renderWidget($view))); +
+ +
+ HTML, + trim($this->renderWidget($view)) + ); } protected function getTemplatePaths(): array diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php index ced0fe607174e..0aaf6fb8db73f 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap5LayoutTest.php @@ -75,9 +75,10 @@ public function testMoneyWidgetInIso() ->createView(); self::assertSame(<<<'HTML' -
-HTML - , trim($this->renderWidget($view))); +
+ HTML, + trim($this->renderWidget($view)) + ); } protected function getTemplatePaths(): array diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index d0e90b1f2a6f7..066aed57ee526 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bridge\Twig\Extension\FormExtension; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Form\TwigRendererEngine; @@ -84,9 +85,7 @@ public static function isSelectedChoiceProvider(): array ]; } - /** - * @dataProvider isSelectedChoiceProvider - */ + #[DataProvider('isSelectedChoiceProvider')] public function testIsChoiceSelected($expected, $choice, $value) { $choice = new ChoiceView($choice, $choice, $choice.' label'); @@ -126,9 +125,7 @@ public static function isRootFormProvider(): array ]; } - /** - * @dataProvider isRootFormProvider - */ + #[DataProvider('isRootFormProvider')] public function testIsRootForm($expected, FormView $formView) { $this->assertSame($expected, \Symfony\Bridge\Twig\Extension\twig_is_root_form($formView)); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php index b92c3f831cb7d..e84e4cd3a37c8 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\HttpFoundationExtension; use Symfony\Component\HttpFoundation\Request; @@ -20,9 +21,7 @@ class HttpFoundationExtensionTest extends TestCase { - /** - * @dataProvider getGenerateAbsoluteUrlData - */ + #[DataProvider('getGenerateAbsoluteUrlData')] public function testGenerateAbsoluteUrl($expected, $path, $pathinfo) { $stack = new RequestStack(); @@ -55,9 +54,7 @@ public static function getGenerateAbsoluteUrlData() ]; } - /** - * @dataProvider getGenerateAbsoluteUrlRequestContextData - */ + #[DataProvider('getGenerateAbsoluteUrlRequestContextData')] public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected) { $requestContext = new RequestContext($baseUrl, 'GET', $host, $scheme, $httpPort, $httpsPort, $path); @@ -66,10 +63,8 @@ public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host $this->assertEquals($expected, $extension->generateAbsoluteUrl($path)); } - /** - * @dataProvider getGenerateAbsoluteUrlRequestContextData - */ - public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path) + #[DataProvider('getGenerateAbsoluteUrlRequestContextData')] + public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected) { $extension = new HttpFoundationExtension(new UrlHelper(new RequestStack())); @@ -105,9 +100,7 @@ public function testGenerateAbsoluteUrlWithScriptFileName() ); } - /** - * @dataProvider getGenerateRelativePathData - */ + #[DataProvider('getGenerateRelativePathData')] public function testGenerateRelativePath($expected, $path, $pathinfo) { $stack = new RequestStack(); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php index ccce1de340c02..3e17a28ca05f7 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php @@ -23,6 +23,7 @@ use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; use Symfony\Component\HttpKernel\Fragment\FragmentUriGenerator; use Twig\Environment; +use Twig\Error\RuntimeError; use Twig\Loader\ArrayLoader; use Twig\RuntimeLoader\RuntimeLoaderInterface; @@ -32,7 +33,7 @@ public function testFragmentWithError() { $renderer = $this->getFragmentHandler(new \Exception('foo')); - $this->expectException(\Twig\Error\RuntimeError::class); + $this->expectException(RuntimeError::class); $this->renderTemplate($renderer); } @@ -68,9 +69,11 @@ public function testGenerateFragmentUri() $loader = new ArrayLoader([ 'index' => \sprintf(<< true, 'cache' => false]); $twig->addExtension(new HttpKernelExtension()); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php index 742a74f325b91..def7085ce71fe 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\RoutingExtension; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -21,9 +22,7 @@ class RoutingExtensionTest extends TestCase { - /** - * @dataProvider getEscapingTemplates - */ + #[DataProvider('getEscapingTemplates')] public function testEscaping($template, $mustBeEscaped) { $twig = new Environment($this->createMock(LoaderInterface::class), ['debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0]); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/SecurityExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/SecurityExtensionTest.php index e0ca4dcbb6901..92ea0ea794dad 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/SecurityExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/SecurityExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ClassExistsMock; use Symfony\Bridge\Twig\Extension\SecurityExtension; @@ -32,9 +33,7 @@ protected function tearDown(): void ClassExistsMock::withMockedClasses([FieldVote::class => true]); } - /** - * @dataProvider provideObjectFieldAclCases - */ + #[DataProvider('provideObjectFieldAclCases')] public function testIsGrantedCreatesFieldVoteObjectWhenFieldNotNull($object, $field, $expectedSubject) { $securityChecker = $this->createMock(AuthorizationCheckerInterface::class); @@ -65,9 +64,7 @@ public function testIsGrantedThrowsWhenFieldNotNullAndFieldVoteClassDoesNotExist $securityExtension->isGranted('ROLE', 'object', 'bar'); } - /** - * @dataProvider provideObjectFieldAclCases - */ + #[DataProvider('provideObjectFieldAclCases')] public function testIsGrantedForUserCreatesFieldVoteObjectWhenFieldNotNull($object, $field, $expectedSubject) { if (!interface_exists(UserAuthorizationCheckerInterface::class)) { @@ -94,8 +91,8 @@ public static function provideObjectFieldAclCases() return [ [null, null, null], ['object', null, 'object'], - ['object', false, new FieldVote('object', false)], - ['object', 0, new FieldVote('object', 0)], + ['object', '', new FieldVote('object', false)], + ['object', '0', new FieldVote('object', 0)], ['object', '', new FieldVote('object', '')], ['object', 'field', new FieldVote('object', 'field')], ]; diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/SerializerExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/SerializerExtensionTest.php index 610030cec5a9f..b6e1a030dc4c0 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/SerializerExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/SerializerExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\SerializerExtension; use Symfony\Bridge\Twig\Extension\SerializerRuntime; @@ -30,9 +31,7 @@ */ class SerializerExtensionTest extends TestCase { - /** - * @dataProvider serializerDataProvider - */ + #[DataProvider('serializerDataProvider')] public function testSerializeFilter(string $template, string $expectedResult) { $twig = $this->getTwig($template); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php index d7ff03d72ff98..3d3785342b936 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php @@ -11,25 +11,25 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\StopwatchExtension; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Stopwatch\StopwatchEvent; use Twig\Environment; use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; use Twig\Loader\ArrayLoader; class StopwatchExtensionTest extends TestCase { public function testFailIfStoppingWrongEvent() { - $this->expectException(\Twig\Error\SyntaxError::class); + $this->expectException(SyntaxError::class); $this->testTiming('{% stopwatch "foo" %}{% endstopwatch "bar" %}', []); } - /** - * @dataProvider getTimingTemplates - */ + #[DataProvider('getTimingTemplates')] public function testTiming($template, $events) { $twig = new Environment(new ArrayLoader(['template' => $template]), ['debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0]); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php index f6dd5f623baee..bb98d1195a116 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php @@ -11,12 +11,14 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Component\Translation\Loader\ArrayLoader; use Symfony\Component\Translation\Translator; use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment; +use Twig\Error\SyntaxError; use Twig\Loader\ArrayLoader as TwigArrayLoader; use Twig\TemplateWrapper; @@ -29,9 +31,7 @@ public function testEscaping() $this->assertEquals('Percent: 12% (approx.)', $output); } - /** - * @dataProvider getTransTests - */ + #[DataProvider('getTransTests')] public function testTrans($template, $expected, array $variables = []) { if ($expected != $this->getTemplate($template)->render($variables)) { @@ -49,14 +49,14 @@ public function testTrans($template, $expected, array $variables = []) public function testTransUnknownKeyword() { - $this->expectException(\Twig\Error\SyntaxError::class); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3.'); $this->getTemplate("{% trans \n\nfoo %}{% endtrans %}")->render(); } public function testTransComplexBody() { - $this->expectException(\Twig\Error\SyntaxError::class); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('A message inside a trans tag must be a simple text in "index" at line 2.'); $this->getTemplate("{% trans %}\n{{ 1 + 2 }}{% endtrans %}")->render(); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php index 21f9e663b27b4..d7e94aab5fdcb 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php @@ -36,7 +36,7 @@ protected function setUp(): void ]; $transitionsMetadata = new \SplObjectStorage(); - $transitionsMetadata->attach($this->t1, ['title' => 't1 title']); + $transitionsMetadata[$this->t1] = ['title' => 't1 title']; $metadataStore = new InMemoryMetadataStore( ['title' => 'workflow title'], ['orderer' => ['title' => 'ordered title']], diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php index cce8ee9a68839..1895d6c74c030 100644 --- a/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Mime/BodyRendererTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Mime; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Mime\BodyRenderer; use Symfony\Bridge\Twig\Mime\TemplatedEmail; @@ -54,13 +55,13 @@ public function testRenderHtmlOnlyWithLeagueConverter() public function testRenderMultiLineHtmlOnly() { $html = << - - -HTML -HTML; + + + + HTML + HTML; $email = $this->prepareEmail(null, $html); $body = $email->getBody(); $this->assertInstanceOf(AlternativePart::class, $body); @@ -137,9 +138,7 @@ public function testRenderedOnceUnserializableContext() $this->assertEquals('Text', $email->getTextBody()); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testRenderWithLocale() { $localeSwitcher = new LocaleSwitcher('en', []); diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php index f77b3ad4b5337..2fb64eed33439 100644 --- a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php @@ -66,42 +66,42 @@ public function testSymfonySerialize() $expected = clone $e; $expectedJson = << - Content-Type: image/png; name="$contentId1" - Content-Transfer-Encoding: base64 - Content-Disposition: inline; - name="$contentId1"; - filename="@assets/images/logo1.png" - - PART + Content-ID: <$contentId1> + Content-Type: image/png; name="$contentId1" + Content-Transfer-Encoding: base64 + Content-Disposition: inline; + name="$contentId1"; + filename="@assets/images/logo1.png" + + PART ); $part2 = str_replace("\n", "\r\n", << - Content-Type: image/png; name="$contentId2" - Content-Transfer-Encoding: base64 - Content-Disposition: inline; - name="$contentId2"; filename=image.png + Content-ID: <$contentId2> + Content-Type: image/png; name="$contentId2" + Content-Transfer-Encoding: base64 + Content-Disposition: inline; + name="$contentId2"; filename=image.png - PART + PART ); self::assertStringContainsString('![](cid:@assets/images/logo1.png)![](cid:image.png)', $body); @@ -64,20 +64,20 @@ public function testEmailAttach() $part1 = str_replace("\n", "\r\n", <<env->isDebug()) { - $barvars = []; - foreach ($context as $barkey => $barval) { - if (!$barval instanceof \Twig\Template) { - $barvars[$barkey] = $barval; - } - } - // line 7 - \Symfony\Component\VarDumper\VarDumper::dump($barvars); -} + if ($this->env->isDebug()) { + $barvars = []; + foreach ($context as $barkey => $barval) { + if (!$barval instanceof \Twig\Template) { + $barvars[$barkey] = $barval; + } + } + // line 7 + \Symfony\Component\VarDumper\VarDumper::dump($barvars); + } -EOTXT; + EOTXT; $this->assertSame($expected, $compiler->compile($node)->getSource()); } @@ -53,18 +53,18 @@ public function testIndented() $compiler = new Compiler($env); $expected = <<<'EOTXT' - if ($this->env->isDebug()) { - $barvars = []; - foreach ($context as $barkey => $barval) { - if (!$barval instanceof \Twig\Template) { - $barvars[$barkey] = $barval; - } - } - // line 7 - \Symfony\Component\VarDumper\VarDumper::dump($barvars); - } - -EOTXT; + if ($this->env->isDebug()) { + $barvars = []; + foreach ($context as $barkey => $barval) { + if (!$barval instanceof \Twig\Template) { + $barvars[$barkey] = $barval; + } + } + // line 7 + \Symfony\Component\VarDumper\VarDumper::dump($barvars); + } + + EOTXT; $this->assertSame($expected, $compiler->compile($node, 1)->getSource()); } @@ -81,12 +81,12 @@ public function testOneVar() $compiler = new Compiler($env); $expected = <<<'EOTXT' -if ($this->env->isDebug()) { - // line 7 - \Symfony\Component\VarDumper\VarDumper::dump(%foo%); -} + if ($this->env->isDebug()) { + // line 7 + \Symfony\Component\VarDumper\VarDumper::dump(%foo%); + } -EOTXT; + EOTXT; $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); @@ -105,15 +105,15 @@ public function testMultiVars() $compiler = new Compiler($env); $expected = <<<'EOTXT' -if ($this->env->isDebug()) { - // line 7 - \Symfony\Component\VarDumper\VarDumper::dump([ - "foo" => %foo%, - "bar" => %bar%, - ]); -} + if ($this->env->isDebug()) { + // line 7 + \Symfony\Component\VarDumper\VarDumper::dump([ + "foo" => %foo%, + "bar" => %bar%, + ]); + } -EOTXT; + EOTXT; $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php index 40063c6b7817f..3d3fd6ec25f57 100644 --- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\NodeVisitor; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; @@ -24,7 +25,7 @@ class TranslationDefaultDomainNodeVisitorTest extends TestCase private static string $message = 'message'; private static string $domain = 'domain'; - /** @dataProvider getDefaultDomainAssignmentTestData */ + #[DataProvider('getDefaultDomainAssignmentTestData')] public function testDefaultDomainAssignment(Node $node) { $env = new Environment($this->createMock(LoaderInterface::class), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); @@ -50,7 +51,7 @@ public function testDefaultDomainAssignment(Node $node) $this->assertEquals([[self::$message, self::$domain]], $visitor->getMessages()); } - /** @dataProvider getDefaultDomainAssignmentTestData */ + #[DataProvider('getDefaultDomainAssignmentTestData')] public function testNewModuleWithoutDefaultDomainTag(Node $node) { $env = new Environment($this->createMock(LoaderInterface::class), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php index fc48beb6caba1..49a00a539bd0a 100644 --- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\NodeVisitor; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; use Twig\Environment; @@ -25,7 +26,7 @@ class TranslationNodeVisitorTest extends TestCase { - /** @dataProvider getMessagesExtractionTestData */ + #[DataProvider('getMessagesExtractionTestData')] public function testMessagesExtraction(Node $node, array $expectedMessages) { $env = new Environment($this->createMock(LoaderInterface::class), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); diff --git a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php index 0c4bcdf62f89b..f4d79ffbab5b8 100644 --- a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php +++ b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\TokenParser; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Node\FormThemeNode; use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; @@ -24,9 +25,7 @@ class FormThemeTokenParserTest extends TestCase { - /** - * @dataProvider getTestsForFormTheme - */ + #[DataProvider('getTestsForFormTheme')] public function testCompile($source, $expected) { $env = new Environment($this->createMock(LoaderInterface::class), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); diff --git a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php index f9ae8c348e0fb..d649df4ef955e 100644 --- a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig\Tests\Translation; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Translation\TwigExtractor; @@ -24,9 +25,7 @@ class TwigExtractorTest extends TestCase { public const CUSTOM_DOMAIN = 'domain'; - /** - * @dataProvider getExtractData - */ + #[DataProvider('getExtractData')] public function testExtract($template, $messages) { $loader = $this->createMock(LoaderInterface::class); @@ -94,9 +93,7 @@ public static function getExtractData() ]; } - /** - * @dataProvider resourcesWithSyntaxErrorsProvider - */ + #[DataProvider('resourcesWithSyntaxErrorsProvider')] public function testExtractSyntaxError($resources, array $messages) { $twig = new Environment($this->createMock(LoaderInterface::class)); @@ -117,9 +114,7 @@ public static function resourcesWithSyntaxErrorsProvider(): array ]; } - /** - * @dataProvider resourceProvider - */ + #[DataProvider('resourceProvider')] public function testExtractWithFiles($resource) { $loader = new ArrayLoader([]); diff --git a/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigTest.php b/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigTest.php index cac1b316cbeda..2b418e9ab44be 100644 --- a/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigTest.php @@ -27,15 +27,15 @@ public function testAttributes() $loader = new AttributeLoader(); self::assertTrue($loader->loadClassMetadata($metadata)); - [$bConstraint] = $metadata->properties['b']->getConstraints(); + [$bConstraint] = $metadata->getPropertyMetadata('b')[0]->getConstraints(); self::assertSame('myMessage', $bConstraint->message); self::assertSame(['Default', 'TwigDummy'], $bConstraint->groups); - [$cConstraint] = $metadata->properties['c']->getConstraints(); + [$cConstraint] = $metadata->getPropertyMetadata('c')[0]->getConstraints(); self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); - [$dConstraint] = $metadata->properties['d']->getConstraints(); + [$dConstraint] = $metadata->getPropertyMetadata('d')[0]->getConstraints(); self::assertFalse($dConstraint->skipDeprecations); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigValidatorTest.php b/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigValidatorTest.php index da5597ad1f45f..f41e06dc35e58 100644 --- a/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigValidatorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Validator/Constraints/TwigValidatorTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bridge\Twig\Tests\Validator\Constraints; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Bridge\Twig\Validator\Constraints\Twig; use Symfony\Bridge\Twig\Validator\Constraints\TwigValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -39,9 +42,7 @@ protected function createValidator(): TwigValidator return new TwigValidator($environment); } - /** - * @dataProvider getValidValues - */ + #[DataProvider('getValidValues')] public function testTwigIsValid($value) { $this->validator->validate($value, new Twig()); @@ -49,9 +50,7 @@ public function testTwigIsValid($value) $this->assertNoViolation(); } - /** - * @dataProvider getInvalidValues - */ + #[DataProvider('getInvalidValues')] public function testInvalidValues($value, $message, $line) { $constraint = new Twig('myMessageTest'); @@ -66,10 +65,10 @@ public function testInvalidValues($value, $message, $line) } /** - * When deprecations are skipped by the validator, the testsuite reporter will catch them so we need to mark the test as legacy. - * - * @group legacy + * When deprecations are skipped by the validator, the testsuite reporter will catch them so we need to mark the test as ignoring deprecations. */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testTwigWithSkipDeprecation() { $constraint = new Twig(skipDeprecations: true); diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index dd2e55d752dc1..9fafcd55a0984 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -25,33 +25,33 @@ "egulias/email-validator": "^2.1.10|^3|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^6.4|^7.0", - "symfony/asset-mapper": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/emoji": "^7.1", - "symfony/finder": "^6.4|^7.0", - "symfony/form": "^6.4.20|^7.2.5", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", + "symfony/asset": "^6.4|^7.0|^8.0", + "symfony/asset-mapper": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/emoji": "^7.1|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4.20|^7.2.5|^8.0", + "symfony/html-sanitizer": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^7.3|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/security-csrf": "^6.4|^7.0", - "symfony/security-http": "^6.4|^7.0", - "symfony/serializer": "^6.4.3|^7.0.3", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/workflow": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/security-csrf": "^6.4|^7.0|^8.0", + "symfony/security-http": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4.3|^7.0.3|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/web-link": "^6.4|^7.0|^8.0", + "symfony/workflow": "^6.4|^7.0|^8.0", "twig/cssinliner-extra": "^3", "twig/inky-extra": "^3", "twig/markdown-extra": "^3" diff --git a/src/Symfony/Bridge/Twig/phpunit.xml.dist b/src/Symfony/Bridge/Twig/phpunit.xml.dist index e5a59c8c5edec..033362023a05c 100644 --- a/src/Symfony/Bridge/Twig/phpunit.xml.dist +++ b/src/Symfony/Bridge/Twig/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php index 51090815b9cc1..bc90fec759933 100644 --- a/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php +++ b/src/Symfony/Bundle/DebugBundle/Tests/DependencyInjection/DebugExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\DebugBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\DebugBundle\DebugBundle; use Symfony\Bundle\DebugBundle\DependencyInjection\DebugExtension; @@ -80,9 +81,7 @@ public static function provideServicesUsingDumpDestinationCreation(): array ]; } - /** - * @dataProvider provideServicesUsingDumpDestinationCreation - */ + #[DataProvider('provideServicesUsingDumpDestinationCreation')] public function testServicesUsingDumpDestinationCreation(?string $dumpDestination, string $expectedHost, ?string $expectedOutput) { $container = $this->createContainer(); diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index 31b480091abdc..07d7604aa9d7b 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -19,14 +19,14 @@ "php": ">=8.2", "ext-xml": "*", "composer-runtime-api": ">=2.1", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^7.3|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "require-dev": { - "symfony/web-profiler-bundle": "^6.4|^7.0" + "symfony/web-profiler-bundle": "^6.4|^7.0|^8.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\DebugBundle\\": "" }, diff --git a/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist b/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist index a81e38228ec4c..c3e55004d8b66 100644 --- a/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist +++ b/src/Symfony/Bundle/DebugBundle/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index ce62c9cdf836b..dec24b35d7e1c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -1,6 +1,16 @@ CHANGELOG ========= +7.4 +--- + + * Auto-register routes from attributes found on controller services + * Add `ControllerHelper`; the helpers from AbstractController as a standalone service + * Allow using their name without added suffix when using `#[Target]` for custom services + * Deprecate `Symfony\Bundle\FrameworkBundle\Console\Application::add()` in favor of `Symfony\Bundle\FrameworkBundle\Console\Application::addCommand()` + * Add `assertEmailAddressNotContains()` to the `MailerAssertionsTrait` + * Add `framework.type_info.aliases` option + 7.3 --- @@ -698,7 +708,7 @@ CHANGELOG * added Client::enableProfiler() * a new parameter has been added to the DIC: `router.request_context.base_url` You can customize it for your functional tests or for generating URLs with - the right base URL when your are in the CLI context. + the right base URL when you are in the CLI context. * added support for default templates per render tag 2.1.0 diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 0c6899328a2fc..8b4604970dca5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -36,11 +36,11 @@ protected function configure(): void { $this ->setHelp(<<<'EOT' -The %command.name% command displays information about the current Symfony project. + The %command.name% command displays information about the current Symfony project. -The PHP section displays important configuration that could affect your application. The values might -be different between web and CLI. -EOT + The PHP section displays important configuration that could affect your application. The values might + be different between web and CLI. + EOT ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 5dc8c828e743d..099204cae3068 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -23,7 +23,6 @@ use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\KernelInterface; /** @@ -58,24 +57,24 @@ protected function configure(): void ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') ->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist') ->setHelp(<<<'EOT' -The %command.name% command installs bundle assets into a given -directory (e.g. the public directory). + The %command.name% command installs bundle assets into a given + directory (e.g. the public directory). - php %command.full_name% public + php %command.full_name% public -A "bundles" directory will be created inside the target directory and the -"Resources/public" directory of each bundle will be copied into it. + A "bundles" directory will be created inside the target directory and the + "Resources/public" directory of each bundle will be copied into it. -To create a symlink to each bundle instead of copying its assets, use the ---symlink option (will fall back to hard copies when symbolic links aren't possible: + To create a symlink to each bundle instead of copying its assets, use the + --symlink option (will fall back to hard copies when symbolic links aren't possible: - php %command.full_name% public --symlink + php %command.full_name% public --symlink -To make symlink relative, add the --relative option: + To make symlink relative, add the --relative option: - php %command.full_name% public --symlink --relative + php %command.full_name% public --symlink --relative -EOT + EOT ) ; } @@ -119,7 +118,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $copyUsed = false; $exitCode = 0; $validAssetDirs = []; - /** @var BundleInterface $bundle */ foreach ($kernel->getBundles() as $bundle) { if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) { continue; @@ -239,7 +237,7 @@ private function symlink(string $originDir, string $targetDir, bool $relative = */ private function hardCopy(string $originDir, string $targetDir): string { - $this->filesystem->mkdir($targetDir, 0777); + $this->filesystem->mkdir($targetDir, 0o777); // We use a custom iterator to ignore VCS files $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php index 2f625e9e37800..01151009527d9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/BuildDebugContainerTrait.php @@ -39,7 +39,9 @@ protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilde return $this->container; } - if (!$kernel->isDebug() || !$kernel->getContainer()->getParameter('debug.container.dump') || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { + $file = $kernel->isDebug() ? $kernel->getContainer()->getParameter('debug.container.dump') : false; + + if (!$file || !(new ConfigCache($file, true))->isFresh()) { $buildContainer = \Closure::bind(function () { $this->initializeBundles(); @@ -57,13 +59,17 @@ protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilde return $containerBuilder; }, $kernel, $kernel::class); $container = $buildContainer(); - (new XmlFileLoader($container, new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); - $locatorPass = new ServiceLocatorTagPass(); - $locatorPass->process($container); - $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); - $container->getCompilerPassConfig()->setOptimizationPasses([]); - $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); + if (str_ends_with($file, '.xml') && is_file(substr_replace($file, '.ser', -4))) { + $dumpedContainer = unserialize(file_get_contents(substr_replace($file, '.ser', -4))); + $container->setDefinitions($dumpedContainer->getDefinitions()); + $container->setAliases($dumpedContainer->getAliases()); + $container->__construct($dumpedContainer->getParameterBag()); + } else { + (new XmlFileLoader($container, new FileLocator()))->load($file); + $locatorPass = new ServiceLocatorTagPass(); + $locatorPass->process($container); + } } return $this->container = $container; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 0e48ead596cca..3f3960ef8daf5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -56,12 +56,12 @@ protected function configure(): void new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), ]) ->setHelp(<<<'EOF' -The %command.name% command clears and warms up the application cache for a given environment -and debug mode: + The %command.name% command clears and warms up the application cache for a given environment + and debug mode: - php %command.full_name% --env=dev - php %command.full_name% --env=prod --no-debug -EOF + php %command.full_name% --env=dev + php %command.full_name% --env=prod --no-debug + EOF ) ; } @@ -213,7 +213,7 @@ private function isNfs(string $dir): bool if ('/' === \DIRECTORY_SEPARATOR && @is_readable('/proc/mounts') && $files = @file('/proc/mounts')) { foreach ($files as $mount) { $mount = \array_slice(explode(' ', $mount), 1, -3); - if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) { + if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'], true)) { continue; } $mounts[] = implode(' ', $mount).'/'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index 5d840e597d5d1..d4bca0d8f5382 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -51,10 +51,10 @@ protected function configure(): void ->addOption('all', null, InputOption::VALUE_NONE, 'Clear all cache pools') ->addOption('exclude', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'A list of cache pools or cache pool clearers to exclude') ->setHelp(<<<'EOF' -The %command.name% command clears the given cache pools or cache pool clearers. + The %command.name% command clears the given cache pools or cache pool clearers. - %command.full_name% [...] -EOF + %command.full_name% [...] + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php index 8fb1d1aaa701a..c3c23a391ad83 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolDeleteCommand.php @@ -47,10 +47,10 @@ protected function configure(): void new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), ]) ->setHelp(<<<'EOF' -The %command.name% deletes an item from a given cache pool. + The %command.name% deletes an item from a given cache pool. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php index 6b8e71eb0469e..6aedfb0c01428 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolListCommand.php @@ -38,8 +38,8 @@ protected function configure(): void { $this ->setHelp(<<<'EOF' -The %command.name% command lists all available cache pools. -EOF + The %command.name% command lists all available cache pools. + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php index 745a001ccc6f8..5036da8ef8510 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php @@ -39,10 +39,10 @@ protected function configure(): void { $this ->setHelp(<<<'EOF' -The %command.name% command deletes all expired items from all pruneable pools. + The %command.name% command deletes all expired items from all pruneable pools. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php index b096b080183eb..6dd01447eeeac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -44,11 +44,11 @@ protected function configure(): void new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), ]) ->setHelp(<<<'EOF' -The %command.name% command warms up the cache. + The %command.name% command warms up the cache. -Before running this command, the cache must be empty. + Before running this command, the cache must be empty. -EOF + EOF ) ; } @@ -69,9 +69,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $kernel->warmUp($cacheDir); } - $preload = $this->cacheWarmer->warmUp($cacheDir); - $buildDir = $kernel->getContainer()->getParameter('kernel.build_dir'); + + $preload = $this->cacheWarmer->warmUp($cacheDir, $buildDir); + if ($preload && $cacheDir === $buildDir && file_exists($preloadFile = $buildDir.'/'.$kernel->getContainer()->getParameter('kernel.container_class').'.preload.php')) { Preloader::append($preloadFile, $preload); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 8d5f85ceea4ca..50c8dddf56a37 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -49,23 +49,23 @@ protected function configure(): void new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), class_exists(Yaml::class) ? 'txt' : 'json'), ]) ->setHelp(<<%command.name%
command dumps the current configuration for an -extension/bundle. + The %command.name% command dumps the current configuration for an + extension/bundle. -Either the extension alias or bundle name can be used: + Either the extension alias or bundle name can be used: - php %command.full_name% framework - php %command.full_name% FrameworkBundle + php %command.full_name% framework + php %command.full_name% FrameworkBundle -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% framework --format=json + php %command.full_name% framework --format=json -For dumping a specific option, add its path as second argument: + For dumping a specific option, add its path as second argument: - php %command.full_name% framework serializer.enabled + php %command.full_name% framework serializer.enabled -EOF + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php index 3cb744d746cae..3a6d1252dae40 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php @@ -47,23 +47,23 @@ protected function configure(): void new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'yaml'), ]) ->setHelp(<<%command.name% command dumps the default configuration for an -extension/bundle. + The %command.name% command dumps the default configuration for an + extension/bundle. -Either the extension alias or bundle name can be used: + Either the extension alias or bundle name can be used: - php %command.full_name% framework - php %command.full_name% FrameworkBundle + php %command.full_name% framework + php %command.full_name% FrameworkBundle -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% FrameworkBundle --format=json + php %command.full_name% FrameworkBundle --format=json -For dumping a specific option, add its path as second argument (only available for the yaml format): + For dumping a specific option, add its path as second argument (only available for the yaml format): - php %command.full_name% framework http_client.default_options + php %command.full_name% framework http_client.default_options -EOF + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index 17c71bdca688a..f0f7d5a1b43d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -57,59 +57,59 @@ protected function configure(): void new InputOption('deprecations', null, InputOption::VALUE_NONE, 'Display deprecations generated when compiling and warming up the container'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays all configured public services: + The %command.name% command displays all configured public services: - php %command.full_name% + php %command.full_name% -To see deprecations generated during container compilation and cache warmup, use the --deprecations option: + To see deprecations generated during container compilation and cache warmup, use the --deprecations option: - php %command.full_name% --deprecations + php %command.full_name% --deprecations -To get specific information about a service, specify its name: + To get specific information about a service, specify its name: - php %command.full_name% validator + php %command.full_name% validator -To get specific information about a service including all its arguments, use the --show-arguments flag: + To get specific information about a service including all its arguments, use the --show-arguments flag: - php %command.full_name% validator --show-arguments + php %command.full_name% validator --show-arguments -To see available types that can be used for autowiring, use the --types flag: + To see available types that can be used for autowiring, use the --types flag: - php %command.full_name% --types + php %command.full_name% --types -To see environment variables used by the container, use the --env-vars flag: + To see environment variables used by the container, use the --env-vars flag: - php %command.full_name% --env-vars + php %command.full_name% --env-vars -Display a specific environment variable by specifying its name with the --env-var option: + Display a specific environment variable by specifying its name with the --env-var option: - php %command.full_name% --env-var=APP_ENV + php %command.full_name% --env-var=APP_ENV -Use the --tags option to display tagged public services grouped by tag: + Use the --tags option to display tagged public services grouped by tag: - php %command.full_name% --tags + php %command.full_name% --tags -Find all services with a specific tag by specifying the tag name with the --tag option: + Find all services with a specific tag by specifying the tag name with the --tag option: - php %command.full_name% --tag=form.type + php %command.full_name% --tag=form.type -Use the --parameters option to display all parameters: + Use the --parameters option to display all parameters: - php %command.full_name% --parameters + php %command.full_name% --parameters -Display a specific parameter by specifying its name with the --parameter option: + Display a specific parameter by specifying its name with the --parameter option: - php %command.full_name% --parameter=kernel.debug + php %command.full_name% --parameter=kernel.debug -By default, internal services are hidden. You can display them -using the --show-hidden flag: + By default, internal services are hidden. You can display them + using the --show-hidden flag: - php %command.full_name% --show-hidden + php %command.full_name% --show-hidden -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% --format=json -EOF + php %command.full_name% --format=json + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php index d71fd6810fd13..2fc0be7c53c2d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php @@ -25,7 +25,6 @@ use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Compiler\ResolveFactoryClassPass; use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass; -use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; @@ -82,9 +81,10 @@ private function getContainerBuilder(bool $resolveEnvVars): ContainerBuilder } $kernel = $this->getApplication()->getKernel(); - $kernelContainer = $kernel->getContainer(); + $container = $kernel->getContainer(); + $file = $kernel->isDebug() ? $container->getParameter('debug.container.dump') : false; - if (!$kernel->isDebug() || !$kernelContainer->getParameter('debug.container.dump') || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) { + if (!$file || !(new ConfigCache($file, true))->isFresh()) { if (!$kernel instanceof Kernel) { throw new RuntimeException(\sprintf('This command does not support the application kernel: "%s" does not extend "%s".', get_debug_type($kernel), Kernel::class)); } @@ -96,15 +96,20 @@ private function getContainerBuilder(bool $resolveEnvVars): ContainerBuilder }, $kernel, $kernel::class); $container = $buildContainer(); } else { - if (!$kernelContainer instanceof Container) { - throw new RuntimeException(\sprintf('This command does not support the application container: "%s" does not extend "%s".', get_debug_type($kernelContainer), Container::class)); + if (str_ends_with($file, '.xml') && is_file(substr_replace($file, '.ser', -4))) { + $container = unserialize(file_get_contents(substr_replace($file, '.ser', -4))); + } else { + (new XmlFileLoader($container = new ContainerBuilder(new EnvPlaceholderParameterBag()), new FileLocator()))->load($file); } - (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); + if (!$container instanceof ContainerBuilder) { + throw new RuntimeException(\sprintf('This command does not support the application container: "%s" is not a "%s".', get_debug_type($container), ContainerBuilder::class)); + } if ($resolveEnvVars) { $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveParameterPlaceHoldersPass(), new ResolveFactoryClassPass()]); } else { + $parameterBag = $container->getParameterBag(); $refl = new \ReflectionProperty($parameterBag, 'resolved'); $refl->setValue($parameterBag, true); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php index e159c5a39593d..5c1869c6a03e6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php @@ -20,7 +20,6 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; /** @@ -48,16 +47,16 @@ protected function configure(): void new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays the classes and interfaces that -you can use as type-hints for autowiring: + The %command.name% command displays the classes and interfaces that + you can use as type-hints for autowiring: - php %command.full_name% + php %command.full_name% -You can also pass a search term to filter the list: + You can also pass a search term to filter the list: - php %command.full_name% log + php %command.full_name% log -EOF + EOF ) ; } @@ -137,7 +136,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $target = substr($id, \strlen($previousId) + 3); - if ($previousId.' $'.(new Target($target))->getParsedName() === $serviceId) { + if ($container->findDefinition($id) === $container->findDefinition($serviceId)) { $serviceLine .= ' - target:'.$target.''; break; } @@ -185,7 +184,7 @@ private function getFileLink(string $class): string return ''; } - return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); + return $r->getFileName() ? ($this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()) ?: '') : ''; } public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index 3c51cb1b71103..43766ed92fbc0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -53,18 +53,18 @@ protected function configure(): void new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays all configured listeners: + The %command.name% command displays all configured listeners: - php %command.full_name% + php %command.full_name% -To get specific listeners for an event, specify its name: + To get specific listeners for an event, specify its name: - php %command.full_name% kernel.request + php %command.full_name% kernel.request -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% --format=json -EOF + php %command.full_name% --format=json + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index e543771150fc5..3daf865b3ad76 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -58,14 +58,14 @@ protected function configure(): void new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Filter by HTTP method', '', ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']), ]) ->setHelp(<<<'EOF' -The %command.name% displays the configured routes: + The %command.name% displays the configured routes: - php %command.full_name% + php %command.full_name% -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% --format=json -EOF + php %command.full_name% --format=json + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index 3f0ea3cb57f61..dee448517c48e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -53,15 +53,15 @@ protected function configure(): void new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Set the URI host'), ]) ->setHelp(<<<'EOF' -The %command.name% shows which routes match a given request and which don't and for what reason: + The %command.name% shows which routes match a given request and which don't and for what reason: - php %command.full_name% /foo + php %command.full_name% /foo -or + or - php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose + php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose -EOF + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php index 4e392b6771673..3dee294509fa4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsDecryptToLocalCommand.php @@ -40,14 +40,14 @@ protected function configure(): void $this ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force overriding of secrets that already exist in the local vault') ->setHelp(<<<'EOF' -The %command.name% command decrypts all secrets and copies them in the local vault. + The %command.name% command decrypts all secrets and copies them in the local vault. - %command.full_name% + %command.full_name% -When the --force option is provided, secrets that already exist in the local vault are overridden. + When the --force option is provided, secrets that already exist in the local vault are overridden. - %command.full_name% --force -EOF + %command.full_name% --force + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php index 9740098e5b80c..248f10966d4ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsEncryptFromLocalCommand.php @@ -38,10 +38,10 @@ protected function configure(): void { $this ->setHelp(<<<'EOF' -The %command.name% command encrypts all locally overridden secrets to the vault. + The %command.name% command encrypts all locally overridden secrets to the vault. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php index 66a752eac7e47..e0d5d9c526909 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsGenerateKeysCommand.php @@ -43,16 +43,16 @@ protected function configure(): void ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') ->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypt existing secrets with the newly generated keys.') ->setHelp(<<<'EOF' -The %command.name% command generates a new encryption key. + The %command.name% command generates a new encryption key. - %command.full_name% + %command.full_name% -If encryption keys already exist, the command must be called with -the --rotate option in order to override those keys and re-encrypt -existing secrets. + If encryption keys already exist, the command must be called with + the --rotate option in order to override those keys and re-encrypt + existing secrets. - %command.full_name% --rotate -EOF + %command.full_name% --rotate + EOF ) ; } @@ -63,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $vault = $input->getOption('local') ? $this->localVault : $this->vault; if (null === $vault) { - $io->success('The local vault is disabled.'); + $io->error('The local vault is disabled.'); return 1; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php index 920b3b1fc4006..9057f58d1ce9d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsListCommand.php @@ -43,14 +43,14 @@ protected function configure(): void $this ->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names') ->setHelp(<<<'EOF' -The %command.name% command list all stored secrets. + The %command.name% command list all stored secrets. - %command.full_name% + %command.full_name% -When the option --reveal is provided, the decrypted secrets are also displayed. + When the option --reveal is provided, the decrypted secrets are also displayed. - %command.full_name% --reveal -EOF + %command.full_name% --reveal + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php index 11660b00d778a..2c3bbb18e764b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRemoveCommand.php @@ -45,10 +45,10 @@ protected function configure(): void ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') ->setHelp(<<<'EOF' -The %command.name% command removes a secret from the vault. + The %command.name% command removes a secret from the vault. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } @@ -59,7 +59,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $vault = $input->getOption('local') ? $this->localVault : $this->vault; if (null === $vault) { - $io->success('The local vault is disabled.'); + $io->error('The local vault is disabled.'); return 1; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRevealCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRevealCommand.php index c2110ee76f683..8a678e14d8297 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRevealCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsRevealCommand.php @@ -38,10 +38,10 @@ protected function configure(): void $this ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret to reveal', null, fn () => array_keys($this->vault->list())) ->setHelp(<<<'EOF' -The %command.name% command reveals a stored secret. + The %command.name% command reveals a stored secret. - %command.full_name% -EOF + %command.full_name% + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php index f7e8eeaa6bd12..c9eabb25a8bc1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/SecretsSetCommand.php @@ -48,24 +48,24 @@ protected function configure(): void ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') ->addOption('random', 'r', InputOption::VALUE_OPTIONAL, 'Generate a random value.', false) ->setHelp(<<<'EOF' -The %command.name% command stores a secret in the vault. + The %command.name% command stores a secret in the vault. - %command.full_name% + %command.full_name% -To reference secrets in services.yaml or any other config -files, use "%env()%". + To reference secrets in services.yaml or any other config + files, use "%env()%". -By default, the secret value should be entered interactively. -Alternatively, provide a file where to read the secret from: + By default, the secret value should be entered interactively. + Alternatively, provide a file where to read the secret from: - php %command.full_name% filename + php %command.full_name% filename -Use "-" as a file name to read from STDIN: + Use "-" as a file name to read from STDIN: - cat filename | php %command.full_name% - + cat filename | php %command.full_name% - -Use --local to override secrets for local needs. -EOF + Use --local to override secrets for local needs. + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index a320130d5a6e7..b186646a3ae6d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -75,35 +75,35 @@ protected function configure(): void new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), ]) ->setHelp(<<<'EOF' -The %command.name% command helps finding unused or missing translation -messages and comparing them with the fallback ones by inspecting the -templates and translation files of a given bundle or the default translations directory. + The %command.name% command helps finding unused or missing translation + messages and comparing them with the fallback ones by inspecting the + templates and translation files of a given bundle or the default translations directory. -You can display information about bundle translations in a specific locale: + You can display information about bundle translations in a specific locale: - php %command.full_name% en AcmeDemoBundle + php %command.full_name% en AcmeDemoBundle -You can also specify a translation domain for the search: + You can also specify a translation domain for the search: - php %command.full_name% --domain=messages en AcmeDemoBundle + php %command.full_name% --domain=messages en AcmeDemoBundle -You can only display missing messages: + You can only display missing messages: - php %command.full_name% --only-missing en AcmeDemoBundle + php %command.full_name% --only-missing en AcmeDemoBundle -You can only display unused messages: + You can only display unused messages: - php %command.full_name% --only-unused en AcmeDemoBundle + php %command.full_name% --only-unused en AcmeDemoBundle -You can display information about application translations in a specific locale: + You can display information about application translations in a specific locale: - php %command.full_name% en + php %command.full_name% en -You can display information about translations in all registered bundles in a specific locale: + You can display information about translations in all registered bundles in a specific locale: - php %command.full_name% --all en + php %command.full_name% --all en -EOF + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationExtractCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationExtractCommand.php index c8e61b61a64a0..32f19fbe45e7e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationExtractCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationExtractCommand.php @@ -83,34 +83,34 @@ protected function configure(): void new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setHelp(<<<'EOF' -The %command.name% command extracts translation strings from templates -of a given bundle or the default translations directory. It can display them or merge -the new ones into the translation files. + The %command.name% command extracts translation strings from templates + of a given bundle or the default translations directory. It can display them or merge + the new ones into the translation files. -When new translation strings are found it can automatically add a prefix to the translation -message. However, if the --no-fill option is used, the --prefix -option has no effect, since the translation values are left empty. + When new translation strings are found it can automatically add a prefix to the translation + message. However, if the --no-fill option is used, the --prefix + option has no effect, since the translation values are left empty. -Example running against a Bundle (AcmeBundle) + Example running against a Bundle (AcmeBundle) - php %command.full_name% --dump-messages en AcmeBundle - php %command.full_name% --force --prefix="new_" fr AcmeBundle + php %command.full_name% --dump-messages en AcmeBundle + php %command.full_name% --force --prefix="new_" fr AcmeBundle -Example running against default messages directory + Example running against default messages directory - php %command.full_name% --dump-messages en - php %command.full_name% --force --prefix="new_" fr + php %command.full_name% --dump-messages en + php %command.full_name% --force --prefix="new_" fr -You can sort the output with the --sort flag: + You can sort the output with the --sort flag: - php %command.full_name% --dump-messages --sort=asc en AcmeBundle - php %command.full_name% --force --sort=desc fr + php %command.full_name% --dump-messages --sort=asc en AcmeBundle + php %command.full_name% --force --sort=desc fr -You can dump a tree-like structure using the yaml format with --as-tree flag: + You can dump a tree-like structure using the yaml format with --as-tree flag: - php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle + php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle -EOF + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index 201fb8be80c0d..06570e9eaee57 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -59,13 +59,13 @@ protected function configure(): void new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format ['.implode('|', self::DUMP_FORMAT_OPTIONS).']', 'dot'), ]) ->setHelp(<<<'EOF' -The %command.name% command dumps the graphical representation of a -workflow in different formats + The %command.name% command dumps the graphical representation of a + workflow in different formats -DOT: %command.full_name% | dot -Tpng > workflow.png -PUML: %command.full_name% --dump-format=puml | java -jar plantuml.jar -p > workflow.png -MERMAID: %command.full_name% --dump-format=mermaid | mmdc -o workflow.svg -EOF + DOT: %command.full_name% | dot -Tpng > workflow.png + PUML: %command.full_name% --dump-format=puml | java -jar plantuml.jar -p > workflow.png + MERMAID: %command.full_name% --dump-format=mermaid | mmdc -o workflow.svg + EOF ) ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index 5b094f165fe06..9bbe39db1b21e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -47,11 +47,11 @@ protected function configure(): void $this->setHelp($this->getHelp().<<<'EOF' -Or find all files in a bundle: + Or find all files in a bundle: - php %command.full_name% @AcmeDemoBundle + php %command.full_name% @AcmeDemoBundle -EOF + EOF ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index 14139081264fc..5948add7c6977 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -46,11 +46,11 @@ protected function configure(): void $this->setHelp($this->getHelp().<<<'EOF' -Or find all files in a bundle: + Or find all files in a bundle: - php %command.full_name% @AcmeDemoBundle + php %command.full_name% @AcmeDemoBundle -EOF + EOF ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index 274e7b06d3462..8eb3808a5f4df 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -159,11 +159,29 @@ public function getLongVersion(): string return parent::getLongVersion().\sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); } + /** + * @deprecated since Symfony 7.4, use Application::addCommand() instead + */ public function add(Command $command): ?Command + { + trigger_deprecation('symfony/framework-bundle', '7.4', 'The "%s()" method is deprecated and will be removed in Symfony 8.0, use "%s::addCommand()" instead.', __METHOD__, self::class); + + return $this->addCommand($command); + } + + public function addCommand(callable|Command $command): ?Command { $this->registerCommands(); - return parent::add($command); + if (!method_exists(BaseApplication::class, 'addCommand')) { + if (!$command instanceof Command) { + throw new \LogicException('Using callables as commands requires symfony/console 7.4 or higher.'); + } + + return parent::add($command); + } + + return parent::addCommand($command); } protected function registerCommands(): void @@ -197,7 +215,7 @@ protected function registerCommands(): void foreach ($container->getParameter('console.command.ids') as $id) { if (!isset($lazyCommandIds[$id])) { try { - $this->add($container->get($id)); + $this->addCommand($container->get($id)); } catch (\Throwable $e) { $this->registrationErrors[] = $e; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 12b3454115e2c..25f727be91a84 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -38,6 +38,18 @@ */ class TextDescriptor extends Descriptor { + private const VERB_COLORS = [ + 'ANY' => 'default', + 'GET' => 'blue', + 'QUERY' => 'blue', + 'HEAD' => 'magenta', + 'OPTIONS' => 'blue', + 'POST' => 'green', + 'PUT' => 'yellow', + 'PATCH' => 'yellow', + 'DELETE' => 'red', + ]; + public function __construct( private ?FileLinkFormatter $fileLinkFormatter = null, ) { @@ -45,40 +57,64 @@ public function __construct( protected function describeRouteCollection(RouteCollection $routes, array $options = []): void { - $showControllers = isset($options['show_controllers']) && $options['show_controllers']; - - $tableHeaders = ['Name', 'Method', 'Scheme', 'Host', 'Path']; - if ($showControllers) { - $tableHeaders[] = 'Controller'; - } - - if ($showAliases = $options['show_aliases'] ?? false) { - $tableHeaders[] = 'Aliases'; - } + $showAliases = $options['show_aliases'] ?? false; + $showControllers = $options['show_controllers'] ?? false; $tableRows = []; + $shouldShowScheme = false; + $shouldShowHost = false; foreach ($routes->all() as $name => $route) { $controller = $route->getDefault('_controller'); + $scheme = $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'; + $shouldShowScheme = $shouldShowScheme || 'ANY' !== $scheme; + + $host = '' !== $route->getHost() ? $route->getHost() : 'ANY'; + $shouldShowHost = $shouldShowHost || 'ANY' !== $host; + $row = [ - $name, - $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', - $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', - '' !== $route->getHost() ? $route->getHost() : 'ANY', - $this->formatControllerLink($controller, $route->getPath(), $options['container'] ?? null), + 'Name' => $name, + 'Methods' => $this->formatMethods($route->getMethods()), + 'Scheme' => $scheme, + 'Host' => $host, + 'Path' => $route->getPath(), ]; if ($showControllers) { - $row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller), $options['container'] ?? null) : ''; + $row['Controller'] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller), $options['container'] ?? null) : ''; } if ($showAliases) { - $row[] = implode('|', ($reverseAliases ??= $this->getReverseAliases($routes))[$name] ?? []); + $row['Aliases'] = implode('|', $this->getReverseAliases($routes)[$name] ?? []); } $tableRows[] = $row; } + $tableHeaders = ['Name', 'Method']; + + if ($shouldShowScheme) { + $tableHeaders[] = 'Scheme'; + } else { + array_walk($tableRows, function (&$row) { unset($row['Scheme']); }); + } + + if ($shouldShowHost) { + $tableHeaders[] = 'Host'; + } else { + array_walk($tableRows, function (&$row) { unset($row['Host']); }); + } + + $tableHeaders[] = 'Path'; + + if ($showControllers) { + $tableHeaders[] = 'Controller'; + } + + if ($showAliases) { + $tableHeaders[] = 'Aliases'; + } + if (isset($options['output'])) { $options['output']->table($tableHeaders, $tableRows); } else { @@ -103,7 +139,7 @@ protected function describeRoute(Route $route, array $options = []): void ['Host', '' !== $route->getHost() ? $route->getHost() : 'ANY'], ['Host Regex', '' !== $route->getHost() ? $route->compile()->getHostRegex() : ''], ['Scheme', $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'], - ['Method', $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'], + ['Method', $this->formatMethods($route->getMethods())], ['Requirements', $route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM'], ['Class', $route::class], ['Defaults', $this->formatRouterConfig($defaults)], @@ -576,6 +612,24 @@ private function formatRouterConfig(array $config): string return trim($configAsString); } + /** + * @param array $methods + */ + private function formatMethods(array $methods): string + { + if ([] === $methods) { + $methods = ['ANY']; + } + + return implode('|', array_map( + fn (string $method): string => \sprintf('%s', self::VERB_COLORS[$method] ?? 'default', $method), + $methods + )); + } + + /** + * @param (callable():ContainerBuilder)|null $getContainer + */ private function formatControllerLink(mixed $controller, string $anchorText, ?callable $getContainer = null): string { if (null === $this->fileLinkFormatter) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index 8daa61d2a2855..6a25ae3a30d31 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -288,6 +288,9 @@ private function getContainerServiceDocument(object $service, string $id, ?Conta return $dom; } + /** + * @param (callable(string):bool)|null $filter + */ private function getContainerServicesDocument(ContainerBuilder $container, ?string $tag = null, bool $showHidden = false, ?callable $filter = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index de7395d5a83f7..c44028f8c6982 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -67,18 +67,6 @@ public function setContainer(ContainerInterface $container): ?ContainerInterface return $previous; } - /** - * Gets a container parameter by its name. - */ - protected function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null - { - if (!$this->container->has('parameter_bag')) { - throw new ServiceNotFoundException('parameter_bag.', null, null, [], \sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class)); - } - - return $this->container->get('parameter_bag')->get($name); - } - public static function getSubscribedServices(): array { return [ @@ -96,6 +84,18 @@ public static function getSubscribedServices(): array ]; } + /** + * Gets a container parameter by its name. + */ + protected function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null + { + if (!$this->container->has('parameter_bag')) { + throw new ServiceNotFoundException('parameter_bag.', null, null, [], \sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class)); + } + + return $this->container->get('parameter_bag')->get($name); + } + /** * Generates a URL from the given parameters. * diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerHelper.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerHelper.php new file mode 100644 index 0000000000000..4fc56b6a91e1b --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerHelper.php @@ -0,0 +1,473 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Controller; + +use Psr\Container\ContainerInterface; +use Psr\Link\EvolvableLinkInterface; +use Psr\Link\LinkInterface; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\HttpFoundation\Session\FlashBagAwareSessionInterface; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AccessDecision; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Security\Core\Exception\AccessDeniedException; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Csrf\CsrfToken; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; +use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Component\WebLink\HttpHeaderSerializer; +use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Twig\Environment; + +/** + * Provides the helpers from AbstractControler as a standalone service. + * + * Best used together with #[AutowireMethodOf] to remove any coupling. + */ +class ControllerHelper implements ServiceSubscriberInterface +{ + public function __construct( + private ContainerInterface $container, + ) { + } + + public static function getSubscribedServices(): array + { + return [ + 'router' => '?'.RouterInterface::class, + 'request_stack' => '?'.RequestStack::class, + 'http_kernel' => '?'.HttpKernelInterface::class, + 'serializer' => '?'.SerializerInterface::class, + 'security.authorization_checker' => '?'.AuthorizationCheckerInterface::class, + 'twig' => '?'.Environment::class, + 'form.factory' => '?'.FormFactoryInterface::class, + 'security.token_storage' => '?'.TokenStorageInterface::class, + 'security.csrf.token_manager' => '?'.CsrfTokenManagerInterface::class, + 'parameter_bag' => '?'.ContainerBagInterface::class, + 'web_link.http_header_serializer' => '?'.HttpHeaderSerializer::class, + ]; + } + + /** + * Gets a container parameter by its name. + */ + public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null + { + if (!$this->container->has('parameter_bag')) { + throw new ServiceNotFoundException('parameter_bag.', null, null, [], \sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class)); + } + + return $this->container->get('parameter_bag')->get($name); + } + + /** + * Generates a URL from the given parameters. + * + * @see UrlGeneratorInterface + */ + public function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string + { + return $this->container->get('router')->generate($route, $parameters, $referenceType); + } + + /** + * Forwards the request to another controller. + * + * @param string $controller The controller name (a string like "App\Controller\PostController::index" or "App\Controller\PostController" if it is invokable) + */ + public function forward(string $controller, array $path = [], array $query = []): Response + { + $request = $this->container->get('request_stack')->getCurrentRequest(); + $path['_controller'] = $controller; + $subRequest = $request->duplicate($query, null, $path); + + return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + } + + /** + * Returns a RedirectResponse to the given URL. + * + * @param int $status The HTTP status code (302 "Found" by default) + */ + public function redirect(string $url, int $status = 302): RedirectResponse + { + return new RedirectResponse($url, $status); + } + + /** + * Returns a RedirectResponse to the given route with the given parameters. + * + * @param int $status The HTTP status code (302 "Found" by default) + */ + public function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse + { + return $this->redirect($this->generateUrl($route, $parameters), $status); + } + + /** + * Returns a JsonResponse that uses the serializer component if enabled, or json_encode. + * + * @param int $status The HTTP status code (200 "OK" by default) + */ + public function json(mixed $data, int $status = 200, array $headers = [], array $context = []): JsonResponse + { + if ($this->container->has('serializer')) { + $json = $this->container->get('serializer')->serialize($data, 'json', array_merge([ + 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS, + ], $context)); + + return new JsonResponse($json, $status, $headers, true); + } + + return new JsonResponse($data, $status, $headers); + } + + /** + * Returns a BinaryFileResponse object with original or customized file name and disposition header. + */ + public function file(\SplFileInfo|string $file, ?string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse + { + $response = new BinaryFileResponse($file); + $response->setContentDisposition($disposition, $fileName ?? $response->getFile()->getFilename()); + + return $response; + } + + /** + * Adds a flash message to the current session for type. + * + * @throws \LogicException + */ + public function addFlash(string $type, mixed $message): void + { + try { + $session = $this->container->get('request_stack')->getSession(); + } catch (SessionNotFoundException $e) { + throw new \LogicException('You cannot use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".', 0, $e); + } + + if (!$session instanceof FlashBagAwareSessionInterface) { + throw new \LogicException(\sprintf('You cannot use the addFlash method because class "%s" doesn\'t implement "%s".', get_debug_type($session), FlashBagAwareSessionInterface::class)); + } + + $session->getFlashBag()->add($type, $message); + } + + /** + * Checks if the attribute is granted against the current authentication token and optionally supplied subject. + * + * @throws \LogicException + */ + public function isGranted(mixed $attribute, mixed $subject = null): bool + { + if (!$this->container->has('security.authorization_checker')) { + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); + } + + return $this->container->get('security.authorization_checker')->isGranted($attribute, $subject); + } + + /** + * Checks if the attribute is granted against the current authentication token and optionally supplied subject. + */ + public function getAccessDecision(mixed $attribute, mixed $subject = null): AccessDecision + { + if (!$this->container->has('security.authorization_checker')) { + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); + } + + $accessDecision = new AccessDecision(); + $accessDecision->isGranted = $this->container->get('security.authorization_checker')->isGranted($attribute, $subject, $accessDecision); + + return $accessDecision; + } + + /** + * Throws an exception unless the attribute is granted against the current authentication token and optionally + * supplied subject. + * + * @throws AccessDeniedException + */ + public function denyAccessUnlessGranted(mixed $attribute, mixed $subject = null, string $message = 'Access Denied.'): void + { + if (class_exists(AccessDecision::class)) { + $accessDecision = $this->getAccessDecision($attribute, $subject); + $isGranted = $accessDecision->isGranted; + } else { + $accessDecision = null; + $isGranted = $this->isGranted($attribute, $subject); + } + + if (!$isGranted) { + $e = $this->createAccessDeniedException(3 > \func_num_args() && $accessDecision ? $accessDecision->getMessage() : $message); + $e->setAttributes([$attribute]); + $e->setSubject($subject); + + if ($accessDecision) { + $e->setAccessDecision($accessDecision); + } + + throw $e; + } + } + + /** + * Returns a rendered view. + * + * Forms found in parameters are auto-cast to form views. + */ + public function renderView(string $view, array $parameters = []): string + { + return $this->doRenderView($view, null, $parameters, __FUNCTION__); + } + + /** + * Returns a rendered block from a view. + * + * Forms found in parameters are auto-cast to form views. + */ + public function renderBlockView(string $view, string $block, array $parameters = []): string + { + return $this->doRenderView($view, $block, $parameters, __FUNCTION__); + } + + /** + * Renders a view. + * + * If an invalid form is found in the list of parameters, a 422 status code is returned. + * Forms found in parameters are auto-cast to form views. + */ + public function render(string $view, array $parameters = [], ?Response $response = null): Response + { + return $this->doRender($view, null, $parameters, $response, __FUNCTION__); + } + + /** + * Renders a block in a view. + * + * If an invalid form is found in the list of parameters, a 422 status code is returned. + * Forms found in parameters are auto-cast to form views. + */ + public function renderBlock(string $view, string $block, array $parameters = [], ?Response $response = null): Response + { + return $this->doRender($view, $block, $parameters, $response, __FUNCTION__); + } + + /** + * Streams a view. + */ + public function stream(string $view, array $parameters = [], ?StreamedResponse $response = null): StreamedResponse + { + if (!$this->container->has('twig')) { + throw new \LogicException('You cannot use the "stream" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); + } + + $twig = $this->container->get('twig'); + + $callback = function () use ($twig, $view, $parameters) { + $twig->display($view, $parameters); + }; + + if (null === $response) { + return new StreamedResponse($callback); + } + + $response->setCallback($callback); + + return $response; + } + + /** + * Returns a NotFoundHttpException. + * + * This will result in a 404 response code. Usage example: + * + * throw $this->createNotFoundException('Page not found!'); + */ + public function createNotFoundException(string $message = 'Not Found', ?\Throwable $previous = null): NotFoundHttpException + { + return new NotFoundHttpException($message, $previous); + } + + /** + * Returns an AccessDeniedException. + * + * This will result in a 403 response code. Usage example: + * + * throw $this->createAccessDeniedException('Unable to access this page!'); + * + * @throws \LogicException If the Security component is not available + */ + public function createAccessDeniedException(string $message = 'Access Denied.', ?\Throwable $previous = null): AccessDeniedException + { + if (!class_exists(AccessDeniedException::class)) { + throw new \LogicException('You cannot use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".'); + } + + return new AccessDeniedException($message, $previous); + } + + /** + * Creates and returns a Form instance from the type of the form. + */ + public function createForm(string $type, mixed $data = null, array $options = []): FormInterface + { + return $this->container->get('form.factory')->create($type, $data, $options); + } + + /** + * Creates and returns a form builder instance. + */ + public function createFormBuilder(mixed $data = null, array $options = []): FormBuilderInterface + { + return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options); + } + + /** + * Get a user from the Security Token Storage. + * + * @throws \LogicException If SecurityBundle is not available + * + * @see TokenInterface::getUser() + */ + public function getUser(): ?UserInterface + { + if (!$this->container->has('security.token_storage')) { + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); + } + + if (null === $token = $this->container->get('security.token_storage')->getToken()) { + return null; + } + + return $token->getUser(); + } + + /** + * Checks the validity of a CSRF token. + * + * @param string $id The id used when generating the token + * @param string|null $token The actual token sent with the request that should be validated + */ + public function isCsrfTokenValid(string $id, #[\SensitiveParameter] ?string $token): bool + { + if (!$this->container->has('security.csrf.token_manager')) { + throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".'); + } + + return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token)); + } + + /** + * Adds a Link HTTP header to the current response. + * + * @see https://tools.ietf.org/html/rfc5988 + */ + public function addLink(Request $request, LinkInterface $link): void + { + if (!class_exists(AddLinkHeaderListener::class)) { + throw new \LogicException('You cannot use the "addLink" method if the WebLink component is not available. Try running "composer require symfony/web-link".'); + } + + if (null === $linkProvider = $request->attributes->get('_links')) { + $request->attributes->set('_links', new GenericLinkProvider([$link])); + + return; + } + + $request->attributes->set('_links', $linkProvider->withLink($link)); + } + + /** + * @param LinkInterface[] $links + */ + public function sendEarlyHints(iterable $links = [], ?Response $response = null): Response + { + if (!$this->container->has('web_link.http_header_serializer')) { + throw new \LogicException('You cannot use the "sendEarlyHints" method if the WebLink component is not available. Try running "composer require symfony/web-link".'); + } + + $response ??= new Response(); + + $populatedLinks = []; + foreach ($links as $link) { + if ($link instanceof EvolvableLinkInterface && !$link->getRels()) { + $link = $link->withRel('preload'); + } + + $populatedLinks[] = $link; + } + + $response->headers->set('Link', $this->container->get('web_link.http_header_serializer')->serialize($populatedLinks), false); + $response->sendHeaders(103); + + return $response; + } + + private function doRenderView(string $view, ?string $block, array $parameters, string $method): string + { + if (!$this->container->has('twig')) { + throw new \LogicException(\sprintf('You cannot use the "%s" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".', $method)); + } + + foreach ($parameters as $k => $v) { + if ($v instanceof FormInterface) { + $parameters[$k] = $v->createView(); + } + } + + if (null !== $block) { + return $this->container->get('twig')->load($view)->renderBlock($block, $parameters); + } + + return $this->container->get('twig')->render($view, $parameters); + } + + private function doRender(string $view, ?string $block, array $parameters, ?Response $response, string $method): Response + { + $content = $this->doRenderView($view, $block, $parameters, $method); + $response ??= new Response(); + + if (200 === $response->getStatusCode()) { + foreach ($parameters as $v) { + if ($v instanceof FormInterface && $v->isSubmitted() && !$v->isValid()) { + $response->setStatusCode(422); + break; + } + } + } + + $response->setContent($content); + + return $response; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php index e4023e623ef45..456305bc95f49 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php @@ -13,8 +13,11 @@ use Symfony\Component\Config\ConfigCache; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\XmlDumper; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\Filesystem\Filesystem; /** * Dumps the ContainerBuilder to a cache file so that it can be used by @@ -31,9 +34,52 @@ public function process(ContainerBuilder $container): void return; } - $cache = new ConfigCache($container->getParameter('debug.container.dump'), true); - if (!$cache->isFresh()) { - $cache->write((new XmlDumper($container))->dump(), $container->getResources()); + $file = $container->getParameter('debug.container.dump'); + $cache = new ConfigCache($file, true); + if ($cache->isFresh()) { + return; + } + $cache->write((new XmlDumper($container))->dump(), $container->getResources()); + + if (!str_ends_with($file, '.xml')) { + return; + } + + $file = substr_replace($file, '.ser', -4); + + try { + $dump = new ContainerBuilder(clone $container->getParameterBag()); + $dump->setDefinitions(unserialize(serialize($container->getDefinitions()))); + $dump->setAliases($container->getAliases()); + + if (($bag = $container->getParameterBag()) instanceof EnvPlaceholderParameterBag) { + (new ResolveEnvPlaceholdersPass(null))->process($dump); + $dump->__construct(new EnvPlaceholderParameterBag($container->resolveEnvPlaceholders($this->escapeParameters($bag->all())))); + } + + $fs = new Filesystem(); + $fs->dumpFile($file, serialize($dump)); + $fs->chmod($file, 0o666, umask()); + } catch (\Throwable $e) { + $container->getCompiler()->log($this, $e->getMessage()); + // ignore serialization and file-system errors + if (file_exists($file)) { + @unlink($file); + } } } + + private function escapeParameters(array $parameters): array + { + $params = []; + foreach ($parameters as $k => $v) { + $params[$k] = match (true) { + \is_array($v) => $this->escapeParameters($v), + \is_string($v) => str_replace('%', '%%', $v), + default => $v, + }; + } + + return $params; + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index d66a5c6fff8b6..841e1831555a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1304,6 +1304,17 @@ private function addTypeInfoSection(ArrayNodeDefinition $rootNode, callable $ena ->arrayNode('type_info') ->info('Type info configuration') ->{$enableIfStandalone('symfony/type-info', Type::class)}() + ->addDefaultsIfNotSet() + ->fixXmlConfig('alias', 'aliases') + ->children() + ->arrayNode('aliases') + ->info('Additional type aliases to be used during type context creation.') + ->defaultValue([]) + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->scalarPrototype()->end() + ->end() + ->end() ->end() ->end() ; @@ -2562,7 +2573,7 @@ private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $ ->end() ->end() ->validate() - ->ifTrue(static fn ($v) => !\in_array($v['policy'], ['no_limit', 'compound']) && !isset($v['limit'])) + ->ifTrue(static fn ($v) => !\in_array($v['policy'], ['no_limit', 'compound'], true) && !isset($v['limit'])) ->thenInvalid('A limit must be provided when using a policy different than "compound" or "no_limit".') ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 0cf63bfea9fca..f256fec23c883 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -33,6 +33,7 @@ use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface; use Symfony\Bundle\FullStack; use Symfony\Bundle\MercureBundle\MercureBundle; +use Symfony\Component\Asset\Package; use Symfony\Component\Asset\PackageInterface; use Symfony\Component\AssetMapper\AssetMapper; use Symfony\Component\AssetMapper\Compiler\AssetCompilerInterface; @@ -61,7 +62,6 @@ use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; @@ -134,6 +134,8 @@ use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Middleware\DeduplicateMiddleware; use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; +use Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory; +use Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory; use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; use Symfony\Component\Messenger\Transport\TransportFactoryInterface as MessengerTransportFactoryInterface; use Symfony\Component\Messenger\Transport\TransportInterface; @@ -170,6 +172,7 @@ use Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer; use Symfony\Component\RemoteEvent\RemoteEvent; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Routing\Loader\AttributeServicesLoader; use Symfony\Component\Scheduler\Attribute\AsCronTask; use Symfony\Component\Scheduler\Attribute\AsPeriodicTask; use Symfony\Component\Scheduler\Attribute\AsSchedule; @@ -177,6 +180,7 @@ use Symfony\Component\Scheduler\Messenger\Serializer\Normalizer\SchedulerTriggerNormalizer; use Symfony\Component\Security\Core\AuthenticationEvents; use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Semaphore\PersistingStoreInterface as SemaphoreStoreInterface; use Symfony\Component\Semaphore\Semaphore; @@ -217,6 +221,7 @@ use Symfony\Component\Validator\ObjectInitializerInterface; use Symfony\Component\Validator\Validation; use Symfony\Component\Webhook\Controller\WebhookController; +use Symfony\Component\WebLink\HttpHeaderParser; use Symfony\Component\WebLink\HttpHeaderSerializer; use Symfony\Component\Workflow; use Symfony\Component\Workflow\WorkflowInterface; @@ -389,7 +394,7 @@ public function load(array $configs, ContainerBuilder $container): void } if ($this->readConfigEnabled('assets', $container, $config['assets'])) { - if (!class_exists(\Symfony\Component\Asset\Package::class)) { + if (!class_exists(Package::class)) { throw new LogicException('Asset support cannot be enabled as the Asset component is not installed. Try running "composer require symfony/asset".'); } @@ -465,7 +470,7 @@ public function load(array $configs, ContainerBuilder $container): void } if ($typeInfoEnabled = $this->readConfigEnabled('type_info', $container, $config['type_info'])) { - $this->registerTypeInfoConfiguration($container, $loader); + $this->registerTypeInfoConfiguration($config['type_info'], $container, $loader); } if ($propertyInfoEnabled) { @@ -502,6 +507,11 @@ public function load(array $configs, ContainerBuilder $container): void } $loader->load('web_link.php'); + + // Require symfony/web-link 7.4 + if (!class_exists(HttpHeaderParser::class)) { + $container->removeDefinition('web_link.http_header_parser'); + } } if ($this->readConfigEnabled('uid', $container, $config['uid'])) { @@ -589,9 +599,9 @@ public function load(array $configs, ContainerBuilder $container): void $container->removeDefinition('cache.messenger.restart_workers_signal'); if ($container->hasDefinition('messenger.transport.amqp.factory') && !class_exists(MessengerBridge\Amqp\Transport\AmqpTransportFactory::class)) { - if (class_exists(\Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory::class)) { + if (class_exists(AmqpTransportFactory::class)) { $container->getDefinition('messenger.transport.amqp.factory') - ->setClass(\Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory::class) + ->setClass(AmqpTransportFactory::class) ->addTag('messenger.transport_factory'); } else { $container->removeDefinition('messenger.transport.amqp.factory'); @@ -599,9 +609,9 @@ public function load(array $configs, ContainerBuilder $container): void } if ($container->hasDefinition('messenger.transport.redis.factory') && !class_exists(MessengerBridge\Redis\Transport\RedisTransportFactory::class)) { - if (class_exists(\Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory::class)) { + if (class_exists(RedisTransportFactory::class)) { $container->getDefinition('messenger.transport.redis.factory') - ->setClass(\Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory::class) + ->setClass(RedisTransportFactory::class) ->addTag('messenger.transport_factory'); } else { $container->removeDefinition('messenger.transport.redis.factory'); @@ -759,7 +769,7 @@ public function load(array $configs, ContainerBuilder $container): void $definition->addTag('controller.service_arguments'); }); $container->registerAttributeForAutoconfiguration(Route::class, static function (ChildDefinition $definition, Route $attribute, \ReflectionClass|\ReflectionMethod $reflection): void { - $definition->addTag('controller.service_arguments'); + $definition->addTag('controller.service_arguments')->addTag('routing.controller'); }); $container->registerAttributeForAutoconfiguration(AsRemoteEventConsumer::class, static function (ChildDefinition $definition, AsRemoteEventConsumer $attribute): void { $definition->addTag('remote_event.consumer', ['consumer' => $attribute->name]); @@ -1098,7 +1108,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $guardsConfiguration[$eventName][] = $configuration; } if ($transition['metadata']) { - $transitionsMetadataDefinition->addMethodCall('attach', [ + $transitionsMetadataDefinition->addMethodCall('offsetSet', [ new Reference($transitionId), $transition['metadata'], ]); @@ -1118,7 +1128,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $guardsConfiguration[$eventName][] = $configuration; } if ($transition['metadata']) { - $transitionsMetadataDefinition->addMethodCall('attach', [ + $transitionsMetadataDefinition->addMethodCall('offsetSet', [ new Reference($transitionId), $transition['metadata'], ]); @@ -1184,8 +1194,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ // Store to container $container->setDefinition($workflowId, $workflowDefinition); $container->setDefinition($definitionDefinitionId, $definitionDefinition); - $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name.'.'.$type); - $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name); + $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name.'.'.$type, $name); // Add workflow to Registry if ($workflow['supports']) { @@ -1299,6 +1308,10 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co $loader->load('routing.php'); + if (!class_exists(AttributeServicesLoader::class)) { + $container->removeDefinition('routing.loader.attribute.services'); + } + if ($config['utf8']) { $container->getDefinition('routing.loader')->replaceArgument(1, ['utf8' => true]); } @@ -1420,7 +1433,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co $packageDefinition = $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version) ->addTag('assets.package', ['package' => $name]); $container->setDefinition('assets._package_'.$name, $packageDefinition); - $container->registerAliasForArgument('assets._package_'.$name, PackageInterface::class, $name.'.package'); + $container->registerAliasForArgument('assets._package_'.$name, PackageInterface::class, $name.'.package', $name); } } @@ -1967,7 +1980,7 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild return; } - if (!class_exists(\Symfony\Component\Security\Csrf\CsrfToken::class)) { + if (!class_exists(CsrfToken::class)) { throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".'); } if (!$config['stateless_token_ids'] && !$this->isInitializedConfigEnabled('session')) { @@ -2049,7 +2062,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder } $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { - $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? YamlFileLoader::class : XmlFileLoader::class, [$path]); + $definition = new Definition(\in_array($extension, ['yaml', 'yml'], true) ? YamlFileLoader::class : XmlFileLoader::class, [$path]); $serializerLoaders[] = $definition; }; @@ -2162,7 +2175,7 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild } } - private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void + private function registerTypeInfoConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void { if (!class_exists(Type::class)) { throw new LogicException('TypeInfo support cannot be enabled as the TypeInfo component is not installed. Try running "composer require symfony/type-info".'); @@ -2171,7 +2184,8 @@ private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpF $loader->load('type_info.php'); if (ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/type-info'])) { - $container->register('type_info.resolver.string', StringTypeResolver::class); + $container->register('type_info.resolver.string', StringTypeResolver::class) + ->setArguments([null, null, $config['aliases']]); $container->register('type_info.resolver.reflection_parameter.phpdoc_aware', PhpDocAwareReflectionTypeResolver::class) ->setArguments([new Reference('type_info.resolver.reflection_parameter'), new Reference('type_info.resolver.string'), new Reference('type_info.type_context_factory')]); @@ -2188,6 +2202,8 @@ private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpF \ReflectionProperty::class => new Reference('type_info.resolver.reflection_property.phpdoc_aware'), \ReflectionFunctionAbstract::class => new Reference('type_info.resolver.reflection_return.phpdoc_aware'), ] + $resolversLocator->getValues()); + + $container->getDefinition('type_info.type_context_factory')->replaceArgument(1, $config['aliases']); } } @@ -2241,7 +2257,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false)); $container->setAlias(LockFactory::class, new Alias('lock.factory', false)); } else { - $container->registerAliasForArgument('lock.'.$resourceName.'.factory', LockFactory::class, $resourceName.'.lock.factory'); + $container->registerAliasForArgument('lock.'.$resourceName.'.factory', LockFactory::class, $resourceName.'.lock.factory', $resourceName); } } } @@ -2276,7 +2292,7 @@ private function registerSemaphoreConfiguration(array $config, ContainerBuilder $container->setAlias('semaphore.factory', new Alias('semaphore.'.$resourceName.'.factory', false)); $container->setAlias(SemaphoreFactory::class, new Alias('semaphore.factory', false)); } else { - $container->registerAliasForArgument('semaphore.'.$resourceName.'.factory', SemaphoreFactory::class, $resourceName.'.semaphore.factory'); + $container->registerAliasForArgument('semaphore.'.$resourceName.'.factory', SemaphoreFactory::class, $resourceName.'.semaphore.factory', $resourceName); } } } @@ -2879,6 +2895,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\Mailomat\Transport\MailomatTransportFactory::class => 'mailer.transport_factory.mailomat', MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', + MailerBridge\MicrosoftGraph\Transport\MicrosoftGraphTransportFactory::class => 'mailer.transport_factory.microsoftgraph', MailerBridge\Postal\Transport\PostalTransportFactory::class => 'mailer.transport_factory.postal', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', MailerBridge\Mailtrap\Transport\MailtrapTransportFactory::class => 'mailer.transport_factory.mailtrap', @@ -2931,7 +2948,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co $headers = new Definition(Headers::class); foreach ($config['headers'] as $name => $data) { $value = $data['value']; - if (\in_array(strtolower($name), ['from', 'to', 'cc', 'bcc', 'reply-to'])) { + if (\in_array(strtolower($name), ['from', 'to', 'cc', 'bcc', 'reply-to'], true)) { $value = (array) $value; } $headers->addMethodCall('addHeader', [$name, $value]); @@ -3301,13 +3318,11 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde $factoryAlias = $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter'); if (interface_exists(RateLimiterFactoryInterface::class)) { - $container->registerAliasForArgument($limiterId, RateLimiterFactoryInterface::class, $name.'.limiter'); - $factoryAlias->setDeprecated('symfony/framework-bundle', '7.3', \sprintf('The "%%alias_id%%" autowiring alias is deprecated and will be removed in 8.0, use "%s $%s" instead.', RateLimiterFactoryInterface::class, (new Target($name.'.limiter'))->getParsedName())); - $internalAliasId = \sprintf('.%s $%s.limiter', RateLimiterFactory::class, $name); + $container->registerAliasForArgument($limiterId, RateLimiterFactoryInterface::class, $name.'.limiter', $name); - if ($container->hasAlias($internalAliasId)) { - $container->getAlias($internalAliasId)->setDeprecated('symfony/framework-bundle', '7.3', \sprintf('The "%%alias_id%%" autowiring alias is deprecated and will be removed in 8.0, use "%s $%s" instead.', RateLimiterFactoryInterface::class, (new Target($name.'.limiter'))->getParsedName())); - } + $factoryAlias->setDeprecated('symfony/framework-bundle', '7.3', 'The "%alias_id%" autowiring alias is deprecated and will be removed in 8.0, use "RateLimiterFactoryInterface" instead.'); + $container->getAlias(\sprintf('.%s $%s.limiter', RateLimiterFactory::class, $name)) + ->setDeprecated('symfony/framework-bundle', '7.3', 'The "%alias_id%" autowiring alias is deprecated and will be removed in 8.0, use "RateLimiterFactoryInterface" instead.'); } } @@ -3332,7 +3347,7 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde ))) ; - $container->registerAliasForArgument($limiterId, RateLimiterFactoryInterface::class, $name.'.limiter'); + $container->registerAliasForArgument($limiterId, RateLimiterFactoryInterface::class, $name.'.limiter', $name); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 300fe22fb37a9..7a262f3287825 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -61,6 +61,7 @@ use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoConstructorPass; use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass; use Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass; +use Symfony\Component\Routing\DependencyInjection\RoutingControllerPass; use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass; use Symfony\Component\Runtime\SymfonyRuntime; use Symfony\Component\Scheduler\DependencyInjection\AddScheduleMessengerPass; @@ -103,8 +104,7 @@ public function boot(): void $_ENV['DOCTRINE_DEPRECATIONS'] = $_SERVER['DOCTRINE_DEPRECATIONS'] ??= 'trigger'; if (class_exists(SymfonyRuntime::class)) { - $handler = set_error_handler('var_dump'); - restore_error_handler(); + $handler = get_error_handler(); } else { $handler = [ErrorHandler::register(null, false)]; } @@ -147,6 +147,7 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new RoutingResolverPass()); + $this->addCompilerPassIfExists($container, RoutingControllerPass::class); $this->addCompilerPassIfExists($container, DataCollectorTranslatorPass::class); $container->addCompilerPass(new ProfilerPass()); // must be registered before removing private services as some might be listeners/subscribers diff --git a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php index add2508ff466f..d5b4262a45f44 100644 --- a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php +++ b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php @@ -205,25 +205,25 @@ protected function getScript(object $request): string $profilerCode = ''; if ($this->profiler) { $profilerCode = <<<'EOF' -$container = $kernel->getContainer(); -$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; -$container->get('profiler')->enable(); -EOF; + $container = $kernel->getContainer(); + $container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; + $container->get('profiler')->enable(); + EOF; } $code = <<boot(); -$profilerCode + \$kernel = unserialize($kernel); + \$kernel->boot(); + $profilerCode -\$request = unserialize($request); -EOF; + \$request = unserialize($request); + EOF; return $code.$this->getHandleScript(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php index 7ef10bb522af0..fda2f75d72888 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php @@ -45,6 +45,7 @@ use Symfony\Component\Console\Messenger\RunCommandMessageHandler; use Symfony\Component\Dotenv\Command\DebugCommand as DotenvDebugCommand; use Symfony\Component\ErrorHandler\Command\ErrorDumpCommand; +use Symfony\Component\Form\Command\DebugCommand; use Symfony\Component\Messenger\Command\ConsumeMessagesCommand; use Symfony\Component\Messenger\Command\DebugCommand as MessengerDebugCommand; use Symfony\Component\Messenger\Command\FailedMessagesRemoveCommand; @@ -327,7 +328,7 @@ ]) ->tag('console.command') - ->set('console.command.form_debug', \Symfony\Component\Form\Command\DebugCommand::class) + ->set('console.command.form_debug', DebugCommand::class) ->args([ service('form.registry'), [], // All form types namespaces are stored here by FormPass diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php index 2c79b4d55556f..e88e95166ddc4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php @@ -24,6 +24,7 @@ use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Mailtrap\Transport\MailtrapTransportFactory; +use Symfony\Component\Mailer\Bridge\MicrosoftGraph\Transport\MicrosoftGraphTransportFactory; use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; @@ -60,6 +61,7 @@ 'mailjet' => MailjetTransportFactory::class, 'mailomat' => MailomatTransportFactory::class, 'mailpace' => MailPaceTransportFactory::class, + 'microsoftgraph' => MicrosoftGraphTransportFactory::class, 'native' => NativeTransportFactory::class, 'null' => NullTransportFactory::class, 'postal' => PostalTransportFactory::class, diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php index a81c53a633461..ba734bee2489e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php @@ -39,6 +39,7 @@ param('profiler_listener.only_main_requests'), ]) ->tag('kernel.event_subscriber') + ->tag('kernel.reset', ['method' => '?reset']) ->set('console_profiler_listener', ConsoleProfilerListener::class) ->args([ diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.php index 8cdbbf33a4fe1..ad7ace2ca650f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.php @@ -26,6 +26,7 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Loader\AttributeDirectoryLoader; use Symfony\Component\Routing\Loader\AttributeFileLoader; +use Symfony\Component\Routing\Loader\AttributeServicesLoader; use Symfony\Component\Routing\Loader\ContainerLoader; use Symfony\Component\Routing\Loader\DirectoryLoader; use Symfony\Component\Routing\Loader\GlobFileLoader; @@ -98,6 +99,12 @@ ]) ->tag('routing.loader', ['priority' => -10]) + ->set('routing.loader.attribute.services', AttributeServicesLoader::class) + ->args([ + abstract_arg('classes tagged with "routing.controller"'), + ]) + ->tag('routing.loader', ['priority' => -10]) + ->set('routing.loader.attribute.directory', AttributeDirectoryLoader::class) ->args([ service('file_locator'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index a8567aa3e717e..40399c8563c40 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -382,7 +382,18 @@ - + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/type_info.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/type_info.php index 71e3646a1e041..0cf5dcbf50cc3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/type_info.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/type_info.php @@ -23,7 +23,10 @@ $container->services() // type context ->set('type_info.type_context_factory', TypeContextFactory::class) - ->args([service('type_info.resolver.string')->nullOnInvalid()]) + ->args([ + service('type_info.resolver.string')->nullOnInvalid(), + [], + ]) // type resolvers ->set('type_info.resolver', TypeResolver::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php index a4e975dac8749..29e1287156398 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\FrameworkBundle\Controller\ControllerHelper; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Bundle\FrameworkBundle\Controller\TemplateController; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; @@ -145,6 +146,12 @@ ->set('controller.cache_attribute_listener', CacheAttributeListener::class) ->tag('kernel.event_subscriber') + ->tag('kernel.reset', ['method' => '?reset']) + + ->set('controller.helper', ControllerHelper::class) + ->tag('container.service_subscriber') + + ->alias(ControllerHelper::class, 'controller.helper') ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.php index 64345cc997717..df55d194734d5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web_link.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; +use Symfony\Component\WebLink\HttpHeaderParser; use Symfony\Component\WebLink\HttpHeaderSerializer; return static function (ContainerConfigurator $container) { @@ -20,6 +21,9 @@ ->set('web_link.http_header_serializer', HttpHeaderSerializer::class) ->alias(HttpHeaderSerializer::class, 'web_link.http_header_serializer') + ->set('web_link.http_header_parser', HttpHeaderParser::class) + ->alias(HttpHeaderParser::class, 'web_link.http_header_parser') + ->set('web_link.add_link_header_listener', AddLinkHeaderListener::class) ->args([ service('web_link.http_header_serializer'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php index 9efa07fae5b73..f9e41273c56cc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php @@ -36,6 +36,9 @@ class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface { private array $collectedParameters = []; + /** + * @var \Closure(string):mixed + */ private \Closure $paramFetcher; /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php b/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php index 2a8e5dcc8b147..5abdfdc702383 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php +++ b/src/Symfony/Bundle/FrameworkBundle/Secrets/SodiumVault.php @@ -228,7 +228,7 @@ private function export(string $filename, string $data): void private function createSecretsDir(): void { - if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0777, true) && !is_dir($this->secretsDir)) { + if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0o777, true) && !is_dir($this->secretsDir)) { throw new \RuntimeException(\sprintf('Unable to create the secrets directory (%s).', $this->secretsDir)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/BrowserKitAssertionsTrait.php b/src/Symfony/Bundle/FrameworkBundle/Test/BrowserKitAssertionsTrait.php index 1b7437b778ec5..6086e75ecec4c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/BrowserKitAssertionsTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/BrowserKitAssertionsTrait.php @@ -16,6 +16,7 @@ use PHPUnit\Framework\Constraint\LogicalNot; use PHPUnit\Framework\ExpectationFailedException; use Symfony\Component\BrowserKit\AbstractBrowser; +use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\Test\Constraint as BrowserKitConstraint; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -28,24 +29,31 @@ */ trait BrowserKitAssertionsTrait { - public static function assertResponseIsSuccessful(string $message = '', bool $verbose = true): void + private static bool $defaultVerboseMode = true; + + public static function setBrowserKitAssertionsAsVerbose(bool $verbose): void { - self::assertThatForResponse(new ResponseConstraint\ResponseIsSuccessful($verbose), $message); + self::$defaultVerboseMode = $verbose; } - public static function assertResponseStatusCodeSame(int $expectedCode, string $message = '', bool $verbose = true): void + public static function assertResponseIsSuccessful(string $message = '', ?bool $verbose = null): void { - self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode, $verbose), $message); + self::assertThatForResponse(new ResponseConstraint\ResponseIsSuccessful($verbose ?? self::$defaultVerboseMode), $message); } - public static function assertResponseFormatSame(?string $expectedFormat, string $message = ''): void + public static function assertResponseStatusCodeSame(int $expectedCode, string $message = '', ?bool $verbose = null): void { - self::assertThatForResponse(new ResponseConstraint\ResponseFormatSame(self::getRequest(), $expectedFormat), $message); + self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode, $verbose ?? self::$defaultVerboseMode), $message); } - public static function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = '', bool $verbose = true): void + public static function assertResponseFormatSame(?string $expectedFormat, string $message = '', ?bool $verbose = null): void { - $constraint = new ResponseConstraint\ResponseIsRedirected($verbose); + self::assertThatForResponse(new ResponseConstraint\ResponseFormatSame(self::getRequest(), $expectedFormat, $verbose ?? self::$defaultVerboseMode), $message); + } + + public static function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = '', ?bool $verbose = null): void + { + $constraint = new ResponseConstraint\ResponseIsRedirected($verbose ?? self::$defaultVerboseMode); if ($expectedLocation) { if (class_exists(ResponseConstraint\ResponseHeaderLocationSame::class)) { $locationConstraint = new ResponseConstraint\ResponseHeaderLocationSame(self::getRequest(), $expectedLocation); @@ -100,9 +108,9 @@ public static function assertResponseCookieValueSame(string $name, string $expec ), $message); } - public static function assertResponseIsUnprocessable(string $message = '', bool $verbose = true): void + public static function assertResponseIsUnprocessable(string $message = '', ?bool $verbose = null): void { - self::assertThatForResponse(new ResponseConstraint\ResponseIsUnprocessable($verbose), $message); + self::assertThatForResponse(new ResponseConstraint\ResponseIsUnprocessable($verbose ?? self::$defaultVerboseMode), $message); } public static function assertBrowserHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void @@ -115,6 +123,38 @@ public static function assertBrowserNotHasCookie(string $name, string $path = '/ self::assertThatForClient(new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message); } + public static function assertBrowserHistoryIsOnFirstPage(string $message = ''): void + { + if (!method_exists(History::class, 'isFirstPage')) { + throw new \LogicException('The `assertBrowserHistoryIsOnFirstPage` method requires symfony/browser-kit >= 7.4.'); + } + self::assertThatForClient(new BrowserKitConstraint\BrowserHistoryIsOnFirstPage(), $message); + } + + public static function assertBrowserHistoryIsNotOnFirstPage(string $message = ''): void + { + if (!method_exists(History::class, 'isFirstPage')) { + throw new \LogicException('The `assertBrowserHistoryIsNotOnFirstPage` method requires symfony/browser-kit >= 7.4.'); + } + self::assertThatForClient(new LogicalNot(new BrowserKitConstraint\BrowserHistoryIsOnFirstPage()), $message); + } + + public static function assertBrowserHistoryIsOnLastPage(string $message = ''): void + { + if (!method_exists(History::class, 'isLastPage')) { + throw new \LogicException('The `assertBrowserHistoryIsOnLastPage` method requires symfony/browser-kit >= 7.4.'); + } + self::assertThatForClient(new BrowserKitConstraint\BrowserHistoryIsOnLastPage(), $message); + } + + public static function assertBrowserHistoryIsNotOnLastPage(string $message = ''): void + { + if (!method_exists(History::class, 'isLastPage')) { + throw new \LogicException('The `assertBrowserHistoryIsNotOnLastPage` method requires symfony/browser-kit >= 7.4.'); + } + self::assertThatForClient(new LogicalNot(new BrowserKitConstraint\BrowserHistoryIsOnLastPage()), $message); + } + public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForClient(LogicalAnd::fromConstraints( diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php b/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php index 2308c3e2fd1cd..07f4c99f5157f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/MailerAssertionsTrait.php @@ -90,6 +90,11 @@ public static function assertEmailAddressContains(RawMessage $email, string $hea self::assertThat($email, new MimeConstraint\EmailAddressContains($headerName, $expectedValue), $message); } + public static function assertEmailAddressNotContains(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void + { + self::assertThat($email, new LogicalNot(new MimeConstraint\EmailAddressContains($headerName, $expectedValue)), $message); + } + public static function assertEmailSubjectContains(RawMessage $email, string $expectedValue, string $message = ''): void { self::assertThat($email, new MimeConstraint\EmailSubjectContains($expectedValue), $message); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php index f17aad0e3dc60..5c19d2a3f530a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\Cache\Adapter\NullAdapter; @@ -38,9 +39,7 @@ private function getArrayPool(string $file): PhpArrayAdapter return $this->arrayPool = new PhpArrayAdapter($file, new NullAdapter()); } - /** - * @dataProvider loaderProvider - */ + #[DataProvider('loaderProvider')] public function testWarmUp(array $loaders) { $file = sys_get_temp_dir().'/cache-serializer.php'; @@ -57,9 +56,7 @@ public function testWarmUp(array $loaders) $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Author')->isHit()); } - /** - * @dataProvider loaderProvider - */ + #[DataProvider('loaderProvider')] public function testWarmUpAbsoluteFilePath(array $loaders) { $file = sys_get_temp_dir().'/0/cache-serializer.php'; @@ -79,9 +76,7 @@ public function testWarmUpAbsoluteFilePath(array $loaders) $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Author')->isHit()); } - /** - * @dataProvider loaderProvider - */ + #[DataProvider('loaderProvider')] public function testWarmUpWithoutBuildDir(array $loaders) { $file = sys_get_temp_dir().'/cache-serializer.php'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/AboutCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/AboutCommandTest.php index bcf3c7fe0da76..044d816e06216 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/AboutCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/AboutCommand/AboutCommandTest.php @@ -34,7 +34,7 @@ public function testAboutWithReadableFiles() $this->fs->mkdir($kernel->getProjectDir()); $this->fs->dumpFile($kernel->getCacheDir().'/readable_file', 'The file content.'); - $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0777); + $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0o777); $tester = $this->createCommandTester($kernel); $ret = $tester->execute([]); @@ -43,7 +43,7 @@ public function testAboutWithReadableFiles() $this->assertStringContainsString('Cache directory', $tester->getDisplay()); $this->assertStringContainsString('Log directory', $tester->getDisplay()); - $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0777); + $this->fs->chmod($kernel->getCacheDir().'/readable_file', 0o777); try { $this->fs->remove($kernel->getProjectDir()); @@ -62,7 +62,7 @@ public function testAboutWithUnreadableFiles() } $this->fs->dumpFile($kernel->getCacheDir().'/unreadable_file', 'The file content.'); - $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0222); + $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0o222); $tester = $this->createCommandTester($kernel); $ret = $tester->execute([]); @@ -71,7 +71,7 @@ public function testAboutWithUnreadableFiles() $this->assertStringContainsString('Cache directory', $tester->getDisplay()); $this->assertStringContainsString('Log directory', $tester->getDisplay()); - $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0777); + $this->fs->chmod($kernel->getCacheDir().'/unreadable_file', 0o777); try { $this->fs->remove($kernel->getProjectDir()); @@ -82,7 +82,7 @@ public function testAboutWithUnreadableFiles() private function createCommandTester(TestAppKernel $kernel): CommandTester { $application = new Application($kernel); - $application->add(new AboutCommand()); + $application->addCommand(new AboutCommand()); return new CommandTester($application->find('about')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php index 3a927f217874d..dcf7881346cbd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolClearCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Psr\Cache\CacheItemPoolInterface; use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand; @@ -30,13 +31,11 @@ protected function setUp(): void $this->cachePool = $this->createMock(CacheItemPoolInterface::class); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $application = new Application($this->getKernel()); - $application->add(new CachePoolClearCommand(new Psr6CacheClearer(['foo' => $this->cachePool]), ['foo'])); + $application->addCommand(new CachePoolClearCommand(new Psr6CacheClearer(['foo' => $this->cachePool]), ['foo'])); $tester = new CommandCompletionTester($application->get('cache:pool:clear')); $suggestions = $tester->complete($input); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php index 3db39e12173e6..afd3ecdd79f79 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePoolDeleteCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Psr\Cache\CacheItemPoolInterface; use Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand; @@ -84,13 +85,11 @@ public function testCommandDeleteFailed() $tester->execute(['pool' => 'foo', 'key' => 'bar']); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $application = new Application($this->getKernel()); - $application->add(new CachePoolDeleteCommand(new Psr6CacheClearer(['foo' => $this->cachePool]), ['foo'])); + $application->addCommand(new CachePoolDeleteCommand(new Psr6CacheClearer(['foo' => $this->cachePool]), ['foo'])); $tester = new CommandCompletionTester($application->get('cache:pool:delete')); $suggestions = $tester->complete($input); @@ -125,7 +124,7 @@ private function getKernel(): MockObject&KernelInterface private function getCommandTester(KernelInterface $kernel): CommandTester { $application = new Application($kernel); - $application->add(new CachePoolDeleteCommand(new Psr6CacheClearer(['foo' => $this->cachePool]))); + $application->addCommand(new CachePoolDeleteCommand(new Psr6CacheClearer(['foo' => $this->cachePool]))); return new CommandTester($application->find('cache:pool:delete')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php index a2d0ad7fef8f6..18a3622f21455 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php @@ -77,7 +77,7 @@ private function getPruneableInterfaceMock(): MockObject&PruneableInterface private function getCommandTester(KernelInterface $kernel, RewindableGenerator $generator): CommandTester { $application = new Application($kernel); - $application->add(new CachePoolPruneCommand($generator)); + $application->addCommand(new CachePoolPruneCommand($generator)); return new CommandTester($application->find('cache:pool:prune')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php index 359196e11dd28..7dc1e0dc64bfb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand; use Symfony\Component\Console\Tester\CommandCompletionTester; @@ -20,9 +21,7 @@ class EventDispatcherDebugCommandTest extends TestCase { - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $tester = $this->createCommandCompletionTester(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index b6b6771f928ab..97b1859bea321 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -46,8 +46,8 @@ public function testWithNotMatchPath() private function createCommandTester(): CommandTester { $application = new Application($this->getKernel()); - $application->add(new RouterMatchCommand($this->getRouter())); - $application->add(new RouterDebugCommand($this->getRouter())); + $application->addCommand(new RouterMatchCommand($this->getRouter())); + $application->addCommand(new RouterDebugCommand($this->getRouter())); return new CommandTester($application->find('router:match')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsDecryptToLocalCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsDecryptToLocalCommandTest.php new file mode 100644 index 0000000000000..fb5a6619406d4 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsDecryptToLocalCommandTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand; +use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Filesystem\Filesystem; + +#[RequiresPhpExtension('sodium')] +class SecretsDecryptToLocalCommandTest extends TestCase +{ + private string $mainDir; + private string $localDir; + + protected function setUp(): void + { + $this->mainDir = sys_get_temp_dir().'/sf_secrets/main/'; + $this->localDir = sys_get_temp_dir().'/sf_secrets/local/'; + + $fs = new Filesystem(); + $fs->remove([$this->mainDir, $this->localDir]); + + $mainVault = new SodiumVault($this->mainDir); + $mainVault->generateKeys(); + $mainVault->seal('FOO_SECRET', 'super_secret_value'); + + $localVault = new SodiumVault($this->localDir); + $localVault->generateKeys(); + } + + protected function tearDown(): void + { + (new Filesystem())->remove([$this->mainDir, $this->localDir]); + } + + public function testSecretsAreDecryptedAndStoredInLocalVault() + { + $mainVault = new SodiumVault($this->mainDir); + $localVault = new SodiumVault($this->localDir); + $tester = new CommandTester(new SecretsDecryptToLocalCommand($mainVault, $localVault)); + + $this->assertSame(0, $tester->execute([])); + $this->assertStringContainsString('1 secret found in the vault.', $tester->getDisplay()); + $this->assertStringContainsString('Secret "FOO_SECRET" encrypted', $tester->getDisplay()); + + $this->assertArrayHasKey('FOO_SECRET', $localVault->list(true)); + $this->assertSame('super_secret_value', $localVault->reveal('FOO_SECRET')); + } + + public function testExistingLocalSecretsAreSkippedWithoutForce() + { + $mainVault = new SodiumVault($this->mainDir); + $localVault = new SodiumVault($this->localDir); + $localVault->seal('FOO_SECRET', 'old_value'); + $tester = new CommandTester(new SecretsDecryptToLocalCommand($mainVault, $localVault)); + + $this->assertSame(0, $tester->execute([])); + $this->assertStringContainsString('1 secret is already overridden in the local vault and will be skipped.', $tester->getDisplay()); + $this->assertSame('old_value', $localVault->reveal('FOO_SECRET')); + } + + public function testForceOptionOverridesLocalSecrets() + { + $mainVault = new SodiumVault($this->mainDir); + $localVault = new SodiumVault($this->localDir); + $localVault->seal('FOO_SECRET', 'old_value'); + $tester = new CommandTester(new SecretsDecryptToLocalCommand($mainVault, $localVault)); + + $this->assertSame(0, $tester->execute(['--force' => true])); + $this->assertStringContainsString('Secret "FOO_SECRET" encrypted', $tester->getDisplay()); + $this->assertSame('super_secret_value', $localVault->reveal('FOO_SECRET')); + } + + public function testFailsGracefullyWhenLocalVaultIsDisabled() + { + $mainVault = new SodiumVault($this->mainDir); + $tester = new CommandTester(new SecretsDecryptToLocalCommand($mainVault, null)); + + $this->assertSame(1, $tester->execute([])); + $this->assertStringContainsString('The local vault is disabled.', $tester->getDisplay()); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsEncryptFromLocalCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsEncryptFromLocalCommandTest.php new file mode 100644 index 0000000000000..6e458913aba96 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsEncryptFromLocalCommandTest.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand; +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Filesystem\Filesystem; + +#[RequiresPhpExtension('sodium')] +class SecretsEncryptFromLocalCommandTest extends TestCase +{ + private string $vaultDir; + private string $localVaultDir; + private Filesystem $fs; + + protected function setUp(): void + { + $this->vaultDir = sys_get_temp_dir().'/sf_secrets/vault_'.uniqid(); + $this->localVaultDir = sys_get_temp_dir().'/sf_secrets/local_'.uniqid(); + $this->fs = new Filesystem(); + $this->fs->remove([$this->vaultDir, $this->localVaultDir]); + } + + protected function tearDown(): void + { + $this->fs->remove([$this->vaultDir, $this->localVaultDir]); + } + + public function testFailsWhenLocalVaultIsDisabled() + { + $vault = $this->createMock(AbstractVault::class); + $command = new SecretsEncryptFromLocalCommand($vault, null); + $tester = new CommandTester($command); + + $this->assertSame(1, $tester->execute([])); + $this->assertStringContainsString('The local vault is disabled.', $tester->getDisplay()); + } + + public function testEncryptsLocalOverrides() + { + $vault = new SodiumVault($this->vaultDir); + $vault->generateKeys(); + + $localVault = new SodiumVault($this->localVaultDir); + $localVault->generateKeys(); + + $vault->seal('MY_SECRET', 'prod-value'); + $localVault->seal('MY_SECRET', 'local-value'); + + $command = new SecretsEncryptFromLocalCommand($vault, $localVault); + $tester = new CommandTester($command); + + $exitCode = $tester->execute([]); + $this->assertSame(0, $exitCode); + + $revealed = $vault->reveal('MY_SECRET'); + $this->assertSame('local-value', $revealed); + } + + public function testDoesNotSealIfSameValue() + { + $vault = new SodiumVault($this->vaultDir); + $vault->generateKeys(); + + $localVault = new SodiumVault($this->localVaultDir); + $localVault->generateKeys(); + + $vault->seal('SHARED_SECRET', 'same-value'); + $localVault->seal('SHARED_SECRET', 'same-value'); + + $command = new SecretsEncryptFromLocalCommand($vault, $localVault); + $tester = new CommandTester($command); + + $exitCode = $tester->execute([]); + $this->assertSame(0, $exitCode); + + $revealed = $vault->reveal('SHARED_SECRET'); + $this->assertSame('same-value', $revealed); + } + + public function testFailsIfLocalSecretIsMissing() + { + $vault = new SodiumVault($this->vaultDir); + $vault->generateKeys(); + + $localVault = new SodiumVault($this->localVaultDir); + $localVault->generateKeys(); + + $vault->seal('MISSING_IN_LOCAL', 'prod-only'); + + $command = new SecretsEncryptFromLocalCommand($vault, $localVault); + $tester = new CommandTester($command); + + $this->assertSame(1, $tester->execute([])); + $this->assertStringContainsString('Secret "MISSING_IN_LOCAL" not found', $tester->getDisplay()); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsGenerateKeysCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsGenerateKeysCommandTest.php new file mode 100644 index 0000000000000..2940fcfc38803 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsGenerateKeysCommandTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand; +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Filesystem\Filesystem; + +#[RequiresPhpExtension('sodium')] +class SecretsGenerateKeysCommandTest extends TestCase +{ + private string $secretsDir; + private const ENC_KEY_FILE = 'test.encrypt.public.php'; + private const DEC_KEY_FILE = 'test.decrypt.private.php'; + + protected function setUp(): void + { + $this->secretsDir = sys_get_temp_dir().'/sf_secrets/test/'; + (new Filesystem())->remove($this->secretsDir); + } + + protected function tearDown(): void + { + (new Filesystem())->remove($this->secretsDir); + } + + public function testItGeneratesSodiumKeys() + { + $vault = new SodiumVault($this->secretsDir); + $tester = new CommandTester(new SecretsGenerateKeysCommand($vault)); + + $this->assertSame(0, $tester->execute([])); + $this->assertKeysExistAndReadable(); + } + + public function testItRotatesSodiumKeysWhenRequested() + { + $vault = new SodiumVault($this->secretsDir); + $tester = new CommandTester(new SecretsGenerateKeysCommand($vault)); + + $this->assertSame(0, $tester->execute(['--rotate' => true])); + $this->assertKeysExistAndReadable(); + } + + public function testItFailsGracefullyWhenLocalVaultIsDisabled() + { + $vault = $this->createMock(AbstractVault::class); + $tester = new CommandTester(new SecretsGenerateKeysCommand($vault)); + + $this->assertSame(1, $tester->execute(['--local' => true])); + $this->assertStringContainsString('The local vault is disabled.', $tester->getDisplay()); + } + + public function testFailsWhenKeysAlreadyExistAndRotateNotPassed() + { + $vault = new SodiumVault($this->secretsDir); + $vault->generateKeys(); + + $command = new SecretsGenerateKeysCommand($vault); + $tester = new CommandTester($command); + + $this->assertSame(1, $tester->execute([])); + $this->assertStringContainsString('Sodium keys already exist at', $tester->getDisplay()); + } + + private function assertKeysExistAndReadable(): void + { + $encPath = $this->secretsDir.'/'.self::ENC_KEY_FILE; + $decPath = $this->secretsDir.'/'.self::DEC_KEY_FILE; + + $this->assertFileExists($encPath, 'Encryption key file does not exist.'); + $this->assertFileExists($decPath, 'Decryption key file does not exist.'); + $this->assertNotFalse(@file_get_contents($encPath), 'Encryption key file is not readable.'); + $this->assertNotFalse(@file_get_contents($decPath), 'Decryption key file is not readable.'); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsListCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsListCommandTest.php index 12d3ab2e8ac28..de09d8941b240 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsListCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsListCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\BackupGlobals; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand; use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; @@ -19,9 +20,7 @@ class SecretsListCommandTest extends TestCase { - /** - * @backupGlobals enabled - */ + #[BackupGlobals(true)] public function testExecute() { $vault = $this->createMock(AbstractVault::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php index 2c12b6128d9f5..d09fa3c019cdc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRemoveCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand; use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; @@ -18,9 +19,7 @@ class SecretsRemoveCommandTest extends TestCase { - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(bool $withLocalVault, array $input, array $expectedSuggestions) { $vault = $this->createMock(AbstractVault::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRevealCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRevealCommandTest.php index d77d303d5c88b..37065d1c0a973 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRevealCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsRevealCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\BackupGlobals; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\SecretsRevealCommand; use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; @@ -59,9 +60,7 @@ public function testFailedDecrypt() $this->assertStringContainsString('The secret "secretKey" could not be decrypted.', trim($tester->getDisplay(true))); } - /** - * @backupGlobals enabled - */ + #[BackupGlobals(true)] public function testLocalVaultOverride() { $vault = $this->createMock(AbstractVault::class); @@ -78,9 +77,7 @@ public function testLocalVaultOverride() $this->assertEquals('newSecretValue', trim($tester->getDisplay(true))); } - /** - * @backupGlobals enabled - */ + #[BackupGlobals(true)] public function testOnlyLocalVaultContainsName() { $vault = $this->createMock(AbstractVault::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php index 678fb417c53cf..57db9c529cec6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/SecretsSetCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand; use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; @@ -18,9 +19,7 @@ class SecretsSetCommandTest extends TestCase { - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $vault = $this->createMock(AbstractVault::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index c6c91a8574298..e0e49fd2ede0c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; @@ -223,7 +224,7 @@ function ($path, $catalogue) use ($loadedMessages) { $command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $codePaths, $enabledLocales); $application = new Application($kernel); - $application->add($command); + $application->addCommand($command); return $application->find('debug:translation'); } @@ -240,9 +241,7 @@ private function getBundle($path) return $bundle; } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $extractedMessagesWithDomains = [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandCompletionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandCompletionTest.php index 6d2f22d96a183..49874fe7c3d3f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandCompletionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandCompletionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\TranslationExtractCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; @@ -30,9 +31,7 @@ class TranslationExtractCommandCompletionTest extends TestCase private Filesystem $fs; private string $translationDir; - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $tester = $this->createCommandCompletionTester(['messages' => ['foo' => 'foo']]); @@ -132,7 +131,7 @@ function ($path, $catalogue) use ($loadedMessages) { $command = new TranslationExtractCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $codePaths, ['en', 'fr']); $application = new Application($kernel); - $application->add($command); + $application->addCommand($command); return new CommandCompletionTester($application->find('translation:extract')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandTest.php index c5e78de12a3f6..276af4476e12c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationExtractCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\TranslationExtractCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; @@ -154,12 +155,12 @@ public function testFilterDuplicateTransPaths() if (preg_match('/\.[a-z]+$/', $transPath)) { if (!realpath(\dirname($transPath))) { - mkdir(\dirname($transPath), 0777, true); + mkdir(\dirname($transPath), 0o777, true); } touch($transPath); } else { - mkdir($transPath, 0777, true); + mkdir($transPath, 0o777, true); } } @@ -177,9 +178,7 @@ public function testFilterDuplicateTransPaths() $this->assertEquals($expectedPaths, $filteredTransPaths); } - /** - * @dataProvider removeNoFillProvider - */ + #[DataProvider('removeNoFillProvider')] public function testRemoveNoFillTranslationsMethod($noFillCounter, $messages) { // Preparing mock @@ -304,7 +303,7 @@ function (MessageCatalogue $catalogue) use ($writerMessages) { $command = new TranslationExtractCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $codePaths); $application = new Application($kernel); - $application->add($command); + $application->addCommand($command); return new CommandTester($application->find('translation:extract')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php index 284e97623ad15..d7d17a9235564 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/WorkflowDumpCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; use Symfony\Component\Console\Application; @@ -19,13 +20,16 @@ class WorkflowDumpCommandTest extends TestCase { - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $application = new Application(); - $application->add(new WorkflowDumpCommand(new ServiceLocator([]))); + $command = new WorkflowDumpCommand(new ServiceLocator([])); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } $tester = new CommandCompletionTester($application->find('workflow:dump')); $suggestions = $tester->complete($input, 2); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/XliffLintCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/XliffLintCommandTest.php index d5495ada92e00..f10834c5b0a02 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/XliffLintCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/XliffLintCommandTest.php @@ -35,10 +35,10 @@ public function testGetHelp() { $command = new XliffLintCommand(); $expected = <<php %command.full_name% @AcmeDemoBundle -EOF; + php %command.full_name% @AcmeDemoBundle + EOF; $this->assertStringContainsString($expected, $command->getHelp()); } @@ -59,7 +59,12 @@ private function createCommandTester($application = null): CommandTester { if (!$application) { $application = new BaseApplication(); - $application->add(new XliffLintCommand()); + $command = new XliffLintCommand(); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } } $command = $application->find('lint:xliff'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php index ec2093119511c..28c55a5bad0d6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/YamlLintCommandTest.php @@ -73,10 +73,10 @@ public function testGetHelp() { $command = new YamlLintCommand(); $expected = <<php %command.full_name% @AcmeDemoBundle -EOF; + php %command.full_name% @AcmeDemoBundle + EOF; $this->assertStringContainsString($expected, $command->getHelp()); } @@ -107,7 +107,12 @@ private function createCommandTester($application = null): CommandTester { if (!$application) { $application = new BaseApplication(); - $application->add(new YamlLintCommand()); + $command = new YamlLintCommand(); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } } $command = $application->find('lint:yaml'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index 0b92a813c2d27..7f712107c22b8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -119,7 +119,7 @@ public function testBundleCommandCanOverriddeAPreExistingCommandWithTheSameName( $application = new Application($kernel); $newCommand = new Command('example'); - $application->add($newCommand); + $application->addCommand($newCommand); $this->assertSame($newCommand, $application->get('example')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTestCase.php index eb18fbcc75b79..a6cbd308505cc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTestCase.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\FooUnitEnum; use Symfony\Component\Console\Input\ArrayInput; @@ -39,8 +42,8 @@ protected function tearDown(): void putenv($this->colSize ? 'COLUMNS='.$this->colSize : 'COLUMNS'); } - /** @dataProvider getDescribeRouteCollectionTestData */ - public function testDescribeRouteCollection(RouteCollection $routes, $expectedDescription) + #[DataProvider('getDescribeRouteCollectionTestData')] + public function testDescribeRouteCollection(RouteCollection $routes, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $routes); } @@ -50,8 +53,8 @@ public static function getDescribeRouteCollectionTestData(): array return static::getDescriptionTestData(ObjectsProvider::getRouteCollections()); } - /** @dataProvider getDescribeRouteCollectionWithHttpMethodFilterTestData */ - public function testDescribeRouteCollectionWithHttpMethodFilter(string $httpMethod, RouteCollection $routes, $expectedDescription) + #[DataProvider('getDescribeRouteCollectionWithHttpMethodFilterTestData')] + public function testDescribeRouteCollectionWithHttpMethodFilter(string $httpMethod, RouteCollection $routes, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $routes, ['method' => $httpMethod]); } @@ -65,8 +68,8 @@ public static function getDescribeRouteCollectionWithHttpMethodFilterTestData(): } } - /** @dataProvider getDescribeRouteTestData */ - public function testDescribeRoute(Route $route, $expectedDescription) + #[DataProvider('getDescribeRouteTestData')] + public function testDescribeRoute(Route $route, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $route); } @@ -76,8 +79,8 @@ public static function getDescribeRouteTestData(): array return static::getDescriptionTestData(ObjectsProvider::getRoutes()); } - /** @dataProvider getDescribeContainerParametersTestData */ - public function testDescribeContainerParameters(ParameterBag $parameters, $expectedDescription) + #[DataProvider('getDescribeContainerParametersTestData')] + public function testDescribeContainerParameters(ParameterBag $parameters, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $parameters); } @@ -87,8 +90,8 @@ public static function getDescribeContainerParametersTestData(): array return static::getDescriptionTestData(ObjectsProvider::getContainerParameters()); } - /** @dataProvider getDescribeContainerBuilderTestData */ - public function testDescribeContainerBuilder(ContainerBuilder $builder, $expectedDescription, array $options) + #[DataProvider('getDescribeContainerBuilderTestData')] + public function testDescribeContainerBuilder(ContainerBuilder $builder, $expectedDescription, array $options, $file) { $this->assertDescription($expectedDescription, $builder, $options); } @@ -98,10 +101,8 @@ public static function getDescribeContainerBuilderTestData(): array return static::getContainerBuilderDescriptionTestData(ObjectsProvider::getContainerBuilders()); } - /** - * @dataProvider getDescribeContainerExistingClassDefinitionTestData - */ - public function testDescribeContainerExistingClassDefinition(Definition $definition, $expectedDescription) + #[DataProvider('getDescribeContainerExistingClassDefinitionTestData')] + public function testDescribeContainerExistingClassDefinition(Definition $definition, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $definition); } @@ -111,8 +112,8 @@ public static function getDescribeContainerExistingClassDefinitionTestData(): ar return static::getDescriptionTestData(ObjectsProvider::getContainerDefinitionsWithExistingClasses()); } - /** @dataProvider getDescribeContainerDefinitionTestData */ - public function testDescribeContainerDefinition(Definition $definition, $expectedDescription) + #[DataProvider('getDescribeContainerDefinitionTestData')] + public function testDescribeContainerDefinition(Definition $definition, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $definition); } @@ -122,8 +123,8 @@ public static function getDescribeContainerDefinitionTestData(): array return static::getDescriptionTestData(ObjectsProvider::getContainerDefinitions()); } - /** @dataProvider getDescribeContainerDefinitionWithArgumentsShownTestData */ - public function testDescribeContainerDefinitionWithArgumentsShown(Definition $definition, $expectedDescription) + #[DataProvider('getDescribeContainerDefinitionWithArgumentsShownTestData')] + public function testDescribeContainerDefinitionWithArgumentsShown(Definition $definition, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $definition, []); } @@ -142,8 +143,8 @@ public static function getDescribeContainerDefinitionWithArgumentsShownTestData( return static::getDescriptionTestData($definitionsWithArgs); } - /** @dataProvider getDescribeContainerAliasTestData */ - public function testDescribeContainerAlias(Alias $alias, $expectedDescription) + #[DataProvider('getDescribeContainerAliasTestData')] + public function testDescribeContainerAlias(Alias $alias, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $alias); } @@ -153,8 +154,8 @@ public static function getDescribeContainerAliasTestData(): array return static::getDescriptionTestData(ObjectsProvider::getContainerAliases()); } - /** @dataProvider getDescribeContainerDefinitionWhichIsAnAliasTestData */ - public function testDescribeContainerDefinitionWhichIsAnAlias(Alias $alias, $expectedDescription, ContainerBuilder $builder, $options = []) + #[DataProvider('getDescribeContainerDefinitionWhichIsAnAliasTestData')] + public function testDescribeContainerDefinitionWhichIsAnAlias(Alias $alias, $expectedDescription, ContainerBuilder $builder, $options = [], $file = null) { $this->assertDescription($expectedDescription, $builder, $options); } @@ -185,13 +186,12 @@ public static function getDescribeContainerDefinitionWhichIsAnAliasTestData(): a } /** - * The legacy group must be kept as deprecations will always be raised. - * - * @group legacy - * - * @dataProvider getDescribeContainerParameterTestData + * The #[IgnoreDeprecation] attribute must be kept as deprecations will always be raised. */ - public function testDescribeContainerParameter($parameter, $expectedDescription, array $options) + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getDescribeContainerParameterTestData')] + public function testDescribeContainerParameter($parameter, $expectedDescription, array $options, $file) { $this->assertDescription($expectedDescription, $parameter, $options); } @@ -213,8 +213,8 @@ public static function getDescribeContainerParameterTestData(): array return $data; } - /** @dataProvider getDescribeEventDispatcherTestData */ - public function testDescribeEventDispatcher(EventDispatcher $eventDispatcher, $expectedDescription, array $options) + #[DataProvider('getDescribeEventDispatcherTestData')] + public function testDescribeEventDispatcher(EventDispatcher $eventDispatcher, $expectedDescription, array $options, $file) { $this->assertDescription($expectedDescription, $eventDispatcher, $options); } @@ -224,8 +224,8 @@ public static function getDescribeEventDispatcherTestData(): array return static::getEventDispatcherDescriptionTestData(ObjectsProvider::getEventDispatchers()); } - /** @dataProvider getDescribeCallableTestData */ - public function testDescribeCallable($callable, $expectedDescription) + #[DataProvider('getDescribeCallableTestData')] + public function testDescribeCallable($callable, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $callable); } @@ -235,12 +235,10 @@ public static function getDescribeCallableTestData(): array return static::getDescriptionTestData(ObjectsProvider::getCallables()); } - /** - * @group legacy - * - * @dataProvider getDescribeDeprecatedCallableTestData - */ - public function testDescribeDeprecatedCallable($callable, $expectedDescription) + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getDescribeDeprecatedCallableTestData')] + public function testDescribeDeprecatedCallable($callable, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $callable); } @@ -250,7 +248,7 @@ public static function getDescribeDeprecatedCallableTestData(): array return static::getDescriptionTestData(ObjectsProvider::getDeprecatedCallables()); } - /** @dataProvider getClassDescriptionTestData */ + #[DataProvider('getClassDescriptionTestData')] public function testGetClassDescription($object, $expectedDescription) { $this->assertEquals($expectedDescription, $this->getDescriptor()->getClassDescription($object)); @@ -266,10 +264,8 @@ public static function getClassDescriptionTestData(): array ]; } - /** - * @dataProvider getDeprecationsTestData - */ - public function testGetDeprecations(ContainerBuilder $builder, $expectedDescription) + #[DataProvider('getDeprecationsTestData')] + public function testGetDeprecations(ContainerBuilder $builder, $expectedDescription, $file) { $this->assertDescription($expectedDescription, $builder, ['deprecations' => true]); } @@ -357,7 +353,7 @@ private static function getEventDispatcherDescriptionTestData(array $objects): a return $data; } - /** @dataProvider getDescribeContainerBuilderWithPriorityTagsTestData */ + #[DataProvider('getDescribeContainerBuilderWithPriorityTagsTestData')] public function testDescribeContainerBuilderWithPriorityTags(ContainerBuilder $builder, $expectedDescription, array $options) { $this->assertDescription($expectedDescription, $builder, $options); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index 8eb1c438601c2..07c66e9c87523 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -34,7 +34,32 @@ public static function getRouteCollections() $collection1->add($name, $route); } - return ['route_collection_1' => $collection1]; + $routesWithGenericHost = new RouteCollection(); + $routesWithGenericHost->add('some_route', new RouteStub( + '/some-route', + ['_controller' => 'Controller'], + [], + [], + null, + ['https'], + )); + + $routesWithGenericScheme = new RouteCollection(); + $routesWithGenericScheme->add('some_route_with_host', new RouteStub( + '/some-route', + ['_controller' => 'strpos'], + [], + [], + 'symfony.com', + [], + )); + + return [ + 'empty_route_collection' => new RouteCollection(), + 'route_collection_1' => $collection1, + 'route_with_generic_host' => $routesWithGenericHost, + 'route_with_generic_scheme' => $routesWithGenericScheme, + ]; } public static function getRouteCollectionsByHttpMethod(): array diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php index 34e16f5e42eff..101ac68a0e0df 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/TextDescriptorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor; use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; use Symfony\Component\Routing\Route; @@ -45,11 +46,11 @@ public static function getDescribeRouteWithControllerLinkTestData() return $getDescribeData; } - /** @dataProvider getDescribeRouteWithControllerLinkTestData */ - public function testDescribeRouteWithControllerLink(Route $route, $expectedDescription) + #[DataProvider('getDescribeRouteWithControllerLinkTestData')] + public function testDescribeRouteWithControllerLink(Route $route, $expectedDescription, $file) { static::$fileLinkFormatter = new FileLinkFormatter('myeditor://open?file=%f&line=%l'); - parent::testDescribeRoute($route, str_replace('[:file:]', __FILE__, $expectedDescription)); + parent::testDescribeRoute($route, str_replace('[:file:]', __FILE__, $expectedDescription), $file); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index 2024cb8f77082..f778aa4be00ae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Controller; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\DependencyInjection\Container; @@ -101,7 +103,7 @@ public function testMissingParameterBag() $controller->setContainer($container); $this->expectException(ServiceNotFoundException::class); - $this->expectExceptionMessage('TestAbstractController::getParameter()" method is missing a parameter bag'); + $this->expectExceptionMessage('::getParameter()" method is missing a parameter bag'); $controller->getParameter('foo'); } @@ -389,9 +391,7 @@ public function testdenyAccessUnlessGranted() } } - /** - * @dataProvider provideDenyAccessUnlessGrantedSetsAttributesAsArray - */ + #[DataProvider('provideDenyAccessUnlessGrantedSetsAttributesAsArray')] public function testdenyAccessUnlessGrantedSetsAttributesAsArray($attribute, $exceptionAttributes) { $authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); @@ -526,9 +526,7 @@ public function testRedirectToRoute() $this->assertSame(302, $response->getStatusCode()); } - /** - * @runInSeparateProcess - */ + #[RunInSeparateProcess] public function testAddFlash() { $flashBag = new FlashBag(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerHelperTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerHelperTest.php new file mode 100644 index 0000000000000..cb35c4757c99c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerHelperTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Controller; + +use Psr\Container\ContainerInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\FrameworkBundle\Controller\ControllerHelper; + +class ControllerHelperTest extends AbstractControllerTest +{ + protected function createController() + { + return new class extends ControllerHelper { + public function __construct() + { + } + + public function setContainer(ContainerInterface $container) + { + parent::__construct($container); + } + }; + } + + public function testSync() + { + $r = new \ReflectionClass(ControllerHelper::class); + $m = $r->getMethod('getSubscribedServices'); + $helperSrc = file($r->getFileName()); + $helperSrc = implode('', \array_slice($helperSrc, $m->getStartLine() - 1, $r->getEndLine() - $m->getStartLine())); + + $r = new \ReflectionClass(AbstractController::class); + $m = $r->getMethod('getSubscribedServices'); + $abstractSrc = file($r->getFileName()); + $code = [ + implode('', \array_slice($abstractSrc, $m->getStartLine() - 1, $m->getEndLine() - $m->getStartLine() + 1)), + ]; + + foreach ($r->getMethods(\ReflectionMethod::IS_PROTECTED) as $m) { + if ($m->getDocComment()) { + $code[] = ' '.$m->getDocComment(); + } + $code[] = substr_replace(implode('', \array_slice($abstractSrc, $m->getStartLine() - 1, $m->getEndLine() - $m->getStartLine() + 1)), 'public', 4, 9); + } + foreach ($r->getMethods(\ReflectionMethod::IS_PRIVATE) as $m) { + if ($m->getDocComment()) { + $code[] = ' '.$m->getDocComment(); + } + $code[] = implode('', \array_slice($abstractSrc, $m->getStartLine() - 1, $m->getEndLine() - $m->getStartLine() + 1)); + } + $code = implode("\n", $code); + + $this->assertSame($code, $helperSrc, 'Methods from AbstractController are not properly synced in ControllerHelper'); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php index 7c7398fd32331..ce14ca559f13e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -11,15 +11,15 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Controller; +use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface as Psr11ContainerInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest; -class ControllerResolverTest extends ContainerControllerResolverTest +class ControllerResolverTest extends TestCase { public function testAbstractControllerGetsContainerWhenNotSet() { @@ -111,11 +111,6 @@ protected function createControllerResolver(?LoggerInterface $logger = null, ?Ps return new ControllerResolver($container, $logger); } - - protected function createMockParser() - { - return $this->createMock(ControllerNameParser::class); - } } class DummyController extends AbstractController diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php index 161424e0e43ee..55f3b33c300fb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Controller; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\HttpFoundation\ParameterBag; @@ -60,9 +61,7 @@ public function testEmptyRoute() } } - /** - * @dataProvider provider - */ + #[DataProvider('provider')] public function testRoute($permanent, $keepRequestMethod, $keepQueryParams, $ignoreAttributes, $expectedCode, $expectedAttributes) { $request = new Request(); @@ -255,9 +254,7 @@ public static function urlRedirectProvider(): array ]; } - /** - * @dataProvider urlRedirectProvider - */ + #[DataProvider('urlRedirectProvider')] public function testUrlRedirect($scheme, $httpPort, $httpsPort, $requestScheme, $requestPort, $expectedPort) { $host = 'www.example.com'; @@ -287,9 +284,7 @@ public static function pathQueryParamsProvider(): array ]; } - /** - * @dataProvider pathQueryParamsProvider - */ + #[DataProvider('pathQueryParamsProvider')] public function testPathQueryParams($expectedUrl, $path, $queryString) { $scheme = 'http'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php index 5a2215009dc44..12dfc085dea42 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector; use Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface; @@ -98,9 +99,7 @@ public static function getTemplate(): string }]; } - /** - * @dataProvider provideValidCollectorWithTemplateUsingAutoconfigure - */ + #[DataProvider('provideValidCollectorWithTemplateUsingAutoconfigure')] public function testValidCollectorWithTemplateUsingAutoconfigure(TemplateAwareDataCollectorInterface $dataCollector) { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php index fc69d5bd16858..3a6824e4fc92b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php @@ -33,44 +33,44 @@ public function testProcess() $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32); $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING); - $container->register('Test\public_service') + $container->register('test.public_service', 'stdClass') ->setPublic(true) - ->addArgument(new Reference('Test\private_used_shared_service')) - ->addArgument(new Reference('Test\private_used_non_shared_service')) - ->addArgument(new Reference('Test\soon_private_service')) + ->addArgument(new Reference('test.private_used_shared_service')) + ->addArgument(new Reference('test.private_used_non_shared_service')) + ->addArgument(new Reference('test.soon_private_service')) ; - $container->register('Test\soon_private_service') + $container->register('test.soon_private_service', 'stdClass') ->setPublic(true) ->addTag('container.private', ['package' => 'foo/bar', 'version' => '1.42']) ; - $container->register('Test\soon_private_service_decorated') + $container->register('test.soon_private_service_decorated', 'stdClass') ->setPublic(true) ->addTag('container.private', ['package' => 'foo/bar', 'version' => '1.42']) ; - $container->register('Test\soon_private_service_decorator') - ->setDecoratedService('Test\soon_private_service_decorated') - ->setArguments(['Test\soon_private_service_decorator.inner']); + $container->register('test.soon_private_service_decorator', 'stdClass') + ->setDecoratedService('test.soon_private_service_decorated') + ->setArguments(['test.soon_private_service_decorator.inner']); - $container->register('Test\private_used_shared_service'); - $container->register('Test\private_unused_shared_service'); - $container->register('Test\private_used_non_shared_service')->setShared(false); - $container->register('Test\private_unused_non_shared_service')->setShared(false); + $container->register('test.private_used_shared_service', 'stdClass'); + $container->register('test.private_unused_shared_service', 'stdClass'); + $container->register('test.private_used_non_shared_service', 'stdClass')->setShared(false); + $container->register('test.private_unused_non_shared_service', 'stdClass')->setShared(false); $container->compile(); $expected = [ - 'Test\private_used_shared_service' => new ServiceClosureArgument(new Reference('Test\private_used_shared_service')), - 'Test\private_used_non_shared_service' => new ServiceClosureArgument(new Reference('Test\private_used_non_shared_service')), - 'Test\soon_private_service' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service')), - 'Test\soon_private_service_decorator' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service_decorated')), - 'Test\soon_private_service_decorated' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service_decorated')), + 'test.private_used_shared_service' => new ServiceClosureArgument(new Reference('test.private_used_shared_service')), + 'test.private_used_non_shared_service' => new ServiceClosureArgument(new Reference('test.private_used_non_shared_service')), + 'test.soon_private_service' => new ServiceClosureArgument(new Reference('.container.private.test.soon_private_service')), + 'test.soon_private_service_decorator' => new ServiceClosureArgument(new Reference('.container.private.test.soon_private_service_decorated')), + 'test.soon_private_service_decorated' => new ServiceClosureArgument(new Reference('.container.private.test.soon_private_service_decorated')), ]; $privateServices = $container->getDefinition('test.private_services_locator')->getArgument(0); unset($privateServices[\Symfony\Component\DependencyInjection\ContainerInterface::class], $privateServices[ContainerInterface::class]); $this->assertEquals($expected, $privateServices); - $this->assertFalse($container->getDefinition('Test\private_used_non_shared_service')->isShared()); + $this->assertFalse($container->getDefinition('test.private_used_non_shared_service')->isShared()); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index c8142e98ab1a7..19d563f5234b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection; use Doctrine\DBAL\Connection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration; use Symfony\Bundle\FullStack; @@ -61,9 +62,7 @@ public function getTestValidSessionName() ]; } - /** - * @dataProvider getTestInvalidSessionName - */ + #[DataProvider('getTestInvalidSessionName')] public function testInvalidSessionName($sessionName) { $processor = new Processor(); @@ -153,9 +152,7 @@ public function testAssetMapperCanBeEnabled() $this->assertEquals($defaultConfig, $config['asset_mapper']); } - /** - * @dataProvider provideImportmapPolyfillTests - */ + #[DataProvider('provideImportmapPolyfillTests')] public function testAssetMapperPolyfillValue(mixed $polyfillValue, bool $isValid, mixed $expected) { $processor = new Processor(); @@ -189,9 +186,7 @@ public static function provideImportmapPolyfillTests() yield [false, true, false]; } - /** - * @dataProvider provideValidAssetsPackageNameConfigurationTests - */ + #[DataProvider('provideValidAssetsPackageNameConfigurationTests')] public function testValidAssetsPackageNameConfiguration($packageName) { $processor = new Processor(); @@ -221,9 +216,7 @@ public static function provideValidAssetsPackageNameConfigurationTests(): array ]; } - /** - * @dataProvider provideInvalidAssetConfigurationTests - */ + #[DataProvider('provideInvalidAssetConfigurationTests')] public function testInvalidAssetsConfiguration(array $assetConfig, $expectedMessage) { $processor = new Processor(); @@ -275,9 +268,7 @@ public static function provideInvalidAssetConfigurationTests(): iterable yield [$createPackageConfig($config), 'You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.']; } - /** - * @dataProvider provideValidLockConfigurationTests - */ + #[DataProvider('provideValidLockConfigurationTests')] public function testValidLockConfiguration($lockConfig, $processedConfig) { $processor = new Processor(); @@ -375,9 +366,7 @@ public function testLockMergeConfigs() ); } - /** - * @dataProvider provideValidSemaphoreConfigurationTests - */ + #[DataProvider('provideValidSemaphoreConfigurationTests')] public function testValidSemaphoreConfiguration($semaphoreConfig, $processedConfig) { $processor = new Processor(); @@ -823,6 +812,7 @@ protected static function getBundleDefaultConfig() ], 'type_info' => [ 'enabled' => !class_exists(FullStack::class) && class_exists(Type::class), + 'aliases' => [], ], 'property_info' => [ 'enabled' => !class_exists(FullStack::class), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/type_info.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/type_info.php index 0e7dcbae0e1da..3bf8b31500958 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/type_info.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/type_info.php @@ -7,5 +7,8 @@ 'php_errors' => ['log' => true], 'type_info' => [ 'enabled' => true, + 'aliases' => [ + 'CustomAlias' => 'int', + ], ], ]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/type_info.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/type_info.xml index 0fe4d525d1d5c..b3ca5e08a9243 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/type_info.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/type_info.xml @@ -8,6 +8,8 @@ - + + int + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/type_info.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/type_info.yml index 4d6b405b28821..bca245dfd8e1d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/type_info.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/type_info.yml @@ -6,3 +6,5 @@ framework: log: true type_info: enabled: true + aliases: + CustomAlias: int diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index b5f5f1ef5dc95..ba9732239c391 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -11,8 +11,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerAwareInterface; +use Psr\Log\LogLevel; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator; @@ -58,6 +60,10 @@ use Symfony\Component\HttpClient\ThrottlingHttpClient; use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\ConflictHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; @@ -389,7 +395,7 @@ public function testWorkflows() $transitionsMetadata = $metadataStoreDefinition->getArgument(2); $this->assertSame(\SplObjectStorage::class, $transitionsMetadata->getClass()); $transitionsMetadataCall = $transitionsMetadata->getMethodCalls()[0]; - $this->assertSame('attach', $transitionsMetadataCall[0]); + $this->assertSame('offsetSet', $transitionsMetadataCall[0]); $params = $transitionsMetadataCall[1]; $this->assertCount(2, $params); $this->assertInstanceOf(Reference::class, $params[0]); @@ -598,8 +604,8 @@ public function testPhpErrorsWithLogLevels() $definition = $container->getDefinition('debug.error_handler_configurator'); $this->assertEquals(new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE), $definition->getArgument(0)); $this->assertSame([ - \E_NOTICE => \Psr\Log\LogLevel::ERROR, - \E_WARNING => \Psr\Log\LogLevel::ERROR, + \E_NOTICE => LogLevel::ERROR, + \E_WARNING => LogLevel::ERROR, ], $definition->getArgument(1)); } @@ -610,35 +616,35 @@ public function testExceptionsConfig() $configuration = $container->getDefinition('exception_listener')->getArgument(3); $this->assertSame([ - \Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class, - \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class, - \Symfony\Component\HttpKernel\Exception\ConflictHttpException::class, - \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class, + BadRequestHttpException::class, + NotFoundHttpException::class, + ConflictHttpException::class, + ServiceUnavailableHttpException::class, ], array_keys($configuration)); $this->assertEqualsCanonicalizing([ 'log_channel' => null, 'log_level' => 'info', 'status_code' => 422, - ], $configuration[\Symfony\Component\HttpKernel\Exception\BadRequestHttpException::class]); + ], $configuration[BadRequestHttpException::class]); $this->assertEqualsCanonicalizing([ 'log_channel' => null, 'log_level' => 'info', 'status_code' => null, - ], $configuration[\Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class]); + ], $configuration[NotFoundHttpException::class]); $this->assertEqualsCanonicalizing([ 'log_channel' => null, 'log_level' => 'info', 'status_code' => null, - ], $configuration[\Symfony\Component\HttpKernel\Exception\ConflictHttpException::class]); + ], $configuration[ConflictHttpException::class]); $this->assertEqualsCanonicalizing([ 'log_channel' => null, 'log_level' => null, 'status_code' => 500, - ], $configuration[\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class]); + ], $configuration[ServiceUnavailableHttpException::class]); } public function testRouter() @@ -1934,9 +1940,7 @@ public function testRedisTagAwareAdapter() } } - /** - * @dataProvider appRedisTagAwareConfigProvider - */ + #[DataProvider('appRedisTagAwareConfigProvider')] public function testAppRedisTagAwareAdapter(string $configFile) { $container = $this->createContainerFromFile($configFile); @@ -1980,9 +1984,7 @@ public function testCacheTaggableTagAppliedToPools() } } - /** - * @dataProvider appRedisTagAwareConfigProvider - */ + #[DataProvider('appRedisTagAwareConfigProvider')] public function testCacheTaggableTagAppliedToRedisAwareAppPool(string $configFile) { $container = $this->createContainerFromFile($configFile); @@ -2222,9 +2224,7 @@ public static function provideMailer(): iterable ]; } - /** - * @dataProvider provideMailer - */ + #[DataProvider('provideMailer')] public function testMailer(string $configFile, array $expectedTransports, array $expectedRecipients, array $expectedAllowedRecipients) { $container = $this->createContainerFromFile($configFile); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index c4f67c2f12ebe..d3c1f8ef4bfe1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -135,9 +136,7 @@ public function testWorkflowValidationStateMachine() }); } - /** - * @dataProvider provideWorkflowValidationCustomTests - */ + #[DataProvider('provideWorkflowValidationCustomTests')] public function testWorkflowValidationCustomBroken(string $class, string $message) { $this->expectException(InvalidConfigurationException::class); @@ -431,9 +430,7 @@ public function testRateLimiterCompoundPolicyInvalidLimiters() }); } - /** - * @dataProvider emailValidationModeProvider - */ + #[DataProvider('emailValidationModeProvider')] public function testValidatorEmailValidationMode(string $mode) { $this->expectNotToPerformAssertions(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.json new file mode 100644 index 0000000000000..7dd4387521924 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.json @@ -0,0 +1,2 @@ +[] + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.md new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.txt new file mode 100644 index 0000000000000..de24cefb89204 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.txt @@ -0,0 +1,4 @@ + ------ -------- ------ +  Name   Method   Path  + ------ -------- ------ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.xml new file mode 100644 index 0000000000000..ea7517e162a61 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/empty_route_collection.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt index 9814273b7a221..bb70cea61d94b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1.txt @@ -7,7 +7,7 @@ | Host | localhost | | Host Regex | #HOST_REGEX# | | Scheme | http|https | -| Method | GET|HEAD | +| Method | GET|HEAD | | Requirements | name: [a-z]+ | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | | Defaults | name: Joseph | diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt index ad7a4c8c844fb..827873de5fd7b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_1_link.txt @@ -7,10 +7,10 @@ | Host | localhost | | Host Regex | #HOST_REGEX# | | Scheme | http|https | -| Method | GET|HEAD | +| Method | GET|HEAD | | Requirements | name: [a-z]+ | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | -| Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=58\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | +| Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=59\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | | | name: Joseph | | Options | compiler_class: Symfony\Component\Routing\RouteCompiler | | | opt1: val1 | diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt index 533409d402add..7bdbb83a01965 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2.txt @@ -7,7 +7,7 @@ | Host | localhost | | Host Regex | #HOST_REGEX# | | Scheme | http|https | -| Method | PUT|POST | +| Method | PUT|POST | | Requirements | NO CUSTOM | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | | Defaults | NONE | diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt index 8e3fe4ca7d65f..25941f6511d6d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_2_link.txt @@ -7,10 +7,10 @@ | Host | localhost | | Host Regex | #HOST_REGEX# | | Scheme | http|https | -| Method | PUT|POST | +| Method | PUT|POST | | Requirements | NO CUSTOM | | Class | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub | -| Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=58\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | +| Defaults | _controller: ]8;;myeditor://open?file=[:file:]&line=59\Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\MyController::__invoke()]8;;\ | | Options | compiler_class: Symfony\Component\Routing\RouteCompiler | | | opt1: val1 | | | opt2: val2 | diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json index 200108a166aac..b5d584c957462 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.json @@ -37,3 +37,4 @@ "condition": "context.getMethod() in ['GET', 'HEAD', 'POST']" } } + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md index 432001f0247fa..64b38953bd5b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.md @@ -34,5 +34,4 @@ route_2 - `compiler_class`: Symfony\Component\Routing\RouteCompiler - `opt1`: val1 - `opt2`: val2 -- Condition: context.getMethod() in ['GET', 'HEAD', 'POST'] - +- Condition: context.getMethod() in ['GET', 'HEAD', 'POST'] \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.txt index 9d06562328908..b787a2d4b9705 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.txt @@ -1,7 +1,7 @@ --------- ---------- ------------ ----------- ---------------  Name   Method   Scheme   Host   Path  --------- ---------- ------------ ----------- --------------- - route_1 GET|HEAD http|https localhost /hello/{name} - route_2 PUT|POST http|https localhost /name/add + route_1 GET|HEAD http|https localhost /hello/{name} + route_2 PUT|POST http|https localhost /name/add --------- ---------- ------------ ----------- --------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml index 6a07e059649c8..c36826d869d48 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_1.xml @@ -34,3 +34,4 @@ context.getMethod() in ['GET', 'HEAD', 'POST'] + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_2.txt index a9f9ee21b7497..e511a2857354f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_2.txt @@ -1,7 +1,7 @@ --------- ---------- ------------ ----------- ---------------  Name   Method   Scheme   Host   Path  --------- ---------- ------------ ----------- --------------- - route_1 GET|HEAD http|https localhost /hello/{name} - route_3 ANY http|https localhost /other/route + route_1 GET|HEAD http|https localhost /hello/{name} + route_3 ANY http|https localhost /other/route --------- ---------- ------------ ----------- --------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_3.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_3.txt index 8822b3c40793a..1d89756d24703 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_3.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_collection_3.txt @@ -1,6 +1,6 @@ --------- ---------- ------------ ----------- -----------  Name   Method   Scheme   Host   Path  --------- ---------- ------------ ----------- ----------- - route_2 PUT|POST http|https localhost /name/add + route_2 PUT|POST http|https localhost /name/add --------- ---------- ------------ ----------- ----------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.json new file mode 100644 index 0000000000000..bc002e61d9ef6 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.json @@ -0,0 +1,18 @@ +{ + "some_route": { + "path": "\/some-route", + "pathRegex": "#PATH_REGEX#", + "host": "ANY", + "hostRegex": "", + "scheme": "https", + "method": "ANY", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\RouteStub", + "defaults": { + "_controller": "Controller" + }, + "requirements": "NO CUSTOM", + "options": { + "compiler_class": "Symfony\\Component\\Routing\\RouteCompiler" + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.md new file mode 100644 index 0000000000000..41466a1646f4a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.md @@ -0,0 +1,15 @@ +some_route +---------- + +- Path: /some-route +- Path Regex: #PATH_REGEX# +- Host: ANY +- Host Regex: +- Scheme: https +- Method: ANY +- Class: Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub +- Defaults: + - `_controller`: Controller +- Requirements: NO CUSTOM +- Options: + - `compiler_class`: Symfony\Component\Routing\RouteCompiler \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.txt new file mode 100644 index 0000000000000..6c34fc464c5ef --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.txt @@ -0,0 +1,6 @@ + ------------ -------- -------- ------------- +  Name   Method   Scheme   Path  + ------------ -------- -------- ------------- + some_route ANY https /some-route + ------------ -------- -------- ------------- + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.xml new file mode 100644 index 0000000000000..de9930fc5cc2e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_host.xml @@ -0,0 +1,14 @@ + + + + /some-route + https + + Controller + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.json new file mode 100644 index 0000000000000..811c077732f8c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.json @@ -0,0 +1,18 @@ +{ + "some_route_with_host": { + "path": "\/some-route", + "pathRegex": "#PATH_REGEX#", + "host": "symfony.com", + "hostRegex": "#HOST_REGEX#", + "scheme": "ANY", + "method": "ANY", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\RouteStub", + "defaults": { + "_controller": "strpos" + }, + "requirements": "NO CUSTOM", + "options": { + "compiler_class": "Symfony\\Component\\Routing\\RouteCompiler" + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.md new file mode 100644 index 0000000000000..8a8bad6ea9fd5 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.md @@ -0,0 +1,15 @@ +some_route_with_host +-------------------- + +- Path: /some-route +- Path Regex: #PATH_REGEX# +- Host: symfony.com +- Host Regex: #HOST_REGEX# +- Scheme: ANY +- Method: ANY +- Class: Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\RouteStub +- Defaults: + - `_controller`: strpos +- Requirements: NO CUSTOM +- Options: + - `compiler_class`: Symfony\Component\Routing\RouteCompiler diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.txt new file mode 100644 index 0000000000000..cb83e325a81e2 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.txt @@ -0,0 +1,6 @@ + ---------------------- -------- ------------- ------------- +  Name   Method   Host   Path  + ---------------------- -------- ------------- ------------- + some_route_with_host ANY symfony.com /some-route + ---------------------- -------- ------------- ------------- + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.xml new file mode 100644 index 0000000000000..fe7d8da8d9a4f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/route_with_generic_scheme.xml @@ -0,0 +1,13 @@ + + + + /some-route + symfony.com + + strpos + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractAttributeRoutingTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractAttributeRoutingTestCase.php index 5166c8dda4384..842d7268f7355 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractAttributeRoutingTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractAttributeRoutingTestCase.php @@ -11,13 +11,12 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\HttpFoundation\Request; abstract class AbstractAttributeRoutingTestCase extends AbstractWebTestCase { - /** - * @dataProvider getRoutes - */ + #[DataProvider('getRoutes')] public function testAnnotatedController(string $path, string $expectedValue) { $client = $this->createClient(['test_case' => $this->getTestCaseApp(), 'root_config' => 'config.yml']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php index 4848976aede71..79c8a704b4a2b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; @@ -21,9 +22,7 @@ class ApiAttributesTest extends AbstractWebTestCase { - /** - * @dataProvider mapQueryStringProvider - */ + #[DataProvider('mapQueryStringProvider')] public function testMapQueryString(string $uri, array $query, string $expectedResponse, int $expectedStatusCode) { $client = self::createClient(['test_case' => 'ApiAttributesTest']); @@ -146,24 +145,24 @@ public static function mapQueryStringProvider(): iterable ]; $expectedResponse = <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 404, - "detail": "filter: This value should be of type Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter.", - "violations": [ - { - "parameters": { - "hint": "Failed to create object because the class misses the \"filter\" property.", - "{{ type }}": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter" - }, - "propertyPath": "filter", - "template": "This value should be of type {{ type }}.", - "title": "This value should be of type Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter." - } - ] - } - JSON; + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 404, + "detail": "filter: This value should be of type Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter.", + "violations": [ + { + "parameters": { + "hint": "Failed to create object because the class misses the \"filter\" property.", + "{{ type }}": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter" + }, + "propertyPath": "filter", + "template": "This value should be of type {{ type }}.", + "title": "This value should be of type Symfony\\Bundle\\FrameworkBundle\\Tests\\Functional\\Filter." + } + ] + } + JSON; yield 'empty query string mapping non-nullable attribute without default value' => [ 'uri' => '/map-query-string-to-non-nullable-attribute-without-default-value.json', @@ -214,9 +213,7 @@ public static function mapQueryStringProvider(): iterable ]; } - /** - * @dataProvider mapRequestPayloadProvider - */ + #[DataProvider('mapRequestPayloadProvider')] public function testMapRequestPayload(string $uri, string $format, array $parameters, ?string $content, callable $responseAssertion, int $expectedStatusCode) { $client = self::createClient(['test_case' => 'ApiAttributesTest']); @@ -603,7 +600,7 @@ public static function mapRequestPayloadProvider(): iterable self::assertIsArray($json['violations'] ?? null); self::assertCount(1, $json['violations']); self::assertSame('approved', $json['violations'][0]['propertyPath'] ?? null); -}, + }, 'expectedStatusCode' => 422, ]; @@ -947,11 +944,11 @@ public function __invoke(#[MapRequestPayload] ?RequestBody $body, Request $reque return new Response( << - {$body->comment} - {$body->approved} - - XML + + {$body->comment} + {$body->approved} + + XML ); } } @@ -966,11 +963,11 @@ public function __invoke(Request $request, #[MapRequestPayload] RequestBody $bod return new Response( << - {$body->comment} - {$body->approved} - - XML + + {$body->comment} + {$body->approved} + + XML ); } } @@ -985,11 +982,11 @@ public function __invoke(Request $request, #[MapRequestPayload] RequestBody $bod return new Response( << - {$body->comment} - {$body->approved} - - XML + + {$body->comment} + {$body->approved} + + XML ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php index a068034344782..45663f0bfeb05 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php @@ -28,7 +28,7 @@ public function testBundlePublicDir() $fs = new Filesystem(); $fs->remove($projectDir); $fs->mkdir($projectDir.'/public'); - $command = (new Application($kernel))->add(new AssetsInstallCommand($fs, $projectDir)); + $command = (new Application($kernel))->addCommand(new AssetsInstallCommand($fs, $projectDir)); $exitCode = (new CommandTester($command))->execute(['target' => $projectDir.'/public']); $this->assertSame(0, $exitCode); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index dbd78645d881c..53e8b5c48778b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Group; use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Cache\Adapter\FilesystemAdapter; @@ -19,9 +20,7 @@ use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\Finder\SplFileInfo; -/** - * @group functional - */ +#[Group('functional')] class CachePoolClearCommandTest extends AbstractWebTestCase { protected function setUp(): void @@ -146,7 +145,7 @@ public function testExcludedPool() private function createCommandTester(?array $poolNames = null) { $application = new Application(static::$kernel); - $application->add(new CachePoolClearCommand(static::getContainer()->get('cache.global_clearer'), $poolNames)); + $application->addCommand(new CachePoolClearCommand(static::getContainer()->get('cache.global_clearer'), $poolNames)); return new CommandTester($application->find('cache:pool:clear')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolListCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolListCommandTest.php index 8e9061845a45e..6dcbc4294e945 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolListCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolListCommandTest.php @@ -11,13 +11,12 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Group; use Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; -/** - * @group functional - */ +#[Group('functional')] class CachePoolListCommandTest extends AbstractWebTestCase { protected function setUp(): void @@ -46,7 +45,7 @@ public function testEmptyList() private function createCommandTester(array $poolNames) { $application = new Application(static::$kernel); - $application->add(new CachePoolListCommand($poolNames)); + $application->addCommand(new CachePoolListCommand($poolNames)); return new CommandTester($application->find('cache:pool:list')); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php index 23f4a116ef341..64829949a9932 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Error\Warning; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\Cache\Adapter\TagAwareAdapter; @@ -24,18 +27,15 @@ public function testCachePools() $this->doTestCachePools([], AdapterInterface::class); } - /** - * @requires extension redis - * - * @group integration - */ + #[RequiresPhpExtension('redis')] + #[Group('integration')] public function testRedisCachePools() { $this->skipIfRedisUnavailable(); try { $this->doTestCachePools(['root_config' => 'redis_config.yml', 'environment' => 'redis_cache'], RedisAdapter::class); - } catch (\PHPUnit\Framework\Error\Warning $e) { + } catch (Warning $e) { if (!str_starts_with($e->getMessage(), 'unable to connect to')) { throw $e; } @@ -48,18 +48,15 @@ public function testRedisCachePools() } } - /** - * @requires extension redis - * - * @group integration - */ + #[RequiresPhpExtension('redis')] + #[Group('integration')] public function testRedisCustomCachePools() { $this->skipIfRedisUnavailable(); try { $this->doTestCachePools(['root_config' => 'redis_custom_config.yml', 'environment' => 'custom_redis_cache'], RedisAdapter::class); - } catch (\PHPUnit\Framework\Error\Warning $e) { + } catch (Warning $e) { if (!str_starts_with($e->getMessage(), 'unable to connect to')) { throw $e; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php index bd153963632e2..ea4ee07883c8c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\TestWith; use Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Exception\InvalidArgumentException; @@ -19,15 +22,11 @@ use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; -/** - * @group functional - */ +#[Group('functional')] class ConfigDebugCommandTest extends AbstractWebTestCase { - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testShowList(bool $debug) { $tester = $this->createCommandTester($debug); @@ -44,10 +43,8 @@ public function testShowList(bool $debug) $this->assertStringContainsString(' test_dump', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpKernelExtension(bool $debug) { $tester = $this->createCommandTester($debug); @@ -58,10 +55,8 @@ public function testDumpKernelExtension(bool $debug) $this->assertStringContainsString(' foo: bar', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpBundleName(bool $debug) { $tester = $this->createCommandTester($debug); @@ -71,10 +66,8 @@ public function testDumpBundleName(bool $debug) $this->assertStringContainsString('custom: foo', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpBundleOption(bool $debug) { $tester = $this->createCommandTester($debug); @@ -84,10 +77,8 @@ public function testDumpBundleOption(bool $debug) $this->assertStringContainsString('foo', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpWithoutTitleIsValidJson(bool $debug) { $tester = $this->createCommandTester($debug); @@ -97,10 +88,8 @@ public function testDumpWithoutTitleIsValidJson(bool $debug) $this->assertJson($tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpWithUnsupportedFormat(bool $debug) { $tester = $this->createCommandTester($debug); @@ -114,10 +103,8 @@ public function testDumpWithUnsupportedFormat(bool $debug) ]); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testParametersValuesAreResolved(bool $debug) { $tester = $this->createCommandTester($debug); @@ -128,10 +115,8 @@ public function testParametersValuesAreResolved(bool $debug) $this->assertStringContainsString('secret: test', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testParametersValuesAreFullyResolved(bool $debug) { $tester = $this->createCommandTester($debug); @@ -141,13 +126,11 @@ public function testParametersValuesAreFullyResolved(bool $debug) $this->assertStringContainsString('locale: en', $tester->getDisplay()); $this->assertStringContainsString('secret: test', $tester->getDisplay()); $this->assertStringContainsString('cookie_httponly: true', $tester->getDisplay()); - $this->assertStringContainsString('ide: '.$debug ? ($_ENV['SYMFONY_IDE'] ?? $_SERVER['SYMFONY_IDE'] ?? 'null') : 'null', $tester->getDisplay()); + $this->assertStringContainsString('ide: '.($debug ? ($_ENV['SYMFONY_IDE'] ?? $_SERVER['SYMFONY_IDE'] ?? 'null') : 'null'), $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDefaultParameterValueIsResolvedIfConfigIsExisting(bool $debug) { $tester = $this->createCommandTester($debug); @@ -158,10 +141,8 @@ public function testDefaultParameterValueIsResolvedIfConfigIsExisting(bool $debu $this->assertStringContainsString(\sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpExtensionConfigWithoutBundle(bool $debug) { $tester = $this->createCommandTester($debug); @@ -171,10 +152,8 @@ public function testDumpExtensionConfigWithoutBundle(bool $debug) $this->assertStringContainsString('enabled: true', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpUndefinedBundleOption(bool $debug) { $tester = $this->createCommandTester($debug); @@ -183,10 +162,8 @@ public function testDumpUndefinedBundleOption(bool $debug) $this->assertStringContainsString('Unable to find configuration for "test.foo"', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpWithPrefixedEnv(bool $debug) { $tester = $this->createCommandTester($debug); @@ -195,10 +172,8 @@ public function testDumpWithPrefixedEnv(bool $debug) $this->assertStringContainsString("cookie_httponly: '%env(bool:COOKIE_HTTPONLY)%'", $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpFallsBackToDefaultConfigAndResolvesParameterValue(bool $debug) { $tester = $this->createCommandTester($debug); @@ -208,10 +183,8 @@ public function testDumpFallsBackToDefaultConfigAndResolvesParameterValue(bool $ $this->assertStringContainsString('foo: bar', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpFallsBackToDefaultConfigAndResolvesEnvPlaceholder(bool $debug) { $tester = $this->createCommandTester($debug); @@ -221,10 +194,8 @@ public function testDumpFallsBackToDefaultConfigAndResolvesEnvPlaceholder(bool $ $this->assertStringContainsString("baz: '%env(BAZ)%'", $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpThrowsExceptionWhenDefaultConfigFallbackIsImpossible(bool $debug) { $this->expectException(\LogicException::class); @@ -234,14 +205,12 @@ public function testDumpThrowsExceptionWhenDefaultConfigFallbackIsImpossible(boo $tester->execute(['name' => 'ExtensionWithoutConfigTestBundle']); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(bool $debug, array $input, array $expectedSuggestions) { $application = $this->createApplication($debug); - $application->add(new ConfigDebugCommand()); + $application->addCommand(new ConfigDebugCommand()); $tester = new CommandCompletionTester($application->get('debug:config')); $suggestions = $tester->complete($input); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php index 8f5930faac2eb..377a530e98fe7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDumpReferenceCommandTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\TestWith; use Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\ArrayInput; @@ -18,15 +21,11 @@ use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; -/** - * @group functional - */ +#[Group('functional')] class ConfigDumpReferenceCommandTest extends AbstractWebTestCase { - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testShowList(bool $debug) { $tester = $this->createCommandTester($debug); @@ -43,10 +42,8 @@ public function testShowList(bool $debug) $this->assertStringContainsString(' test_dump', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpKernelExtension(bool $debug) { $tester = $this->createCommandTester($debug); @@ -57,10 +54,8 @@ public function testDumpKernelExtension(bool $debug) $this->assertStringContainsString(' bar', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpBundleName(bool $debug) { $tester = $this->createCommandTester($debug); @@ -71,10 +66,8 @@ public function testDumpBundleName(bool $debug) $this->assertStringContainsString(' custom:', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpExtensionConfigWithoutBundle(bool $debug) { $tester = $this->createCommandTester($debug); @@ -84,10 +77,8 @@ public function testDumpExtensionConfigWithoutBundle(bool $debug) $this->assertStringContainsString('enabled: true', $tester->getDisplay()); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpAtPath(bool $debug) { $tester = $this->createCommandTester($debug); @@ -98,20 +89,19 @@ public function testDumpAtPath(bool $debug) $this->assertSame(0, $ret, 'Returns 0 in case of success'); $this->assertSame(<<<'EOL' -# Default configuration for extension with alias: "test" at path "array" -array: - child1: ~ - child2: ~ + # Default configuration for extension with alias: "test" at path "array" + array: + child1: ~ + child2: ~ -EOL - , $tester->getDisplay(true)); + EOL, + $tester->getDisplay(true) + ); } - /** - * @testWith [true] - * [false] - */ + #[TestWith([true])] + #[TestWith([false])] public function testDumpAtPathXml(bool $debug) { $tester = $this->createCommandTester($debug); @@ -125,14 +115,12 @@ public function testDumpAtPathXml(bool $debug) $this->assertStringContainsString('[ERROR] The "path" option is only available for the "yaml" format.', $tester->getDisplay()); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(bool $debug, array $input, array $expectedSuggestions) { $application = $this->createApplication($debug); - $application->add(new ConfigDumpReferenceCommand()); + $application->addCommand(new ConfigDumpReferenceCommand()); $tester = new CommandCompletionTester($application->get('config:dump-reference')); $suggestions = $tester->complete($input); $this->assertSame($expectedSuggestions, $suggestions); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php index d21d4d113d2e6..e1e7ce084999e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerDebugCommandTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BackslashClass; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\ContainerExcluded; @@ -18,9 +20,7 @@ use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\HttpKernel\HttpKernelInterface; -/** - * @group functional - */ +#[Group('functional')] class ContainerDebugCommandTest extends AbstractWebTestCase { public function testDumpContainerIfNotExists() @@ -113,9 +113,7 @@ public function testExcludedService() $this->assertStringNotContainsString(ContainerExcluded::class, $tester->getDisplay()); } - /** - * @dataProvider provideIgnoreBackslashWhenFindingService - */ + #[DataProvider('provideIgnoreBackslashWhenFindingService')] public function testIgnoreBackslashWhenFindingService(string $validServiceId) { static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml']); @@ -168,25 +166,26 @@ public function testDescribeEnvVars() $this->assertStringMatchesFormat(<<<'TXT' -Symfony Container Environment Variables -======================================= + Symfony Container Environment Variables + ======================================= - --------- ----------------- ------------%w - Name Default value Real value%w - --------- ----------------- ------------%w - JSON "[1, "2.5", 3]" n/a%w - REAL n/a "value"%w - UNKNOWN n/a n/a%w - --------- ----------------- ------------%w + --------- ----------------- ------------%w + Name Default value Real value%w + --------- ----------------- ------------%w + JSON "[1, "2.5", 3]" n/a%w + REAL n/a "value"%w + UNKNOWN n/a n/a%w + --------- ----------------- ------------%w - // Note real values might be different between web and CLI.%w + // Note real values might be different between web and CLI.%w - [WARNING] The following variables are missing:%w + [WARNING] The following variables are missing:%w - * UNKNOWN + * UNKNOWN -TXT - , $tester->getDisplay(true)); + TXT, + $tester->getDisplay(true) + ); putenv('REAL'); } @@ -214,10 +213,10 @@ public function testGetDeprecation() file_put_contents($path, serialize([[ 'type' => 16384, 'message' => 'The "Symfony\Bundle\FrameworkBundle\Controller\Controller" class is deprecated since Symfony 4.2, use Symfony\Bundle\FrameworkBundle\Controller\AbstractController instead.', - 'file' => '/home/hamza/projet/contrib/sf/vendor/symfony/framework-bundle/Controller/Controller.php', + 'file' => '/home/hamza/project/contrib/sf/vendor/symfony/framework-bundle/Controller/Controller.php', 'line' => 17, 'trace' => [[ - 'file' => '/home/hamza/projet/contrib/sf/src/Controller/DefaultController.php', + 'file' => '/home/hamza/project/contrib/sf/src/Controller/DefaultController.php', 'line' => 9, 'function' => 'spl_autoload_call', ]], @@ -233,7 +232,7 @@ public function testGetDeprecation() $tester->assertCommandIsSuccessful(); $this->assertStringContainsString('Symfony\Bundle\FrameworkBundle\Controller\Controller', $tester->getDisplay()); - $this->assertStringContainsString('/home/hamza/projet/contrib/sf/vendor/symfony/framework-bundle/Controller/Controller.php', $tester->getDisplay()); + $this->assertStringContainsString('/home/hamza/project/contrib/sf/vendor/symfony/framework-bundle/Controller/Controller.php', $tester->getDisplay()); } public function testGetDeprecationNone() @@ -282,9 +281,7 @@ public static function provideIgnoreBackslashWhenFindingService(): array ]; } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions, array $notExpectedSuggestions = []) { static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml', 'debug' => true]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php index f0b6b4bd57b07..8e50caa01dc02 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php @@ -11,19 +11,18 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\DependencyInjection\Argument\ArgumentTrait; -/** - * @group functional - */ +#[Group('functional')] class ContainerLintCommandTest extends AbstractWebTestCase { private Application $application; - /** - * @dataProvider containerLintProvider - */ + #[DataProvider('containerLintProvider')] public function testLintContainer(string $configFile, bool $resolveEnvVars, int $expectedExitCode, string $expectedOutput) { $kernel = static::createKernel([ @@ -40,13 +39,16 @@ public function testLintContainer(string $configFile, bool $resolveEnvVars, int $this->assertStringContainsString($expectedOutput, $tester->getDisplay()); } - public static function containerLintProvider(): array + public static function containerLintProvider(): iterable { - return [ - ['escaped_percent.yml', false, 0, 'The container was linted successfully'], - ['missing_env_var.yml', false, 0, 'The container was linted successfully'], - ['missing_env_var.yml', true, 1, 'Environment variable not found: "BAR"'], - ]; + yield ['escaped_percent.yml', false, 0, 'The container was linted successfully']; + + if (trait_exists(ArgumentTrait::class)) { + yield ['escaped_percent.yml', true, 0, 'The container was linted successfully']; + } + + yield ['missing_env_var.yml', false, 0, 'The container was linted successfully']; + yield ['missing_env_var.yml', true, 1, 'Environment variable not found: "BAR"']; } private function createCommandTester(): CommandTester diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php index ca11e3faea143..de94a1e718eff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; @@ -20,9 +22,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Routing\RouterInterface; -/** - * @group functional - */ +#[Group('functional')] class DebugAutowiringCommandTest extends AbstractWebTestCase { public function testBasicFunctionality() @@ -116,13 +116,11 @@ public function testNotConfusedByClassAliases() $this->assertStringContainsString(ClassAliasExampleClass::class, $tester->getDisplay()); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $kernel = static::bootKernel(['test_case' => 'ContainerDebug', 'root_config' => 'config.yml']); - $command = (new Application($kernel))->add(new DebugAutowiringCommand()); + $command = (new Application($kernel))->addCommand(new DebugAutowiringCommand()); $tester = new CommandCompletionTester($command); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/FragmentTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/FragmentTest.php index 48d5c327a3986..b8cff1f48c2a3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/FragmentTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/FragmentTest.php @@ -11,11 +11,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; + class FragmentTest extends AbstractWebTestCase { - /** - * @dataProvider getConfigs - */ + #[DataProvider('getConfigs')] public function testFragment($insulate) { $client = $this->createClient(['test_case' => 'Fragment', 'root_config' => 'config.yml', 'debug' => true]); @@ -26,15 +26,16 @@ public function testFragment($insulate) $client->request('GET', '/fragment_home'); $this->assertEquals(<<getResponse()->getContent()); + bar txt + -- + html + -- + es + -- + fr + TXT, + $client->getResponse()->getContent() + ); } public static function getConfigs() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php index 1ba71d74f9e6e..4193e3ff7e7a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php @@ -99,6 +99,7 @@ public function testMailerAssertions() $this->assertEmailHtmlBodyContains($email, 'Foo'); $this->assertEmailHtmlBodyNotContains($email, 'Bar'); $this->assertEmailAttachmentCount($email, 1); + $this->assertEmailAddressNotContains($email, 'To', 'thomas@symfony.com'); $email = $this->getMailerMessage($second); $this->assertEmailSubjectContains($email, 'Foo'); @@ -106,5 +107,7 @@ public function testMailerAssertions() $this->assertEmailAddressContains($email, 'To', 'fabien@symfony.com'); $this->assertEmailAddressContains($email, 'To', 'thomas@symfony.com'); $this->assertEmailAddressContains($email, 'Reply-To', 'me@symfony.com'); + $this->assertEmailAddressNotContains($email, 'To', 'helene@symfony.com'); + $this->assertEmailAddressNotContains($email, 'Reply-To', 'helene@symfony.com'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/NotificationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/NotificationTest.php index 03b947a0fb909..7511591cb66de 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/NotificationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/NotificationTest.php @@ -11,11 +11,12 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\RequiresMethod; +use Symfony\Bundle\MercureBundle\MercureBundle; + final class NotificationTest extends AbstractWebTestCase { - /** - * @requires function \Symfony\Bundle\MercureBundle\MercureBundle::build - */ + #[RequiresMethod(MercureBundle::class, 'build')] public function testNotifierAssertion() { $client = $this->createClient(['test_case' => 'Notifier', 'root_config' => 'config.yml', 'debug' => true]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ProfilerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ProfilerTest.php index d7825979536e5..b5853dd1a381c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ProfilerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ProfilerTest.php @@ -11,11 +11,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; + class ProfilerTest extends AbstractWebTestCase { - /** - * @dataProvider getConfigs - */ + #[DataProvider('getConfigs')] public function testProfilerIsDisabled($insulate) { $client = $this->createClient(['test_case' => 'Profiler', 'root_config' => 'config.yml']); @@ -36,9 +36,7 @@ public function testProfilerIsDisabled($insulate) $this->assertNull($client->getProfile()); } - /** - * @dataProvider getConfigs - */ + #[DataProvider('getConfigs')] public function testProfilerCollectParameter($insulate) { $client = $this->createClient(['test_case' => 'ProfilerCollectParameter', 'root_config' => 'config.yml']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php index 18cd61b08519c..128932311e6b9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Component\PropertyInfo\Type as LegacyType; use Symfony\Component\TypeInfo\Type; @@ -29,9 +31,8 @@ public function testPhpDocPriority() $this->assertEquals(Type::list(Type::int()), $propertyInfo->getType(Dummy::class, 'codes')); } - /** - * @group legacy - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testPhpDocPriorityLegacy() { static::bootKernel(['test_case' => 'Serializer']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php index 61407880457ce..910e3b6f7901f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php @@ -11,13 +11,14 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\TestWith; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\Console\Tester\CommandTester; -/** - * @group functional - */ +#[Group('functional')] class RouterDebugCommandTest extends AbstractWebTestCase { private Application $application; @@ -89,21 +90,17 @@ public function testSearchWithThrow() $tester->execute(['name' => 'gerard'], ['interactive' => true]); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $tester = new CommandCompletionTester($this->application->get('debug:router')); $this->assertSame($expectedSuggestions, $tester->complete($input)); } - /** - * @testWith ["txt"] - * ["xml"] - * ["json"] - * ["md"] - */ + #[TestWith(['txt'])] + #[TestWith(['xml'])] + #[TestWith(['json'])] + #[TestWith(['md'])] public function testShowAliases(string $format) { $tester = $this->createCommandTester(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php index 4f4caa6eb1567..f1f4f14cf146f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RoutingConditionServiceTest.php @@ -11,11 +11,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; + class RoutingConditionServiceTest extends AbstractWebTestCase { - /** - * @dataProvider provideRoutes - */ + #[DataProvider('provideRoutes')] public function testCondition(int $code, string $path) { $client = static::createClient(['test_case' => 'RoutingConditionService']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SecurityTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SecurityTest.php index c26fa717d9176..ab06b5f6c25eb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SecurityTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SecurityTest.php @@ -11,13 +11,12 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Security\Core\User\InMemoryUser; class SecurityTest extends AbstractWebTestCase { - /** - * @dataProvider getUsers - */ + #[DataProvider('getUsers')] public function testLoginUser(string $username, array $roles, ?string $firewallContext) { $user = new InMemoryUser($username, 'the-password', $roles); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php index 4c1b92ccf539f..88ea3230a8e3d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SessionTest.php @@ -11,13 +11,14 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; + class SessionTest extends AbstractWebTestCase { /** * Tests session attributes persist. - * - * @dataProvider getConfigs */ + #[DataProvider('getConfigs')] public function testWelcome($config, $insulate) { $client = $this->createClient(['test_case' => 'Session', 'root_config' => $config]); @@ -48,9 +49,8 @@ public function testWelcome($config, $insulate) /** * Tests flash messages work in practice. - * - * @dataProvider getConfigs */ + #[DataProvider('getConfigs')] public function testFlash($config, $insulate) { $client = $this->createClient(['test_case' => 'Session', 'root_config' => $config]); @@ -72,9 +72,8 @@ public function testFlash($config, $insulate) /** * See if two separate insulated clients can run without * polluting each other's session data. - * - * @dataProvider getConfigs */ + #[DataProvider('getConfigs')] public function testTwoClients($config, $insulate) { // start first client @@ -128,9 +127,7 @@ public function testTwoClients($config, $insulate) $this->assertStringContainsString('Welcome back client2, nice to meet you.', $crawler2->text()); } - /** - * @dataProvider getConfigs - */ + #[DataProvider('getConfigs')] public function testCorrectCacheControlHeadersForCacheableAction($config, $insulate) { $client = $this->createClient(['test_case' => 'Session', 'root_config' => $config]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SluggerLocaleAwareTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SluggerLocaleAwareTest.php index 76901246138b6..d09f969b065a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SluggerLocaleAwareTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SluggerLocaleAwareTest.php @@ -11,16 +11,14 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Slugger\SlugConstructArgService; -/** - * @group functional - */ +#[Group('functional')] class SluggerLocaleAwareTest extends AbstractWebTestCase { - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testLocalizedSlugger() { $kernel = static::createKernel(['test_case' => 'Slugger', 'root_config' => 'config.yml']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php index fe7093081509f..8b8898ad84933 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use Symfony\Bundle\FrameworkBundle\Test\TestContainer; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\NonPublicService; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService; @@ -68,17 +70,13 @@ public function testSetDecoratedService() $this->assertSame($service, $container->get('decorated')->inner); } - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testBootKernel() { static::bootKernel(['test_case' => 'TestServiceContainer']); } - /** - * @depends testBootKernel - */ + #[Depends('testBootKernel')] public function testKernelIsNotInitialized() { self::assertNull(self::$class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TranslationDebugCommandTest.php index 5e396440cacf4..1d7e2952b6fa5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TranslationDebugCommandTest.php @@ -11,13 +11,12 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\Group; use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; -/** - * @group functional - */ +#[Group('functional')] class TranslationDebugCommandTest extends AbstractWebTestCase { private Application $application; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TypeInfoTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TypeInfoTest.php index 6acdb9c814548..dcda93a332f61 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TypeInfoTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TypeInfoTest.php @@ -13,6 +13,7 @@ use PHPStan\PhpDocParser\Parser\PhpDocParser; use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\TypeInfo\Dummy; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\TypeInfo\Type; class TypeInfoTest extends AbstractWebTestCase @@ -28,5 +29,10 @@ public function testComponent() } $this->assertEquals(Type::int(), static::getContainer()->get('type_info.resolver')->resolve('int')); + + if (Kernel::VERSION_ID >= 70400) { + $this->assertEquals(Type::int(), static::getContainer()->get('type_info.resolver')->resolve(new \ReflectionProperty(Dummy::class, 'customAlias'))); + $this->assertEquals(Type::int(), static::getContainer()->get('type_info.resolver')->resolve('CustomAlias')); + } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php index 59c28b2a6d93a..5748b61cd3743 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php @@ -89,14 +89,16 @@ protected function build(ContainerBuilder $container): void $container->registerExtension(new TestDumpExtension()); } - public function __sleep(): array + public function __serialize(): array { - return ['varDir', 'testCase', 'rootConfig', 'environment', 'debug']; + return [$this->varDir, $this->testCase, $this->rootConfig, $this->environment, $this->debug]; } - public function __wakeup(): void + public function __unserialize(array $data): void { - foreach ($this as $k => $v) { + [$this->varDir, $this->testCase, $this->rootConfig, $this->environment, $this->debug] = $data; + + foreach ($this as $v) { if (\is_object($v)) { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/Dummy.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/Dummy.php index 0f517df5139d0..b91635ad86851 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/Dummy.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/Dummy.php @@ -18,4 +18,9 @@ class Dummy { public string $name; + + /** + * @var CustomAlias + */ + public mixed $customAlias; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/config.yml index 35c7bb4c46c09..925f10724f6ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TypeInfo/config.yml @@ -3,7 +3,9 @@ imports: framework: http_method_override: false - type_info: true + type_info: + aliases: + CustomAlias: int services: type_info.resolver.alias: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php index a6961809932bc..eac061e3bd573 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php @@ -55,12 +55,12 @@ public function getLogDir(): string return $this->cacheDir; } - public function __sleep(): array + public function __serialize(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup(): void + public function __unserialize(array $data): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php index 6f7c84d8bddc1..5fa641c7f62b1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/flex-style/src/FlexStyleMicroKernel.php @@ -64,12 +64,12 @@ public function getProjectDir(): string return \dirname((new \ReflectionObject($this))->getFileName(), 2); } - public function __sleep(): array + public function __serialize(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup(): void + public function __unserialize(array $data): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/AttributeRouteControllerLoaderTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/AttributeRouteControllerLoaderTest.php new file mode 100644 index 0000000000000..3f879f78eff03 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/AttributeRouteControllerLoaderTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Routing; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Routing\AttributeRouteControllerLoader; +use Symfony\Bundle\FrameworkBundle\Tests\Routing\Fixtures\InvokableController; +use Symfony\Bundle\FrameworkBundle\Tests\Routing\Fixtures\MethodActionControllers; + +class AttributeRouteControllerLoaderTest extends TestCase +{ + public function testConfigureRouteSetsControllerForInvokable() + { + $loader = new AttributeRouteControllerLoader(); + $collection = $loader->load(InvokableController::class); + + $route = $collection->get('lol'); + $this->assertSame(InvokableController::class, $route->getDefault('_controller')); + } + + public function testConfigureRouteSetsControllerForMethod() + { + $loader = new AttributeRouteControllerLoader(); + $collection = $loader->load(MethodActionControllers::class); + + $put = $collection->get('put'); + $post = $collection->get('post'); + + $this->assertSame(MethodActionControllers::class.'::put', $put->getDefault('_controller')); + $this->assertSame(MethodActionControllers::class.'::post', $post->getDefault('_controller')); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/Fixtures/InvokableController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/Fixtures/InvokableController.php new file mode 100644 index 0000000000000..d9276f09a75c7 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/Fixtures/InvokableController.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Routing\Fixtures; + +use Symfony\Component\Routing\Attribute\Route; + +#[Route(path: '/here', name: 'lol', methods: ['GET', 'POST'], schemes: ['https'])] +class InvokableController +{ + public function __invoke() + { + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/Fixtures/MethodActionControllers.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/Fixtures/MethodActionControllers.php new file mode 100644 index 0000000000000..f0adec88ace9f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/Fixtures/MethodActionControllers.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Routing\Fixtures; + +use Symfony\Component\Routing\Attribute\Route; + +#[Route('/the/path')] +class MethodActionControllers +{ + #[Route(name: 'post', methods: ['POST'])] + public function post() + { + } + + #[Route(name: 'put', methods: ['PUT'], priority: 10)] + public function put() + { + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php index d2c0215634b2a..f46522a97234c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RouterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Routing; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\Routing\Router; @@ -438,9 +439,7 @@ public function testExceptionOnNonStringParameterWithSfContainer() $router->getRouteCollection(); } - /** - * @dataProvider getNonStringValues - */ + #[DataProvider('getNonStringValues')] public function testDefaultValuesAsNonStrings($value) { $routes = new RouteCollection(); @@ -455,9 +454,7 @@ public function testDefaultValuesAsNonStrings($value) $this->assertSame($value, $route->getDefault('foo')); } - /** - * @dataProvider getNonStringValues - */ + #[DataProvider('getNonStringValues')] public function testDefaultValuesAsNonStringsWithSfContainer($value) { $routes = new RouteCollection(); @@ -525,9 +522,7 @@ public static function getNonStringValues() return [[null], [false], [true], [new \stdClass()], [['foo', 'bar']], [[[]]]]; } - /** - * @dataProvider getContainerParameterForRoute - */ + #[DataProvider('getContainerParameterForRoute')] public function testCacheValidityWithContainerParameters($parameter) { $cacheDir = tempnam(sys_get_temp_dir(), 'sf_router_'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php index f91f4bceda5f4..6d050386b9858 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Secrets/SodiumVaultTest.php @@ -11,14 +11,13 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Secrets; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\String\LazyString; -/** - * @requires extension sodium - */ +#[RequiresPhpExtension('sodium')] class SodiumVaultTest extends TestCase { private string $secretsDir; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php index 84f2ef0ef31f2..a058d3628c081 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php @@ -12,13 +12,16 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Test; use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Attributes\RequiresMethod; use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestAssertionsTrait; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\BrowserKit\Cookie; use Symfony\Component\BrowserKit\CookieJar; +use Symfony\Component\BrowserKit\History; use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\HttpFoundation\Cookie as HttpFoundationCookie; use Symfony\Component\HttpFoundation\Request; @@ -190,6 +193,42 @@ public function testAssertBrowserCookieValueSame() $this->getClientTester()->assertBrowserCookieValueSame('foo', 'babar', false, '/path'); } + #[RequiresMethod(History::class, 'isFirstPage')] + public function testAssertBrowserHistoryIsOnFirstPage() + { + $this->createHistoryTester('isFirstPage', true)->assertBrowserHistoryIsOnFirstPage(); + $this->expectException(AssertionFailedError::class); + $this->expectExceptionMessage('Failed asserting that the Browser history is on the first page.'); + $this->createHistoryTester('isFirstPage', false)->assertBrowserHistoryIsOnFirstPage(); + } + + #[RequiresMethod(History::class, 'isFirstPage')] + public function testAssertBrowserHistoryIsNotOnFirstPage() + { + $this->createHistoryTester('isFirstPage', false)->assertBrowserHistoryIsNotOnFirstPage(); + $this->expectException(AssertionFailedError::class); + $this->expectExceptionMessage('Failed asserting that the Browser history is not on the first page.'); + $this->createHistoryTester('isFirstPage', true)->assertBrowserHistoryIsNotOnFirstPage(); + } + + #[RequiresMethod(History::class, 'isLastPage')] + public function testAssertBrowserHistoryIsOnLastPage() + { + $this->createHistoryTester('isLastPage', true)->assertBrowserHistoryIsOnLastPage(); + $this->expectException(AssertionFailedError::class); + $this->expectExceptionMessage('Failed asserting that the Browser history is on the last page.'); + $this->createHistoryTester('isLastPage', false)->assertBrowserHistoryIsOnLastPage(); + } + + #[RequiresMethod(History::class, 'isLastPage')] + public function testAssertBrowserHistoryIsNotOnLastPage() + { + $this->createHistoryTester('isLastPage', false)->assertBrowserHistoryIsNotOnLastPage(); + $this->expectException(AssertionFailedError::class); + $this->expectExceptionMessage('Failed asserting that the Browser history is not on the last page.'); + $this->createHistoryTester('isLastPage', true)->assertBrowserHistoryIsNotOnLastPage(); + } + public function testAssertSelectorExists() { $this->getCrawlerTester(new Crawler('

'))->assertSelectorExists('body > h1'); @@ -386,6 +425,19 @@ private function getRequestTester(): WebTestCase return $this->getTester($client); } + private function createHistoryTester(string $method, bool $returnValue): WebTestCase + { + /** @var KernelBrowser&MockObject $client */ + $client = $this->createMock(KernelBrowser::class); + /** @var History&MockObject $history */ + $history = $this->createMock(History::class); + + $history->method($method)->willReturn($returnValue); + $client->method('getHistory')->willReturn($history); + + return $this->getTester($client); + } + private function getTester(KernelBrowser $client): WebTestCase { $tester = new class(method_exists($this, 'name') ? $this->name() : $this->getName()) extends WebTestCase { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index e481a965e717d..d5f5d88ebd67b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Translation; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Symfony\Component\Config\Resource\DirectoryResource; @@ -130,7 +131,7 @@ public function testInvalidOptions() new Translator(new Container(), new MessageFormatter(), 'en', [], ['foo' => 'bar']); } - /** @dataProvider getDebugModeAndCacheDirCombinations */ + #[DataProvider('getDebugModeAndCacheDirCombinations')] public function testResourceFilesOptionLoadsBeforeOtherAddedResources($debug, $enableCache) { $someCatalogue = $this->getCatalogue('some_locale', []); diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index a00bac1c3a9b5..d9d1e34f6a407 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -19,61 +19,63 @@ "php": ">=8.2", "composer-runtime-api": ">=2.1", "ext-xml": "*", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^7.2", + "symfony/cache": "^6.4.12|^7.0|^8.0", + "symfony/config": "^7.3|^8.0", + "symfony/dependency-injection": "^7.2|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^7.3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^7.2", + "symfony/error-handler": "^7.3|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^7.3|^8.0", + "symfony/http-kernel": "^7.2|^8.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "^7.1", - "symfony/finder": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/filesystem": "^7.1|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0" }, "require-dev": { "doctrine/persistence": "^1.3|^2|^3", "dragonmantank/cron-expression": "^3.1", "seld/jsonlint": "^1.10", - "symfony/asset": "^6.4|^7.0", - "symfony/asset-mapper": "^6.4|^7.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/dotenv": "^6.4|^7.0", + "symfony/asset": "^6.4|^7.0|^8.0", + "symfony/asset-mapper": "^6.4|^7.0|^8.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/dotenv": "^6.4|^7.0|^8.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/form": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/mailer": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/notifier": "^6.4|^7.0", - "symfony/object-mapper": "^v7.3.0-beta2", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/scheduler": "^6.4.4|^7.0.4", - "symfony/security-bundle": "^6.4|^7.0", - "symfony/semaphore": "^6.4|^7.0", - "symfony/serializer": "^7.2.5", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^7.3", - "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.1.8", - "symfony/validator": "^6.4|^7.0", - "symfony/workflow": "^7.3", - "symfony/yaml": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/json-streamer": "7.3.*", - "symfony/uid": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/webhook": "^7.2", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/html-sanitizer": "^6.4|^7.0|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/mailer": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/mime": "^6.4|^7.0|^8.0", + "symfony/notifier": "^6.4|^7.0|^8.0", + "symfony/object-mapper": "^7.3|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6|^8.0", + "symfony/scheduler": "^6.4.4|^7.0.4|^8.0", + "symfony/security-bundle": "^6.4|^7.0|^8.0", + "symfony/semaphore": "^6.4|^7.0|^8.0", + "symfony/serializer": "^7.2.5|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/translation": "^7.3|^8.0", + "symfony/twig-bundle": "^6.4|^7.0|^8.0", + "symfony/type-info": "^7.1.8|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/workflow": "^7.3|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", + "symfony/property-info": "^6.4|^7.0|^8.0", + "symfony/json-streamer": "^7.3|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "symfony/web-link": "^6.4|^7.0|^8.0", + "symfony/webhook": "^7.2|^8.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "twig/twig": "^3.12" }, @@ -89,12 +91,11 @@ "symfony/dom-crawler": "<6.4", "symfony/http-client": "<6.4", "symfony/form": "<6.4", - "symfony/json-streamer": ">=7.4", "symfony/lock": "<6.4", "symfony/mailer": "<6.4", "symfony/messenger": "<6.4", "symfony/mime": "<6.4", - "symfony/object-mapper": ">=7.4", + "symfony/polyfill-php83": "<1.30", "symfony/property-info": "<6.4", "symfony/property-access": "<6.4", "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", @@ -109,7 +110,7 @@ "symfony/validator": "<6.4", "symfony/web-profiler-bundle": "<6.4", "symfony/webhook": "<7.2", - "symfony/workflow": "<7.3.0-beta2" + "symfony/workflow": "<7.3" }, "autoload": { "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, @@ -117,5 +118,10 @@ "/Tests/" ] }, - "minimum-stability": "dev" + "minimum-stability": "dev", + "config": { + "allow-plugins": { + "symfony/runtime": false + } + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist index d00ee0f1e214e..90e1a751eec0a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist +++ b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -20,7 +21,7 @@ - + ./ @@ -29,5 +30,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 77aa957331bd1..b27667254503e 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -1,6 +1,30 @@ CHANGELOG ========= +7.4 +--- + + * Add options to configure a cache pool and storage service for login throttling rate limiters + * Register alias for argument for password hasher when its key is not a class name: + + With the following configuration: + ```yaml + security: + password_hashers: + recovery_code: auto + ``` + + It is possible to inject the `recovery_code` password hasher in a service: + + ```php + public function __construct( + #[Target('recovery_code')] + private readonly PasswordHasherInterface $passwordHasher, + ) { + } + ``` + * Deprecate `LazyFirewallContext::__invoke()` + 7.3 --- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php index e5994510da126..4158c96852d30 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/DebugFirewallCommand.php @@ -52,22 +52,22 @@ protected function configure(): void $this ->setHelp(<<%command.name% command displays the firewalls that are configured -in your application: + The %command.name% command displays the firewalls that are configured + in your application: - php %command.full_name% + php %command.full_name% -You can pass a firewall name to display more detailed information about -a specific firewall: + You can pass a firewall name to display more detailed information about + a specific firewall: - php %command.full_name% $exampleName + php %command.full_name% $exampleName -To include all events and event listeners for a specific firewall, use the -events option: + To include all events and event listeners for a specific firewall, use the + events option: - php %command.full_name% --events $exampleName + php %command.full_name% --events $exampleName -EOF + EOF ) ->setDefinition([ new InputArgument('name', InputArgument::OPTIONAL, \sprintf('A firewall name (for example "%s")', $exampleName)), diff --git a/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php b/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php index 45f4f498344b1..92b456278110f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php +++ b/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php @@ -88,7 +88,11 @@ protected function callListeners(RequestEvent $event, iterable $listeners): void } foreach ($requestListeners as $listener) { - $listener($event); + if (!$listener instanceof FirewallListenerInterface) { + $listener($event); + } elseif (false !== $listener->supports($event->getRequest())) { + $listener->authenticate($event); + } if ($event->hasResponse()) { break; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php index 38d89b476cc99..cc318db3ee450 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php @@ -38,7 +38,7 @@ public function process(ContainerBuilder $container): void $domainRegexp = (empty($sessionOptions['cookie_secure']) ? 'https?://' : 'https://').$domainRegexp; } - $container->findDefinition('security.http_utils') + $container->getDefinition('security.http_utils') ->addArgument(\sprintf('{^%s$}i', $domainRegexp)) ->addArgument($secureDomainRegexp); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php index 93818f5aa4c04..c981e7802a5d5 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginThrottlingFactory.php @@ -21,6 +21,7 @@ use Symfony\Component\HttpFoundation\RateLimiter\RequestRateLimiterInterface; use Symfony\Component\Lock\LockInterface; use Symfony\Component\RateLimiter\RateLimiterFactory; +use Symfony\Component\RateLimiter\RateLimiterFactoryInterface; use Symfony\Component\RateLimiter\Storage\CacheStorage; use Symfony\Component\Security\Http\RateLimiter\DefaultLoginRateLimiter; @@ -53,6 +54,8 @@ public function addConfiguration(NodeDefinition $builder): void ->integerNode('max_attempts')->defaultValue(5)->end() ->scalarNode('interval')->defaultValue('1 minute')->end() ->scalarNode('lock_factory')->info('The service ID of the lock factory used by the login rate limiter (or null to disable locking).')->defaultNull()->end() + ->stringNode('cache_pool')->info('The cache pool to use for storing the limiter state')->defaultValue('cache.rate_limiter')->end() + ->stringNode('storage_service')->info('The service ID of a custom storage implementation, this precedes any configured "cache_pool"')->defaultNull()->end() ->end(); } @@ -68,6 +71,8 @@ public function createAuthenticator(ContainerBuilder $container, string $firewal 'limit' => $config['max_attempts'], 'interval' => $config['interval'], 'lock_factory' => $config['lock_factory'], + 'cache_pool' => $config['cache_pool'], + 'storage_service' => $config['storage_service'], ]; $this->registerRateLimiter($container, $localId = '_login_local_'.$firewallName, $limiterOptions); @@ -91,9 +96,6 @@ public function createAuthenticator(ContainerBuilder $container, string $firewal private function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig): void { - // default configuration (when used by other DI extensions) - $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter']; - $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')); if (null !== $limiterConfig['lock_factory']) { @@ -115,6 +117,14 @@ private function registerRateLimiter(ContainerBuilder $container, string $name, $limiterConfig['id'] = $name; $limiter->replaceArgument(0, $limiterConfig); - $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter'); + $factoryAlias = $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter'); + + if (interface_exists(RateLimiterFactoryInterface::class)) { + $container->registerAliasForArgument($limiterId, RateLimiterFactoryInterface::class, $name.'.limiter', $name); + + $factoryAlias->setDeprecated('symfony/security-bundle', '7.4', 'The "%alias_id%" autowiring alias is deprecated and will be removed in 8.0, use "RateLimiterFactoryInterface" instead.'); + $container->getAlias(\sprintf('.%s $%s.limiter', RateLimiterFactory::class, $name)) + ->setDeprecated('symfony/security-bundle', '7.4', 'The "%alias_id%" autowiring alias is deprecated and will be removed in 8.0, use "RateLimiterFactoryInterface" instead.'); + } } } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 1711964b3472f..c349a55cd94a9 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -49,6 +49,7 @@ use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher; use Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher; use Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher; +use Symfony\Component\PasswordHasher\PasswordHasherInterface; use Symfony\Component\Routing\Loader\ContainerLoader; use Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy; use Symfony\Component\Security\Core\Authorization\Strategy\ConsensusStrategy; @@ -156,6 +157,8 @@ public function load(array $configs, ContainerBuilder $container): void } $container->setParameter('security.authentication.hide_user_not_found', ExposeSecurityLevel::All !== $config['expose_security_errors']); + $container->deprecateParameter('security.authentication.hide_user_not_found', 'symfony/security-bundle', '7.4'); + $container->setParameter('.security.authentication.expose_security_errors', $config['expose_security_errors']); if (class_exists(Application::class)) { @@ -706,6 +709,17 @@ private function createHashers(array $hashers, ContainerBuilder $container): voi $hasherMap = []; foreach ($hashers as $class => $hasher) { $hasherMap[$class] = $this->createHasher($hasher); + // The key is not a class, so we register an alias for argument to + // ease getting the hasher + if (!class_exists($class) && !interface_exists($class)) { + $id = 'security.password_hasher.'.$class; + $container + ->register($id, PasswordHasherInterface::class) + ->setFactory([new Reference('security.password_hasher_factory'), 'getPasswordHasher']) + ->setArgument(0, $class) + ; + $container->registerAliasForArgument($id, PasswordHasherInterface::class, $class); + } } $container diff --git a/src/Symfony/Bundle/SecurityBundle/Security/LazyFirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/LazyFirewallContext.php index 6835762315415..09526fde6c5cd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/LazyFirewallContext.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/LazyFirewallContext.php @@ -11,9 +11,11 @@ namespace Symfony\Bundle\SecurityBundle\Security; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Http\Event\LazyResponseEvent; +use Symfony\Component\Security\Http\Firewall\AbstractListener; use Symfony\Component\Security\Http\Firewall\ExceptionListener; use Symfony\Component\Security\Http\Firewall\FirewallListenerInterface; use Symfony\Component\Security\Http\Firewall\LogoutListener; @@ -23,7 +25,7 @@ * * @author Nicolas Grekas */ -class LazyFirewallContext extends FirewallContext +class LazyFirewallContext extends FirewallContext implements FirewallListenerInterface { public function __construct( iterable $listeners, @@ -40,19 +42,26 @@ public function getListeners(): iterable return [$this]; } - public function __invoke(RequestEvent $event): void + public function supports(Request $request): ?bool + { + return true; + } + + public function authenticate(RequestEvent $event): void { $listeners = []; $request = $event->getRequest(); $lazy = $request->isMethodCacheable(); foreach (parent::getListeners() as $listener) { - if (!$lazy || !$listener instanceof FirewallListenerInterface) { + if (!$listener instanceof FirewallListenerInterface) { + trigger_deprecation('symfony/security-http', '7.4', 'Using a callable as firewall listener is deprecated, extend "%s" or implement "%s" instead.', AbstractListener::class, FirewallListenerInterface::class); + $listeners[] = $listener; - $lazy = $lazy && $listener instanceof FirewallListenerInterface; + $lazy = false; } elseif (false !== $supports = $listener->supports($request)) { $listeners[] = [$listener, 'authenticate']; - $lazy = null === $supports; + $lazy = $lazy && null === $supports; } } @@ -75,4 +84,19 @@ public function __invoke(RequestEvent $event): void } }); } + + public static function getPriority(): int + { + return 0; + } + + /** + * @deprecated since Symfony 7.4, to be removed in 8.0 + */ + public function __invoke(RequestEvent $event): void + { + trigger_deprecation('symfony/security-bundle', '7.4', 'The "%s()" method is deprecated since Symfony 7.4 and will be removed in 8.0.', __METHOD__); + + $this->authenticate($event); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index 1433b5c90e001..d8b8aeceb2e51 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -88,7 +88,7 @@ public function build(ContainerBuilder $container): void $extension->addUserProviderFactory(new LdapFactory()); $container->addCompilerPass(new AddExpressionLanguageProvidersPass()); $container->addCompilerPass(new AddSecurityVotersPass()); - $container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING); + $container->addCompilerPass(new AddSessionDomainConstraintPass()); $container->addCompilerPass(new CleanRememberMeVerifierPass()); $container->addCompilerPass(new RegisterCsrfFeaturesPass()); $container->addCompilerPass(new RegisterTokenUsageTrackingPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 200); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Command/DebugFirewallCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Command/DebugFirewallCommandTest.php new file mode 100644 index 0000000000000..673f0c434a4bc --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Command/DebugFirewallCommandTest.php @@ -0,0 +1,197 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand; +use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; +use Symfony\Bundle\SecurityBundle\Security\FirewallContext; +use Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; + +class DebugFirewallCommandTest extends TestCase +{ + public function testFirewallListOutputMatchesFixture() + { + $firewallNames = ['main', 'api']; + $contexts = $this->createMock(ContainerInterface::class); + $eventDispatchers = $this->createMock(ContainerInterface::class); + + $command = new DebugFirewallCommand($firewallNames, $contexts, $eventDispatchers, []); + $tester = new CommandTester($command); + + $this->assertSame(0, $tester->execute([])); + $this->assertStringContainsString('Firewalls', $tester->getDisplay()); + $this->assertStringContainsString('The following firewalls are defined:', $tester->getDisplay()); + $this->assertStringContainsString('* main', $tester->getDisplay()); + $this->assertStringContainsString('* api', $tester->getDisplay()); + $this->assertStringContainsString('To view details of a specific firewall', $tester->getDisplay()); + } + + public function testFirewallNotFoundDisplaysError() + { + $firewallNames = ['main', 'api']; + + $contexts = $this->createMock(ContainerInterface::class); + $contexts->method('has')->willReturn(false); + + $eventDispatchers = $this->createMock(ContainerInterface::class); + $authenticators = []; + + $command = new DebugFirewallCommand( + $firewallNames, + $contexts, + $eventDispatchers, + $authenticators + ); + + $tester = new CommandTester($command); + + $this->assertSame(1, $tester->execute(['name' => 'admin'])); + $this->assertStringContainsString('Firewall admin was not found.', $tester->getDisplay()); + $this->assertStringContainsString('Available firewalls are: main, api', $tester->getDisplay()); + } + + public function testFirewallMainOutputMatchesFixture() + { + $firewallNames = ['main']; + + $config = new FirewallConfig( + name: 'main', + userChecker: 'user_checker_service', + requestMatcher: null, + securityEnabled: true, + stateless: false, + provider: 'user_provider_service', + context: 'main', + entryPoint: 'entry_point_service', + accessDeniedHandler: 'access_denied_handler_service', + accessDeniedUrl: '/access-denied', + authenticators: [], + switchUser: null + ); + + $context = new FirewallContext([], config: $config); + + $contexts = $this->createMock(ContainerInterface::class); + $contexts->method('has')->willReturn(true); + $contexts->method('get')->willReturn($context); + + $eventDispatchers = $this->createMock(ContainerInterface::class); + $authenticator = new DummyAuthenticator(); + $authenticators = ['main' => [$authenticator]]; + + $command = new DebugFirewallCommand($firewallNames, $contexts, $eventDispatchers, $authenticators); + $tester = new CommandTester($command); + + $this->assertSame(0, $tester->execute(['name' => 'main', '--events' => true])); + $this->assertEquals($this->getFixtureOutput('firewall_main_output.txt'), trim(str_replace(\PHP_EOL, "\n", $tester->getDisplay()))); + } + + public function testFirewallWithEventsOutputMatchesFixture() + { + $firewallNames = ['main']; + + $config = new FirewallConfig( + name: 'main', + userChecker: 'user_checker_service', + context: 'main', + stateless: false, + provider: 'user_provider_service', + entryPoint: 'entry_point_service', + accessDeniedHandler: 'access_denied_handler_service', + accessDeniedUrl: '/access-denied', + ); + + $context = new FirewallContext([], config: $config); + + $contexts = $this->createMock(ContainerInterface::class); + $contexts->method('has')->willReturn(true); + $contexts->method('get')->willReturn($context); + + $dispatcher = $this->createMock(EventDispatcherInterface::class); + $listener = fn () => null; + $listenerTwo = fn (int $number) => $number * 2; + $dispatcher->method('getListeners')->willReturn([ + 'security.event' => [$listener, $listenerTwo], + ]); + $dispatcher->method('getListenerPriority')->willReturn(42); + + $eventDispatchers = $this->createMock(ContainerInterface::class); + $eventDispatchers->method('has')->willReturn(true); + $eventDispatchers->method('get')->willReturn($dispatcher); + + $authenticator = new DummyAuthenticator(); + $authenticatorTwo = new DummyAuthenticator(); + $authenticatorThree = new DummyAuthenticator(); + $authenticators = ['main' => [$authenticator, $authenticatorTwo], 'api' => [$authenticatorThree]]; + + $command = new DebugFirewallCommand($firewallNames, $contexts, $eventDispatchers, $authenticators); + $tester = new CommandTester($command); + + $this->assertSame(0, $tester->execute(['name' => 'main', '--events' => true])); + $this->assertEquals($this->getFixtureOutput('firewall_main_with_events_output.txt'), trim(str_replace(\PHP_EOL, "\n", $tester->getDisplay()))); + } + + public function testFirewallWithSwitchUserDisplaysSection() + { + $firewallNames = ['main']; + + $switchUserConfig = [ + 'parameter' => '_switch_user_test', + 'provider' => 'custom_provider_test', + 'role' => 'ROLE_ALLOWED_TO_SWITCH', + ]; + + $config = new FirewallConfig( + name: 'main', + userChecker: 'user_checker_service_test', + context: 'main', + stateless: false, + provider: 'user_provider_service_test', + entryPoint: 'entry_point_service_test', + accessDeniedHandler: 'access_denied_handler_service_test', + accessDeniedUrl: '/access-denied-test', + switchUser: $switchUserConfig, + ); + + $context = new FirewallContext([], config: $config); + + $contexts = $this->createMock(ContainerInterface::class); + $contexts->method('has')->willReturn(true); + $contexts->method('get')->willReturn($context); + + $eventDispatchers = $this->createMock(ContainerInterface::class); + $authenticator = new DummyAuthenticator(); + $authenticatorTwo = $this->createMock(AuthenticatorInterface::class); + $authenticators = ['main' => [$authenticator], 'api' => [$authenticatorTwo]]; + + $command = new DebugFirewallCommand( + $firewallNames, + $contexts, + $eventDispatchers, + $authenticators + ); + $tester = new CommandTester($command); + + $this->assertSame(0, $tester->execute(['name' => 'main'])); + $this->assertEquals($this->getFixtureOutput('firewall_main_with_switch_user.txt'), trim(str_replace(\PHP_EOL, "\n", $tester->getDisplay()))); + } + + private function getFixtureOutput(string $file): string + { + return trim(file_get_contents(__DIR__.'/../Fixtures/Descriptor/'.$file)); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php index 5528c9b7a8fc7..d7a468c2d462d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DataCollector; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector; use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; @@ -32,6 +34,7 @@ use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Role\RoleHierarchy; use Symfony\Component\Security\Core\User\InMemoryUser; +use Symfony\Component\Security\Http\Firewall\AbstractListener; use Symfony\Component\Security\Http\FirewallMapInterface; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; use Symfony\Component\VarDumper\Caster\ClassStub; @@ -77,7 +80,7 @@ public function testCollectWhenAuthenticationTokenIsNull() $this->assertNull($collector->getFirewall()); } - /** @dataProvider provideRoles */ + #[DataProvider('provideRoles')] public function testCollectAuthenticationTokenAndRoles(array $roles, array $normalizedRoles, array $inheritedRoles) { $tokenStorage = new TokenStorage(); @@ -185,16 +188,24 @@ public function testGetFirewallReturnsNull() $this->assertNull($collector->getFirewall()); } - /** - * @group time-sensitive - */ + #[Group('time-sensitive')] public function testGetListeners() { $request = new Request(); $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MAIN_REQUEST); $event->setResponse($response = new Response()); - $listener = function ($e) use ($event, &$listenerCalled) { - $listenerCalled += $e === $event; + $listener = new class extends AbstractListener { + public int $callCount = 0; + + public function supports(Request $request): ?bool + { + return true; + } + + public function authenticate(RequestEvent $event): void + { + ++$this->callCount; + } }; $firewallMap = $this ->getMockBuilder(FirewallMap::class) @@ -217,9 +228,9 @@ public function testGetListeners() $collector = new SecurityDataCollector(null, null, null, null, $firewallMap, $firewall, true); $collector->collect($request, $response); - $this->assertNotEmpty($collected = $collector->getListeners()[0]); + $this->assertCount(1, $collector->getListeners()); $collector->lateCollect(); - $this->assertSame(1, $listenerCalled); + $this->assertSame(1, $listener->callCount); } public function testCollectCollectsDecisionLogWhenStrategyIsAffirmative() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php index 4ab483a28f38a..898517d0c8dd7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Debug; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; use Symfony\Bundle\SecurityBundle\Security\FirewallMap; @@ -29,21 +30,30 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; +use Symfony\Component\Security\Http\Firewall\AbstractListener; use Symfony\Component\Security\Http\Firewall\AuthenticatorManagerListener; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; -/** - * @group time-sensitive - */ +#[Group('time-sensitive')] class TraceableFirewallListenerTest extends TestCase { public function testOnKernelRequestRecordsListeners() { $request = new Request(); $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MAIN_REQUEST); - $event->setResponse($response = new Response()); - $listener = function ($e) use ($event, &$listenerCalled) { - $listenerCalled += $e === $event; + $event->setResponse(new Response()); + $listener = new class extends AbstractListener { + public int $callCount = 0; + + public function supports(Request $request): ?bool + { + return true; + } + + public function authenticate(RequestEvent $event): void + { + ++$this->callCount; + } }; $firewallMap = $this->createMock(FirewallMap::class); $firewallMap diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php index cf8527589ee2c..d94b34f4ef5c5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php @@ -145,7 +145,7 @@ private function createContainer($sessionStorageOptions) ]; $ext = new FrameworkExtension(); - $ext->load(['framework' => ['annotations' => false, 'http_method_override' => false, 'handle_all_throwables' => true, 'php_errors' => ['log' => true], 'csrf_protection' => false, 'router' => ['resource' => 'dummy', 'utf8' => true]]], $container); + $ext->load(['framework' => ['http_method_override' => false, 'handle_all_throwables' => true, 'php_errors' => ['log' => true], 'csrf_protection' => false, 'router' => ['resource' => 'dummy', 'utf8' => true]]], $container); $ext = new SecurityExtension(); $ext->load($config, $container); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPassTest.php index e6567e67d6f7d..bc95ab1f47db1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPassTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Compiler; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; use Symfony\Bundle\SecurityBundle\SecurityBundle; @@ -50,9 +51,7 @@ protected function setUp(): void $securityBundle->build($this->container); } - /** - * @dataProvider providePropagatedEvents - */ + #[DataProvider('providePropagatedEvents')] public function testEventIsPropagated(string $configuredEvent, string $registeredEvent) { $this->container->loadFromExtension('security', [ diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php index 6904a21b18113..4bf0429b97f53 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php @@ -11,8 +11,10 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Bundle\SecurityBundle\DependencyInjection\MainConfiguration; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; @@ -21,8 +23,6 @@ class MainConfigurationTest extends TestCase { - use ExpectUserDeprecationMessageTrait; - /** * The minimal, required config needed to not have any required validation * issues. @@ -233,9 +233,7 @@ public function testFirewalls() $configuration->getConfigTreeBuilder(); } - /** - * @dataProvider provideHideUserNotFoundData - */ + #[DataProvider('provideHideUserNotFoundData')] public function testExposeSecurityErrors(array $config, ExposeSecurityLevel $expectedExposeSecurityErrors) { $config = array_merge(static::$minimalConfig, $config); @@ -259,11 +257,9 @@ public static function provideHideUserNotFoundData(): iterable yield [['expose_security_errors' => 'all'], ExposeSecurityLevel::All]; } - /** - * @dataProvider provideHideUserNotFoundLegacyData - * - * @group legacy - */ + #[DataProvider('provideHideUserNotFoundLegacyData')] + #[IgnoreDeprecations] + #[Group('legacy')] public function testExposeSecurityErrorsWithLegacyConfig(array $config, ExposeSecurityLevel $expectedExposeSecurityErrors, ?bool $expectedHideUserNotFound) { $this->expectUserDeprecationMessage('Since symfony/security-bundle 7.3: The "hide_user_not_found" option is deprecated and will be removed in 8.0. Use the "expose_security_errors" option instead.'); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php index be300e7526b82..2cce3b1fb69ab 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Security\Factory; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -25,9 +26,7 @@ protected function setUp(): void $this->container = new ContainerBuilder(); } - /** - * @dataProvider getFailureHandlers - */ + #[DataProvider('getFailureHandlers')] public function testDefaultFailureHandler($serviceId, $defaultHandlerInjection) { $options = [ @@ -68,9 +67,7 @@ public static function getFailureHandlers() ]; } - /** - * @dataProvider getSuccessHandlers - */ + #[DataProvider('getSuccessHandlers')] public function testDefaultSuccessHandler($serviceId, $defaultHandlerInjection) { $options = [ diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php index 88b782363dbf9..dc6c03bbd5e16 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Security\Factory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken\CasTokenHandlerFactory; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\AccessToken\OAuth2TokenHandlerFactory; @@ -183,13 +186,12 @@ public function testInvalidOidcTokenHandlerConfigurationMissingAlgorithmParamete $this->processConfig($config, $factory); } - /** - * @group legacy - * - * @expectedDeprecation Since symfony/security-bundle 7.1: The "key" option is deprecated and will be removed in 8.0. Use the "keyset" option instead. - */ + #[IgnoreDeprecations] + #[Group('legacy')] public function testOidcTokenHandlerConfigurationWithSingleAlgorithm() { + $this->expectUserDeprecationMessage('Since symfony/security-bundle 7.1: The "key" option is deprecated and will be removed in 8.0. Use the "keyset" option instead.'); + $container = new ContainerBuilder(); $jwk = '{"kty":"EC","crv":"P-256","x":"0QEAsI1wGI-dmYatdUZoWSRWggLEpyzopuhwk-YUnA4","y":"KYl-qyZ26HobuYwlQh-r0iHX61thfP82qqEku7i0woo","d":"iA_TV2zvftni_9aFAQwFO_9aypfJFCSpcCyevDvz220"}'; $config = [ @@ -421,9 +423,7 @@ public function testOidcUserInfoTokenHandlerConfigurationWithExistingClient() $this->assertEquals($expected, $container->getDefinition('security.access_token_handler.firewall1')->getArguments()); } - /** - * @dataProvider getOidcUserInfoConfiguration - */ + #[DataProvider('getOidcUserInfoConfiguration')] public function testOidcUserInfoTokenHandlerConfigurationWithBaseUri(array|string $configuration) { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 8607e45a262e2..7a9feccee1eb8 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FirewallListenerFactoryInterface; @@ -29,6 +30,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestMatcher\PathRequestMatcher; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\PasswordHasher\PasswordHasherInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\InMemoryUserChecker; @@ -277,7 +279,7 @@ public function testRegisterAccessControlWithSpecifiedRequestMatcherService() $this->assertSame($requestMatcherId, (string) $args[0]); } - /** @dataProvider provideAdditionalRequestMatcherConstraints */ + #[DataProvider('provideAdditionalRequestMatcherConstraints')] public function testRegisterAccessControlWithRequestMatcherAndAdditionalOptionsThrowsInvalidException(array $additionalConstraints) { $container = $this->getRawContainer(); @@ -476,9 +478,7 @@ public function testDoNotRegisterTheUserProviderAliasWithMultipleProviders() $this->assertFalse($container->has(UserProviderInterface::class)); } - /** - * @dataProvider acceptableIpsProvider - */ + #[DataProvider('acceptableIpsProvider')] public function testAcceptableAccessControlIps($ips) { $container = $this->getRawContainer(); @@ -663,9 +663,7 @@ public static function provideEntryPointFirewalls(): iterable ], 'security.authenticator.guard.main.0']; } - /** - * @dataProvider provideEntryPointRequiredData - */ + #[DataProvider('provideEntryPointRequiredData')] public function testEntryPointRequired(array $firewall, string $messageRegex) { $container = $this->getRawContainer(); @@ -694,9 +692,7 @@ public static function provideEntryPointRequiredData(): iterable ]; } - /** - * @dataProvider provideConfigureCustomAuthenticatorData - */ + #[DataProvider('provideConfigureCustomAuthenticatorData')] public function testConfigureCustomAuthenticator(array $firewall, array $expectedAuthenticators) { $container = $this->getRawContainer(); @@ -769,9 +765,7 @@ public function testCompilesWithSessionListenerWithStatefulllFirewallWithAuthent $this->assertTrue($container->has('security.listener.session.'.$firewallId)); } - /** - * @dataProvider provideUserCheckerConfig - */ + #[DataProvider('provideUserCheckerConfig')] public function testUserCheckerWithAuthenticatorManager(array $config, string $expectedUserCheckerClass) { $container = $this->getRawContainer(); @@ -883,7 +877,7 @@ public function testCustomHasherWithMigrateFrom() $container->loadFromExtension('security', [ 'password_hashers' => [ 'legacy' => 'md5', - 'App\User' => [ + TestUserChecker::class => [ 'id' => 'App\Security\CustomHasher', 'migrate_from' => 'legacy', ], @@ -895,11 +889,19 @@ public function testCustomHasherWithMigrateFrom() $hashersMap = $container->getDefinition('security.password_hasher_factory')->getArgument(0); - $this->assertArrayHasKey('App\User', $hashersMap); - $this->assertEquals($hashersMap['App\User'], [ + $this->assertArrayHasKey(TestUserChecker::class, $hashersMap); + $this->assertEquals($hashersMap[TestUserChecker::class], [ 'instance' => new Reference('App\Security\CustomHasher'), 'migrate_from' => ['legacy'], ]); + + $legacyAlias = \sprintf('%s $%s', PasswordHasherInterface::class, 'legacy'); + $this->assertTrue($container->hasAlias($legacyAlias)); + $definition = $container->getDefinition((string) $container->getAlias($legacyAlias)); + $this->assertSame(PasswordHasherInterface::class, $definition->getClass()); + + $this->assertFalse($container->hasAlias(\sprintf('%s $%s', PasswordHasherInterface::class, 'symfonyBundleSecurityBundleTestsDependencyInjectionTestUserChecker'))); + $this->assertFalse($container->hasAlias(\sprintf('.%s $%s', PasswordHasherInterface::class, TestUserChecker::class))); } public function testAuthenticatorsDecoration() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomAuthenticatorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomAuthenticatorTest.php index e57cda13ff78d..a473d8d19b829 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomAuthenticatorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomAuthenticatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\Authenticator\CustomAuthenticator; @@ -20,9 +21,7 @@ class XmlCustomAuthenticatorTest extends TestCase { - /** - * @dataProvider provideXmlConfigurationFile - */ + #[DataProvider('provideXmlConfigurationFile')] public function testCustomProviderElement(string $configurationFile) { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomProviderTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomProviderTest.php index a3f59fc299a24..a79e74a9f50e9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomProviderTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/XmlCustomProviderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\CustomProvider; @@ -20,9 +21,7 @@ class XmlCustomProviderTest extends TestCase { - /** - * @dataProvider provideXmlConfigurationFile - */ + #[DataProvider('provideXmlConfigurationFile')] public function testCustomProviderElement(string $configurationFile) { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_output.txt b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_output.txt new file mode 100644 index 0000000000000..d224162575d45 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_output.txt @@ -0,0 +1,30 @@ +Firewall "main" +=============== + + ----------------------- ------------------------------- + Option Value + ----------------------- ------------------------------- + Name main + Context main + Lazy No + Stateless No + User Checker user_checker_service + Provider user_provider_service + Entry Point entry_point_service + Access Denied URL /access-denied + Access Denied Handler access_denied_handler_service + ----------------------- ------------------------------- + +Event listeners for firewall "main" +=================================== + + No event dispatcher has been registered for this firewall. + +Authenticators for firewall "main" +================================== + + ----------------------------------------------------------------- + Classname + ----------------------------------------------------------------- + Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator + ----------------------------------------------------------------- diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_with_events_output.txt b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_with_events_output.txt new file mode 100644 index 0000000000000..2d02f34b8a017 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_with_events_output.txt @@ -0,0 +1,39 @@ +Firewall "main" +=============== + + ----------------------- ------------------------------- + Option Value + ----------------------- ------------------------------- + Name main + Context main + Lazy No + Stateless No + User Checker user_checker_service + Provider user_provider_service + Entry Point entry_point_service + Access Denied URL /access-denied + Access Denied Handler access_denied_handler_service + ----------------------- ------------------------------- + +Event listeners for firewall "main" +=================================== + +"security.event" event +---------------------- + + ------- ----------- ---------- + Order Callable Priority + ------- ----------- ---------- + #1 Closure() 42 + #2 Closure() 42 + ------- ----------- ---------- + +Authenticators for firewall "main" +================================== + + ----------------------------------------------------------------- + Classname + ----------------------------------------------------------------- + Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator + Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator + ----------------------------------------------------------------- diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_with_switch_user.txt b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_with_switch_user.txt new file mode 100644 index 0000000000000..4843b86f7e224 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/Descriptor/firewall_main_with_switch_user.txt @@ -0,0 +1,36 @@ +Firewall "main" +=============== + + ----------------------- ------------------------------------ + Option Value + ----------------------- ------------------------------------ + Name main + Context main + Lazy No + Stateless No + User Checker user_checker_service_test + Provider user_provider_service_test + Entry Point entry_point_service_test + Access Denied URL /access-denied-test + Access Denied Handler access_denied_handler_service_test + ----------------------- ------------------------------------ + +User switching +-------------- + + ----------- ------------------------ + Option Value + ----------- ------------------------ + Parameter _switch_user_test + Provider custom_provider_test + User Role ROLE_ALLOWED_TO_SWITCH + ----------- ------------------------ + +Authenticators for firewall "main" +================================== + + ----------------------------------------------------------------- + Classname + ----------------------------------------------------------------- + Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator + ----------------------------------------------------------------- diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/DummyAuthenticator.php b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/DummyAuthenticator.php new file mode 100644 index 0000000000000..8ac51a1e9df56 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Fixtures/DummyAuthenticator.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Fixtures; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; +use Symfony\Component\Security\Http\Authenticator\Passport\Passport; +use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface; + +class DummyAuthenticator implements AuthenticatorInterface +{ + public function supports(Request $request): ?bool + { + return null; + } + + public function authenticate(Request $request): Passport + { + } + + public function createToken(Passport $passport, string $firewallName): TokenInterface + { + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + return null; + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response + { + return null; + } + + public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface + { + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AccessTokenTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AccessTokenTest.php index 75adf296110da..7a2dc8474b8f9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AccessTokenTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AccessTokenTest.php @@ -20,6 +20,8 @@ use Jose\Component\Signature\Algorithm\ES256; use Jose\Component\Signature\JWSBuilder; use Jose\Component\Signature\Serializer\CompactSerializer as JwsCompactSerializer; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; @@ -63,9 +65,7 @@ public function testDefaultFormEncodedBodySuccess() $this->assertSame(['message' => 'Welcome @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider defaultFormEncodedBodyFailureData - */ + #[DataProvider('defaultFormEncodedBodyFailureData')] public function testDefaultFormEncodedBodyFailure(array $parameters, array $headers) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_body_default.yml']); @@ -99,9 +99,7 @@ public function testCustomFormEncodedBodySuccess() $this->assertSame(['message' => 'Good game @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider customFormEncodedBodyFailure - */ + #[DataProvider('customFormEncodedBodyFailure')] public function testCustomFormEncodedBodyFailure(array $parameters, array $headers) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_body_custom.yml']); @@ -156,9 +154,7 @@ public function testMultipleAccessTokenExtractorSuccess() $this->assertSame(['message' => 'Welcome @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider defaultHeaderAccessTokenFailureData - */ + #[DataProvider('defaultHeaderAccessTokenFailureData')] public function testDefaultHeaderAccessTokenFailure(array $headers) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_header_default.yml']); @@ -171,9 +167,7 @@ public function testDefaultHeaderAccessTokenFailure(array $headers) $this->assertSame('Bearer realm="My API",error="invalid_token",error_description="Invalid credentials."', $response->headers->get('WWW-Authenticate')); } - /** - * @dataProvider defaultMissingHeaderAccessTokenFailData - */ + #[DataProvider('defaultMissingHeaderAccessTokenFailData')] public function testDefaultMissingHeaderAccessTokenFail(array $headers) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_header_default.yml']); @@ -195,9 +189,7 @@ public function testCustomHeaderAccessTokenSuccess() $this->assertSame(['message' => 'Good game @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider customHeaderAccessTokenFailure - */ + #[DataProvider('customHeaderAccessTokenFailure')] public function testCustomHeaderAccessTokenFailure(array $headers, int $errorCode) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_header_custom.yml']); @@ -209,9 +201,7 @@ public function testCustomHeaderAccessTokenFailure(array $headers, int $errorCod $this->assertFalse($response->headers->has('WWW-Authenticate')); } - /** - * @dataProvider customMissingHeaderAccessTokenShouldFail - */ + #[DataProvider('customMissingHeaderAccessTokenShouldFail')] public function testCustomMissingHeaderAccessTokenShouldFail(array $headers) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_header_custom.yml']); @@ -256,9 +246,7 @@ public function testDefaultQueryAccessTokenSuccess() $this->assertSame(['message' => 'Welcome @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider defaultQueryAccessTokenFailureData - */ + #[DataProvider('defaultQueryAccessTokenFailureData')] public function testDefaultQueryAccessTokenFailure(string $query) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_query_default.yml']); @@ -292,9 +280,7 @@ public function testCustomQueryAccessTokenSuccess() $this->assertSame(['message' => 'Good game @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider customQueryAccessTokenFailure - */ + #[DataProvider('customQueryAccessTokenFailure')] public function testCustomQueryAccessTokenFailure(string $query) { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_query_custom.yml']); @@ -351,11 +337,8 @@ public function testCustomUserLoader() $this->assertSame(['message' => 'Welcome @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider validAccessTokens - * - * @requires extension openssl - */ + #[DataProvider('validAccessTokens')] + #[RequiresPhpExtension('openssl')] public function testOidcSuccess(callable $tokenFactory) { try { @@ -373,11 +356,8 @@ public function testOidcSuccess(callable $tokenFactory) $this->assertSame(['message' => 'Welcome @dunglas!'], json_decode($response->getContent(), true)); } - /** - * @dataProvider invalidAccessTokens - * - * @requires extension openssl - */ + #[DataProvider('invalidAccessTokens')] + #[RequiresPhpExtension('openssl')] public function testOidcFailure(callable $tokenFactory) { try { @@ -395,9 +375,7 @@ public function testOidcFailure(callable $tokenFactory) $this->assertSame('Bearer realm="My API",error="invalid_token",error_description="Invalid credentials."', $response->headers->get('WWW-Authenticate')); } - /** - * @requires extension openssl - */ + #[RequiresPhpExtension('openssl')] public function testOidcFailureWithJweEnforced() { $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_oidc_jwe.yml']); @@ -421,13 +399,13 @@ public function testOidcFailureWithJweEnforced() public function testCasSuccess() { $casResponse = new MockResponse(<< - - dunglas - PGTIOU-84678-8a9d - - - BODY + + + dunglas + PGTIOU-84678-8a9d + + + BODY ); $client = $this->createClient(['test_case' => 'AccessToken', 'root_config' => 'config_cas.yml']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php index b78f262cf5502..0efab553d1691 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticatorTest.php @@ -11,11 +11,11 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; + class AuthenticatorTest extends AbstractWebTestCase { - /** - * @dataProvider provideEmails - */ + #[DataProvider('provideEmails')] public function testFirewallUserProvider($email, $withinFirewall) { $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'firewall_user_provider.yml']); @@ -31,10 +31,8 @@ public function testFirewallUserProvider($email, $withinFirewall) } } - /** - * @dataProvider provideEmails - */ - public function testWithoutUserProvider($email) + #[DataProvider('provideEmails')] + public function testWithoutUserProvider($email, $withinFirewall) { $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'no_user_provider.yml']); @@ -51,9 +49,7 @@ public static function provideEmails(): iterable yield ['john@example.org', false]; } - /** - * @dataProvider provideEmailsWithFirewalls - */ + #[DataProvider('provideEmailsWithFirewalls')] public function testLoginUsersWithMultipleFirewalls(string $username, string $firewallContext) { $client = $this->createClient(['test_case' => 'Authenticator', 'root_config' => 'multiple_firewall_user_provider.yml']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php index ee8cc60a4edd5..68c6b5d1c596b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Response; @@ -19,9 +20,7 @@ class CsrfFormLoginTest extends AbstractWebTestCase { - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLoginAndLogoutWithCsrfTokens($options) { $client = $this->createClient($options); @@ -56,9 +55,7 @@ public function testFormLoginAndLogoutWithCsrfTokens($options) }); } - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLoginWithInvalidCsrfToken($options) { $client = $this->createClient($options); @@ -83,9 +80,7 @@ public function testFormLoginWithInvalidCsrfToken($options) }); } - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLoginWithCustomTargetPath($options) { $client = $this->createClient($options); @@ -103,9 +98,7 @@ public function testFormLoginWithCustomTargetPath($options) $this->assertStringContainsString('You\'re browsing to path "/foo".', $text); } - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLoginRedirectsToProtectedResourceAfterLogin($options) { $client = $this->createClient($options); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php index f6957f45a87b4..9b144664503a9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php @@ -11,11 +11,12 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; + class FormLoginTest extends AbstractWebTestCase { - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLogin(array $options) { $client = $this->createClient($options); @@ -32,9 +33,7 @@ public function testFormLogin(array $options) $this->assertStringContainsString('You\'re browsing to path "/profile".', $text); } - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLogout(array $options) { $client = $this->createClient($options); @@ -65,9 +64,7 @@ public function testFormLogout(array $options) $this->assertSame($logoutLinks[1]->getUri(), $logoutLinks[5]->getUri()); } - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLoginWithCustomTargetPath(array $options) { $client = $this->createClient($options); @@ -85,9 +82,7 @@ public function testFormLoginWithCustomTargetPath(array $options) $this->assertStringContainsString('You\'re browsing to path "/foo".', $text); } - /** - * @dataProvider provideClientOptions - */ + #[DataProvider('provideClientOptions')] public function testFormLoginRedirectsToProtectedResourceAfterLogin(array $options) { $client = $this->createClient($options); @@ -106,9 +101,7 @@ public function testFormLoginRedirectsToProtectedResourceAfterLogin(array $optio $this->assertStringContainsString('You\'re browsing to path "/protected_resource".', $text); } - /** - * @group time-sensitive - */ + #[Group('time-sensitive')] public function testLoginThrottling() { $client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'login_throttling.yml']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginLdapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginLdapTest.php index f11908299834f..e0e71291c5950 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginLdapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginLdapTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter; use Symfony\Component\Ldap\Adapter\QueryInterface; use Symfony\Component\Ldap\Entry; +use Symfony\Component\Ldap\Security\RoleFetcherInterface; class JsonLoginLdapTest extends AbstractWebTestCase { @@ -32,7 +33,7 @@ public function testKernelBoot() public function testDefaultJsonLdapLoginSuccess() { - if (!interface_exists(\Symfony\Component\Ldap\Security\RoleFetcherInterface::class)) { + if (!interface_exists(RoleFetcherInterface::class)) { $this->markTestSkipped('The "LDAP" component does not support LDAP roles.'); } // Given diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php index 99ba311a26eb8..697272940c263 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php @@ -11,11 +11,12 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; + class LocalizedRoutesAsPathTest extends AbstractWebTestCase { - /** - * @dataProvider getLocales - */ + #[DataProvider('getLocales')] public function testLoginLogoutProcedure(string $locale) { $client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml']); @@ -34,11 +35,8 @@ public function testLoginLogoutProcedure(string $locale) $this->assertEquals('Homepage', $client->followRedirect()->text()); } - /** - * @group issue-32995 - * - * @dataProvider getLocales - */ + #[Group('issue-32995')] + #[DataProvider('getLocales')] public function testLoginFailureWithLocalizedFailurePath(string $locale) { $client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'localized_form_failure_handler.yml']); @@ -52,9 +50,7 @@ public function testLoginFailureWithLocalizedFailurePath(string $locale) $this->assertRedirect($client->getResponse(), '/'.$locale.'/login'); } - /** - * @dataProvider getLocales - */ + #[DataProvider('getLocales')] public function testAccessRestrictedResource(string $locale) { $client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml']); @@ -63,9 +59,7 @@ public function testAccessRestrictedResource(string $locale) $this->assertRedirect($client->getResponse(), '/'.$locale.'/login'); } - /** - * @dataProvider getLocales - */ + #[DataProvider('getLocales')] public function testAccessRestrictedResourceWithForward(string $locale) { $client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes_with_forward.yml']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php index 34fbca10843fa..cd82807ea5b54 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeCookieTest.php @@ -11,11 +11,12 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\HttpFoundation\ResponseHeaderBag; class RememberMeCookieTest extends AbstractWebTestCase { - /** @dataProvider getSessionRememberMeSecureCookieFlagAutoHttpsMap */ + #[DataProvider('getSessionRememberMeSecureCookieFlagAutoHttpsMap')] public function testSessionRememberMeSecureCookieFlagAuto($https, $expectedSecureFlag) { $client = $this->createClient(['test_case' => 'RememberMeCookie', 'root_config' => 'config.yml']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php index 036069f070f6b..70e5f2b5e0ff6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/RememberMeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\RememberMeBundle\Security\UserChangingUserProvider; class RememberMeTest extends AbstractWebTestCase @@ -20,9 +21,7 @@ protected function setUp(): void UserChangingUserProvider::$changePassword = false; } - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testRememberMe(array $options) { $client = $this->createClient(array_merge_recursive(['root_config' => 'config.yml', 'test_case' => 'RememberMe'], $options)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php index 517253fdff94e..625c799f03cb3 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php @@ -11,11 +11,11 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; + class SecurityRoutingIntegrationTest extends AbstractWebTestCase { - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous(array $options) { $client = $this->createClient($options); @@ -24,9 +24,7 @@ public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous(ar $this->assertRedirect($client->getResponse(), '/login'); } - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testRoutingErrorIsExposedWhenNotProtected(array $options) { $client = $this->createClient($options); @@ -35,9 +33,7 @@ public function testRoutingErrorIsExposedWhenNotProtected(array $options) $this->assertEquals(404, $client->getResponse()->getStatusCode(), (string) $client->getResponse()); } - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights(array $options) { $client = $this->createClient($options); @@ -52,9 +48,7 @@ public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWith $this->assertNotEquals(404, $client->getResponse()->getStatusCode()); } - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testSecurityConfigurationForSingleIPAddress(array $options) { $allowedClient = $this->createClient($options, ['REMOTE_ADDR' => '10.10.10.10']); @@ -67,9 +61,7 @@ public function testSecurityConfigurationForSingleIPAddress(array $options) $this->assertRestricted($barredClient, '/secured-by-one-ip'); } - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testSecurityConfigurationForMultipleIPAddresses(array $options) { $allowedClientA = $this->createClient($options, ['REMOTE_ADDR' => '1.1.1.1']); @@ -96,9 +88,7 @@ public function testSecurityConfigurationForMultipleIPAddresses(array $options) $this->assertRestricted($barredClient, '/secured-by-two-ips'); } - /** - * @dataProvider provideConfigs - */ + #[DataProvider('provideConfigs')] public function testSecurityConfigurationForExpression(array $options) { $allowedClient = $this->createClient($options, ['HTTP_USER_AGENT' => 'Firefox 1.0']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php index 76987173bed5c..2225e8c62eda8 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php @@ -11,8 +11,11 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle\ApiAuthenticator; use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\SecuredPageBundle\Security\Core\User\ArrayUserProvider; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\JsonResponse; @@ -65,9 +68,7 @@ public function testUserAuthorizationChecker() $this->assertFalse($security->isGrantedForUser($offlineUser, 'ROLE_FOO')); } - /** - * @dataProvider userWillBeMarkedAsChangedIfRolesHasChangedProvider - */ + #[DataProvider('userWillBeMarkedAsChangedIfRolesHasChangedProvider')] public function testUserWillBeMarkedAsChangedIfRolesHasChanged(UserInterface $userWithAdminRole, UserInterface $userWithoutAdminRole) { $client = $this->createClient(['test_case' => 'AbstractTokenCompareRoles', 'root_config' => 'config.yml']); @@ -108,10 +109,8 @@ public static function userWillBeMarkedAsChangedIfRolesHasChangedProvider(): arr ]; } - /** - * @testWith ["form_login"] - * ["Symfony\\Bundle\\SecurityBundle\\Tests\\Functional\\Bundle\\AuthenticatorBundle\\ApiAuthenticator"] - */ + #[TestWith(['form_login'])] + #[TestWith([ApiAuthenticator::class])] public function testLogin(string $authenticator) { $client = $this->createClient(['test_case' => 'SecurityHelper', 'root_config' => 'config.yml', 'debug' > true]); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index f376847214913..dea034e5247b2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -11,14 +11,13 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Security\Http\Firewall\SwitchUserListener; class SwitchUserTest extends AbstractWebTestCase { - /** - * @dataProvider getTestParameters - */ + #[DataProvider('getTestParameters')] public function testSwitchUser($originalUser, $targetUser, $expectedUser, $expectedStatus) { $client = $this->createAuthenticatedClient($originalUser, ['root_config' => 'switchuser.yml']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/bundles.php index ea92c9159102d..daa1dbf99e40c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/bundles.php @@ -1,5 +1,19 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AccessTokenBundle\AccessTokenBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle; + /* * This file is part of the Symfony package. * @@ -10,8 +24,8 @@ */ return [ - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AccessTokenBundle\AccessTokenBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle(), + new SecurityBundle(), + new FrameworkBundle(), + new AccessTokenBundle(), + new TestBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php index 372700495208f..29ba4aa744217 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/bundles.php @@ -1,5 +1,18 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle\AuthenticatorBundle; + /* * This file is part of the Symfony package. * @@ -10,7 +23,7 @@ */ return [ - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AuthenticatorBundle\AuthenticatorBundle(), + new FrameworkBundle(), + new SecurityBundle(), + new AuthenticatorBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml index 196dcfe1774d2..913cd2a7f9348 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Authenticator/config.yml @@ -1,5 +1,4 @@ framework: - annotations: false http_method_override: false handle_all_throwables: true secret: test diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php index 794461855cb8d..0cf45f4ecef51 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/bundles.php @@ -1,5 +1,19 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle\AutowiringBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle; + /* * This file is part of the Symfony package. * @@ -10,8 +24,8 @@ */ return [ - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle\AutowiringBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle(), + new FrameworkBundle(), + new SecurityBundle(), + new AutowiringBundle(), + new TestBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/bundles.php index 81f9c48b64ca8..5e0de8b33a5be 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/bundles.php @@ -1,5 +1,20 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\CsrfFormLoginBundle\CsrfFormLoginBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle; +use Symfony\Bundle\TwigBundle\TwigBundle; + /* * This file is part of the Symfony package. * @@ -10,9 +25,9 @@ */ return [ - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\TwigBundle\TwigBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\CsrfFormLoginBundle\CsrfFormLoginBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle(), + new FrameworkBundle(), + new SecurityBundle(), + new TwigBundle(), + new CsrfFormLoginBundle(), + new TestBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/bundles.php index b77f03be2703b..a023ddf659108 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/bundles.php @@ -1,5 +1,19 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FirewallEntryPointBundle\FirewallEntryPointBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle; + /* * This file is part of the Symfony package. * @@ -10,8 +24,8 @@ */ return [ - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FirewallEntryPointBundle\FirewallEntryPointBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle(), + new FrameworkBundle(), + new SecurityBundle(), + new FirewallEntryPointBundle(), + new TestBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml index 31b0af34088a3..0e8da68e34093 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/FirewallEntryPoint/config.yml @@ -1,5 +1,4 @@ framework: - annotations: false http_method_override: false handle_all_throwables: true secret: test diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php index bbb9107456b98..c27919ce4be61 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php @@ -1,5 +1,19 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\JsonLoginBundle; +use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle; + /* * This file is part of the Symfony package. * @@ -10,8 +24,8 @@ */ return [ - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\JsonLoginBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\TestBundle(), + new SecurityBundle(), + new FrameworkBundle(), + new JsonLoginBundle(), + new TestBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLoginLdap/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLoginLdap/bundles.php index bcfd17425cfd1..ee4ea222ddc54 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLoginLdap/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLoginLdap/bundles.php @@ -1,5 +1,17 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; + /* * This file is part of the Symfony package. * @@ -10,6 +22,6 @@ */ return [ - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), + new SecurityBundle(), + new FrameworkBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LoginLink/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LoginLink/bundles.php index bcfd17425cfd1..ee4ea222ddc54 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LoginLink/bundles.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LoginLink/bundles.php @@ -1,5 +1,17 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; + /* * This file is part of the Symfony package. * @@ -10,6 +22,6 @@ */ return [ - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), + new SecurityBundle(), + new FrameworkBundle(), ]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml index 0f2e1344d0e71..1a8d83dd130d0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml @@ -1,5 +1,4 @@ framework: - annotations: false http_method_override: false handle_all_throwables: true secret: test diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index 81c85ad76c204..9f4bb72929a77 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Security; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; use Symfony\Bundle\SecurityBundle\Security\FirewallContext; @@ -57,7 +58,7 @@ public function testGetListenersWithInvalidParameter() $this->assertFalse($request->attributes->has('_stateless')); } - /** @dataProvider providesStatefulStatelessRequests */ + #[DataProvider('providesStatefulStatelessRequests')] public function testGetListeners(Request $request, bool $expectedState) { $firewallContext = $this->createMock(FirewallContext::class); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php index 9a126ae328e08..5553f81d55087 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -55,9 +56,7 @@ public function testGetToken() $this->assertSame($token, $security->getToken()); } - /** - * @dataProvider getUserTests - */ + #[DataProvider('getUserTests')] public function testGetUser($userInToken, $expectedUser) { $token = $this->createMock(TokenInterface::class); @@ -99,9 +98,7 @@ public function testIsGranted() $this->assertTrue($security->isGranted('SOME_ATTRIBUTE', 'SOME_SUBJECT')); } - /** - * @dataProvider getFirewallConfigTests - */ + #[DataProvider('getFirewallConfigTests')] public function testGetFirewallConfig(Request $request, ?FirewallConfig $expectedFirewallConfig) { $firewallMap = $this->createMock(FirewallMap::class); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 7459b0175b95f..1a559d0d1411c 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -19,37 +19,39 @@ "php": ">=8.2", "composer-runtime-api": ">=2.1", "ext-xml": "*", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^6.4.11|^7.1.4", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/password-hasher": "^6.4|^7.0", - "symfony/security-core": "^7.3", - "symfony/security-csrf": "^6.4|^7.0", - "symfony/security-http": "^7.3", + "symfony/clock": "^6.4|^7.0|^8.0", + "symfony/config": "^7.3|^8.0", + "symfony/dependency-injection": "^6.4.11|^7.1.4|^8.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/password-hasher": "^6.4|^7.0|^8.0", + "symfony/security-core": "^7.3|^8.0", + "symfony/security-csrf": "^6.4|^7.0|^8.0", + "symfony/security-http": "^7.3|^8.0", "symfony/service-contracts": "^2.5|^3" }, "require-dev": { - "symfony/asset": "^6.4|^7.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/ldap": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/twig-bundle": "^6.4|^7.0", - "symfony/twig-bridge": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", + "symfony/asset": "^6.4|^7.0|^8.0", + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/css-selector": "^6.4|^7.0|^8.0", + "symfony/dom-crawler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/ldap": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/twig-bundle": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", "twig/twig": "^3.12", "web-token/jwt-library": "^3.3.2|^4.0" }, @@ -69,5 +71,10 @@ "/Tests/" ] }, - "minimum-stability": "dev" + "minimum-stability": "dev", + "config": { + "allow-plugins": { + "symfony/runtime": false + } + } } diff --git a/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist b/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist index b8b8a9adbedc1..98a9bc3e8f1a4 100644 --- a/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist +++ b/src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php index 10aa983e0ea46..a5af7fd522832 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php @@ -31,11 +31,11 @@ protected function configure(): void ->setHelp( $this->getHelp().<<<'EOF' -Or all template files in a bundle: + Or all template files in a bundle: - php %command.full_name% @AcmeDemoBundle + php %command.full_name% @AcmeDemoBundle -EOF + EOF ) ; } diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index b21e4f37ece2b..9b5e8d633014e 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; +use Symfony\Bridge\Twig\Extension\FormExtension; use Symfony\Component\Asset\Packages; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; @@ -18,6 +19,7 @@ use Symfony\Component\Emoji\EmojiTransliterator; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Workflow\Workflow; use Symfony\Component\Yaml\Yaml; @@ -54,7 +56,7 @@ public function process(ContainerBuilder $container): void $container->removeDefinition('twig.runtime.importmap'); } - $viewDir = \dirname((new \ReflectionClass(\Symfony\Bridge\Twig\Extension\FormExtension::class))->getFileName(), 2).'/Resources/views'; + $viewDir = \dirname((new \ReflectionClass(FormExtension::class))->getFileName(), 2).'/Resources/views'; $templateIterator = $container->getDefinition('twig.template_iterator'); $templatePaths = $templateIterator->getArgument(1); $loader = $container->getDefinition('twig.loader.native_filesystem'); @@ -122,7 +124,7 @@ public function process(ContainerBuilder $container): void $container->getDefinition('twig.extension.yaml')->addTag('twig.extension'); } - if (class_exists(\Symfony\Component\Stopwatch\Stopwatch::class)) { + if (class_exists(Stopwatch::class)) { $container->getDefinition('twig.extension.debug.stopwatch')->addTag('twig.extension'); } diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index ddc489e783671..197b27df248be 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -11,7 +11,9 @@ namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\RuntimeLoaderPass; use Symfony\Bundle\TwigBundle\DependencyInjection\TwigExtension; use Symfony\Bundle\TwigBundle\Tests\DependencyInjection\AcmeBundle\AcmeBundle; @@ -33,8 +35,6 @@ class TwigExtensionTest extends TestCase { - use ExpectUserDeprecationMessageTrait; - public function testLoadEmptyConfiguration() { $container = $this->createContainer(); @@ -63,9 +63,7 @@ public function testLoadEmptyConfiguration() } } - /** - * @dataProvider getFormatsAndBuildDir - */ + #[DataProvider('getFormatsAndBuildDir')] public function testLoadFullConfiguration(string $format, ?string $buildDir) { $container = $this->createContainer($buildDir); @@ -92,7 +90,7 @@ public function testLoadFullConfiguration(string $format, ?string $buildDir) $this->assertEquals(3.14, $calls[4][1][1], '->load() registers variables as Twig globals'); // Yaml and Php specific configs - if (\in_array($format, ['yml', 'php'])) { + if (\in_array($format, ['yml', 'php'], true)) { $this->assertEquals('bad', $calls[5][1][0], '->load() registers variables as Twig globals'); $this->assertEquals(['key' => 'foo'], $calls[5][1][1], '->load() registers variables as Twig globals'); } @@ -108,9 +106,7 @@ public function testLoadFullConfiguration(string $format, ?string $buildDir) $this->assertEquals(null !== $buildDir ? new Reference('twig.template_cache.chain') : '%kernel.cache_dir%/twig', $options['cache'], '->load() sets the cache option'); } - /** - * @dataProvider getFormatsAndBuildDir - */ + #[DataProvider('getFormatsAndBuildDir')] public function testLoadNoCacheConfiguration(string $format, ?string $buildDir) { $container = $this->createContainer($buildDir); @@ -125,9 +121,7 @@ public function testLoadNoCacheConfiguration(string $format, ?string $buildDir) $this->assertFalse($options['cache'], '->load() sets cache option to false'); } - /** - * @dataProvider getFormatsAndBuildDir - */ + #[DataProvider('getFormatsAndBuildDir')] public function testLoadPathCacheConfiguration(string $format, ?string $buildDir) { $container = $this->createContainer($buildDir); @@ -142,9 +136,7 @@ public function testLoadPathCacheConfiguration(string $format, ?string $buildDir $this->assertSame('random-path', $options['cache'], '->load() sets cache option to string path'); } - /** - * @dataProvider getFormatsAndBuildDir - */ + #[DataProvider('getFormatsAndBuildDir')] public function testLoadProdCacheConfiguration(string $format, ?string $buildDir) { $container = $this->createContainer($buildDir); @@ -159,11 +151,9 @@ public function testLoadProdCacheConfiguration(string $format, ?string $buildDir $this->assertEquals(null !== $buildDir ? new Reference('twig.template_cache.chain') : '%kernel.cache_dir%/twig', $options['cache'], '->load() sets cache option to CacheChain reference'); } - /** - * @group legacy - * - * @dataProvider getFormats - */ + #[IgnoreDeprecations] + #[Group('legacy')] + #[DataProvider('getFormats')] public function testLoadCustomBaseTemplateClassConfiguration(string $format) { $container = $this->createContainer(); @@ -178,9 +168,7 @@ public function testLoadCustomBaseTemplateClassConfiguration(string $format) $this->assertEquals('stdClass', $options['base_template_class'], '->load() sets the base_template_class option'); } - /** - * @dataProvider getFormats - */ + #[DataProvider('getFormats')] public function testLoadCustomTemplateEscapingGuesserConfiguration(string $format) { $container = $this->createContainer(); @@ -192,9 +180,7 @@ public function testLoadCustomTemplateEscapingGuesserConfiguration(string $forma $this->assertEquals([new Reference('my_project.some_bundle.template_escaping_guesser'), 'guess'], $options['autoescape']); } - /** - * @dataProvider getFormats - */ + #[DataProvider('getFormats')] public function testLoadDefaultTemplateEscapingGuesserConfiguration(string $format) { $container = $this->createContainer(); @@ -206,9 +192,7 @@ public function testLoadDefaultTemplateEscapingGuesserConfiguration(string $form $this->assertEquals('name', $options['autoescape']); } - /** - * @dataProvider getFormats - */ + #[DataProvider('getFormats')] public function testLoadCustomDateFormats(string $fileFormat) { $container = $this->createContainer(); @@ -255,9 +239,7 @@ public function testGlobalsWithDifferentTypesAndValues() } } - /** - * @dataProvider getFormats - */ + #[DataProvider('getFormats')] public function testTwigLoaderPaths(string $format) { $container = $this->createContainer(); @@ -308,9 +290,7 @@ public static function getFormatsAndBuildDir(): array ]; } - /** - * @dataProvider stopwatchExtensionAvailabilityProvider - */ + #[DataProvider('stopwatchExtensionAvailabilityProvider')] public function testStopwatchExtensionAvailability(bool $debug, bool $stopwatchEnabled, bool $expected) { $container = $this->createContainer(); @@ -363,9 +343,7 @@ public function testRuntimeLoader() $this->assertEquals('foo', $args['FooClass']->getValues()[0]); } - /** - * @dataProvider getFormats - */ + #[DataProvider('getFormats')] public function testCustomHtmlToTextConverterService(string $format) { if (!class_exists(Mailer::class)) { diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php index 32db815b16a37..04f09be6df97a 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php @@ -32,7 +32,6 @@ class AttributeExtensionTest extends TestCase { - /** @beforeClass */ #[BeforeClass] public static function assertTwigVersion(): void { @@ -90,11 +89,6 @@ public function registerContainerConfiguration(LoaderInterface $loader): void $kernel->boot(); } - /** - * @before - * - * @after - */ #[Before, After] protected function deleteTempDir() { @@ -145,8 +139,9 @@ public static function fooTest(bool $value): bool class RuntimeExtensionWithAttributes { - public function __construct(private bool $prefix) - { + public function __construct( + private string $prefix, + ) { } #[AsTwigFilter('prefix_foo')] diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php index 01abd85b21c3b..4123ddd8633e9 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php @@ -64,7 +64,6 @@ public function registerContainerConfiguration(LoaderInterface $loader): void { $loader->load(function (ContainerBuilder $container) { $config = [ - 'annotations' => false, 'http_method_override' => false, 'php_errors' => ['log' => true], 'secret' => '$ecret', diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 221a7f471290e..b8b67f2bee5e8 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -18,24 +18,25 @@ "require": { "php": ">=8.2", "composer-runtime-api": ">=2.1", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/twig-bridge": "^7.3", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", + "symfony/config": "^7.3|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/twig-bridge": "^7.3|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", "twig/twig": "^3.12" }, "require-dev": { - "symfony/asset": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0" + "symfony/asset": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/form": "^6.4|^7.0|^8.0", + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/runtime": "^6.4.13|^7.1.6", + "symfony/translation": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", + "symfony/web-link": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/framework-bundle": "<6.4", @@ -47,5 +48,10 @@ "/Tests/" ] }, - "minimum-stability": "dev" + "minimum-stability": "dev", + "config": { + "allow-plugins": { + "symfony/runtime": false + } + } } diff --git a/src/Symfony/Bundle/TwigBundle/phpunit.xml.dist b/src/Symfony/Bundle/TwigBundle/phpunit.xml.dist index 5b35c7666f2e5..61155994f5452 100644 --- a/src/Symfony/Bundle/TwigBundle/phpunit.xml.dist +++ b/src/Symfony/Bundle/TwigBundle/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 5e5e8db36e233..a08727013b4bd 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.4 +--- + + * Add support for the `QUERY` HTTP method in the profiler + 7.3 --- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php index 299a1b02cf595..2a8844237797c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php @@ -94,7 +94,7 @@ public function formatArgs(array $args): string $formattedValue = ''.strtolower(htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; - } elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) { + } elseif (\is_string($item[1]) && preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) { $formattedValue = 'binary string'; } else { $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/search.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/search.html.twig index 749ac490c7be5..0fa551a18ba14 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/search.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/search.html.twig @@ -25,7 +25,7 @@ {% if 'command' == profile_type %} {% set methods = ['BATCH', 'INTERACTIVE'] %} {% else %} - {% set methods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT'] %} + {% set methods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'QUERY'] %} {% endif %} {% for m in methods %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index 148b7638ad2eb..d664819d28d2b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -113,6 +113,9 @@ background: var(--sf-toolbar-gray-700); } +.sf-toolbar.sf-toolbar-closed .sf-toolbar-clearer { + display: none; +} .sf-toolbar.sf-toolbar-closed .sf-toolbarreset .sf-toolbar-block { display: none; } @@ -149,7 +152,7 @@ margin-right: 0; position: relative; white-space: nowrap; - max-width: 15%; + max-width: 25%; } .sf-toolbar-block > a, .sf-toolbar-block > a:hover { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig index b82f911c3ddc6..e7a55eb87d846 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig @@ -32,8 +32,8 @@ {% endif %} - diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index dd9527d24b0ab..90cb20eb80950 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -512,11 +512,16 @@ 'sfwdt' + token, '{{ url("_wdt", { "token": "xxxxxx" })|escape('js') }}'.replace(/xxxxxx/, newToken), function(xhr, el) { + var toolbarContent = document.getElementById('sfToolbarMainContent-' + newToken); + /* Do nothing in the edge case where the toolbar has already been replaced with a new one */ - if (!document.getElementById('sfToolbarMainContent-' + newToken)) { + if (!toolbarContent) { return; } + /* Replace the ID, it has to match the new token */ + toolbarContent.parentElement.id = 'sfwdt' + newToken; + /* Evaluate in global scope scripts embedded inside the toolbar */ var i, scripts = [].slice.call(el.querySelectorAll('script')); for (i = 0; i < scripts.length; ++i) { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php index 0e0a1e0aae79c..aa04f60993b28 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\Controller; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; @@ -122,9 +123,7 @@ public function testToolbarActionWithProfilerDisabled() $controller->toolbarAction(Request::create('/_wdt/foo-token'), null); } - /** - * @dataProvider getEmptyTokenCases - */ + #[DataProvider('getEmptyTokenCases')] public function testToolbarActionWithEmptyToken($token) { $urlGenerator = $this->createMock(UrlGeneratorInterface::class); @@ -173,9 +172,7 @@ public static function getEmptyTokenCases() ]; } - /** - * @dataProvider getOpenFileCases - */ + #[DataProvider('getOpenFileCases')] public function testOpeningDisallowedPaths($path, $isAllowed) { $urlGenerator = $this->createMock(UrlGeneratorInterface::class); @@ -206,9 +203,7 @@ public static function getOpenFileCases() ]; } - /** - * @dataProvider provideCspVariants - */ + #[DataProvider('provideCspVariants')] public function testReturns404onTokenNotFound($withCsp) { $twig = $this->createMock(Environment::class); @@ -256,9 +251,7 @@ public function testSearchBarActionDefaultPage() } } - /** - * @dataProvider provideCspVariants - */ + #[DataProvider('provideCspVariants')] public function testSearchResultsAction($withCsp) { $twig = $this->createMock(Environment::class); @@ -433,9 +426,7 @@ public static function provideCspVariants(): array ]; } - /** - * @dataProvider defaultPanelProvider - */ + #[DataProvider('defaultPanelProvider')] public function testDefaultPanel(string $expectedPanel, Profile $profile) { $this->assertDefaultPanel($expectedPanel, $profile); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php index bce62829467b9..be40fde08920a 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\Csp; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler; use Symfony\Bundle\WebProfilerBundle\Csp\NonceGenerator; @@ -19,9 +20,7 @@ class ContentSecurityPolicyHandlerTest extends TestCase { - /** - * @dataProvider provideRequestAndResponses - */ + #[DataProvider('provideRequestAndResponses')] public function testGetNonces($nonce, $expectedNonce, Request $request, Response $response) { $cspHandler = new ContentSecurityPolicyHandler($this->mockNonceGenerator($nonce)); @@ -29,9 +28,7 @@ public function testGetNonces($nonce, $expectedNonce, Request $request, Response $this->assertSame($expectedNonce, $cspHandler->getNonces($request, $response)); } - /** - * @dataProvider provideRequestAndResponsesForOnKernelResponse - */ + #[DataProvider('provideRequestAndResponsesForOnKernelResponse')] public function testOnKernelResponse($nonce, $expectedNonce, Request $request, Response $response, array $expectedCsp) { $cspHandler = new ContentSecurityPolicyHandler($this->mockNonceGenerator($nonce)); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php index 6a9fc99f10281..11b19b35bcf51 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -11,15 +11,14 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\WebProfilerBundle\DependencyInjection\Configuration; use Symfony\Component\Config\Definition\Processor; class ConfigurationTest extends TestCase { - /** - * @dataProvider getDebugModes - */ + #[DataProvider('getDebugModes')] public function testConfigTree(array $options, array $expectedResult) { $processor = new Processor(); @@ -79,9 +78,7 @@ public static function getDebugModes() ]; } - /** - * @dataProvider getInterceptRedirectsConfiguration - */ + #[DataProvider('getInterceptRedirectsConfiguration')] public function testConfigTreeUsingInterceptRedirects(bool $interceptRedirects, array $expectedResult) { $processor = new Processor(); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index 490bc91e6661d..72d4780e301bd 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Bundle\WebProfilerBundle\DependencyInjection\WebProfilerExtension; use Symfony\Bundle\WebProfilerBundle\Tests\TestCase; @@ -88,9 +89,7 @@ protected function tearDown(): void $this->container = null; } - /** - * @dataProvider getDebugModes - */ + #[DataProvider('getDebugModes')] public function testDefaultConfig($debug) { $this->container->setParameter('kernel.debug', $debug); @@ -112,9 +111,7 @@ public static function getDebugModes() ]; } - /** - * @dataProvider getToolbarConfig - */ + #[DataProvider('getToolbarConfig')] public function testToolbarConfig(bool $toolbarEnabled, bool $listenerInjected, bool $listenerEnabled) { $extension = new WebProfilerExtension(); @@ -146,9 +143,7 @@ public static function getToolbarConfig() ]; } - /** - * @dataProvider getInterceptRedirectsToolbarConfig - */ + #[DataProvider('getInterceptRedirectsToolbarConfig')] public function testToolbarConfigUsingInterceptRedirects( bool $toolbarEnabled, bool $interceptRedirects, diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php index 981c85beed41f..420e8393d376c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\EventListener; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\TestCase; use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler; use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener; @@ -25,9 +27,7 @@ class WebDebugToolbarListenerTest extends TestCase { - /** - * @dataProvider getInjectToolbarTests - */ + #[DataProvider('getInjectToolbarTests')] public function testInjectToolbar($content, $expected) { $listener = new WebDebugToolbarListener($this->getTwigMock()); @@ -57,9 +57,7 @@ public static function getInjectToolbarTests() ]; } - /** - * @dataProvider provideRedirects - */ + #[DataProvider('provideRedirects')] public function testHtmlRedirectionIsIntercepted($statusCode) { $response = new Response('Some content', $statusCode); @@ -101,9 +99,7 @@ public function testToolbarIsInjected() $this->assertEquals("\nWDT\n", $response->getContent()); } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedOnNonHtmlContentType() { $response = new Response(''); @@ -117,9 +113,7 @@ public function testToolbarIsNotInjectedOnNonHtmlContentType() $this->assertEquals('', $response->getContent()); } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedOnContentDispositionAttachment() { $response = new Response(''); @@ -133,11 +127,8 @@ public function testToolbarIsNotInjectedOnContentDispositionAttachment() $this->assertEquals('', $response->getContent()); } - /** - * @depends testToolbarIsInjected - * - * @dataProvider provideRedirects - */ + #[DataProvider('provideRedirects')] + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedOnRedirection($statusCode) { $response = new Response('', $statusCode); @@ -159,9 +150,7 @@ public static function provideRedirects(): array ]; } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedWhenThereIsNoNoXDebugTokenResponseHeader() { $response = new Response(''); @@ -174,9 +163,7 @@ public function testToolbarIsNotInjectedWhenThereIsNoNoXDebugTokenResponseHeader $this->assertEquals('', $response->getContent()); } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedWhenOnSubRequest() { $response = new Response(''); @@ -190,9 +177,7 @@ public function testToolbarIsNotInjectedWhenOnSubRequest() $this->assertEquals('', $response->getContent()); } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedOnIncompleteHtmlResponses() { $response = new Response('
Some content
'); @@ -206,9 +191,7 @@ public function testToolbarIsNotInjectedOnIncompleteHtmlResponses() $this->assertEquals('
Some content
', $response->getContent()); } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedOnXmlHttpRequests() { $response = new Response(''); @@ -225,9 +208,7 @@ public function testToolbarIsNotInjectedOnXmlHttpRequests() $this->assertEquals('', $response->getContent()); } - /** - * @depends testToolbarIsInjected - */ + #[Depends('testToolbarIsInjected')] public function testToolbarIsNotInjectedOnNonHtmlRequests() { $response = new Response(''); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php index 0447e5787401e..f8af2e5224cbd 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Functional/WebProfilerBundleKernel.php @@ -51,7 +51,6 @@ protected function configureRoutes(RoutingConfigurator $routes): void protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void { $config = [ - 'annotations' => false, 'http_method_override' => false, 'php_errors' => ['log' => true], 'secret' => 'foo-secret', diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/CodeExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/CodeExtensionTest.php index 314deea4b9550..5377db2fe3384 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/CodeExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/CodeExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Tests\Profiler; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Bundle\WebProfilerBundle\Profiler\CodeExtension; use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; @@ -38,16 +39,16 @@ public function testClassAbbreviationIntegration() ]; $template = <<<'TWIG' -{{ 'Bare'|abbr_class }} -{{ fqcn|abbr_class }} -{{ xss|abbr_class }} -TWIG; + {{ 'Bare'|abbr_class }} + {{ fqcn|abbr_class }} + {{ xss|abbr_class }} + TWIG; $expected = <<<'HTML' -Bare -Foo -<script> -HTML; + Bare + Foo + <script> + HTML; $this->assertEquals($expected, $this->render($template, $data)); } @@ -60,20 +61,20 @@ public function testMethodAbbreviationIntegration() ]; $template = <<<'TWIG' -{{ 'Bare::Method'|abbr_method }} -{{ fqcn|abbr_method }} -{{ 'Closure'|abbr_method }} -{{ 'Method'|abbr_method }} -{{ xss|abbr_method }} -TWIG; + {{ 'Bare::Method'|abbr_method }} + {{ fqcn|abbr_method }} + {{ 'Closure'|abbr_method }} + {{ 'Method'|abbr_method }} + {{ xss|abbr_method }} + TWIG; $expected = <<<'HTML' -Bare::Method() -Foo::Method() -Closure -Method() -<script>() -HTML; + Bare::Method() + Foo::Method() + Closure + Method() + <script>() + HTML; $this->assertEquals($expected, $this->render($template, $data)); } @@ -100,18 +101,18 @@ public function testFormatArgsIntegration() ]; $template = <<<'TWIG' -{{ args|format_args }} -{{ xss|format_args }} -{{ args|format_args_as_text }} -{{ xss|format_args_as_text }} -TWIG; + {{ args|format_args }} + {{ xss|format_args }} + {{ args|format_args_as_text }} + {{ xss|format_args_as_text }} + TWIG; $expected = <<<'HTML' -object(Foo), array('foo', null), resource, 'bar', 123, true -object(<Foo>), array('<foo>'), '<bar>', 123, true, '<script>' -object(Foo), array('foo', null), resource, 'bar', 123, true -object(&lt;Foo&gt;), array('&lt;foo&gt;'), '&lt;bar&gt;', 123, true, '&lt;script&gt;' -HTML; + object(Foo), array('foo', null), resource, 'bar', 123, true + object(<Foo>), array('<foo>'), '<bar>', 123, true, '<script>' + object(Foo), array('foo', null), resource, 'bar', 123, true + object(&lt;Foo&gt;), array('&lt;foo&gt;'), '&lt;bar&gt;', 123, true, '&lt;script&gt;' + HTML; $this->assertEquals($expected, $this->render($template, $data)); } @@ -119,24 +120,22 @@ public function testFormatArgsIntegration() public function testFormatFileIntegration() { $template = <<<'TWIG' -{{ 'foo/bar/baz.php'|format_file(21) }} -TWIG; + {{ 'foo/bar/baz.php'|format_file(21) }} + TWIG; $expected = <<<'HTML' -foo/bar/baz.php at line 21 -HTML; + foo/bar/baz.php at line 21 + HTML; $this->assertEquals($expected, $this->render($template)); } - /** - * @dataProvider fileExcerptIntegrationProvider - */ + #[DataProvider('fileExcerptIntegrationProvider')] public function testFileExcerptIntegration(string $expected, array $data) { $template = <<<'TWIG' -{{ file_path|file_excerpt(line, src_context) }} -TWIG; + {{ file_path|file_excerpt(line, src_context) }} + TWIG; $html = $this->render($template, $data); // highlight_file function output changed sing PHP 8.3 @@ -156,12 +155,12 @@ public static function fileExcerptIntegrationProvider() yield 'php file' => [ 'expected' => <<<'HTML' -
  1. -
  2. -
  3. echo 'Hello';
  4. -
  5. echo 'World!';
  6. -
-HTML, +
  1. +
  2. +
  3. echo 'Hello';
  4. +
  5. echo 'World!';
  6. +
+ HTML, 'data' => [ 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', 'line' => 0, @@ -171,12 +170,12 @@ public static function fileExcerptIntegrationProvider() yield 'php file with selected line and no source context' => [ 'expected' => <<<'HTML' -
  1. -
  2. -
  3. echo 'Hello';
  4. -
  5. echo 'World!';
  6. -
-HTML, +
  1. +
  2. +
  3. echo 'Hello';
  4. +
  5. echo 'World!';
  6. +
+ HTML, 'data' => [ 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', 'line' => 1, @@ -186,10 +185,10 @@ public static function fileExcerptIntegrationProvider() yield 'php file excerpt with selected line and custom source context' => [ 'expected' => <<<'HTML' -
  1. echo 'Hello';
  2. -
  3. echo 'World!';
  4. -
-HTML, +
  1. echo 'Hello';
  2. +
  3. echo 'World!';
  4. +
+ HTML, 'data' => [ 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', 'line' => 3, @@ -199,8 +198,8 @@ public static function fileExcerptIntegrationProvider() yield 'php file excerpt with out of bound selected line' => [ 'expected' => <<<'HTML' -
    -HTML, +
      + HTML, 'data' => [ 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', 'line' => 100, @@ -210,12 +209,12 @@ public static function fileExcerptIntegrationProvider() yield 'json file' => [ 'expected' => <<<'HTML' -
      1. [
      2. -
      3. "Hello",
      4. -
      5. "World!"
      6. -
      7. ]
      8. -
      -HTML, +
      1. [
      2. +
      3. "Hello",
      4. +
      5. "World!"
      6. +
      7. ]
      8. +
      + HTML, 'data' => [ 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.json', 'line' => 0, @@ -227,16 +226,16 @@ public static function fileExcerptIntegrationProvider() public function testFormatFileFromTextIntegration() { $template = <<<'TWIG' -{{ 'in "foo/bar/baz.php" at line 21'|format_file_from_text }} -{{ 'in "foo/bar/baz.php" on line 21'|format_file_from_text }} -{{ 'in "(.*)#', $output->fetch(), 'styles & scripts are output only once'); } - /** - * @dataProvider provideContext - */ + #[DataProvider('provideContext')] public function testDescribe(array $context, string $expectedOutput) { $output = new BufferedOutput(); @@ -74,24 +73,24 @@ public static function provideContext() ], ], << -
      -
      -

      -

      - -
      - -
      -
      -

      - CliDescriptorTest.php on line 30 -

      - [DUMPED] -
      - -TXT, +
      +
      +
      +

      -

      + +
      + +
      +
      +

      + CliDescriptorTest.php on line 30 +

      + [DUMPED] +
      +
      + TXT, ]; yield 'source full' => [ @@ -106,28 +105,28 @@ public static function provideContext() ], ], << -
      -
      -

      -

      - -
      -
      -
        -
      • project dirsrc/Symfony/
      • -
      -
      -
      -
      -

      - CliDescriptorTest.php on line 30 -

      - [DUMPED] -
      - -TXT, + + TXT, ]; yield 'cli' => [ @@ -138,24 +137,24 @@ public static function provideContext() ], ], << -
      -
      -

      $ bin/phpunit

      - -
      - -
      -
      -

      - -

      - [DUMPED] -
      - -TXT, +
      +
      +
      +

      $ bin/phpunit

      + +
      + +
      +
      +

      + +

      + [DUMPED] +
      +
      + TXT, ]; yield 'request' => [ @@ -168,28 +167,28 @@ public static function provideContext() ], ], << -
      -
      -

      GET http://localhost/foo

      - -
      -
      -
        -
      • controller[DUMPED]
      • -
      -
      -
      -
      -

      - -

      - [DUMPED] -
      - -TXT, +
      +
      +
      +

      GET http://localhost/foo

      + +
      +
      +
        +
      • controller[DUMPED]
      • +
      +
      +
      +
      +

      + +

      + [DUMPED] +
      +
      + TXT, ]; } } diff --git a/src/Symfony/Component/VarDumper/Tests/Command/ServerDumpCommandTest.php b/src/Symfony/Component/VarDumper/Tests/Command/ServerDumpCommandTest.php index 47c45fd1b7e9e..77e215cee227a 100644 --- a/src/Symfony/Component/VarDumper/Tests/Command/ServerDumpCommandTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Command/ServerDumpCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\VarDumper\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandCompletionTester; use Symfony\Component\VarDumper\Command\ServerDumpCommand; @@ -18,9 +19,7 @@ class ServerDumpCommandTest extends TestCase { - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $tester = new CommandCompletionTester($this->createCommand()); diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 14b538084b50c..160384155ce22 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\VarDumper\Tests\Dumper; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; use Symfony\Component\VarDumper\Caster\ClassStub; @@ -62,65 +64,62 @@ public function testGet() $this->assertStringMatchesFormat( << 1 - 0 => &1 null - "const" => 1.1 - 1 => true - 2 => false - 3 => NAN - 4 => INF - 5 => -INF - 6 => {$intMax} - "str" => "déjà\\n" - 7 => b""" - é\\x01test\\t\\n - ing - """ - "bo\\u{FEFF}m" => "te\\u{FEFF}st" - "[]" => [] - "res" => stream resource {@{$res} -%A wrapper_type: "plainfile" - stream_type: "STDIO" - mode: "r" - unread_bytes: 0 - seekable: true -%A options: [] - } - "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d - +foo: ""…3 - +"bar": "bar" - } - "closure" => Closure(\$a, ?PDO &\$b = null) {#%d - class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest" - this: Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest {#%d …} - file: "%s%eTests%eFixtures%edumb-var.php" - line: "{$var['line']} to {$var['line']}" - } - "line" => {$var['line']} - "nobj" => array:1 [ - 0 => &3 {#%d} - ] - "recurs" => &4 array:1 [ - 0 => &4 array:1 [&4] - ] - 8 => &1 null - "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} - "snobj" => &3 {#%d} - "snobj2" => {#%d} - "file" => "{$var['file']}" - b"bin-key-é" => "" -] - -EOTXT - , + array:25 [ + "number" => 1 + 0 => &1 null + "const" => 1.1 + 1 => true + 2 => false + 3 => NAN + 4 => INF + 5 => -INF + 6 => {$intMax} + "str" => "déjà\\n" + 7 => b""" + é\\x01test\\t\\n + ing + """ + "bo\\u{FEFF}m" => "te\\u{FEFF}st" + "[]" => [] + "res" => stream resource {@{$res} + %A wrapper_type: "plainfile" + stream_type: "STDIO" + mode: "r" + unread_bytes: 0 + seekable: true + %A options: [] + } + "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d + +foo: ""…3 + +"bar": "bar" + } + "closure" => Closure(\$a, ?PDO &\$b = null) {#%d + class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest" + this: Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest {#%d …} + file: "%s%eTests%eFixtures%edumb-var.php" + line: "{$var['line']} to {$var['line']}" + } + "line" => {$var['line']} + "nobj" => array:1 [ + 0 => &3 {#%d} + ] + "recurs" => &4 array:1 [ + 0 => &4 array:1 [&4] + ] + 8 => &1 null + "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} + "snobj" => &3 {#%d} + "snobj2" => {#%d} + "file" => "{$var['file']}" + b"bin-key-é" => "" + ] + + EOTXT, $out ); } - /** - * @dataProvider provideDumpWithCommaFlagTests - */ + #[DataProvider('provideDumpWithCommaFlagTests')] public function testDumpWithCommaFlag($expected, $flags) { $dumper = new CliDumper(null, null, $flags); @@ -149,63 +148,64 @@ public function testDumpWithCommaFlagsAndExceptionCodeExcerpt() $dump = $dumper->dump($cloner->cloneVar($ex)->withRefHandles(false), true); $this->assertStringMatchesFormat(<<<'EOTXT' -RuntimeException { - #message: "foo" - #code: 0 - #file: "%ACliDumperTest.php" - #line: %d - trace: { - %ACliDumperTest.php:%d { - Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest->testDumpWithCommaFlagsAndExceptionCodeExcerpt() - › - › $ex = new \RuntimeException('foo'); - › - } - %A - } -} + RuntimeException { + #message: "foo" + #code: 0 + #file: "%ACliDumperTest.php" + #line: %d + trace: { + %ACliDumperTest.php:%d { + Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest->testDumpWithCommaFlagsAndExceptionCodeExcerpt() + › + › $ex = new \RuntimeException('foo'); + › + } + %A + } + } -EOTXT - , $dump); + EOTXT, + $dump + ); } public static function provideDumpWithCommaFlagTests() { $expected = <<<'EOTXT' -array:3 [ - "array" => array:2 [ - 0 => "a", - 1 => "b" - ], - "string" => "hello", - "multiline string" => """ - this\n - is\n - a\multiline\n - string - """ -] - -EOTXT; + array:3 [ + "array" => array:2 [ + 0 => "a", + 1 => "b" + ], + "string" => "hello", + "multiline string" => """ + this\n + is\n + a\multiline\n + string + """ + ] + + EOTXT; yield [$expected, CliDumper::DUMP_COMMA_SEPARATOR]; $expected = <<<'EOTXT' -array:3 [ - "array" => array:2 [ - 0 => "a", - 1 => "b", - ], - "string" => "hello", - "multiline string" => """ - this\n - is\n - a\multiline\n - string - """, -] - -EOTXT; + array:3 [ + "array" => array:2 [ + 0 => "a", + 1 => "b", + ], + "string" => "hello", + "multiline string" => """ + this\n + is\n + a\multiline\n + string + """, + ] + + EOTXT; yield [$expected, CliDumper::DUMP_TRAILING_COMMA]; } @@ -220,14 +220,13 @@ public function testJsonCast() $this->assertDumpMatchesFormat( <<<'EOTXT' -array:4 [ - 0 => {} - 1 => &1 null - 2 => &1 null - "" => 2 -] -EOTXT - , + array:4 [ + 0 => {} + 1 => &1 null + 2 => &1 null + "" => 2 + ] + EOTXT, $var ); } @@ -239,11 +238,10 @@ public function testObjectCast() $this->assertDumpMatchesFormat( <<<'EOTXT' -{ - +"1": 2 -} -EOTXT - , + { + +"1": 2 + } + EOTXT, $var ); } @@ -265,10 +263,9 @@ public function testClosedResource() $this->assertStringMatchesFormat( <<assertDumpEquals( << (3) "foo" - 2 => (3) "bar" - ] -] -EOTXT - , + [ + [ + 1 + 2 + 3 + ] + [ + 0 => (3) "foo" + 2 => (3) "bar" + ] + ] + EOTXT, $var ); @@ -305,9 +301,7 @@ public function testFlags() putenv('DUMP_STRING_LENGTH='); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testVirtualProperties() { $this->assertDumpEquals(<<assertStringMatchesFormat( <<doDisplay(array \$context, array \$blocks = []): array - › foo bar - › twig source - › - } - %A%eTemplate.php:%d { …} - %s%eTests%eDumper%eCliDumperTest.php:%d { …} -%A } - } -%Awrapper_type: "PHP" - stream_type: "MEMORY" - mode: "%s+b" - unread_bytes: 0 - seekable: true - uri: "php://memory" -%Aoptions: [] -} + stream resource {@{$ref} + ⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {#%d + #message: "Unexpected Exception thrown from a caster: Foobar" + trace: { + %sTwig.php:2 { + __TwigTemplate_VarDumperFixture_u75a09->doDisplay(array \$context, array \$blocks = []): array + › foo bar + › twig source + › + } + %A%eTemplate.php:%d { …} + %s%eTests%eDumper%eCliDumperTest.php:%d { …} + %A } + } + %Awrapper_type: "PHP" + stream_type: "MEMORY" + mode: "%s+b" + unread_bytes: 0 + seekable: true + uri: "php://memory" + %Aoptions: [] + } -EOTXT - , + EOTXT, $out ); } @@ -397,13 +392,12 @@ public function testRefsInProperties() $this->assertStringMatchesFormat( <<assertDumpMatchesFormat( << 'bar'], 0, << "\e[1;38;5;113mbar\e[0;38;5;208m"\e[m -\e[0;38;5;208m]\e[m + \e[0;38;5;208m\e[38;5;38marray:1\e[0;38;5;208m [\e[m + \e[0;38;5;208m"\e[38;5;113mfoo\e[0;38;5;208m" => "\e[1;38;5;113mbar\e[0;38;5;208m"\e[m + \e[0;38;5;208m]\e[m -EOTXT, + EOTXT, ]; yield [[], AbstractDumper::DUMP_LIGHT_ARRAY, "\e[0;38;5;208m[]\e[m\n"]; @@ -442,19 +435,17 @@ public static function provideDumpArrayWithColor() ['foo' => 'bar'], AbstractDumper::DUMP_LIGHT_ARRAY, << "\e[1;38;5;113mbar\e[0;38;5;208m"\e[m -\e[0;38;5;208m]\e[m + \e[0;38;5;208m[\e[m + \e[0;38;5;208m"\e[38;5;113mfoo\e[0;38;5;208m" => "\e[1;38;5;113mbar\e[0;38;5;208m"\e[m + \e[0;38;5;208m]\e[m -EOTXT, + EOTXT, ]; yield [[], 0, "\e[0;38;5;208m[]\e[m\n"]; } - /** - * @dataProvider provideDumpArrayWithColor - */ + #[DataProvider('provideDumpArrayWithColor')] public function testDumpArrayWithColor($value, $flags, $expectedOut) { if ('\\' === \DIRECTORY_SEPARATOR) { @@ -503,15 +494,14 @@ public function testCollapse() $this->assertSame( <<<'EOTXT' -{ - foo: 123 - +"bar": array:1 [ - "bar" => 123 - ] -} + { + foo: 123 + +"bar": array:1 [ + "bar" => 123 + ] + } -EOTXT - , + EOTXT, $dump ); } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php index 5c1415951fc8b..c7ed9fc47f122 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/ContextProvider/RequestContextProviderTest.php @@ -11,15 +11,14 @@ namespace Dumper\ContextProvider; +use PHPUnit\Framework\Attributes\RequiresMethod; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; -/** - * @requires function \Symfony\Component\HttpFoundation\RequestStack::__construct - */ +#[RequiresMethod(RequestStack::class, '__construct')] class RequestContextProviderTest extends TestCase { public function testGetContextOnNullRequest() diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/ContextualizedDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/ContextualizedDumperTest.php index 3c80a5d5dc979..c9c4d110ded10 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/ContextualizedDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/ContextualizedDumperTest.php @@ -19,16 +19,19 @@ /** * @author Kévin Thérage + * + * @backupGlobals */ class ContextualizedDumperTest extends TestCase { public function testContextualizedCliDumper() { + $_ENV['SYMFONY_IDE'] = $_SERVER['SYMFONY_IDE'] = ''; $wrappedDumper = new CliDumper('php://output'); $wrappedDumper->setColors(true); $var = 'example'; - $href = \sprintf('file://%s#L%s', __FILE__, 37); + $href = \sprintf('file://%s#L%s', __FILE__, 40); $dumper = new ContextualizedDumper($wrappedDumper, [new SourceContextProvider()]); $cloner = new VarCloner(); $data = $cloner->cloneVar($var); diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php index c5a2e4e3fbb66..c91855d005302 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\VarDumper\Tests\Dumper; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Component\VarDumper\Caster\ImgStub; use Symfony\Component\VarDumper\Cloner\VarCloner; @@ -55,72 +57,69 @@ public function testGet() $this->assertStringMatchesFormat( <<array:25 [ - "number" => 1 - 0 => &1 null - "const" => 1.1 - 1 => true - 2 => false - 3 => NAN - 4 => INF - 5 => -INF - 6 => {$intMax} - "str" => "d&%s;j&%s;\\n" - 7 => b""" - é\\x01test\\t\\n - ing - """ - "bo\\u{FEFF}m" => "te\\u{FEFF}st" - "[]" => [] - "res" => stream resource @{$res} -%A wrapper_type: "plainfile" - stream_type: "STDIO" - mode: "r" - unread_bytes: 0 - seekable: true -%A options: [] - } - "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d - +foo: "foo" - +"bar": "bar" - } - "closure" => Closure(\$a, ?PDO &\$b = null) {#%d - class: "Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest" - this: Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest {#%d &%s;} - file: "%s%eVarDumper%eTests%eFixtures%edumb-var.php" - line: "{$var['line']} to {$var['line']}" - } - "line" => {$var['line']} - "nobj" => array:1 [ - 0 => &3 {#%d} - ] - "recurs" => &4 array:1 [ - 0 => &4 array:1 [&4] - ] - 8 => &1 null - "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} - "snobj" => &3 {#%d} - "snobj2" => {#%d} - "file" => "{$var['file']}" - b"bin-key-&%s;" => "" -] - - -EOTXT - , + array:25 [ + "number" => 1 + 0 => &1 null + "const" => 1.1 + 1 => true + 2 => false + 3 => NAN + 4 => INF + 5 => -INF + 6 => {$intMax} + "str" => "d&%s;j&%s;\\n" + 7 => b""" + é\\x01test\\t\\n + ing + """ + "bo\\u{FEFF}m" => "te\\u{FEFF}st" + "[]" => [] + "res" => stream resource @{$res} + %A wrapper_type: "plainfile" + stream_type: "STDIO" + mode: "r" + unread_bytes: 0 + seekable: true + %A options: [] + } + "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d + +foo: "foo" + +"bar": "bar" + } + "closure" => Closure(\$a, ?PDO &\$b = null) {#%d + class: "Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest" + this: Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest {#%d &%s;} + file: "%s%eVarDumper%eTests%eFixtures%edumb-var.php" + line: "{$var['line']} to {$var['line']}" + } + "line" => {$var['line']} + "nobj" => array:1 [ + 0 => &3 {#%d} + ] + "recurs" => &4 array:1 [ + 0 => &4 array:1 [&4] + ] + 8 => &1 null + "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} + "snobj" => &3 {#%d} + "snobj2" => {#%d} + "file" => "{$var['file']}" + b"bin-key-&%s;" => "" + ] + + + EOTXT, $out ); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testVirtualProperties() { $dumper = new HtmlDumper('php://output'); @@ -139,7 +138,9 @@ public function testVirtualProperties() -noType: ~ } - EODUMP, $out); + EODUMP, + $out + ); } public function testCharset() @@ -156,11 +157,10 @@ public function testCharset() $this->assertStringMatchesFormat( <<<'EOTXT' -b"Словарь" - + b"Словарь" + -EOTXT - , + EOTXT, $out ); } @@ -180,20 +180,17 @@ public function testAppend() $out = stream_get_contents($out, -1, 0); $this->assertSame(<<<'EOTXT' -123 - -456 - + 123 + + 456 + -EOTXT - , + EOTXT, $out ); } - /** - * @dataProvider varToDumpProvider - */ + #[DataProvider('varToDumpProvider')] public function testDumpString($var, $needle) { $dumper = new HtmlDumper(); diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/ServerDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/ServerDumperTest.php index 0a7d68b0ec554..16fdbd20ed9c3 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/ServerDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/ServerDumperTest.php @@ -74,16 +74,17 @@ public function getContext(): ?array $this->assertTrue($process->isSuccessful()); $this->assertStringMatchesFormat(<<<'DUMP' -(3) "foo" -[ - "timestamp" => %d.%d - "foo_provider" => [ - (3) "foo" - ] -] -%d -DUMP - , $dumped); + (3) "foo" + [ + "timestamp" => %d.%d + "foo_provider" => [ + (3) "foo" + ] + ] + %d + DUMP, + $dumped + ); } private function getServerProcess(): Process diff --git a/src/Symfony/Component/VarDumper/Tests/Server/ConnectionTest.php b/src/Symfony/Component/VarDumper/Tests/Server/ConnectionTest.php index 56553e6df79fc..624eb845d73af 100644 --- a/src/Symfony/Component/VarDumper/Tests/Server/ConnectionTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Server/ConnectionTest.php @@ -56,17 +56,18 @@ public function getContext(): ?array $this->assertTrue($process->isSuccessful()); $this->assertStringMatchesFormat(<<<'DUMP' -(3) "foo" -[ - "timestamp" => %d.%d - "foo_provider" => [ - (3) "foo" - ] -] -%d + (3) "foo" + [ + "timestamp" => %d.%d + "foo_provider" => [ + (3) "foo" + ] + ] + %d -DUMP - , $dumped); + DUMP, + $dumped + ); } public function testNoServer() diff --git a/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php b/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php index 0c5aa7c19412b..2f7b657592caf 100644 --- a/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php @@ -28,13 +28,13 @@ public function testItComparesLargeData() $expected = \sprintf("array:%d [\n", $howMany + 1); for ($i = 0; $i <= $howMany; ++$i) { $expected .= << array:4 [ - 0 => "a" - 1 => "b" - 2 => "c" - 3 => "d" - ]\n -EODUMP; + $i => array:4 [ + 0 => "a" + 1 => "b" + 2 => "c" + 3 => "d" + ]\n + EODUMP; } $expected .= "]\n"; @@ -60,15 +60,16 @@ public function testItCanBeConfigured() $this->assertSame($casters, $this->varDumperConfig['casters']); $this->assertDumpEquals(<<tearDownVarDumper(); diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index d11e55924ca2c..bffa992ec6eac 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -21,10 +21,10 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", "twig/twig": "^3.12" }, "conflict": { diff --git a/src/Symfony/Component/VarDumper/phpunit.xml.dist b/src/Symfony/Component/VarDumper/phpunit.xml.dist index a629967b7baa2..a67c97251efbe 100644 --- a/src/Symfony/Component/VarDumper/phpunit.xml.dist +++ b/src/Symfony/Component/VarDumper/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -21,7 +22,7 @@ - + ./ @@ -30,5 +31,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Component/VarExporter/Internal/Exporter.php b/src/Symfony/Component/VarExporter/Internal/Exporter.php index 75954dbf3e759..6de4138fd798a 100644 --- a/src/Symfony/Component/VarExporter/Internal/Exporter.php +++ b/src/Symfony/Component/VarExporter/Internal/Exporter.php @@ -76,33 +76,23 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount $class = $value::class; $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); $properties = []; + $sleep = null; + $proto = Registry::$prototypes[$class]; if ($reflector->hasMethod('__serialize')) { if (!$reflector->getMethod('__serialize')->isPublic()) { throw new \Error(\sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); } - if (!\is_array($serializeProperties = $value->__serialize())) { + if (!\is_array($arrayValue = $value->__serialize())) { throw new \TypeError($class.'::__serialize() must return an array'); } if ($reflector->hasMethod('__unserialize')) { - $properties = $serializeProperties; - } else { - foreach ($serializeProperties as $n => $v) { - $p = $reflector->hasProperty($n) ? $reflector->getProperty($n) : null; - $c = $p && (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly()) ? $p->class : 'stdClass'; - $properties[$c][$n] = $v; - } + $properties = $arrayValue; + goto prepare_value; } - - goto prepare_value; - } - - $sleep = null; - $proto = Registry::$prototypes[$class]; - - if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { + } elseif (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { // ArrayIterator and ArrayObject need special care because their "flags" // option changes the behavior of the (array) casting operator. [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto); @@ -118,9 +108,7 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount } $properties = ['SplObjectStorage' => ["\0" => $properties]]; $arrayValue = (array) $value; - } elseif ($value instanceof \Serializable - || $value instanceof \__PHP_Incomplete_Class - ) { + } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class) { ++$objectsCount; $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; $value = new Reference($id); @@ -144,16 +132,15 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount $i = 0; $n = (string) $name; if ('' === $n || "\0" !== $n[0]) { - $p = $reflector->hasProperty($n) ? $reflector->getProperty($n) : null; - $c = $p && (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly()) ? $p->class : 'stdClass'; + $parent = $reflector; + do { + $p = $parent->hasProperty($n) ? $parent->getProperty($n) : null; + } while (!$p && $parent = $parent->getParentClass()); + + $c = $p && (!$p->isPublic() || (\PHP_VERSION_ID >= 80400 ? $p->isProtectedSet() || $p->isPrivateSet() : $p->isReadOnly())) ? $p->class : 'stdClass'; } elseif ('*' === $n[1]) { $n = substr($n, 3); $c = $reflector->getProperty($n)->class; - if ('Error' === $c) { - $c = 'TypeError'; - } elseif ('Exception' === $c) { - $c = 'ErrorException'; - } } else { $i = strpos($n, "\0", 2); $c = substr($n, 1, $i - 1); @@ -166,8 +153,14 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount } unset($sleep[$name], $sleep[$n]); } - if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { + if ("\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { $properties[$c][$n] = $v; + } elseif (!\array_key_exists($name, $proto) || $proto[$name] !== $v) { + $properties[match ($c) { + 'Error' => 'TypeError', + 'Exception' => 'ErrorException', + default => $c, + }][$n] = $v; } } if ($sleep) { diff --git a/src/Symfony/Component/VarExporter/Internal/Hydrator.php b/src/Symfony/Component/VarExporter/Internal/Hydrator.php index 450935e5bdaa3..3c8dde0d36be1 100644 --- a/src/Symfony/Component/VarExporter/Internal/Hydrator.php +++ b/src/Symfony/Component/VarExporter/Internal/Hydrator.php @@ -80,7 +80,7 @@ public static function getHydrator($class) if ("\0" === $name) { foreach ($values as $i => $v) { for ($j = 0; $j < \count($v); ++$j) { - $objects[$i]->attach($v[$j], $v[++$j]); + $objects[$i][$v[$j]] = $v[++$j]; } } continue; @@ -188,7 +188,7 @@ public static function getSimpleHydrator($class) continue; } for ($i = 0; $i < \count($value); ++$i) { - $object->attach($value[$i], $value[++$i]); + $object[$value[$i]] = $value[++$i]; } } }; diff --git a/src/Symfony/Component/VarExporter/ProxyHelper.php b/src/Symfony/Component/VarExporter/ProxyHelper.php index 315d3dcf98140..e5014f6eeb272 100644 --- a/src/Symfony/Component/VarExporter/ProxyHelper.php +++ b/src/Symfony/Component/VarExporter/ProxyHelper.php @@ -221,20 +221,20 @@ public static function generateLazyProxy(?\ReflectionClass $class, array $interf if ('get' === $hook) { $ref = ($method->returnsReference() ? '&' : ''); $hooks .= <<lazyObjectState->realInstance->{$p->name}; - } + {$ref}get { + return \$this->lazyObjectState->realInstance->{$p->name}; + } - EOPHP; + EOPHP; } elseif ('set' === $hook) { $parameters = self::exportParameters($method, true); $arg = '$'.$method->getParameters()[0]->name; $hooks .= <<lazyObjectState->realInstance->{$p->name} = {$arg}; - } + set({$parameters}) { + \$this->lazyObjectState->realInstance->{$p->name} = {$arg}; + } - EOPHP; + EOPHP; } else { throw new LogicException(\sprintf('Cannot generate lazy proxy: hook "%s::%s()" is not supported.', $class->name, $method->name)); } @@ -277,8 +277,8 @@ public static function generateLazyProxy(?\ReflectionClass $class, array $interf $body = " throw new \BadMethodCallException('Cannot forward abstract method \"{$method->class}::{$method->name}()\".');"; } elseif (str_ends_with($signature, '): never') || str_ends_with($signature, '): void')) { $body = <<lazyObjectState->realInstance->{$method->name}({$args}); - EOPHP; + \$this->lazyObjectState->realInstance->{$method->name}({$args}); + EOPHP; } else { $mayReturnThis = false; foreach (preg_split('/[()|&]++/', self::exportType($method) ?? 'static') as $type) { @@ -296,19 +296,19 @@ public static function generateLazyProxy(?\ReflectionClass $class, array $interf if ($method->returnsReference() || !$mayReturnThis) { $body = <<lazyObjectState->realInstance->{$method->name}({$args}); - EOPHP; + return \$this->lazyObjectState->realInstance->{$method->name}({$args}); + EOPHP; } else { $body = <<lazyObjectState->realInstance; - \${1} = \${0}->{$method->name}({$args}); - - return match (true) { - \${1} === \${0} => \$this, - !\${1} instanceof \${0} || !\${0} instanceof \${1} => \${1}, - null !== \$this->lazyObjectState->cloneInstance =& \${1} => clone \$this, - }; - EOPHP; + \${0} = \$this->lazyObjectState->realInstance; + \${1} = \${0}->{$method->name}({$args}); + + return match (true) { + \${1} === \${0} => \$this, + !\${1} instanceof \${0} || !\${0} instanceof \${1} => \${1}, + null !== \$this->lazyObjectState->cloneInstance =& \${1} => clone \$this, + }; + EOPHP; } } $methods[$lcName] = " {$signature}\n {\n{$body}\n }"; @@ -351,14 +351,14 @@ public function __unserialize(\$data): void if ($lazyProxyTraitStatement) { $lazyProxyTraitStatement = implode("\n ", $lazyProxyTraitStatement); $lazyProxyTraitStatement = <<lazyObjectState)) { - (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); - } else { - {$parentCall}; - } - EOPHP; + if (isset(\$this->lazyObjectState)) { + (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); + } else { + {$parentCall}; + } + EOPHP; } else { if (!$methodsHaveToBeProxied && !$method->isAbstract()) { // Skip proxying methods that might return $this @@ -459,12 +459,12 @@ private static function generateLegacyLazyProxy(?\ReflectionClass $class, array } $body = <<lazyObjectState)) { - return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); - } + if (isset(\$this->lazyObjectState)) { + return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); + } - return {$parentCall}; - EOPHP; + return {$parentCall}; + EOPHP; } $methods[$lcName] = " {$signature}\n {\n{$body}\n }"; } @@ -491,10 +491,10 @@ private static function generateLegacyLazyProxy(?\ReflectionClass $class, array ) { // fix contravariance type problem when $class declares a `__unserialize()` method without typehint. $lazyProxyTraitStatement = << [ + 'Symfony\\Component\\VarExporter\\Tests\\ParentOf__SerializeButNo__Unserialize' => [ 'foo' => [ + 'foo', + ], + ], + 'stdClass' => [ + 'baz' => [ 'ccc', ], ], + 'Symfony\\Component\\VarExporter\\Tests\\__SerializeButNo__Unserialize' => [ + 'bar' => [ + 'ddd', + ], + ], ], $o[0], [] diff --git a/src/Symfony/Component/VarExporter/Tests/InstantiatorTest.php b/src/Symfony/Component/VarExporter/Tests/InstantiatorTest.php index 062d4ea83fec9..be01ca4688ca9 100644 --- a/src/Symfony/Component/VarExporter/Tests/InstantiatorTest.php +++ b/src/Symfony/Component/VarExporter/Tests/InstantiatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\VarExporter\Exception\ClassNotFoundException; use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; @@ -25,9 +26,7 @@ public function testNotFoundClass() Instantiator::instantiate('SomeNotExistingClass'); } - /** - * @dataProvider provideFailingInstantiation - */ + #[DataProvider('provideFailingInstantiation')] public function testFailingInstantiation(string $class) { $this->expectException(NotInstantiableTypeException::class); diff --git a/src/Symfony/Component/VarExporter/Tests/LazyProxyTraitTest.php b/src/Symfony/Component/VarExporter/Tests/LazyProxyTraitTest.php index 9e0ab515c9fee..b5544de8edb8a 100644 --- a/src/Symfony/Component/VarExporter/Tests/LazyProxyTraitTest.php +++ b/src/Symfony/Component/VarExporter/Tests/LazyProxyTraitTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; @@ -31,9 +32,7 @@ use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\TestWakeupClass; use Symfony\Component\VarExporter\Tests\Fixtures\SimpleObject; -/** - * @requires PHP 8.4 - */ +#[RequiresPhp('8.4')] class LazyProxyTraitTest extends TestCase { public function testGetter() @@ -292,9 +291,7 @@ public function testReinitRegularLazyProxy() $this->assertSame(234, $object->foo); } - /** - * @requires PHP 8.3 - */ + #[RequiresPhp('8.3')] public function testReinitReadonlyLazyProxy() { $object = $this->createLazyProxy(ReadOnlyClass::class, fn () => new ConcreteReadOnlyClass(123)); @@ -306,9 +303,7 @@ public function testReinitReadonlyLazyProxy() $this->assertSame(234, $object->foo); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testConcretePropertyHooks() { $initialized = false; @@ -335,9 +330,7 @@ public function testConcretePropertyHooks() $this->assertSame(345, $object->backed); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testAbstractPropertyHooks() { $initialized = false; @@ -369,9 +362,7 @@ public function testAbstractPropertyHooks() $this->assertTrue($initialized); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testAsymmetricVisibility() { $object = $this->createLazyProxy(AsymmetricVisibility::class, function () { diff --git a/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php b/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php index 2060e35dc41dd..925ede12adca5 100644 --- a/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php +++ b/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php @@ -11,6 +11,10 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; @@ -29,9 +33,8 @@ use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\HookedWithDefaultValue; use Symfony\Component\VarExporter\Tests\Fixtures\SimpleObject; -/** - * @group legacy - */ +#[IgnoreDeprecations] +#[Group('legacy')] class LegacyLazyGhostTraitTest extends TestCase { public function testGetPublic() @@ -139,9 +142,7 @@ public function testSerialize() $this->assertTrue($clone->isLazyObjectInitialized()); } - /** - * @dataProvider provideMagicClass - */ + #[DataProvider('provideMagicClass')] public function testMagicClass(MagicClass $instance) { $this->assertSame('bar', $instance->foo); @@ -241,9 +242,7 @@ public function testIndirectModification() $this->assertSame([123], $proxy->foo); } - /** - * @requires PHP 8.3 - */ + #[RequiresPhp('8.3')] public function testReadOnlyClass() { $proxy = $this->createLazyGhost(ReadOnlyClass::class, fn ($proxy) => $proxy->__construct(123)); @@ -297,9 +296,7 @@ public function testReinitLazyGhost() $this->assertSame(3, $object->public); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testPropertyHooks() { $initialized = false; @@ -322,9 +319,7 @@ public function testPropertyHooks() $this->assertSame(345, $object->backed); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testPropertyHooksWithDefaultValue() { $initialized = false; @@ -350,9 +345,7 @@ public function testPropertyHooksWithDefaultValue() $this->assertTrue($object->backedBoolWithDefault); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testAsymmetricVisibility() { $object = $this->createLazyGhost(AsymmetricVisibility::class, function ($instance) { diff --git a/src/Symfony/Component/VarExporter/Tests/LegacyLazyProxyTraitTest.php b/src/Symfony/Component/VarExporter/Tests/LegacyLazyProxyTraitTest.php index 383b08fe82e22..c19a9b219252a 100644 --- a/src/Symfony/Component/VarExporter/Tests/LegacyLazyProxyTraitTest.php +++ b/src/Symfony/Component/VarExporter/Tests/LegacyLazyProxyTraitTest.php @@ -11,16 +11,17 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\RequiresPhp; use Symfony\Component\VarExporter\LazyProxyTrait; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\FinalPublicClass; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\TestClass; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\TestOverwritePropClass; -/** - * @requires PHP < 8.4 - * - * @group legacy - */ +#[IgnoreDeprecations] +#[Group('legacy')] +#[RequiresPhp('<8.4')] class LegacyLazyProxyTraitTest extends LazyProxyTraitTest { public function testLazyDecoratorClass() diff --git a/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php b/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php index 71c46c448ac1d..96845ffed0987 100644 --- a/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php +++ b/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php @@ -11,61 +11,62 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\RequiresPhp; use Symfony\Component\VarExporter\Exception\LogicException; use Symfony\Component\VarExporter\ProxyHelper; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\Php82NullStandaloneReturnType; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\StringMagicGetClass; -/** - * @requires PHP < 8.4 - * - * @group legacy - */ +#[IgnoreDeprecations] +#[Group('legacy')] +#[RequiresPhp('<8.4')] class LegacyProxyHelperTest extends ProxyHelperTest { public function testGenerateLazyProxy() { $expected = <<<'EOPHP' - extends \Symfony\Component\VarExporter\Tests\TestForProxyHelper implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\LazyProxyTrait; - - private const LAZY_OBJECT_PROPERTY_SCOPES = []; - - public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar + extends \Symfony\Component\VarExporter\Tests\TestForProxyHelper implements \Symfony\Component\VarExporter\LazyObjectInterface { - if (isset($this->lazyObjectState)) { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo1(...\func_get_args()); - } + use \Symfony\Component\VarExporter\LazyProxyTrait; - return parent::foo1(...\func_get_args()); - } + private const LAZY_OBJECT_PROPERTY_SCOPES = []; - public function foo4(\Symfony\Component\VarExporter\Tests\Bar|string $b, &$d): void - { - if (isset($this->lazyObjectState)) { - ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo4($b, $d, ...\array_slice(\func_get_args(), 2)); - } else { - parent::foo4($b, $d, ...\array_slice(\func_get_args(), 2)); + public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar + { + if (isset($this->lazyObjectState)) { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo1(...\func_get_args()); + } + + return parent::foo1(...\func_get_args()); } - } - protected function foo7() - { - if (isset($this->lazyObjectState)) { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo7(...\func_get_args()); + public function foo4(\Symfony\Component\VarExporter\Tests\Bar|string $b, &$d): void + { + if (isset($this->lazyObjectState)) { + ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo4($b, $d, ...\array_slice(\func_get_args(), 2)); + } else { + parent::foo4($b, $d, ...\array_slice(\func_get_args(), 2)); + } } - return throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelper::foo7()".'); + protected function foo7() + { + if (isset($this->lazyObjectState)) { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo7(...\func_get_args()); + } + + return throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelper::foo7()".'); + } } - } - // Help opcache.preload discover always-needed symbols - class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + // Help opcache.preload discover always-needed symbols + class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); - EOPHP; + EOPHP; $this->assertSame($expected, ProxyHelper::generateLazyProxy(new \ReflectionClass(TestForProxyHelper::class))); } @@ -73,51 +74,51 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); public function testGenerateLazyProxyForInterfaces() { $expected = <<<'EOPHP' - implements \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1, \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2, \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\LazyProxyTrait; + implements \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1, \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2, \Symfony\Component\VarExporter\LazyObjectInterface + { + use \Symfony\Component\VarExporter\LazyProxyTrait; - private const LAZY_OBJECT_PROPERTY_SCOPES = []; + private const LAZY_OBJECT_PROPERTY_SCOPES = []; - public function initializeLazyObject(): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1&\Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 - { - if ($state = $this->lazyObjectState ?? null) { - return $state->realInstance ??= ($state->initializer)(); + public function initializeLazyObject(): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1&\Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 + { + if ($state = $this->lazyObjectState ?? null) { + return $state->realInstance ??= ($state->initializer)(); + } + + return $this; } - return $this; - } + public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar + { + if (isset($this->lazyObjectState)) { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo1(...\func_get_args()); + } - public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar - { - if (isset($this->lazyObjectState)) { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo1(...\func_get_args()); + return throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1::foo1()".'); } - return throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1::foo1()".'); - } + public function foo2(?\Symfony\Component\VarExporter\Tests\Bar $b, ...$d): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 + { + if (isset($this->lazyObjectState)) { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo2(...\func_get_args()); + } - public function foo2(?\Symfony\Component\VarExporter\Tests\Bar $b, ...$d): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 - { - if (isset($this->lazyObjectState)) { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo2(...\func_get_args()); + return throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2::foo2()".'); } - return throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2::foo2()".'); - } - - public static function foo3(): string - { - throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2::foo3()".'); + public static function foo3(): string + { + throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2::foo3()".'); + } } - } - // Help opcache.preload discover always-needed symbols - class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); + // Help opcache.preload discover always-needed symbols + class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); - EOPHP; + EOPHP; $this->assertSame($expected, ProxyHelper::generateLazyProxy(null, [new \ReflectionClass(TestForProxyHelperInterface1::class), new \ReflectionClass(TestForProxyHelperInterface2::class)])); } @@ -129,50 +130,50 @@ public function __unserialize($array): void { } }, <<<'EOPHP' - implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\LazyProxyTrait { - __unserialize as private __doUnserialize; - } + implements \Symfony\Component\VarExporter\LazyObjectInterface + { + use \Symfony\Component\VarExporter\LazyProxyTrait { + __unserialize as private __doUnserialize; + } - private const LAZY_OBJECT_PROPERTY_SCOPES = []; + private const LAZY_OBJECT_PROPERTY_SCOPES = []; - public function __unserialize($data): void - { - $this->__doUnserialize($data); + public function __unserialize($data): void + { + $this->__doUnserialize($data); + } } - } - EOPHP]; + EOPHP]; yield 'type hinted __unserialize method' => [new class { public function __unserialize(array $array): void { } }, <<<'EOPHP' - implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\LazyProxyTrait; + implements \Symfony\Component\VarExporter\LazyObjectInterface + { + use \Symfony\Component\VarExporter\LazyProxyTrait; - private const LAZY_OBJECT_PROPERTY_SCOPES = []; - } - EOPHP]; + private const LAZY_OBJECT_PROPERTY_SCOPES = []; + } + EOPHP]; } public function testAttributes() { $expected = <<<'EOPHP' - public function foo(#[\SensitiveParameter] $a): int - { - if (isset($this->lazyObjectState)) { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo(...\func_get_args()); - } + public function foo(#[\SensitiveParameter] $a): int + { + if (isset($this->lazyObjectState)) { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->foo(...\func_get_args()); + } - return parent::foo(...\func_get_args()); + return parent::foo(...\func_get_args()); + } } - } - EOPHP; + EOPHP; $class = new \ReflectionClass(new class { #[SomeAttribute] diff --git a/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php b/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php index ab396bc902ce6..a868cdf243287 100644 --- a/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php +++ b/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php @@ -11,19 +11,17 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use Symfony\Component\VarExporter\ProxyHelper; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\Hooked; use Symfony\Component\VarExporter\Tests\Fixtures\LazyProxy\Php82NullStandaloneReturnType; -/** - * @requires PHP 8.4 - */ +#[RequiresPhp('8.4')] class ProxyHelperTest extends TestCase { - /** - * @dataProvider provideExportSignature - */ + #[DataProvider('provideExportSignature')] public function testExportSignature(string $expected, \ReflectionMethod $method) { $this->assertSame($expected, ProxyHelper::exportSignature($method)); @@ -48,17 +46,17 @@ public static function provideExportSignature() public function testExportSignatureFQ() { $expected = <<<'EOPHP' - public function bar($a = \Symfony\Component\VarExporter\Tests\Bar::BAZ, - $b = new \Symfony\Component\VarExporter\Tests\Bar(\Symfony\Component\VarExporter\Tests\Bar::BAZ, bar: \Symfony\Component\VarExporter\Tests\Bar::BAZ), - $c = new \stdClass(), - $d = new \Symfony\Component\VarExporter\Tests\TestSignatureFQ(), - $e = new \Symfony\Component\VarExporter\Tests\Bar(), - $f = new \Symfony\Component\VarExporter\Tests\Qux(), - $g = new \Symfony\Component\VarExporter\Tests\Qux(), - $i = new \Qux(), - $j = \stdClass::BAZ, - $k = \Symfony\Component\VarExporter\Tests\Bar) - EOPHP; + public function bar($a = \Symfony\Component\VarExporter\Tests\Bar::BAZ, + $b = new \Symfony\Component\VarExporter\Tests\Bar(\Symfony\Component\VarExporter\Tests\Bar::BAZ, bar: \Symfony\Component\VarExporter\Tests\Bar::BAZ), + $c = new \stdClass(), + $d = new \Symfony\Component\VarExporter\Tests\TestSignatureFQ(), + $e = new \Symfony\Component\VarExporter\Tests\Bar(), + $f = new \Symfony\Component\VarExporter\Tests\Qux(), + $g = new \Symfony\Component\VarExporter\Tests\Qux(), + $i = new \Qux(), + $j = \stdClass::BAZ, + $k = \Symfony\Component\VarExporter\Tests\Bar) + EOPHP; $this->assertSame($expected, str_replace(', $', ",\n$", ProxyHelper::exportSignature(new \ReflectionMethod(TestSignatureFQ::class, 'bar')))); } @@ -66,98 +64,98 @@ public function bar($a = \Symfony\Component\VarExporter\Tests\Bar::BAZ, public function testGenerateLazyProxy() { $expected = <<<'EOPHP' - extends \Symfony\Component\VarExporter\Tests\TestForProxyHelper implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait; - - private const LAZY_OBJECT_PROPERTY_SCOPES = []; - - public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar - { - return $this->lazyObjectState->realInstance->foo1(...\func_get_args()); - } - - public function foo2(?\Symfony\Component\VarExporter\Tests\Bar $b, ...$d): ?\Symfony\Component\VarExporter\Tests\TestForProxyHelper - { - ${0} = $this->lazyObjectState->realInstance; - ${1} = ${0}->foo2(...\func_get_args()); - - return match (true) { - ${1} === ${0} => $this, - !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, - null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, - }; - } - - public function &foo3(\Symfony\Component\VarExporter\Tests\Bar &$b, string &...$c) - { - return $this->lazyObjectState->realInstance->foo3($b, ...$c); - } - - public function foo4(\Symfony\Component\VarExporter\Tests\Bar|string $b, &$d): void - { - $this->lazyObjectState->realInstance->foo4($b, $d, ...\array_slice(\func_get_args(), 2)); - } - - public function foo5($b = new \stdClass([0 => 123]) . \Symfony\Component\VarExporter\Tests\Bar . \Symfony\Component\VarExporter\Tests\Bar::BAR . "a\0b") - { - ${0} = $this->lazyObjectState->realInstance; - ${1} = ${0}->foo5(...\func_get_args()); - - return match (true) { - ${1} === ${0} => $this, - !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, - null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, - }; - } - - protected function foo6($b = null, $c = \PHP_EOL, $d = [\PHP_EOL], $e = [false, true, null]): never - { - $this->lazyObjectState->realInstance->foo6(...\func_get_args()); - } - - protected function foo7() - { - ${0} = $this->lazyObjectState->realInstance; - ${1} = ${0}->foo7(...\func_get_args()); - - return match (true) { - ${1} === ${0} => $this, - !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, - null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, - }; - } - - public function foo9($a = \Symfony\Component\VarExporter\Tests\TestForProxyHelper::BOB, $b = ['$a', "\$a\\n", "\$a\n"], $c = ['$a', "\$a\\n", "\$a\n", new \stdClass()]) + extends \Symfony\Component\VarExporter\Tests\TestForProxyHelper implements \Symfony\Component\VarExporter\LazyObjectInterface { - ${0} = $this->lazyObjectState->realInstance; - ${1} = ${0}->foo9(...\func_get_args()); - - return match (true) { - ${1} === ${0} => $this, - !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, - null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, - }; + use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait; + + private const LAZY_OBJECT_PROPERTY_SCOPES = []; + + public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar + { + return $this->lazyObjectState->realInstance->foo1(...\func_get_args()); + } + + public function foo2(?\Symfony\Component\VarExporter\Tests\Bar $b, ...$d): ?\Symfony\Component\VarExporter\Tests\TestForProxyHelper + { + ${0} = $this->lazyObjectState->realInstance; + ${1} = ${0}->foo2(...\func_get_args()); + + return match (true) { + ${1} === ${0} => $this, + !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, + null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, + }; + } + + public function &foo3(\Symfony\Component\VarExporter\Tests\Bar &$b, string &...$c) + { + return $this->lazyObjectState->realInstance->foo3($b, ...$c); + } + + public function foo4(\Symfony\Component\VarExporter\Tests\Bar|string $b, &$d): void + { + $this->lazyObjectState->realInstance->foo4($b, $d, ...\array_slice(\func_get_args(), 2)); + } + + public function foo5($b = new \stdClass([0 => 123]) . \Symfony\Component\VarExporter\Tests\Bar . \Symfony\Component\VarExporter\Tests\Bar::BAR . "a\0b") + { + ${0} = $this->lazyObjectState->realInstance; + ${1} = ${0}->foo5(...\func_get_args()); + + return match (true) { + ${1} === ${0} => $this, + !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, + null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, + }; + } + + protected function foo6($b = null, $c = \PHP_EOL, $d = [\PHP_EOL], $e = [false, true, null]): never + { + $this->lazyObjectState->realInstance->foo6(...\func_get_args()); + } + + protected function foo7() + { + ${0} = $this->lazyObjectState->realInstance; + ${1} = ${0}->foo7(...\func_get_args()); + + return match (true) { + ${1} === ${0} => $this, + !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, + null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, + }; + } + + public function foo9($a = \Symfony\Component\VarExporter\Tests\TestForProxyHelper::BOB, $b = ['$a', "\$a\\n", "\$a\n"], $c = ['$a', "\$a\\n", "\$a\n", new \stdClass()]) + { + ${0} = $this->lazyObjectState->realInstance; + ${1} = ${0}->foo9(...\func_get_args()); + + return match (true) { + ${1} === ${0} => $this, + !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, + null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, + }; + } + + public function foo10($a = [\M_PI, new \Symfony\Component\VarExporter\Tests\M_PI()]) + { + ${0} = $this->lazyObjectState->realInstance; + ${1} = ${0}->foo10(...\func_get_args()); + + return match (true) { + ${1} === ${0} => $this, + !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, + null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, + }; + } } - public function foo10($a = [\M_PI, new \Symfony\Component\VarExporter\Tests\M_PI()]) - { - ${0} = $this->lazyObjectState->realInstance; - ${1} = ${0}->foo10(...\func_get_args()); - - return match (true) { - ${1} === ${0} => $this, - !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, - null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, - }; - } - } - - // Help opcache.preload discover always-needed symbols - class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); + // Help opcache.preload discover always-needed symbols + class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - EOPHP; + EOPHP; $this->assertSame($expected, ProxyHelper::generateLazyProxy(new \ReflectionClass(TestForProxyHelper::class))); } @@ -165,52 +163,50 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); public function testGenerateLazyProxyForInterfaces() { $expected = <<<'EOPHP' - implements \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1, \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2, \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait; - - private const LAZY_OBJECT_PROPERTY_SCOPES = []; - - public function initializeLazyObject(): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1&\Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 + implements \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1, \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2, \Symfony\Component\VarExporter\LazyObjectInterface { - return $this->lazyObjectState->realInstance; + use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait; + + private const LAZY_OBJECT_PROPERTY_SCOPES = []; + + public function initializeLazyObject(): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface1&\Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 + { + return $this->lazyObjectState->realInstance; + } + + public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar + { + return $this->lazyObjectState->realInstance->foo1(...\func_get_args()); + } + + public function foo2(?\Symfony\Component\VarExporter\Tests\Bar $b, ...$d): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 + { + ${0} = $this->lazyObjectState->realInstance; + ${1} = ${0}->foo2(...\func_get_args()); + + return match (true) { + ${1} === ${0} => $this, + !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, + null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, + }; + } + + public static function foo3(): string + { + throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2::foo3()".'); + } } - public function foo1(): ?\Symfony\Component\VarExporter\Tests\Bar - { - return $this->lazyObjectState->realInstance->foo1(...\func_get_args()); - } + // Help opcache.preload discover always-needed symbols + class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); + class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - public function foo2(?\Symfony\Component\VarExporter\Tests\Bar $b, ...$d): \Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2 - { - ${0} = $this->lazyObjectState->realInstance; - ${1} = ${0}->foo2(...\func_get_args()); - - return match (true) { - ${1} === ${0} => $this, - !${1} instanceof ${0} || !${0} instanceof ${1} => ${1}, - null !== $this->lazyObjectState->cloneInstance =& ${1} => clone $this, - }; - } - - public static function foo3(): string - { - throw new \BadMethodCallException('Cannot forward abstract method "Symfony\Component\VarExporter\Tests\TestForProxyHelperInterface2::foo3()".'); - } - } - - // Help opcache.preload discover always-needed symbols - class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - - EOPHP; + EOPHP; $this->assertSame($expected, ProxyHelper::generateLazyProxy(null, [new \ReflectionClass(TestForProxyHelperInterface1::class), new \ReflectionClass(TestForProxyHelperInterface2::class)])); } - /** - * @dataProvider classWithUnserializeMagicMethodProvider - */ + #[DataProvider('classWithUnserializeMagicMethodProvider')] public function testGenerateLazyProxyForClassWithUnserializeMagicMethod(object $obj, string $expected) { $this->assertStringContainsString($expected, ProxyHelper::generateLazyProxy(new \ReflectionClass($obj::class))); @@ -223,46 +219,46 @@ public function __unserialize($array): void { } }, <<<'EOPHP' - implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait { - __unserialize as private __doUnserialize; - } + implements \Symfony\Component\VarExporter\LazyObjectInterface + { + use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait { + __unserialize as private __doUnserialize; + } - private const LAZY_OBJECT_PROPERTY_SCOPES = []; + private const LAZY_OBJECT_PROPERTY_SCOPES = []; - public function __unserialize($data): void - { - $this->__doUnserialize($data); + public function __unserialize($data): void + { + $this->__doUnserialize($data); + } } - } - EOPHP]; + EOPHP]; yield 'type hinted __unserialize method' => [new class extends \stdClass { public function __unserialize(array $array): void { } }, <<<'EOPHP' - implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait; + implements \Symfony\Component\VarExporter\LazyObjectInterface + { + use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait; - private const LAZY_OBJECT_PROPERTY_SCOPES = []; - } - EOPHP]; + private const LAZY_OBJECT_PROPERTY_SCOPES = []; + } + EOPHP]; } public function testAttributes() { $expected = <<<'EOPHP' - public function foo(#[\SensitiveParameter] $a): int - { - return $this->lazyObjectState->realInstance->foo(...\func_get_args()); + public function foo(#[\SensitiveParameter] $a): int + { + return $this->lazyObjectState->realInstance->foo(...\func_get_args()); + } } - } - EOPHP; + EOPHP; $class = new \ReflectionClass(new class extends \stdClass { #[SomeAttribute] @@ -282,9 +278,7 @@ public function testNullStandaloneReturnType() ); } - /** - * @requires PHP 8.4 - */ + #[RequiresPhp('8.4')] public function testPropertyHooks() { $proxyCode = ProxyHelper::generateLazyProxy(new \ReflectionClass(Hooked::class)); diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php index 6ca98b91487aa..6ac661f630da5 100644 --- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php +++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\VarExporter\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\VarDumper\Test\VarDumperTestTrait; use Symfony\Component\VarExporter\Exception\ClassNotFoundException; @@ -39,9 +40,7 @@ public function testPhpIncompleteClassesAreForbidden() } } - /** - * @dataProvider provideFailingSerialization - */ + #[DataProvider('provideFailingSerialization')] public function testFailingSerialization($value) { $this->expectException(NotInstantiableTypeException::class); @@ -77,9 +76,7 @@ public static function provideFailingSerialization() yield [$a]; } - /** - * @dataProvider provideExport - */ + #[DataProvider('provideExport')] public function testExport(string $testName, $value, bool $staticValueExpected = false) { $dumpedValue = $this->getDump($value); @@ -464,19 +461,33 @@ public function __unserialize(array $data): void } } -class __SerializeButNo__Unserialize +class ParentOf__SerializeButNo__Unserialize { - public $foo; + private $foo = 'foo'; + + public function getFoo() + { + return $this->foo; + } +} + +class __SerializeButNo__Unserialize extends ParentOf__SerializeButNo__Unserialize +{ + public $baz; + private $bar; public function __construct() { - $this->foo = 'ccc'; + $this->baz = 'ccc'; + $this->bar = 'ddd'; } public function __serialize(): array { return [ - 'foo' => $this->foo, + 'foo' => $this->getFoo(), + 'baz' => $this->baz, + 'bar' => $this->bar, ]; } } diff --git a/src/Symfony/Component/VarExporter/composer.json b/src/Symfony/Component/VarExporter/composer.json index 215d3ee56a836..36f1b422ff267 100644 --- a/src/Symfony/Component/VarExporter/composer.json +++ b/src/Symfony/Component/VarExporter/composer.json @@ -20,9 +20,9 @@ "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/property-access": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "autoload": { "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, diff --git a/src/Symfony/Component/VarExporter/phpunit.xml.dist b/src/Symfony/Component/VarExporter/phpunit.xml.dist index 52e3cb005fcbf..bb837da2c24f4 100644 --- a/src/Symfony/Component/VarExporter/phpunit.xml.dist +++ b/src/Symfony/Component/VarExporter/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Component/WebLink/CHANGELOG.md b/src/Symfony/Component/WebLink/CHANGELOG.md index 28dad5abdd749..6da8115f91fcc 100644 --- a/src/Symfony/Component/WebLink/CHANGELOG.md +++ b/src/Symfony/Component/WebLink/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +7.4 +--- + + * Add `HttpHeaderParser` to read `Link` headers from HTTP responses + * Make `HttpHeaderSerializer` non-final + 4.4.0 ----- diff --git a/src/Symfony/Component/WebLink/HttpHeaderParser.php b/src/Symfony/Component/WebLink/HttpHeaderParser.php new file mode 100644 index 0000000000000..fbb2a60c99326 --- /dev/null +++ b/src/Symfony/Component/WebLink/HttpHeaderParser.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\WebLink; + +use Psr\Link\EvolvableLinkProviderInterface; + +/** + * Parse a list of HTTP Link headers into a list of Link instances. + * + * @see https://tools.ietf.org/html/rfc5988 + * + * @author Jérôme Tamarelle + */ +class HttpHeaderParser +{ + // Regex to match each link entry: <...>; param1=...; param2=... + private const LINK_PATTERN = '/<([^>]*)>\s*((?:\s*;\s*[a-zA-Z0-9\-_]+(?:\s*=\s*(?:"(?:[^"\\\\]|\\\\.)*"|[^";,\s]+))?)*)/'; + + // Regex to match parameters: ; key[=value] + private const PARAM_PATTERN = '/;\s*([a-zA-Z0-9\-_]+)(?:\s*=\s*(?:"((?:[^"\\\\]|\\\\.)*)"|([^";,\s]+)))?/'; + + /** + * @param string|string[] $headers Value of the "Link" HTTP header + */ + public function parse(string|array $headers): EvolvableLinkProviderInterface + { + if (\is_array($headers)) { + $headers = implode(', ', $headers); + } + $links = new GenericLinkProvider(); + + if (!preg_match_all(self::LINK_PATTERN, $headers, $matches, \PREG_SET_ORDER)) { + return $links; + } + + foreach ($matches as $match) { + $href = $match[1]; + $attributesString = $match[2]; + + $attributes = []; + if (preg_match_all(self::PARAM_PATTERN, $attributesString, $attributeMatches, \PREG_SET_ORDER)) { + $rels = null; + foreach ($attributeMatches as $pm) { + $key = $pm[1]; + $value = match (true) { + // Quoted value, unescape quotes + ($pm[2] ?? '') !== '' => stripcslashes($pm[2]), + ($pm[3] ?? '') !== '' => $pm[3], + // No value + default => true, + }; + + if ('rel' === $key) { + // Only the first occurrence of the "rel" attribute is read + $rels ??= true === $value ? [] : preg_split('/\s+/', $value, 0, \PREG_SPLIT_NO_EMPTY); + } elseif (\is_array($attributes[$key] ?? null)) { + $attributes[$key][] = $value; + } elseif (isset($attributes[$key])) { + $attributes[$key] = [$attributes[$key], $value]; + } else { + $attributes[$key] = $value; + } + } + } + + $link = new Link(null, $href); + foreach ($rels ?? [] as $rel) { + $link = $link->withRel($rel); + } + foreach ($attributes as $k => $v) { + $link = $link->withAttribute($k, $v); + } + $links = $links->withLink($link); + } + + return $links; + } +} diff --git a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php index 4d537c96f9cb8..d3b686add0baa 100644 --- a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php +++ b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php @@ -20,7 +20,7 @@ * * @author Kévin Dunglas */ -final class HttpHeaderSerializer +class HttpHeaderSerializer { /** * Builds the value of the "Link" HTTP header. diff --git a/src/Symfony/Component/WebLink/Link.php b/src/Symfony/Component/WebLink/Link.php index 1f5fbbdf9c6b5..519194c675206 100644 --- a/src/Symfony/Component/WebLink/Link.php +++ b/src/Symfony/Component/WebLink/Link.php @@ -153,7 +153,7 @@ class Link implements EvolvableLinkInterface private array $rel = []; /** - * @var array + * @var array> */ private array $attributes = []; @@ -181,6 +181,11 @@ public function getRels(): array return array_values($this->rel); } + /** + * Returns a list of attributes that describe the target URI. + * + * @return array> + */ public function getAttributes(): array { return $this->attributes; @@ -210,6 +215,14 @@ public function withoutRel(string $rel): static return $that; } + /** + * Returns an instance with the specified attribute added. + * + * If the specified attribute is already present, it will be overwritten + * with the new value. + * + * @param scalar|\Stringable|list $value + */ public function withAttribute(string $attribute, string|\Stringable|int|float|bool|array $value): static { $that = clone $this; diff --git a/src/Symfony/Component/WebLink/Tests/HttpHeaderParserTest.php b/src/Symfony/Component/WebLink/Tests/HttpHeaderParserTest.php new file mode 100644 index 0000000000000..210e85a4417e3 --- /dev/null +++ b/src/Symfony/Component/WebLink/Tests/HttpHeaderParserTest.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\WebLink\Tests; + +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; +use Symfony\Component\WebLink\HttpHeaderParser; + +class HttpHeaderParserTest extends TestCase +{ + public function testParse() + { + $parser = new HttpHeaderParser(); + + $header = [ + '; rel="prerender",; rel="dns-prefetch"; pr="0.7",; rel="preload"; as="script"', + '; rel="preload"; as="image"; nopush,; rel="alternate next"; hreflang="fr"; hreflang="de"; title="Hello"', + ]; + $provider = $parser->parse($header); + $links = $provider->getLinks(); + + self::assertCount(5, $links); + + self::assertSame(['prerender'], $links[0]->getRels()); + self::assertSame('/1', $links[0]->getHref()); + self::assertSame([], $links[0]->getAttributes()); + + self::assertSame(['dns-prefetch'], $links[1]->getRels()); + self::assertSame('/2', $links[1]->getHref()); + self::assertSame(['pr' => '0.7'], $links[1]->getAttributes()); + + self::assertSame(['preload'], $links[2]->getRels()); + self::assertSame('/3', $links[2]->getHref()); + self::assertSame(['as' => 'script'], $links[2]->getAttributes()); + + self::assertSame(['preload'], $links[3]->getRels()); + self::assertSame('/4', $links[3]->getHref()); + self::assertSame(['as' => 'image', 'nopush' => true], $links[3]->getAttributes()); + + self::assertSame(['alternate', 'next'], $links[4]->getRels()); + self::assertSame('/5', $links[4]->getHref()); + self::assertSame(['hreflang' => ['fr', 'de'], 'title' => 'Hello'], $links[4]->getAttributes()); + } + + public function testParseEmpty() + { + $parser = new HttpHeaderParser(); + $provider = $parser->parse(''); + self::assertCount(0, $provider->getLinks()); + } + + #[DataProvider('provideHeaderParsingCases')] + public function testParseVariousAttributes(string $header, array $expectedRels, array $expectedAttributes) + { + $parser = new HttpHeaderParser(); + $links = $parser->parse($header)->getLinks(); + + self::assertCount(1, $links); + self::assertSame('/foo', $links[0]->getHref()); + self::assertSame($expectedRels, $links[0]->getRels()); + self::assertSame($expectedAttributes, $links[0]->getAttributes()); + } + + public static function provideHeaderParsingCases() + { + yield 'double_quotes_in_attribute_value' => [ + '; rel="alternate"; title="\"escape me\" \"already escaped\" \"\"\""', + ['alternate'], + ['title' => '"escape me" "already escaped" """'], + ]; + + yield 'unquoted_attribute_value' => [ + '; rel=alternate; type=text/html', + ['alternate'], + ['type' => 'text/html'], + ]; + + yield 'attribute_with_punctuation' => [ + '; rel="alternate"; title=">; hello, world; test:case"', + ['alternate'], + ['title' => '>; hello, world; test:case'], + ]; + + yield 'no_rel' => [ + '; type=text/html', + [], + ['type' => 'text/html'], + ]; + + yield 'empty_rel' => [ + '; rel', + [], + [], + ]; + + yield 'multiple_rel_attributes_get_first' => [ + '; rel="alternate" rel="next"', + ['alternate'], + [], + ]; + } +} diff --git a/src/Symfony/Component/WebLink/Tests/LinkTest.php b/src/Symfony/Component/WebLink/Tests/LinkTest.php index 226bc3af11620..a32501f79e97b 100644 --- a/src/Symfony/Component/WebLink/Tests/LinkTest.php +++ b/src/Symfony/Component/WebLink/Tests/LinkTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\WebLink\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\WebLink\Link; @@ -27,10 +28,10 @@ public function testCanSetAndRetrieveValues() ->withAttribute('me', 'you') ; - $this->assertEquals('http://www.google.com', $link->getHref()); + $this->assertSame('http://www.google.com', $link->getHref()); $this->assertContains('next', $link->getRels()); $this->assertArrayHasKey('me', $link->getAttributes()); - $this->assertEquals('you', $link->getAttributes()['me']); + $this->assertSame('you', $link->getAttributes()['me']); } public function testCanRemoveValues() @@ -44,7 +45,7 @@ public function testCanRemoveValues() $link = $link->withoutAttribute('me') ->withoutRel('next'); - $this->assertEquals('http://www.google.com', $link->getHref()); + $this->assertSame('http://www.google.com', $link->getHref()); $this->assertFalse(\in_array('next', $link->getRels(), true)); $this->assertArrayNotHasKey('me', $link->getAttributes()); } @@ -65,13 +66,11 @@ public function testConstructor() { $link = new Link('next', 'http://www.google.com'); - $this->assertEquals('http://www.google.com', $link->getHref()); + $this->assertSame('http://www.google.com', $link->getHref()); $this->assertContains('next', $link->getRels()); } - /** - * @dataProvider templatedHrefProvider - */ + #[DataProvider('templatedHrefProvider')] public function testTemplated(string $href) { $link = (new Link()) @@ -80,9 +79,7 @@ public function testTemplated(string $href) $this->assertTrue($link->isTemplated()); } - /** - * @dataProvider notTemplatedHrefProvider - */ + #[DataProvider('notTemplatedHrefProvider')] public function testNotTemplated(string $href) { $link = (new Link()) diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index 3203f6fa83163..0d7ca7857629a 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -23,7 +23,7 @@ "psr/link": "^1.1|^2.0" }, "require-dev": { - "symfony/http-kernel": "^6.4|^7.0" + "symfony/http-kernel": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/http-kernel": "<6.4" diff --git a/src/Symfony/Component/WebLink/phpunit.xml.dist b/src/Symfony/Component/WebLink/phpunit.xml.dist index 660c6b2d95694..c533bb7cbfa70 100644 --- a/src/Symfony/Component/WebLink/phpunit.xml.dist +++ b/src/Symfony/Component/WebLink/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -26,5 +27,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Component/Webhook/Tests/Controller/WebhookControllerTest.php b/src/Symfony/Component/Webhook/Tests/Controller/WebhookControllerTest.php index 1a3d5196e1e5b..50c730f4f70ae 100644 --- a/src/Symfony/Component/Webhook/Tests/Controller/WebhookControllerTest.php +++ b/src/Symfony/Component/Webhook/Tests/Controller/WebhookControllerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Webhook\Tests\Controller; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -32,9 +33,7 @@ public function testNoParserAvailable() $this->assertSame(404, $response->getStatusCode()); } - /** - * @dataProvider rejectedParseProvider - */ + #[DataProvider('rejectedParseProvider')] public function testParserRejectsPayload($return) { $secret = '1234'; diff --git a/src/Symfony/Component/Webhook/composer.json b/src/Symfony/Component/Webhook/composer.json index 46ce35b5d90cb..035817b066383 100644 --- a/src/Symfony/Component/Webhook/composer.json +++ b/src/Symfony/Component/Webhook/composer.json @@ -17,14 +17,14 @@ ], "require": { "php": ">=8.2", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/remote-event": "^6.4|^7.0" + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/remote-event": "^6.4|^7.0|^8.0" }, "require-dev": { - "symfony/http-client": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Webhook\\": "" }, diff --git a/src/Symfony/Component/Webhook/phpunit.xml.dist b/src/Symfony/Component/Webhook/phpunit.xml.dist index ff3020250d20c..0cfad7da6125e 100644 --- a/src/Symfony/Component/Webhook/phpunit.xml.dist +++ b/src/Symfony/Component/Webhook/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -26,5 +27,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Component/Workflow/Tests/Attribute/AsListenerTest.php b/src/Symfony/Component/Workflow/Tests/Attribute/AsListenerTest.php index 0a8c232571c47..065657428693b 100644 --- a/src/Symfony/Component/Workflow/Tests/Attribute/AsListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/Attribute/AsListenerTest.php @@ -11,15 +11,14 @@ namespace Symfony\Component\Workflow\Tests\Attribute; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Workflow\Attribute; use Symfony\Component\Workflow\Exception\LogicException; class AsListenerTest extends TestCase { - /** - * @dataProvider provideOkTests - */ + #[DataProvider('provideOkTests')] public function testOk(string $class, string $expectedEvent, ?string $workflow = null, ?string $node = null) { $attribute = new $class($workflow, $node); @@ -58,9 +57,7 @@ public static function provideOkTests(): iterable yield [Attribute\AsTransitionListener::class, 'workflow.w.transition.n', 'w', 'n']; } - /** - * @dataProvider provideTransitionThrowException - */ + #[DataProvider('provideTransitionThrowException')] public function testTransitionThrowException(string $class) { $this->expectException(LogicException::class); @@ -71,15 +68,13 @@ public function testTransitionThrowException(string $class) public static function provideTransitionThrowException(): iterable { - yield [Attribute\AsAnnounceListener::class, 'workflow.announce']; - yield [Attribute\AsCompletedListener::class, 'workflow.completed']; - yield [Attribute\AsGuardListener::class, 'workflow.guard']; - yield [Attribute\AsTransitionListener::class, 'workflow.transition']; + yield [Attribute\AsAnnounceListener::class]; + yield [Attribute\AsCompletedListener::class]; + yield [Attribute\AsGuardListener::class]; + yield [Attribute\AsTransitionListener::class]; } - /** - * @dataProvider providePlaceThrowException - */ + #[DataProvider('providePlaceThrowException')] public function testPlaceThrowException(string $class) { $this->expectException(LogicException::class); @@ -90,8 +85,8 @@ public function testPlaceThrowException(string $class) public static function providePlaceThrowException(): iterable { - yield [Attribute\AsEnteredListener::class, 'workflow.entered']; - yield [Attribute\AsEnterListener::class, 'workflow.enter']; - yield [Attribute\AsLeaveListener::class, 'workflow.leave']; + yield [Attribute\AsEnteredListener::class]; + yield [Attribute\AsEnterListener::class]; + yield [Attribute\AsLeaveListener::class]; } } diff --git a/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php b/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php index 257ad66eea8b8..d513450f1e908 100644 --- a/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/Debug/TraceableWorkflowTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Workflow\Tests\Debug; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Stopwatch\Stopwatch; @@ -38,9 +39,7 @@ protected function setUp(): void ); } - /** - * @dataProvider provideFunctionNames - */ + #[DataProvider('provideFunctionNames')] public function testCallsInner(string $function, array $args, mixed $returnValue) { $this->innerWorkflow->expects($this->once()) diff --git a/src/Symfony/Component/Workflow/Tests/Dumper/GraphvizDumperTest.php b/src/Symfony/Component/Workflow/Tests/Dumper/GraphvizDumperTest.php index 935671517fd02..228c496c12a32 100644 --- a/src/Symfony/Component/Workflow/Tests/Dumper/GraphvizDumperTest.php +++ b/src/Symfony/Component/Workflow/Tests/Dumper/GraphvizDumperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Workflow\Tests\Dumper; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Workflow\Dumper\GraphvizDumper; use Symfony\Component\Workflow\Marking; @@ -20,9 +21,7 @@ class GraphvizDumperTest extends TestCase { use WorkflowBuilderTrait; - /** - * @dataProvider provideWorkflowDefinitionWithoutMarking - */ + #[DataProvider('provideWorkflowDefinitionWithoutMarking')] public function testDumpWithoutMarking($definition, $expected, $withMetadata) { $dump = (new GraphvizDumper())->dump($definition, null, ['with-metadata' => $withMetadata]); @@ -30,9 +29,7 @@ public function testDumpWithoutMarking($definition, $expected, $withMetadata) $this->assertEquals($expected, $dump); } - /** - * @dataProvider provideWorkflowDefinitionWithMarking - */ + #[DataProvider('provideWorkflowDefinitionWithMarking')] public function testDumpWithMarking($definition, $marking, $expected, $withMetadata) { $dump = (new GraphvizDumper())->dump($definition, $marking, ['with-metadata' => $withMetadata]); diff --git a/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php b/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php index a8d1978bac652..639f67ce7e37a 100644 --- a/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php +++ b/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Workflow\Tests\Dumper; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\DefinitionBuilder; @@ -23,9 +24,7 @@ class MermaidDumperTest extends TestCase { use WorkflowBuilderTrait; - /** - * @dataProvider provideWorkflowDefinitionWithoutMarking - */ + #[DataProvider('provideWorkflowDefinitionWithoutMarking')] public function testDumpWithoutMarking(Definition $definition, string $expected) { $dumper = new MermaidDumper(MermaidDumper::TRANSITION_TYPE_WORKFLOW); @@ -35,9 +34,7 @@ public function testDumpWithoutMarking(Definition $definition, string $expected) $this->assertEquals($expected, $dump); } - /** - * @dataProvider provideWorkflowWithReservedWords - */ + #[DataProvider('provideWorkflowWithReservedWords')] public function testDumpWithReservedWordsAsPlacenames(Definition $definition, string $expected) { $dumper = new MermaidDumper(MermaidDumper::TRANSITION_TYPE_WORKFLOW); @@ -47,9 +44,7 @@ public function testDumpWithReservedWordsAsPlacenames(Definition $definition, st $this->assertEquals($expected, $dump); } - /** - * @dataProvider provideStateMachine - */ + #[DataProvider('provideStateMachine')] public function testDumpAsStateMachine(Definition $definition, string $expected) { $dumper = new MermaidDumper(MermaidDumper::TRANSITION_TYPE_STATEMACHINE); @@ -59,9 +54,7 @@ public function testDumpAsStateMachine(Definition $definition, string $expected) $this->assertEquals($expected, $dump); } - /** - * @dataProvider provideWorkflowWithMarking - */ + #[DataProvider('provideWorkflowWithMarking')] public function testDumpWorkflowWithMarking(Definition $definition, Marking $marking, string $expected) { $dumper = new MermaidDumper(MermaidDumper::TRANSITION_TYPE_WORKFLOW); diff --git a/src/Symfony/Component/Workflow/Tests/Dumper/PlantUmlDumperTest.php b/src/Symfony/Component/Workflow/Tests/Dumper/PlantUmlDumperTest.php index a018a4eb8f54d..838c9bd828f03 100644 --- a/src/Symfony/Component/Workflow/Tests/Dumper/PlantUmlDumperTest.php +++ b/src/Symfony/Component/Workflow/Tests/Dumper/PlantUmlDumperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Workflow\Tests\Dumper; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\Dumper\PlantUmlDumper; @@ -23,9 +24,7 @@ class PlantUmlDumperTest extends TestCase { use WorkflowBuilderTrait; - /** - * @dataProvider provideWorkflowDefinitionWithoutMarking - */ + #[DataProvider('provideWorkflowDefinitionWithoutMarking')] public function testDumpWorkflowWithoutMarking($definition, $marking, $expectedFileName, $title) { $dumper = new PlantUmlDumper(PlantUmlDumper::WORKFLOW_TRANSITION); @@ -46,9 +45,7 @@ public static function provideWorkflowDefinitionWithoutMarking(): \Generator yield [self::createComplexWorkflowDefinition(), $marking, 'complex-workflow-marking', 'ComplexDiagram']; } - /** - * @dataProvider provideStateMachineDefinitionWithoutMarking - */ + #[DataProvider('provideStateMachineDefinitionWithoutMarking')] public function testDumpStateMachineWithoutMarking($definition, $marking, $expectedFileName, $title) { $dumper = new PlantUmlDumper(PlantUmlDumper::STATEMACHINE_TRANSITION); diff --git a/src/Symfony/Component/Workflow/Tests/Dumper/StateMachineGraphvizDumperTest.php b/src/Symfony/Component/Workflow/Tests/Dumper/StateMachineGraphvizDumperTest.php index 20b3694f82952..52779e45f9f1f 100644 --- a/src/Symfony/Component/Workflow/Tests/Dumper/StateMachineGraphvizDumperTest.php +++ b/src/Symfony/Component/Workflow/Tests/Dumper/StateMachineGraphvizDumperTest.php @@ -27,23 +27,23 @@ public function testDumpWithoutMarking() $dump = (new StateMachineGraphvizDumper())->dump($definition); $expected = <<<'EOGRAPH' -digraph workflow { - ratio="compress" rankdir="LR" - node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"]; - edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"]; - - place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"]; - place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle]; - place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle]; - place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle]; - place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"]; - place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="My custom transition -label 3" style="solid" fontcolor="Grey" color="Red"]; - place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid" color="Blue"]; - place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_3c363836cf4e16666669a25da280a1865c2d2874 [label="t3" style="solid"]; -} - -EOGRAPH; + digraph workflow { + ratio="compress" rankdir="LR" + node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"]; + edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"]; + + place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"]; + place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle]; + place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle]; + place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle]; + place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"]; + place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="My custom transition + label 3" style="solid" fontcolor="Grey" color="Red"]; + place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid" color="Blue"]; + place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_3c363836cf4e16666669a25da280a1865c2d2874 [label="t3" style="solid"]; + } + + EOGRAPH; $this->assertEquals($expected, $dump); } @@ -54,23 +54,23 @@ public function testDumpWithMarking() $marking = new Marking(['b' => 1]); $expected = <<<'EOGRAPH' -digraph workflow { - ratio="compress" rankdir="LR" - node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"]; - edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"]; - - place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"]; - place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle color="#FF0000" shape="doublecircle"]; - place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle]; - place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle]; - place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"]; - place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="My custom transition -label 3" style="solid" fontcolor="Grey" color="Red"]; - place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid" color="Blue"]; - place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_3c363836cf4e16666669a25da280a1865c2d2874 [label="t3" style="solid"]; -} - -EOGRAPH; + digraph workflow { + ratio="compress" rankdir="LR" + node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="false" width="1"]; + edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"]; + + place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 [label="a", shape=circle style="filled"]; + place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="b", shape=circle color="#FF0000" shape="doublecircle"]; + place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="c", shape=circle]; + place_3c363836cf4e16666669a25da280a1865c2d2874 [label="d", shape=circle]; + place_86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="t1" style="solid"]; + place_3c363836cf4e16666669a25da280a1865c2d2874 -> place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 [label="My custom transition + label 3" style="solid" fontcolor="Grey" color="Red"]; + place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_84a516841ba77a5b4648de2cd0dfcb30ea46dbb4 [label="t2" style="solid" color="Blue"]; + place_e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98 -> place_3c363836cf4e16666669a25da280a1865c2d2874 [label="t3" style="solid"]; + } + + EOGRAPH; $dump = (new StateMachineGraphvizDumper())->dump($definition, $marking); diff --git a/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php b/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php index 3c745234a7304..24780f455570b 100644 --- a/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php +++ b/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Workflow\Tests\Event; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Workflow\Event\AnnounceEvent; use Symfony\Component\Workflow\Event\CompletedEvent; @@ -23,10 +24,9 @@ class EventNameTraitTest extends TestCase { /** - * @dataProvider getEvents - * * @param class-string $class */ + #[DataProvider('getEvents')] public function testEventNames(string $class, ?string $workflowName, ?string $transitionOrPlaceName, string $expected) { $name = $class::getName($workflowName, $transitionOrPlaceName); diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowBuilderTrait.php b/src/Symfony/Component/Workflow/Tests/WorkflowBuilderTrait.php index 86478bba78c47..99a07d7818607 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowBuilderTrait.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowBuilderTrait.php @@ -129,9 +129,9 @@ private static function createComplexStateMachineDefinition(): Definition $transitionsMetadata = new \SplObjectStorage(); // PHP 7.2 doesn't allow this heredoc syntax in an array, use a dedicated variable instead $label = <<<'EOTXT' -My custom transition -label 3 -EOTXT; + My custom transition + label 3 + EOTXT; $transitionsMetadata[$transitionWithMetadataDumpStyle] = [ 'label' => $label, 'color' => 'Grey', diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index 48e2209f2ac03..d44d2c6ff1877 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Workflow\Tests; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Workflow\Definition; @@ -27,6 +29,7 @@ use Symfony\Component\Workflow\TransitionBlocker; use Symfony\Component\Workflow\Workflow; use Symfony\Component\Workflow\WorkflowEvents; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class WorkflowTest extends TestCase { @@ -439,9 +442,7 @@ public static function provideApplyWithEventDispatcherForAnnounceTests(): \Gener yield [true, []]; } - /** - * @dataProvider provideApplyWithEventDispatcherForAnnounceTests - */ + #[DataProvider('provideApplyWithEventDispatcherForAnnounceTests')] public function testApplyWithEventDispatcherForAnnounce(bool $fired, array $context) { $definition = $this->createComplexWorkflowDefinition(); @@ -820,10 +821,8 @@ public function testGetEnabledTransitionsWithSameNameTransition() $this->assertSame('to_a', $transitions[2]->getName()); } - /** - * @@testWith ["back1"] - * ["back2"] - */ + #[TestWith(['back1'])] + #[TestWith(['back2'])] public function testApplyWithSameNameBackTransition(string $transition) { $definition = $this->createWorkflowWithSameNameBackTransition(); @@ -878,7 +877,7 @@ private function assertPlaces(array $expected, Marking $marking) } } -class EventDispatcherMock implements \Symfony\Contracts\EventDispatcher\EventDispatcherInterface +class EventDispatcherMock implements EventDispatcherInterface { public array $dispatchedEvents = []; diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 3e2c50a38cffd..ff8561caa1c88 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -25,15 +25,15 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/validator": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/event-dispatcher": "<6.4" diff --git a/src/Symfony/Component/Workflow/phpunit.xml.dist b/src/Symfony/Component/Workflow/phpunit.xml.dist index 15e5deb058413..f4d82677e0e93 100644 --- a/src/Symfony/Component/Workflow/phpunit.xml.dist +++ b/src/Symfony/Component/Workflow/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -26,5 +27,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 0fab77c569b67..2088d2f1d17d1 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -58,30 +58,30 @@ protected function configure(): void ->addOption('exclude', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Path(s) to exclude') ->addOption('parse-tags', null, InputOption::VALUE_NEGATABLE, 'Parse custom tags', null) ->setHelp(<<%command.name% command lints a YAML file and outputs to STDOUT -the first encountered syntax error. + The %command.name% command lints a YAML file and outputs to STDOUT + the first encountered syntax error. -You can validates YAML contents passed from STDIN: + You can validates YAML contents passed from STDIN: - cat filename | php %command.full_name% - + cat filename | php %command.full_name% - -You can also validate the syntax of a file: + You can also validate the syntax of a file: - php %command.full_name% filename + php %command.full_name% filename -Or of a whole directory: + Or of a whole directory: - php %command.full_name% dirname + php %command.full_name% dirname -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% dirname --format=json + php %command.full_name% dirname --format=json -You can also exclude one or more specific files: + You can also exclude one or more specific files: - php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml" + php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml" -EOF + EOF ) ; } @@ -224,7 +224,7 @@ private function getFiles(string $fileOrDirectory): iterable } foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) { - if (!\in_array($file->getExtension(), ['yml', 'yaml'])) { + if (!\in_array($file->getExtension(), ['yml', 'yaml'], true)) { continue; } diff --git a/src/Symfony/Component/Yaml/Escaper.php b/src/Symfony/Component/Yaml/Escaper.php index 8cc492c579fb3..921d62ffa2c2d 100644 --- a/src/Symfony/Component/Yaml/Escaper.php +++ b/src/Symfony/Component/Yaml/Escaper.php @@ -76,7 +76,7 @@ public static function requiresSingleQuoting(string $value): bool { // Determines if a PHP value is entirely composed of a value that would // require single quoting in YAML. - if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'])) { + if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'], true)) { return true; } diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 1c9fa609d0a25..f98ce3012eccf 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -829,19 +829,19 @@ private static function isBinaryString(string $value): bool private static function getTimestampRegex(): string { return <<[0-9][0-9][0-9][0-9]) - -(?P[0-9][0-9]?) - -(?P[0-9][0-9]?) - (?:(?:[Tt]|[ \t]+) - (?P[0-9][0-9]?) - :(?P[0-9][0-9]) - :(?P[0-9][0-9]) - (?:\.(?P[0-9]*))? - (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) - (?::(?P[0-9][0-9]))?))?)? - $~x -EOF; + ~^ + (?P[0-9][0-9][0-9][0-9]) + -(?P[0-9][0-9]?) + -(?P[0-9][0-9]?) + (?:(?:[Tt]|[ \t]+) + (?P[0-9][0-9]?) + :(?P[0-9][0-9]) + :(?P[0-9][0-9]) + (?:\.(?P[0-9]*))? + (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) + (?::(?P[0-9][0-9]))?))?)? + $~x + EOF; } /** diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index be5890829b64e..fe54a1f2993bb 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -198,7 +198,7 @@ private function doParse(string $value, int $flags): mixed } } elseif ( self::preg_match('#^(?P(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{!].*?)) *\:(( |\t)++(?P.+))?$#u', rtrim($this->currentLine), $values) - && (!str_contains($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"])) + && (!str_contains($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"], true)) ) { if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence.', $this->currentLineNb + 1, $this->currentLine, $this->filename); diff --git a/src/Symfony/Component/Yaml/Resources/bin/yaml-lint b/src/Symfony/Component/Yaml/Resources/bin/yaml-lint index 143869e018148..eca04976f36b6 100755 --- a/src/Symfony/Component/Yaml/Resources/bin/yaml-lint +++ b/src/Symfony/Component/Yaml/Resources/bin/yaml-lint @@ -42,8 +42,13 @@ if (!class_exists(Application::class)) { exit(1); } -(new Application())->add($command = new LintCommand()) - ->getApplication() +$command = new LintCommand(); +if (method_exists($app = new Application(), 'addCommand')) { + $app->addCommand($command); +} else { + $app->add($command); +} +$app ->setDefaultCommand($command->getName(), true) ->run() ; diff --git a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php index a501f48d09e37..cb8a888700416 100644 --- a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Yaml\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; @@ -68,9 +69,9 @@ public function testLintIncorrectFile() public function testLintIncorrectFileWithGithubFormat() { $incorrectContent = <<createCommandTester(); $filename = $this->createFile($incorrectContent); @@ -89,9 +90,9 @@ public function testLintAutodetectsGithubActionEnvironment() putenv('GITHUB_ACTIONS=1'); $incorrectContent = <<createCommandTester(); $filename = $this->createFile($incorrectContent); @@ -106,8 +107,8 @@ public function testLintAutodetectsGithubActionEnvironment() public function testConstantAsKey() { $yaml = <<createCommandTester()->execute(['filename' => $this->createFile($yaml)], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); } @@ -115,8 +116,8 @@ public function testConstantAsKey() public function testCustomTags() { $yaml = <<createCommandTester()->execute(['filename' => $this->createFile($yaml), '--parse-tags' => true], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); } @@ -124,8 +125,8 @@ public function testCustomTags() public function testCustomTagsError() { $yaml = <<createCommandTester()->execute(['filename' => $this->createFile($yaml)], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertSame(1, $ret, 'lint:yaml exits with code 1 in case of error'); } @@ -152,9 +153,7 @@ public function testLintFileNotReadable() $tester->execute(['filename' => $filename], ['decorated' => false]); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $tester = new CommandCompletionTester($this->createCommand()); @@ -180,7 +179,12 @@ private function createFile($content): string protected function createCommand(): Command { $application = new Application(); - $application->add(new LintCommand()); + $command = new LintCommand(); + if (method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } return $application->find('lint:yaml'); } diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 8eac4aee0b54c..f38864753ae05 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Yaml\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Yaml\Dumper; use Symfony\Component\Yaml\Exception\DumpException; @@ -59,26 +60,26 @@ public function testIndentationInConstructor() { $dumper = new Dumper(7); $expected = <<<'EOF' -'': bar -foo: '#bar' -"foo'bar": { } -bar: - - 1 - - foo - - - a: A -foobar: - foo: bar - bar: - - 1 - - foo - foobar: - foo: bar - bar: - - 1 - - foo - -EOF; + '': bar + foo: '#bar' + "foo'bar": { } + bar: + - 1 + - foo + - + a: A + foobar: + foo: bar + bar: + - 1 + - foo + foobar: + foo: bar + bar: + - 1 + - foo + + EOF; $this->assertSame($expected, $dumper->dump($this->array, 4, 0)); $this->assertSameData($this->array, $this->parser->parse($expected)); } @@ -114,83 +115,83 @@ public function testSpecifications() public function testInlineLevel() { $expected = <<<'EOF' -{ '': bar, foo: '#bar', "foo'bar": { }, bar: [1, foo, { a: A }], foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } } -EOF; + { '': bar, foo: '#bar', "foo'bar": { }, bar: [1, foo, { a: A }], foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } } + EOF; $this->assertSame($expected, $this->dumper->dump($this->array, -10), '->dump() takes an inline level argument'); $this->assertSame($expected, $this->dumper->dump($this->array, 0), '->dump() takes an inline level argument'); $this->assertSameData($this->array, $this->parser->parse($expected)); $expected = <<<'EOF' -'': bar -foo: '#bar' -"foo'bar": { } -bar: [1, foo, { a: A }] -foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } + '': bar + foo: '#bar' + "foo'bar": { } + bar: [1, foo, { a: A }] + foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } -EOF; + EOF; $this->assertSame($expected, $this->dumper->dump($this->array, 1), '->dump() takes an inline level argument'); $this->assertSameData($this->array, $this->parser->parse($expected)); $expected = <<<'EOF' -'': bar -foo: '#bar' -"foo'bar": { } -bar: - - 1 - - foo - - { a: A } -foobar: - foo: bar - bar: [1, foo] - foobar: { foo: bar, bar: [1, foo] } - -EOF; + '': bar + foo: '#bar' + "foo'bar": { } + bar: + - 1 + - foo + - { a: A } + foobar: + foo: bar + bar: [1, foo] + foobar: { foo: bar, bar: [1, foo] } + + EOF; $this->assertSame($expected, $this->dumper->dump($this->array, 2), '->dump() takes an inline level argument'); $this->assertSameData($this->array, $this->parser->parse($expected)); $expected = <<<'EOF' -'': bar -foo: '#bar' -"foo'bar": { } -bar: - - 1 - - foo - - - a: A -foobar: - foo: bar - bar: - - 1 - - foo - foobar: - foo: bar - bar: [1, foo] - -EOF; + '': bar + foo: '#bar' + "foo'bar": { } + bar: + - 1 + - foo + - + a: A + foobar: + foo: bar + bar: + - 1 + - foo + foobar: + foo: bar + bar: [1, foo] + + EOF; $this->assertSame($expected, $this->dumper->dump($this->array, 3), '->dump() takes an inline level argument'); $this->assertSameData($this->array, $this->parser->parse($expected)); $expected = <<<'EOF' -'': bar -foo: '#bar' -"foo'bar": { } -bar: - - 1 - - foo - - - a: A -foobar: - foo: bar - bar: - - 1 - - foo - foobar: - foo: bar - bar: - - 1 - - foo - -EOF; + '': bar + foo: '#bar' + "foo'bar": { } + bar: + - 1 + - foo + - + a: A + foobar: + foo: bar + bar: + - 1 + - foo + foobar: + foo: bar + bar: + - 1 + - foo + + EOF; $this->assertSame($expected, $this->dumper->dump($this->array, 4), '->dump() takes an inline level argument'); $this->assertSame($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument'); $this->assertSameData($this->array, $this->parser->parse($expected)); @@ -273,9 +274,7 @@ public function testDumpNullAsEmptyAtRoot() $this->assertSame('null', $this->dumper->dump(null, 2, flags: Yaml::DUMP_NULL_AS_EMPTY)); } - /** - * @dataProvider getEscapeSequences - */ + #[DataProvider('getEscapeSequences')] public function testEscapedEscapeSequencesInQuotedScalar($input, $expected) { $this->assertSame($expected, $this->dumper->dump($input)); @@ -322,9 +321,7 @@ public function testNonUtf8DataIsDumpedBase64Encoded() $this->assertSame('!!binary ZsM/cg==', $this->dumper->dump("f\xc3\x3fr")); } - /** - * @dataProvider objectAsMapProvider - */ + #[DataProvider('objectAsMapProvider')] public function testDumpObjectAsMap($object, $expected) { $yaml = $this->dumper->dump($object, 0, 0, Yaml::DUMP_OBJECT_AS_MAP); @@ -370,13 +367,13 @@ public function testDumpingArrayObjectInstancesRespectsInlineLevel() $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); $expected = <<assertSame($expected, $yaml); } @@ -388,8 +385,8 @@ public function testDumpingArrayObjectInstancesWithNumericKeysInlined() $yaml = $this->dumper->dump($outer, 0, 0, Yaml::DUMP_OBJECT_AS_MAP); $expected = <<assertSame($expected, $yaml); } @@ -400,13 +397,13 @@ public function testDumpingArrayObjectInstancesWithNumericKeysRespectsInlineLeve $outer = new \ArrayObject(['a', $inner]); $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); $expected = <<assertSame($expected, $yaml); } @@ -438,13 +435,13 @@ public function testDumpingStdClassInstancesRespectsInlineLevel() $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); $expected = <<assertSame($expected, $yaml); $this->assertSameData($outer, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); } @@ -464,13 +461,13 @@ public function testDumpingTaggedValueSequenceRespectsInlineLevel() $yaml = $this->dumper->dump($data, 2); $expected = <<assertSame($expected, $yaml); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); } @@ -502,10 +499,10 @@ public function testDumpingTaggedValueTopLevelAssoc() $data = new TaggedValue('user', ['name' => 'jane']); $expected = <<<'YAML' -!user -name: jane + !user + name: jane -YAML; + YAML; $yaml = $this->dumper->dump($data, 2); $this->assertSame($expected, $yaml); } @@ -544,11 +541,11 @@ public function testDumpingTaggedValueSequenceWithInlinedTagValues() $yaml = $this->dumper->dump($data, 1); $expected = <<assertSame($expected, $yaml); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); } @@ -569,14 +566,14 @@ public function testDumpingTaggedValueMapRespectsInlineLevel() $yaml = $this->dumper->dump($data, 2); $expected = <<assertSame($expected, $yaml); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); } @@ -596,10 +593,10 @@ public function testDumpingTaggedValueMapWithInlinedTagValues() $yaml = $this->dumper->dump($data, 1); $expected = <<assertSame($expected, $yaml); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); } @@ -611,10 +608,10 @@ public function testDumpingNotInlinedScalarTaggedValue() 'user2' => new TaggedValue('user', 'john'), ]; $expected = <<assertSame($expected, $this->dumper->dump($data, 2)); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); @@ -626,9 +623,9 @@ public function testDumpingNotInlinedNullTaggedValue() 'foo' => new TaggedValue('bar', null), ]; $expected = <<assertSame($expected, $this->dumper->dump($data, 2)); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_CONSTANT)); @@ -708,10 +705,10 @@ public function testDumpingInlinedMultiLineIfRnBreakLineInTaggedValue() ], ]; $expected = <<<'YAML' -data: - foo: !bar "foo\r\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz" + data: + foo: !bar "foo\r\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz" -YAML; + YAML; $yml = $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $this->assertSame($expected, $yml); $this->assertSameData($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); @@ -731,22 +728,22 @@ public function testDumpMultiLineStringAsScalarBlock() ]; $yml = $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $expected = str_replace("@\n", "\n", <<<'YAML' -data: - single_line: 'foo bar baz' - multi_line: |- - foo - line with trailing spaces: - @ - bar - integer like line: - 123456789 - empty line: - - baz - multi_line_with_carriage_return: "foo\nbar\r\nbaz" - nested_inlined_multi_line_string: { inlined_multi_line: "foo\nbar\r\nempty line:\n\nbaz" } - -YAML + data: + single_line: 'foo bar baz' + multi_line: |- + foo + line with trailing spaces: + @ + bar + integer like line: + 123456789 + empty line: + + baz + multi_line_with_carriage_return: "foo\nbar\r\nbaz" + nested_inlined_multi_line_string: { inlined_multi_line: "foo\nbar\r\nempty line:\n\nbaz" } + + YAML ); $this->assertSame($expected, $yml); $this->assertSame($data, $this->parser->parse($yml)); @@ -819,10 +816,10 @@ public function testCarriageReturnNotFollowedByNewlineIsPreservedWhenDumpingAsMu ], ]; $expected = <<<'YAML' -parent: - foo: "bar\n\rbaz: qux" + parent: + foo: "bar\n\rbaz: qux" -YAML; + YAML; $this->assertSame($expected, $this->dumper->dump($data, 4, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); $this->assertSame($data, $this->parser->parse($expected)); } @@ -861,31 +858,31 @@ public function testDumpTrailingNewlineInMultiLineLiteralBlocks() $yaml = $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $expected = <<assertSame($expected, $yaml); $this->assertSame($data, $this->parser->parse($yaml)); @@ -910,9 +907,7 @@ public function testDumpNullAsTilde() $this->assertSame('{ foo: ~ }', $this->dumper->dump(['foo' => null], 0, 0, Yaml::DUMP_NULL_AS_TILDE)); } - /** - * @dataProvider getForceQuotesOnValuesData - */ + #[DataProvider('getForceQuotesOnValuesData')] public function testCanForceQuotesOnValues(array $input, string $expected) { $this->assertSame($expected, $this->dumper->dump($input, 0, 0, Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES)); @@ -991,9 +986,7 @@ public static function getForceQuotesOnValuesData(): iterable ]; } - /** - * @dataProvider getNumericKeyData - */ + #[DataProvider('getNumericKeyData')] public function testDumpInlineNumericKeyAsString(array $input, bool $inline, int $flags, string $expected) { $this->assertSame($expected, $this->dumper->dump($input, $inline ? 0 : 4, 0, $flags)); @@ -1016,9 +1009,9 @@ public static function getNumericKeyData() ]; $expected = <<<'YAML' - '200': foo + '200': foo - YAML; + YAML; yield 'Int key with flag' => [ [200 => 'foo'], @@ -1028,9 +1021,9 @@ public static function getNumericKeyData() ]; $expected = <<<'YAML' - 200: foo + 200: foo - YAML; + YAML; yield 'Int key without flag' => [ [200 => 'foo'], @@ -1040,10 +1033,10 @@ public static function getNumericKeyData() ]; $expected = <<<'YAML' - - 200 - - foo + - 200 + - foo - YAML; + YAML; yield 'List array with flag' => [ [200, 'foo'], @@ -1053,9 +1046,9 @@ public static function getNumericKeyData() ]; $expected = <<<'YAML' - '200': !number 5 + '200': !number 5 - YAML; + YAML; yield 'Int tagged value with flag' => [ [ @@ -1067,9 +1060,9 @@ public static function getNumericKeyData() ]; $expected = <<<'YAML' - 200: !number 5 + 200: !number 5 - YAML; + YAML; yield 'Int tagged value without flag' => [ [ @@ -1084,11 +1077,11 @@ public static function getNumericKeyData() public function testDumpIdeographicSpaces() { $expected = <<assertSame($expected, $this->dumper->dump([ 'alone' => ' ', 'within_string' => 'a b', @@ -1096,9 +1089,7 @@ public function testDumpIdeographicSpaces() ], 2)); } - /** - * @dataProvider getDateTimeData - */ + #[DataProvider('getDateTimeData')] public function testDumpDateTime(array $input, string $expected) { $this->assertSame($expected, rtrim($this->dumper->dump($input, 1))); @@ -1170,141 +1161,139 @@ public static function getDumpCompactNestedMapping() yield 'Compact nested mapping 1' => [ $data, << [ $data, << [ $data, << [ $data, << [ $data, << + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Yaml\Tests\Fixtures; enum FooBackedEnum: string diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/FooUnitEnum.php b/src/Symfony/Component/Yaml/Tests/Fixtures/FooUnitEnum.php index 59092e27e8728..4a26488e5e5ad 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/FooUnitEnum.php +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/FooUnitEnum.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Yaml\Tests\Fixtures; enum FooUnitEnum diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index 2acc4998e207e..ad1284292bcd0 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -365,7 +365,7 @@ syck: | --- -test: Literal perserves newlines +test: Literal preserves newlines todo: true spec: 2.13 yaml: | diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 7d787afe2630b..e2a69306fda97 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Yaml\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Inline; @@ -26,17 +27,13 @@ protected function setUp(): void Inline::initialize(0, 0); } - /** - * @dataProvider getTestsForParse - */ + #[DataProvider('getTestsForParse')] public function testParse(string $yaml, $value, $flags = 0) { $this->assertSame($value, Inline::parse($yaml, $flags), \sprintf('::parse() converts an inline YAML to a PHP structure (%s)', $yaml)); } - /** - * @dataProvider getTestsForParseWithMapObjects - */ + #[DataProvider('getTestsForParseWithMapObjects')] public function testParseWithMapObjects($yaml, $value, $flags = Yaml::PARSE_OBJECT_FOR_MAP) { $actual = Inline::parse($yaml, $flags); @@ -44,9 +41,7 @@ public function testParseWithMapObjects($yaml, $value, $flags = Yaml::PARSE_OBJE $this->assertSame(serialize($value), serialize($actual)); } - /** - * @dataProvider getTestsForParsePhpConstants - */ + #[DataProvider('getTestsForParsePhpConstants')] public function testParsePhpConstants($yaml, $value) { $actual = Inline::parse($yaml, Yaml::PARSE_CONSTANT); @@ -119,9 +114,7 @@ public function testParsePhpEnumThrowsExceptionOnInvalidType() Inline::parse('!php/enum SomeEnum::Foo', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } - /** - * @dataProvider getTestsForDump - */ + #[DataProvider('getTestsForDump')] public function testDump($yaml, $value, $parseFlags = 0) { $this->assertEquals($yaml, Inline::dump($value), \sprintf('::dump() converts a PHP structure to an inline YAML (%s)', $yaml)); @@ -223,9 +216,7 @@ public function testParseScalarWithCorrectlyQuotedStringShouldReturnString() $this->assertSame($expect, Inline::parseScalar($value)); } - /** - * @dataProvider getDataForParseReferences - */ + #[DataProvider('getDataForParseReferences')] public function testParseReferences($yaml, $expected) { $references = ['var' => 'var-value']; @@ -271,9 +262,7 @@ public function testParseUnquotedAsteriskFollowedByAComment() Inline::parse('{ foo: * #foo }'); } - /** - * @dataProvider getReservedIndicators - */ + #[DataProvider('getReservedIndicators')] public function testParseUnquotedScalarStartingWithReservedIndicator($indicator) { $this->expectException(ParseException::class); @@ -287,9 +276,7 @@ public static function getReservedIndicators() return [['@'], ['`']]; } - /** - * @dataProvider getScalarIndicators - */ + #[DataProvider('getScalarIndicators')] public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) { $this->expectException(ParseException::class); @@ -303,9 +290,7 @@ public static function getScalarIndicators() return [['|'], ['>'], ['%']]; } - /** - * @dataProvider getDataForIsHash - */ + #[DataProvider('getDataForIsHash')] public function testIsHash($array, $expected) { $this->assertSame($expected, Inline::isHash($array)); @@ -340,8 +325,8 @@ public static function getTestsForParse() ['123.45_67', 123.4567], ['0x4D2', 0x4D2], ['0x_4_D_2_', 0x4D2], - ['0o2333', 02333], - ['0o_2_3_3_3', 02333], + ['0o2333', 0o2333], + ['0o_2_3_3_3', 0o2333], ['.Inf', -log(0)], ['-.Inf', log(0)], ["'686e444'", '686e444'], @@ -423,7 +408,7 @@ public static function getTestsForParseWithMapObjects() ["'quoted string'", 'quoted string'], ['12.30e+02', 12.30e+02], ['0x4D2', 0x4D2], - ['0o2333', 02333], + ['0o2333', 0o2333], ['.Inf', -log(0)], ['-.Inf', log(0)], ["'686e444'", '686e444'], @@ -505,7 +490,7 @@ public static function getTestsForDump() ['1230.0', 12.30e+02], ['1.23E+45', 12.30e+44], ['1234', 0x4D2], - ['1243', 02333], + ['1243', 0o2333], ["'0x_4_D_2_'", '0x_4_D_2_'], ["'0_2_3_3_3'", '0_2_3_3_3'], ['.Inf', -log(0)], @@ -570,18 +555,14 @@ public static function getTestsForDump() ]; } - /** - * @dataProvider getTimestampTests - */ - public function testParseTimestampAsUnixTimestampByDefault(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond) + #[DataProvider('getTimestampTests')] + public function testParseTimestampAsUnixTimestampByDefault(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond, string $timezone) { $expectedDate = (new \DateTimeImmutable($yaml, new \DateTimeZone('UTC')))->format('U'); $this->assertSame($microsecond ? (float) "$expectedDate.$microsecond" : (int) $expectedDate, Inline::parse($yaml)); } - /** - * @dataProvider getTimestampTests - */ + #[DataProvider('getTimestampTests')] public function testParseTimestampAsDateTimeObject(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond, string $timezone) { $expected = (new \DateTimeImmutable($yaml)) @@ -604,10 +585,8 @@ public static function getTimestampTests(): array ]; } - /** - * @dataProvider getTimestampTests - */ - public function testParseNestedTimestampListAsDateTimeObject(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond) + #[DataProvider('getTimestampTests')] + public function testParseNestedTimestampListAsDateTimeObject(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond, string $timezone) { $expected = (new \DateTimeImmutable($yaml)) ->setTimeZone(new \DateTimeZone('UTC')) @@ -628,17 +607,13 @@ public function testParseInvalidDate() Inline::parse('2024-50-50', Yaml::PARSE_DATETIME); } - /** - * @dataProvider getDateTimeDumpTests - */ + #[DataProvider('getDateTimeDumpTests')] public function testDumpDateTime($dateTime, $expected) { $this->assertSame($expected, Inline::dump($dateTime)); } - /** - * @dataProvider getNumericKeyData - */ + #[DataProvider('getNumericKeyData')] public function testDumpNumericKeyAsString(array|int $input, int $flags, string $expected) { $this->assertSame($expected, Inline::dump($input, $flags)); @@ -761,9 +736,7 @@ public static function getDateTimeDumpTests() return $tests; } - /** - * @dataProvider getBinaryData - */ + #[DataProvider('getBinaryData')] public function testParseBinaryData($data) { $this->assertSame('Hello world', Inline::parse($data)); @@ -778,9 +751,7 @@ public static function getBinaryData() ]; } - /** - * @dataProvider getInvalidBinaryData - */ + #[DataProvider('getInvalidBinaryData')] public function testParseInvalidBinaryData($data, $expectedMessage) { $this->expectException(ParseException::class); @@ -823,9 +794,7 @@ public function testMappingKeysCannotBeOmitted() Inline::parse('{: foo}'); } - /** - * @dataProvider getTestsForNullValues - */ + #[DataProvider('getTestsForNullValues')] public function testParseMissingMappingValueAsNull($yaml, $expected) { $this->assertSame($expected, Inline::parse($yaml)); @@ -844,9 +813,7 @@ public function testTheEmptyStringIsAValidMappingKey() $this->assertSame(['' => 'foo'], Inline::parse('{ "": foo }')); } - /** - * @dataProvider getNotPhpCompatibleMappingKeyData - */ + #[DataProvider('getNotPhpCompatibleMappingKeyData')] public function testImplicitStringCastingOfMappingKeysThrowsException(string $yaml) { $this->expectException(ParseException::class); @@ -925,9 +892,7 @@ public function testUnfinishedInlineMap() Inline::parse("{abc: 'def'"); } - /** - * @dataProvider getTestsForOctalNumbers - */ + #[DataProvider('getTestsForOctalNumbers')] public function testParseOctalNumbers($expected, $yaml) { self::assertSame($expected, Inline::parse($yaml)); @@ -942,9 +907,7 @@ public static function getTestsForOctalNumbers() ]; } - /** - * @dataProvider getTestsForOctalNumbersYaml11Notation - */ + #[DataProvider('getTestsForOctalNumbersYaml11Notation')] public function testParseOctalNumbersYaml11Notation(string $expected, string $yaml) { self::assertSame($expected, Inline::parse($yaml)); @@ -961,9 +924,7 @@ public static function getTestsForOctalNumbersYaml11Notation() ]; } - /** - * @dataProvider phpObjectTagWithEmptyValueProvider - */ + #[DataProvider('phpObjectTagWithEmptyValueProvider')] public function testPhpObjectWithEmptyValue(string $value) { $this->expectException(ParseException::class); @@ -984,9 +945,7 @@ public static function phpObjectTagWithEmptyValueProvider() ]; } - /** - * @dataProvider phpConstTagWithEmptyValueProvider - */ + #[DataProvider('phpConstTagWithEmptyValueProvider')] public function testPhpConstTagWithEmptyValue(string $value) { $this->expectException(ParseException::class); @@ -995,9 +954,7 @@ public function testPhpConstTagWithEmptyValue(string $value) Inline::parse($value, Yaml::PARSE_CONSTANT); } - /** - * @dataProvider phpConstTagWithEmptyValueProvider - */ + #[DataProvider('phpConstTagWithEmptyValueProvider')] public function testPhpEnumTagWithEmptyValue(string $value) { $this->expectException(ParseException::class); @@ -1031,9 +988,7 @@ public function testParseUnquotedStringContainingHashTagNotPrefixedBySpace() self::assertSame('foo#nocomment', Inline::parse('foo#nocomment')); } - /** - * @dataProvider unquotedExclamationMarkThrowsProvider - */ + #[DataProvider('unquotedExclamationMarkThrowsProvider')] public function testUnquotedExclamationMarkThrows(string $value) { $this->expectException(ParseException::class); @@ -1065,9 +1020,7 @@ public static function unquotedExclamationMarkThrowsProvider() ]; } - /** - * @dataProvider quotedExclamationMarkProvider - */ + #[DataProvider('quotedExclamationMarkProvider')] public function testQuotedExclamationMark($expected, string $value) { $this->assertSame($expected, Inline::parse($value)); @@ -1096,9 +1049,7 @@ public static function quotedExclamationMarkProvider() ]; } - /** - * @dataProvider ideographicSpaceProvider - */ + #[DataProvider('ideographicSpaceProvider')] public function testParseIdeographicSpace(string $yaml, string $expected) { $this->assertSame($expected, Inline::parse($yaml)); @@ -1126,8 +1077,8 @@ public function testParseDoubleQuotedTaggedString() public function testParseQuotedReferenceLikeStringsInMapping() { $yaml = <<assertSame(['foo' => '&foo', 'bar' => '&bar', 'baz' => '&baz'], Inline::parse($yaml)); } @@ -1135,8 +1086,8 @@ public function testParseQuotedReferenceLikeStringsInMapping() public function testParseQuotedReferenceLikeStringsInSequence() { $yaml = <<assertSame(['&foo', '&bar', '&baz'], Inline::parse($yaml)); } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 836ec23ffa582..de948d8b8f353 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -11,8 +11,11 @@ namespace Symfony\Component\Yaml\Tests; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Tag\TaggedValue; @@ -20,8 +23,6 @@ class ParserTest extends TestCase { - use ExpectUserDeprecationMessageTrait; - private ?Parser $parser; protected function setUp(): void @@ -33,7 +34,7 @@ protected function tearDown(): void { $this->parser = null; - chmod(__DIR__.'/Fixtures/not_readable.yml', 0644); + chmod(__DIR__.'/Fixtures/not_readable.yml', 0o644); } public function testTopLevelNumber() @@ -55,10 +56,10 @@ public function testTopLevelNull() public function testEmptyValueInExpandedMappingIsSupported() { $yml = <<<'YAML' -foo: - bar: - baz: qux -YAML; + foo: + bar: + baz: qux + YAML; $data = $this->parser->parse($yml); $expected = ['foo' => ['bar' => null, 'baz' => 'qux']]; @@ -68,11 +69,11 @@ public function testEmptyValueInExpandedMappingIsSupported() public function testEmptyValueInExpandedSequenceIsSupported() { $yml = <<<'YAML' -foo: - - bar - - - - baz -YAML; + foo: + - bar + - + - baz + YAML; $data = $this->parser->parse($yml); $expected = ['foo' => ['bar', null, 'baz']]; @@ -114,9 +115,9 @@ public function testTaggedValueTopLevelAssocInline() public function testTaggedValueTopLevelAssoc() { $yml = <<<'YAML' -!user -name: barbara -YAML; + !user + name: barbara + YAML; $data = $this->parser->parse($yml, Yaml::PARSE_CUSTOM_TAGS); $expected = new TaggedValue('user', ['name' => 'barbara']); $this->assertSameData($expected, $data); @@ -125,9 +126,9 @@ public function testTaggedValueTopLevelAssoc() public function testTaggedValueTopLevelList() { $yml = <<<'YAML' -!users -- barbara -YAML; + !users + - barbara + YAML; $data = $this->parser->parse($yml, Yaml::PARSE_CUSTOM_TAGS); $expected = new TaggedValue('users', ['barbara']); $this->assertSameData($expected, $data); @@ -136,18 +137,16 @@ public function testTaggedValueTopLevelList() public function testTaggedTextAsListItem() { $yml = <<<'YAML' -- !text | - first line -YAML; + - !text | + first line + YAML; // @todo Fix the parser, eliminate this exception. $this->expectException(ParseException::class); $this->expectExceptionMessage('Unable to parse at line 2 (near "!text |").'); $this->parser->parse($yml, Yaml::PARSE_CUSTOM_TAGS); } - /** - * @dataProvider getDataFormSpecifications - */ + #[DataProvider('getDataFormSpecifications')] public function testSpecifications($expected, $yaml, $comment) { $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment); @@ -163,9 +162,7 @@ public static function getNonStringMappingKeysData() return self::loadTestsFromFixtureFiles('nonStringKeys.yml'); } - /** - * @dataProvider invalidIndentation - */ + #[DataProvider('invalidIndentation')] public function testTabsAsIndentationInYaml(string $given, string $expectedMessage) { $this->expectException(ParseException::class); @@ -209,9 +206,7 @@ public function testParserIsStateless() $this->parser->parse("abc:\n\tabc"); } - /** - * @dataProvider validTokenSeparators - */ + #[DataProvider('validTokenSeparators')] public function testValidTokenSeparation(string $given, array $expected) { $actual = $this->parser->parse($given); @@ -243,10 +238,10 @@ public static function validTokenSeparators(): array public function testEndOfTheDocumentMarker() { $yaml = <<<'EOF' ---- %YAML:1.0 -foo -... -EOF; + --- %YAML:1.0 + foo + ... + EOF; $this->assertEquals('foo', $this->parser->parse($yaml)); } @@ -256,14 +251,14 @@ public static function getBlockChompingTests() $tests = []; $yaml = <<<'EOF' -foo: |- - one - two -bar: |- - one - two - -EOF; + foo: |- + one + two + bar: |- + one + two + + EOF; $expected = [ 'foo' => "one\ntwo", 'bar' => "one\ntwo", @@ -271,16 +266,16 @@ public static function getBlockChompingTests() $tests['Literal block chomping strip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: |- - one - two + foo: |- + one + two -bar: |- - one - two + bar: |- + one + two -EOF; + EOF; $expected = [ 'foo' => "one\ntwo", 'bar' => "one\ntwo", @@ -288,21 +283,21 @@ public static function getBlockChompingTests() $tests['Literal block chomping strip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' -{} + {} -EOF; + EOF; $expected = []; $tests['Literal block chomping strip with multiple trailing newlines after a 1-liner'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: |- - one - two -bar: |- - one - two -EOF; + foo: |- + one + two + bar: |- + one + two + EOF; $expected = [ 'foo' => "one\ntwo", 'bar' => "one\ntwo", @@ -310,14 +305,14 @@ public static function getBlockChompingTests() $tests['Literal block chomping strip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: | - one - two -bar: | - one - two - -EOF; + foo: | + one + two + bar: | + one + two + + EOF; $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", @@ -325,16 +320,16 @@ public static function getBlockChompingTests() $tests['Literal block chomping clip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: | - one - two + foo: | + one + two -bar: | - one - two + bar: | + one + two -EOF; + EOF; $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", @@ -342,12 +337,12 @@ public static function getBlockChompingTests() $tests['Literal block chomping clip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: -- bar: | - one + foo: + - bar: | + one - two -EOF; + two + EOF; $expected = [ 'foo' => [ [ @@ -358,13 +353,13 @@ public static function getBlockChompingTests() $tests['Literal block chomping clip with embedded blank line inside unindented collection'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: | - one - two -bar: | - one - two -EOF; + foo: | + one + two + bar: | + one + two + EOF; $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo", @@ -372,14 +367,14 @@ public static function getBlockChompingTests() $tests['Literal block chomping clip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: |+ - one - two -bar: |+ - one - two - -EOF; + foo: |+ + one + two + bar: |+ + one + two + + EOF; $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", @@ -387,16 +382,16 @@ public static function getBlockChompingTests() $tests['Literal block chomping keep with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: |+ - one - two + foo: |+ + one + two -bar: |+ - one - two + bar: |+ + one + two -EOF; + EOF; $expected = [ 'foo' => "one\ntwo\n\n", 'bar' => "one\ntwo\n\n", @@ -404,13 +399,13 @@ public static function getBlockChompingTests() $tests['Literal block chomping keep with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: |+ - one - two -bar: |+ - one - two -EOF; + foo: |+ + one + two + bar: |+ + one + two + EOF; $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo", @@ -418,14 +413,14 @@ public static function getBlockChompingTests() $tests['Literal block chomping keep without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: >- - one - two -bar: >- - one - two - -EOF; + foo: >- + one + two + bar: >- + one + two + + EOF; $expected = [ 'foo' => 'one two', 'bar' => 'one two', @@ -433,16 +428,16 @@ public static function getBlockChompingTests() $tests['Folded block chomping strip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: >- - one - two + foo: >- + one + two -bar: >- - one - two + bar: >- + one + two -EOF; + EOF; $expected = [ 'foo' => 'one two', 'bar' => 'one two', @@ -450,13 +445,13 @@ public static function getBlockChompingTests() $tests['Folded block chomping strip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: >- - one - two -bar: >- - one - two -EOF; + foo: >- + one + two + bar: >- + one + two + EOF; $expected = [ 'foo' => 'one two', 'bar' => 'one two', @@ -464,14 +459,14 @@ public static function getBlockChompingTests() $tests['Folded block chomping strip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: > - one - two -bar: > - one - two - -EOF; + foo: > + one + two + bar: > + one + two + + EOF; $expected = [ 'foo' => "one two\n", 'bar' => "one two\n", @@ -479,16 +474,16 @@ public static function getBlockChompingTests() $tests['Folded block chomping clip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: > - one - two + foo: > + one + two -bar: > - one - two + bar: > + one + two -EOF; + EOF; $expected = [ 'foo' => "one two\n", 'bar' => "one two\n", @@ -496,13 +491,13 @@ public static function getBlockChompingTests() $tests['Folded block chomping clip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: > - one - two -bar: > - one - two -EOF; + foo: > + one + two + bar: > + one + two + EOF; $expected = [ 'foo' => "one two\n", 'bar' => 'one two', @@ -510,14 +505,14 @@ public static function getBlockChompingTests() $tests['Folded block chomping clip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: >+ - one - two -bar: >+ - one - two - -EOF; + foo: >+ + one + two + bar: >+ + one + two + + EOF; $expected = [ 'foo' => "one two\n", 'bar' => "one two\n", @@ -525,16 +520,16 @@ public static function getBlockChompingTests() $tests['Folded block chomping keep with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: >+ - one - two + foo: >+ + one + two -bar: >+ - one - two + bar: >+ + one + two -EOF; + EOF; $expected = [ 'foo' => "one two\n\n", 'bar' => "one two\n\n", @@ -542,13 +537,13 @@ public static function getBlockChompingTests() $tests['Folded block chomping keep with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' -foo: >+ - one - two -bar: >+ - one - two -EOF; + foo: >+ + one + two + bar: >+ + one + two + EOF; $expected = [ 'foo' => "one two\n", 'bar' => 'one two', @@ -558,9 +553,7 @@ public static function getBlockChompingTests() return $tests; } - /** - * @dataProvider getBlockChompingTests - */ + #[DataProvider('getBlockChompingTests')] public function testBlockChomping($expected, $yaml) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -574,12 +567,12 @@ public function testBlockChomping($expected, $yaml) public function testBlockLiteralWithLeadingNewlines() { $yaml = <<<'EOF' -foo: |- + foo: |- - bar + bar -EOF; + EOF; $expected = [ 'foo' => "\n\nbar", ]; @@ -590,24 +583,22 @@ public function testBlockLiteralWithLeadingNewlines() public function testObjectSupportEnabled() { $input = <<<'EOF' -foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} -bar: 1 -EOF; + foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} + bar: 1 + EOF; $this->assertSameData(['foo' => new B(), 'bar' => 1], $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); } public function testObjectSupportDisabledButNoExceptions() { $input = <<<'EOF' -foo: !php/object O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} -bar: 1 -EOF; + foo: !php/object O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} + bar: 1 + EOF; $this->assertSameData(['foo' => null, 'bar' => 1], $this->parser->parse($input), '->parse() does not parse objects'); } - /** - * @dataProvider getObjectForMapTests - */ + #[DataProvider('getObjectForMapTests')] public function testObjectForMap($yaml, $expected) { $flags = Yaml::PARSE_OBJECT_FOR_MAP; @@ -620,9 +611,9 @@ public static function getObjectForMapTests() $tests = []; $yaml = <<<'EOF' -foo: - fiz: [cat] -EOF; + foo: + fiz: [cat] + EOF; $expected = new \stdClass(); $expected->foo = new \stdClass(); $expected->foo->fiz = ['cat']; @@ -641,10 +632,10 @@ public static function getObjectForMapTests() $tests['object-for-map-is-applied-after-parsing'] = [$yaml, $expected]; $yaml = <<<'EOT' -array: - - key: one - - key: two -EOT; + array: + - key: one + - key: two + EOT; $expected = new \stdClass(); $expected->array = []; $expected->array[0] = new \stdClass(); @@ -654,10 +645,10 @@ public static function getObjectForMapTests() $tests['nest-map-and-sequence'] = [$yaml, $expected]; $yaml = <<<'YAML' -map: - 1: one - 2: two -YAML; + map: + 1: one + 2: two + YAML; $expected = new \stdClass(); $expected->map = new \stdClass(); $expected->map->{1} = 'one'; @@ -665,10 +656,10 @@ public static function getObjectForMapTests() $tests['numeric-keys'] = [$yaml, $expected]; $yaml = <<<'YAML' -map: - '0': one - '1': two -YAML; + map: + '0': one + '1': two + YAML; $expected = new \stdClass(); $expected->map = new \stdClass(); $expected->map->{0} = 'one'; @@ -681,9 +672,9 @@ public static function getObjectForMapTests() public function testObjectsSupportDisabledWithExceptions() { $yaml = <<<'EOF' -foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} -bar: 1 -EOF; + foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} + bar: 1 + EOF; $this->expectException(ParseException::class); @@ -693,10 +684,10 @@ public function testObjectsSupportDisabledWithExceptions() public function testMappingKeyInMultiLineStringThrowsException() { $yaml = <<<'EOF' -data: - dbal:wrong - default_connection: monolith -EOF; + data: + dbal:wrong + default_connection: monolith + EOF; $this->expectException(ParseException::class); $this->expectExceptionMessage('Mapping values are not allowed in multi-line blocks at line 2 (near "dbal:wrong").'); @@ -715,9 +706,7 @@ public function testCanParseContentWithTrailingSpaces() $this->assertSame($expected, $this->parser->parse($yaml)); } - /** - * @requires extension iconv - */ + #[RequiresPhpExtension('iconv')] public function testNonUtf8Exception() { $yamls = [ @@ -741,12 +730,12 @@ public function testUnindentedCollectionException() { $yaml = <<<'EOF' -collection: --item1 --item2 --item3 + collection: + -item1 + -item2 + -item3 -EOF; + EOF; $this->expectException(ParseException::class); @@ -757,11 +746,11 @@ public function testShortcutKeyUnindentedCollectionException() { $yaml = <<<'EOF' -collection: -- key: foo - foo: bar + collection: + - key: foo + foo: bar -EOF; + EOF; $this->expectException(ParseException::class); @@ -773,17 +762,17 @@ public function testMultipleDocumentsNotSupportedException() $this->expectException(ParseException::class); $this->expectExceptionMessageMatches('/^Multiple documents are not supported.+/'); Yaml::parse(<<<'EOL' -# Ranking of 1998 home runs ---- -- Mark McGwire -- Sammy Sosa -- Ken Griffey - -# Team ranking ---- -- Chicago Cubs -- St Louis Cardinals -EOL + # Ranking of 1998 home runs + --- + - Mark McGwire + - Sammy Sosa + - Ken Griffey + + # Team ranking + --- + - Chicago Cubs + - St Louis Cardinals + EOL ); } @@ -791,24 +780,24 @@ public function testSequenceInAMapping() { $this->expectException(ParseException::class); Yaml::parse(<<<'EOF' -yaml: - hash: me - - array stuff -EOF + yaml: + hash: me + - array stuff + EOF ); } public function testSequenceInMappingStartedBySingleDashLine() { $yaml = <<<'EOT' -a: -- - b: - - - bar: baz -- foo -d: e -EOT; + a: + - + b: + - + bar: baz + - foo + d: e + EOT; $expected = [ 'a' => [ [ @@ -829,12 +818,12 @@ public function testSequenceInMappingStartedBySingleDashLine() public function testSequenceFollowedByCommentEmbeddedInMapping() { $yaml = <<<'EOT' -a: - b: - - c -# comment - d: e -EOT; + a: + b: + - c + # comment + d: e + EOT; $expected = [ 'a' => [ 'b' => ['c'], @@ -848,14 +837,14 @@ public function testSequenceFollowedByCommentEmbeddedInMapping() public function testNonStringFollowedByCommentEmbeddedInMapping() { $yaml = <<<'EOT' -a: - b: - {} -# comment - d: - 1.1 -# another comment -EOT; + a: + b: + {} + # comment + d: + 1.1 + # another comment + EOT; $expected = [ 'a' => [ 'b' => [], @@ -871,30 +860,28 @@ public static function getParseExceptionNotAffectedMultiLineStringLastResortPars $tests = []; $yaml = <<<'EOT' -a - b: -EOT; + a + b: + EOT; $tests['parse error on first line'] = [$yaml]; $yaml = <<<'EOT' -a + a -b - c: -EOT; + b + c: + EOT; $tests['parse error due to inconsistent indentation'] = [$yaml]; $yaml = <<<'EOT' - & * ! | > ' " % @ ` #, { asd a;sdasd }-@^qw3 -EOT; + & * ! | > ' " % @ ` #, { asd a;sdasd }-@^qw3 + EOT; $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = [$yaml]; return $tests; } - /** - * @dataProvider getParseExceptionNotAffectedMultiLineStringLastResortParsing - */ + #[DataProvider('getParseExceptionNotAffectedMultiLineStringLastResortParsing')] public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing($yaml) { $this->expectException(ParseException::class); @@ -904,11 +891,11 @@ public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing( public function testMultiLineStringLastResortParsing() { $yaml = <<<'EOT' -test: - You can have things that don't look like strings here - true - yes you can -EOT; + test: + You can have things that don't look like strings here + true + yes you can + EOT; $expected = [ 'test' => 'You can have things that don\'t look like strings here true yes you can', ]; @@ -916,10 +903,10 @@ public function testMultiLineStringLastResortParsing() $this->assertSame($expected, $this->parser->parse($yaml)); $yaml = <<<'EOT' -a: - b - c -EOT; + a: + b + c + EOT; $expected = [ 'a' => 'b c', ]; @@ -931,10 +918,10 @@ public function testMappingInASequence() { $this->expectException(ParseException::class); Yaml::parse(<<<'EOF' -yaml: - - array stuff - hash: me -EOF + yaml: + - array stuff + hash: me + EOF ); } @@ -943,11 +930,11 @@ public function testScalarInSequence() $this->expectException(ParseException::class); $this->expectExceptionMessage('missing colon'); Yaml::parse(<<<'EOF' -foo: - - bar -"missing colon" - foo: bar -EOF + foo: + - bar + "missing colon" + foo: bar + EOF ); } @@ -964,13 +951,13 @@ public function testScalarInSequence() public function testMappingDuplicateKeyBlock() { $input = <<<'EOD' -parent: - child: first - child: duplicate -parent: - child: duplicate - child: duplicate -EOD; + parent: + child: first + child: duplicate + parent: + child: duplicate + child: duplicate + EOD; $this->expectException(ParseException::class); $this->expectExceptionMessage('Duplicate key "child" detected'); @@ -981,9 +968,9 @@ public function testMappingDuplicateKeyBlock() public function testMappingDuplicateKeyFlow() { $input = <<<'EOD' -parent: { child: first, child: duplicate } -parent: { child: duplicate, child: duplicate } -EOD; + parent: { child: first, child: duplicate } + parent: { child: duplicate, child: duplicate } + EOD; $this->expectException(ParseException::class); $this->expectExceptionMessage('Duplicate key "child" detected'); @@ -991,9 +978,7 @@ public function testMappingDuplicateKeyFlow() Yaml::parse($input); } - /** - * @dataProvider getParseExceptionOnDuplicateData - */ + #[DataProvider('getParseExceptionOnDuplicateData')] public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber) { $this->expectException(ParseException::class); @@ -1007,71 +992,70 @@ public static function getParseExceptionOnDuplicateData() $tests = []; $yaml = <<expectUserDeprecationMessage('Since symfony/yaml 7.2: Duplicate key "child" detected on line 4 whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated and will throw a ParseException in 8.0.'); $yaml = <<assertSame(['hash' => null], Yaml::parse($input)); } @@ -1097,74 +1081,74 @@ public function testCommentAtTheRootIndent() ], ], ], Yaml::parse(<<<'EOF' -# comment 1 -services: -# comment 2 - # comment 3 - app.foo_service: - class: Foo -# comment 4 - # comment 5 - app/bar_service: - class: Bar -EOF + # comment 1 + services: + # comment 2 + # comment 3 + app.foo_service: + class: Foo + # comment 4 + # comment 5 + app/bar_service: + class: Bar + EOF )); } public function testStringBlockWithComments() { $this->assertSame(['content' => <<<'EOT' -# comment 1 -header + # comment 1 + header - # comment 2 - -

      title

      - + # comment 2 + +

      title

      + -footer # comment3 -EOT + footer # comment3 + EOT ], Yaml::parse(<<<'EOF' -content: | - # comment 1 - header + content: | + # comment 1 + header - # comment 2 - -

      title

      - + # comment 2 + +

      title

      + - footer # comment3 -EOF + footer # comment3 + EOF )); } public function testFoldedStringBlockWithComments() { $this->assertSame([['content' => <<<'EOT' -# comment 1 -header + # comment 1 + header - # comment 2 - -

      title

      - + # comment 2 + +

      title

      + -footer # comment3 -EOT + footer # comment3 + EOT ]], Yaml::parse(<<<'EOF' -- - content: | - # comment 1 - header - - # comment 2 - -

      title

      - - - footer # comment3 -EOF + - + content: | + # comment 1 + header + + # comment 2 + +

      title

      + + + footer # comment3 + EOF )); } @@ -1173,30 +1157,30 @@ public function testNestedFoldedStringBlockWithComments() $this->assertSame([[ 'title' => 'some title', 'content' => <<<'EOT' -# comment 1 -header + # comment 1 + header - # comment 2 - -

      title

      - + # comment 2 + +

      title

      + -footer # comment3 -EOT, + footer # comment3 + EOT, ]], Yaml::parse(<<<'EOF' -- - title: some title - content: | - # comment 1 - header - - # comment 2 - -

      title

      - - - footer # comment3 -EOF + - + title: some title + content: | + # comment 1 + header + + # comment 2 + +

      title

      + + + footer # comment3 + EOF )); } @@ -1217,41 +1201,41 @@ public function testReferenceResolvingInInlineStrings() 'baz' => ['foo'], 'foobar' => ['foo'], ], Yaml::parse(<<<'EOF' -var: &var var-value -scalar: *var -list: [ *var ] -list_in_list: [[ *var ]] -map_in_list: [ { key: *var } ] -embedded_mapping: [ key: *var ] -map: { key: *var } -list_in_map: { key: [*var] } -map_in_map: { foo: { bar: *var } } -foo: { bar: &baz baz } -bar: { foo: *baz } -baz: [ &foo foo ] -foobar: [ *foo ] -EOF + var: &var var-value + scalar: *var + list: [ *var ] + list_in_list: [[ *var ]] + map_in_list: [ { key: *var } ] + embedded_mapping: [ key: *var ] + map: { key: *var } + list_in_map: { key: [*var] } + map_in_map: { foo: { bar: *var } } + foo: { bar: &baz baz } + bar: { foo: *baz } + baz: [ &foo foo ] + foobar: [ *foo ] + EOF )); } public function testYamlDirective() { $yaml = <<<'EOF' -%YAML 1.2 ---- -foo: 1 -bar: 2 -EOF; + %YAML 1.2 + --- + foo: 1 + bar: 2 + EOF; $this->assertSame(['foo' => 1, 'bar' => 2], $this->parser->parse($yaml)); } public function testFloatKeys() { $yaml = <<<'EOF' -foo: - 1.2: "bar" - 1.3: "baz" -EOF; + foo: + 1.2: "bar" + 1.3: "baz" + EOF; $this->expectException(ParseException::class); $this->expectExceptionMessage('Numeric keys are not supported. Quote your evaluable mapping keys instead'); @@ -1262,9 +1246,9 @@ public function testFloatKeys() public function testBooleanKeys() { $yaml = <<<'EOF' -true: foo -false: bar -EOF; + true: foo + false: bar + EOF; $this->expectException(ParseException::class); $this->expectExceptionMessage('Non-string keys are not supported. Quote your evaluable mapping keys instead'); @@ -1275,15 +1259,15 @@ public function testBooleanKeys() public function testExplicitStringCasting() { $yaml = <<<'EOF' -'1.2': "bar" -!!str 1.3: "baz" + '1.2': "bar" + !!str 1.3: "baz" -'true': foo -!!str false: bar + 'true': foo + !!str false: bar -!!str null: 'null' -'~': 'null' -EOF; + !!str null: 'null' + '~': 'null' + EOF; $expected = [ '1.2' => 'bar', @@ -1300,8 +1284,8 @@ public function testExplicitStringCasting() public function testColonInMappingValueException() { $yaml = <<<'EOF' -foo: bar: baz -EOF; + foo: bar: baz + EOF; $this->expectException(ParseException::class); $this->expectExceptionMessage('A colon cannot be used in an unquoted mapping value'); @@ -1312,16 +1296,14 @@ public function testColonInMappingValueException() public function testColonInMappingValueExceptionNotTriggeredByColonInComment() { $yaml = <<<'EOT' -foo: - bar: foobar # Note: a comment after a colon -EOT; + foo: + bar: foobar # Note: a comment after a colon + EOT; $this->assertSame(['foo' => ['bar' => 'foobar']], $this->parser->parse($yaml)); } - /** - * @dataProvider getCommentLikeStringInScalarBlockData - */ + #[DataProvider('getCommentLikeStringInScalarBlockData')] public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expectedParserResult) { $this->assertSame($expectedParserResult, $this->parser->parse($yaml)); @@ -1332,96 +1314,92 @@ public static function getCommentLikeStringInScalarBlockData() $tests = []; $yaml = <<<'EOT' -pages: - - - title: some title - content: | - # comment 1 - header - - # comment 2 - -

      title

      - - - footer # comment3 -EOT; + pages: + - + title: some title + content: | + # comment 1 + header + + # comment 2 + +

      title

      + + + footer # comment3 + EOT; $expected = [ 'pages' => [ [ 'title' => 'some title', 'content' => <<<'EOT' -# comment 1 -header + # comment 1 + header - # comment 2 - -

      title

      - + # comment 2 + +

      title

      + -footer # comment3 -EOT - , + footer # comment3 + EOT, ], ], ]; $tests[] = [$yaml, $expected]; $yaml = <<<'EOT' -test: | - foo - # bar - baz -collection: - - one: | - foo - # bar - baz - - two: | - foo - # bar - baz -EOT; + test: | + foo + # bar + baz + collection: + - one: | + foo + # bar + baz + - two: | + foo + # bar + baz + EOT; $expected = [ 'test' => <<<'EOT' -foo -# bar -baz + foo + # bar + baz -EOT - , + EOT, 'collection' => [ [ 'one' => <<<'EOT' -foo -# bar -baz + foo + # bar + baz -EOT - , + EOT, ], [ 'two' => <<<'EOT' -foo -# bar -baz -EOT - , + foo + # bar + baz + EOT, ], ], ]; $tests[] = [$yaml, $expected]; $yaml = <<<'EOT' -foo: - bar: - scalar-block: > - line1 - line2> - baz: -# comment - foobar: ~ -EOT; + foo: + bar: + scalar-block: > + line1 + line2> + baz: + # comment + foobar: ~ + EOT; $expected = [ 'foo' => [ 'bar' => [ @@ -1435,13 +1413,13 @@ public static function getCommentLikeStringInScalarBlockData() $tests[] = [$yaml, $expected]; $yaml = <<<'EOT' -a: - b: hello -# c: | -# first row -# second row - d: hello -EOT; + a: + b: hello + # c: | + # first row + # second row + d: hello + EOT; $expected = [ 'a' => [ 'b' => 'hello', @@ -1456,22 +1434,21 @@ public static function getCommentLikeStringInScalarBlockData() public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks() { $yaml = <<<'EOT' -test: > -

      A heading

      + test: > +

      A heading

      -
        -
      • a list
      • -
      • may be a good example
      • -
      -EOT; +
        +
      • a list
      • +
      • may be a good example
      • +
      + EOT; $this->assertSame( [ 'test' => <<<'EOT' -

      A heading

      -
      • a list
      • may be a good example
      -EOT - , +

      A heading

      +
      • a list
      • may be a good example
      + EOT, ], $this->parser->parse($yaml) ); @@ -1480,33 +1457,30 @@ public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks() public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks() { $yaml = <<<'EOT' -test: > -

      A heading

      + test: > +

      A heading

      -
        -
      • a list
      • -
      • may be a good example
      • -
      -EOT; +
        +
      • a list
      • +
      • may be a good example
      • +
      + EOT; $this->assertSame( [ 'test' => <<<'EOT' -

      A heading

      -
        -
      • a list
      • -
      • may be a good example
      • -
      -EOT - , +

      A heading

      +
        +
      • a list
      • +
      • may be a good example
      • +
      + EOT, ], $this->parser->parse($yaml) ); } - /** - * @dataProvider getBinaryData - */ + #[DataProvider('getBinaryData')] public function testParseBinaryData($data) { $this->assertSame(['data' => 'Hello world'], $this->parser->parse($data)); @@ -1520,22 +1494,20 @@ public static function getBinaryData() 'containing spaces' => ['data: !!binary "SGVs bG8gd 29ybGQ="'], 'in block scalar' => [ <<<'EOT' -data: !!binary | - SGVsbG8gd29ybGQ= -EOT, + data: !!binary | + SGVsbG8gd29ybGQ= + EOT, ], 'containing spaces in block scalar' => [ <<<'EOT' -data: !!binary | - SGVs bG8gd 29ybGQ= -EOT, + data: !!binary | + SGVs bG8gd 29ybGQ= + EOT, ], ]; } - /** - * @dataProvider getInvalidBinaryData - */ + #[DataProvider('getInvalidBinaryData')] public function testParseInvalidBinaryData($data, $expectedMessage) { $this->expectException(ParseException::class); @@ -1553,34 +1525,30 @@ public static function getInvalidBinaryData() 'misplaced equals character' => ['data: !!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'], 'length not a multiple of four in block scalar' => [ <<<'EOT' -data: !!binary | - SGVsbG8d29ybGQ= -EOT - , + data: !!binary | + SGVsbG8d29ybGQ= + EOT, '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/', ], 'invalid characters in block scalar' => [ <<<'EOT' -data: !!binary | - SGVsbG8#d29ybGQ= -EOT - , + data: !!binary | + SGVsbG8#d29ybGQ= + EOT, '/The base64 encoded data \(.*\) contains invalid characters/', ], 'too many equals characters in block scalar' => [ <<<'EOT' -data: !!binary | - SGVsbG8gd29yb=== -EOT - , + data: !!binary | + SGVsbG8gd29yb=== + EOT, '/The base64 encoded data \(.*\) contains invalid characters/', ], 'misplaced equals character in block scalar' => [ <<<'EOT' -data: !!binary | - SGVsbG8gd29ybG=Q -EOT - , + data: !!binary | + SGVsbG8gd29ybG=Q + EOT, '/The base64 encoded data \(.*\) contains invalid characters/', ], ]; @@ -1589,8 +1557,8 @@ public static function getInvalidBinaryData() public function testParseDateWithSubseconds() { $yaml = <<<'EOT' -date: 2002-12-14T01:23:45.670000Z -EOT; + date: 2002-12-14T01:23:45.670000Z + EOT; $this->assertSameData(['date' => 1039829025.67], $this->parser->parse($yaml)); } @@ -1598,8 +1566,8 @@ public function testParseDateWithSubseconds() public function testParseDateAsMappingValue() { $yaml = <<<'EOT' -date: 2002-12-14 -EOT; + date: 2002-12-14 + EOT; $expectedDate = (new \DateTimeImmutable()) ->setTimeZone(new \DateTimeZone('UTC')) ->setDate(2002, 12, 14) @@ -1608,9 +1576,7 @@ public function testParseDateAsMappingValue() $this->assertSameData(['date' => $expectedDate], $this->parser->parse($yaml, Yaml::PARSE_DATETIME)); } - /** - * @dataProvider parserThrowsExceptionWithCorrectLineNumberProvider - */ + #[DataProvider('parserThrowsExceptionWithCorrectLineNumberProvider')] public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yaml) { $this->expectException(ParseException::class); @@ -1625,49 +1591,49 @@ public static function parserThrowsExceptionWithCorrectLineNumberProvider() [ 4, <<<'YAML' -foo: - - - # bar - bar: "123", -YAML, + foo: + - + # bar + bar: "123", + YAML, ], [ 5, <<<'YAML' -foo: - - - # bar - # bar - bar: "123", -YAML, + foo: + - + # bar + # bar + bar: "123", + YAML, ], [ 8, <<<'YAML' -foo: - - - # foobar - baz: 123 -bar: - - - # bar - bar: "123", -YAML, + foo: + - + # foobar + baz: 123 + bar: + - + # bar + bar: "123", + YAML, ], [ 10, <<<'YAML' -foo: - - - # foobar - # foobar - baz: 123 -bar: - - - # bar - # bar - bar: "123", -YAML, + foo: + - + # foobar + # foobar + baz: 123 + bar: + - + # bar + # bar + bar: "123", + YAML, ], ]; } @@ -1675,12 +1641,12 @@ public static function parserThrowsExceptionWithCorrectLineNumberProvider() public function testParseMultiLineQuotedString() { $yaml = <<assertSame(['foo' => 'bar baz foobar foo', 'bar' => 'baz'], $this->parser->parse($yaml)); } @@ -1688,10 +1654,10 @@ public function testParseMultiLineQuotedString() public function testMultiLineQuotedStringWithTrailingBackslash() { $yaml = <<assertSame(['foobar' => 'foobar'], $this->parser->parse($yaml)); } @@ -1699,11 +1665,11 @@ public function testMultiLineQuotedStringWithTrailingBackslash() public function testCommentCharactersInMultiLineQuotedStrings() { $yaml = << [ 'foobar' => 'foo #bar', @@ -1717,10 +1683,10 @@ public function testCommentCharactersInMultiLineQuotedStrings() public function testBlankLinesInQuotedMultiLineString() { $yaml = << "foo\nbar", ]; @@ -1731,10 +1697,10 @@ public function testBlankLinesInQuotedMultiLineString() public function testEscapedQuoteInQuotedMultiLineString() { $yaml = << 'foo "bar" baz', ]; @@ -1745,9 +1711,9 @@ public function testEscapedQuoteInQuotedMultiLineString() public function testBackslashInQuotedMultiLineString() { $yaml = << 'foo bar\\', ]; @@ -1755,9 +1721,7 @@ public function testBackslashInQuotedMultiLineString() $this->assertSame($expected, $this->parser->parse($yaml)); } - /** - * @dataProvider wrappedUnquotedStringsProvider - */ + #[DataProvider('wrappedUnquotedStringsProvider')] public function testWrappedUnquotedStringWithMultipleSpacesInValue(string $yaml, array $expected) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -1786,19 +1750,17 @@ public static function wrappedUnquotedStringsProvider() public function testParseMultiLineUnquotedString() { $yaml = <<assertSame(['foo' => 'bar baz foobar foo', 'bar' => 'baz'], $this->parser->parse($yaml)); } - /** - * @dataProvider unquotedStringWithTrailingComment - */ + #[DataProvider('unquotedStringWithTrailingComment')] public function testParseMultiLineUnquotedStringWithTrailingComment(string $yaml, array $expected) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -1809,59 +1771,57 @@ public static function unquotedStringWithTrailingComment() return [ 'comment after comma' => [ <<<'YAML' - { - foo: 3, # comment - bar: 3 - } - YAML, + { + foo: 3, # comment + bar: 3 + } + YAML, ['foo' => 3, 'bar' => 3], ], 'comment after space' => [ <<<'YAML' - { - foo: 3 # comment - } - YAML, + { + foo: 3 # comment + } + YAML, ['foo' => 3], ], 'comment after space, but missing space after #' => [ <<<'YAML' - { - foo: 3 #comment - } - YAML, + { + foo: 3 #comment + } + YAML, ['foo' => 3], ], 'comment after tab' => [ << 3], ], 'comment after tab, but missing space after #' => [ << 3], ], '# in mapping value' => [ <<<'YAML' - { - foo: example.com/#about - } - YAML, + { + foo: example.com/#about + } + YAML, ['foo' => 'example.com/#about'], ], ]; } - /** - * @dataProvider escapedQuotationCharactersInQuotedStrings - */ + #[DataProvider('escapedQuotationCharactersInQuotedStrings')] public function testParseQuotedStringContainingEscapedQuotationCharacters(string $yaml, array $expected) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -1872,12 +1832,11 @@ public static function escapedQuotationCharactersInQuotedStrings() return [ 'single quoted string' => [ << [ [ @@ -1889,12 +1848,11 @@ public static function escapedQuotationCharactersInQuotedStrings() ], 'double quoted string' => [ << [ [ @@ -1917,9 +1875,7 @@ public function testParseMultiLineString() $this->assertSame("foo bar\nbaz", $this->parser->parse("foo\nbar\n\nbaz")); } - /** - * @dataProvider multiLineDataProvider - */ + #[DataProvider('multiLineDataProvider')] public function testParseMultiLineMappingValue($yaml, $expected, $parseError) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -1930,13 +1886,13 @@ public static function multiLineDataProvider() $tests = []; $yaml = <<<'EOF' -foo: -- bar: - one + foo: + - bar: + one - two - three -EOF; + two + three + EOF; $expected = [ 'foo' => [ [ @@ -1948,35 +1904,35 @@ public static function multiLineDataProvider() $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' -bar -"foo" -EOF; + bar + "foo" + EOF; $expected = 'bar "foo"'; $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' -bar -"foo -EOF; + bar + "foo + EOF; $expected = 'bar "foo'; $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' -bar + bar -'foo' -EOF; + 'foo' + EOF; $expected = "bar\n'foo'"; $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' -bar + bar -foo' -EOF; + foo' + EOF; $expected = "bar\nfoo'"; $tests[] = [$yaml, $expected, false]; @@ -1984,9 +1940,7 @@ public static function multiLineDataProvider() return $tests; } - /** - * @dataProvider inlineNotationSpanningMultipleLinesProvider - */ + #[DataProvider('inlineNotationSpanningMultipleLinesProvider')] public function testInlineNotationSpanningMultipleLines($expected, string $yaml) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -1998,42 +1952,38 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array 'mapping' => [ ['foo' => 'bar', 'bar' => 'baz'], << [ ['foo' => 'bar', 'bar' => 'baz'], << [ ['foo', 'bar'], << [ ['foo', 'bar'], << [ [ @@ -2042,10 +1992,9 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ [ @@ -2056,9 +2005,9 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ [ @@ -2066,21 +2015,20 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ['entry2'], ], << [ ['foo' => ['bar', 'foobar'], 'bar' => ['baz']], << [ [ @@ -2091,12 +2039,11 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ [ @@ -2107,12 +2054,12 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array 'bar' => 'baz', ], << [ [ @@ -2125,12 +2072,11 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ [ @@ -2143,25 +2089,23 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ ['foo', ['bar' => 'baz']], << [ [ @@ -2171,12 +2115,11 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ [ @@ -2188,13 +2131,12 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ [ @@ -2206,40 +2148,37 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ], ], << [ "foo\nbar", << [ "foo\nbar", << [ ['foo' => "bar\nbaz"], << [ [ @@ -2250,12 +2189,12 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array 'param' => 'some', ], << [ [ @@ -2266,9 +2205,9 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array 'param' => 'some', ], << [ [ @@ -2279,9 +2218,9 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array 'param' => 'some', ], << [ [ @@ -2292,10 +2231,10 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array 'param' => 'some', ], << [ [ @@ -2309,33 +2248,33 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ['foo' => 'bar}'], ], << [ [ @@ -2349,14 +2288,14 @@ public static function inlineNotationSpanningMultipleLinesProvider(): array ['te"st]'], ], <<expectExceptionMessage('Unable to parse at line 2 (near "foobar").'); $yaml = <<parser->parse($yaml); } @@ -2380,8 +2319,8 @@ public function testInlineMappingFollowedByMoreContentIsInvalid() $this->expectExceptionMessage('Unexpected token "baz" at line 1 (near "{ foo: bar } baz").'); $yaml = <<parser->parse($yaml); } @@ -2392,8 +2331,8 @@ public function testInlineSequenceFollowedByMoreContentIsInvalid() $this->expectExceptionMessage('Unexpected token ",bar," at line 1 (near "[\'foo\'],bar,").'); $yaml = <<parser->parse($yaml); } @@ -2410,9 +2349,7 @@ public function testInvalidInlineSequenceContainingStringWithEscapedQuotationCha $this->parser->parse('["\\"]'); } - /** - * @dataProvider taggedValuesProvider - */ + #[DataProvider('taggedValuesProvider')] public function testCustomTagSupport($expected, $yaml) { $this->assertSameData($expected, $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS)); @@ -2427,35 +2364,35 @@ public static function taggedValuesProvider() 'quz' => new TaggedValue('long', 'this is a long text'), ], << - this is a long - text -YAML, + foo: !inline bar + quz: !long > + this is a long + text + YAML, ], 'sequences' => [ [new TaggedValue('foo', ['yaml']), new TaggedValue('quz', ['bar'])], << [ new TaggedValue('foo', ['foo' => new TaggedValue('quz', ['bar']), 'quz' => new TaggedValue('foo', ['quz' => 'bar'])]), << [ [new TaggedValue('foo', ['foo', 'bar']), new TaggedValue('quz', ['foo' => 'bar', 'quz' => new TaggedValue('bar', ['one' => 'bar'])])], << [ [new TaggedValue('foo', 'bar')], @@ -2466,24 +2403,24 @@ public static function taggedValuesProvider() [new TaggedValue('foo', ['foo', 'baz'])], ], << [ [ [new TaggedValue('foo', ['foo', 'baz'])], ], <<expectException(ParseException::class); $this->expectExceptionMessage('Complex mappings are not supported at line 1 (near "? "1"").'); @@ -2538,11 +2475,11 @@ public function testComplexMappingThrowsParseException() public function testComplexMappingNestedInMappingThrowsParseException() { $yaml = <<expectException(ParseException::class); $this->expectExceptionMessage('Complex mappings are not supported at line 2 (near "? "1"").'); @@ -2553,10 +2490,10 @@ public function testComplexMappingNestedInMappingThrowsParseException() public function testComplexMappingNestedInSequenceThrowsParseException() { $yaml = <<expectException(ParseException::class); $this->expectExceptionMessage('Complex mappings are not supported at line 1 (near "- ? "1"").'); @@ -2567,10 +2504,10 @@ public function testComplexMappingNestedInSequenceThrowsParseException() public function testParsingIniThrowsException() { $ini = <<expectException(ParseException::class); $this->expectExceptionMessage('Unable to parse at line 2 (near " foo = bar").'); @@ -2621,17 +2558,17 @@ public function testCanParseVeryLongValue() public function testParserCleansUpReferencesBetweenRuns() { $yaml = <<parser->parse($yaml); $yaml = <<expectException(ParseException::class); $this->expectExceptionMessage('Reference "foo" does not exist at line 2'); @@ -2642,12 +2579,12 @@ public function testParserCleansUpReferencesBetweenRuns() public function testPhpConstantTagMappingKey() { $yaml = << [ 'foo' => [ @@ -2673,13 +2610,13 @@ public function testWrongPhpConstantSyntax() public function testPhpConstantTagMappingAsScalarKey() { $yaml = <<assertSame([ 'map1' => [['foo' => 'value_0', 'bar' => 'value_1']], 'map2' => [['foo' => 'value_0', 'bar' => 'value_1']], @@ -2689,10 +2626,10 @@ public function testPhpConstantTagMappingAsScalarKey() public function testTagMappingAsScalarKey() { $yaml = <<assertSame([ 'map1' => [['0' => 'value_0', '1' => 'value_1']], ], $this->parser->parse($yaml)); @@ -2701,19 +2638,19 @@ public function testTagMappingAsScalarKey() public function testMergeKeysWhenMappingsAreParsedAsObjects() { $yaml = << (object) [ 'bar' => 1, @@ -2765,7 +2702,7 @@ public function testParsingNotReadableFilesThrowsException() } $file = __DIR__.'/Fixtures/not_readable.yml'; - chmod($file, 0200); + chmod($file, 0o200); $this->expectException(ParseException::class); $this->expectExceptionMessageMatches('#^File ".+/Fixtures/not_readable.yml" cannot be read\.$#'); @@ -2776,15 +2713,15 @@ public function testParsingNotReadableFilesThrowsException() public function testParseReferencesOnMergeKeys() { $yaml = << [ 'a' => 'foo', @@ -2804,15 +2741,15 @@ public function testParseReferencesOnMergeKeys() public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects() { $yaml = << (object) [ 'a' => 'foo', @@ -2832,8 +2769,8 @@ public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects() public function testEvalRefException() { $yaml = <<expectException(ParseException::class); $this->expectExceptionMessage('Reference "foo" does not exist'); @@ -2841,9 +2778,7 @@ public function testEvalRefException() $this->parser->parse($yaml); } - /** - * @dataProvider circularReferenceProvider - */ + #[DataProvider('circularReferenceProvider')] public function testDetectCircularReferences($yaml) { $this->expectException(ParseException::class); @@ -2856,28 +2791,28 @@ public static function circularReferenceProvider() $tests = []; $yaml = <<- - #/string/bar -anyOfMultiline: - - $ref: >- - #/string/bar - second line -nested: - anyOf: - - $ref: >- - #/string/bar -YAML; + anyOf: + - $ref: >- + #/string/bar + anyOfMultiline: + - $ref: >- + #/string/bar + second line + nested: + anyOf: + - $ref: >- + #/string/bar + YAML; $expected = [ 'anyOf' => [ 0 => [ @@ -2921,9 +2856,7 @@ public function testBlockScalarArray() $this->assertSame($expected, $this->parser->parse($yaml)); } - /** - * @dataProvider indentedMappingData - */ + #[DataProvider('indentedMappingData')] public function testParseIndentedMappings($yaml, $expected) { $this->assertSame($expected, $this->parser->parse($yaml)); @@ -2934,11 +2867,11 @@ public static function indentedMappingData() $tests = []; $yaml = << [ [ @@ -2950,11 +2883,11 @@ public static function indentedMappingData() $tests['comment line is first line in indented block'] = [$yaml, $expected]; $yaml = << [ [ @@ -2967,10 +2900,10 @@ public static function indentedMappingData() $tests['mapping value on new line starting with a comment line'] = [$yaml, $expected]; $yaml = << [ [ @@ -2981,10 +2914,10 @@ public static function indentedMappingData() $tests['mapping in sequence starting on a new line'] = [$yaml, $expected]; $yaml = << [ 'bar' => 'baz', @@ -2998,11 +2931,11 @@ public static function indentedMappingData() public function testMultiLineComment() { $yaml = <<assertSame(['parameters' => 'abc'], $this->parser->parse($yaml)); } @@ -3010,14 +2943,14 @@ public function testMultiLineComment() public function testParseValueWithModifiers() { $yaml = <<assertSame( [ 'parameters' => [ @@ -3031,14 +2964,14 @@ public function testParseValueWithModifiers() public function testParseValueWithNegativeModifiers() { $yaml = <<assertSame( [ 'parameters' => [ @@ -3110,12 +3043,12 @@ public function testParsingMultipleDocuments() { $shortDocument = 'foo: bar'; $longDocument = <<assertSame([ 'unquoted' => ' ', 'quoted' => ' ', diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index 2ceac94665037..931642400f4db 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "require-dev": { - "symfony/console": "^6.4|^7.0" + "symfony/console": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/console": "<6.4" diff --git a/src/Symfony/Component/Yaml/phpunit.xml.dist b/src/Symfony/Component/Yaml/phpunit.xml.dist index 3dc41d45ed45d..e1f4cbc888b2e 100644 --- a/src/Symfony/Component/Yaml/phpunit.xml.dist +++ b/src/Symfony/Component/Yaml/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -26,5 +27,9 @@ ./Tests ./vendor - + + + + + diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index 9a528f6982920..7f5473abd53ca 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -12,6 +12,7 @@ namespace Symfony\Contracts\HttpClient\Test; use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; @@ -346,6 +347,8 @@ public function test304() * @testWith [[]] * [["Content-Length: 7"]] */ + #[TestWith([[]])] + #[TestWith([['Content-Length: 7']])] public function testRedirects(array $headers = []) { $client = $this->getHttpClient(__FUNCTION__); diff --git a/src/Symfony/Contracts/Service/Test/ServiceLocatorTest.php b/src/Symfony/Contracts/Service/Test/ServiceLocatorTest.php index 07d12b4a5bdd3..015ca71e187b4 100644 --- a/src/Symfony/Contracts/Service/Test/ServiceLocatorTest.php +++ b/src/Symfony/Contracts/Service/Test/ServiceLocatorTest.php @@ -11,13 +11,9 @@ namespace Symfony\Contracts\Service\Test; -class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); - -if (false) { - /** - * @deprecated since PHPUnit 9.6 - */ - class ServiceLocatorTest - { - } +/** + * @deprecated since PHPUnit 9.6 + */ +class ServiceLocatorTest extends ServiceLocatorTestCase +{ } diff --git a/src/Symfony/Contracts/Tests/Service/ServiceSubscriberTraitTest.php b/src/Symfony/Contracts/Tests/Service/ServiceSubscriberTraitTest.php index bf0db2c1e158a..b506e6e5ae353 100644 --- a/src/Symfony/Contracts/Tests/Service/ServiceSubscriberTraitTest.php +++ b/src/Symfony/Contracts/Tests/Service/ServiceSubscriberTraitTest.php @@ -11,6 +11,8 @@ namespace Symfony\Contracts\Tests\Service; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Contracts\Service\Attribute\Required; @@ -19,9 +21,8 @@ use Symfony\Contracts\Service\ServiceSubscriberInterface; use Symfony\Contracts\Service\ServiceSubscriberTrait; -/** - * @group legacy - */ +#[IgnoreDeprecations] +#[Group('legacy')] class ServiceSubscriberTraitTest extends TestCase { public static function setUpBeforeClass(): void diff --git a/src/Symfony/Contracts/Translation/TranslatorTrait.php b/src/Symfony/Contracts/Translation/TranslatorTrait.php index afedd9928b39b..06d3e30592029 100644 --- a/src/Symfony/Contracts/Translation/TranslatorTrait.php +++ b/src/Symfony/Contracts/Translation/TranslatorTrait.php @@ -62,22 +62,22 @@ public function trans(?string $id, array $parameters = [], ?string $domain = nul } $intervalRegexp = <<<'EOF' -/^(?P - ({\s* - (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) - \s*}) - - | - - (?P[\[\]]) - \s* - (?P-Inf|\-?\d+(\.\d+)?) - \s*,\s* - (?P\+?Inf|\-?\d+(\.\d+)?) - \s* - (?P[\[\]]) -)\s*(?P.*?)$/xs -EOF; + /^(?P + ({\s* + (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) + \s*}) + + | + + (?P[\[\]]) + \s* + (?P-Inf|\-?\d+(\.\d+)?) + \s*,\s* + (?P\+?Inf|\-?\d+(\.\d+)?) + \s* + (?P[\[\]]) + )\s*(?P.*?)$/xs + EOF; $standardRules = []; foreach ($parts as $part) { diff --git a/src/Symfony/Contracts/phpunit.xml.dist b/src/Symfony/Contracts/phpunit.xml.dist index 947db86d20ad9..8a2d5481ed3cf 100644 --- a/src/Symfony/Contracts/phpunit.xml.dist +++ b/src/Symfony/Contracts/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -20,7 +21,7 @@ - + ./ @@ -30,6 +31,9 @@ ./Translation/Test/ ./vendor - + + + +