From bfb57aad65b08b304164a81dfe701ed8fcf1b6d7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 26 Aug 2023 15:52:45 +0200 Subject: [PATCH 01/23] Bump Symfony version to 5.4.29 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 8f448da150ce0..42e6ed4b1e80f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.28'; - public const VERSION_ID = 50428; + public const VERSION = '5.4.29-DEV'; + public const VERSION_ID = 50429; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 28; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 29; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From aaf507a766cfb2b63152f3cc5c89e0d11c2ed00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Despont?= Date: Tue, 29 Aug 2023 08:36:24 +0200 Subject: [PATCH 02/23] Update Pbkdf2PasswordHasher.php Because https://www.php.net/manual/en/function.hash-pbkdf2.php is expecting string and not ?string. Pertmits avoiding deprecation warning. --- .../Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php b/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php index 57fbe0728fe93..2fc762cb4e870 100644 --- a/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php +++ b/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php @@ -69,7 +69,7 @@ public function hash(string $plainPassword, string $salt = null): string throw new LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } - $digest = hash_pbkdf2($this->algorithm, $plainPassword, $salt, $this->iterations, $this->length, true); + $digest = hash_pbkdf2($this->algorithm, $plainPassword, $salt ?? '', $this->iterations, $this->length, true); return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } From bfc4bddc7b9358dfb77dfa76446380b40a219290 Mon Sep 17 00:00:00 2001 From: Caligone Date: Sat, 2 Sep 2023 09:45:59 +0200 Subject: [PATCH 03/23] [Serializer] Looking for DiscriminatorMap on interfaces when the current object also extends from a class --- .../ClassDiscriminatorFromClassMetadata.php | 4 +++- .../Tests/Fixtures/DummyMessageInterface.php | 3 ++- .../Fixtures/DummyMessageNumberThree.php | 19 +++++++++++++++++++ .../Serializer/Tests/SerializerTest.php | 13 +++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php diff --git a/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php b/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php index 23554ffda98ab..6f69c890b91d9 100644 --- a/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php +++ b/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php @@ -78,7 +78,9 @@ private function resolveMappingForMappedObject($object) { $reflectionClass = new \ReflectionClass($object); if ($parentClass = $reflectionClass->getParentClass()) { - return $this->getMappingForMappedObject($parentClass->getName()); + if (null !== ($parentMapping = $this->getMappingForMappedObject($parentClass->getName()))) { + return $parentMapping; + } } foreach ($reflectionClass->getInterfaceNames() as $interfaceName) { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php index 55bb00bc8e253..78beb8374aaff 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php @@ -16,7 +16,8 @@ /** * @DiscriminatorMap(typeProperty="type", mapping={ * "one"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne", - * "two"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo" + * "two"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo", + * "three"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberThree" * }) * * @author Samuel Roze diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php new file mode 100644 index 0000000000000..e15fc62c7bae0 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.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\Serializer\Tests\Fixtures; + +/** + * @author Samuel Roze + */ +class DummyMessageNumberThree extends \stdClass implements DummyMessageInterface +{ +} diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index b4e84132a0858..2141c0cf6d334 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -58,6 +58,7 @@ use Symfony\Component\Serializer\Tests\Fixtures\DummyFirstChildQuux; use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface; use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne; +use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberThree; use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo; use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumConstructor; use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumProperty; @@ -488,6 +489,18 @@ public function testDeserializeAndSerializeNestedInterfacedObjectsWithTheClassMe $this->assertEquals($example, $deserialized); } + public function testDeserializeAndSerializeNestedAbstractAndInterfacedObjectsWithTheClassMetadataDiscriminator() + { + $example = new DummyMessageNumberThree(); + + $serializer = $this->serializerWithClassDiscriminator(); + + $serialized = $serializer->serialize($example, 'json'); + $deserialized = $serializer->deserialize($serialized, DummyMessageInterface::class, 'json'); + + $this->assertEquals($example, $deserialized); + } + public function testExceptionWhenTypeIsNotKnownInDiscriminator() { try { From 809cf7403771d123134139819e6508466a8258d2 Mon Sep 17 00:00:00 2001 From: "Phil E. Taylor" Date: Wed, 6 Sep 2023 22:45:09 +0100 Subject: [PATCH 04/23] PHP 8.3 highlight_file function output changes --- .../Bridge/Twig/Extension/CodeExtension.php | 26 ++++++++++++++----- .../ErrorRenderer/HtmlErrorRenderer.php | 26 ++++++++++++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 3bf8ccd294b41..59845396cfe40 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -123,13 +123,25 @@ public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?stri // highlight_file could throw warnings // see https://bugs.php.net/25725 $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { - return "".str_replace('
', "

", $m[2]).''; - }, $code); - $content = explode('
', $code); + if (\PHP_VERSION_ID >= 80300) { + // remove main pre/code tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline code tags + $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; + }, $code); + // Convert spaces to html entities to preserve indentation when rendered + $code = str_replace(' ', ' ', $code); + $content = explode("\n", $code); + } else { + // remove main code/span tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline spans + $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { + return "".str_replace('
', "

", $m[2]).''; + }, $code); + $content = explode('
', $code); + } $lines = []; if (0 > $srcContext) { diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php index b8a9aeda61fda..92434b8e94506 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php +++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php @@ -269,13 +269,25 @@ private function fileExcerpt(string $file, int $line, int $srcContext = 3): stri // highlight_file could throw warnings // see https://bugs.php.net/25725 $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { - return "".str_replace('
', "

", $m[2]).''; - }, $code); - $content = explode('
', $code); + if (\PHP_VERSION_ID >= 80300) { + // remove main pre/code tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline code tags + $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; + }, $code); + // Convert spaces to html entities to preserve indentation when rendered + $code = str_replace(' ', ' ', $code); + $content = explode("\n", $code); + } else { + // remove main code/span tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline spans + $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { + return "".str_replace('
', "

", $m[2]).''; + }, $code); + $content = explode('
', $code); + } $lines = []; if (0 > $srcContext) { From e1a14b754b0333b719a078c58c88103ac46789b0 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Thu, 7 Sep 2023 00:39:36 +0200 Subject: [PATCH 05/23] [FrameworkBundle] Always use buildDir as `ConfigBuilderGenerator` outputDir --- .../CacheWarmer/ConfigBuilderCacheWarmer.php | 2 +- .../ConfigBuilderCacheWarmerTest.php | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php index ed20bbcb648d7..50843f5263c18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php @@ -44,7 +44,7 @@ public function __construct(KernelInterface $kernel, LoggerInterface $logger = n */ public function warmUp(string $cacheDir) { - $generator = new ConfigBuilderGenerator($cacheDir); + $generator = new ConfigBuilderGenerator($this->kernel->getBuildDir()); foreach ($this->kernel->getBundles() as $bundle) { $extension = $bundle->getContainerExtension(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php new file mode 100644 index 0000000000000..c64e5d3b4cdd3 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; + +use Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpKernel\Kernel; + +class ConfigBuilderCacheWarmerTest extends TestCase +{ + private $varDir; + + protected function setUp(): void + { + $this->varDir = sys_get_temp_dir().'/'.uniqid(); + $fs = new Filesystem(); + $fs->mkdir($this->varDir); + } + + protected function tearDown(): void + { + $fs = new Filesystem(); + $fs->remove($this->varDir); + unset($this->varDir); + } + + public function testBuildDirIsUsedAsConfigBuilderOutputDir() + { + $kernel = new class($this->varDir) extends Kernel { + private $varDir; + + public function __construct(string $varDir) + { + parent::__construct('test', false); + + $this->varDir = $varDir; + } + + public function registerBundles(): iterable + { + yield new FrameworkBundle(); + } + + public function getBuildDir(): string + { + return $this->varDir.'/build'; + } + + public function getCacheDir(): string + { + return $this->varDir.'/cache'; + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + } + }; + $kernel->boot(); + + $warmer = new ConfigBuilderCacheWarmer($kernel); + $warmer->warmUp($kernel->getCacheDir()); + + self::assertDirectoryExists($kernel->getBuildDir().'/Symfony'); + self::assertDirectoryDoesNotExist($kernel->getCacheDir().'/Symfony'); + } +} From 0182fc7d306cd4253dc1550946686d2cbee0c14e Mon Sep 17 00:00:00 2001 From: Makrevski Zoran Date: Sat, 9 Sep 2023 10:37:18 +0300 Subject: [PATCH 06/23] [Form][Security][Validator] Add mk translations --- .../Resources/translations/validators.mk.xlf | 139 ++++++ .../Resources/translations/security.mk.xlf | 83 ++++ .../Resources/translations/validators.mk.xlf | 431 ++++++++++++++++++ 3 files changed, 653 insertions(+) create mode 100644 src/Symfony/Component/Form/Resources/translations/validators.mk.xlf create mode 100644 src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf create mode 100644 src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf diff --git a/src/Symfony/Component/Form/Resources/translations/validators.mk.xlf b/src/Symfony/Component/Form/Resources/translations/validators.mk.xlf new file mode 100644 index 0000000000000..ea86b304cee25 --- /dev/null +++ b/src/Symfony/Component/Form/Resources/translations/validators.mk.xlf @@ -0,0 +1,139 @@ + + + + + + This form should not contain extra fields. + Оваа форма не треба да содржи дополнителни полиња. + + + The uploaded file was too large. Please try to upload a smaller file. + Датотеката што се обидовте да ја подигнете е преголема. Ве молиме обидете се со помала датотека. + + + The CSRF token is invalid. Please try to resubmit the form. + Вашиот CSRF токен е невалиден. Ве молиме испратете ја формата одново. + + + This value is not a valid HTML5 color. + Оваа вредност не е валидна HTML5 боја. + + + Please enter a valid birthdate. + Ве молиме внесете валидна дата на раѓање. + + + The selected choice is invalid. + Избраната опција е невалидна. + + + The collection is invalid. + Колекцијата е невалидна. + + + Please select a valid color. + Ве молиме одберете валидна боја. + + + Please select a valid country. + Ве молиме одберете валидна земја. + + + Please select a valid currency. + Ве молиме одберете валидна валута. + + + Please choose a valid date interval. + Ве молиме одберете валиден интервал помеѓу два датума. + + + Please enter a valid date and time. + Ве молиме внесете валиден датум и време. + + + Please enter a valid date. + Ве молиме внесете валиден датум. + + + Please select a valid file. + Ве молиме одберете валидна датотека. + + + The hidden field is invalid. + Скриеното поле е невалидно. + + + Please enter an integer. + Ве молиме внесете цел број. + + + Please select a valid language. + Ве молиме одберете валиден јазик. + + + Please select a valid locale. + Ве молиме одберете валидна локализација. + + + Please enter a valid money amount. + Ве молиме внесете валидна сума на пари. + + + Please enter a number. + Ве молиме внесете број. + + + The password is invalid. + Лозинката е погрешна. + + + Please enter a percentage value. + Ве молиме внесете процентуална вредност. + + + The values do not match. + Вредностите не се совпаѓаат. + + + Please enter a valid time. + Ве молиме внесете валидно време. + + + Please select a valid timezone. + Ве молиме одберете валидна временска зона. + + + Please enter a valid URL. + Ве молиме внесете валиден униформен локатор на ресурси (URL). + + + Please enter a valid search term. + Ве молиме внесете валиден термин за пребарување. + + + Please provide a valid phone number. + Ве молиме внесете валиден телефонски број. + + + The checkbox has an invalid value. + Полето за штиклирање има неважечка вредност. + + + Please enter a valid email address. + Ве молиме внесете валидна адреса за е-пошта. + + + Please select a valid option. + Ве молиме одберете валидна опција. + + + Please select a valid range. + Ве молиме одберете важечки опсег. + + + Please enter a valid week. + Ве молиме внесете валидна недела. + + + + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf new file mode 100644 index 0000000000000..051affcf8b241 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf @@ -0,0 +1,83 @@ + + + + + + An authentication exception occurred. + Настана грешка во автентикацијата. + + + Authentication credentials could not be found. + Акредитивите за автентикација не се пронајдени. + + + Authentication request could not be processed due to a system problem. + Барањето за автентикација не можеше да биде процесуирано заради системски проблем. + + + Invalid credentials. + Невалидни акредитиви. + + + Cookie has already been used by someone else. + Колачето е веќе користено од некој друг. + + + Not privileged to request the resource. + Немате привилегии за да го побарате ресурсот. + + + Invalid CSRF token. + Невалиден CSRF токен. + + + No authentication provider found to support the authentication token. + Не е пронајден провајдер за автентикација кој го поддржува токенот за автентикација. + + + No session available, it either timed out or cookies are not enabled. + Сесијата е недостапна, или е истечена, или колачињата не се овозможени. + + + No token could be found. + Токенот не е најден. + + + Username could not be found. + Корисничкото име не е најдено. + + + Account has expired. + Корисничката сметка е истечена. + + + Credentials have expired. + Акредитивите се истечени. + + + Account is disabled. + Корисничката сметка е деактивирана. + + + Account is locked. + Корисничката сметка е заклучена. + + + Too many failed login attempts, please try again later. + Премногу неуспешни обиди за најавување, ве молиме обидете се повторно подоцна. + + + Invalid or expired login link. + Неважечка или истечена врска за најавување. + + + Too many failed login attempts, please try again in %minutes% minute. + Премногу неуспешни обиди за најавување, обидете се повторно за %minutes% минута. + + + Too many failed login attempts, please try again in %minutes% minutes. + Премногу неуспешни обиди за најавување, обидете се повторно за %minutes% минути. + + + + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf new file mode 100644 index 0000000000000..eb15989839b8a --- /dev/null +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf @@ -0,0 +1,431 @@ + + + + + + This value should be false. + Оваа вредност треба да биде лажна. + + + This value should be true. + Оваа вредност треба да биде вистинита. + + + This value should be of type {{ type }}. + Оваа вредност треба да биде од типот {{ type }}. + + + This value should be blank. + Оваа вредност треба да биде празна. + + + The value you selected is not a valid choice. + Вредноста што ја одбравте не е валиден избор. + + + You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. + Мора да одберете најмалку {{ limit }} избор.|Мора да одберете најмалку {{ limit }} изброи. + + + You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. + Може да одберете најмногу {{ limit }} избор.|Мора да одберете најмногу {{ limit }} избори. + + + One or more of the given values is invalid. + Една или повеќе од дадените вредности не се валидни. + + + This field was not expected. + Ова поле не беше очекувано. + + + This field is missing. + Ова поле недостига. + + + This value is not a valid date. + Оваа вредност не е валиден датум. + + + This value is not a valid datetime. + Оваа вредност не е валиден датум и време. + + + This value is not a valid email address. + Оваа вредност не е валидна адреса за е-пошта. + + + The file could not be found. + Датотеката не е најдена. + + + The file is not readable. + Датотеката не може да биде прочитана. + + + The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. + Датотеката е премногу голема ({{ size }} {{ suffix }}). Максималната дозволена големина е {{ limit }} {{ suffix }}. + + + The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. + Миме типот на датотеката не е валиден ({{ type }}). Дозволените миме типови се {{ types }}. + + + This value should be {{ limit }} or less. + Оваа вредност треба да биде {{ limit }} или помалку. + + + This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. + Оваа вредност е предолга. Треба да содржи {{ limit }} карактер или помалку.|Оваа вредност е предолга. Треба да содржи {{ limit }} карактери или помалку. + + + This value should be {{ limit }} or more. + Оваа вредност треба да е {{ limit }} или повеќе. + + + This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. + Оваа вредност е прекратка. Треба да содржи {{ limit }} карактер или повеќе.|Оваа вредност е прекратка. Треба да содржи {{ limit }} карактери или повеќе. + + + This value should not be blank. + Ова поле не може да биде празно. + + + This value should not be null. + Оваа вредност не може да биде ништо (null). + + + This value should be null. + Оваа вредност треба да е ништо (null). + + + This value is not valid. + Оваа вредност не е валидна. + + + This value is not a valid time. + Оваа вредност не е валидно време. + + + This value is not a valid URL. + Оваа вредност не е валиден URL. + + + The two values should be equal. + Двете вредности треба да се еднакви. + + + The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. + Датотеката е премногу голема. Максималната дозволена големина е {{ limit }} {{ suffix }}. + + + The file is too large. + Датотеката е премногу голема. + + + The file could not be uploaded. + Датотеката не може да биде подигната. + + + This value should be a valid number. + Оваа вредност треба да е валиден број. + + + This file is not a valid image. + Оваа датотека не е валидна слика. + + + This is not a valid IP address. + Ова не е валидна IP адреса. + + + This value is not a valid language. + Оваа вредност не е валиден јазик. + + + This value is not a valid locale. + Оваа вредност не е валидна локализација. + + + This value is not a valid country. + Оваа вредност не е валидна земја. + + + This value is already used. + Оваа вредност веќе се користи. + + + The size of the image could not be detected. + Големината на сликата не може да се детектира. + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + Ширината на сликата е преголема ({{ width }}px). Максималната дозволена ширина е {{ max_width }}px. + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + Ширината на сликата е премала ({{ width }}px). Минималната дозволена ширина е {{ min_width }}px. + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + Висината на сликата е преголема ({{ height }}px). Максималната дозволена висина е {{ max_height }}px. + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + Висината на сликата е премала ({{ height }}px). Минималната дозволена висина е {{ min_height }}px. + + + This value should be the user's current password. + Оваа вредност треба да биде сегашната лозинка на корисникот. + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + Оваа вредност треба да има точно {{ limit }} карактер.|Оваа вредност треба да има точно {{ limit }} карактери. + + + The file was only partially uploaded. + Датотеката е само делумно подигната. + + + No file was uploaded. + Датотеката не е подигната. + + + No temporary folder was configured in php.ini. + Ниту една привремена папка не е конфигурирана во php.ini. + + + Cannot write temporary file to disk. + Не може да се напише привремена датотека на дискот. + + + A PHP extension caused the upload to fail. + PHP екстензијата предизвика подигнувањето да биде неуспешно. + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + Оваа колекција треба да содржи {{ limit }} елемент или повеќе.|Оваа колекција треба да содржи {{ limit }} елементи или повеќе. + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + Оваа колекција треба да содржи {{ limit }} елемент или помалку.|Оваа колекција треба да содржи {{ limit }} елементи или помалку. + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + Оваа колекција треба да содржи точно {{ limit }} елемент.|Оваа колекција треба да содржи точно {{ limit }} елементи. + + + Invalid card number. + Бројот на картичката не е валиден. + + + Unsupported card type or invalid card number. + Неподдржан тип на картичка или бројот на картичката не е валиден. + + + This is not a valid International Bank Account Number (IBAN). + Ова не е валиден број на меѓународна банкарска сметка (IBAN). + + + This value is not a valid ISBN-10. + Оваа вредност не е валиден ISBN-10. + + + This value is not a valid ISBN-13. + Оваа вредност не е валиден ISBN-13. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Оваа вредност не е ниту валиден ISBN-10 ниту валиден ISBN-13. + + + This value is not a valid ISSN. + Оваа вредност не е валиден ISSN. + + + This value is not a valid currency. + Оваа вредност не е валидна валута. + + + This value should be equal to {{ compared_value }}. + Оваа вредност треба да биде еднаква на {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Оваа вредност треба да е поголема од {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Оваа вредност треба да е поголема или еднаква на {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Оваа вредност треба да е идентична на {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Оваа вредност треба да е помала од {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + Оваа вредност треба да е помала или еднаква на {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Оваа вредност треба да не биде еднаква на {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Оваа вредност треба да не биде идентична со {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Соодносот на сликата е преголем ({{ ratio }}).Максималниот дозволен сооднос е {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Соодносот на сликата е премал ({{ ratio }}). Минималниот дозволен сооднос е {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Сликата е квадратна ({{ width }}x{{ height }}px). Квадратни слики не се дозволени. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Сликата е ориентирана кон пејзаж ({{ width }}x{{ height }}px). Сликите ориентирани кон пејзаж не се дозволени. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Сликата е ориентирана кон портрет ({{ width }}x{{ height }}px). Сликите ориентирани кон портрет не се дозволени. + + + An empty file is not allowed. + Празна датотека не е дозволена. + + + The host could not be resolved. + Хостот е недостапен. + + + This value does not match the expected {{ charset }} charset. + Оваа вредност не се совпаѓа со очекуваниот {{ charset }} сет на карактери (charset). + + + This is not a valid Business Identifier Code (BIC). + Ова не е валиден бизнис идентификациски код (BIC). + + + Error + Грешка + + + This is not a valid UUID. + Ова не е валиден универзален уникатен идентификатор (UUID). + + + This value should be a multiple of {{ compared_value }}. + Оваа вредност треба да биде повеќекратна од {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Овој бизнис идентификациски код (BIC) не е поврзан со IBAN {{ iban }}. + + + This value should be valid JSON. + Оваа вредност треба да биде валиден JSON. + + + This collection should contain only unique elements. + Оваа колекција треба да содржи само уникатни елементи. + + + This value should be positive. + Оваа вредност треба да биде позитивна. + + + This value should be either positive or zero. + Оваа вредност треба да биде или позитивна или нула. + + + This value should be negative. + Оваа вредност треба да биде негативна. + + + This value should be either negative or zero. + Оваа вредност треба да биде или негативна или нула. + + + This value is not a valid timezone. + Оваа вредност не е валидна временска зона. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + Оваа лозинка е компромитирана и не смее да биде користена. Ве молиме употребете друга лозинка. + + + This value should be between {{ min }} and {{ max }}. + Оваа вредност треба да е помеѓу {{ min }} и {{ max }}. + + + This value is not a valid hostname. + Оваа вредност не е валидно име за мрежниот сметач (hostname). + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Бројот на елементи во оваа колекција треба да биде повеќекратен од {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Оваа вредност треба да задоволува најмалку едно од следните ограничувања: + + + Each element of this collection should satisfy its own set of constraints. + Секој елемент од оваа колекција треба да задоволува сопствен сет на ограничувања. + + + This value is not a valid International Securities Identification Number (ISIN). + Оваа вредност не е важечки меѓународен идентификациски број за хартии од вредност (ISIN). + + + This value should be a valid expression. + Оваа вредност треба да биде валиден израз. + + + This value is not a valid CSS color. + Оваа вредност не е валидна CSS боја. + + + This value is not a valid CIDR notation. + Оваа вредност не е валидна CIDR ознака. + + + The value of the netmask should be between {{ min }} and {{ max }}. + Вредноста на мрежната маска (netmask) треба да биде помеѓу {{ min }} и {{ max }}. + + + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + Името на датотеката е предолго. Треба да има {{ filename_max_length }} карактер има помалку.|Името на датотеката е предолго. Треба да има {{ filename_max_length }} карактери или помалку. + + + The password strength is too low. Please use a stronger password. + Оваа лозинка е премногу едноставна. Ве молиме користете посилна лозинка. + + + This value contains characters that are not allowed by the current restriction-level. + Оваа вредност содржи карактери кои не се дозволени од тековното ниво на ограничување. + + + Using invisible characters is not allowed. + Користењето на невидливи знаци не е дозволено. + + + Mixing numbers from different scripts is not allowed. + Не е дозволено мешање на броеви од различни скрипти. + + + Using hidden overlay characters is not allowed. + Не е дозволено користење на скриени знаци за преклопување. + + + + From 578a15200b33c21d161b40261b0a8ef74119008c Mon Sep 17 00:00:00 2001 From: Markus Fasselt Date: Thu, 7 Sep 2023 21:58:43 +0200 Subject: [PATCH 07/23] [Cache] fix using multiple Redis Sentinel hosts when the first one is not resolvable --- src/Symfony/Component/Cache/Traits/RedisTrait.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 220e65e744d43..0e7740e628369 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -217,8 +217,11 @@ public static function createConnection(string $dsn, array $options = []) } $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra); - if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { - [$host, $port] = $address; + try { + if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { + [$host, $port] = $address; + } + } catch (\RedisException $e) { } } while (++$hostIndex < \count($hosts) && !$address); From c557647ede0bae07098067bb25c2eaaf49277a5b Mon Sep 17 00:00:00 2001 From: Uladzimir Tsykun Date: Mon, 11 Sep 2023 18:39:34 +0200 Subject: [PATCH 08/23] Make tests green again --- .../Component/VarDumper/Tests/Dumper/CliDumperTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 7809fcdb9f523..1c7dcc07ff4e9 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -553,6 +553,10 @@ public function testDumpArrayWithColor($value, $flags, $expectedOut) public function testCollapse() { + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->markTestSkipped('This test cannot be run on Windows.'); + } + $stub = new Stub(); $stub->type = Stub::TYPE_OBJECT; $stub->class = 'stdClass'; From 338e2da2d2e57cbbafac2d68713e529bce918572 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 12 Sep 2023 09:44:46 +0200 Subject: [PATCH 09/23] chore: fix ci deprecations --- .github/workflows/integration-tests.yml | 4 ++-- .github/workflows/intl-data-tests.yml | 2 +- .github/workflows/package-tests.yml | 2 +- .github/workflows/phpunit-bridge.yml | 2 +- .github/workflows/psalm.yml | 4 ++-- .github/workflows/unit-tests.yml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index dc80c6fb28ce6..6e785c383a0f1 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -107,7 +107,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install system dependencies run: | @@ -191,7 +191,7 @@ jobs: # sudo rm -rf .phpunit # [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit - - uses: marceloprado/has-changed-path@v1 + - uses: marceloprado/has-changed-path@v1.0.1 id: changed-translation-files with: paths: src/**/Resources/translations/*.xlf diff --git a/.github/workflows/intl-data-tests.yml b/.github/workflows/intl-data-tests.yml index 8db09e52912af..ac2b8d41237ad 100644 --- a/.github/workflows/intl-data-tests.yml +++ b/.github/workflows/intl-data-tests.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install system dependencies run: | diff --git a/.github/workflows/package-tests.yml b/.github/workflows/package-tests.yml index a6955dbead472..1840d30f091a6 100644 --- a/.github/workflows/package-tests.yml +++ b/.github/workflows/package-tests.yml @@ -14,7 +14,7 @@ jobs: runs-on: Ubuntu-20.04 steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Fetch branch from where the PR started run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index 2229bbc866655..f63c02bc31925 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 219b8677325d0..27b51d5af7428 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -30,12 +30,12 @@ jobs: coverage: none - name: Checkout target branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.base_ref }} - name: Checkout PR - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install dependencies run: | diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 199887754e036..94b69e6c9891c 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -40,7 +40,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 From 4312e96c28eec5ba8825d71f8b751aa4e37f7df5 Mon Sep 17 00:00:00 2001 From: soyuka Date: Sun, 27 Aug 2023 12:21:37 +0200 Subject: [PATCH 10/23] [FrameworkBundle] no serializer mapping cache in debug mode without enable_annotations There's no reason we should disable the cache only without `enable_annotations`, when working only with attributes, in debug mode the cache is enabled which is why we often need to clear cache when changing a serialized object to get the changes. --- .../DependencyInjection/FrameworkExtension.php | 7 ++++--- .../DependencyInjection/FrameworkExtensionTestCase.php | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 206bda1039a44..da60eeabb41c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1790,14 +1790,15 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->removeDefinition('serializer.normalizer.mime_message'); } + if ($container->getParameter('kernel.debug')) { + $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); + } + $serializerLoaders = []; if (isset($config['enable_annotations']) && $config['enable_annotations']) { if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { throw new \LogicException('"enable_annotations" on the serializer cannot be set as the PHP version is lower than 8 and Annotations support is disabled. Consider upgrading PHP.'); } - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); - } $annotationLoader = new Definition( 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index d1a0f52eac4fb..f5429d617b1a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1530,6 +1530,12 @@ public function testSerializerCacheActivated() public function testSerializerCacheUsedWithoutAnnotationsAndMappingFiles() { $container = $this->createContainerFromFile('serializer_mapping_without_annotations', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]); + $this->assertFalse($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); + } + + public function testSerializerCacheUsedWithoutAnnotationsAndMappingFilesNoDebug() + { + $container = $this->createContainerFromFile('serializer_mapping_without_annotations', ['kernel.debug' => false, 'kernel.container_class' => __CLASS__]); $this->assertTrue($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); } From 4264558fea9705c22c14fce0374db49efe665a09 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 13 Sep 2023 13:47:37 +0200 Subject: [PATCH 11/23] [String] Update wcswidth data with Unicode 15.1 --- .../String/Resources/WcswidthDataGenerator.php | 2 +- .../Resources/data/wcswidth_table_wide.php | 18 +++++++++++++++--- .../Resources/data/wcswidth_table_zero.php | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php b/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php index 69d32e292a990..7443d051ee14d 100644 --- a/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php +++ b/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php @@ -46,7 +46,7 @@ private function writeWideWidthData(): void $version = $matches[1]; - if (!preg_match_all('/^([A-H\d]{4,})(?:\.\.([A-H\d]{4,}))?;[W|F]/m', $content, $matches, \PREG_SET_ORDER)) { + if (!preg_match_all('/^([A-H\d]{4,})(?:\.\.([A-H\d]{4,}))? +; [W|F]/m', $content, $matches, \PREG_SET_ORDER)) { throw new RuntimeException('The wide width pattern did not match anything.'); } diff --git a/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php b/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php index 5a647e67bf30f..8314c8fd504c2 100644 --- a/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php +++ b/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php @@ -3,8 +3,8 @@ /* * This file has been auto-generated by the Symfony String Component for internal use. * - * Unicode version: 15.0.0 - * Date: 2022-10-05T17:16:36+02:00 + * Unicode version: 15.1.0 + * Date: 2023-09-13T11:47:12+00:00 */ return [ @@ -166,7 +166,7 @@ ], [ 12272, - 12283, + 12287, ], [ 12288, @@ -396,6 +396,10 @@ 12736, 12771, ], + [ + 12783, + 12783, + ], [ 12784, 12799, @@ -1110,6 +1114,14 @@ ], [ 191457, + 191471, + ], + [ + 191472, + 192093, + ], + [ + 192094, 194559, ], [ diff --git a/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php b/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php index 9ae7330325291..e5b26a21515ea 100644 --- a/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php +++ b/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php @@ -3,8 +3,8 @@ /* * This file has been auto-generated by the Symfony String Component for internal use. * - * Unicode version: 15.0.0 - * Date: 2022-10-05T17:16:37+02:00 + * Unicode version: 15.1.0 + * Date: 2023-09-13T11:47:13+00:00 */ return [ From fdef0abb6e098430320cad11e86ee6f9d569a5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20H=C3=A9lias?= Date: Thu, 14 Sep 2023 22:49:15 +0200 Subject: [PATCH 12/23] [HttpClient] Fix TraceableResponse if response has no destruct method --- .../Component/HttpClient/Response/TraceableResponse.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php index d656c0a5f94d7..3bf1571fda1fb 100644 --- a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php +++ b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php @@ -57,7 +57,9 @@ public function __wakeup() public function __destruct() { try { - $this->response->__destruct(); + if (method_exists($this->response, '__destruct')) { + $this->response->__destruct(); + } } finally { if ($this->event && $this->event->isStarted()) { $this->event->stop(); From 35341187ba3ba6078552ff4e308b6a470b644491 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sat, 16 Sep 2023 13:22:53 +0200 Subject: [PATCH 13/23] [Translator] Fix support for `default_path` in XML --- .../FrameworkBundle/Resources/config/schema/symfony-1.0.xsd | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 29f64dad9bed9..faee50e2528a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -191,6 +191,7 @@ + From 4d65f302bf0928fe2140f565091949ce986c4dc3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 18 Sep 2023 17:40:31 +0200 Subject: [PATCH 14/23] [SecurityBundle][PasswordHasher] Fix password migration with custom hasher service with security bundle config --- .../DependencyInjection/SecurityExtension.php | 5 +- .../SecurityExtensionTest.php | 27 ++++++++++ .../Hasher/PasswordHasherFactory.php | 50 ++++++++++++------- .../Hasher/PasswordHasherFactoryTest.php | 33 ++++++++++++ 4 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index d64b2c38ac7e7..c165024b68d0d 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -848,7 +848,10 @@ private function createHasher(array $config) { // a custom hasher service if (isset($config['id'])) { - return new Reference($config['id']); + return $config['migrate_from'] ?? false ? [ + 'instance' => new Reference($config['id']), + 'migrate_from' => $config['migrate_from'], + ] : new Reference($config['id']); } if ($config['migrate_from'] ?? false) { diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 71ca327ca40c6..eef68e4c3de46 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -881,6 +881,33 @@ public function testLegacyAuthorizationManagerSignature() $this->assertEquals('%security.access.always_authenticate_before_granting%', (string) $args[3]); } + public function testCustomHasherWithMigrateFrom() + { + $container = $this->getRawContainer(); + + $container->loadFromExtension('security', [ + 'enable_authenticator_manager' => true, + 'password_hashers' => [ + 'legacy' => 'md5', + 'App\User' => [ + 'id' => 'App\Security\CustomHasher', + 'migrate_from' => 'legacy', + ], + ], + 'firewalls' => ['main' => ['http_basic' => true]], + ]); + + $container->compile(); + + $hashersMap = $container->getDefinition('security.password_hasher_factory')->getArgument(0); + + $this->assertArrayHasKey('App\User', $hashersMap); + $this->assertEquals($hashersMap['App\User'], [ + 'instance' => new Reference('App\Security\CustomHasher'), + 'migrate_from' => ['legacy'], + ]); + } + protected function getRawContainer() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php b/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php index dd7e015c1ecd2..116301c04a441 100644 --- a/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php +++ b/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php @@ -71,6 +71,14 @@ public function getPasswordHasher($user): PasswordHasherInterface */ private function createHasher(array $config, bool $isExtra = false): PasswordHasherInterface { + if (isset($config['instance'])) { + if (!isset($config['migrate_from'])) { + return $config['instance']; + } + + $config = $this->getMigratingPasswordConfig($config); + } + if (isset($config['algorithm'])) { $rawConfig = $config; $config = $this->getHasherConfigFromAlgorithm($config); @@ -142,24 +150,8 @@ private function getHasherConfigFromAlgorithm(array $config): array ]; } - if ($frompasswordHashers = ($config['migrate_from'] ?? false)) { - unset($config['migrate_from']); - $hasherChain = [$this->createHasher($config, true)]; - - foreach ($frompasswordHashers as $name) { - if (isset($this->passwordHashers[$name])) { - $hasher = $this->createHasherUsingAdapter($name); - } else { - $hasher = $this->createHasher(['algorithm' => $name], true); - } - - $hasherChain[] = $hasher; - } - - return [ - 'class' => MigratingPasswordHasher::class, - 'arguments' => $hasherChain, - ]; + if ($config['migrate_from'] ?? false) { + return $this->getMigratingPasswordConfig($config); } switch ($config['algorithm']) { @@ -239,4 +231,26 @@ private function getHasherConfigFromAlgorithm(array $config): array ], ]; } + + private function getMigratingPasswordConfig(array $config): array + { + $frompasswordHashers = $config['migrate_from']; + unset($config['migrate_from']); + $hasherChain = [$this->createHasher($config, true)]; + + foreach ($frompasswordHashers as $name) { + if ($this->passwordHashers[$name] ?? false) { + $hasher = $this->createHasherUsingAdapter($name); + } else { + $hasher = $this->createHasher(['algorithm' => $name], true); + } + + $hasherChain[] = $hasher; + } + + return [ + 'class' => MigratingPasswordHasher::class, + 'arguments' => $hasherChain, + ]; + } } diff --git a/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php b/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php index 1f24a0d3cace2..1b97eedcdac48 100644 --- a/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php +++ b/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php @@ -49,6 +49,17 @@ public function testGetHasherWithService() $this->assertEquals($expectedHasher->hash('foo', ''), $hasher->hash('foo', '')); } + public function testGetHasherWithInstance() + { + $factory = new PasswordHasherFactory([ + PasswordAuthenticatedUserInterface::class => ['instance' => new MessageDigestPasswordHasher('sha1')], + ]); + + $hasher = $factory->getPasswordHasher($this->createMock(PasswordAuthenticatedUserInterface::class)); + $expectedHasher = new MessageDigestPasswordHasher('sha1'); + $this->assertEquals($expectedHasher->hash('foo', ''), $hasher->hash('foo', '')); + } + public function testGetHasherWithClassName() { $factory = new PasswordHasherFactory([ @@ -163,6 +174,28 @@ public function testMigrateFrom() $this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null)); } + public function testMigrateFromWithCustomInstance() + { + if (!SodiumPasswordHasher::isSupported()) { + $this->markTestSkipped('Sodium is not available'); + } + + $sodium = new SodiumPasswordHasher(); + + $factory = new PasswordHasherFactory([ + 'digest_hasher' => $digest = new MessageDigestPasswordHasher('sha256'), + SomeUser::class => ['instance' => $sodium, 'migrate_from' => ['bcrypt', 'digest_hasher']], + ]); + + $hasher = $factory->getPasswordHasher(SomeUser::class); + $this->assertInstanceOf(MigratingPasswordHasher::class, $hasher); + + $this->assertTrue($hasher->verify((new SodiumPasswordHasher())->hash('foo', null), 'foo', null)); + $this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, null, \PASSWORD_BCRYPT))->hash('foo', null), 'foo', null)); + $this->assertTrue($hasher->verify($digest->hash('foo', null), 'foo', null)); + $this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null)); + } + /** * @group legacy */ From 5ad2b5a6022d3aa51f52a2dae7d687ae57ce43b1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 18 Sep 2023 17:58:13 +0200 Subject: [PATCH 15/23] Update the PR template --- .github/PULL_REQUEST_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0dfc06eb7c16b..f56136de940d3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,14 +1,14 @@ | Q | A | ------------- | --- -| Branch? | 6.4 for features / 5.4, or 6.3 for bug fixes +| Branch? | 6.4 for features / 5.4 or 6.3 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no | Tickets | Fix #... | License | MIT -| Doc PR | symfony/symfony-docs#... +

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy