diff --git a/.github/composer-config.json b/.github/composer-config.json index 25d2bcd027af8..65919964fa8a1 100644 --- a/.github/composer-config.json +++ b/.github/composer-config.json @@ -6,6 +6,7 @@ "symfony/http-kernel": "source", "symfony/messenger": "source", "symfony/notifier": "source", + "symfony/proxy-manager-bridge": "source", "symfony/translation": "source", "symfony/validator": "source", "*": "dist" diff --git a/.github/patch-types.php b/.github/patch-types.php index e40bfb0ec0f6c..33ba6347a3ef0 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -16,12 +16,15 @@ case false !== strpos($file = realpath($file), '/vendor/'): case false !== strpos($file, '/src/Symfony/Bridge/PhpUnit/'): case false !== strpos($file, '/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php'): + case false !== strpos($file, '/src/Symfony/Component/Cache/Tests/Fixtures/DriverWrapper.php'): case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadFileName.php'): case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php'): case false !== strpos($file, '/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php'): + case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/intersectiontype_classes.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/MultipleArgumentsOptionalScalarNotReallyOptional.php'): + case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/IntersectionConstructor.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/ParentNotExists.php'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Preload/'): case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/BadClasses/MissingParent.php'): @@ -32,6 +35,7 @@ case false !== strpos($file, '/src/Symfony/Component/Runtime/Internal/ComposerPlugin.php'): case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'): + case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/ReflectionIntersectionTypeFixture.php'): continue 2; } diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 5b68583a06a14..acdb9ff52b6f4 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -123,7 +123,7 @@ jobs: with: coverage: "none" extensions: "json,couchbase,memcached,mongodb,redis,rdkafka,xsl,ldap" - ini-values: "memory_limit=-1" + ini-values: date.timezone=Europe/Paris,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 php-version: "${{ matrix.php }}" tools: pecl @@ -136,7 +136,7 @@ jobs: uses: docker://bitnami/openldap with: entrypoint: /bin/bash - args: -c "(/opt/bitnami/openldap/bin/ldapwhoami -h localhost:3389 -D cn=admin,dc=symfony,dc=com -w symfony||sleep 5) && /opt/bitnami/openldap/bin/ldapadd -h ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif && /opt/bitnami/openldap/bin/ldapdelete -h ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony cn=a,ou=users,dc=symfony,dc=com" + args: -c "(/opt/bitnami/openldap/bin/ldapwhoami -H ldap://ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony||sleep 5) && /opt/bitnami/openldap/bin/ldapadd -H ldap://ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony -f src/Symfony/Component/Ldap/Tests/Fixtures/data/fixtures.ldif && /opt/bitnami/openldap/bin/ldapdelete -H ldap://ldap:3389 -D cn=admin,dc=symfony,dc=com -w symfony cn=a,ou=users,dc=symfony,dc=com" - name: Install dependencies run: | diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml new file mode 100644 index 0000000000000..5bbcc63041020 --- /dev/null +++ b/.github/workflows/phpunit-bridge.yml @@ -0,0 +1,31 @@ +name: PhpUnitBridge + +on: + push: + paths: + - 'src/Symfony/Bridge/PhpUnit/**' + pull_request: + paths: + - 'src/Symfony/Bridge/PhpUnit/**' + +defaults: + run: + shell: bash + +jobs: + lint: + name: Lint + runs-on: Ubuntu-20.04 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: "none" + php-version: "7.1" + + - name: Lint + run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {} diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index ceffbe310240c..430d67c4c8cda 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -41,13 +41,12 @@ jobs: run: | echo "extensions=mbstring" >> $GITHUB_ENV composer config platform.php 8.0.99 - composer require --dev --no-update masterminds/html5:~2.7.5@dev - name: Setup PHP uses: shivammathur/setup-php@v2 with: coverage: "none" - ini-values: date.timezone=Europe/Paris,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1 + ini-values: date.timezone=Europe/Paris,memory_limit=-1,default_socket_timeout=10,session.gc_probability=0,apc.enable_cli=1,zend.assertions=1 php-version: "${{ matrix.php }}" extensions: "${{ env.extensions }}" tools: flex @@ -140,7 +139,7 @@ jobs: if: "${{ matrix.php == '8.0' && ! matrix.mode }}" run: | sed -i 's/"\*\*\/Tests\/"//' composer.json - composer install --optimize-autoloader + composer install -q --optimize-autoloader SYMFONY_PATCH_TYPE_DECLARATIONS=force=1 php .github/patch-types.php SYMFONY_PATCH_TYPE_DECLARATIONS=force=1 php .github/patch-types.php # ensure the script is idempotent echo PHPUNIT="$PHPUNIT,legacy" >> $GITHUB_ENV @@ -185,10 +184,12 @@ jobs: # matrix.mode = high-deps echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP && $PHPUNIT$LEGACY'" || X=1 + # get a list of the patched components (relies on .github/build-packages.php being called in the previous step) (cd src/Symfony/Component/HttpFoundation; mv composer.bak composer.json) - COMPONENTS=$(git diff --name-only src/ | grep composer.json || true) + PATCHED_COMPONENTS=$(git diff --name-only src/ | grep composer.json || true) - if [[ $COMPONENTS && $SYMFONY_VERSION = *.4 ]]; then + # for x.4 branches, checkout and test previous major with the patched components (only for patched components) + if [[ $PATCHED_COMPONENTS && $SYMFONY_VERSION = *.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" @@ -196,13 +197,13 @@ jobs: export SYMFONY_REQUIRE=">=$SYMFONY_VERSION" git fetch --depth=2 origin $SYMFONY_VERSION git checkout -m FETCH_HEAD - COMPONENTS=$(echo "$COMPONENTS" | xargs dirname | xargs -n1 -I{} bash -c "[ -e '{}/phpunit.xml.dist' ] && echo '{}'" | sort || true) + PATCHED_COMPONENTS=$(echo "$PATCHED_COMPONENTS" | xargs dirname | xargs -n1 -I{} bash -c "[ -e '{}/phpunit.xml.dist' ] && echo '{}'" | sort || true) (cd src/Symfony/Component/HttpFoundation; composer require --dev --no-update mongodb/mongodb) - if [[ $COMPONENTS ]]; then + if [[ $PATCHED_COMPONENTS ]]; then echo "::group::install phpunit" ./phpunit install echo "::endgroup::" - echo "$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$LEGACY'" || X=1 fi fi diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 95aee3c4ba462..cfe2bb4456738 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -11,6 +11,7 @@ '@Symfony' => true, '@Symfony:risky' => true, 'protected_to_private' => false, + 'nullable_type_declaration_for_default_null_value' => ['use_nullable_type_declaration' => false], ]) ->setRiskyAllowed(true) ->setFinder( @@ -26,6 +27,7 @@ 'Symfony/Bundle/FrameworkBundle/Resources/views/Form', // explicit trigger_error tests 'Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/', + 'Symfony/Component/Intl/Resources/data/', ]) // Support for older PHPunit version ->notPath('Symfony/Bridge/PhpUnit/SymfonyTestsListener.php') diff --git a/CHANGELOG-5.2.md b/CHANGELOG-5.2.md index eaac88436e233..f84a666111572 100644 --- a/CHANGELOG-5.2.md +++ b/CHANGELOG-5.2.md @@ -7,6 +7,46 @@ in 5.2 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.2.0...v5.2.1 +* 5.2.11 (2021-06-30) + + * bug #41893 [Filesystem] Workaround cannot dumpFile into "protected" folders on Windows (arnegroskurth) + * bug #41896 [Messenger] fix FlattenExceptionNormalizer (nicolas-grekas) + * bug #41242 [SecurityBundle] Change information label from red to yellow (94noni) + * bug #41665 [HttpKernel] Keep max lifetime also when part of the responses don't set it (mpdude) + * bug #41760 [ErrorHandler] fix handling buffered SilencedErrorContext (nicolas-grekas) + * bug #41807 [HttpClient] fix Psr18Client when allow_url_fopen=0 (nicolas-grekas) + * bug #40857 [DependencyInjection] Add support of PHP enumerations (alexandre-daubois) + * bug #41767 [Config] fix tracking default values that reference the parent class (nicolas-grekas) + * bug #41768 [DependencyInjection] Fix binding "iterable $foo" when using the PHP-DSL (nicolas-grekas) + * bug #41801 [Uid] Fix fromString() with low base58 values (fancyweb) + * bug #41793 [Cache] handle prefixed redis connections when clearing pools (nicolas-grekas) + * bug #41804 [Cache] fix eventual consistency when using RedisTagAwareAdapter with a cluster (nicolas-grekas) + * bug #41773 [Cache] Disable locking on Windows by default (nicolas-grekas) + * bug #41655 [Mailer] fix encoding of addresses using SmtpTransport (dmaicher) + * bug #41663 [HttpKernel] [HttpCache] Keep s-maxage=0 from ESI sub-responses (mpdude) + * bug #41739 Avoid broken action URL in text notification mail (mbrodala) + * bug #41701 [VarDumper] Fix tests for PHP 8.1 (alexandre-daubois) + * bug #41795 [FrameworkBundle] Replace var_export with VarExporter to use array short syntax in secrets list files (alexandre-daubois) + * bug #41779 [DependencyInjection] throw proper exception when decorating a synthetic service (nicolas-grekas) + * bug #41776 [ErrorHandler] [DebugClassLoader] Do not check Phake mocks classes (adoy) + * bug #41780 [PhpUnitBridge] fix handling the COMPOSER_BINARY env var when using simple-phpunit (Taluu) + * bug #41670 [HttpFoundation] allow savePath of NativeFileSessionHandler to be null (simon.chrzanowski) + * bug #41751 [Messenger] prevent reflection usages when classes do not exist (xabbuh) + * bug #41616 [Messenger] Remove TLS related options when not using TLS (odolbeau) + * bug #41719 [FrameworkBundle] fix Could not find service "test.service_container" (smilesrg) + * bug #41674 [HttpClient] fix compat with cURL <= 7.37 (nicolas-grekas) + * bug #41656 [HttpClient] throw exception when AsyncDecoratorTrait gets an already consumed response (nicolas-grekas) + * bug #41644 [Config] fix tracking attributes in ReflectionClassResource (nicolas-grekas) + * bug #41621 [Process] Fix incorrect parameter type (bch36) + * bug #41624 [HttpClient] Revert bindto workaround for unaffected PHP versions (derrabus) + * bug #41549 [Security] Fix opcache preload with alias classes (jderusse) + * bug #41491 [Serializer] Do not allow to denormalize string with spaces only to valid a DateTime object (sidz) + * bug #41218 [DependencyInjection] Update loader’s directory when calling ContainerConfigurator::withPath (MatTheCat) + * bug #41505 [FrameworkBundle] fix KernelBrowser::loginUser with a stateless firewall (dunglas) + * bug #41509 [SecurityBundle] Link UserProviderListener to correct firewall dispatcher (Matth--) + * bug #41386 [Console] Escape synopsis output (jschaedl) + * bug #41495 [HttpFoundation] Add ReturnTypeWillChange to SessionHandlers (nikic) + * 5.2.10 (2021-06-01) * bug #41000 [Form] Use !isset for checks cause this doesn't falsely include 0 (Kai Dederichs) diff --git a/CHANGELOG-5.3.md b/CHANGELOG-5.3.md index d3d595787c3cf..ecfcb955ad67a 100644 --- a/CHANGELOG-5.3.md +++ b/CHANGELOG-5.3.md @@ -7,6 +7,55 @@ in 5.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.3.0...v5.3.1 +* 5.3.4 (2021-07-26) + + * bug #41504 [Translation] Fix default value for locales in translation push|pull commands (welcoMattic) + * bug #42243 [Translation] [Lokalise] Fix `base_uri` (welcoMattic, Nyholm) + * bug #42212 [Lock] Handle lock with long key (jderusse) + * bug #42223 [Debug][ErrorHandler] Do not use the php80 polyfill (nicolas-grekas) + * bug #42207 [Console] fix table setHeaderTitle without headers (a1812) + * bug #42130 [Translation] fix fallback to Locale::getDefault() (nicolas-grekas) + * bug #42184 [Mailer] Make sure Http TransportException is not leaking (Nyholm) + * bug #42091 [Console] Run commands when implements SignalableCommandInterface without pcntl and they have'nt signals (PaolaRuby) + * bug #42150 [Form] Fix 'invalid_message' use in multiple ChoiceType (alexandre-daubois) + * bug #42183 [Notifier] Allow passing a previous throwable to exceptions (derrabus) + * bug #42185 [Notifier] Make sure Http TransportException is not leaking (Nyholm) + * bug #42182 [Notifier] Make sure Http TransportException is not leaking (Nyholm) + * bug #42173 [Messenger] [Redis] Fix auth option wrongly considered invalid (chalasr) + * bug #42174 Indicate compatibility with psr/log 2 and 3 (derrabus) + * bug #41897 [Security] fix #41891 Save hashed tokenValue in RememberMe cookie (qurben) + * bug #42156 Fix missing assignment (Seldaek) + * bug #42112 [HttpFoundation] fix FileBag under PHP 8.1 (alexpott) + * bug #42131 [PhpUnitBridge] Fix composer resolution on Windows (Rainrider) + * bug #42097 [DependencyInjection] Support for intersection types (derrabus) + * bug #42114 [HttpFoundation] Fix return types of SessionHandler::gc() (derrabus) + * bug #42099 [VarDumper] Support for intersection types (derrabus) + * bug #42011 [Cache] Support decorated Dbal drivers in PdoAdapter (Jeroeny) + * bug #42068 Add a Special Case for Translating Choices in en_US_POSIX (chrisguitarguy) + * bug #42074 Fix ctype_digit deprecation (alexpott) + * bug #42084 [WebProfilerBundle] Fix the values of some CSS properties (javiereguiluz) + * bug #42079 [FrameworkBundle] Fixed file operations in Sodium vault seal (javiereguiluz) + * bug #42078 [DoctrineBridge] [Doctrine Bridge] Fix an exception message (javiereguiluz) + * bug #42067 [Messenger] [Redis] Make `auth` option works (welcoMattic) + * bug #42054 [DoctrineBridge] fix setting default mapping type to attribute/annotation on php 8/7 respectively (nicolas-grekas) + * bug #42059 [Messenger] Fixed BC layer for RedeliveryStamp (Nyholm) + * bug #42060 [Messenger] AmqpTransport implements QueueReceiverInterface (xabbuh) + * bug #42049 [TwigBridge] do not render the same label id attribute twice (xabbuh) + * bug #42019 [DependencyInjection] Fix TaggedLocator attribute without indexAttribute argument (Lucas Bäuerle) + * bug #42032 [HttpKernel] recover from failed deserializations (xabbuh) + * bug #42035 [Messenger] Fix use_notify default value for PostgreSqlConnection (tgalopin) + * bug #42009 [Console] Fix save correct name in setDefaultCommand() for PHP8 (a1812) + * bug #41990 [Lock] fix derivating semaphore from key (nicolas-grekas) + * bug #41986 [Notifier] Fix TransportTestCase (OskarStark) + * bug #40529 [Translation] Missing translations from traits (insekticid) + * bug #41384 Fix SkippedTestSuite (jderusse) + * bug #41966 [Console] Revert "bug #41952 fix handling positional arguments" (chalasr, nicolas-grekas) + * bug #41905 [EventDispatcher] Correct the called event listener method case (JJsty1e) + * bug #41961 [Serializer] Need to clear cache when updating Annotation Groups on Entities (monteiro) + * bug #41952 [Console] fix handling positional arguments (nicolas-grekas) + * bug #41917 Rethrow exception in `DoctrineTokenProvider` (jderusse) + * bug #41887 [PhpUnitBridge] Fix deprecation handler with PHPUnit 10 (YaFou) + * 5.3.3 (2021-06-30) * bug #41910 [Security] Handle concurency in Csrf DoctrineTokenProvider (jderusse) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 311957098418a..275042f9e08f6 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -13,8 +13,8 @@ The Symfony Connect username in parenthesis allows to get more information - Robin Chalas (chalas_r) - Christophe Coevoet (stof) - Maxime Steinhausser (ogizanagi) - - Kévin Dunglas (dunglas) - Jérémy DERUSSÉ (jderusse) + - Kévin Dunglas (dunglas) - Grégoire Pineau (lyrixx) - Wouter De Jong (wouterj) - Jordi Boggiano (seldaek) @@ -43,8 +43,8 @@ The Symfony Connect username in parenthesis allows to get more information - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - - Igor Wiedler (igorw) - Jan Schädlich (jschaedl) + - Igor Wiedler (igorw) - Eriksen Costa (eriksencosta) - Ener-Getick (energetick) - Sarah Khalil (saro0h) @@ -112,10 +112,10 @@ The Symfony Connect username in parenthesis allows to get more information - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - John Wards (johnwards) + - Baptiste Clavié (talus) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - Alexander Schranz (alexander-schranz) - - Baptiste Clavié (talus) - Arnaud Le Blanc (arnaud-lb) - Przemysław Bogusz (przemyslaw-bogusz) - Maxime STEINHAUSSER @@ -138,6 +138,7 @@ The Symfony Connect username in parenthesis allows to get more information - Włodzimierz Gajda (gajdaw) - Christian Scheb - Adrien Brault (adrienbrault) + - Tomas Norkūnas (norkunas) - Julien Falque (julienfalque) - Jacob Dreesen (jdreesen) - Malte Schlüter (maltemaltesich) @@ -147,21 +148,20 @@ The Symfony Connect username in parenthesis allows to get more information - Colin Frei - Javier Spagnoletti (phansys) - Joshua Thijssen - - Tomas Norkūnas (norkunas) - Yanick Witschi (toflar) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - excelwebzone - Gordon Franke (gimler) - Saif Eddin Gmati (azjezz) + - HypeMC (hypemc) - Jesse Rushlow (geeshoe) - Fabien Pennequin (fabienpennequin) - Théo FIDRY (theofidry) + - Olivier Dolbeau (odolbeau) - Eric GELOEN (gelo) - Matthieu Napoli (mnapoli) - - HypeMC (hypemc) - Jannik Zschiesche (apfelbox) - - Olivier Dolbeau (odolbeau) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) - Tigran Azatyan (tigranazatyan) @@ -202,12 +202,14 @@ The Symfony Connect username in parenthesis allows to get more information - Andreas Schempp (aschempp) - Romaric Drigon (romaricdrigon) - Arman Hosseini (arman) + - Alexandre Daubois (alexandre-daubois) - Niels Keurentjes (curry684) - Vyacheslav Pavlov - Richard Shank (iampersistent) - Wouter J - Thomas Rabaix (rande) - Chi-teck + - Mathieu Santostefano (welcomattic) - Jeroen Spee (jeroens) - Timo Bakx (timobakx) - Marco Pivetta (ocramius) @@ -233,9 +235,9 @@ The Symfony Connect username in parenthesis allows to get more information - GDIBass - Samuel NELA (snela) - David Prévot - - Mathieu Santostefano - Dmitrii Poddubnyi (karser) - Joe Bennett (kralos) + - Michael Babker (mbabker) - Tien Vo (tienvx) - Timothée Barray (tyx) - James Halsall (jaitsu) @@ -244,6 +246,7 @@ The Symfony Connect username in parenthesis allows to get more information - Benjamin Leveque (benji07) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) + - Mathieu Lechat (mat_the_cat) - Marek Štípek (maryo) - Daniel Espendiller - Possum @@ -257,6 +260,7 @@ The Symfony Connect username in parenthesis allows to get more information - Christopher Hertel (chertel) - DQNEO - Hidde Wieringa (hiddewie) + - Hugo Monteiro (monteiro) - Antonio Pauletich (x-coder264) - Andre Rømcke (andrerom) - Nate Wiebe (natewiebe13) @@ -275,7 +279,6 @@ The Symfony Connect username in parenthesis allows to get more information - Tom Van Looy (tvlooy) - Guillaume Pédelagrabe - Noel Guilbert (noel) - - Mathieu Lechat (mat_the_cat) - Anthony GRASSIOT (antograssiot) - Stadly - Stepan Anchugov (kix) @@ -296,12 +299,10 @@ The Symfony Connect username in parenthesis allows to get more information - Pierre Minnieur (pminnieur) - fivestar - Dominique Bongiraud - - Hugo Monteiro (monteiro) - dFayet - Jeremy Livingston (jeremylivingston) - Michael Lee (zerustech) - Matthieu Auger (matthieuauger) - - Michael Babker (mbabker) - Leszek Prabucki (l3l0) - Nicolas Philippe (nikophil) - Colin O'Dell (colinodell) @@ -312,15 +313,17 @@ The Symfony Connect username in parenthesis allows to get more information - John Kary (johnkary) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) + - Denis Brumann (dbrumann) - Michele Orselli (orso) - Sven Paulus (subsven) - Daniel STANCU - Maxime Veber (nek-) + - Ion Bazan (ionbazan) - Loick Piera (pyrech) - Clara van Miert + - Valentine Boineau (valentineboineau) - Bastien Jaillot (bastnic) - Rui Marinho (ruimarinho) - - Alexandre Daubois (alexandre-daubois) - Eugene Wissner - Bohan Yang (brentybh) - Pascal Montoya @@ -363,7 +366,6 @@ The Symfony Connect username in parenthesis allows to get more information - Roman Marintšenko (inori) - Xavier Montaña Carreras (xmontana) - Mickaël Andrieu (mickaelandrieu) - - Ion Bazan (ionbazan) - Xavier Perez - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA @@ -374,7 +376,6 @@ The Symfony Connect username in parenthesis allows to get more information - Anton Chernikov (anton_ch1989) - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) - - Denis Brumann (dbrumann) - Jordan Samouh (jordansamouh) - Jakub Kucharovic (jkucharovic) - Sullivan SENECHAL (soullivaneuh) @@ -489,6 +490,7 @@ The Symfony Connect username in parenthesis allows to get more information - Loïc Frémont (loic425) - Oleksandr Barabolia (oleksandrbarabolia) - ivan + - Artem Henvald (artemgenvald) - Greg Anderson - Tri Pham (phamuyentri) - BoShurik @@ -523,6 +525,7 @@ The Symfony Connect username in parenthesis allows to get more information - Terje Bråten - Renan Gonçalves (renan_saddam) - Marco Petersen (ocrampete16) + - Tarmo Leppänen (tarlepp) - Martin Auswöger - Robbert Klarenbeek (robbertkl) - Eric Masoero (eric-masoero) @@ -556,7 +559,6 @@ The Symfony Connect username in parenthesis allows to get more information - Tamas Szijarto - Michele Locati - Pavel Volokitin (pvolok) - - Valentine Boineau (valentineboineau) - Gijs van Lammeren - Arthur de Moulins (4rthem) - Matthias Althaus (althaus) @@ -616,7 +618,6 @@ The Symfony Connect username in parenthesis allows to get more information - Christopher Davis (chrisguitarguy) - Andrey Sevastianov - Webnet team (webnet) - - Artem Henvald (artemgenvald) - marie - Jan Schumann - Noémi Salaün (noemi-salaun) @@ -643,6 +644,7 @@ The Symfony Connect username in parenthesis allows to get more information - Xavier Briand (xavierbriand) - Asmir Mustafic (goetas) - DerManoMann + - Stefan Gehrig (sgehrig) - vagrant - Aurimas Niekis (gcds) - EdgarPE @@ -674,7 +676,6 @@ The Symfony Connect username in parenthesis allows to get more information - Soner Sayakci - Tobias Weichart - Miro Michalicka - - Tarmo Leppänen (tarlepp) - Marcin Sikoń (marphi) - M. Vondano - Dominik Zogg (dominik.zogg) @@ -786,6 +787,7 @@ The Symfony Connect username in parenthesis allows to get more information - Joachim Løvgaard (loevgaard) - jhonnyL - sasezaki + - Jonathan Scheiber (jmsche) - Kristof Van Cauwenbergh (kristofvc) - Dawid Pakuła (zulusx) - Marco Lipparini (liarco) @@ -832,6 +834,7 @@ The Symfony Connect username in parenthesis allows to get more information - Pablo Lozano (arkadis) - Thiago Cordeiro (thiagocordeiro) - Jan Behrens + - Dragos Protung (dragosprotung) - Mantas Var (mvar) - Terje Bråten - Yann LUCAS (drixs6o9) @@ -912,7 +915,6 @@ The Symfony Connect username in parenthesis allows to get more information - Julien Fredon - Jacek Wilczyński (jacekwilczynski) - Xavier Leune (xleune) - - Stefan Gehrig (sgehrig) - Hany el-Kerdany - Wang Jingyu - Åsmund Garfors @@ -1075,6 +1077,7 @@ The Symfony Connect username in parenthesis allows to get more information - Andrea Sprega (asprega) - Alexander Volochnev (exelenz) - Viktor Bajraktar (njutn95) + - SiD (plbsid) - Mbechezi Nawo - Michael Piecko - Toni Peric (tperic) @@ -1223,7 +1226,6 @@ The Symfony Connect username in parenthesis allows to get more information - Bernhard Rusch - Ivan - Quentin Schuler - - Jonathan Scheiber (jmsche) - Pierre Vanliefland (pvanliefland) - Roy Klutman (royklutman) - Sofiane HADDAG (sofhad) @@ -1231,6 +1233,7 @@ The Symfony Connect username in parenthesis allows to get more information - Taylor Otwell - Dries Vints - Sami Mussbach + - Kien Nguyen - Foxprodev - Eric Hertwig - Niels Robin-Aubertin @@ -1391,7 +1394,6 @@ The Symfony Connect username in parenthesis allows to get more information - Andre Johnson - Marco Pfeiffer - Rootie - - Dragos Protung (dragosprotung) - Gabriel Solomon (gabrielsolomon) - Daniel Alejandro Castro Arellano (lexcast) - Aleksandar Dimitrov (netbull) @@ -1454,6 +1456,7 @@ The Symfony Connect username in parenthesis allows to get more information - Amirreza Shafaat (amirrezashafaat) - Adoni Pavlakis (adoni) - Nicolas Le Goff (nlegoff) + - Maarten Nusteling (nusje2000) - Ahmed EBEN HASSINE (famas23) - Ben Oman - Chris de Kok @@ -1464,6 +1467,7 @@ The Symfony Connect username in parenthesis allows to get more information - Irmantas Šiupšinskas (irmantas) - Danilo Silva - Giuseppe Campanelli + - Matthieu Calie (matth--) - Arnaud PETITPAS (apetitpa) - Ken Stanley - ivan @@ -1651,6 +1655,7 @@ The Symfony Connect username in parenthesis allows to get more information - Loïc Ovigne (oviglo) - Artem Kolesnikov (tyomo4ka) - Markkus Millend + - Clément - Gustavo Adrian - Jorrit Schippers (jorrit) - Yannick @@ -1664,6 +1669,7 @@ The Symfony Connect username in parenthesis allows to get more information - Amine Yakoubi - Eduardo García Sanz (coma) - Sergio (deverad) + - simon chrzanowski (simonch) - Makdessi Alex - James Gilliland - fduch (fduch) @@ -1677,7 +1683,6 @@ The Symfony Connect username in parenthesis allows to get more information - arnaud (arnooo999) - Gilles Doge (gido) - Oscar Esteve (oesteve) - - SiD (plbsid) - abulford - Philipp Kretzschmar - antograssiot @@ -1901,6 +1906,7 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel González Zaballos (dem3trio) - Emmanuel Vella (emmanuel.vella) - Guillaume BRETOU (guiguiboy) + - Nikita Popov (nikic) - Carsten Nielsen (phreaknerd) - Jay Severson - Benny Born @@ -1938,6 +1944,7 @@ The Symfony Connect username in parenthesis allows to get more information - r1pp3rj4ck - phydevs - mmokhi + - Serhii Smirnov - Robert Queck - Peter Bouwdewijn - mlively @@ -1961,6 +1968,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matthew J Mucklo - AnrDaemon - Emre Akinci (emre) + - Chris Maiden (matason) - fdgdfg (psampaz) - Andrea Ruggiero (pupax) - Stéphane Seng @@ -1976,6 +1984,7 @@ The Symfony Connect username in parenthesis allows to get more information - Valentin VALCIU - Jeremiah VALERIE - Julien Menth + - George Yiannoulopoulos - Yannick Snobbert - Kevin Dew - James Cowgill @@ -2516,6 +2525,7 @@ The Symfony Connect username in parenthesis allows to get more information - Youpie - Jason Stephens - srsbiz + - Tinjo Schöni - Taylan Kasap - Michael Orlitzky - Nicolas A. Bérard-Nault @@ -2625,6 +2635,7 @@ The Symfony Connect username in parenthesis allows to get more information - Michal Forbak - Drew Butler - Alexey Berezuev + - Pierrick Charron - Steve Müller - Andras Ratz - andreabreu98 @@ -2636,10 +2647,12 @@ The Symfony Connect username in parenthesis allows to get more information - Anatol Belski - Şəhriyar İmanov - Alexis BOYER + - bch36 - Kaipi Yann - adam-mospan - Steve Hyde - Sam Williams + - Ettore Del Negro - Guillaume Aveline - Adrian Philipp - James Michael DuPont diff --git a/UPGRADE-5.2.md b/UPGRADE-5.2.md index 3334ed6665f2c..a1c4a137cb72e 100644 --- a/UPGRADE-5.2.md +++ b/UPGRADE-5.2.md @@ -22,22 +22,22 @@ Form * Deprecated `PropertyPathMapper` in favor of `DataMapper` and `PropertyPathAccessor`. - Before: + Before: - ```php - use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; + ```php + use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; - $builder->setDataMapper(new PropertyPathMapper()); - ``` + $builder->setDataMapper(new PropertyPathMapper()); + ``` - After: + After: - ```php - use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor; - use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper; + ```php + use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor; + use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper; - $builder->setDataMapper(new DataMapper(new PropertyPathAccessor())); - ``` + $builder->setDataMapper(new DataMapper(new PropertyPathAccessor())); + ``` HttpFoundation -------------- diff --git a/composer.json b/composer.json index 3c6619b7f2823..1b2709407654f 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "psr/event-dispatcher-implementation": "1.0", "psr/http-client-implementation": "1.0", "psr/link-implementation": "1.0", - "psr/log-implementation": "1.0", + "psr/log-implementation": "1.0|2.0", "psr/simple-cache-implementation": "1.0", "symfony/cache-implementation": "1.0|2.0", "symfony/event-dispatcher-implementation": "2.0", @@ -42,7 +42,7 @@ "psr/container": "^1.0", "psr/event-dispatcher": "^1.0", "psr/link": "^1.0", - "psr/log": "~1.0", + "psr/log": "^1|^2", "symfony/contracts": "^2.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", @@ -51,7 +51,7 @@ "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.11", - "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php80": "^1.16", "symfony/polyfill-php81": "^1.22", "symfony/polyfill-uuid": "^1.15" }, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5bf27434011c1..df9f82525162a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -31,6 +31,7 @@ ./src/Symfony/Bridge/*/Tests/ ./src/Symfony/Component/*/Tests/ ./src/Symfony/Component/*/*/Tests/ + ./src/Symfony/Component/*/*/*/Tests/ ./src/Symfony/Contract/*/Tests/ ./src/Symfony/Bundle/*/Tests/ diff --git a/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php b/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php index 386d8c62703c6..a55bf81de542f 100644 --- a/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php +++ b/src/Symfony/Bridge/Doctrine/ContainerAwareEventManager.php @@ -58,7 +58,7 @@ public function dispatchEvent($eventName, EventArgs $eventArgs = null) return; } - $eventArgs = null === $eventArgs ? EventArgs::getEmptyInstance() : $eventArgs; + $eventArgs = $eventArgs ?? EventArgs::getEmptyInstance(); if (!isset($this->initialized[$eventName])) { $this->initializeListeners($eventName); @@ -219,10 +219,7 @@ private function getHash($listener): string return spl_object_hash($listener); } - /** - * @param object $listener - */ - private function getMethod($listener, string $event): string + private function getMethod(object $listener, string $event): string { if (!method_exists($listener, $event) && method_exists($listener, '__invoke')) { return '__invoke'; diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php b/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php index 26bdb7ff267d0..dabb9ff2a35e2 100644 --- a/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php +++ b/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php @@ -18,10 +18,7 @@ final class ObjectParameter private $stringable; private $class; - /** - * @param object $object - */ - public function __construct($object, ?\Throwable $error) + public function __construct(object $object, ?\Throwable $error) { $this->object = $object; $this->error = $error; @@ -29,10 +26,7 @@ public function __construct($object, ?\Throwable $error) $this->class = \get_class($object); } - /** - * @return object - */ - public function getObject() + public function getObject(): object { return $this->object; } diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 00652bb71612a..868042bc31e6f 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\DependencyInjection; +use Symfony\Component\Config\Resource\GlobResource; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -88,6 +89,25 @@ protected function loadMappingInformation(array $objectManager, ContainerBuilder if (!$mappingConfig) { continue; } + } elseif (!$mappingConfig['type'] && \PHP_VERSION_ID < 80000) { + $mappingConfig['type'] = 'annotation'; + } elseif (!$mappingConfig['type']) { + $mappingConfig['type'] = 'attribute'; + + $glob = new GlobResource($mappingConfig['dir'], '*', true); + $container->addResource($glob); + + foreach ($glob as $file) { + $content = file_get_contents($file); + + if (preg_match('/^#\[.*Entity\b/m', $content)) { + break; + } + if (preg_match('/^ \* @.*Entity\b/m', $content)) { + $mappingConfig['type'] = 'annotation'; + break; + } + } } $this->assertValidMappingConfiguration($mappingConfig, $objectManager['name']); @@ -201,7 +221,7 @@ protected function registerMappingDrivers(array $objectManager, ContainerBuilder ]); } $mappingDriverDef->setPublic(false); - if (false !== strpos($mappingDriverDef->getClass(), 'yml') || false !== strpos($mappingDriverDef->getClass(), 'xml')) { + if (str_contains($mappingDriverDef->getClass(), 'yml') || str_contains($mappingDriverDef->getClass(), 'xml')) { $mappingDriverDef->setArguments([array_flip($driverPaths)]); $mappingDriverDef->addMethodCall('setGlobalBasename', ['mapping']); } diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index b6a699287b8c8..324d5d26d4b06 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -92,7 +92,7 @@ public static function createChoiceName(object $choice, $key, string $value): st * @internal This method is public to be usable as callback. It should not * be used in user code. */ - public function getQueryBuilderPartsForCachingHash($queryBuilder): ?array + public function getQueryBuilderPartsForCachingHash(object $queryBuilder): ?array { return null; } @@ -232,12 +232,13 @@ public function configureOptions(OptionsResolver $resolver) /** * Return the default loader object. * - * @param mixed $queryBuilder - * * @return EntityLoaderInterface */ - abstract public function getLoader(ObjectManager $manager, $queryBuilder, string $class); + abstract public function getLoader(ObjectManager $manager, object $queryBuilder, string $class); + /** + * @return string + */ public function getParent() { return ChoiceType::class; @@ -263,7 +264,7 @@ private function getCachedIdReader(ObjectManager $manager, string $class): ?IdRe return $this->idReaders[$hash] = $idReader->isSingleId() ? $idReader : null; } - private function getCachedEntityLoader(ObjectManager $manager, $queryBuilder, string $class, array $vary): EntityLoaderInterface + private function getCachedEntityLoader(ObjectManager $manager, object $queryBuilder, string $class, array $vary): EntityLoaderInterface { $hash = CachingFactoryDecorator::generateHash($vary); diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php b/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php index 6627630675b53..90d6ce8750887 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/EntityType.php @@ -50,7 +50,7 @@ public function configureOptions(OptionsResolver $resolver) * * @return ORMQueryBuilderLoader */ - public function getLoader(ObjectManager $manager, $queryBuilder, string $class) + public function getLoader(ObjectManager $manager, object $queryBuilder, string $class) { if (!$queryBuilder instanceof QueryBuilder) { throw new \TypeError(sprintf('Expected an instance of "%s", but got "%s".', QueryBuilder::class, get_debug_type($queryBuilder))); @@ -76,7 +76,7 @@ public function getBlockPrefix() * @internal This method is public to be usable as callback. It should not * be used in user code. */ - public function getQueryBuilderPartsForCachingHash($queryBuilder): ?array + public function getQueryBuilderPartsForCachingHash(object $queryBuilder): ?array { if (!$queryBuilder instanceof QueryBuilder) { throw new \TypeError(sprintf('Expected an instance of "%s", but got "%s".', QueryBuilder::class, get_debug_type($queryBuilder))); diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index f031eeb172340..1f7f6afe4cc0f 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -50,7 +50,7 @@ public function getProperties(string $class, array $context = []) if ($metadata instanceof ClassMetadataInfo && class_exists(\Doctrine\ORM\Mapping\Embedded::class) && $metadata->embeddedClasses) { $properties = array_filter($properties, function ($property) { - return false === strpos($property, '.'); + return !str_contains($property, '.'); }); $properties = array_merge($properties, array_keys($metadata->embeddedClasses)); diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php index ae4be69b259f2..a8825e75e915f 100644 --- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php @@ -200,6 +200,7 @@ public function updateExistingToken(PersistentTokenInterface $token, string $tok $this->conn->commit(); } catch (\Exception $e) { $this->conn->rollBack(); + throw $e; } } diff --git a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php index f965b8173f1ac..20264f4d954dd 100644 --- a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php @@ -133,10 +133,14 @@ public function supportsClass(string $class) * * @final */ - public function upgradePassword(UserInterface $user, string $newEncodedPassword): void + public function upgradePassword($user, string $newHashedPassword): void { if (!$user instanceof PasswordAuthenticatedUserInterface) { trigger_deprecation('symfony/doctrine-bridge', '5.3', 'The "%s::upgradePassword()" method expects an instance of "%s" as first argument, the "%s" class should implement it.', PasswordUpgraderInterface::class, PasswordAuthenticatedUserInterface::class, get_debug_type($user)); + + if (!$user instanceof UserInterface) { + throw new \TypeError(sprintf('The "%s()" method expects an instance of "%s" as first argument, "%s" given.', __METHOD__, PasswordAuthenticatedUserInterface::class, get_debug_type($user))); + } } $class = $this->getClass(); @@ -146,7 +150,7 @@ public function upgradePassword(UserInterface $user, string $newEncodedPassword) $repository = $this->getRepository(); if ($repository instanceof PasswordUpgraderInterface) { - $repository->upgradePassword($user, $newEncodedPassword); + $repository->upgradePassword($user, $newHashedPassword); } } @@ -165,7 +169,7 @@ private function getClass(): string if (null === $this->class) { $class = $this->classOrAlias; - if (false !== strpos($class, ':')) { + if (str_contains($class, ':')) { $class = $this->getClassMetadata()->getName(); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php index 76b6f4bdfd77e..63cba7387c4a1 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php @@ -31,17 +31,17 @@ class DoctrineChoiceLoaderTest extends TestCase use ExpectDeprecationTrait; /** - * @var ChoiceListFactoryInterface|MockObject + * @var MockObject&ChoiceListFactoryInterface */ private $factory; /** - * @var ObjectManager|MockObject + * @var MockObject&ObjectManager */ private $om; /** - * @var ObjectRepository|MockObject + * @var MockObject&ObjectRepository */ private $repository; @@ -51,12 +51,12 @@ class DoctrineChoiceLoaderTest extends TestCase private $class; /** - * @var IdReader|MockObject + * @var MockObject&IdReader */ private $idReader; /** - * @var EntityLoaderInterface|MockObject + * @var MockObject&EntityLoaderInterface */ private $objectLoader; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index 8833d0ac45e87..34962d9e7c916 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -59,7 +59,7 @@ class EntityTypeTest extends BaseTypeTest private $em; /** - * @var MockObject|ManagerRegistry + * @var MockObject&ManagerRegistry */ private $emRegistry; @@ -1312,7 +1312,10 @@ public function testLoaderCachingWithParameters() $this->assertSame($choiceList1, $choiceList3); } - protected function createRegistryMock($name, $em) + /** + * @return MockObject&ManagerRegistry + */ + protected function createRegistryMock($name, $em): ManagerRegistry { $registry = $this->createMock(ManagerRegistry::class); $registry->expects($this->any()) diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php index 5ddd60df8e857..a004935a6afdc 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -19,9 +19,6 @@ class ManagerRegistryTest extends TestCase { public static function setUpBeforeClass(): void { - if (!class_exists(\PHPUnit_Framework_TestCase::class)) { - self::markTestSkipped('proxy-manager-bridge is not yet compatible with namespaced phpunit versions.'); - } $test = new PhpDumperTest(); $test->testDumpContainerWithProxyServiceWillShareProxies(); } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index bed785cbd88c9..2cf9ca8c0d074 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -11,6 +11,8 @@ namespace Symfony\Bridge\Doctrine\Validator\Constraints; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\Persistence\ManagerRegistry; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -163,7 +165,7 @@ public function validate($entity, Constraint $constraint) return; } - $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0]; + $errorPath = $constraint->errorPath ?? $fields[0]; $invalidValue = $criteria[$errorPath] ?? $criteria[$fields[0]]; $this->context->buildViolation($constraint->message) @@ -175,7 +177,7 @@ public function validate($entity, Constraint $constraint) ->addViolation(); } - private function formatWithIdentifiers($em, $class, $value) + private function formatWithIdentifiers(EntityManagerInterface $em, ClassMetadata $class, $value) { if (!\is_object($value) || $value instanceof \DateTimeInterface) { return $this->formatValue($value, self::PRETTY_DATE); diff --git a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php index ca9eb4fab168c..f0f9a95652399 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php +++ b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php @@ -104,7 +104,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool } if (null === $lengthConstraint) { - if (isset($mapping['originalClass']) && false === strpos($mapping['declaredField'], '.')) { + if (isset($mapping['originalClass']) && !str_contains($mapping['declaredField'], '.')) { $metadata->addPropertyConstraint($mapping['declaredField'], new Valid()); $loaded = true; } elseif (property_exists($className, $mapping['fieldName'])) { diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 75db8e99e7700..152ed0ea75da2 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -22,7 +22,7 @@ "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2" }, "require-dev": { diff --git a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php index f17f4af3e3c9a..03811ab1571c7 100644 --- a/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php +++ b/src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php @@ -97,7 +97,7 @@ protected function execute(InputInterface $input, OutputInterface $output) 'multiline' => OutputInterface::VERBOSITY_DEBUG <= $output->getVerbosity(), ])); - if (false === strpos($host = $input->getOption('host'), '://')) { + if (!str_contains($host = $input->getOption('host'), '://')) { $host = 'tcp://'.$host; } diff --git a/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php b/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php index d232d68cd9404..4b87c264e4d5a 100644 --- a/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php +++ b/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php @@ -163,7 +163,7 @@ private function replacePlaceHolder(array $record): array { $message = $record['message']; - if (false === strpos($message, '{')) { + if (!str_contains($message, '{')) { return $record; } diff --git a/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php b/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php index c31dba880295c..a59825f6ab1f4 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php @@ -129,6 +129,9 @@ private function sendToElasticsearch(array $records) $this->wait(false); } + /** + * @return array + */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); diff --git a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php index 056b4ab9a9bb8..53491e9df521d 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php @@ -61,7 +61,7 @@ public function __construct(string $host, $level = Logger::DEBUG, bool $bubble = { parent::__construct($level, $bubble); - if (false === strpos($host, '://')) { + if (!str_contains($host, '://')) { $host = 'tcp://'.$host; } diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php index 6ee30da38a993..424f9ce10d597 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/ConsoleCommandProcessorTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; class ConsoleCommandProcessorTest extends TestCase { @@ -66,10 +67,7 @@ private function getConsoleEvent(): ConsoleEvent $input->method('getOptions')->willReturn(self::TEST_OPTIONS); $command = $this->createMock(Command::class); $command->method('getName')->willReturn(self::TEST_NAME); - $consoleEvent = $this->createMock(ConsoleEvent::class); - $consoleEvent->method('getCommand')->willReturn($command); - $consoleEvent->method('getInput')->willReturn($input); - return $consoleEvent; + return new ConsoleEvent($command, $input, $this->createMock(OutputInterface::class)); } } diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index b7cc4f200af58..73ead5aa0aa1a 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -20,7 +20,8 @@ "monolog/monolog": "^1.25.1|^2", "symfony/service-contracts": "^1.1|^2", "symfony/http-kernel": "^5.3", - "symfony/deprecation-contracts": "^2.1" + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { "symfony/console": "^4.4|^5.0", diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index cfa2ddc124d4b..32461976f04b8 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PhpUnit; use PHPUnit\Framework\TestResult; +use PHPUnit\Util\Error\Handler; use PHPUnit\Util\ErrorHandler; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Configuration; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation; @@ -38,7 +39,7 @@ class DeprecationErrorHandler private $deprecationGroups = []; private static $isRegistered = false; - private static $isAtLeastPhpUnit83; + private static $errorHandler; public function __construct() { @@ -162,7 +163,7 @@ public function handleError($type, $msg, $file, $line, $context = []) if ('legacy' === $group) { $this->deprecationGroups[$group]->addNotice(); - } else if ($deprecation->originatesFromAnObject()) { + } elseif ($deprecation->originatesFromAnObject()) { $class = $deprecation->originatingClass(); $method = $deprecation->originatingMethod(); $this->deprecationGroups[$group]->addNoticeFromObject($msg, $class, $method); @@ -347,16 +348,23 @@ private function displayDeprecations($groups, $configuration, $isFailing) private static function getPhpUnitErrorHandler() { - if (!isset(self::$isAtLeastPhpUnit83)) { - self::$isAtLeastPhpUnit83 = class_exists(ErrorHandler::class) && method_exists(ErrorHandler::class, '__invoke'); + if (!$eh = self::$errorHandler) { + if (class_exists(Handler::class)) { + $eh = self::$errorHandler = Handler::class; + } elseif (method_exists(ErrorHandler::class, '__invoke')) { + $eh = self::$errorHandler = ErrorHandler::class; + } else { + return self::$errorHandler = 'PHPUnit\Util\ErrorHandler::handleError'; + } } - if (!self::$isAtLeastPhpUnit83) { - return 'PHPUnit\Util\ErrorHandler::handleError'; + + if ('PHPUnit\Util\ErrorHandler::handleError' === $eh) { + return $eh; } foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { if (isset($frame['object']) && $frame['object'] instanceof TestResult) { - return new ErrorHandler( + return new $eh( $frame['object']->getConvertDeprecationsToExceptions(), $frame['object']->getConvertErrorsToExceptions(), $frame['object']->getConvertNoticesToExceptions(), diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php index 6f9214832c6b5..f9bd78619d6b5 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php @@ -13,11 +13,14 @@ use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite; +use PHPUnit\Metadata\Api\Groups; use PHPUnit\Util\Test; use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor; use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; use Symfony\Component\ErrorHandler\DebugClassLoader; +class_exists(Groups::class); + /** * @internal */ @@ -201,12 +204,13 @@ public function isLegacy() } $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') || strpos($this->originClass, '\Legacy') - || \in_array('legacy', Test::getGroups($this->originClass, $method), true); + || \in_array('legacy', $groups($this->originClass, $method), true); } /** diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index 61aa8a2da2b8b..63d7562a1d5ad 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -147,14 +147,13 @@ putenv('SYMFONY_DEPRECATIONS_HELPER=disabled'); } -if (false === $COMPOSER = getenv('COMPOSER_BINARY')) { - $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') - || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar 2> NUL`) : `which composer.phar 2> /dev/null`))) - || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer 2> NUL`) : `which composer 2> /dev/null`))) - || file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`)).\DIRECTORY_SEPARATOR.'composer.phar') - ? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang - : 'composer'; -} +$COMPOSER = ($COMPOSER = getenv('COMPOSER_BINARY')) + || file_exists($COMPOSER = $oldPwd.'/composer.phar') + || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar 2> NUL`) : `which composer.phar 2> /dev/null`))) + || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer 2> NUL`) : `which composer 2> /dev/null`))) + || file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`)).\DIRECTORY_SEPARATOR.'composer.phar') + ? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang + : 'composer'; $prevCacheDir = getenv('COMPOSER_CACHE_DIR'); if ($prevCacheDir) { diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php index 141147a64c00b..d665070f02454 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php @@ -28,12 +28,12 @@ public function generate(\ReflectionClass $originalClass, ClassGenerator $classG parent::generate($originalClass, $classGenerator, $proxyOptions); foreach ($classGenerator->getMethods() as $method) { - if (0 === strpos($originalClass->getFilename(), __FILE__)) { + if (str_starts_with($originalClass->getFilename(), __FILE__)) { $method->setBody(str_replace(var_export($originalClass->name, true), '__CLASS__', $method->getBody())); } } - if (0 === strpos($originalClass->getFilename(), __FILE__)) { + if (str_starts_with($originalClass->getFilename(), __FILE__)) { $interfaces = $classGenerator->getImplementedInterfaces(); array_pop($interfaces); $classGenerator->setImplementedInterfaces(array_merge($interfaces, $originalClass->getInterfaceNames())); diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 145ac6880f828..91d93ba7cf421 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -19,7 +19,8 @@ "php": ">=7.2.5", "composer/package-versions-deprecated": "^1.8", "friendsofphp/proxy-manager-lts": "^1.0.2", - "symfony/dependency-injection": "^5.0" + "symfony/dependency-injection": "^5.0", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { "symfony/config": "^4.4|^5.0" diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 5a79e42cc0d51..887f81b1f4211 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -212,7 +212,7 @@ private function displayGeneralText(SymfonyStyle $io, string $filter = null) foreach ($types as $index => $type) { $items = []; foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { - if (!$filter || false !== strpos($name, $filter)) { + if (!$filter || str_contains($name, $filter)) { $items[$name] = $name.$this->getPrettyMetadata($type, $entity, $decorated); } } @@ -246,7 +246,7 @@ private function displayGeneralJson(SymfonyStyle $io, ?string $filter) $data = []; foreach ($types as $type) { foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { - if (!$filter || false !== strpos($name, $filter)) { + if (!$filter || str_contains($name, $filter)) { $data[$type][$name] = $this->getMetadata($type, $entity); } } @@ -396,7 +396,7 @@ private function findWrongBundleOverrides(): array $folders = glob($this->twigDefaultPath.'/bundles/*', \GLOB_ONLYDIR); $relativePath = ltrim(substr($this->twigDefaultPath.'/bundles/', \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); $bundleNames = array_reduce($folders, function ($carry, $absolutePath) use ($relativePath) { - if (0 === strpos($absolutePath, $this->projectDir)) { + if (str_starts_with($absolutePath, $this->projectDir)) { $name = basename($absolutePath); $path = ltrim($relativePath.$name, \DIRECTORY_SEPARATOR); $carry[$name] = $path; @@ -526,7 +526,7 @@ private function findAlternatives(string $name, array $collection): array $alternatives = []; foreach ($collection as $item) { $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } @@ -540,7 +540,7 @@ private function findAlternatives(string $name, array $collection): array private function getRelativePath(string $path): string { - if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) { + if (null !== $this->projectDir && str_starts_with($path, $this->projectDir)) { return ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); } diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 5ecc09060b4cd..5282557ee2799 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -65,7 +65,7 @@ public function abbrClass(string $class): string public function abbrMethod(string $method): string { - if (false !== strpos($method, '::')) { + if (str_contains($method, '::')) { [$class, $method] = explode('::', $method, 2); $result = sprintf('%s::%s()', $this->abbrClass($class), $method); } elseif ('Closure' === $method) { @@ -190,7 +190,7 @@ public function getFileRelative(string $file): ?string { $file = str_replace('\\', '/', $file); - if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) { + if (null !== $this->projectDir && str_starts_with($file, $this->projectDir)) { return ltrim(substr($file, \strlen($this->projectDir)), '/'); } @@ -209,7 +209,7 @@ public function formatFileFromText(string $text): string */ public function formatLogMessage(string $message, array $context): string { - if ($context && false !== strpos($message, '{')) { + if ($context && str_contains($message, '{')) { $replacements = []; foreach ($context as $key => $val) { if (is_scalar($val)) { diff --git a/src/Symfony/Bridge/Twig/Node/DumpNode.php b/src/Symfony/Bridge/Twig/Node/DumpNode.php index 16718e8a75986..68c00556f86bf 100644 --- a/src/Symfony/Bridge/Twig/Node/DumpNode.php +++ b/src/Symfony/Bridge/Twig/Node/DumpNode.php @@ -21,7 +21,7 @@ final class DumpNode extends Node { private $varPrefix; - public function __construct($varPrefix, ?Node $values, int $lineno, string $tag = null) + public function __construct(string $varPrefix, ?Node $values, int $lineno, string $tag = null) { $nodes = []; if (null !== $values) { 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 bd2de97cf27b7..fb440282861d8 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 @@ -125,7 +125,7 @@ {% if app is defined and app.request is defined %}{%- set input_lang = app.request.locale -%}{%- endif -%} {%- set attr = {lang: input_lang} | merge(attr) -%} {{- block('form_widget_simple') -}} - {%- set label_attr = label_attr|merge({ class: (label_attr.class|default('') ~ ' custom-file-label')|trim }) -%} + {%- set label_attr = label_attr|merge({ class: (label_attr.class|default('') ~ ' custom-file-label')|trim })|filter((value, key) => key != 'id') -%}