From b0db10cf6c869b58890889f66500a6bdc4fbd8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20J=2E=20Garc=C3=ADa=20Lagar?= Date: Tue, 9 Jul 2019 16:56:37 +0200 Subject: [PATCH 1/6] [RFC] Alternative implementation (#71) --- .travis.yml | 12 +- composer.json | 16 +- phpunit.xml.dist | 7 +- .../DunglasDoctrineJsonOdmExtension.php | 16 ++ src/Bundle/Resources/config/services.xml | 17 +-- src/Normalizer/ObjectNormalizer.php | 111 -------------- src/Serializer.php | 52 +++++++ .../InjectCustomNormalizerPass.php | 29 ++++ .../TestBundle/Entity/ScalarValue.php | 47 ++++++ tests/Fixtures/TestBundle/TestBundle.php | 6 + tests/FunctionalTest.php | 5 +- tests/SerializerTest.php | 143 ++++++++++++++++++ 12 files changed, 317 insertions(+), 144 deletions(-) delete mode 100644 src/Normalizer/ObjectNormalizer.php create mode 100644 src/Serializer.php create mode 100644 tests/Fixtures/TestBundle/DependencyInjection/InjectCustomNormalizerPass.php create mode 100644 tests/Fixtures/TestBundle/Entity/ScalarValue.php create mode 100644 tests/SerializerTest.php diff --git a/.travis.yml b/.travis.yml index 541e39a..9311751 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,24 +20,26 @@ env: - MYSQL_DBNAME="travis_ci_test" php: - - 5.5 - - 5.6 - - 7.0 - 7.1 - 7.2 + - 7.3 - nightly matrix: fast_finish: true include: - php: 7.1 - env: deps=low + env: deps=low SYMFONY_PHPUNIT_VERSION=5.7.27 - php: 7.1 env: deps=beta - php: 7.2 - env: deps=low + env: deps=low SYMFONY_PHPUNIT_VERSION=5.7.27 - php: 7.2 env: deps=beta + - php: 7.3 + env: deps=low SYMFONY_PHPUNIT_VERSION=5.7.27 + - php: 7.3 + env: deps=beta allow_failures: - env: deps=beta - php: nightly diff --git a/composer.json b/composer.json index b69398b..0006d4d 100644 --- a/composer.json +++ b/composer.json @@ -13,17 +13,17 @@ } ], "require": { - "php": "^5.5.9 || ^7.0", - "doctrine/orm": "^2.5", - "symfony/property-access": "^2.8 || ^3.0 || ^4.0", - "symfony/property-info": "^2.8 || ^3.0 || ^4.0", - "symfony/serializer": "^2.8 || ^3.0 || ^4.0" + "php": "^7.1", + "doctrine/orm": "^2.6.3", + "symfony/property-access": "^2.8 || ^3.4 || ^4.1", + "symfony/property-info": "^2.8 || ^3.4 || ^4.1", + "symfony/serializer": "^2.8 || ^3.4 || ^4.1" }, "require-dev": { "doctrine/doctrine-bundle": "^1.6", - "symfony/finder": "^2.8 || ^3.0 || ^4.0", - "symfony/framework-bundle": "^2.8 || ^3.0 || ^4.0", - "symfony/phpunit-bridge": "^3.3 || ^4.0" + "symfony/finder": "^2.8 || ^3.4 || ^4.1", + "symfony/framework-bundle": "^2.8 || ^3.4 || ^4.1", + "symfony/phpunit-bridge": "^4.3" }, "suggest": { "symfony/framework-bundle": "To use the provided bundle.", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b679ac3..7476484 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -7,6 +7,8 @@ > + + @@ -15,11 +17,6 @@ - - - - - . diff --git a/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php b/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php index 938ffcb..a8a58b5 100644 --- a/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php +++ b/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php @@ -11,9 +11,11 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; /** * @author Kévin Dunglas @@ -45,5 +47,19 @@ public function load(array $configs, ContainerBuilder $container) { $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.xml'); + + $this->defineArraySerializerIfRequired($container); + } + + /** + * BC layer for Symfony Framework Bundle <= 3.1.6. + * + * @param ContainerBuilder $container + */ + private function defineArraySerializerIfRequired(ContainerBuilder $container): void + { + if (!$container->hasDefinition('serializer.denormalizer.array')) { + $container->setDefinition('serializer.denormalizer.array', new Definition(ArrayDenormalizer::class)); + } } } diff --git a/src/Bundle/Resources/config/services.xml b/src/Bundle/Resources/config/services.xml index 6ad4998..64fa999 100644 --- a/src/Bundle/Resources/config/services.xml +++ b/src/Bundle/Resources/config/services.xml @@ -5,21 +5,10 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - - null - - - - - - - - - - + - + + diff --git a/src/Normalizer/ObjectNormalizer.php b/src/Normalizer/ObjectNormalizer.php deleted file mode 100644 index e17f5cc..0000000 --- a/src/Normalizer/ObjectNormalizer.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Dunglas\DoctrineJsonOdm\Normalizer; - -use Doctrine\Common\Util\ClassUtils; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\SerializerAwareInterface; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Transforms an object to an array with the following keys: - * * _type: the class name - * * _value: a representation of the values of the object. - * - * @author Kévin Dunglas - */ -final class ObjectNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface -{ - /** - * @var NormalizerInterface|DenormalizerInterface - */ - private $serializer; - private $objectNormalizer; - - public function __construct(NormalizerInterface $objectNormalizer) - { - if (!$objectNormalizer instanceof DenormalizerInterface) { - throw new \InvalidArgumentException(sprintf('The normalizer used must implement the "%s" interface.', DenormalizerInterface::class)); - } - - $this->objectNormalizer = $objectNormalizer; - } - - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []) - { - return array_merge(['#type' => ClassUtils::getClass($object)], $this->objectNormalizer->normalize($object, $format, $context)); - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null) - { - return is_object($data); - } - - /** - * {@inheritdoc} - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - if (is_object($data)) { - return $data; - } - - if (isset($data['#type'])) { - $type = $data['#type']; - unset($data['#type']); - - $data = $this->denormalize($data, $type, $format, $context); - $data = $this->objectNormalizer->denormalize($data, $type, $format, $context); - - return $data; - } - - if (is_array($data) || $data instanceof \Traversable) { - foreach ($data as $key => $value) { - $data[$key] = $this->serializer->denormalize($value, $class, $format, $context); - } - } - - return $data; - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function setSerializer(SerializerInterface $serializer) - { - if (!$serializer instanceof NormalizerInterface || !$serializer instanceof DenormalizerInterface) { - throw new \InvalidArgumentException( - sprintf('The injected serializer must implement "%s" and "%s".', NormalizerInterface::class, DenormalizerInterface::class) - ); - } - - $this->serializer = $serializer; - - if ($this->objectNormalizer instanceof SerializerAwareInterface) { - $this->objectNormalizer->setSerializer($serializer); - } - } -} diff --git a/src/Serializer.php b/src/Serializer.php new file mode 100644 index 0000000..be573c3 --- /dev/null +++ b/src/Serializer.php @@ -0,0 +1,52 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Dunglas\DoctrineJsonOdm; + +use Symfony\Component\Serializer\Serializer as BaseSerializer; + +final class Serializer extends BaseSerializer +{ + private const KEY_TYPE = '#type'; + private const KEY_SCALAR = '#scalar'; + + public function normalize($data, $format = null, array $context = []) + { + $normalizedData = parent::normalize($data, $format, $context); + + if (is_object($data)) { + $typeData = [self::KEY_TYPE => get_class($data)]; + $valueData = is_scalar($normalizedData) ? [self::KEY_SCALAR => $normalizedData] : $normalizedData; + $normalizedData = array_merge($typeData, $valueData); + } + + return $normalizedData; + } + + public function denormalize($data, $class, $format = null, array $context = []) + { + if (is_array($data) && (isset($data[self::KEY_TYPE]))) { + $type = $data[self::KEY_TYPE]; + unset($data[self::KEY_TYPE]); + + $data = $data[self::KEY_SCALAR] ?? $data; + $data = $this->denormalize($data, $type, $format, $context); + + return parent::denormalize($data, $type, $format, $context); + } + + if (is_iterable($data)) { + $class = ($class === '') ? 'stdClass' : $class; + + return parent::denormalize($data, $class.'[]', $format, $context); + } + + return $data; + } +} diff --git a/tests/Fixtures/TestBundle/DependencyInjection/InjectCustomNormalizerPass.php b/tests/Fixtures/TestBundle/DependencyInjection/InjectCustomNormalizerPass.php new file mode 100644 index 0000000..b85240d --- /dev/null +++ b/tests/Fixtures/TestBundle/DependencyInjection/InjectCustomNormalizerPass.php @@ -0,0 +1,29 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Serializer\Normalizer\CustomNormalizer; + +class InjectCustomNormalizerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $container->setDefinition('dunglas_doctrine_json_odm.normalizer.custom', new Definition(CustomNormalizer::class)); + + $serializerDefinition = $container->getDefinition('dunglas_doctrine_json_odm.serializer'); + $arguments = $serializerDefinition->getArguments(); + $arguments[0] = array_merge([new Reference('dunglas_doctrine_json_odm.normalizer.custom')], $arguments[0]); + $serializerDefinition->setArguments($arguments); + } +} diff --git a/tests/Fixtures/TestBundle/Entity/ScalarValue.php b/tests/Fixtures/TestBundle/Entity/ScalarValue.php new file mode 100644 index 0000000..e7ab03b --- /dev/null +++ b/tests/Fixtures/TestBundle/Entity/ScalarValue.php @@ -0,0 +1,47 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity; + +use Symfony\Component\Serializer\Normalizer\DenormalizableInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +use Symfony\Component\Serializer\Normalizer\NormalizableInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; + +/** + * Fixture class to test object normalized as scalar values. + * + * @author Antonio J. García Lagar + */ +class ScalarValue implements NormalizableInterface, DenormalizableInterface +{ + private $value; + + public function __construct($value = '') + { + $this->value = $value; + } + + public function value() + { + return $this->value; + } + + public function normalize(NormalizerInterface $normalizer, $format = null, array $context = []) + { + return $this->value; + } + + public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = []) + { + $this->value = $data; + + return $this; + } +} diff --git a/tests/Fixtures/TestBundle/TestBundle.php b/tests/Fixtures/TestBundle/TestBundle.php index 384c5bd..bca3aac 100644 --- a/tests/Fixtures/TestBundle/TestBundle.php +++ b/tests/Fixtures/TestBundle/TestBundle.php @@ -9,6 +9,8 @@ namespace Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\DependencyInjection\InjectCustomNormalizerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; /** @@ -16,4 +18,8 @@ */ final class TestBundle extends Bundle { + public function build(ContainerBuilder $container) + { + $container->addCompilerPass(new InjectCustomNormalizerPass()); + } } diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 6be3235..cb51954 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -15,6 +15,7 @@ use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Baz; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Foo; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Product; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\ScalarValue; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Console\Input\StringInput; @@ -81,7 +82,9 @@ public function testStoreAndRetrieveDocumentsOfVariousTypes() $baz->setName('Baz'); $baz->setSize(7); - $misc = [$bar, $baz]; + $scalarValue = new ScalarValue('foobar'); + + $misc = [$bar, $baz, $scalarValue]; $foo = new Foo(); $foo->setName('Foo'); diff --git a/tests/SerializerTest.php b/tests/SerializerTest.php new file mode 100644 index 0000000..8d8e1dd --- /dev/null +++ b/tests/SerializerTest.php @@ -0,0 +1,143 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Dunglas\DoctrineJsonOdm\tests; + +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Attribute; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Attributes; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Bar; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Baz; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Foo; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\ScalarValue; +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; + +/** + * @author Kévin Dunglas + */ +class SerializerTest extends KernelTestCase +{ + /** + * @var Application + */ + private $application; + + protected function setUp() + { + $this->bootKernel(); + + $this->application = new Application(self::$kernel); + $this->application->setAutoExit(false); + } + + public function testStoreAndRetrieveDocument() + { + $attribute1 = new Attribute(); + $attribute1->key = 'foo'; + $attribute1->value = 'bar'; + + $attribute2 = new Attribute(); + $attribute2->key = 'weights'; + $attribute2->value = [34, 67]; + + $attributes = [$attribute1, $attribute2]; + + $serializer = self::$kernel->getContainer()->get('dunglas_doctrine_json_odm.serializer'); + $data = $serializer->serialize($attributes, 'json'); + $restoredAttributes = $serializer->deserialize($data, '', 'json'); + + $this->assertEquals($attributes, $restoredAttributes); + } + + public function testStoreAndRetrieveDocumentsOfVariousTypes() + { + $bar = new Bar(); + $bar->setTitle('Bar'); + $bar->setWeight(12); + + $baz = new Baz(); + $baz->setName('Baz'); + $baz->setSize(7); + + $scalarValue = new ScalarValue('foobar'); + + $misc = [$bar, $baz, $scalarValue]; + + $foo = new Foo(); + $foo->setName('Foo'); + $foo->setMisc($misc); + + $serializer = self::$kernel->getContainer()->get('dunglas_doctrine_json_odm.serializer'); + $data = $serializer->serialize($misc, 'json'); + $restoredMisc = $serializer->deserialize($data, '', 'json'); + + $this->assertEquals($misc, $restoredMisc); + } + + public function testNestedObjects() + { + $attribute = new Attribute(); + $attribute->key = 'nested'; + $attribute->value = 'bar'; + + $attributeParent = new Attribute(); + $attributeParent->key = 'parent'; + $attributeParent->value = [[$attribute]]; + + $misc = [$attributeParent]; + + $serializer = self::$kernel->getContainer()->get('dunglas_doctrine_json_odm.serializer'); + $data = $serializer->serialize($misc, 'json'); + $restoredMisc = $serializer->deserialize($data, '', 'json'); + + $this->assertEquals($misc, $restoredMisc); + } + + public function testNestedObjectsInNestedObject() + { + $attribute1 = new Attribute(); + $attribute1->key = 'attribute1'; + + $attribute2 = new Attribute(); + $attribute2->key = 'attribute2'; + + $attributes = new Attributes(); + $attributes->setAttributes([$attribute1, $attribute2]); + + $misc = [$attributes]; + + $serializer = self::$kernel->getContainer()->get('dunglas_doctrine_json_odm.serializer'); + $data = $serializer->serialize($misc, 'json'); + $restoredMisc = $serializer->deserialize($data, '', 'json'); + + $this->assertEquals($misc, $restoredMisc); + } + + public function testNullIsStoredAsNull() + { + $serializer = self::$kernel->getContainer()->get('dunglas_doctrine_json_odm.serializer'); + $data = $serializer->serialize(null, 'json'); + $restoredMisc = $serializer->deserialize($data, '', 'json'); + + $this->assertEquals(null, $restoredMisc); + } + + public function testScalarIsStoredInScalarKey() + { + $serializer = self::$kernel->getContainer()->get('dunglas_doctrine_json_odm.serializer'); + $value = new ScalarValue('foobar'); + $data = $serializer->serialize($value, 'json'); + $decodeData = json_decode($data, true); + $this->assertArrayHasKey('#scalar', $decodeData); + $this->assertSame($value->value(), $decodeData['#scalar']); + $restoredValue = $serializer->deserialize($data, '', 'json'); + + $this->assertEquals($value, $restoredValue); + } +} From 3b1740cf2564e5baf358552a71ad800554d479bd Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Tue, 9 Jul 2019 16:59:07 +0200 Subject: [PATCH 2/6] Cleaned up README a bit --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 21aed04..9c82244 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ An Object-Document Mapper (ODM) for [Doctrine ORM](http://www.doctrine-project.o [![SensioLabsInsight](https://insight.sensiolabs.com/projects/20cf915b-1554-4f89-8772-ef0f913ec759/mini.png)](https://insight.sensiolabs.com/projects/20cf915b-1554-4f89-8772-ef0f913ec759) [![StyleCI](https://styleci.io/repos/57223826/shield)](https://styleci.io/repos/57223826) -Did you ever dreamed of a tool creating powerful data models mixing traditional efficient relational mappings with modern +Did you ever dream of a tool creating powerful data models mixing traditional, efficient relational mappings with modern schema-less and NoSQL-like ones? With Doctrine JSON ODM, it's now possible to create and query such hybrid data models with ease. Thanks to [modern JSON @@ -15,8 +15,8 @@ types of RDBMS](http://www.postgresql.org/docs/current/static/datatype-json.html powerful and [fast as hell (similar in performance to a MongoDB database)](http://www.enterprisedb.com/postgres-plus-edb-blog/marc-linster/postgres-outperforms-mongodb-and-ushers-new-developer-reality)! You can even [define indexes](http://www.postgresql.org/docs/current/static/datatype-json.html#JSON-INDEXING) for those documents. -Doctrine JSON ODM allows to store PHP objects as JSON documents in modern dynamic columns of RDBMS. -It works with JSON and JSONB columns of PostgreSQL (>= 9.4) and the JSON column of MySQL (>= 5.7.8). +Doctrine JSON ODM allows to store PHP objects as JSON documents in modern, dynamic columns of an RDBMS. +It works with JSON and JSONB columns of PostgreSQL (>= 9.4) and the JSON column type of MySQL (>= 5.7.8). For more information about concepts behind Doctrine JSON ODM, take a look at [the presentation given by Benjamin Eberlei at Symfony Catalunya 2016](https://qafoo.com/resources/presentations/symfony_catalunya_2016/doctrine_orm_and_nosql.html). @@ -26,27 +26,27 @@ To install the library, use [Composer](https://getcomposer.org/), the PHP packag composer require dunglas/doctrine-json-odm -If you are using [Symfony 4+](https://symfony.com) or [API Platform](https://api-platform.com), you have nothing more to do! +If you are using [Symfony 4+](https://symfony.com) or [API Platform](https://api-platform.com), you don't need to do anything else! If you use Doctrine directly, use a bootstrap code similar to the following: ```php setSerializer( - new Serializer([new ObjectNormalizer(new BaseObjectNormalizer())], [new JsonEncoder()]) + new Serializer([new ArrayDenormalizer(), new ObjectNormalizer()], [new JsonEncoder()]) ); } @@ -67,7 +67,9 @@ return EntityManager::create($conn, $config); ## Install with Symfony 2 and 3 -The library comes with a bundle for the [Symfony](https://symfony.com) framework. If you use Symfony 4+, it is automatically registered. For Symfony 2 and 3, you must register it yourself: +The library comes with a bundle for the [Symfony](https://symfony.com) framework. If you use Symfony 4+ and Symfony +Flex, it is automatically registered thanks to [its recipe](https://github.com/symfony/recipes-contrib/tree/master/dunglas/doctrine-json-odm). +For Symfony 2 and 3, you must register it yourself: ```php // ... From edca92ced3e03a17e6a3b53b561611ee3569a1ac Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Wed, 10 Jul 2019 09:21:52 +0200 Subject: [PATCH 3/6] Also test PHP 7.4 --- .gitignore | 1 + .travis.yml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 83b4844..3faf73f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /phpunit.xml /tests/Fixtures/cache /tests/Fixtures/logs +/var \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 9311751..e144d9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: php +dist: xenial cache: directories: @@ -23,6 +24,7 @@ php: - 7.1 - 7.2 - 7.3 + - 7.4-snapshot - nightly matrix: @@ -43,6 +45,7 @@ matrix: allow_failures: - env: deps=beta - php: nightly + - php: 7.4-snapshot before_install: - phpenv config-rm xdebug.ini || echo "xdebug not available" From 630449b2dece5cf5e89142c1e2995c0dfcb9b547 Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Wed, 10 Jul 2019 09:22:07 +0200 Subject: [PATCH 4/6] Raised minimum supported Symfony version to 3.4 --- README.md | 2 +- composer.json | 10 +++++----- .../DunglasDoctrineJsonOdmExtension.php | 16 ---------------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9c82244..91a8a2b 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ then, it is stored in a dynamic JSON column in the database. When the object will be hydrated, the JSON content of this column is transformed back to its original values, thanks again to the Symfony Serializer. -All PHP objects and structures will be preserved (if you use Symfony >= 3.1, see the FAQ). +All PHP objects and structures will be preserved. You can store any type of (serializable) PHP data structures in properties mapped using the `json_document` type. diff --git a/composer.json b/composer.json index 0006d4d..74b208b 100644 --- a/composer.json +++ b/composer.json @@ -15,14 +15,14 @@ "require": { "php": "^7.1", "doctrine/orm": "^2.6.3", - "symfony/property-access": "^2.8 || ^3.4 || ^4.1", - "symfony/property-info": "^2.8 || ^3.4 || ^4.1", - "symfony/serializer": "^2.8 || ^3.4 || ^4.1" + "symfony/property-access": "^3.4 || ^4.1", + "symfony/property-info": "^3.4 || ^4.1", + "symfony/serializer": "^3.4 || ^4.1" }, "require-dev": { "doctrine/doctrine-bundle": "^1.6", - "symfony/finder": "^2.8 || ^3.4 || ^4.1", - "symfony/framework-bundle": "^2.8 || ^3.4 || ^4.1", + "symfony/finder": "^3.4 || ^4.1", + "symfony/framework-bundle": "^3.4 || ^4.1", "symfony/phpunit-bridge": "^4.3" }, "suggest": { diff --git a/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php b/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php index a8a58b5..938ffcb 100644 --- a/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php +++ b/src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php @@ -11,11 +11,9 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; /** * @author Kévin Dunglas @@ -47,19 +45,5 @@ public function load(array $configs, ContainerBuilder $container) { $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.xml'); - - $this->defineArraySerializerIfRequired($container); - } - - /** - * BC layer for Symfony Framework Bundle <= 3.1.6. - * - * @param ContainerBuilder $container - */ - private function defineArraySerializerIfRequired(ContainerBuilder $container): void - { - if (!$container->hasDefinition('serializer.denormalizer.array')) { - $container->setDefinition('serializer.denormalizer.array', new Definition(ArrayDenormalizer::class)); - } } } From f77d4d726989745d1ffc3d8699b9f39834caefc7 Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Wed, 10 Jul 2019 10:16:43 +0200 Subject: [PATCH 5/6] Fixing tests and deprecations --- composer.json | 2 +- phpunit.xml.dist | 1 + tests/AbstractKernelTestCase.php | 29 ++++++++++++++++ tests/Fixtures/AppKernel.php | 10 ++++-- .../MakeServicesPublicPass.php | 34 +++++++++++++++++++ tests/FunctionalTest.php | 16 ++------- tests/SerializerTest.php | 19 ++--------- 7 files changed, 77 insertions(+), 34 deletions(-) create mode 100644 tests/AbstractKernelTestCase.php create mode 100644 tests/Fixtures/TestBundle/DependencyInjection/MakeServicesPublicPass.php diff --git a/composer.json b/composer.json index 74b208b..4c3d8f5 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "symfony/serializer": "^3.4 || ^4.1" }, "require-dev": { - "doctrine/doctrine-bundle": "^1.6", + "doctrine/doctrine-bundle": "^1.8", "symfony/finder": "^3.4 || ^4.1", "symfony/framework-bundle": "^3.4 || ^4.1", "symfony/phpunit-bridge": "^4.3" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7476484..6628c4a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -9,6 +9,7 @@ + diff --git a/tests/AbstractKernelTestCase.php b/tests/AbstractKernelTestCase.php new file mode 100644 index 0000000..e03a769 --- /dev/null +++ b/tests/AbstractKernelTestCase.php @@ -0,0 +1,29 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Dunglas\DoctrineJsonOdm\Tests; + +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; + +abstract class AbstractKernelTestCase extends KernelTestCase +{ + /** + * @var Application + */ + protected $application; + + protected function setUp() + { + $this->bootKernel(); + + $this->application = new Application(self::$kernel); + $this->application->setAutoExit(false); + } +} diff --git a/tests/Fixtures/AppKernel.php b/tests/Fixtures/AppKernel.php index c7f9841..f0ebd83 100644 --- a/tests/Fixtures/AppKernel.php +++ b/tests/Fixtures/AppKernel.php @@ -9,6 +9,7 @@ use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Dunglas\DoctrineJsonOdm\Bundle\DunglasDoctrineJsonOdmBundle; +use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\DependencyInjection\MakeServicesPublicPass; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\TestBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -40,15 +41,15 @@ protected function configureRoutes(RouteCollectionBuilder $routes) { } - protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) { - $c->loadFromExtension('framework', [ + $container->loadFromExtension('framework', [ 'secret' => 'jsonodm', 'test' => null, ]); $db = getenv('DB'); - $c->loadFromExtension('doctrine', [ + $container->loadFromExtension('doctrine', [ 'dbal' => [ 'driver' => 'MYSQL' === $db ? 'pdo_mysql' : 'pdo_pgsql', 'host' => getenv("{$db}_HOST"), @@ -62,5 +63,8 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'auto_mapping' => true, ], ]); + + // Make a few services public until we depend on Symfony 4.1+ and can use the new test container + $container->addCompilerPass(new MakeServicesPublicPass()); } } diff --git a/tests/Fixtures/TestBundle/DependencyInjection/MakeServicesPublicPass.php b/tests/Fixtures/TestBundle/DependencyInjection/MakeServicesPublicPass.php new file mode 100644 index 0000000..589af01 --- /dev/null +++ b/tests/Fixtures/TestBundle/DependencyInjection/MakeServicesPublicPass.php @@ -0,0 +1,34 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class MakeServicesPublicPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + static $services = [ + 'doctrine.orm.default_entity_manager', + 'doctrine.dbal.default_connection', + 'doctrine', + ]; + + foreach ($services as $service) { + if (!$container->hasDefinition($service)) { + continue; + } + + $definition = $container->getDefinition($service); + $definition->setPublic(true); + } + } +} diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index cb51954..93bb1cb 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -7,7 +7,7 @@ * with this source code in the file LICENSE. */ -namespace Dunglas\DoctrineJsonOdm\tests; +namespace Dunglas\DoctrineJsonOdm\Tests; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Attribute; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Attributes; @@ -16,26 +16,16 @@ use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Foo; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Product; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\ScalarValue; -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Console\Input\StringInput; /** * @author Kévin Dunglas */ -class FunctionalTest extends KernelTestCase +class FunctionalTest extends AbstractKernelTestCase { - /** - * @var Application - */ - private $application; - protected function setUp() { - $this->bootKernel(); - - $this->application = new Application(self::$kernel); - $this->application->setAutoExit(false); + parent::setUp(); $this->runCommand('doctrine:schema:drop --force'); $this->runCommand('doctrine:schema:create'); diff --git a/tests/SerializerTest.php b/tests/SerializerTest.php index 8d8e1dd..f12dc61 100644 --- a/tests/SerializerTest.php +++ b/tests/SerializerTest.php @@ -7,7 +7,7 @@ * with this source code in the file LICENSE. */ -namespace Dunglas\DoctrineJsonOdm\tests; +namespace Dunglas\DoctrineJsonOdm\Tests; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Attribute; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Attributes; @@ -15,27 +15,12 @@ use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Baz; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\Foo; use Dunglas\DoctrineJsonOdm\Tests\Fixtures\TestBundle\Entity\ScalarValue; -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; /** * @author Kévin Dunglas */ -class SerializerTest extends KernelTestCase +class SerializerTest extends AbstractKernelTestCase { - /** - * @var Application - */ - private $application; - - protected function setUp() - { - $this->bootKernel(); - - $this->application = new Application(self::$kernel); - $this->application->setAutoExit(false); - } - public function testStoreAndRetrieveDocument() { $attribute1 = new Attribute(); From 19cec1699ea1b30aecb77be9bf7222b27681871d Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Wed, 10 Jul 2019 10:27:16 +0200 Subject: [PATCH 6/6] Fixed PHP 7.4 testing on travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e144d9a..c0681a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ php: - 7.1 - 7.2 - 7.3 - - 7.4-snapshot + - 7.4snapshot - nightly matrix: @@ -45,7 +45,7 @@ matrix: allow_failures: - env: deps=beta - php: nightly - - php: 7.4-snapshot + - php: 7.4snapshot before_install: - phpenv config-rm xdebug.ini || echo "xdebug not available"