diff --git a/.appveyor.yml b/.appveyor.yml
index c125ea3afb205..889aafe26929b 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -12,7 +12,6 @@ init:
- SET SYMFONY_DEPRECATIONS_HELPER=strict
- SET ANSICON=121x90 (121x90)
- SET SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE=1
- - SET SYMFONY_DEPRECATIONS_HELPER=max[direct]=1
- REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f
install:
@@ -20,8 +19,10 @@ install:
- appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip
- 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul
- cd ext
- - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.8-7.1-ts-vc14-x86.zip
- - 7z x php_apcu-5.1.8-7.1-ts-vc14-x86.zip -y >nul
+ - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.18-7.1-ts-vc14-x86.zip
+ - 7z x php_apcu-5.1.18-7.1-ts-vc14-x86.zip -y >nul
+ - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-5.1.1-7.1-ts-vc14-x86.zip
+ - 7z x php_redis-5.1.1-7.1-ts-vc14-x86.zip -y >nul
- cd ..
- copy /Y php.ini-development php.ini-min
- echo memory_limit=-1 >> php.ini-min
@@ -37,6 +38,7 @@ install:
- echo opcache.enable_cli=1 >> php.ini-max
- echo extension=php_openssl.dll >> php.ini-max
- echo extension=php_apcu.dll >> php.ini-max
+ - echo extension=php_redis.dll >> php.ini-max
- echo apc.enable_cli=1 >> php.ini-max
- echo extension=php_intl.dll >> php.ini-max
- echo extension=php_mbstring.dll >> php.ini-max
@@ -55,13 +57,14 @@ install:
- SET COMPOSER_ROOT_VERSION=%SYMFONY_VERSION%.x-dev
- php composer.phar update --no-progress --ansi
- php phpunit install
+ - choco install memurai-developer
test_script:
- SET X=0
- SET SYMFONY_PHPUNIT_SKIPPED_TESTS=phpunit.skipped
- copy /Y c:\php\php.ini-min c:\php\php.ini
- IF %APPVEYOR_REPO_BRANCH:~-2% neq .x (rm -Rf src\Symfony\Bridge\PhpUnit)
- - php phpunit src\Symfony --exclude-group tty,benchmark,intl-data || SET X=!errorlevel!
+ - php phpunit src\Symfony --exclude-group tty,benchmark,intl-data,network,transient-on-windows || SET X=!errorlevel!
- copy /Y c:\php\php.ini-max c:\php\php.ini
- - php phpunit src\Symfony --exclude-group tty,benchmark,intl-data || SET X=!errorlevel!
+ - php phpunit src\Symfony --exclude-group tty,benchmark,intl-data,network,transient-on-windows || SET X=!errorlevel!
- exit %X%
diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml
index 5518d4e4ad79d..ef0f72c794278 100644
--- a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml
@@ -1,5 +1,5 @@
name: 🐛 Bug Report
-description: ⚠️ See below for security reports
+description: ⚠️ NEVER report security issues, read https://symfony.com/security instead
labels: Bug
body:
@@ -14,7 +14,7 @@ body:
id: description
attributes:
label: Description
- description: A clear and consise description of the problem
+ description: A clear and concise description of the problem
validations:
required: true
- type: textarea
@@ -22,15 +22,21 @@ body:
attributes:
label: How to reproduce
description: |
- Code and/or config needed to reproduce the problem.
- If it's a complex bug, create a "bug reproducer" as explained in https://symfony.com/doc/current/contributing/code/reproducer.html
+ ⚠️ This is the most important part of the report ⚠️
+ Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix.
+ Please, take the time to show us some code and/or config that is needed for others to reproduce the problem easily.
+ Most of the time, creating a "bug reproducer" as explained in the URL below is the best way to help us
+ and increases the chances someone will have a look at it:
+ https://symfony.com/doc/current/contributing/code/reproducer.html
validations:
required: true
- type: textarea
id: possible-solution
attributes:
label: Possible Solution
- description: "Optional: only if you have suggestions on a fix/reason for the bug"
+ description: |
+ Optional: only if you have suggestions on a fix/reason for the bug
+ Don't hesitate to create a pull request with your solution, it helps get faster feedback.
- type: textarea
id: additional-context
attributes:
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000000..34227566ed84a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Support Question
+ url: https://symfony.com/support
+ about: We use GitHub issues only to discuss about Symfony bugs and new features. For this kind of questions about using Symfony or third-party bundles, please use any of the support alternatives shown in https://symfony.com/support
+ - name: Documentation Issue
+ url: https://github.com/symfony/symfony-docs/issues
+ about: Symfony Documentation has its own dedicated repository.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 62662f876fd3a..5e7092d385910 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,6 +1,6 @@
| Q | A
| ------------- | ---
-| Branch? | 5.4 for features / 4.4 or 5.3 for bug fixes
+| Branch? | 6.1 for features / 4.4, 5.3, 5.4 or 6.0 for bug fixes
| Bug fix? | yes/no
| New feature? | yes/no
| Deprecations? | yes/no
@@ -8,14 +8,14 @@
| License | MIT
| Doc PR | symfony/symfony-docs#...
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 09acdcd9dbbae..72002fa8998ef 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -99,16 +99,11 @@ jobs:
- name: Run tests
run: ./phpunit --group integration -v
env:
- SYMFONY_DEPRECATIONS_HELPER: max[direct]=1 # to be removed once DbalLogger is compatible with dbal 3.2+
- REDIS_HOST: localhost
REDIS_CLUSTER_HOSTS: 'localhost:7000 localhost:7001 localhost:7002 localhost:7003 localhost:7004 localhost:7005'
REDIS_SENTINEL_HOSTS: 'localhost:26379'
REDIS_SENTINEL_SERVICE: redis_sentinel
MESSENGER_REDIS_DSN: redis://127.0.0.1:7006/messages
MESSENGER_AMQP_DSN: amqp://localhost/%2f/messages
- MEMCACHED_HOST: localhost
- LDAP_HOST: localhost
- LDAP_PORT: 3389
#- name: Run HTTP push tests
# if: matrix.php == '8.0'
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index edd59d3f188f6..712657bd3d3c7 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -12,7 +12,6 @@ jobs:
tests:
name: Tests
- runs-on: Ubuntu-20.04
env:
extensions: amqp,apcu,igbinary,intl,mbstring,memcached,redis-5.3.4
@@ -21,15 +20,17 @@ jobs:
matrix:
include:
- php: '7.2'
- - php: '8.1'
- php: '7.4'
- mode: high-deps
- php: '8.0'
+ mode: high-deps
+ - php: '8.1'
mode: low-deps
- php: '8.2'
mode: experimental
fail-fast: false
+ runs-on: ubuntu-20.04
+
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -61,12 +62,11 @@ jobs:
([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json"
echo COLUMNS=120 >> $GITHUB_ENV
- echo PHPUNIT="$(readlink -f ./phpunit) --exclude-group tty,benchmark,intl-data" >> $GITHUB_ENV
+ echo PHPUNIT="$(pwd)/phpunit --exclude-group tty,benchmark,intl-data" >> $GITHUB_ENV
echo COMPOSER_UP='composer update --no-progress --ansi' >> $GITHUB_ENV
- echo SYMFONY_DEPRECATIONS_HELPER=max[direct]=1 >> $GITHUB_ENV # to be removed once DbalLogger is compatible with dbal 3.2+
SYMFONY_VERSIONS=$(git ls-remote -q --heads | cut -f2 | grep -o '/[1-9][0-9]*\.[0-9].*' | sort -V)
- SYMFONY_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | grep -P -o '[0-9]+\.[0-9]+')
+ SYMFONY_VERSION=$(grep ' VERSION = ' src/Symfony/Component/HttpKernel/Kernel.php | cut -d "'" -f2 | cut -d '.' -f 1-2)
SYMFONY_FEATURE_BRANCH=$(curl -s https://raw.githubusercontent.com/symfony/recipes/flex/main/index.json | jq -r '.versions."dev-name"')
# Install the phpunit-bridge from a PR if required
@@ -112,9 +112,9 @@ jobs:
# Skip the phpunit-bridge on bugfix-branches when not in *-deps mode
if [[ ! "${{ matrix.mode }}" = *-deps && $SYMFONY_VERSION != $SYMFONY_FEATURE_BRANCH ]]; then
- echo COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -not -wholename '*/Bridge/PhpUnit/*' -printf '%h ') >> $GITHUB_ENV
+ echo COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -not -wholename '*/Bridge/PhpUnit/*' | xargs -I{} dirname {}) >> $GITHUB_ENV
else
- echo COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h ') >> $GITHUB_ENV
+ echo COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist | xargs -I{} dirname {}) >> $GITHUB_ENV
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
@@ -173,14 +173,14 @@ jobs:
exit 0
fi
- (cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb)
-
if [[ "${{ matrix.mode }}" = low-deps ]]; then
echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT'"
exit 0
fi
+ (cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb)
+
# matrix.mode = high-deps
echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP && $PHPUNIT$LEGACY'" || X=1
diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
index fdb481fd190a8..3e8de34c124cb 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,
+ 'native_constant_invocation' => ['strict' => false],
'nullable_type_declaration_for_default_null_value' => ['use_nullable_type_declaration' => false],
])
->setRiskyAllowed(true)
diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md
index 10a473cffdec6..e3c35bfafa5ad 100644
--- a/CHANGELOG-4.4.md
+++ b/CHANGELOG-4.4.md
@@ -7,6 +7,42 @@ in 4.4 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/v4.4.0...v4.4.1
+* 4.4.36 (2021-12-29)
+
+ * bug #44838 [DependencyInjection][HttpKernel] Fix enum typed bindings (ogizanagi)
+ * bug #44826 [HttpKernel] Do not attempt to register enum arguments in controller service locator (ogizanagi)
+ * bug #44820 [Cache] Don't lock when doing nested computations (nicolas-grekas)
+ * bug #44807 [Messenger] fix Redis support on 32b arch (nicolas-grekas)
+ * bug #44759 [HttpFoundation] Fix notice when HTTP_PHP_AUTH_USER passed without pass (Vitali Tsyrkin)
+ * bug #44799 [Cache] fix compat with apcu < 5.1.10 (nicolas-grekas)
+ * bug #44732 [Mime] Relaxing in-reply-to header validation (ThomasLandauer)
+ * bug #44728 [Mime] Fix encoding filenames in multipart/form-data (nicolas-grekas)
+ * bug #44710 [DependencyInjection] fix linting callable classes (nicolas-grekas)
+ * bug #44639 [DependencyInjection] Cast tag attribute value to string (ruudk)
+ * bug #44473 [Validator] Restore default locale in ConstraintValidatorTestCase (rodnaph)
+ * bug #44577 [Cache] Fix proxy no expiration to the Redis (Sergey Belyshkin)
+ * bug #44669 [Cache] disable lock on CLI (nicolas-grekas)
+ * bug #44537 [Config] In XmlUtils, avoid converting from octal every string starting with a 0 (alexandre-daubois)
+ * bug #44625 [HttpClient] fix monitoring responses issued before reset() (nicolas-grekas)
+ * bug #44623 [HttpClient] Fix dealing with "HTTP/1.1 000 " responses (nicolas-grekas)
+ * bug #44601 [HttpClient] Fix closing curl-multi handle too early on destruct (nicolas-grekas)
+ * bug #44571 [HttpClient] Don't reset timeout counter when initializing requests (nicolas-grekas)
+ * bug #44479 [HttpClient] Double check if handle is complete (Nyholm)
+ * bug #44418 [DependencyInjection] Resolve ChildDefinition in AbstractRecursivePass (fancyweb)
+ * bug #43164 [FrameworkBundle] Fix cache pool configuration with one adapter and one provider (fancyweb)
+ * bug #44538 [Process] fixed uppercase ARGC and ARGV should also be skipped (rbaarsma)
+ * bug #44438 [HttpClient] Fix handling thrown \Exception in \Generator in MockResponse (fancyweb)
+ * bug #44502 [HttpFoundation] do not call preg_match() on null (xabbuh)
+ * bug #44467 [Console] Fix parameter types for `ProcessHelper::mustRun()` (derrabus)
+ * bug #44399 Prevent infinite nesting of lazy `ObjectManager` instances when `ObjectManager` is reset (Ocramius)
+ * bug #44375 [DoctrineBridge] fix calling get_class on non-object (kbond)
+ * bug #44361 [HttpClient] Fix handling error info in MockResponse (fancyweb)
+ * bug #43876 [Validator] Fix validation for single level domains (HypeMC)
+ * bug #44327 [Debug][ErrorHandler] Increased the reserved memory from 10k to 32k (sakalys)
+ * bug #44261 [Process] intersect with getenv() in case-insensitive manner to get default envs (stable-staple)
+ * bug #44295 [Serializer] fix support for lazy/unset properties (nicolas-grekas)
+ * bug #44269 [DoctrineBridge] Revert " add support for the JSON type" (dunglas)
+
* 4.4.35 (2021-11-24)
* security #cve-2021-41270 [Serializer] Use single quote to escape formulas (jderusse)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index b5e87ad1280f4..48ae19030db84 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -12,15 +12,15 @@ The Symfony Connect username in parenthesis allows to get more information
- Tobias Schultze (tobion)
- Robin Chalas (chalas_r)
- Christophe Coevoet (stof)
- - Jérémy DERUSSÉ (jderusse)
- Wouter De Jong (wouterj)
+ - Jérémy DERUSSÉ (jderusse)
- Grégoire Pineau (lyrixx)
- Maxime Steinhausser (ogizanagi)
- Kévin Dunglas (dunglas)
- Jordi Boggiano (seldaek)
+ - Thomas Calvet (fancyweb)
- Victor Berchet (victor)
- Javier Eguiluz (javier.eguiluz)
- - Thomas Calvet (fancyweb)
- Ryan Weaver (weaverryan)
- Roland Franssen (ro0)
- Jakub Zalas (jakubzalas)
@@ -54,19 +54,19 @@ The Symfony Connect username in parenthesis allows to get more information
- Valentin Udaltsov (vudaltsov)
- Iltar van der Berg (kjarli)
- Jonathan Wage (jwage)
+ - Jérôme Tamarelle (gromnan)
- Matthias Pigulla (mpdude)
- Diego Saint Esteben (dosten)
- Grégoire Paris (greg0ire)
- Alexandre Salomé (alexandresalome)
- - Jérôme Tamarelle (gromnan)
- William Durand (couac)
- ornicar
+ - Titouan Galopin (tgalopin)
- Konstantin Myakshin (koc)
- Dany Maillard (maidmaid)
- Francis Besset (francisbesset)
- stealth35 (stealth35)
- Alexander Mols (asm89)
- - Titouan Galopin (tgalopin)
- Laurent VOULLEMIER (lvo)
- Vasilij Dusko | CREATION
- Bulat Shakirzyanov (avalanche123)
@@ -79,10 +79,10 @@ The Symfony Connect username in parenthesis allows to get more information
- Miha Vrhovnik
- Diego Saint Esteben (dii3g0)
- Mathieu Piot (mpiot)
+ - Antoine M (amakdessi)
- Konstantin Kudryashov (everzet)
- Vladimir Reznichenko (kalessil)
- Bilal Amarni (bamarni)
- - Antoine M (amakdessi)
- Florin Patan (florinpatan)
- Jáchym Toušek (enumag)
- Alex Pott
@@ -107,24 +107,24 @@ The Symfony Connect username in parenthesis allows to get more information
- Lee McDermott
- Brandon Turner
- Luis Cordova (cordoval)
+ - Mathieu Santostefano (welcomattic)
- Daniel Holmes (dholmes)
- Sebastiaan Stok (sstok)
+ - HypeMC (hypemc)
- Toni Uebernickel (havvg)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
- - Mathieu Santostefano (welcomattic)
- John Wards (johnwards)
- Tomas Norkūnas (norkunas)
+ - Alexandre Daubois (alexandre-daubois)
- Baptiste Clavié (talus)
- - HypeMC (hypemc)
- Antoine Hérault (herzult)
- Paráda József (paradajozsef)
- - Alexandre Daubois (alexandre-daubois)
- Vincent Langlet (deviling)
+ - Julien Falque (julienfalque)
- Massimiliano Arione (garak)
- Arnaud Le Blanc (arnaud-lb)
- Przemysław Bogusz (przemyslaw-bogusz)
- - Julien Falque (julienfalque)
- Maxime STEINHAUSSER
- Michal Piotrowski (eventhorizon)
- Tomáš Votruba (tomas_votruba)
@@ -143,6 +143,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Włodzimierz Gajda (gajdaw)
- Christian Scheb
- Adrien Brault (adrienbrault)
+ - Maxime Helias (maxhelias)
- Yanick Witschi (toflar)
- Jacob Dreesen (jdreesen)
- Malte Schlüter (maltemaltesich)
@@ -152,6 +153,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Teoh Han Hui (teohhanhui)
- Colin Frei
- Javier Spagnoletti (phansys)
+ - Ruud Kamphuis (ruudk)
- Joshua Thijssen
- Daniel Wehner (dawehner)
- Tugdual Saunier (tucksaun)
@@ -159,15 +161,13 @@ The Symfony Connect username in parenthesis allows to get more information
- Gordon Franke (gimler)
- Saif Eddin Gmati (azjezz)
- Richard van Laak (rvanlaak)
- - Maxime Helias (maxhelias)
+ - Gary PEGEOT (gary-p)
- Jesse Rushlow (geeshoe)
- Fabien Pennequin (fabienpennequin)
- Olivier Dolbeau (odolbeau)
- Smaine Milianni (ismail1432)
- Eric GELOEN (gelo)
- - Gary PEGEOT (gary-p)
- Matthieu Napoli (mnapoli)
- - Ruud Kamphuis (ruudk)
- Ion Bazan (ionbazan)
- Jannik Zschiesche (apfelbox)
- Robert Schönthal (digitalkaoz)
@@ -190,6 +190,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Albert Casademont (acasademont)
- Arnaud Kleinpeter (nanocom)
- Guilherme Blanco (guilhermeblanco)
+ - Marco Pivetta (ocramius)
- SpacePossum
- Alexander Menshchikov (zmey_kk)
- Pablo Godel (pgodel)
@@ -203,20 +204,23 @@ The Symfony Connect username in parenthesis allows to get more information
- jwdeitch
- Jeroen Spee (jeroens)
- Jérôme Parmentier (lctrs)
- - Marco Pivetta (ocramius)
- Fabien Bourigault (fbourigault)
- Joe Bennett (kralos)
- Mikael Pajunen
- Andreas Schempp (aschempp)
- Alessandro Lai (jean85)
- Romaric Drigon (romaricdrigon)
+ - Christopher Hertel (chertel)
- Arman Hosseini (arman)
+ - Rokas Mikalkėnas (rokasm)
- Niels Keurentjes (curry684)
- Vyacheslav Pavlov
+ - Andreas Möller (localheinz)
- Richard Shank (iampersistent)
- Wouter J
- Thomas Rabaix (rande)
- Chi-teck
+ - Baptiste Leduc (korbeil)
- Timo Bakx (timobakx)
- Vincent Touzet (vincenttouzet)
- Nate Wiebe (natewiebe13)
@@ -225,16 +229,13 @@ The Symfony Connect username in parenthesis allows to get more information
- Ben Davies (bendavies)
- Clemens Tolboom
- Helmer Aaviksoo
- - Christopher Hertel (chertel)
- Remon van de Kamp (rpkamp)
- - Rokas Mikalkėnas (rokasm)
- Filippo Tessarotto (slamdunk)
- Hiromi Hishida (77web)
- Michael Käfer (michael_kaefer)
- Matthieu Ouellette-Vachon (maoueh)
- Michał Pipa (michal.pipa)
- Dawid Nowak
- - Andreas Möller (localheinz)
- Roman Martinuk (a2a4)
- Amal Raghav (kertz)
- Jonathan Ingram (jonathaningram)
@@ -244,7 +245,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Samuel NELA (snela)
- David Prévot
- Hugo Monteiro (monteiro)
- - Baptiste Leduc (korbeil)
- Dmitrii Poddubnyi (karser)
- zairig imad (zairigimad)
- Tien Vo (tienvx)
@@ -275,6 +275,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Thibaut Cheymol (tcheymol)
- Sebastien Morel (plopix)
- mcfedr (mcfedr)
+ - Colin O'Dell (colinodell)
- Ruben Gonzalez (rubenrua)
- Benjamin Dulau (dbenjamin)
- Baptiste Lafontaine (magnetik)
@@ -311,7 +312,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Matthieu Auger (matthieuauger)
- Leszek Prabucki (l3l0)
- Nicolas Philippe (nikophil)
- - Colin O'Dell (colinodell)
- Emanuele Panzeri (thepanz)
- François Zaninotto (fzaninotto)
- Dustin Whittle (dustinwhittle)
@@ -325,6 +325,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Sven Paulus (subsven)
- Daniel STANCU
- Maxime Veber (nek-)
+ - Sylvain Fabre (sylfabre)
- Loick Piera (pyrech)
- Clara van Miert
- Valentine Boineau (valentineboineau)
@@ -340,6 +341,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Victor Bocharsky (bocharsky_bw)
- Bozhidar Hristov (warxcell)
- Marcel Beerta (mazen)
+ - Thomas Landauer (thomas-landauer)
- Pavel Batanov (scaytrase)
- Mantis Development
- Loïc Faugeron
@@ -373,10 +375,11 @@ The Symfony Connect username in parenthesis allows to get more information
- Roman Marintšenko (inori)
- Xavier Montaña Carreras (xmontana)
- Mickaël Andrieu (mickaelandrieu)
+ - Soner Sayakci
- Xavier Perez
- Arjen Brouwer (arjenjb)
- Katsuhiro OGAWA
- - Sylvain Fabre (sylfabre)
+ - Artem Lopata
- Patrick McDougle (patrick-mcdougle)
- Marc Weistroff (futurecat)
- Alif Rachmawadi
@@ -402,7 +405,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Jhonny Lidfors (jhonne)
- Diego Agulló (aeoris)
- jdhoek
- - Thomas Landauer (thomas-landauer)
- Jurica Vlahoviček (vjurica)
- Bob den Otter (bopp)
- Thomas Schulz (king2500)
@@ -436,7 +438,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Wouter Van Hecke
- Iker Ibarguren (ikerib)
- Bob van de Vijver (bobvandevijver)
- - Soner Sayakci
- Peter Kruithof (pkruithof)
- Michael Holm (hollo)
- Arjen van der Meijden
@@ -459,6 +460,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Manuel Kiessling (manuelkiessling)
- Dimitri Gritsajuk (ottaviano)
- Alexey Kopytko (sanmai)
+ - Gijs van Lammeren
- Pol Dellaiera (drupol)
- Atsuhiro KUBO (iteman)
- Alireza Mirsepassi (alirezamirsepassi)
@@ -535,7 +537,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Christian Gärtner (dagardner)
- Dmytro Borysovskyi (dmytr0)
- Tomasz Kowalczyk (thunderer)
- - Artem Lopata
- Artur Eshenbrener
- Thomas Perez (scullwm)
- Yoann RENARD (yrenard)
@@ -553,6 +554,7 @@ The Symfony Connect username in parenthesis allows to get more information
- hossein zolfi (ocean)
- Clément Gautier (clementgautier)
- Koen Reiniers (koenre)
+ - Hugo Alliaume (kocal)
- Sanpi
- Eduardo Gulias (egulias)
- giulio de donato (liuggio)
@@ -560,10 +562,12 @@ The Symfony Connect username in parenthesis allows to get more information
- ShinDarth
- Stéphane PY (steph_py)
- Philipp Kräutli (pkraeutli)
+ - Rhodri Pugh (rodnaph)
- Grzegorz Zdanowski (kiler129)
- Kirill chEbba Chebunin (chebba)
-
- Fabien Villepinte
+ - SiD (plbsid)
- Matthew Grasmick
- Greg Thornton (xdissent)
- BENOIT POLASZEK (bpolaszek)
@@ -575,12 +579,12 @@ The Symfony Connect username in parenthesis allows to get more information
- Loïc Chardonnet (gnusat)
- Marek Kalnik (marekkalnik)
- Vyacheslav Salakhutdinov (megazoll)
+ - Antoine Lamirault
- Phil Taylor (prazgod)
- Hassan Amouhzi
- Tamas Szijarto
- Michele Locati
- Pavel Volokitin (pvolok)
- - Gijs van Lammeren
- Arthur de Moulins (4rthem)
- Matthias Althaus (althaus)
- Nicolas Dewez (nicolas_dewez)
@@ -650,6 +654,7 @@ The Symfony Connect username in parenthesis allows to get more information
- scyzoryck
- Matthias Krauser (mkrauser)
- Erkhembayar Gantulga (erheme318)
+ - Alexis Lefebvre
- Lorenzo Millucci (lmillucci)
- Jérôme Tamarelle (jtamarelle-prismamedia)
- Andrii Popov (andrii-popov)
@@ -677,6 +682,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Chris Sedlmayr (catchamonkey)
- Indra Gunawan (indragunawan)
- Mathias STRASSER (roukmoute)
+ - simon chrzanowski (simonch)
- Kamil Kokot (pamil)
- Seb Koelen
- Christoph Mewes (xrstf)
@@ -719,7 +725,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Marek Zajac
- Adam Harvey
- Anton Bakai
- - Rhodri Pugh (rodnaph)
- battye
- Sam Fleming (sam_fleming)
- William Arslett
@@ -749,7 +754,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Sebastian Bergmann
- Miroslav Sustek
- Pablo Díez (pablodip)
- - SiD (plbsid)
- Michel Roca (mroca)
- Kevin McBride
- Sergio Santoro
@@ -780,6 +784,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Markus Lanthaler (lanthaler)
- Remi Collet
- Vicent Soria Durá (vicentgodella)
+ - Daniel Gorgan
- Michael Moravec
- Carlos Buenosvinos (carlosbuenosvinos)
- Leevi Graham (leevigraham)
@@ -799,6 +804,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Scott Arciszewski
- Xavier HAUSHERR
- Norbert Orzechowicz (norzechowicz)
+ - stlrnz
- Denis Charrier (brucewouaigne)
- Matthijs van den Bos (matthijs)
- Simon Podlipsky (simpod)
@@ -912,8 +918,8 @@ The Symfony Connect username in parenthesis allows to get more information
- vitaliytv
- Nicolas Martin (cocorambo)
- Adrian Nguyen (vuphuong87)
+ - Khoo Yong Jun
- Sebastian Blum
- - Alexis Lefebvre
- Laurent Clouet
- aubx
- Julien Turby
@@ -930,6 +936,7 @@ The Symfony Connect username in parenthesis allows to get more information
- pizzaminded
- Stéphane Escandell (sescandell)
- Konstantin S. M. Möllers (ksmmoellers)
+ - Fractal Zombie
- linh
- James Johnston
- Sinan Eldem
@@ -978,6 +985,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Evgeny Anisiforov
- smoench
- Max Grigorian (maxakawizard)
+ - Martins Sipenko
- Guilherme Augusto Henschel
- Rostyslav Kinash
- Cristoforo Cervino (cristoforocervino)
@@ -1021,9 +1029,11 @@ The Symfony Connect username in parenthesis allows to get more information
- Tomas Javaisis
- Ivan Grigoriev
- Johann Saunier (prophet777)
+ - Kevin SCHNEKENBURGER
- Fabien Salles (blacked)
- Andreas Erhard
- John VanDeWeghe
+ - Sergey Belyshkin
- Michael Devery (mickadoo)
- Antoine Corcy
- Ahmed Ashraf (ahmedash95)
@@ -1085,6 +1095,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Roromix
- Maxime AILLOUD (mailloud)
- Richard van den Brand (ricbra)
+ - Toon Verwerft (veewee)
- mohammadreza honarkhah
- develop
- flip111
@@ -1191,6 +1202,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Julien Pauli
- Dominik Piekarski (dompie)
- Rares Sebastian Moldovan (raresmldvn)
+ - Jérémy REYNAUD (babeuloula)
- Mathieu Rochette (mathroc)
- Victor Garcia
- Jérôme Tanghe (deuchnord)
@@ -1239,7 +1251,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Tito Costa
- Jan Prieser
- GDIBass
- - Antoine Lamirault
+ - Maximilian Bösing
- Thiago Melo
- Adrien Lucas (adrienlucas)
- Zhuravlev Alexander (scif)
@@ -1300,7 +1312,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Loïc Beurlet
- Sébastien COURJEAN
- Ana Raro
- - Daniel Gorgan
- Ana Raro
- Tony Malzhacker
- Pchol
@@ -1380,13 +1391,14 @@ The Symfony Connect username in parenthesis allows to get more information
- Forfarle (forfarle)
- Harry Walter (haswalt)
- Johnson Page (jwpage)
+ - Kuba Werłos (kuba)
- Ruben Gonzalez (rubenruateltek)
- Michael Roterman (wtfzdotnet)
+ - Philipp Keck
- Arno Geurts
- Adán Lobato (adanlobato)
- Ian Jenkins (jenkoian)
- Kai Eichinger (kai_eichinger)
- - Hugo Alliaume (kocal)
- Marcos Gómez Vilches (markitosgv)
- Matthew Davis (mdavis1982)
- Paulo Ribeiro (paulo)
@@ -1396,7 +1408,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Antoine LA
- den
- Pavol Tuka
- - stlrnz
- pawel-lewtak
- omerida
- Gábor Tóth
@@ -1476,9 +1487,7 @@ The Symfony Connect username in parenthesis allows to get more information
- neghmurken
- xaav
- Mahmoud Mostafa (mahmoud)
- - Fractal Zombie
- Ahmed Abdou
- - Khoo Yong Jun
- shreyadenny
- Daniel Iwaniec
- Pieter
@@ -1509,6 +1518,7 @@ The Symfony Connect username in parenthesis allows to get more information
- LHommet Nicolas (nicolaslh)
- fabios
- Sander Coolen (scoolen)
+ - Emil Masiakowski
- Amirreza Shafaat (amirrezashafaat)
- Adoni Pavlakis (adoni)
- Nicolas Le Goff (nlegoff)
@@ -1628,6 +1638,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Jean-Guilhem Rouel (jean-gui)
- Yoann MOROCUTTI
- jfcixmedia
+ - Tomasz Kusy
- Dominic Tubach
- Nikita Konstantinov
- Martijn Evers
@@ -1635,6 +1646,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Philipp Fritsche
- tarlepp
- Benjamin Paap (benjaminpaap)
+ - Guillaume Aveline
- Christian
- Denis Golubovskiy (bukashk0zzz)
- Arkadiusz Rzadkowolski (flies)
@@ -1647,7 +1659,6 @@ The Symfony Connect username in parenthesis allows to get more information
- hugofonseca (fonsecas72)
- Marc Duboc (icemad)
- Martynas Narbutas
- - Toon Verwerft (veewee)
- Bailey Parker
- Eddie Jaoude
- Antanas Arvasevicius
@@ -1716,6 +1727,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Charles Sanquer (csanquer)
- Albert Ganiev (helios-ag)
- Neil Katin
+ - Oleg Mifle
- David Otton
- Will Donohoe
- gnito-org
@@ -1740,13 +1752,13 @@ 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)
- Juan Miguel Besada Vidal (soutlink)
- dlorek
- Stuart Fyfe
+ - Jason Schilling (chapterjason)
- David de Boer (ddeboer)
- Eno Mullaraj (emullaraj)
- Nathan PAGE (nathix)
@@ -1765,6 +1777,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Roger Webb
- Dmitriy Simushev
- Pawel Smolinski
+ - Simon Watiau (simonwatiau)
- Oxan van Leeuwen
- pkowalczyk
- Soner Sayakci
@@ -1815,6 +1828,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Dmitri Petmanson
- heccjj
- Alexandre Melard
+ - PierreRebeilleau
- Jay Klehr
- Sergey Yuferev
- Tobias Stöckler
@@ -1954,7 +1968,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Wojciech Błoszyk (wbloszyk)
- Giorgio Premi
- abunch
- - Sergey Belyshkin
- tamcy
- Mikko Pesari
- ncou
@@ -1982,6 +1995,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Raphaëll Roussel
- Tadcka
- Beth Binkovitz
+ - Maxim Semkin
- Gonzalo Míguez
- Fabian Haase
- Romain Geissler
@@ -2027,6 +2041,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Tony Vermeiren (tony)
- Bart Wach
- Jos Elstgeest
+ - Kirill Lazarev
- Thomas Counsell
- BilgeXA
- r1pp3rj4ck
@@ -2197,6 +2212,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Matt Farmer
- catch
- aetxebeste
+ - Vitali Tsyrkin
- Juga Paazmaya
- Alexandre Segura
- afaricamp
@@ -2249,6 +2265,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Andreas
- Markus
- agaktr
+ - Mostafa
- kernig
- Thomas Chmielowiec
- shdev
@@ -2276,6 +2293,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Christoph Nissle (derstoffel)
- Denys Voronin (hurricane)
- Ionel Scutelnicu (ionelscutelnicu)
+ - Juan Gonzalez Montes (juanwilde)
- Mathieu Dewet (mdewet)
- Nicolas Tallefourtané (nicolab)
- Botond Dani (picur)
@@ -2294,7 +2312,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Christopher Parotat
- Dennis Haarbrink
- me_shaon
- - Maximilian Bösing
- 蝦米
- Grayson Koonce (breerly)
- Andrey Helldar (helldar)
@@ -2373,6 +2390,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Cyril Pascal (paxal)
- Cédric Dugat (ph3nol)
- Philip Dahlstrøm (phidah)
+ - Pierre Rebeilleau (pierrereb)
- Milos Colakovic (project2481)
- Raphael de Almeida (raphaeldealmeida)
- Rénald Casagraude (rcasagraude)
@@ -2435,6 +2453,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Peter Breuls
- Chansig
- Tischoi
+ - divinity76
- Andreas Hasenack
- J Bruni
- Alexey Prilipko
@@ -2468,6 +2487,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Pedro Magalhães (pmmaga)
- Rares Vlaseanu (raresvla)
- Sergii Dolgushev (serhey)
+ - Rein Baarsma (solidwebcode)
- tante kinast (tante)
- Stephen Lewis (tehanomalousone)
- Ahmed Hannachi (tiecoders)
@@ -2525,6 +2545,7 @@ The Symfony Connect username in parenthesis allows to get more information
- grifx
- Robert Campbell
- Matt Lehner
+ - Olexandr Kalaidzhy
- Helmut Januschka
- Hein Zaw Htet™
- Ruben Kruiswijk
@@ -2585,6 +2606,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Gerrit Drost
- Linnaea Von Lavia
- Bastien Clément
+ - Julius Šakalys
- Javan Eskander
- Lenar Lõhmus
- Cristian Gonzalez
@@ -2596,7 +2618,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Pavinthan
- Sylvain METAYER
- ddebree
- - Kuba Werłos
- Gyula Szucs
- Tomas Liubinas
- Ivo Valchev
@@ -2664,7 +2685,6 @@ The Symfony Connect username in parenthesis allows to get more information
- Geordie
- Exploit.cz
- GuillaumeVerdon
- - Philipp Keck
- Angel Fernando Quiroz Campos
- Ondrej Mirtes
- akimsko
@@ -2726,6 +2746,7 @@ The Symfony Connect username in parenthesis allows to get more information
- arend
- Vincent Godé
- Dusan Kasan
+ - helmi
- Michael Steininger
- Nardberjean
- Karolis
@@ -2865,6 +2886,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Babichev Maxim
- Edvin Hultberg
- Benjamin Long
+ - Kévin Gonella
- Ben Miller
- Peter Gribanov
- Ash014
@@ -2896,6 +2918,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Steve Marvell
- Dawid Nowak
- Lesnykh Ilia
+ - Shyim
- sabruss
- darnel
- Karolis Daužickas
@@ -2943,6 +2966,7 @@ The Symfony Connect username in parenthesis allows to get more information
- Christian Gripp (core23)
- Christoph Schaefer (cvschaefer)
- Damon Jones (damon__jones)
+ - Alexandre Fiocre (demos77)
- Łukasz Giza (destroyer)
- Daniel Londero (dlondero)
- Sebastian Landwehr (dword123)
diff --git a/composer.json b/composer.json
index 5388530c16c85..c2933d54031f7 100644
--- a/composer.json
+++ b/composer.json
@@ -152,6 +152,12 @@
"ocramius/proxy-manager": "<2.1",
"phpunit/phpunit": "<5.4.3"
},
+ "config": {
+ "allow-plugins": {
+ "composer/package-versions-deprecated": true,
+ "symfony/runtime": true
+ }
+ },
"autoload": {
"psr-4": {
"Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/",
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index c4e152a05938f..0c4dd3ee87287 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -18,6 +18,7 @@
+
diff --git a/psalm.xml b/psalm.xml
index 015c0ed18b21b..3fb94145699cf 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -27,5 +27,13 @@
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php
index 2139562dedbaf..0ed055fec64b7 100644
--- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php
+++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php
@@ -62,7 +62,7 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) {
$name = $this->aliases[$name];
}
if (isset($this->fileMap[$name])) {
- $wrappedInstance = $this->load($this->fileMap[$name]);
+ $wrappedInstance = $this->load($this->fileMap[$name], false);
} else {
$method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service'; // BC with DI v3.4
$wrappedInstance = $this->{$method}(false);
diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php
index c6b219aa795ab..30f12129c2719 100644
--- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php
+++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php
@@ -40,7 +40,7 @@ private function pingConnection(EntityManagerInterface $entityManager)
try {
$connection->executeQuery($connection->getDatabasePlatform()->getDummySelectSQL());
- } catch (DBALException | Exception $e) {
+ } catch (DBALException|Exception $e) {
$connection->close();
$connection->connect();
}
diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php
index 072fa91affa2b..769beae70ba25 100644
--- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php
+++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php
@@ -189,7 +189,6 @@ public function getTypes($class, $property, array $context = [])
case self::$useDeprecatedConstants ? DBALType::TARRAY : Types::ARRAY:
// no break
case 'json_array':
- case 'json':
return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)];
case self::$useDeprecatedConstants ? DBALType::SIMPLE_ARRAY : Types::SIMPLE_ARRAY:
@@ -231,7 +230,7 @@ private function getMetadata(string $class): ?ClassMetadata
{
try {
return $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class);
- } catch (MappingException | OrmMappingException $exception) {
+ } catch (MappingException|OrmMappingException $exception) {
return null;
}
}
@@ -317,7 +316,6 @@ private function getPhpType(string $doctrineType): ?string
case self::$useDeprecatedConstants ? DBALType::SIMPLE_ARRAY : Types::SIMPLE_ARRAY:
// no break
case 'json_array':
- case 'json':
return Type::BUILTIN_TYPE_ARRAY;
}
diff --git a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php
index d79b7d4998134..710e87a15e0b8 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php
@@ -15,6 +15,9 @@
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Logger\DbalLogger;
+/**
+ * @group legacy
+ */
class DbalLoggerTest extends TestCase
{
/**
@@ -46,8 +49,8 @@ public function getLogFixtures()
['SQL', null, []],
['SQL', [], []],
['SQL', ['foo' => 'bar'], ['foo' => 'bar']],
- ['SQL', ['foo' => "\x7F\xFF"], ['foo' => DbalLogger::BINARY_DATA_VALUE]],
- ['SQL', ['foo' => "bar\x7F\xFF"], ['foo' => DbalLogger::BINARY_DATA_VALUE]],
+ ['SQL', ['foo' => "\x7F\xFF"], ['foo' => '(binary value)']],
+ ['SQL', ['foo' => "bar\x7F\xFF"], ['foo' => '(binary value)']],
['SQL', ['foo' => ''], ['foo' => '']],
];
}
diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php
index a004935a6afdc..dd7dabcc87db1 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php
@@ -12,8 +12,15 @@
namespace Symfony\Bridge\Doctrine\Tests;
use PHPUnit\Framework\TestCase;
+use ProxyManager\Proxy\LazyLoadingInterface;
+use ProxyManager\Proxy\ValueHolderInterface;
use Symfony\Bridge\Doctrine\ManagerRegistry;
+use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Bridge\ProxyManager\Tests\LazyProxy\Dumper\PhpDumperTest;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
+use Symfony\Component\Filesystem\Filesystem;
class ManagerRegistryTest extends TestCase
{
@@ -39,6 +46,91 @@ public function testResetService()
$this->assertSame($foo, $container->get('foo'));
$this->assertObjectNotHasAttribute('bar', $foo);
}
+
+ /**
+ * When performing an entity manager lazy service reset, the reset operations may re-use 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
+ * the reset operation keeps increasing this nesting until the application eventually runs into stack
+ * overflow or memory overflow operations, which can happen for long-running processes that rely on
+ * services that are reset very often.
+ */
+ public function testResetServiceWillNotNestFurtherLazyServicesWithinEachOther()
+ {
+ // This test scenario only applies to containers composed as a set of generated sources
+ $this->dumpLazyServiceProjectAsFilesServiceContainer();
+
+ /** @var ContainerInterface $container */
+ $container = new \LazyServiceProjectAsFilesServiceContainer();
+
+ $registry = new TestManagerRegistry(
+ 'irrelevant',
+ [],
+ ['defaultManager' => 'foo'],
+ 'irrelevant',
+ 'defaultManager',
+ 'irrelevant'
+ );
+ $registry->setTestContainer($container);
+
+ $service = $container->get('foo');
+
+ self::assertInstanceOf(\stdClass::class, $service);
+ self::assertInstanceOf(LazyLoadingInterface::class, $service);
+ self::assertInstanceOf(ValueHolderInterface::class, $service);
+ self::assertFalse($service->isProxyInitialized());
+
+ $service->initializeProxy();
+
+ self::assertTrue($container->initialized('foo'));
+ self::assertTrue($service->isProxyInitialized());
+
+ $registry->resetManager();
+ $service->initializeProxy();
+
+ $wrappedValue = $service->getWrappedValueHolderValue();
+ self::assertInstanceOf(\stdClass::class, $wrappedValue);
+ self::assertNotInstanceOf(LazyLoadingInterface::class, $wrappedValue);
+ self::assertNotInstanceOf(ValueHolderInterface::class, $wrappedValue);
+ }
+
+ private function dumpLazyServiceProjectAsFilesServiceContainer()
+ {
+ if (class_exists(\LazyServiceProjectAsFilesServiceContainer::class, false)) {
+ return;
+ }
+
+ $container = new ContainerBuilder();
+
+ $container->register('foo', \stdClass::class)
+ ->setPublic(true)
+ ->setLazy(true);
+ $container->compile();
+
+ $fileSystem = new Filesystem();
+
+ $temporaryPath = $fileSystem->tempnam(sys_get_temp_dir(), 'symfonyManagerRegistryTest');
+ $fileSystem->remove($temporaryPath);
+ $fileSystem->mkdir($temporaryPath);
+
+ $dumper = new PhpDumper($container);
+
+ $dumper->setProxyDumper(new ProxyDumper());
+ $containerFiles = $dumper->dump([
+ 'class' => 'LazyServiceProjectAsFilesServiceContainer',
+ 'as_files' => true,
+ ]);
+
+ array_walk(
+ $containerFiles,
+ static function (string $containerSources, string $fileName) use ($temporaryPath): void {
+ (new Filesystem())->dumpFile($temporaryPath.'/'.$fileName, $containerSources);
+ }
+ );
+
+ require $temporaryPath.'/LazyServiceProjectAsFilesServiceContainer.php';
+ }
}
class TestManagerRegistry extends ManagerRegistry
diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php
index 71eaf31ca7f80..7e256eb77e2d8 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php
@@ -254,11 +254,11 @@ public function typesProvider()
new Type(Type::BUILTIN_TYPE_INT),
new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class)
)]],
- ['json', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
+ ['json', null],
];
if (class_exists(Types::class)) {
- $provider[] = ['json', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]];
+ $provider[] = ['json', null];
}
return $provider;
diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php
index c0945114c9c23..bc0041c20b64c 100644
--- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php
+++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php
@@ -37,6 +37,7 @@
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
/**
@@ -821,6 +822,32 @@ public function testValidateUniquenessWithEmptyIterator($entity, $result)
$this->assertNoViolation();
}
+ public function testValueMustBeObject()
+ {
+ $constraint = new UniqueEntity([
+ 'message' => 'myMessage',
+ 'fields' => ['name'],
+ 'em' => self::EM_NAME,
+ ]);
+
+ $this->expectException(UnexpectedValueException::class);
+
+ $this->validator->validate('foo', $constraint);
+ }
+
+ public function testValueCanBeNull()
+ {
+ $constraint = new UniqueEntity([
+ 'message' => 'myMessage',
+ 'fields' => ['name'],
+ 'em' => self::EM_NAME,
+ ]);
+
+ $this->validator->validate(null, $constraint);
+
+ $this->assertNoViolation();
+ }
+
public function resultWithEmptyIterator(): array
{
$entity = new SingleIntIdEntity(1, 'foo');
diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
index df17e0eedd4c8..cce8cb9079723 100644
--- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
+++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
@@ -16,6 +16,7 @@
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+use Symfony\Component\Validator\Exception\UnexpectedValueException;
/**
* Unique Entity Validator checks if one or a set of fields contain unique values.
@@ -61,6 +62,10 @@ public function validate($entity, Constraint $constraint)
return;
}
+ if (!\is_object($entity)) {
+ throw new UnexpectedValueException($entity, 'object');
+ }
+
if ($constraint->em) {
$em = $this->registry->getManager($constraint->em);
diff --git a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php
index f0f9a95652399..b3ab046ebd42b 100644
--- a/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php
+++ b/src/Symfony/Bridge/Doctrine/Validator/DoctrineLoader.php
@@ -49,7 +49,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
$className = $metadata->getClassName();
try {
$doctrineMetadata = $this->entityManager->getClassMetadata($className);
- } catch (MappingException | OrmMappingException $exception) {
+ } catch (MappingException|OrmMappingException $exception) {
return false;
}
diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json
index 79961033bc0a6..cce2609cf1a89 100644
--- a/src/Symfony/Bridge/Doctrine/composer.json
+++ b/src/Symfony/Bridge/Doctrine/composer.json
@@ -49,11 +49,13 @@
"conflict": {
"doctrine/dbal": "<2.7",
"doctrine/orm": "<2.6.3",
+ "doctrine/lexer": "<1.1",
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
"symfony/dependency-injection": "<3.4",
"symfony/form": "<4.4",
"symfony/http-kernel": "<4.3.7",
"symfony/messenger": "<4.3",
+ "symfony/proxy-manager-bridge": "<4.4.19",
"symfony/security-core": "<4.4",
"symfony/validator": "<4.4.2|<5.0.2,>=5.0"
},
diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json
index 09692b8c89d74..577138489e690 100644
--- a/src/Symfony/Bridge/ProxyManager/composer.json
+++ b/src/Symfony/Bridge/ProxyManager/composer.json
@@ -17,7 +17,6 @@
],
"require": {
"php": ">=7.1.3",
- "composer/package-versions-deprecated": "^1.8",
"friendsofphp/proxy-manager-lts": "^1.0.2",
"symfony/dependency-injection": "^4.0|^5.0",
"symfony/polyfill-php80": "^1.16"
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
index d8e8468c3f4bc..9f0b0c070a2d9 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
@@ -57,7 +57,7 @@ protected function setUp(): void
protected function renderForm(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form', $vars);
+ return $this->renderer->renderBlock($view, 'form', $vars);
}
protected function renderLabel(FormView $view, $label = null, array $vars = [])
@@ -66,42 +66,42 @@ protected function renderLabel(FormView $view, $label = null, array $vars = [])
$vars += ['label' => $label];
}
- return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
protected function renderHelp(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ return $this->renderer->searchAndRenderBlock($view, 'help');
}
protected function renderErrors(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
+ return $this->renderer->searchAndRenderBlock($view, 'errors');
}
protected function renderWidget(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
}
protected function renderRow(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'row', $vars);
}
protected function renderRest(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
}
protected function renderStart(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
+ return $this->renderer->renderBlock($view, 'form_start', $vars);
}
protected function renderEnd(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
+ return $this->renderer->renderBlock($view, 'form_end', $vars);
}
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true)
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
index 0735cc2973e65..38c445f927726 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
@@ -107,7 +107,7 @@ public function testMoneyWidgetInIso()
protected function renderForm(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form', $vars);
+ return $this->renderer->renderBlock($view, 'form', $vars);
}
protected function renderLabel(FormView $view, $label = null, array $vars = [])
@@ -116,42 +116,42 @@ protected function renderLabel(FormView $view, $label = null, array $vars = [])
$vars += ['label' => $label];
}
- return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
protected function renderHelp(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ return $this->renderer->searchAndRenderBlock($view, 'help');
}
protected function renderErrors(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
+ return $this->renderer->searchAndRenderBlock($view, 'errors');
}
protected function renderWidget(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
}
protected function renderRow(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'row', $vars);
}
protected function renderRest(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
}
protected function renderStart(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
+ return $this->renderer->renderBlock($view, 'form_start', $vars);
}
protected function renderEnd(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
+ return $this->renderer->renderBlock($view, 'form_end', $vars);
}
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true)
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php
index da0564851229a..5c2e5afcfdf99 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php
@@ -59,7 +59,7 @@ protected function setUp(): void
protected function renderForm(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form', $vars);
+ return $this->renderer->renderBlock($view, 'form', $vars);
}
protected function renderLabel(FormView $view, $label = null, array $vars = [])
@@ -68,42 +68,42 @@ protected function renderLabel(FormView $view, $label = null, array $vars = [])
$vars += ['label' => $label];
}
- return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
protected function renderHelp(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ return $this->renderer->searchAndRenderBlock($view, 'help');
}
protected function renderErrors(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
+ return $this->renderer->searchAndRenderBlock($view, 'errors');
}
protected function renderWidget(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
}
protected function renderRow(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'row', $vars);
}
protected function renderRest(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
}
protected function renderStart(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
+ return $this->renderer->renderBlock($view, 'form_start', $vars);
}
protected function renderEnd(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
+ return $this->renderer->renderBlock($view, 'form_end', $vars);
}
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true)
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php
index f62e903473ca5..7dda79420ca12 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php
@@ -111,7 +111,7 @@ public function testMoneyWidgetInIso()
protected function renderForm(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form', $vars);
+ return $this->renderer->renderBlock($view, 'form', $vars);
}
protected function renderLabel(FormView $view, $label = null, array $vars = [])
@@ -120,42 +120,42 @@ protected function renderLabel(FormView $view, $label = null, array $vars = [])
$vars += ['label' => $label];
}
- return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
protected function renderHelp(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ return $this->renderer->searchAndRenderBlock($view, 'help');
}
protected function renderErrors(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
+ return $this->renderer->searchAndRenderBlock($view, 'errors');
}
protected function renderWidget(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
}
protected function renderRow(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'row', $vars);
}
protected function renderRest(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
}
protected function renderStart(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
+ return $this->renderer->renderBlock($view, 'form_start', $vars);
}
protected function renderEnd(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
+ return $this->renderer->renderBlock($view, 'form_end', $vars);
}
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true)
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
index 9e7b1684b8265..ff9357627579c 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
@@ -298,7 +298,7 @@ public function testHelpHtmlIsTrue()
protected function renderForm(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form', $vars);
+ return $this->renderer->renderBlock($view, 'form', $vars);
}
protected function renderLabel(FormView $view, $label = null, array $vars = [])
@@ -307,42 +307,42 @@ protected function renderLabel(FormView $view, $label = null, array $vars = [])
$vars += ['label' => $label];
}
- return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
protected function renderHelp(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ return $this->renderer->searchAndRenderBlock($view, 'help');
}
protected function renderErrors(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
+ return $this->renderer->searchAndRenderBlock($view, 'errors');
}
protected function renderWidget(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
}
protected function renderRow(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'row', $vars);
}
protected function renderRest(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
}
protected function renderStart(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
+ return $this->renderer->renderBlock($view, 'form_start', $vars);
}
protected function renderEnd(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
+ return $this->renderer->renderBlock($view, 'form_end', $vars);
}
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true)
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
index ecf3597b311a8..301a74ed94449 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
@@ -184,7 +184,7 @@ public function testHelpHtmlIsTrue()
protected function renderForm(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form', $vars);
+ return $this->renderer->renderBlock($view, 'form', $vars);
}
protected function renderLabel(FormView $view, $label = null, array $vars = [])
@@ -193,42 +193,42 @@ protected function renderLabel(FormView $view, $label = null, array $vars = [])
$vars += ['label' => $label];
}
- return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
protected function renderHelp(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ return $this->renderer->searchAndRenderBlock($view, 'help');
}
protected function renderErrors(FormView $view)
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
+ return $this->renderer->searchAndRenderBlock($view, 'errors');
}
protected function renderWidget(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
}
protected function renderRow(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'row', $vars);
}
protected function renderRest(FormView $view, array $vars = [])
{
- return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
+ return $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
}
protected function renderStart(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
+ return $this->renderer->renderBlock($view, 'form_start', $vars);
}
protected function renderEnd(FormView $view, array $vars = [])
{
- return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
+ return $this->renderer->renderBlock($view, 'form_end', $vars);
}
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true)
diff --git a/src/Symfony/Bundle/DebugBundle/README.md b/src/Symfony/Bundle/DebugBundle/README.md
new file mode 100644
index 0000000000000..bed2f5b6d680a
--- /dev/null
+++ b/src/Symfony/Bundle/DebugBundle/README.md
@@ -0,0 +1,13 @@
+DebugBundle
+===========
+
+DebugBundle provides a tight integration of the Symfony VarDumper component and
+the ServerLogCommand from MonologBridge into the Symfony full-stack framework.
+
+Resources
+---------
+
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json
index bae6358b2c005..261f3d23c7264 100644
--- a/src/Symfony/Bundle/DebugBundle/composer.json
+++ b/src/Symfony/Bundle/DebugBundle/composer.json
@@ -1,7 +1,7 @@
{
"name": "symfony/debug-bundle",
"type": "symfony-bundle",
- "description": "Provides a tight integration of the Symfony Debug component into the Symfony full-stack framework",
+ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index f52bdb7ff5c14..3875db646ff21 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -1012,13 +1012,14 @@ private function addCacheSection(ArrayNodeDefinition $rootNode)
->prototype('array')
->fixXmlConfig('adapter')
->beforeNormalization()
- ->ifTrue(function ($v) { return (isset($v['adapters']) || \is_array($v['adapter'] ?? null)) && isset($v['provider']); })
- ->thenInvalid('Pool cannot have a "provider" while "adapter" is set to a map')
+ ->ifTrue(function ($v) { return isset($v['provider']) && \is_array($v['adapters'] ?? $v['adapter'] ?? null) && 1 < \count($v['adapters'] ?? $v['adapter']); })
+ ->thenInvalid('Pool cannot have a "provider" while more than one adapter is defined')
->end()
->children()
->arrayNode('adapters')
->performNoDeepMerging()
->info('One or more adapters to chain for creating the pool, defaults to "cache.app".')
+ ->beforeNormalization()->castToArray()->end()
->beforeNormalization()
->always()->then(function ($values) {
if ([0] === array_keys($values) && \is_array($values[0])) {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php
index 4951b46c45137..2db6d689530ff 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TimedPhpEngineTest.php
@@ -31,7 +31,7 @@ public function testThatRenderLogsTime()
$container = $this->createMock(Container::class);
$templateNameParser = $this->getTemplateNameParser();
$globalVariables = $this->getGlobalVariables();
- $loader = $this->getLoader($this->getStorage());
+ $loader = $this->getLoader(new StringStorage('foo'));
$stopwatch = new Stopwatch();
@@ -60,17 +60,7 @@ private function getGlobalVariables(): GlobalVariables
return $this->createMock(GlobalVariables::class);
}
- private function getStorage(): StringStorage
- {
- return $this->getMockBuilder(StringStorage::class)
- ->disableOriginalConstructor()
- ->getMockForAbstractClass();
- }
-
- /**
- * @param StringStorage $storage
- */
- private function getLoader($storage): Loader
+ private function getLoader(StringStorage $storage): Loader
{
$loader = $this->getMockForAbstractClass(Loader::class);
$loader->expects($this->once())
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
index 22f3a8fa54351..1996249a72070 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
@@ -730,7 +730,7 @@ private function createExpression(ContainerBuilder $container, string $expressio
private function createRequestMatcher(ContainerBuilder $container, string $path = null, string $host = null, int $port = null, array $methods = [], array $ips = null, array $attributes = []): Reference
{
if ($methods) {
- $methods = array_map('strtoupper', (array) $methods);
+ $methods = array_map('strtoupper', $methods);
}
if (null !== $ips) {
diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
index a5127a25d823c..dda4ae6e82f32 100644
--- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
+++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
@@ -64,7 +64,7 @@ public function showAction(Request $request, FlattenException $exception, DebugL
$code = $exception->getStatusCode();
return new Response($this->twig->render(
- (string) $this->findTemplate($request, $request->getRequestFormat(), $code, $showException),
+ $this->findTemplate($request, $request->getRequestFormat(), $code, $showException),
[
'status_code' => $code,
'status_text' => Response::$statusTexts[$code] ?? '',
diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
index edbdc3ea92a11..3b281bc87e8a8 100644
--- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
@@ -74,7 +74,7 @@ static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifet
$key = (string) $key;
if (null === $item->expiry) {
$ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
- } elseif (0 === $item->expiry) {
+ } elseif (!$item->expiry) {
$ttl = 0;
} elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
$expiredIds[] = $getId($key);
diff --git a/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php
index 106d8821b862c..16029f3608ce7 100644
--- a/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php
@@ -80,7 +80,7 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix, $defaultLifet
$key = (string) $key;
if (null === $item->expiry) {
$ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
- } elseif (0 === $item->expiry) {
+ } elseif (!$item->expiry) {
$ttl = 0;
} elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
$expiredIds[] = $getId($key);
diff --git a/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php
index 8fba15b32fd3b..157043abef188 100644
--- a/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php
@@ -124,14 +124,14 @@ public function save(CacheItemInterface $item)
$value = $item["\0*\0value"];
$expiry = $item["\0*\0expiry"];
- if (0 === $expiry) {
- $expiry = \PHP_INT_MAX;
- }
-
- if (null !== $expiry && $expiry <= microtime(true)) {
- $this->deleteItem($key);
+ if (null !== $expiry) {
+ if (!$expiry) {
+ $expiry = \PHP_INT_MAX;
+ } elseif ($expiry <= microtime(true)) {
+ $this->deleteItem($key);
- return true;
+ return true;
+ }
}
if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
return false;
diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
index d5b0593353ae9..3a1e658bc0ac4 100644
--- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
@@ -88,7 +88,7 @@ static function (CacheItemInterface $innerItem, array $item) {
$item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
}
$innerItem->set($item["\0*\0value"]);
- $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', 0 === $item["\0*\0expiry"] ? \PHP_INT_MAX : $item["\0*\0expiry"])) : null);
+ $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $item["\0*\0expiry"])) : null);
},
null,
CacheItem::class
diff --git a/src/Symfony/Component/Cache/LockRegistry.php b/src/Symfony/Component/Cache/LockRegistry.php
index 70fcac9cc12af..20fba4d3d4da4 100644
--- a/src/Symfony/Component/Cache/LockRegistry.php
+++ b/src/Symfony/Component/Cache/LockRegistry.php
@@ -88,7 +88,7 @@ public static function compute(callable $callback, ItemInterface $item, bool &$s
$key = self::$files ? abs(crc32($item->getKey())) % \count(self::$files) : -1;
- if ($key < 0 || (self::$lockedFiles[$key] ?? false) || !$lock = self::open($key)) {
+ if ($key < 0 || self::$lockedFiles || !$lock = self::open($key)) {
return $callback($item, $save);
}
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php
index 3ff73aeab965f..123cda89b8728 100644
--- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php
+++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php
@@ -118,7 +118,7 @@ public function testGetMetadata()
$metadata = $item->getMetadata();
$this->assertArrayHasKey(CacheItem::METADATA_CTIME, $metadata);
- $this->assertEqualsWithDelta(999, $metadata[CacheItem::METADATA_CTIME], 10);
+ $this->assertEqualsWithDelta(999, $metadata[CacheItem::METADATA_CTIME], 150);
$this->assertArrayHasKey(CacheItem::METADATA_EXPIRY, $metadata);
$this->assertEqualsWithDelta(9 + time(), $metadata[CacheItem::METADATA_EXPIRY], 1);
}
@@ -296,6 +296,15 @@ public function testWeirdDataMatchingMetadataWrappedValues()
$this->assertTrue($cache->hasItem('foobar'));
}
+
+ public function testNullByteInKey()
+ {
+ $cache = $this->createCachePool(0, __FUNCTION__);
+
+ $cache->save($cache->getItem("a\0b")->set(123));
+
+ $this->assertSame(123, $cache->getItem("a\0b")->get());
+ }
}
class NotUnserializable
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php
new file mode 100644
index 0000000000000..46516e0095e6e
--- /dev/null
+++ b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterAndRedisAdapterTest.php
@@ -0,0 +1,72 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Tests\Adapter;
+
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\Adapter\AbstractAdapter;
+use Symfony\Component\Cache\Adapter\ProxyAdapter;
+use Symfony\Component\Cache\Adapter\RedisAdapter;
+use Symfony\Component\Cache\CacheItem;
+
+/**
+ * @group integration
+ */
+class ProxyAdapterAndRedisAdapterTest extends AbstractRedisAdapterTest
+{
+ protected $skippedTests = [
+ 'testPrune' => 'RedisAdapter does not implement PruneableInterface.',
+ ];
+
+ public static function setUpBeforeClass(): void
+ {
+ parent::setUpBeforeClass();
+ self::$redis = AbstractAdapter::createConnection('redis://'.getenv('REDIS_HOST'));
+ }
+
+ public function createCachePool($defaultLifetime = 0, string $testMethod = null): CacheItemPoolInterface
+ {
+ return new ProxyAdapter(new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__), 100), 'ProxyNS', $defaultLifetime);
+ }
+
+ public function testSaveItemPermanently()
+ {
+ $setCacheItemExpiry = \Closure::bind(
+ static function (CacheItem $item, $expiry) {
+ $item->expiry = $expiry;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+
+ $cache = $this->createCachePool(1);
+ $value = rand();
+ $item = $cache->getItem('foo');
+ $setCacheItemExpiry($item, 0);
+ $cache->save($item->set($value));
+ $item = $cache->getItem('bar');
+ $setCacheItemExpiry($item, 0.0);
+ $cache->save($item->set($value));
+ $item = $cache->getItem('baz');
+ $cache->save($item->set($value));
+
+ $this->assertSame($value, $this->cache->getItem('foo')->get());
+ $this->assertSame($value, $this->cache->getItem('bar')->get());
+ $this->assertSame($value, $this->cache->getItem('baz')->get());
+
+ sleep(1);
+ $this->assertSame($value, $this->cache->getItem('foo')->get());
+ $this->assertSame($value, $this->cache->getItem('bar')->get());
+ $this->assertFalse($this->cache->getItem('baz')->isHit());
+ }
+}
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php
index 4b7c64058c958..2ac5a459e7cbf 100644
--- a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php
+++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php
@@ -14,12 +14,10 @@
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
-use Psr\Log\LoggerInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
-use Symfony\Component\Cache\LockRegistry;
use Symfony\Component\Cache\Tests\Fixtures\PrunableAdapter;
/**
@@ -198,24 +196,6 @@ public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemAndOnlyHasTags
$this->assertFalse($item->isHit());
}
- public function testLog()
- {
- $lockFiles = LockRegistry::setFiles([__FILE__]);
-
- $logger = $this->createMock(LoggerInterface::class);
- $logger
- ->expects($this->atLeastOnce())
- ->method($this->anything());
-
- $cache = new TagAwareAdapter(new ArrayAdapter());
- $cache->setLogger($logger);
-
- // Computing will produce at least one log
- $cache->get('foo', static function (): string { return 'ccc'; });
-
- LockRegistry::setFiles($lockFiles);
- }
-
/**
* @return MockObject&PruneableCacheInterface
*/
diff --git a/src/Symfony/Component/Cache/Traits/ApcuTrait.php b/src/Symfony/Component/Cache/Traits/ApcuTrait.php
index b56ae4f7c39ac..ace28c7d37bd8 100644
--- a/src/Symfony/Component/Cache/Traits/ApcuTrait.php
+++ b/src/Symfony/Component/Cache/Traits/ApcuTrait.php
@@ -54,7 +54,14 @@ protected function doFetch(array $ids)
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
try {
$values = [];
- foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) {
+ $ids = array_flip($ids);
+ foreach (apcu_fetch(array_keys($ids), $ok) ?: [] as $k => $v) {
+ if (!isset($ids[$k])) {
+ // work around https://github.com/krakjoe/apcu/issues/247
+ $k = key($ids);
+ }
+ unset($ids[$k]);
+
if (null !== $v || $ok) {
$values[$k] = $v;
}
diff --git a/src/Symfony/Component/Cache/Traits/ContractsTrait.php b/src/Symfony/Component/Cache/Traits/ContractsTrait.php
index 06070c970cac5..49a96eed359f5 100644
--- a/src/Symfony/Component/Cache/Traits/ContractsTrait.php
+++ b/src/Symfony/Component/Cache/Traits/ContractsTrait.php
@@ -31,7 +31,7 @@ trait ContractsTrait
doGet as private contractsGet;
}
- private $callbackWrapper = [LockRegistry::class, 'compute'];
+ private $callbackWrapper;
private $computing = [];
/**
@@ -41,8 +41,16 @@ trait ContractsTrait
*/
public function setCallbackWrapper(?callable $callbackWrapper): callable
{
+ if (!isset($this->callbackWrapper)) {
+ $this->callbackWrapper = \Closure::fromCallable([LockRegistry::class, 'compute']);
+
+ if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
+ $this->setCallbackWrapper(null);
+ }
+ }
+
$previousWrapper = $this->callbackWrapper;
- $this->callbackWrapper = $callbackWrapper ?? function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) {
+ $this->callbackWrapper = $callbackWrapper ?? static function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) {
return $callback($item, $save);
};
@@ -82,6 +90,10 @@ static function (CacheItem $item, float $startTime, ?array &$metadata) {
$this->computing[$key] = $key;
$startTime = microtime(true);
+ if (!isset($this->callbackWrapper)) {
+ $this->setCallbackWrapper($this->setCallbackWrapper(null));
+ }
+
try {
$value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
$setMetadata($item, $startTime, $metadata);
diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php
index 5b0461409cfb5..4d5e123005877 100644
--- a/src/Symfony/Component/Cache/Traits/PdoTrait.php
+++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php
@@ -412,7 +412,7 @@ protected function doSave(array $values, int $lifetime)
if (null === $driver && !(\is_object($result) ? $result->rowCount() : $stmt->rowCount())) {
try {
$insertStmt->execute();
- } catch (DBALException | Exception $e) {
+ } catch (DBALException|Exception $e) {
} catch (\PDOException $e) {
// A concurrent write won, let it be
}
diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php
index 8179ce7fb4f1e..f04b767e7f704 100644
--- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php
+++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php
@@ -38,7 +38,7 @@ public function __construct(string $resource, bool $exists = null)
{
$this->resource = $resource;
if (null !== $exists) {
- $this->exists = [(bool) $exists, null];
+ $this->exists = [$exists, null];
}
}
diff --git a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php
index a7a8ae980d597..9319b98ea26a8 100644
--- a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php
+++ b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php
@@ -169,6 +169,8 @@ public function getDataForPhpize(): array
[1, '1'],
[-1, '-1'],
[0777, '0777'],
+ [-511, '-0777'],
+ ['0877', '0877'],
[255, '0xFF'],
[100.0, '1e2'],
[-120.0, '-1.2E2'],
diff --git a/src/Symfony/Component/Config/Util/XmlUtils.php b/src/Symfony/Component/Config/Util/XmlUtils.php
index 12caa486bfc4c..e032414944071 100644
--- a/src/Symfony/Component/Config/Util/XmlUtils.php
+++ b/src/Symfony/Component/Config/Util/XmlUtils.php
@@ -236,15 +236,11 @@ public static function phpize($value)
case 'null' === $lowercaseValue:
return null;
case ctype_digit($value):
- $raw = $value;
- $cast = (int) $value;
-
- return '0' == $value[0] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw);
case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)):
$raw = $value;
$cast = (int) $value;
- return '0' == $value[1] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw);
+ return self::isOctal($value) ? \intval($value, 8) : (($raw === (string) $cast) ? $cast : $raw);
case 'true' === $lowercaseValue:
return true;
case 'false' === $lowercaseValue:
@@ -281,4 +277,13 @@ protected static function getXmlErrors($internalErrors)
return $errors;
}
+
+ private static function isOctal(string $str): bool
+ {
+ if ('-' === $str[0]) {
+ $str = substr($str, 1);
+ }
+
+ return $str === '0'.decoct(\intval($str, 8));
+ }
}
diff --git a/src/Symfony/Component/Console/Helper/ProcessHelper.php b/src/Symfony/Component/Console/Helper/ProcessHelper.php
index d580357b93ffd..862d09f214522 100644
--- a/src/Symfony/Component/Console/Helper/ProcessHelper.php
+++ b/src/Symfony/Component/Console/Helper/ProcessHelper.php
@@ -95,10 +95,10 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call
* This is identical to run() except that an exception is thrown if the process
* exits with a non-zero exit code.
*
- * @param string|Process $cmd An instance of Process or a command to run
- * @param string|null $error An error message that must be displayed if something went wrong
- * @param callable|null $callback A PHP callback to run whenever there is some
- * output available on STDOUT or STDERR
+ * @param array|Process $cmd An instance of Process or a command to run
+ * @param string|null $error An error message that must be displayed if something went wrong
+ * @param callable|null $callback A PHP callback to run whenever there is some
+ * output available on STDOUT or STDERR
*
* @return Process The process that ran
*
diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php
index 1634c01991b0a..6e9953dd27a7b 100644
--- a/src/Symfony/Component/Console/Tests/ApplicationTest.php
+++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php
@@ -894,6 +894,9 @@ public function testRenderExceptionLineBreaks()
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks');
}
+ /**
+ * @group transient-on-windows
+ */
public function testRenderAnonymousException()
{
$application = new Application();
@@ -917,6 +920,9 @@ public function testRenderAnonymousException()
$this->assertStringContainsString('Dummy type "class@anonymous" is invalid.', $tester->getDisplay(true));
}
+ /**
+ * @group transient-on-windows
+ */
public function testRenderExceptionStackTraceContainsRootException()
{
$application = new Application();
diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php
index fd22f201adef6..99791f9aad9f3 100644
--- a/src/Symfony/Component/Debug/ErrorHandler.php
+++ b/src/Symfony/Component/Debug/ErrorHandler.php
@@ -119,7 +119,7 @@ class ErrorHandler
public static function register(self $handler = null, $replace = true)
{
if (null === self::$reservedMemory) {
- self::$reservedMemory = str_repeat('x', 10240);
+ self::$reservedMemory = str_repeat('x', 32768);
register_shutdown_function(__CLASS__.'::handleFatalError');
}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
index 73ed14a60a42e..4fb467d965d8d 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\LogicException;
@@ -131,25 +132,35 @@ protected function getConstructor(Definition $definition, $required)
if ($factory) {
[$class, $method] = $factory;
+
+ if ('__construct' === $method) {
+ throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
+ }
+
if ($class instanceof Reference) {
- $class = $this->container->findDefinition((string) $class)->getClass();
+ $factoryDefinition = $this->container->findDefinition((string) $class);
+ while ((null === $class = $factoryDefinition->getClass()) && $factoryDefinition instanceof ChildDefinition) {
+ $factoryDefinition = $this->container->findDefinition($factoryDefinition->getParent());
+ }
} elseif ($class instanceof Definition) {
$class = $class->getClass();
} elseif (null === $class) {
$class = $definition->getClass();
}
- if ('__construct' === $method) {
- throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
- }
-
return $this->getReflectionMethod(new Definition($class), $method);
}
- $class = $definition->getClass();
+ while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) {
+ $definition = $this->container->findDefinition($definition->getParent());
+ }
try {
if (!$r = $this->container->getReflectionClass($class)) {
+ if (null === $class) {
+ throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
+ }
+
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
}
} catch (\ReflectionException $e) {
@@ -179,7 +190,11 @@ protected function getReflectionMethod(Definition $definition, $method)
return $this->getConstructor($definition, true);
}
- if (!$class = $definition->getClass()) {
+ while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) {
+ $definition = $this->container->findDefinition($definition->getParent());
+ }
+
+ if (null === $class) {
throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
}
@@ -188,6 +203,10 @@ protected function getReflectionMethod(Definition $definition, $method)
}
if (!$r->hasMethod($method)) {
+ if ($r->hasMethod('__call') && ($r = $r->getMethod('__call')) && $r->isPublic()) {
+ return new \ReflectionMethod(static function (...$arguments) {}, '__invoke');
+ }
+
throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
index 59c15cf2382c1..88355eb7f04c7 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
@@ -133,6 +133,11 @@ protected function processValue($value, $isRoot = false)
continue;
}
+ if (is_subclass_of($m[1], \UnitEnum::class)) {
+ $bindingNames[substr($key, \strlen($m[0]))] = $binding;
+ continue;
+ }
+
if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) {
throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected "%s", "%s", "%s", "%s" or null, "%s" given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, ServiceLocatorArgument::class, \gettype($bindingValue)));
}
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
index 8017fc579aaa2..17cf2c1a74a68 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
@@ -138,7 +138,7 @@ private function addService(Definition $definition, ?string $id, \DOMElement $pa
$tag = $this->document->createElement('tag');
$tag->setAttribute('name', $name);
foreach ($attributes as $key => $value) {
- $tag->setAttribute($key, $value);
+ $tag->setAttribute($key, $value ?? '');
}
$service->appendChild($tag);
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
index 968a3f5eebff5..fdf4fa1f4c887 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
@@ -197,7 +197,7 @@ private function parseDefinition(\DOMElement $service, string $file, array $defa
if ($alias = $service->getAttribute('alias')) {
$this->validateAlias($service, $file);
- $this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias));
+ $this->container->setAlias($service->getAttribute('id'), $alias = new Alias($alias));
if ($publicAttr = $service->getAttribute('public')) {
$alias->setPublic(XmlUtils::phpize($publicAttr));
} elseif (isset($defaults['public'])) {
@@ -345,7 +345,7 @@ private function parseDefinition(\DOMElement $service, string $file, array $defa
}
if ('' === $tag->getAttribute('name')) {
- throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', (string) $service->getAttribute('id'), $file));
+ throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $service->getAttribute('id'), $file));
}
$definition->addTag($tag->getAttribute('name'), $parameters);
@@ -374,7 +374,7 @@ private function parseDefinition(\DOMElement $service, string $file, array $defa
} elseif ('null' === $decorationOnInvalid) {
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
} else {
- throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, (string) $service->getAttribute('id'), $file));
+ throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, $service->getAttribute('id'), $file));
}
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AbstractRecursivePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AbstractRecursivePassTest.php
new file mode 100644
index 0000000000000..aecdc9a5a2169
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AbstractRecursivePassTest.php
@@ -0,0 +1,127 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Tests\Compiler;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy;
+
+class AbstractRecursivePassTest extends TestCase
+{
+ public function testGetConstructorResolvesFactoryChildDefinitionsClass()
+ {
+ $container = new ContainerBuilder();
+ $container->setParameter('factory_dummy_class', FactoryDummy::class);
+ $container
+ ->register('parent', '%factory_dummy_class%')
+ ->setAbstract(true);
+ $container->setDefinition('child', new ChildDefinition('parent'));
+ $container
+ ->register('foo', \stdClass::class)
+ ->setFactory([new Reference('child'), 'createFactory']);
+
+ $pass = new class() extends AbstractRecursivePass {
+ public $actual;
+
+ protected function processValue($value, $isRoot = false)
+ {
+ if ($value instanceof Definition && 'foo' === $this->currentId) {
+ $this->actual = $this->getConstructor($value, true);
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+ };
+ $pass->process($container);
+
+ $this->assertInstanceOf(\ReflectionMethod::class, $pass->actual);
+ $this->assertSame(FactoryDummy::class, $pass->actual->class);
+ }
+
+ public function testGetConstructorResolvesChildDefinitionsClass()
+ {
+ $container = new ContainerBuilder();
+ $container
+ ->register('parent', Bar::class)
+ ->setAbstract(true);
+ $container->setDefinition('foo', new ChildDefinition('parent'));
+
+ $pass = new class() extends AbstractRecursivePass {
+ public $actual;
+
+ protected function processValue($value, $isRoot = false)
+ {
+ if ($value instanceof Definition && 'foo' === $this->currentId) {
+ $this->actual = $this->getConstructor($value, true);
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+ };
+ $pass->process($container);
+
+ $this->assertInstanceOf(\ReflectionMethod::class, $pass->actual);
+ $this->assertSame(Bar::class, $pass->actual->class);
+ }
+
+ public function testGetReflectionMethodResolvesChildDefinitionsClass()
+ {
+ $container = new ContainerBuilder();
+ $container
+ ->register('parent', Bar::class)
+ ->setAbstract(true);
+ $container->setDefinition('foo', new ChildDefinition('parent'));
+
+ $pass = new class() extends AbstractRecursivePass {
+ public $actual;
+
+ protected function processValue($value, $isRoot = false)
+ {
+ if ($value instanceof Definition && 'foo' === $this->currentId) {
+ $this->actual = $this->getReflectionMethod($value, 'create');
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+ };
+ $pass->process($container);
+
+ $this->assertInstanceOf(\ReflectionMethod::class, $pass->actual);
+ $this->assertSame(Bar::class, $pass->actual->class);
+ }
+
+ public function testGetConstructorDefinitionNoClass()
+ {
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('Invalid service "foo": the class is not set.');
+
+ $container = new ContainerBuilder();
+ $container->register('foo');
+
+ (new class() extends AbstractRecursivePass {
+ protected function processValue($value, $isRoot = false)
+ {
+ if ($value instanceof Definition && 'foo' === $this->currentId) {
+ $this->getConstructor($value, true);
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+ })->process($container);
+ }
+}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php
index adb725cc99c7f..9de33d2f5eef3 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php
@@ -988,4 +988,22 @@ public function testIntersectionTypeFailsWithReference()
(new CheckTypeDeclarationsPass(true))->process($container);
}
+
+ public function testCallableClass()
+ {
+ $container = new ContainerBuilder();
+ $definition = $container->register('foo', CallableClass::class);
+ $definition->addMethodCall('callMethod', [123]);
+
+ (new CheckTypeDeclarationsPass())->process($container);
+
+ $this->addToAssertionCount(1);
+ }
+}
+
+class CallableClass
+{
+ public function __call($name, $arguments)
+ {
+ }
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
index 199961a10d6fb..5d4f5ef9bb5f4 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
@@ -24,7 +24,9 @@
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedEnumArgumentDummy;
use Symfony\Component\DependencyInjection\Tests\Fixtures\ParentNotExists;
use Symfony\Component\DependencyInjection\TypedReference;
@@ -63,6 +65,27 @@ public function testProcess()
$this->assertEquals([['setSensitiveClass', [new Reference('foo')]]], $definition->getMethodCalls());
}
+ /**
+ * @requires PHP 8.1
+ */
+ public function testProcessEnum()
+ {
+ $container = new ContainerBuilder();
+
+ $bindings = [
+ FooUnitEnum::class.' $bar' => new BoundArgument(FooUnitEnum::BAR),
+ ];
+
+ $definition = $container->register(NamedEnumArgumentDummy::class, NamedEnumArgumentDummy::class);
+ $definition->setBindings($bindings);
+
+ $pass = new ResolveBindingsPass();
+ $pass->process($container);
+
+ $expected = [FooUnitEnum::BAR];
+ $this->assertEquals($expected, $definition->getArguments());
+ }
+
public function testUnusedBinding()
{
$this->expectException(InvalidArgumentException::class);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedEnumArgumentDummy.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedEnumArgumentDummy.php
new file mode 100644
index 0000000000000..c172c996a7fb7
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedEnumArgumentDummy.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
+
+class NamedEnumArgumentDummy
+{
+ public function __construct(FooUnitEnum $bar)
+ {
+ }
+}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
index 3ea49503e9753..f4606815cd705 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
@@ -17,6 +17,7 @@
->register('foo', FooClass::class)
->addTag('foo', ['foo' => 'foo'])
->addTag('foo', ['bar' => 'bar', 'baz' => 'baz'])
+ ->addTag('nullable', ['bar' => 'bar', 'baz' => null])
->setFactory(['Bar\\FooClass', 'getInstance'])
->setArguments(['foo', new Reference('foo.baz'), ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%'], true, new Reference('service_container')])
->setProperties(['foo' => 'bar', 'moo' => new Reference('foo.baz'), 'qux' => ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%']])
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
index 55ec20ee10059..13fb730237136 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
@@ -10,6 +10,7 @@
+
foo
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
index fd2be046f8cd6..f9f987e8546cc 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
@@ -13,6 +13,7 @@ services:
tags:
- { name: foo, foo: foo }
- { name: foo, bar: bar, baz: baz }
+ - { name: nullable, bar: bar, baz: ~ }
arguments: [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container']
properties: { foo: bar, moo: '@foo.baz', qux: { '%foo%': 'foo is %foo%', foobar: '%foo%' } }
calls:
diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php
index de7b3aedc37ae..36c7a41e5fbc7 100644
--- a/src/Symfony/Component/DomCrawler/Crawler.php
+++ b/src/Symfony/Component/DomCrawler/Crawler.php
@@ -1186,7 +1186,7 @@ protected function sibling($node, $siblingDir = 'nextSibling')
private function parseHtml5(string $htmlContent, string $charset = 'UTF-8'): \DOMDocument
{
- return $this->html5Parser->parse($this->convertToHtmlEntities($htmlContent, $charset), [], $charset);
+ return $this->html5Parser->parse($this->convertToHtmlEntities($htmlContent, $charset));
}
private function parseXhtml(string $htmlContent, string $charset = 'UTF-8'): \DOMDocument
@@ -1222,11 +1222,11 @@ private function convertToHtmlEntities(string $htmlContent, string $charset = 'U
try {
return mb_convert_encoding($htmlContent, 'HTML-ENTITIES', $charset);
- } catch (\Exception | \ValueError $e) {
+ } catch (\Exception|\ValueError $e) {
try {
$htmlContent = iconv($charset, 'UTF-8', $htmlContent);
$htmlContent = mb_convert_encoding($htmlContent, 'HTML-ENTITIES', 'UTF-8');
- } catch (\Exception | \ValueError $e) {
+ } catch (\Exception|\ValueError $e) {
}
return $htmlContent;
diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php
index 8180f4bfa10ba..16a252df4f87d 100644
--- a/src/Symfony/Component/Dotenv/Dotenv.php
+++ b/src/Symfony/Component/Dotenv/Dotenv.php
@@ -54,8 +54,8 @@ public function __construct(bool $usePutenv = true)
/**
* Loads one or several .env files.
*
- * @param string $path A file to load
- * @param ...string $extraPaths A list of additional files to load
+ * @param string $path A file to load
+ * @param string[] ...$extraPaths A list of additional files to load
*
* @throws FormatException when a file has a syntax error
* @throws PathException when a file does not exist or is not readable
@@ -112,8 +112,8 @@ public function loadEnv(string $path, string $varName = 'APP_ENV', string $defau
/**
* Loads one or several .env files and enables override existing vars.
*
- * @param string $path A file to load
- * @param ...string $extraPaths A list of additional files to load
+ * @param string $path A file to load
+ * @param string[] ...$extraPaths A list of additional files to load
*
* @throws FormatException when a file has a syntax error
* @throws PathException when a file does not exist or is not readable
diff --git a/src/Symfony/Component/ErrorHandler/ErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorHandler.php
index e6e21d601700e..ceadcaf674fc6 100644
--- a/src/Symfony/Component/ErrorHandler/ErrorHandler.php
+++ b/src/Symfony/Component/ErrorHandler/ErrorHandler.php
@@ -111,7 +111,7 @@ class ErrorHandler
public static function register(self $handler = null, bool $replace = true): self
{
if (null === self::$reservedMemory) {
- self::$reservedMemory = str_repeat('x', 10240);
+ self::$reservedMemory = str_repeat('x', 32768);
register_shutdown_function(__CLASS__.'::handleFatalError');
}
@@ -342,7 +342,7 @@ public function scopeAt(int $levels, bool $replace = false): int
public function traceAt(int $levels, bool $replace = false): int
{
$prev = $this->tracedErrors;
- $this->tracedErrors = (int) $levels;
+ $this->tracedErrors = $levels;
if (!$replace) {
$this->tracedErrors |= $prev;
}
@@ -609,7 +609,9 @@ public function handleException(\Throwable $exception)
}
$loggedErrors = $this->loggedErrors;
- $this->loggedErrors = $exception === $handlerException ? 0 : $this->loggedErrors;
+ if ($exception === $handlerException) {
+ $this->loggedErrors &= ~$type;
+ }
try {
$this->handleException($handlerException);
diff --git a/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt b/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt
index 06540f4530121..be5ce6a5cdffa 100644
--- a/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt
+++ b/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt
@@ -16,7 +16,9 @@ if (true) {
{
public function log($level, $message, array $context = []): void
{
- echo 'LOG: ', $message, "\n";
+ if (0 !== strpos($message, 'Deprecated: ')) {
+ echo 'LOG: ', $message, "\n";
+ }
}
}
}
@@ -34,5 +36,5 @@ Exception {%S
#message: "foo"
#code: 0
#file: "%s"
- #line: 25
+ #line: 27
}
diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
index a18e6185beeec..8508ab707b9a3 100644
--- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
+++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
@@ -64,7 +64,7 @@ public function current()
// the logic here avoids redoing the same work in all iterations
if (null === $subPathname = $this->subPath) {
- $subPathname = $this->subPath = (string) $this->getSubPath();
+ $subPathname = $this->subPath = $this->getSubPath();
}
if ('' !== $subPathname) {
$subPathname .= $this->directorySeparator;
diff --git a/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
index 037810aea799f..f48cc941f8ad3 100644
--- a/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
+++ b/src/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
@@ -21,7 +21,7 @@ class RecursiveDirectoryIteratorTest extends IteratorTestCase
public function testRewindOnFtp()
{
try {
- $i = new RecursiveDirectoryIterator('ftp://speedtest.tele2.net/', \RecursiveDirectoryIterator::SKIP_DOTS);
+ $i = new RecursiveDirectoryIterator('ftp://speedtest:speedtest@ftp.otenet.gr/', \RecursiveDirectoryIterator::SKIP_DOTS);
} catch (\UnexpectedValueException $e) {
$this->markTestSkipped('Unsupported stream "ftp".');
}
@@ -37,14 +37,14 @@ public function testRewindOnFtp()
public function testSeekOnFtp()
{
try {
- $i = new RecursiveDirectoryIterator('ftp://speedtest.tele2.net/', \RecursiveDirectoryIterator::SKIP_DOTS);
+ $i = new RecursiveDirectoryIterator('ftp://speedtest:speedtest@ftp.otenet.gr/', \RecursiveDirectoryIterator::SKIP_DOTS);
} catch (\UnexpectedValueException $e) {
$this->markTestSkipped('Unsupported stream "ftp".');
}
$contains = [
- 'ftp://speedtest.tele2.net'.\DIRECTORY_SEPARATOR.'1000GB.zip',
- 'ftp://speedtest.tele2.net'.\DIRECTORY_SEPARATOR.'100GB.zip',
+ 'ftp://speedtest:speedtest@ftp.otenet.gr'.\DIRECTORY_SEPARATOR.'test100Mb.db',
+ 'ftp://speedtest:speedtest@ftp.otenet.gr'.\DIRECTORY_SEPARATOR.'test100k.db',
];
$actual = [];
diff --git a/src/Symfony/Component/Form/Resources/translations/validators.fa.xlf b/src/Symfony/Component/Form/Resources/translations/validators.fa.xlf
index 4ed719917549d..4a98eea8eb314 100644
--- a/src/Symfony/Component/Form/Resources/translations/validators.fa.xlf
+++ b/src/Symfony/Component/Form/Resources/translations/validators.fa.xlf
@@ -24,7 +24,7 @@
The selected choice is invalid.
- گزینهی انتخابشده نامعتبر است.
+ گزینه انتخاب شده نامعتبر است.
The collection is invalid.
@@ -44,7 +44,7 @@
Please choose a valid date interval.
- لطفاً یک بازهی زمانی معتبر انتخاب کنید.
+ لطفاً یک بازه زمانی معتبر انتخاب کنید.
Please enter a valid date and time.
@@ -124,15 +124,15 @@
Please select a valid option.
- لطفاً یک گزینهی معتبر انتخاب کنید.
+ لطفاً یک گزینه معتبر انتخاب کنید.
Please select a valid range.
- لطفاً یک محدودهی معتبر انتخاب کنید.
+ لطفاً یک محدوده معتبر انتخاب کنید.
Please enter a valid week.
- لطفاً یک هفتهی معتبر وارد کنید.
+ لطفاً یک هفته معتبر وارد کنید.