From 11c508691e3667333642e560f5e56ea664b8e0d1 Mon Sep 17 00:00:00 2001 From: Maciej Malarz Date: Tue, 30 Jun 2020 21:58:19 +0200 Subject: [PATCH] Fix updating collections with similar names --- .../Persisters/CollectionPersister.php | 3 +- .../Tests/Functional/Ticket/GH2195Test.php | 136 ++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2195Test.php diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php index e554e59e43..89a125caf9 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php @@ -459,6 +459,7 @@ private function excludeSubPaths(array $paths) : array return $paths; } sort($paths); + $paths = array_map(static function (string $path) { return $path . '.$'; }, $paths); $uniquePaths = [$paths[0]]; for ($i = 1, $count = count($paths); $i < $count; ++$i) { $lastUniquePath = end($uniquePaths); @@ -471,6 +472,6 @@ private function excludeSubPaths(array $paths) : array $uniquePaths[] = $paths[$i]; } - return $uniquePaths; + return array_map(static function (string $path) { return substr($path, 0, -2); }, $uniquePaths); } } diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2195Test.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2195Test.php new file mode 100644 index 0000000000..8b7204885a --- /dev/null +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH2195Test.php @@ -0,0 +1,136 @@ +id = (string) new ObjectId(); + + $document = new GH2195MainDocument(); + $document->id = $this->id; + + $document->property[] = new GH2195Level1(100, [[1, true], [2, true], [3, true]]); + $document->property[] = new GH2195Level1(101, [[1, true], [2, true], [3, true]]); + $document->property[] = new GH2195Level1(102, [[1, true], [2, true], [3, true]]); + + $document->property_old[] = new GH2195Level1(100, [[1, true], [2, true], [3, true]]); + $document->property_old[] = new GH2195Level1(101, [[1, true], [2, true], [3, true]]); + $document->property_old[] = new GH2195Level1(102, [[1, true], [2, true], [3, true]]); + + $this->dm->persist($document); + $this->dm->flush(); + $this->dm->clear(); + } + + public function testCollectionWithSimilarNames(): void + { + /** @var GH2195MainDocument $document */ + $document = $this->dm->find(GH2195MainDocument::class, $this->id); + + $this->assertNotNull($document); + + $document->property->remove(1); + $document->property_old->remove(2); + + $this->dm->flush(); + $this->dm->refresh($document); + + $this->assertEquals(2, $document->property->count(), 'Should have deleted 2nd element'); + $this->assertEquals(2, $document->property_old->count(), 'Should have deleted 3rd element'); + } + + public function testSubcollectionRemove(): void + { + /** @var GH2195MainDocument $document */ + $document = $this->dm->find(GH2195MainDocument::class, $this->id); + + $this->assertNotNull($document); + + $document->property_old[1]->items->remove(0); + $document->property_old->remove(2); + + $this->dm->flush(); + $this->dm->refresh($document); + + $this->assertEquals(2, $document->property_old[1]->items->count(), 'Should have deleted 1st element'); + $this->assertEquals(2, $document->property_old->count(), 'Should have deleted 3rd element'); + } +} + +/** @ODM\Document */ +class GH2195MainDocument +{ + /** + * @ODM\Id + * + * @var string + */ + public $id; + + /** + * @ODM\EmbedMany(targetDocument=GH2195Level1::class, strategy="pushAll") + */ + public $property; + + /** + * @ODM\EmbedMany(targetDocument=GH2195Level1::class) + */ + public $property_old; + + public function __construct() + { + $this->property = new ArrayCollection(); + $this->property_old = new ArrayCollection(); + } +} + +/** @ODM\EmbeddedDocument */ +class GH2195Level1 +{ + /** @ODM\Field(type="int") */ + public $value; + + /** @ODM\EmbedMany(targetDocument=GH2195Level2::class, strategy="pushAll") */ + public $items; + + public function __construct(int $value, array $items) + { + $this->value = $value; + $this->items = new ArrayCollection(); + foreach ($items as [$v, $f]) { + $this->items[] = new GH2195Level2($v, $f); + } + } +} + +/** @ODM\EmbeddedDocument */ +class GH2195Level2 +{ + /** @ODM\Field(type="int") */ + public $value; + + /** @ODM\Field(type="boolean") */ + public $is_flag; + + public function __construct(int $value, bool $is_flag) + { + $this->value = $value; + $this->is_flag = $is_flag; + } +}