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,