Skip to content

Commit 92b6346

Browse files
committed
Merge branch '1.0.x'
* 1.0.x: Add changelog entry Fix field name usage when fixing embedded document ownership Failing test case of github issue #1428 Add changelog for 1.0.6 release Prevent spl_object_hash collisions Fix exception if PersistentCollection was unserialized
2 parents d87ab17 + df0771f commit 92b6346

5 files changed

Lines changed: 176 additions & 6 deletions

File tree

CHANGELOG-1.0.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ the older and newer versions, respectively.
1212
To generate a changelog summary since the last version, run
1313
`git log --no-merges --oneline XXX...HEAD`
1414

15+
1.0.6 (2016-06-09)
16+
------------------
17+
18+
All issues and pull requests in this release may be found under the
19+
[1.0.6 milestone](https://github.com/doctrine/mongodb-odm/issues?q=milestone%3A1.0.6).
20+
21+
* [#1382](https://github.com/doctrine/mongodb-odm/pull/1382) fixes the conversion `MongoDate` objects to `DateTime`.
22+
* [#1406](https://github.com/doctrine/mongodb-odm/pull/1406) fixes queries to simple references.
23+
* [#1416](https://github.com/doctrine/mongodb-odm/pull/1416) fixes name resolution when priming references contained in embedded documents.
24+
* [#1417](https://github.com/doctrine/mongodb-odm/pull/1417) fixes unserializing PersistentCollection objects contained in documents.
25+
* [#1431](https://github.com/doctrine/mongodb-odm/pull/1431) fixes potential object hash collisions with embedded documents by keeping a copy of the document in UnitOfWork.
26+
* [#1432](https://github.com/doctrine/mongodb-odm/pull/1432) fixes the usage of embedded document field names when fixing document ownership.
27+
1528
1.0.5 (2016-02-16)
1629
------------------
1730

lib/Doctrine/ODM/MongoDB/UnitOfWork.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,8 @@ class UnitOfWork implements PropertyChangedListener
240240
private $persistenceBuilder;
241241

242242
/**
243-
* Array of parent associations between embedded documents
243+
* Array of parent associations between embedded documents.
244244
*
245-
* @todo We might need to clean up this array in clear(), doDetach(), etc.
246245
* @var array
247246
*/
248247
private $parentAssociations = array();
@@ -252,6 +251,15 @@ class UnitOfWork implements PropertyChangedListener
252251
*/
253252
private $lifecycleEventManager;
254253

254+
/**
255+
* Array of embedded documents known to UnitOfWork. We need to hold them to prevent spl_object_hash
256+
* collisions in case already managed object is lost due to GC (so now it won't). Embedded documents
257+
* found during doDetach are removed from the registry, to empty it altogether clear() can be utilized.
258+
*
259+
* @var array
260+
*/
261+
private $embeddedDocumentsRegistry = array();
262+
255263
/**
256264
* Initializes a new UnitOfWork instance, bound to the given DocumentManager.
257265
*
@@ -292,6 +300,7 @@ public function getPersistenceBuilder()
292300
public function setParentAssociation($document, $mapping, $parent, $propertyPath)
293301
{
294302
$oid = spl_object_hash($document);
303+
$this->embeddedDocumentsRegistry[$oid] = $document;
295304
$this->parentAssociations[$oid] = array($mapping, $parent, $propertyPath);
296305
}
297306

@@ -974,8 +983,8 @@ private function computeAssociationChanges($parentDocument, array $assoc, $value
974983
if ($knownParent && $knownParent !== $parentDocument) {
975984
$entry = clone $entry;
976985
if ($assoc['type'] === ClassMetadata::ONE) {
977-
$class->setFieldValue($parentDocument, $assoc['name'], $entry);
978-
$this->setOriginalDocumentProperty(spl_object_hash($parentDocument), $assoc['name'], $entry);
986+
$class->setFieldValue($parentDocument, $assoc['fieldName'], $entry);
987+
$this->setOriginalDocumentProperty(spl_object_hash($parentDocument), $assoc['fieldName'], $entry);
979988
} else {
980989
// must use unwrapped value to not trigger orphan removal
981990
$unwrappedValue[$key] = $entry;
@@ -1984,7 +1993,7 @@ private function doDetach($document, array &$visited)
19841993
$this->documentDeletions[$oid], $this->documentIdentifiers[$oid],
19851994
$this->documentStates[$oid], $this->originalDocumentData[$oid],
19861995
$this->parentAssociations[$oid], $this->documentUpserts[$oid],
1987-
$this->hasScheduledCollections[$oid]);
1996+
$this->hasScheduledCollections[$oid], $this->embeddedDocumentsRegistry[$oid]);
19881997
break;
19891998
case self::STATE_NEW:
19901999
case self::STATE_DETACHED:
@@ -2282,6 +2291,7 @@ public function clear($documentName = null)
22822291
$this->collectionUpdates =
22832292
$this->collectionDeletions =
22842293
$this->parentAssociations =
2294+
$this->embeddedDocumentsRegistry =
22852295
$this->orphanRemovals =
22862296
$this->hasScheduledCollections = array();
22872297
} else {
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace Doctrine\ODM\MongoDB\Tests\Functional;
4+
5+
use Doctrine\ODM\MongoDB\DocumentManager;
6+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
7+
use Doctrine\ODM\MongoDB\Tests\BaseTest;
8+
9+
class SplObjectHashCollisionsTest extends BaseTest
10+
{
11+
/**
12+
* @dataProvider provideParentAssociationsIsCleared
13+
*/
14+
public function testParentAssociationsIsCleared($f)
15+
{
16+
$d = new SplColDoc();
17+
$d->one = new SplColEmbed('d.one.v1');
18+
$d->many[] = new SplColEmbed('d.many.0.v1');
19+
$d->many[] = new SplColEmbed('d.many.1.v1');
20+
21+
$this->dm->persist($d);
22+
$this->expectCount('parentAssociations', 3);
23+
$this->expectCount('embeddedDocumentsRegistry', 3);
24+
$f($this->dm, $d);
25+
$this->expectCount('parentAssociations', 0);
26+
$this->expectCount('embeddedDocumentsRegistry', 0);
27+
}
28+
29+
/**
30+
* @dataProvider provideParentAssociationsIsCleared
31+
*/
32+
public function testParentAssociationsLeftover($f, $leftover)
33+
{
34+
$d = new SplColDoc();
35+
$d->one = new SplColEmbed('d.one.v1');
36+
$d->many[] = new SplColEmbed('d.many.0.v1');
37+
$d->many[] = new SplColEmbed('d.many.1.v1');
38+
$this->dm->persist($d);
39+
$d->one = new SplColEmbed('d.one.v2');
40+
$this->dm->flush();
41+
42+
$this->expectCount('parentAssociations', 4);
43+
$this->expectCount('embeddedDocumentsRegistry', 4);
44+
$f($this->dm, $d);
45+
$this->expectCount('parentAssociations', $leftover);
46+
$this->expectCount('embeddedDocumentsRegistry', $leftover);
47+
}
48+
49+
public function provideParentAssociationsIsCleared()
50+
{
51+
return array(
52+
array( function (DocumentManager $dm) { $dm->clear(); }, 0 ),
53+
array( function (DocumentManager $dm, $doc) { $dm->clear(get_class($doc)); }, 1 ),
54+
array( function (DocumentManager $dm, $doc) { $dm->detach($doc); }, 1 ),
55+
);
56+
}
57+
58+
private function expectCount($prop, $expected)
59+
{
60+
$ro = new \ReflectionObject($this->uow);
61+
$rp = $ro->getProperty($prop);
62+
$rp->setAccessible(true);
63+
$this->assertCount($expected, $rp->getValue($this->uow));
64+
}
65+
}
66+
67+
/** @ODM\Document */
68+
class SplColDoc
69+
{
70+
/** @ODM\Id */
71+
public $id;
72+
73+
/** @ODM\Field(type="string") */
74+
public $name;
75+
76+
/** @ODM\EmbedOne */
77+
public $one;
78+
79+
/** @ODM\EmbedMany */
80+
public $many = array();
81+
}
82+
83+
/** @ODM\EmbeddedDocument */
84+
class SplColEmbed
85+
{
86+
/** @ODM\Field(type="string") */
87+
public $name;
88+
89+
public function __construct($name)
90+
{
91+
$this->name = $name;
92+
}
93+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace Doctrine\ODM\MongoDB\Tests\Functional\Ticket;
4+
5+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
6+
use Doctrine\ODM\MongoDB\Tests\BaseTest;
7+
use PHPUnit_Framework_Error_Notice;
8+
9+
class GH1428Test extends BaseTest
10+
{
11+
public function testShortNameLoss_OnReplacingMiddleEmbeddedDoc_OfNestedEmbedding()
12+
{
13+
$owner = new GH1428Document();
14+
$nestedEmbedded = new GH1428NestedEmbeddedDocument();
15+
$this->dm->persist($owner);
16+
$this->dm->flush();
17+
18+
$owner->embedded = new GH1428EmbeddedDocument();
19+
$owner->embedded->nestedEmbedded = $nestedEmbedded;
20+
$this->dm->flush();
21+
22+
$owner->embedded = new GH1428EmbeddedDocument();
23+
$owner->embedded->nestedEmbedded = $nestedEmbedded;
24+
25+
try {
26+
$this->dm->flush();
27+
$this->assertTrue(true);
28+
} catch (PHPUnit_Framework_Error_Notice $ex) {
29+
$this->fail($ex);
30+
}
31+
}
32+
}
33+
34+
/** @ODM\Document */
35+
class GH1428Document
36+
{
37+
/** @ODM\Id */
38+
public $id;
39+
40+
/** @ODM\EmbedOne(targetDocument="GH1428EmbeddedDocument") */
41+
public $embedded;
42+
}
43+
44+
/** @ODM\EmbeddedDocument */
45+
class GH1428EmbeddedDocument
46+
{
47+
/** @ODM\EmbedOne(targetDocument="GH1428NestedEmbeddedDocument", name="shortNameThatDoesntExist") */
48+
public $nestedEmbedded;
49+
}
50+
51+
/** @ODM\EmbeddedDocument */
52+
class GH1428NestedEmbeddedDocument
53+
{
54+
}

tests/Doctrine/ODM/MongoDB/Tests/PersistentCollectionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function testExceptionForGetTypeClassWithoutMapping()
5454
$unserialized->setDocumentManager($this->dm);
5555
$unserialized->getTypeClass();
5656
}
57-
57+
5858
public function testGetTypeClassWorksAfterUnserialization()
5959
{
6060
$collection = new PersistentCollection(new ArrayCollection(), $this->dm, $this->uow);

0 commit comments

Comments
 (0)