diff --git a/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php b/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php
index 0679d2bf6d..7c111a8ba3 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php
+++ b/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php
@@ -124,7 +124,7 @@ class ContentSecurityPolicyHandler
$headers = $this->getCspHeaders($response);
foreach ($headers as $header => $directives) {
- foreach (['script-src' => 'csp_script_nonce', 'style-src' => 'csp_style_nonce'] as $type => $tokenName) {
+ foreach (['script-src' => 'csp_script_nonce', 'script-src-elem' => 'csp_script_nonce', 'style-src' => 'csp_style_nonce', 'style-src-elem' => 'csp_style_nonce'] as $type => $tokenName) {
if ($this->authorizesInline($directives, $type)) {
continue;
}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php
index acccc7cbfb..349db2aaf7 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php
+++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php
@@ -41,7 +41,7 @@ class ContentSecurityPolicyHandlerTest extends TestCase
$this->assertFalse($response->headers->has('X-SymfonyProfiler-Style-Nonce'));
foreach ($expectedCsp as $header => $value) {
- $this->assertSame($value, $response->headers->get($header));
+ $this->assertSame($value, $response->headers->get($header), $header);
}
}
@@ -131,7 +131,7 @@ class ContentSecurityPolicyHandlerTest extends TestCase
['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce],
$this->createRequest(),
$this->createResponse(['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'']),
- ['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; style-src \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; style-src \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null],
+ ['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src-elem \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src-elem \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null],
],
[
$nonce,
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
index 54933d953a..b6cce8165e 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
@@ -215,8 +215,10 @@ class NativeSessionStorage implements SessionStorageInterface
return false;
}
- if (null !== $lifetime) {
+ if (null !== $lifetime && $lifetime != ini_get('session.cookie_lifetime')) {
+ $this->save();
ini_set('session.cookie_lifetime', $lifetime);
+ $this->start();
}
if ($destroy) {
@@ -225,10 +227,6 @@ class NativeSessionStorage implements SessionStorageInterface
$isRegenerated = session_regenerate_id($destroy);
- // The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it.
- // @see https://bugs.php.net/70013
- $this->loadSession();
-
if (null !== $this->emulateSameSite) {
$originalCookie = SessionUtils::popSessionCookie(session_name(), session_id());
if (null !== $originalCookie) {
diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php
index ace6249394..4cb0b2dab3 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php
@@ -120,6 +120,19 @@ class NativeSessionStorageTest extends TestCase
$this->assertEquals(11, $storage->getBag('attributes')->get('legs'));
}
+ public function testRegenerateWithCustomLifetime()
+ {
+ $storage = $this->getStorage();
+ $storage->start();
+ $id = $storage->getId();
+ $lifetime = 999999;
+ $storage->getBag('attributes')->set('legs', 11);
+ $storage->regenerate(false, $lifetime);
+ $this->assertNotEquals($id, $storage->getId());
+ $this->assertEquals(11, $storage->getBag('attributes')->get('legs'));
+ $this->assertEquals($lifetime, ini_get('session.cookie_lifetime'));
+ }
+
public function testSessionGlobalIsUpToDateAfterIdRegeneration()
{
$storage = $this->getStorage();
diff --git a/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php b/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php
index d58b120457..433d9a8a26 100644
--- a/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php
+++ b/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php
@@ -44,7 +44,7 @@ class OptionsResolverIntrospectorTest extends TestCase
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
- $this->assertSame('bar', $debug->getDefault($option));
+ $debug->getDefault($option);
}
public function testGetDefaultThrowsOnNotDefinedOption()
@@ -54,7 +54,7 @@ class OptionsResolverIntrospectorTest extends TestCase
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
- $this->assertSame('bar', $debug->getDefault('foo'));
+ $debug->getDefault('foo');
}
public function testGetLazyClosures()
@@ -75,7 +75,7 @@ class OptionsResolverIntrospectorTest extends TestCase
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
- $this->assertSame('bar', $debug->getLazyClosures($option));
+ $debug->getLazyClosures($option);
}
public function testGetLazyClosuresThrowsOnNotDefinedOption()
@@ -85,7 +85,7 @@ class OptionsResolverIntrospectorTest extends TestCase
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
- $this->assertSame('bar', $debug->getLazyClosures('foo'));
+ $debug->getLazyClosures('foo');
}
public function testGetAllowedTypes()
diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
index 01f948291a..cac049a0a6 100644
--- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
+++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
@@ -385,7 +385,7 @@ class PropertyAccessor implements PropertyAccessorInterface
} catch (\TypeError $e) {
// handle uninitialized properties in PHP >= 7
if (preg_match((sprintf('/^Return value of %s::%s\(\) must be of the type (\w+), null returned$/', preg_quote(\get_class($object)), $access[self::ACCESS_NAME])), $e->getMessage(), $matches)) {
- throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Have you forgotten to initialize a property or to make the return type nullable using "?%3$s" instead?', \get_class($object), $access[self::ACCESS_NAME], $matches[1]), 0, $e);
+ throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Did you forget to initialize a property or to make the return type nullable using "?%3$s"?', \get_class($object), $access[self::ACCESS_NAME], $matches[1]), 0, $e);
}
throw $e;
@@ -418,7 +418,7 @@ class PropertyAccessor implements PropertyAccessorInterface
if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) {
$r = new \ReflectionProperty($matches[1], $matches[2]);
- throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%3$s". You should either initialize it or make it nullable using "?%3$s" instead.', $r->getDeclaringClass()->getName(), $r->getName(), $r->getType()->getName()), 0, $e);
+ throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getName(), $r->getType()->getName()), 0, $e);
}
throw $e;
diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
index 5304a807f1..c42076ea06 100644
--- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
+++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
@@ -139,7 +139,7 @@ class PropertyAccessorTest extends TestCase
public function testGetValueThrowsExceptionIfUninitializedProperty()
{
$this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException');
- $this->expectExceptionMessage('The property "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedProperty::$uninitialized" is not readable because it is typed "string". You should either initialize it or make it nullable using "?string" instead.');
+ $this->expectExceptionMessage('The property "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedProperty::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.');
$this->propertyAccessor->getValue(new UninitializedProperty(), 'uninitialized');
}
@@ -150,7 +150,7 @@ class PropertyAccessorTest extends TestCase
public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetter()
{
$this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException');
- $this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty::getUninitialized()" returned "null", but expected type "array". Have you forgotten to initialize a property or to make the return type nullable using "?array" instead?');
+ $this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?');
$this->propertyAccessor->getValue(new UninitializedPrivateProperty(), 'uninitialized');
}
diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
index 6de6517b72..ccb216b624 100644
--- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
+++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
@@ -58,6 +58,9 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
private $enableConstructorExtraction;
private $accessFlags;
+ private $arrayMutatorPrefixesFirst;
+ private $arrayMutatorPrefixesLast;
+
/**
* @param string[]|null $mutatorPrefixes
* @param string[]|null $accessorPrefixes
@@ -70,6 +73,9 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
$this->arrayMutatorPrefixes = null !== $arrayMutatorPrefixes ? $arrayMutatorPrefixes : self::$defaultArrayMutatorPrefixes;
$this->enableConstructorExtraction = $enableConstructorExtraction;
$this->accessFlags = $accessFlags;
+
+ $this->arrayMutatorPrefixesFirst = array_merge($this->arrayMutatorPrefixes, array_diff($this->mutatorPrefixes, $this->arrayMutatorPrefixes));
+ $this->arrayMutatorPrefixesLast = array_reverse($this->arrayMutatorPrefixesFirst);
}
/**
@@ -405,7 +411,9 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
$ucProperty = ucfirst($property);
$ucSingulars = (array) Inflector::singularize($ucProperty);
- foreach ($this->mutatorPrefixes as $prefix) {
+ $mutatorPrefixes = \in_array($ucProperty, $ucSingulars, true) ? $this->arrayMutatorPrefixesLast : $this->arrayMutatorPrefixesFirst;
+
+ foreach ($mutatorPrefixes as $prefix) {
$names = [$ucProperty];
if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
$names = array_merge($names, $ucSingulars);
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
index 45fd42c39a..0fadd46413 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
@@ -70,6 +70,7 @@ class ReflectionExtractorTest extends TestCase
'realParent',
'xTotals',
'YT',
+ 'date',
'c',
'd',
'e',
@@ -109,6 +110,7 @@ class ReflectionExtractorTest extends TestCase
'foo4',
'foo5',
'files',
+ 'date',
'c',
'd',
'e',
@@ -173,6 +175,8 @@ class ReflectionExtractorTest extends TestCase
['staticSetter', null],
['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')]],
['realParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]],
+ ['date', [new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class)]],
+ ['dates', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class))]],
];
}
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
index ec4b75a099..bcec074438 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
@@ -210,4 +210,12 @@ class Dummy extends ParentDummy
public function getYT()
{
}
+
+ public function setDate(\DateTime $date)
+ {
+ }
+
+ public function addDate(\DateTime $date)
+ {
+ }
}
diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
index be4f9c47ae..c012c8d1a6 100644
--- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
@@ -482,7 +482,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
*/
protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, $parameterName, $parameterData, array $context, $format = null)
{
- if (null === $this->propertyTypeExtractor || null === $types = $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) {
+ if (null === $this->propertyTypeExtractor || null === $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) {
return parent::denormalizeParameter($class, $parameter, $parameterName, $parameterData, $context, $format);
}
@@ -617,6 +617,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
unset($context[$key]);
}
unset($context[self::EXCLUDE_FROM_CACHE_KEY]);
+ unset($context[self::OBJECT_TO_POPULATE]);
unset($context['cache_key']); // avoid artificially different keys
try {
diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php
index 3de0ac086a..01b8950cb4 100644
--- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php
@@ -174,6 +174,14 @@ class AbstractObjectNormalizerTest extends TestCase
$this->assertEquals('bar', $stringCollection->children[1]);
}
+ public function testDenormalizeNotSerializableObjectToPopulate()
+ {
+ $normalizer = new AbstractObjectNormalizerDummy();
+ $normalizedData = $normalizer->denormalize(['foo' => 'foo'], Dummy::class, null, [AbstractObjectNormalizer::OBJECT_TO_POPULATE => new NotSerializable()]);
+
+ $this->assertSame('foo', $normalizedData->foo);
+ }
+
private function getDenormalizerForStringCollection()
{
$extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock();
@@ -448,3 +456,15 @@ class ArrayDenormalizerDummy implements DenormalizerInterface, SerializerAwareIn
$this->serializer = $serializer;
}
}
+
+class NotSerializable
+{
+ public function __sleep()
+ {
+ if (class_exists(\Error::class)) {
+ throw new \Error('not serializable');
+ }
+
+ throw new \Exception('not serializable');
+ }
+}
diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php
index 43c21f5768..77d7354946 100644
--- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php
+++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php
@@ -24,7 +24,7 @@ class UrlValidator extends ConstraintValidator
{
const PATTERN = '~^
(%s):// # protocol
- (([\_\.\pL\pN-]+:)?([\_\.\pL\pN-]+)@)? # basic auth
+ (((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+)@)? # basic auth
(
([\pL\pN\pS\-\_\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
| # or
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf
index 80911a9902..3c03fd8525 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf
@@ -370,6 +370,18 @@
This value is not a valid 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.
+ Каждый элемент этой коллекции должен удовлетворять своему собственному набору ограничений.
+