diff --git a/UPGRADE-1.13.md b/UPGRADE-1.13.md index 9dd81dc43bf..b5a21b9158c 100644 --- a/UPGRADE-1.13.md +++ b/UPGRADE-1.13.md @@ -126,3 +126,8 @@ 1. Due to optimizations of the Order's grid the `Sylius\Component\Core\Repository\OrderRepositoryInterface::createSearchListQueryBuilder` method bas been deprecated and replaced by `Sylius\Component\Core\Repository\OrderRepositoryInterface::createCriteriaAwareSearchListQueryBuilder`. Also `Sylius\Component\Core\Repository\OrderRepositoryInterface::createByCustomerIdQueryBuilder` has been deprecated and replaced by `Sylius\Component\Core\Repository\OrderRepositoryInterface::createByCustomerIdCriteriaAwareQueryBuilder` for the same reason. Both changes affect `sylius_admin_order` and `sylius_admin_customer_order` grids configuration. + +1. We have explicitly added relationships between product and reviews and between product and attributes in XML mappings. + Because of that, the subscribers `Sylius\Bundle\AttributeBundle\Doctrine\ORM\Subscriber\LoadMetadataSubscriber` + and `Sylius\Bundle\ReviewBundle\Doctrine\ORM\Subscriber\LoadMetadataSubscriber` have changed so that it does not add + a relationship if one already exists. If you have overwritten or decorated it, there may be a need to update it. diff --git a/src/Sylius/Bundle/AttributeBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php b/src/Sylius/Bundle/AttributeBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php index 1824b9d9087..75bd827521e 100644 --- a/src/Sylius/Bundle/AttributeBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php +++ b/src/Sylius/Bundle/AttributeBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php @@ -50,6 +50,10 @@ private function mapSubjectOnAttributeValue( ClassMetadataInfo $metadata, ClassMetadataFactory $metadataFactory, ): void { + if ($metadata->hasAssociation('subject')) { + return; + } + /** @var ClassMetadataInfo $targetEntityMetadata */ $targetEntityMetadata = $metadataFactory->getMetadataFor($subjectClass); $subjectMapping = [ @@ -64,7 +68,7 @@ private function mapSubjectOnAttributeValue( ]], ]; - $this->mapManyToOne($metadata, $subjectMapping); + $metadata->mapManyToOne($subjectMapping); } private function mapAttributeOnAttributeValue( @@ -72,6 +76,10 @@ private function mapAttributeOnAttributeValue( ClassMetadataInfo $metadata, ClassMetadataFactory $metadataFactory, ): void { + if ($metadata->hasAssociation('attribute')) { + return; + } + /** @var ClassMetadataInfo $attributeMetadata */ $attributeMetadata = $metadataFactory->getMetadataFor($attributeClass); $attributeMapping = [ @@ -84,11 +92,6 @@ private function mapAttributeOnAttributeValue( ]], ]; - $this->mapManyToOne($metadata, $attributeMapping); - } - - private function mapManyToOne(ClassMetadataInfo $metadata, array $subjectMapping): void - { - $metadata->mapManyToOne($subjectMapping); + $metadata->mapManyToOne($attributeMapping); } } diff --git a/src/Sylius/Bundle/AttributeBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php b/src/Sylius/Bundle/AttributeBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php index 0fe95141510..1cef5923e80 100644 --- a/src/Sylius/Bundle/AttributeBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php +++ b/src/Sylius/Bundle/AttributeBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php @@ -58,23 +58,6 @@ function it_subscribes_load_class_metadata_event(): void $this->getSubscribedEvents()->shouldReturn(['loadClassMetadata']); } - function it_does_not_add_a_many_to_one_mapping_if_the_class_is_not_a_configured_attribute_value_model( - LoadClassMetadataEventArgs $eventArgs, - ClassMetadataInfo $metadata, - EntityManager $entityManager, - ClassMetadataFactory $classMetadataFactory, - ): void { - $eventArgs->getEntityManager()->willReturn($entityManager); - $entityManager->getMetadataFactory()->willReturn($classMetadataFactory); - - $eventArgs->getClassMetadata()->willReturn($metadata); - $metadata->getName()->willReturn('KeepMoving\ThisClass\DoesNot\Concern\You'); - - $metadata->mapManyToOne(Argument::any())->shouldNotBeCalled(); - - $this->loadClassMetadata($eventArgs); - } - function it_maps_many_to_one_associations_from_the_attribute_value_model_to_the_subject_model_and_the_attribute_model( LoadClassMetadataEventArgs $eventArgs, ClassMetadataInfo $metadata, @@ -82,6 +65,7 @@ function it_maps_many_to_one_associations_from_the_attribute_value_model_to_the_ ClassMetadataFactory $classMetadataFactory, ClassMetadataInfo $classMetadataInfo, ): void { + $eventArgs->getClassMetadata()->willReturn($metadata); $eventArgs->getEntityManager()->willReturn($entityManager); $entityManager->getMetadataFactory()->willReturn($classMetadataFactory); $classMetadataInfo->fieldMappings = [ @@ -92,9 +76,9 @@ function it_maps_many_to_one_associations_from_the_attribute_value_model_to_the_ $classMetadataFactory->getMetadataFor('Some\App\Product\Entity\Product')->willReturn($classMetadataInfo); $classMetadataFactory->getMetadataFor('Some\App\Product\Entity\Attribute')->willReturn($classMetadataInfo); - $eventArgs->getClassMetadata()->willReturn($metadata); - $eventArgs->getClassMetadata()->willReturn($metadata); $metadata->getName()->willReturn('Some\App\Product\Entity\AttributeValue'); + $metadata->hasAssociation('subject')->willReturn(false); + $metadata->hasAssociation('attribute')->willReturn(false); $subjectMapping = [ 'fieldName' => 'subject', @@ -124,6 +108,42 @@ function it_maps_many_to_one_associations_from_the_attribute_value_model_to_the_ $this->loadClassMetadata($eventArgs); } + function it_does_not_map_relations_for_attribute_value_model_if_the_relations_already_exist( + LoadClassMetadataEventArgs $eventArgs, + ClassMetadataInfo $metadata, + EntityManager $entityManager, + ClassMetadataFactory $classMetadataFactory, + ): void { + $eventArgs->getClassMetadata()->willReturn($metadata); + $eventArgs->getEntityManager()->willReturn($entityManager); + $entityManager->getMetadataFactory()->willReturn($classMetadataFactory); + + $metadata->getName()->willReturn('Some\App\Product\Entity\AttributeValue'); + $metadata->hasAssociation('subject')->willReturn(true); + $metadata->hasAssociation('attribute')->willReturn(true); + + $metadata->mapManyToOne(Argument::any())->shouldNotBeCalled(); + + $this->loadClassMetadata($eventArgs); + } + + function it_does_not_add_a_many_to_one_mapping_if_the_class_is_not_a_configured_attribute_value_model( + LoadClassMetadataEventArgs $eventArgs, + ClassMetadataInfo $metadata, + EntityManager $entityManager, + ClassMetadataFactory $classMetadataFactory, + ): void { + $eventArgs->getEntityManager()->willReturn($entityManager); + $entityManager->getMetadataFactory()->willReturn($classMetadataFactory); + + $eventArgs->getClassMetadata()->willReturn($metadata); + $metadata->getName()->willReturn('KeepMoving\ThisClass\DoesNot\Concern\You'); + + $metadata->mapManyToOne(Argument::any())->shouldNotBeCalled(); + + $this->loadClassMetadata($eventArgs); + } + function it_does_not_add_values_one_to_many_mapping_if_the_class_is_not_a_configured_attribute_model( LoadClassMetadataEventArgs $eventArgs, ClassMetadataInfo $metadata, diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Product.orm.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Product.orm.xml index 64ce69a3461..9d81ccedfc4 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Product.orm.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Product.orm.xml @@ -35,6 +35,12 @@ + + + + + + diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/ProductReview.orm.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/ProductReview.orm.xml index b42a3681ce6..4dad1799587 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/ProductReview.orm.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/ProductReview.orm.xml @@ -13,6 +13,17 @@ - + + + + + + + + + + + + diff --git a/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/ProductAttributeValue.orm.xml b/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/ProductAttributeValue.orm.xml index a0da0bcb42f..2ff76dbf58f 100644 --- a/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/ProductAttributeValue.orm.xml +++ b/src/Sylius/Bundle/ProductBundle/Resources/config/doctrine/model/ProductAttributeValue.orm.xml @@ -16,6 +16,14 @@ xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - + + + + + + + + + diff --git a/src/Sylius/Bundle/ReviewBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php b/src/Sylius/Bundle/ReviewBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php index 760ddf3cada..d68a6ec80a6 100644 --- a/src/Sylius/Bundle/ReviewBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php +++ b/src/Sylius/Bundle/ReviewBundle/Doctrine/ORM/Subscriber/LoadMetadataSubscriber.php @@ -38,16 +38,22 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArguments): v foreach ($this->subjects as $subject => $class) { if ($class['review']['classes']['model'] === $metadata->getName()) { - $reviewableEntity = $class['subject']; - $reviewerEntity = $class['reviewer']['classes']['model']; - $reviewableEntityMetadata = $metadataFactory->getMetadataFor($reviewableEntity); - $reviewerEntityMetadata = $metadataFactory->getMetadataFor($reviewerEntity); + if (!$metadata->hasAssociation('reviewSubject')) { + $reviewableEntity = $class['subject']; + $reviewableEntityMetadata = $metadataFactory->getMetadataFor($reviewableEntity); - $metadata->mapManyToOne($this->createSubjectMapping($reviewableEntity, $subject, $reviewableEntityMetadata)); - $metadata->mapManyToOne($this->createReviewerMapping($reviewerEntity, $reviewerEntityMetadata)); + $metadata->mapManyToOne($this->createSubjectMapping($reviewableEntity, $subject, $reviewableEntityMetadata)); + } + + if (!$metadata->hasAssociation('author')) { + $reviewerEntity = $class['reviewer']['classes']['model']; + $reviewerEntityMetadata = $metadataFactory->getMetadataFor($reviewerEntity); + + $metadata->mapManyToOne($this->createReviewerMapping($reviewerEntity, $reviewerEntityMetadata)); + } } - if ($class['subject'] === $metadata->getName()) { + if ($class['subject'] === $metadata->getName() && !$metadata->hasAssociation('reviews')) { $reviewEntity = $class['review']['classes']['model']; $metadata->mapOneToMany($this->createReviewsMapping($reviewEntity)); diff --git a/src/Sylius/Bundle/ReviewBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php b/src/Sylius/Bundle/ReviewBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php index 61ad376b853..7e07a1dd497 100644 --- a/src/Sylius/Bundle/ReviewBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php +++ b/src/Sylius/Bundle/ReviewBundle/spec/Doctrine/ORM/Subscriber/LoadMetadataSubscriberSpec.php @@ -66,7 +66,10 @@ function it_maps_proper_relations_for_review_model( $classMetadataInfo->fieldMappings = ['id' => ['columnName' => 'id']]; $metadataFactory->getMetadataFor('AcmeBundle\Entity\ReviewableModel')->willReturn($classMetadataInfo); $metadataFactory->getMetadataFor('AcmeBundle\Entity\ReviewerModel')->willReturn($classMetadataInfo); + $metadata->getName()->willReturn('AcmeBundle\Entity\ReviewModel'); + $metadata->hasAssociation('reviewSubject')->willReturn(false); + $metadata->hasAssociation('author')->willReturn(false); $metadata->mapManyToOne([ 'fieldName' => 'reviewSubject', @@ -95,6 +98,25 @@ function it_maps_proper_relations_for_review_model( $this->loadClassMetadata($eventArguments); } + function it_does_not_map_relation_for_review_model_if_the_relation_already_exists( + ClassMetadataFactory $metadataFactory, + ClassMetadata $metadata, + EntityManager $entityManager, + LoadClassMetadataEventArgs $eventArguments, + ): void { + $eventArguments->getClassMetadata()->willReturn($metadata); + $eventArguments->getEntityManager()->willReturn($entityManager); + $entityManager->getMetadataFactory()->willReturn($metadataFactory); + + $metadata->getName()->willReturn('AcmeBundle\Entity\ReviewModel'); + $metadata->hasAssociation('reviewSubject')->willReturn(true); + $metadata->hasAssociation('author')->willReturn(true); + + $metadata->mapManyToOne(Argument::any())->shouldNotBeCalled(); + + $this->loadClassMetadata($eventArguments); + } + function it_maps_proper_relations_for_reviewable_model( ClassMetadataFactory $metadataFactory, ClassMetadata $metadata, @@ -104,7 +126,9 @@ function it_maps_proper_relations_for_reviewable_model( $eventArguments->getClassMetadata()->willReturn($metadata); $eventArguments->getEntityManager()->willReturn($entityManager); $entityManager->getMetadataFactory()->willReturn($metadataFactory); + $metadata->getName()->willReturn('AcmeBundle\Entity\ReviewableModel'); + $metadata->hasAssociation('reviews')->willReturn(false); $metadata->mapOneToMany([ 'fieldName' => 'reviews', @@ -116,7 +140,25 @@ function it_maps_proper_relations_for_reviewable_model( $this->loadClassMetadata($eventArguments); } - function it_skips_mapping_configuration_if_metadata_name_is_not_different( + function it_does_not_map_relations_for_reviewable_model_if_the_relation_already_exists( + ClassMetadataFactory $metadataFactory, + ClassMetadata $metadata, + EntityManager $entityManager, + LoadClassMetadataEventArgs $eventArguments, + ): void { + $eventArguments->getClassMetadata()->willReturn($metadata); + $eventArguments->getEntityManager()->willReturn($entityManager); + $entityManager->getMetadataFactory()->willReturn($metadataFactory); + + $metadata->getName()->willReturn('AcmeBundle\Entity\ReviewableModel'); + $metadata->hasAssociation('reviews')->willReturn(true); + + $metadata->mapOneToMany(Argument::any())->shouldNotBeCalled(); + + $this->loadClassMetadata($eventArguments); + } + + function it_skips_mapping_configuration_if_metadata_name_is_different( ClassMetadataFactory $metadataFactory, ClassMetadata $metadata, EntityManager $entityManager,