diff --git a/src/Form/DataTransformer/ModelToIdPropertyTransformer.php b/src/Form/DataTransformer/ModelToIdPropertyTransformer.php index 0556526b61a..6d7e841cb0c 100644 --- a/src/Form/DataTransformer/ModelToIdPropertyTransformer.php +++ b/src/Form/DataTransformer/ModelToIdPropertyTransformer.php @@ -112,9 +112,11 @@ public function reverseTransform($value) return '_labels' !== $key; }, ARRAY_FILTER_USE_KEY); - $singleIdentifierFieldName = $this->modelManager->getIdentifierFieldNames($this->className)[0]; + $query = $this->modelManager->createQuery($this->className); + $this->modelManager->addIdentifiersToQuery($this->className, $query, $ids); + $result = $this->modelManager->executeQuery($query); - foreach ($this->modelManager->findBy($this->className, [$singleIdentifierFieldName => $ids]) as $model) { + foreach ($result as $model) { $collection->add($model); } diff --git a/src/Form/DataTransformer/ModelsToArrayTransformer.php b/src/Form/DataTransformer/ModelsToArrayTransformer.php index 3c73628d61f..cb574bc6e99 100644 --- a/src/Form/DataTransformer/ModelsToArrayTransformer.php +++ b/src/Form/DataTransformer/ModelsToArrayTransformer.php @@ -168,24 +168,21 @@ public function reverseTransform($value) throw new UnexpectedTypeException($value, 'array'); } - /** @phpstan-var ArrayCollection $collection */ - $collection = $this->modelManager->getModelCollectionInstance($this->class); - $singleIdentifierFieldName = $this->modelManager->getIdentifierFieldNames($this->class)[0]; - $result = $this->modelManager->findBy($this->class, [$singleIdentifierFieldName => $value]); + $query = $this->modelManager->createQuery($this->class); + $this->modelManager->addIdentifiersToQuery($this->class, $query, $value); + $result = $this->modelManager->executeQuery($query); $diffCount = \count($value) - \count($result); if (0 !== $diffCount) { throw new TransformationFailedException(sprintf( - '%u keys could not be found in the provided values: "%s"', + '%u keys could not be found in the provided values: "%s".', $diffCount, implode('", "', $value) )); } - return []; - - return $collection; + return new ArrayCollection($result); } /** diff --git a/tests/Form/DataTransformer/ModelToIdPropertyTransformerTest.php b/tests/Form/DataTransformer/ModelToIdPropertyTransformerTest.php index 1ae051e08e1..ec0bef3dc8a 100644 --- a/tests/Form/DataTransformer/ModelToIdPropertyTransformerTest.php +++ b/tests/Form/DataTransformer/ModelToIdPropertyTransformerTest.php @@ -14,7 +14,9 @@ namespace Sonata\AdminBundle\Tests\Form\DataTransformer; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use PHPUnit\Framework\TestCase; +use Sonata\AdminBundle\Datagrid\ProxyQueryInterface; use Sonata\AdminBundle\Form\DataTransformer\ModelToIdPropertyTransformer; use Sonata\AdminBundle\Model\ModelManagerInterface; use Sonata\AdminBundle\Tests\Fixtures\Entity\Foo; @@ -58,50 +60,43 @@ public function testReverseTransform(): void */ public function testReverseTransformMultiple(array $expected, $params, Foo $entity1, Foo $entity2, Foo $entity3): void { - $transformer = new ModelToIdPropertyTransformer($this->modelManager, Foo::class, 'bar', true); - - $this->modelManager + $modelManager = $this->createMock(ModelManagerInterface::class); + $transformer = new ModelToIdPropertyTransformer($modelManager, Foo::class, 'bar', true); + $proxyQuery = $this->createMock(ProxyQueryInterface::class); + $modelManager ->expects($this->exactly($params ? 1 : 0)) - ->method('getIdentifierFieldNames') - ->willReturn(['id']); - - $this->modelManager + ->method('createQuery') + ->with($this->equalTo(Foo::class)) + ->willReturn($proxyQuery); + $modelManager ->expects($this->exactly($params ? 1 : 0)) - ->method('findBy') - ->willReturnCallback(static function (string $className, array $criteria) use ($entity1, $entity2, $entity3): array { + ->method('executeQuery') + ->with($this->equalTo($proxyQuery)) + ->willReturnCallback(static function (ProxyQueryInterface $query) use ($params, $entity1, $entity2, $entity3): array { $collection = []; - if (Foo::class !== $className || !isset($criteria['id'])) { - return $collection; - } - - if (\in_array(123, $criteria['id'], true)) { + if (\in_array(123, $params, true)) { $collection[] = $entity1; } - if (\in_array(456, $criteria['id'], true)) { + if (\in_array(456, $params, true)) { $collection[] = $entity2; } - if (\in_array(789, $criteria['id'], true)) { + if (\in_array(789, $params, true)) { $collection[] = $entity3; } return $collection; }); - $collection = new ArrayCollection(); - $this->modelManager - ->method('getModelCollectionInstance') - ->with($this->equalTo(Foo::class)) - ->willReturn($collection); - $result = $transformer->reverseTransform($params); - $this->assertInstanceOf(ArrayCollection::class, $result); + $this->assertInstanceOf(Collection::class, $result); + $this->assertCount(\count($expected), $result); $this->assertSame($expected, $result->getValues()); } - public function getReverseTransformMultipleTests() + public function getReverseTransformMultipleTests(): iterable { $entity1 = new Foo(); $entity1->setBaz(123); @@ -115,12 +110,10 @@ public function getReverseTransformMultipleTests() $entity3->setBaz(789); $entity3->setBar('example3'); - return [ - [[], null, $entity1, $entity2, $entity3], - [[], false, $entity1, $entity2, $entity3], - [[$entity1], [123, '_labels' => ['example']], $entity1, $entity2, $entity3], - [[$entity1, $entity2, $entity3], [123, 456, 789, '_labels' => ['example', 'example2', 'example3']], $entity1, $entity2, $entity3], - ]; + yield [[], null, $entity1, $entity2, $entity3]; + yield [[], false, $entity1, $entity2, $entity3]; + yield [[$entity1], [123, '_labels' => ['example']], $entity1, $entity2, $entity3]; + yield [[$entity1, $entity2, $entity3], [123, 456, 789, '_labels' => ['example', 'example2', 'example3']], $entity1, $entity2, $entity3]; } /** diff --git a/tests/Form/DataTransformer/ModelsToArrayTransformerTest.php b/tests/Form/DataTransformer/ModelsToArrayTransformerTest.php index 770002e78d5..83463f607bc 100644 --- a/tests/Form/DataTransformer/ModelsToArrayTransformerTest.php +++ b/tests/Form/DataTransformer/ModelsToArrayTransformerTest.php @@ -13,11 +13,15 @@ namespace Sonata\AdminBundle\Tests\Form\DataTransformer; +use Doctrine\Common\Collections\Collection; use PHPUnit\Framework\TestCase; +use Sonata\AdminBundle\Datagrid\ProxyQueryInterface; use Sonata\AdminBundle\Form\ChoiceList\ModelChoiceLoader; use Sonata\AdminBundle\Form\DataTransformer\ModelsToArrayTransformer; use Sonata\AdminBundle\Model\ModelManagerInterface; use Sonata\AdminBundle\Tests\Fixtures\Entity\Foo; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Exception\UnexpectedTypeException; class ModelsToArrayTransformerTest extends TestCase { @@ -44,4 +48,87 @@ public function testLegacyConstructor(): void $this->assertInstanceOf(ModelsToArrayTransformer::class, $transformer); } + + /** + * @dataProvider reverseTransformProvider + */ + public function testReverseTransform(?array $value): void + { + $modelManager = $this->createStub(ModelManagerInterface::class); + + if (null !== $value) { + $proxyQuery = $this->createStub(ProxyQueryInterface::class); + $modelManager + ->method('createQuery') + ->with($this->equalTo(Foo::class)) + ->willReturn($proxyQuery); + $modelManager + ->method('executeQuery') + ->with($this->equalTo($proxyQuery)) + ->willReturn($value); + } + + $transformer = new ModelsToArrayTransformer( + $modelManager, + Foo::class + ); + + $result = $transformer->reverseTransform($value); + + if (null === $value) { + $this->assertNull($result); + } else { + $this->assertInstanceOf(Collection::class, $result); + $this->assertCount(\count($value), $result); + } + } + + public function reverseTransformProvider(): iterable + { + yield [['a']]; + yield [['a', 'b', 3]]; + yield [null]; + } + + public function testReverseTransformUnexpectedType(): void + { + $value = 'unexpected'; + $modelManager = $this->createStub(ModelManagerInterface::class); + + $transformer = new ModelsToArrayTransformer( + $modelManager, + Foo::class + ); + + $this->expectException(UnexpectedTypeException::class); + $this->expectExceptionMessage('Expected argument of type "array", "string" given'); + + $transformer->reverseTransform($value); + } + + public function testReverseTransformFailed(): void + { + $value = ['a', 'b']; + $reverseTransformCollection = ['a']; + $modelManager = $this->createStub(ModelManagerInterface::class); + $proxyQuery = $this->createStub(ProxyQueryInterface::class); + $modelManager + ->method('createQuery') + ->with($this->equalTo(Foo::class)) + ->willReturn($proxyQuery); + $modelManager + ->method('executeQuery') + ->with($this->equalTo($proxyQuery)) + ->willReturn($reverseTransformCollection); + + $transformer = new ModelsToArrayTransformer( + $modelManager, + Foo::class + ); + + $this->expectException(TransformationFailedException::class); + $this->expectExceptionMessage('1 keys could not be found in the provided values: "a", "b".'); + + $transformer->reverseTransform($value); + } }