diff --git a/src/Services/EntityMergers/Mergers/PartMerger.php b/src/Services/EntityMergers/Mergers/PartMerger.php index 731da0b7..7e96d20f 100644 --- a/src/Services/EntityMergers/Mergers/PartMerger.php +++ b/src/Services/EntityMergers/Mergers/PartMerger.php @@ -100,6 +100,12 @@ class PartMerger implements EntityMergerInterface return $target; } + private static function comparePartAssociations(PartAssociation $t, PartAssociation $o): bool { + //We compare the translation keys, as it contains info about the type and other type info + return $t->getOther() === $o->getOther() + && $t->getTypeTranslationKey() === $o->getTypeTranslationKey(); + } + private function mergeCollectionFields(Part $target, Part $other, array $context): void { /******************************************************************************** @@ -111,11 +117,29 @@ class PartMerger implements EntityMergerInterface $this->mergeAttachments($target, $other); $this->mergeParameters($target, $other); - $this->mergeCollections($target, $other, 'associated_parts_as_owner', function (PartAssociation $t, PartAssociation $o) { - //We compare the translation keys, as it contains info about the type and other type info - return $t->getOther() === $o->getOther() - && $t->getTypeTranslationKey() === $o->getTypeTranslationKey(); - }); + //Merge the associations + $this->mergeCollections($target, $other, 'associated_parts_as_owner', self::comparePartAssociations(...)); + + //We have to recreate the associations towards the other part, as they are not created by the merger + foreach ($other->getAssociatedPartsAsOther() as $association) { + //Clone the association + $clone = clone $association; + //Set the target part as the other part + $clone->setOther($target); + $owner = $clone->getOwner(); + if (!$owner) { + continue; + } + //Ensure that the association is not already present + foreach ($owner->getAssociatedPartsAsOwner() as $existing_association) { + if (self::comparePartAssociations($existing_association, $clone)) { + continue 2; + } + } + + //Add the association to the owner + $owner->addAssociatedPartsAsOwner($clone); + } $this->mergeCollections($target, $other, 'orderdetails', function (Orderdetail $t, Orderdetail $o) { //First check that the orderdetails infos are equal diff --git a/tests/Services/EntityMergers/Mergers/EntityMergerHelperTraitTest.php b/tests/Services/EntityMergers/Mergers/EntityMergerHelperTraitTest.php index 674bd524..7daedef2 100644 --- a/tests/Services/EntityMergers/Mergers/EntityMergerHelperTraitTest.php +++ b/tests/Services/EntityMergers/Mergers/EntityMergerHelperTraitTest.php @@ -213,7 +213,7 @@ class EntityMergerHelperTraitTest extends KernelTestCase $obj2->string_property = ''; $this->assertSame($obj1, $this->mergeTextWithSeparator($obj1, $obj2, 'string_property', ' # ')); $this->assertSame('Test1', $obj1->string_property); - + } public function testMergeComment(): void diff --git a/tests/Services/EntityMergers/Mergers/PartMergerTest.php b/tests/Services/EntityMergers/Mergers/PartMergerTest.php index 591172b3..d607ee72 100644 --- a/tests/Services/EntityMergers/Mergers/PartMergerTest.php +++ b/tests/Services/EntityMergers/Mergers/PartMergerTest.php @@ -20,12 +20,15 @@ namespace App\Tests\Services\EntityMergers\Mergers; +use App\Entity\Parts\AssociationType; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\Part; +use App\Entity\Parts\PartAssociation; use App\Entity\Parts\PartLot; +use App\Entity\PriceInformations\Orderdetail; use App\Services\EntityMergers\Mergers\PartMerger; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -96,6 +99,46 @@ class PartMergerTest extends KernelTestCase $this->assertTrue($merged->isNeedsReview()); } + public function testMergeOfAssociatedPartsAsOther(): void + { + //Part1 is associated with part2 and part3: + $part1 = (new Part()) + ->setName('part1'); + $part2 = (new Part()) + ->setName('part2'); + $part3 = (new Part()) + ->setName('part3'); + + $association1 = (new PartAssociation()) + ->setOther($part2) + ->setType(AssociationType::COMPATIBLE); + + $association2 = (new PartAssociation()) + ->setOther($part2) + ->setType(AssociationType::SUPERSEDES); + + $association3 = (new PartAssociation()) + ->setOther($part3) + ->setType(AssociationType::SUPERSEDES); + + $part1->addAssociatedPartsAsOwner($association1); + $part1->addAssociatedPartsAsOwner($association2); + $part1->addAssociatedPartsAsOwner($association3); + //Fill the other side of the association manually, as we have no entity manager + $part2->getAssociatedPartsAsOther()->add($association1); + $part2->getAssociatedPartsAsOther()->add($association2); + $part3->getAssociatedPartsAsOther()->add($association3); + + //Now we merge part2 into part3: + $merged = $this->merger->merge($part3, $part2); + $this->assertSame($merged, $part3); + + //Now part1 should have 4 associations, 2 with part2 and 2 with part3 + $this->assertCount(4, $part1->getAssociatedPartsAsOwner()); + $this->assertCount(2, $part1->getAssociatedPartsAsOwner()->filter(fn(PartAssociation $a) => $a->getOther() === $part2)); + $this->assertCount(2, $part1->getAssociatedPartsAsOwner()->filter(fn(PartAssociation $a) => $a->getOther() === $part3)); + } + /** * This test also functions as test for EntityMergerHelperTrait::mergeCollections() so its pretty long. * @return void