From 05d4bcb987179e60007fbd6f9378870a2d396ba1 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 25 Jun 2018 17:34:31 +0200 Subject: [PATCH 01/11] fix handling of empty DI extension configs --- .../Compiler/ValidateEnvPlaceholdersPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ValidateEnvPlaceholdersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ValidateEnvPlaceholdersPass.php index 402aca6378..06b655328b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ValidateEnvPlaceholdersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ValidateEnvPlaceholdersPass.php @@ -65,7 +65,7 @@ class ValidateEnvPlaceholdersPass implements CompilerPassInterface $processor = new Processor(); foreach ($extensions as $name => $extension) { - if (!$extension instanceof ConfigurationExtensionInterface || !$config = $container->getExtensionConfig($name)) { + if (!$extension instanceof ConfigurationExtensionInterface || !$config = array_filter($container->getExtensionConfig($name))) { // this extension has no semantic configuration or was not called continue; } From c91b7afe35eee53234463871dc97e9cd23f67dbb Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Fri, 29 Jun 2018 12:43:55 +0100 Subject: [PATCH 02/11] Ensure the class discriminator mechanism works with serialization groups as well --- .../Normalizer/ObjectNormalizer.php | 21 +++++++ .../Tests/Fixtures/DummyMessageInterface.php | 4 +- .../Tests/Fixtures/DummyMessageNumberOne.php | 7 +++ .../Tests/Fixtures/DummyMessageNumberTwo.php | 19 ++++++ .../Serializer/Tests/SerializerTest.php | 62 +++++++++---------- 5 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberTwo.php diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index bf463fe545..6c9098528b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -16,6 +16,7 @@ use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\Serializer\Exception\RuntimeException; +use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -131,4 +132,24 @@ class ObjectNormalizer extends AbstractObjectNormalizer // Properties not found are ignored } } + + /** + * {@inheritdoc} + */ + protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false) + { + if (false === $allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString)) { + return false; + } + + if (null !== $this->classDiscriminatorResolver && null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForMappedObject($classOrObject)) { + $allowedAttributes[] = $attributesAsString ? $discriminatorMapping->getTypeProperty() : new AttributeMetadata($discriminatorMapping->getTypeProperty()); + + foreach ($discriminatorMapping->getTypesMapping() as $class) { + $allowedAttributes = array_merge($allowedAttributes, parent::getAllowedAttributes($class, $context, $attributesAsString)); + } + } + + return $allowedAttributes; + } } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php index f0b4c4d128..55bb00bc8e 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php @@ -15,8 +15,8 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * @DiscriminatorMap(typeProperty="type", mapping={ - * "first"="Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild", - * "second"="Symfony\Component\Serializer\Tests\Fixtures\AbstractDummySecondChild" + * "one"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne", + * "two"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo" * }) * * @author Samuel Roze diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberOne.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberOne.php index 381f7f8a6c..200476b542 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberOne.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberOne.php @@ -11,10 +11,17 @@ namespace Symfony\Component\Serializer\Tests\Fixtures; +use Symfony\Component\Serializer\Annotation\Groups; + /** * @author Samuel Roze */ class DummyMessageNumberOne implements DummyMessageInterface { public $one; + + /** + * @Groups({"two"}) + */ + public $two; } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberTwo.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberTwo.php new file mode 100644 index 0000000000..060c10dd79 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberTwo.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 DummyMessageNumberTwo implements DummyMessageInterface +{ +} diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index 7550b3c9b7..25fbbf38ce 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -11,11 +11,14 @@ namespace Symfony\Component\Serializer\Tests; +use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping; use Symfony\Component\Serializer\Mapping\ClassMetadata; +use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; +use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; @@ -398,11 +401,9 @@ class SerializerTest extends TestCase $example = new DummyMessageNumberOne(); $example->one = 1; - $jsonData = '{"message-type":"one","one":1}'; - - $discriminatorResolver = new ClassDiscriminatorFromClassMetadata($this->metadataFactoryMockForDummyInterface()); - $serializer = new Serializer(array(new ObjectNormalizer(null, null, null, null, $discriminatorResolver)), array('json' => new JsonEncoder())); + $jsonData = '{"type":"one","one":1,"two":null}'; + $serializer = $this->serializerWithClassDiscriminator(); $deserialized = $serializer->deserialize($jsonData, DummyMessageInterface::class, 'json'); $this->assertEquals($example, $deserialized); @@ -410,51 +411,48 @@ class SerializerTest extends TestCase $this->assertEquals($jsonData, $serialized); } + public function testDeserializeAndSerializeInterfacedObjectsWithTheClassMetadataDiscriminatorResolverAndGroups() + { + $example = new DummyMessageNumberOne(); + $example->two = 2; + + $serializer = $this->serializerWithClassDiscriminator(); + $deserialized = $serializer->deserialize('{"type":"one","one":1,"two":2}', DummyMessageInterface::class, 'json', array( + 'groups' => array('two'), + )); + + $this->assertEquals($example, $deserialized); + + $serialized = $serializer->serialize($deserialized, 'json', array( + 'groups' => array('two'), + )); + + $this->assertEquals('{"two":2,"type":"one"}', $serialized); + } + /** * @expectedException \Symfony\Component\Serializer\Exception\RuntimeException * @expectedExceptionMessage The type "second" has no mapped class for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface" */ public function testExceptionWhenTypeIsNotKnownInDiscriminator() { - $discriminatorResolver = new ClassDiscriminatorFromClassMetadata($this->metadataFactoryMockForDummyInterface()); - $serializer = new Serializer(array(new ObjectNormalizer(null, null, null, null, $discriminatorResolver)), array('json' => new JsonEncoder())); - $serializer->deserialize('{"message-type":"second","one":1}', DummyMessageInterface::class, 'json'); + $this->serializerWithClassDiscriminator()->deserialize('{"type":"second","one":1}', DummyMessageInterface::class, 'json'); } /** * @expectedException \Symfony\Component\Serializer\Exception\RuntimeException - * @expectedExceptionMessage Type property "message-type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface" + * @expectedExceptionMessage Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface" */ public function testExceptionWhenTypeIsNotInTheBodyToDeserialiaze() { - $discriminatorResolver = new ClassDiscriminatorFromClassMetadata($this->metadataFactoryMockForDummyInterface()); - $serializer = new Serializer(array(new ObjectNormalizer(null, null, null, null, $discriminatorResolver)), array('json' => new JsonEncoder())); - $serializer->deserialize('{"one":1}', DummyMessageInterface::class, 'json'); + $this->serializerWithClassDiscriminator()->deserialize('{"one":1}', DummyMessageInterface::class, 'json'); } - private function metadataFactoryMockForDummyInterface() + private function serializerWithClassDiscriminator() { - $factoryMock = $this->getMockBuilder(ClassMetadataFactoryInterface::class)->getMock(); - $factoryMock->method('hasMetadataFor')->will($this->returnValueMap(array( - array( - DummyMessageInterface::class, - true, - ), - ))); + $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); - $factoryMock->method('getMetadataFor')->will($this->returnValueMap(array( - array( - DummyMessageInterface::class, - new ClassMetadata( - DummyMessageInterface::class, - new ClassDiscriminatorMapping('message-type', array( - 'one' => DummyMessageNumberOne::class, - )) - ), - ), - ))); - - return $factoryMock; + return new Serializer(array(new ObjectNormalizer($classMetadataFactory, null, null, null, new ClassDiscriminatorFromClassMetadata($classMetadataFactory))), array('json' => new JsonEncoder())); } } From 9055611dc3e5592d30568a4797e8e9391d9c1e28 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 29 Jun 2018 18:29:00 +0200 Subject: [PATCH 03/11] [Lock] Fix SemaphoreStoreTest on OS X --- .../Lock/Tests/Store/SemaphoreStoreTest.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php index 7057505072..38babded28 100644 --- a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php @@ -50,13 +50,22 @@ class SemaphoreStoreTest extends AbstractStoreTest private function getOpenedSemaphores() { + if ('Darwin' === PHP_OS) { + $lines = explode(PHP_EOL, trim(`ipcs -s`)); + if (-1 === $start = array_search('Semaphores:', $lines)) { + throw new \Exception('Failed to extract list of opened semaphores. Expected a Semaphore list, got '.implode(PHP_EOL, $lines)); + } + + return \count(\array_slice($lines, ++$start)); + } + $lines = explode(PHP_EOL, trim(`LC_ALL=C ipcs -su`)); if ('------ Semaphore Status --------' !== $lines[0]) { - throw new \Exception('Failed to extract list of opend semaphores. Expect a Semaphore status, got '.implode(PHP_EOL, $lines)); + throw new \Exception('Failed to extract list of opened semaphores. Expected a Semaphore status, got '.implode(PHP_EOL, $lines)); } list($key, $value) = explode(' = ', $lines[1]); if ('used arrays' !== $key) { - throw new \Exception('Failed to extract list of opend semaphores. Expect a used arrays key, got '.implode(PHP_EOL, $lines)); + throw new \Exception('Failed to extract list of opened semaphores. Expected a "used arrays" key, got '.implode(PHP_EOL, $lines)); } return (int) $value; From 582d797b1629ae048198e97acf624b823b8cb1c2 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 30 Jun 2018 11:20:07 +0200 Subject: [PATCH 04/11] [Form] Fix fixtures for forward compat --- .../Descriptor/default_option_with_normalizer.txt | 4 ++-- .../overridden_option_with_default_closures.txt | 8 ++++---- .../Descriptor/required_option_with_allowed_values.txt | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt index 87d656a3fa..391c3e694d 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt @@ -15,9 +15,9 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (choice_translation_domain ---------------- --------------------%s Allowed values - %s ---------------- --------------------%s - Normalizer Closure%s{ %s + Normalizer Closure%s{%w parameters: 2 %s - file: "%s%eExtension%eCore%eType%eChoiceType.php" + file: "%s%eExtension%eCore%eType%eChoiceType.php"%w line: "%s to %s" %s } %s ---------------- --------------------%s diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt index 967d177c7e..846d6f3846 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt @@ -8,14 +8,14 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (empty_data) Default Value: null %s %s Closure(s): [ %s - Closure%s{ %s + Closure%s{%w parameters: 1 %s - file: "%s%eExtension%eCore%eType%eFormType.php" + file: "%s%eExtension%eCore%eType%eFormType.php"%w line: "%s to %s" %s }, %s - Closure%s{ %s + Closure%s{%w parameters: 2 %s - file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php" + file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php"%w line: "%s to %s" %s } %s ] %s diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt index 0d2e7f44d9..8cc88a550a 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt @@ -16,9 +16,9 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (foo) "baz" %s ] %s ---------------- --------------------%s - Normalizer Closure%s{ %s + Normalizer Closure%s{%w parameters: 2 %s - file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php" + file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php"%w line: "%s to %s" %s } %s ---------------- --------------------%s From ba8b63b195a87a89a3a7dc3cdf777721824adeb9 Mon Sep 17 00:00:00 2001 From: Constantine Shtompel Date: Wed, 27 Jun 2018 23:40:07 +0300 Subject: [PATCH 05/11] [Cache] provider does not respect option maxIdLength with versioning enabled --- .../Tests/Adapter/MaxIdLengthAdapterTest.php | 28 +++++++++++++++++++ .../Component/Cache/Traits/AbstractTrait.php | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php index cf2384c5f3..266e1f850c 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php @@ -34,6 +34,34 @@ class MaxIdLengthAdapterTest extends TestCase $cache->hasItem(str_repeat('-', 39)); } + public function testLongKeyVersioning() + { + $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) + ->setConstructorArgs(array(str_repeat('-', 26))) + ->getMock(); + + $reflectionClass = new \ReflectionClass(AbstractAdapter::class); + + $reflectionMethod = $reflectionClass->getMethod('getId'); + $reflectionMethod->setAccessible(true); + + // No versioning enabled + $this->assertEquals('--------------------------:------------', $reflectionMethod->invokeArgs($cache, array(str_repeat('-', 12)))); + $this->assertLessThanOrEqual(50, strlen($reflectionMethod->invokeArgs($cache, array(str_repeat('-', 12))))); + $this->assertLessThanOrEqual(50, strlen($reflectionMethod->invokeArgs($cache, array(str_repeat('-', 23))))); + $this->assertLessThanOrEqual(50, strlen($reflectionMethod->invokeArgs($cache, array(str_repeat('-', 40))))); + + $reflectionProperty = $reflectionClass->getProperty('versioningIsEnabled'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($cache, true); + + // Versioning enabled + $this->assertEquals('--------------------------:1:------------', $reflectionMethod->invokeArgs($cache, array(str_repeat('-', 12)))); + $this->assertLessThanOrEqual(50, strlen($reflectionMethod->invokeArgs($cache, array(str_repeat('-', 12))))); + $this->assertLessThanOrEqual(50, strlen($reflectionMethod->invokeArgs($cache, array(str_repeat('-', 23))))); + $this->assertLessThanOrEqual(50, strlen($reflectionMethod->invokeArgs($cache, array(str_repeat('-', 40))))); + } + /** * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException * @expectedExceptionMessage Namespace must be 26 chars max, 40 given ("----------------------------------------") diff --git a/src/Symfony/Component/Cache/Traits/AbstractTrait.php b/src/Symfony/Component/Cache/Traits/AbstractTrait.php index 7953ae6e8b..ec60fe79c4 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractTrait.php @@ -255,7 +255,7 @@ trait AbstractTrait return $this->namespace.$this->namespaceVersion.$key; } if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { - $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), ':', -22); + $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), ':', -(\strlen($this->namespaceVersion) + 22)); } return $id; From f54d96926acfd29e78205525bb5f3a09d923147a Mon Sep 17 00:00:00 2001 From: Chris Wilkinson Date: Wed, 20 Jun 2018 16:02:10 +0100 Subject: [PATCH 06/11] [HttpKernel] Make AbstractTestSessionListener compatible with CookieClearingLogoutHandler --- .../AbstractTestSessionListener.php | 7 ++++ .../EventListener/TestSessionListenerTest.php | 34 +++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php index 82061fd6ea..75f810e988 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php @@ -71,6 +71,13 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { $params = session_get_cookie_params(); + + foreach ($event->getResponse()->headers->getCookies() as $cookie) { + if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) { + return; + } + } + $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); $this->sessionId = $session->getId(); } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php index 22a2b71239..01f0a3b864 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php @@ -106,6 +106,36 @@ class TestSessionListenerTest extends TestCase $this->assertNotEmpty($response->headers->getCookies()); } + /** + * @dataProvider anotherCookieProvider + */ + public function testSessionWithNewSessionIdAndNewCookieDoesNotSendAnotherCookie($existing, array $expected) + { + $this->sessionHasBeenStarted(); + $this->sessionIsEmpty(); + $this->fixSessionId('456'); + + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $request = Request::create('/', 'GET', array(), array('MOCKSESSID' => '123')); + $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $this->listener->onKernelRequest($event); + + $response = new Response('', 200, array('Set-Cookie' => $existing)); + + $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST, $response); + + $this->assertSame($expected, $response->headers->get('Set-Cookie', null, false)); + } + + public function anotherCookieProvider() + { + return array( + 'same' => array('MOCKSESSID=789; path=/', array('MOCKSESSID=789; path=/')), + 'different domain' => array('MOCKSESSID=789; path=/; domain=example.com', array('MOCKSESSID=789; path=/; domain=example.com', 'MOCKSESSID=456; path=/')), + 'different path' => array('MOCKSESSID=789; path=/foo', array('MOCKSESSID=789; path=/foo', 'MOCKSESSID=456; path=/')), + ); + } + public function testUnstartedSessionIsNotSave() { $this->sessionHasNotBeenStarted(); @@ -123,10 +153,10 @@ class TestSessionListenerTest extends TestCase $this->assertFalse(is_subclass_of(TestSessionListener::class, ServiceSubscriberInterface::class, 'Implementing ServiceSubscriberInterface would create a dep on the DI component, which eg Silex cannot afford')); } - private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST) + private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, Response $response = null) { $request->setSession($this->session); - $response = new Response(); + $response = $response ?: new Response(); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); $event = new FilterResponseEvent($kernel, $request, $type, $response); From 38b369be3f47d0964e0af125359e533035225210 Mon Sep 17 00:00:00 2001 From: Oxan van Leeuwen Date: Sun, 17 Jun 2018 12:05:07 +0200 Subject: [PATCH 07/11] [PropertyInfo] added handling of nullable types in PhpDoc While not specified in PSR-5, PhpDocumentor does support parsing nullable types in the PHP 7.1 syntax (i.e. ?string), and returns those in a Nullable wrapper. We currently don't handle this and neither throw an error, which results in all kind of weird breakage when this syntax is used (e.g. "class string|int not found"). Correctly parse this syntax into a nullable type. --- composer.json | 2 +- .../Tests/Extractor/PhpDocExtractorTest.php | 9 +++++++++ .../Tests/Extractor/ReflectionExtractorTest.php | 9 +++++++++ .../PropertyInfo/Tests/Fixtures/Dummy.php | 15 +++++++++++++++ .../PropertyInfo/Util/PhpDocTypeHelper.php | 12 +++++++++--- src/Symfony/Component/PropertyInfo/composer.json | 2 +- 6 files changed, 44 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index f38c72fb8e..6d5065d4d3 100644 --- a/composer.json +++ b/composer.json @@ -104,7 +104,7 @@ }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", - "phpdocumentor/type-resolver": "<0.2.1", + "phpdocumentor/type-resolver": "<0.3.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, "provide": { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index 647d4c1072..0b769c4531 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -94,6 +94,9 @@ class PhpDocExtractorTest extends TestCase array('e', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))), null, null), array('f', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null), array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null), + array('h', array(new Type(Type::BUILTIN_TYPE_STRING, true)), null, null), + array('i', array(new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)), null, null), + array('j', array(new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')), null, null), array('donotexist', null, null, null), array('staticGetter', null, null, null), array('staticSetter', null, null, null), @@ -130,6 +133,9 @@ class PhpDocExtractorTest extends TestCase array('e', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))), null, null), array('f', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null), array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null), + array('h', array(new Type(Type::BUILTIN_TYPE_STRING, true)), null, null), + array('i', array(new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)), null, null), + array('j', array(new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')), null, null), array('donotexist', null, null, null), array('staticGetter', null, null, null), array('staticSetter', null, null, null), @@ -165,6 +171,9 @@ class PhpDocExtractorTest extends TestCase array('e', null, null, null), array('f', null, null, null), array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null), + array('h', array(new Type(Type::BUILTIN_TYPE_STRING, true)), null, null), + array('i', array(new Type(Type::BUILTIN_TYPE_STRING, true), new Type(Type::BUILTIN_TYPE_INT, true)), null, null), + array('j', array(new Type(Type::BUILTIN_TYPE_OBJECT, true, 'DateTime')), null, null), array('donotexist', null, null, null), array('staticGetter', null, null, null), array('staticSetter', null, null, null), diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index f8c61dd48a..e7fddf473f 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -41,6 +41,9 @@ class ReflectionExtractorTest extends TestCase 'B', 'Guid', 'g', + 'h', + 'i', + 'j', 'emptyVar', 'foo', 'foo2', @@ -77,6 +80,9 @@ class ReflectionExtractorTest extends TestCase 'B', 'Guid', 'g', + 'h', + 'i', + 'j', 'emptyVar', 'foo', 'foo2', @@ -105,6 +111,9 @@ class ReflectionExtractorTest extends TestCase 'B', 'Guid', 'g', + 'h', + 'i', + 'j', 'emptyVar', 'foo', 'foo2', diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index 5993d6e1d4..76c2e1042c 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -68,6 +68,21 @@ class Dummy extends ParentDummy */ public $g; + /** + * @var ?string + */ + public $h; + + /** + * @var ?string|int + */ + public $i; + + /** + * @var ?\DateTime + */ + public $j; + /** * This should not be removed. * diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index bc14cd8b69..e526c62348 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -14,6 +14,7 @@ namespace Symfony\Component\PropertyInfo\Util; use phpDocumentor\Reflection\Type as DocType; use phpDocumentor\Reflection\Types\Compound; use phpDocumentor\Reflection\Types\Null_; +use phpDocumentor\Reflection\Types\Nullable; use Symfony\Component\PropertyInfo\Type; /** @@ -27,13 +28,18 @@ final class PhpDocTypeHelper /** * Creates a {@see Type} from a PHPDoc type. * - * @return Type + * @return Type[] */ public function getTypes(DocType $varType) { $types = array(); $nullable = false; + if ($varType instanceof Nullable) { + $nullable = true; + $varType = $varType->getActualType(); + } + if (!$varType instanceof Compound) { if ($varType instanceof Null_) { $nullable = true; @@ -54,10 +60,10 @@ final class PhpDocTypeHelper // If null is present, all types are nullable $nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes); - $nullable = false !== $nullKey; + $nullable = $nullable || false !== $nullKey; // Remove the null type from the type if other types are defined - if ($nullable && count($varTypes) > 1) { + if ($nullable && false !== $nullKey && count($varTypes) > 1) { unset($varTypes[$nullKey]); } diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index ce41fabd09..bf02fe0f98 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -35,7 +35,7 @@ }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", - "phpdocumentor/type-resolver": "<0.2.1", + "phpdocumentor/type-resolver": "<0.3.0", "symfony/dependency-injection": "<3.3" }, "suggest": { From 89470f19cc9e806ce7584b6091a74ed1a48b807d Mon Sep 17 00:00:00 2001 From: Anto Date: Mon, 2 Jul 2018 13:57:50 +0200 Subject: [PATCH 08/11] [Workflow] Update phpdoc to fit a used className --- src/Symfony/Component/Workflow/Event/Event.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Workflow/Event/Event.php b/src/Symfony/Component/Workflow/Event/Event.php index 943a4da5a6..a9e2086968 100644 --- a/src/Symfony/Component/Workflow/Event/Event.php +++ b/src/Symfony/Component/Workflow/Event/Event.php @@ -30,10 +30,10 @@ class Event extends BaseEvent private $workflowName; /** - * @param object $subject - * @param Marking $marking - * @param Transition $transition - * @param Workflow $workflow + * @param object $subject + * @param Marking $marking + * @param Transition $transition + * @param WorkflowInterface $workflow */ public function __construct($subject, Marking $marking, Transition $transition, $workflow = null) { From cf1bc66464af7b187852f8b4a084bee6468e7046 Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Tue, 3 Jul 2018 08:45:41 +0200 Subject: [PATCH 09/11] [Doctrine Bridge] Fixed usage of wrong variable when tagged subscriber is invalid --- .../CompilerPass/RegisterEventListenersAndSubscribersPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php index b9f5114474..f7d513a14e 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -75,7 +75,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface $connections = isset($tag['connection']) ? array($tag['connection']) : array_keys($this->connections); foreach ($connections as $con) { if (!isset($this->connections[$con])) { - throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $taggedSubscriber, implode(', ', array_keys($this->connections)))); + throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); } $this->getEventManagerDef($container, $con)->addMethodCall('addEventSubscriber', array(new Reference($id))); From 8e37d771453cb1f77e42a10f5fbc80152c38b2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Jul 2018 23:12:41 +0200 Subject: [PATCH 10/11] [HttpFoundation] Fix tests: new message for status 425 --- src/Symfony/Component/HttpFoundation/Response.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 9b4bb4cc53..3a1b5ca8f8 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -64,7 +64,12 @@ class Response const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 const HTTP_LOCKED = 423; // RFC4918 const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 + + /** + * @deprecated + */ const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817 + const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 @@ -169,7 +174,7 @@ class Response 422 => 'Unprocessable Entity', // RFC4918 423 => 'Locked', // RFC4918 424 => 'Failed Dependency', // RFC4918 - 425 => 'Reserved for WebDAV advanced collections expired proposal', // RFC2817 + 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 426 => 'Upgrade Required', // RFC2817 428 => 'Precondition Required', // RFC6585 429 => 'Too Many Requests', // RFC6585 From 2ab7bcf797d3ffe58b05c60adb626a7146d05508 Mon Sep 17 00:00:00 2001 From: AzJezz Date: Sun, 1 Jul 2018 16:55:08 +0200 Subject: [PATCH 11/11] Add color support for Hyper terminal . --- src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php | 3 ++- src/Symfony/Component/Console/Output/StreamOutput.php | 3 ++- src/Symfony/Component/Console/Style/SymfonyStyle.php | 2 +- src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 6 ++++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 0290a69fcf..57751d7329 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -231,7 +231,8 @@ class DeprecationErrorHandler && sapi_windows_vt100_support(STDOUT)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM'); } if (function_exists('stream_isatty')) { diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index 5fc5d01e14..54eb0bea15 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -98,7 +98,8 @@ class StreamOutput extends Output && @sapi_windows_vt100_support($this->stream)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM'); } if (function_exists('stream_isatty')) { diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index a21f3c16e4..b77ca78aff 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -271,7 +271,7 @@ class SymfonyStyle extends OutputStyle { $progressBar = parent::createProgressBar($max); - if ('\\' !== DIRECTORY_SEPARATOR) { + if ('\\' !== DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 9a8ddca86d..466188564c 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -484,7 +484,8 @@ class CliDumper extends AbstractDumper && @sapi_windows_vt100_support($stream)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM'); } if (function_exists('stream_isatty')) { @@ -513,7 +514,8 @@ class CliDumper extends AbstractDumper { $result = 183 <= getenv('ANSICON_VER') || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM'); if (!$result && PHP_VERSION_ID >= 70200) { $version = sprintf(