Merge branch '4.4' into 5.1
* 4.4: Fix transient tests Fix class resolution in Doctrine EventListenerPass [Serializer] Fix tests marked as incomplete [Translator] fix handling plural for floating numbers fix redis messenger options with dsn Update ConsoleEvents.php allow Doctrine persistence 2 too [Messenger] Fix transporting non-UTF8 payloads by encoding them using base 64 add doctrine/persistence as a dev requirement Exclude non-initialized properties accessed with getters
This commit is contained in:
commit
abf8010eae
@ -85,7 +85,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
|
||||
|
||||
if (!isset($managerDefs[$con])) {
|
||||
$managerDef = $parentDef = $this->getEventManagerDef($container, $con);
|
||||
while ($parentDef instanceof ChildDefinition) {
|
||||
while (!$parentDef->getClass() && $parentDef instanceof ChildDefinition) {
|
||||
$parentDef = $container->findDefinition($parentDef->getParent());
|
||||
}
|
||||
$managerClass = $container->getParameterBag()->resolveValue($parentDef->getClass());
|
||||
|
@ -157,9 +157,6 @@ class AbstractControllerTest extends TestCase
|
||||
$controller->getUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $token
|
||||
*/
|
||||
private function getContainerWithTokenStorage($token = null): Container
|
||||
{
|
||||
$tokenStorage = $this->getMockBuilder(\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage::class)->getMock();
|
||||
@ -484,10 +481,10 @@ class AbstractControllerTest extends TestCase
|
||||
public function testRedirect()
|
||||
{
|
||||
$controller = $this->createController();
|
||||
$response = $controller->redirect('http://dunglas.fr', 301);
|
||||
$response = $controller->redirect('https://dunglas.fr', 301);
|
||||
|
||||
$this->assertInstanceOf(\Symfony\Component\HttpFoundation\RedirectResponse::class, $response);
|
||||
$this->assertSame('http://dunglas.fr', $response->getTargetUrl());
|
||||
$this->assertSame('https://dunglas.fr', $response->getTargetUrl());
|
||||
$this->assertSame(301, $response->getStatusCode());
|
||||
}
|
||||
|
||||
@ -532,7 +529,7 @@ class AbstractControllerTest extends TestCase
|
||||
|
||||
public function testGetDoctrine()
|
||||
{
|
||||
$doctrine = $this->getMockBuilder(\Doctrine\Persistence\ManagerRegistry::class)->getMock();
|
||||
$doctrine = $this->createMock(ManagerRegistry::class);
|
||||
|
||||
$container = new Container();
|
||||
$container->set('doctrine', $doctrine);
|
||||
|
@ -35,6 +35,7 @@
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.10.4",
|
||||
"doctrine/cache": "~1.0",
|
||||
"doctrine/persistence": "^1.3|^2.0",
|
||||
"symfony/asset": "^5.1",
|
||||
"symfony/browser-kit": "^4.4|^5.0",
|
||||
"symfony/console": "^4.4|^5.0",
|
||||
|
@ -21,7 +21,7 @@ final class ConsoleEvents
|
||||
/**
|
||||
* The COMMAND event allows you to attach listeners before any command is
|
||||
* executed by the console. It also allows you to modify the command, input and output
|
||||
* before they are handled to the command.
|
||||
* before they are handed to the command.
|
||||
*
|
||||
* @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
|
||||
*/
|
||||
|
@ -23,6 +23,9 @@ use Symfony\Component\HttpKernel\HttpKernel;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* @group time-sensitive
|
||||
*/
|
||||
class InlineFragmentRendererTest extends TestCase
|
||||
{
|
||||
public function testRender()
|
||||
@ -253,8 +256,7 @@ class InlineFragmentRendererTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Kernel expecting a request equals to $request
|
||||
* Allows delta in comparison in case REQUEST_TIME changed by 1 second.
|
||||
* Creates a Kernel expecting a request equals to $request.
|
||||
*/
|
||||
private function getKernelExpectingRequest(Request $request, $strict = false)
|
||||
{
|
||||
@ -262,7 +264,7 @@ class InlineFragmentRendererTest extends TestCase
|
||||
$kernel
|
||||
->expects($this->once())
|
||||
->method('handle')
|
||||
->with($this->equalTo($request, 1))
|
||||
->with($request)
|
||||
->willReturn(new Response('foo'));
|
||||
|
||||
return $kernel;
|
||||
|
@ -121,6 +121,19 @@ class ConnectionTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromDsnWithMixDsnQueryOptions()
|
||||
{
|
||||
$this->assertEquals(
|
||||
Connection::fromDsn('redis://localhost/queue/group1?serializer=2', ['consumer' => 'specific-consumer']),
|
||||
Connection::fromDsn('redis://localhost/queue/group1/specific-consumer?serializer=2')
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
Connection::fromDsn('redis://localhost/queue/group1/consumer1', ['consumer' => 'specific-consumer']),
|
||||
Connection::fromDsn('redis://localhost/queue/group1/consumer1')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
|
@ -105,7 +105,8 @@ class Connection
|
||||
throw new InvalidArgumentException(sprintf('The given Redis DSN "%s" is invalid.', $dsn));
|
||||
}
|
||||
if (isset($parsedUrl['query'])) {
|
||||
parse_str($parsedUrl['query'], $redisOptions);
|
||||
parse_str($parsedUrl['query'], $dsnOptions);
|
||||
$redisOptions = array_merge($redisOptions, $dsnOptions);
|
||||
}
|
||||
|
||||
self::validateOptions($redisOptions);
|
||||
|
@ -76,6 +76,17 @@ class PhpSerializerTest extends TestCase
|
||||
$encoded = $serializer->encode($envelope);
|
||||
$this->assertStringNotContainsString('DummyPhpSerializerNonSendableStamp', $encoded['body']);
|
||||
}
|
||||
|
||||
public function testNonUtf8IsBase64Encoded()
|
||||
{
|
||||
$serializer = new PhpSerializer();
|
||||
|
||||
$envelope = new Envelope(new DummyMessage("\xE9"));
|
||||
|
||||
$encoded = $serializer->encode($envelope);
|
||||
$this->assertTrue((bool) preg_match('//u', $encoded['body']), 'Encodes non-UTF8 payloads');
|
||||
$this->assertEquals($envelope, $serializer->decode($encoded));
|
||||
}
|
||||
}
|
||||
|
||||
class DummyPhpSerializerNonSendableStamp implements NonSendableStampInterface
|
||||
|
@ -29,6 +29,10 @@ class PhpSerializer implements SerializerInterface
|
||||
throw new MessageDecodingFailedException('Encoded envelope should have at least a "body".');
|
||||
}
|
||||
|
||||
if (false === strpos($encodedEnvelope['body'], '}', -1)) {
|
||||
$encodedEnvelope['body'] = base64_decode($encodedEnvelope['body']);
|
||||
}
|
||||
|
||||
$serializeEnvelope = stripslashes($encodedEnvelope['body']);
|
||||
|
||||
return $this->safelyUnserialize($serializeEnvelope);
|
||||
@ -43,6 +47,10 @@ class PhpSerializer implements SerializerInterface
|
||||
|
||||
$body = addslashes(serialize($envelope));
|
||||
|
||||
if (!preg_match('//u', $body)) {
|
||||
$body = base64_encode($body);
|
||||
}
|
||||
|
||||
return [
|
||||
'body' => $body,
|
||||
];
|
||||
|
@ -110,10 +110,20 @@ class ObjectNormalizer extends AbstractObjectNormalizer
|
||||
$checkPropertyInitialization = \PHP_VERSION_ID >= 70400;
|
||||
|
||||
// properties
|
||||
foreach ($reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflProperty) {
|
||||
if ($checkPropertyInitialization && !$reflProperty->isInitialized($object)) {
|
||||
foreach ($reflClass->getProperties() as $reflProperty) {
|
||||
if ($checkPropertyInitialization) {
|
||||
$isPublic = $reflProperty->isPublic();
|
||||
if (!$isPublic) {
|
||||
$reflProperty->setAccessible(true);
|
||||
}
|
||||
if (!$reflProperty->isInitialized($object)) {
|
||||
unset($attributes[$reflProperty->name]);
|
||||
continue;
|
||||
}
|
||||
if (!$isPublic) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
|
||||
continue;
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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 Alexander Borisov <boshurik@gmail.com>
|
||||
*/
|
||||
final class Php74DummyPrivate
|
||||
{
|
||||
private string $uninitializedProperty;
|
||||
|
||||
private string $initializedProperty = 'defaultValue';
|
||||
|
||||
public function getUninitializedProperty(): string
|
||||
{
|
||||
return $this->uninitializedProperty;
|
||||
}
|
||||
|
||||
public function getInitializedProperty(): string
|
||||
{
|
||||
return $this->initializedProperty;
|
||||
}
|
||||
}
|
@ -38,8 +38,6 @@ trait IgnoredAttributesTestTrait
|
||||
$normalizer->normalize($objectOuter, null, $context)
|
||||
);
|
||||
|
||||
$this->markTestIncomplete('AbstractObjectNormalizer::getAttributes caches attributes by class instead of by class+context, reusing the normalizer with different config therefore fails. This is being fixed in https://github.com/symfony/symfony/pull/30907');
|
||||
|
||||
$context = ['ignored_attributes' => ['foo', 'inner']];
|
||||
$this->assertEquals(
|
||||
[
|
||||
|
@ -32,6 +32,7 @@ use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\OtherSerializedNameDummy;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\Php74Dummy;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\Php74DummyPrivate;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder;
|
||||
use Symfony\Component\Serializer\Tests\Normalizer\Features\AttributesTestTrait;
|
||||
use Symfony\Component\Serializer\Tests\Normalizer\Features\CallbacksTestTrait;
|
||||
@ -124,6 +125,18 @@ class ObjectNormalizerTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 7.4
|
||||
*/
|
||||
public function testNormalizeObjectWithUninitializedPrivateProperties()
|
||||
{
|
||||
$obj = new Php74DummyPrivate();
|
||||
$this->assertEquals(
|
||||
['initializedProperty' => 'defaultValue'],
|
||||
$this->normalizer->normalize($obj, 'any')
|
||||
);
|
||||
}
|
||||
|
||||
public function testDenormalize()
|
||||
{
|
||||
$obj = $this->normalizer->denormalize(
|
||||
|
220
src/Symfony/Component/Translation/PluralizationRules.php
Normal file
220
src/Symfony/Component/Translation/PluralizationRules.php
Normal file
@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
/**
|
||||
* Returns the plural rules for a given locale.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use IdentityTranslator instead
|
||||
*/
|
||||
class PluralizationRules
|
||||
{
|
||||
private static $rules = [];
|
||||
|
||||
/**
|
||||
* Returns the plural position to use for the given locale and number.
|
||||
*
|
||||
* @param float $number The number
|
||||
* @param string $locale The locale
|
||||
*
|
||||
* @return int The plural position
|
||||
*/
|
||||
public static function get($number, $locale/*, bool $triggerDeprecation = true*/)
|
||||
{
|
||||
$number = abs($number);
|
||||
|
||||
if (3 > \func_num_args() || func_get_arg(2)) {
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', __CLASS__), \E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ('pt_BR' === $locale) {
|
||||
// temporary set a locale for brazilian
|
||||
$locale = 'xbr';
|
||||
}
|
||||
|
||||
if (\strlen($locale) > 3) {
|
||||
$locale = substr($locale, 0, -\strlen(strrchr($locale, '_')));
|
||||
}
|
||||
|
||||
if (isset(self::$rules[$locale])) {
|
||||
$return = self::$rules[$locale]($number);
|
||||
|
||||
if (!\is_int($return) || $return < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The plural rules are derived from code of the Zend Framework (2010-09-25),
|
||||
* which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
|
||||
* Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
*/
|
||||
switch ($locale) {
|
||||
case 'az':
|
||||
case 'bo':
|
||||
case 'dz':
|
||||
case 'id':
|
||||
case 'ja':
|
||||
case 'jv':
|
||||
case 'ka':
|
||||
case 'km':
|
||||
case 'kn':
|
||||
case 'ko':
|
||||
case 'ms':
|
||||
case 'th':
|
||||
case 'tr':
|
||||
case 'vi':
|
||||
case 'zh':
|
||||
return 0;
|
||||
|
||||
case 'af':
|
||||
case 'bn':
|
||||
case 'bg':
|
||||
case 'ca':
|
||||
case 'da':
|
||||
case 'de':
|
||||
case 'el':
|
||||
case 'en':
|
||||
case 'eo':
|
||||
case 'es':
|
||||
case 'et':
|
||||
case 'eu':
|
||||
case 'fa':
|
||||
case 'fi':
|
||||
case 'fo':
|
||||
case 'fur':
|
||||
case 'fy':
|
||||
case 'gl':
|
||||
case 'gu':
|
||||
case 'ha':
|
||||
case 'he':
|
||||
case 'hu':
|
||||
case 'is':
|
||||
case 'it':
|
||||
case 'ku':
|
||||
case 'lb':
|
||||
case 'ml':
|
||||
case 'mn':
|
||||
case 'mr':
|
||||
case 'nah':
|
||||
case 'nb':
|
||||
case 'ne':
|
||||
case 'nl':
|
||||
case 'nn':
|
||||
case 'no':
|
||||
case 'oc':
|
||||
case 'om':
|
||||
case 'or':
|
||||
case 'pa':
|
||||
case 'pap':
|
||||
case 'ps':
|
||||
case 'pt':
|
||||
case 'so':
|
||||
case 'sq':
|
||||
case 'sv':
|
||||
case 'sw':
|
||||
case 'ta':
|
||||
case 'te':
|
||||
case 'tk':
|
||||
case 'ur':
|
||||
case 'zu':
|
||||
return (1 == $number) ? 0 : 1;
|
||||
|
||||
case 'am':
|
||||
case 'bh':
|
||||
case 'fil':
|
||||
case 'fr':
|
||||
case 'gun':
|
||||
case 'hi':
|
||||
case 'hy':
|
||||
case 'ln':
|
||||
case 'mg':
|
||||
case 'nso':
|
||||
case 'xbr':
|
||||
case 'ti':
|
||||
case 'wa':
|
||||
return ($number < 2) ? 0 : 1;
|
||||
|
||||
case 'be':
|
||||
case 'bs':
|
||||
case 'hr':
|
||||
case 'ru':
|
||||
case 'sh':
|
||||
case 'sr':
|
||||
case 'uk':
|
||||
return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
|
||||
|
||||
case 'cs':
|
||||
case 'sk':
|
||||
return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
|
||||
|
||||
case 'ga':
|
||||
return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2);
|
||||
|
||||
case 'lt':
|
||||
return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
|
||||
|
||||
case 'sl':
|
||||
return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3));
|
||||
|
||||
case 'mk':
|
||||
return (1 == $number % 10) ? 0 : 1;
|
||||
|
||||
case 'mt':
|
||||
return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
|
||||
|
||||
case 'lv':
|
||||
return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2);
|
||||
|
||||
case 'pl':
|
||||
return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
|
||||
|
||||
case 'cy':
|
||||
return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3));
|
||||
|
||||
case 'ro':
|
||||
return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
|
||||
|
||||
case 'ar':
|
||||
return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default plural rule for a given locale.
|
||||
*
|
||||
* @param callable $rule A PHP callable
|
||||
* @param string $locale The locale
|
||||
*/
|
||||
public static function set(callable $rule, $locale)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', __CLASS__), \E_USER_DEPRECATED);
|
||||
|
||||
if ('pt_BR' === $locale) {
|
||||
// temporary set a locale for brazilian
|
||||
$locale = 'xbr';
|
||||
}
|
||||
|
||||
if (\strlen($locale) > 3) {
|
||||
$locale = substr($locale, 0, -\strlen(strrchr($locale, '_')));
|
||||
}
|
||||
|
||||
self::$rules[$locale] = $rule;
|
||||
}
|
||||
}
|
@ -142,11 +142,11 @@ class TranslatorTest extends TestCase
|
||||
/**
|
||||
* @dataProvider getChooseTests
|
||||
*/
|
||||
public function testChoose($expected, $id, $number)
|
||||
public function testChoose($expected, $id, $number, $locale = null)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
|
||||
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number], null, $locale));
|
||||
}
|
||||
|
||||
public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
|
||||
@ -255,6 +255,18 @@ class TranslatorTest extends TestCase
|
||||
['', '|', 1],
|
||||
// Empty plural set (3 plural forms) from a .PO file
|
||||
['', '||', 1],
|
||||
|
||||
// Floating values
|
||||
['1.5 liters', '%count% liter|%count% liters', 1.5],
|
||||
['1.5 litre', '%count% litre|%count% litres', 1.5, 'fr'],
|
||||
|
||||
// Negative values
|
||||
['-1 degree', '%count% degree|%count% degrees', -1],
|
||||
['-1 degré', '%count% degré|%count% degrés', -1],
|
||||
['-1.5 degrees', '%count% degree|%count% degrees', -1.5],
|
||||
['-1.5 degré', '%count% degré|%count% degrés', -1.5, 'fr'],
|
||||
['-2 degrees', '%count% degree|%count% degrees', -2],
|
||||
['-2 degrés', '%count% degré|%count% degrés', -2],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -136,8 +136,10 @@ EOF;
|
||||
* which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
|
||||
* Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
*/
|
||||
private function getPluralizationRule(int $number, string $locale): int
|
||||
private function getPluralizationRule(float $number, string $locale): int
|
||||
{
|
||||
$number = abs($number);
|
||||
|
||||
switch ('pt_BR' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
|
||||
case 'af':
|
||||
case 'bn':
|
||||
@ -205,7 +207,7 @@ EOF;
|
||||
case 'pt_BR':
|
||||
case 'ti':
|
||||
case 'wa':
|
||||
return ((0 == $number) || (1 == $number)) ? 0 : 1;
|
||||
return ($number < 2) ? 0 : 1;
|
||||
|
||||
case 'be':
|
||||
case 'bs':
|
||||
|
Reference in New Issue
Block a user