Skip to content

Commit

Permalink
[MODM-36] Fixing issues with embedded collections.
Browse files Browse the repository at this point in the history
  • Loading branch information
jwage committed Aug 6, 2010
1 parent f48d762 commit 20033a3
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 79 deletions.
Expand Up @@ -17,11 +17,12 @@
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\ODM\MongoDB;
namespace Doctrine\ODM\MongoDB\Collection;

use Doctrine\Common\Collections\Collection,
Doctrine\ODM\MongoDB\Mapping\ClassMetadata,
Doctrine\ODM\MongoDB\Proxy\Proxy,
Doctrine\ODM\MongoDB\DocumentManager,
Closure;

/**
Expand All @@ -32,15 +33,15 @@
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
final class PersistentCollection implements Collection
abstract class AbstractPersistentCollection implements Collection
{
/**
* A snapshot of the collection at the moment it was fetched from the database.
* This is used to create a diff of the collection at commit time.
*
* @var array
*/
private $_snapshot = array();
protected $_snapshot = array();

protected $_owner;

Expand All @@ -51,35 +52,35 @@ final class PersistentCollection implements Collection
*
* @var Doctrine\ODM\MongoDB\DocumentManager
*/
private $_dm;
protected $_dm;

/**
* Whether the collection is dirty and needs to be synchronized with the database
* when the UnitOfWork that manages its persistent state commits.
*
* @var boolean
*/
private $_isDirty = false;
protected $_isDirty = false;

/**
* Whether the collection has already been initialized.
*
* @var boolean
*/
private $_initialized = true;
protected $_initialized = true;

/**
* The wrapped Collection instance.
*
* @var Collection
*/
private $_coll;
protected $_coll;

/**
* Mongo command prefix
* @var string
*/
private $_cmd;
protected $_cmd;

public function __construct(DocumentManager $dm, Collection $coll)
{
Expand All @@ -88,41 +89,12 @@ public function __construct(DocumentManager $dm, Collection $coll)
$this->_cmd = $dm->getConfiguration()->getMongoCmd();
}

/**
* Initializes the collection by loading its contents from the database
* if the collection is not yet initialized.
*/
private function _initialize()
{
if ( ! $this->_initialized) {
$groupedIds = array();
foreach ($this->_coll as $document) {
$class = $this->_dm->getClassMetadata(get_class($document));
$ids[$class->name][] = $class->getIdentifierObject($document);
}

foreach ($groupedIds as $className => $ids) {
$collection = $this->_dm->getDocumentCollection($className);
$data = $collection->find(array('_id' => array($this->_cmd . 'in' => $ids)));
$hints = array(Query::HINT_REFRESH => Query::HINT_REFRESH);
foreach ($data as $id => $documentData) {
$document = $this->_dm->getUnitOfWork()->getOrCreateDocument($this->_typeClass->name, $documentData, $hints);
if ($document instanceof Proxy) {
$document->__isInitialized__ = true;
unset($document->__dm);
unset($document->__identifier);
}
}
}

$this->_initialized = true;
}
}
abstract protected function _initialize();

/**
* Marks this collection as changed/dirty.
*/
private function _changed()
protected function _changed()
{
if ( ! $this->_isDirty) {
$this->_isDirty = true;
Expand Down Expand Up @@ -451,7 +423,6 @@ public function clear()
$this->_changed();
$this->_dm->getUnitOfWork()->scheduleCollectionDeletion($this);
}

return $result;
}

Expand Down
@@ -0,0 +1,53 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\ODM\MongoDB\Collection;

use Doctrine\Common\Collections\Collection,
Doctrine\ODM\MongoDB\Mapping\ClassMetadata,
Doctrine\ODM\MongoDB\Proxy\Proxy,
Closure;

/**
* A PersistentEmbeddedCollection represents a collection of embedded documents.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @since 1.0
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
final class PersistentEmbeddedCollection extends AbstractPersistentCollection
{
protected function _initialize()
{
}

/**
* {@inheritdoc}
*/
public function clear()
{
$this->_initialize();
$result = $this->_coll->clear();
if ($this->_mapping->isOwningSide) {
$this->_changed();
}
return $result;
}
}
@@ -0,0 +1,67 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\ODM\MongoDB\Collection;

use Doctrine\Common\Collections\Collection,
Doctrine\ODM\MongoDB\Mapping\ClassMetadata,
Doctrine\ODM\MongoDB\Proxy\Proxy,
Closure;

/**
* A PersistentReferenceCollection represents a collection of referenced documents.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @since 1.0
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
final class PersistentReferenceCollection extends AbstractPersistentCollection
{
/**
* Initializes the collection by loading its contents from the database
* if the collection is not yet initialized.
*/
protected function _initialize()
{
if ( ! $this->_initialized) {
$groupedIds = array();
foreach ($this->_coll as $document) {
$class = $this->_dm->getClassMetadata(get_class($document));
$ids[$class->name][] = $class->getIdentifierObject($document);
}

foreach ($groupedIds as $className => $ids) {
$collection = $this->_dm->getDocumentCollection($className);
$data = $collection->find(array('_id' => array($this->_cmd . 'in' => $ids)));
$hints = array(Query::HINT_REFRESH => Query::HINT_REFRESH);
foreach ($data as $id => $documentData) {
$document = $this->_dm->getUnitOfWork()->getOrCreateDocument($this->_typeClass->name, $documentData, $hints);
if ($document instanceof Proxy) {
$document->__isInitialized__ = true;
unset($document->__dm);
unset($document->__identifier);
}
}
}

$this->_initialized = true;
}
}
}
2 changes: 1 addition & 1 deletion lib/Doctrine/ODM/MongoDB/DocumentManager.php
Expand Up @@ -24,7 +24,7 @@
Doctrine\ODM\MongoDB\Mapping\Driver\PHPDriver,
Doctrine\ODM\MongoDB\Query,
Doctrine\ODM\MongoDB\Mongo,
Doctrine\ODM\MongoDB\PersistentCollection,
Doctrine\ODM\MongoDB\Collection\PersistentReferenceCollection,
Doctrine\ODM\MongoDB\Proxy\ProxyFactory,
Doctrine\ODM\MongoDB\Query\Parser,
Doctrine\Common\Collections\ArrayCollection,
Expand Down
7 changes: 4 additions & 3 deletions lib/Doctrine/ODM/MongoDB/Hydrator.php
Expand Up @@ -21,8 +21,9 @@

use Doctrine\ODM\MongoDB\Query,
Doctrine\ODM\MongoDB\Mapping\ClassMetadata,
Doctrine\ODM\MongoDB\PersistentCollection,
Doctrine\ODM\MongoDB\Mapping\Types\Type,
Doctrine\ODM\MongoDB\Collection\PersistentReferenceCollection,
Doctrine\ODM\MongoDB\Collection\PersistentEmbeddedCollection,
Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\Collection;

Expand Down Expand Up @@ -159,7 +160,7 @@ private function _hydrateOneReference(array $mapping, array $reference)

private function _hydrateManyReference(array $mapping, array $references)
{
$documents = new PersistentCollection($this->_dm, new ArrayCollection());
$documents = new PersistentReferenceCollection($this->_dm, new ArrayCollection());
$documents->setInitialized(false);
foreach ($references as $reference) {
$document = $this->_hydrateOneReference($mapping, $reference);
Expand Down Expand Up @@ -192,7 +193,7 @@ private function _hydrateManyEmbedded(array $mapping, array $embeddedDocuments)
$document = $this->_hydrateOneEmbedded($mapping, $embeddedDocument);
$documents->add($document);
}
return $documents;
return new PersistentEmbeddedCollection($this->_dm, $documents);
}

private function _hydrateField(array $mapping, $value)
Expand Down

0 comments on commit 20033a3

Please sign in to comment.