Skip to content
Browse files

Adding concept of deleteBy() and restoreBy() for use in events and ca…

…scading deletes to related documents.
  • Loading branch information...
1 parent 5631161 commit c2edb9e9224baa924b2f621c86124a897bab312c @jwage jwage committed Feb 15, 2011
View
54 README.markdown
@@ -14,9 +14,8 @@ instance:
// $dm is a DocumentManager instance we should already have
$config = new Configuration();
- $uow = new UnitOfWork($dm, $config);
$evm = new EventManager();
- $sdm = new SoftDeleteManager($dm, $config, $uow, $evm);
+ $sdm = new SoftDeleteManager($dm, $config, $evm);
## SoftDelete Documents
@@ -26,7 +25,6 @@ SoftDeleteable interface:
interface SoftDeleteable
{
function getDeletedAt();
- function isDeleted();
}
An implementation might look like this:
@@ -45,11 +43,6 @@ An implementation might look like this:
{
return $this->deletedAt;
}
-
- public function isDeleted()
- {
- return $this->deletedAt !== null ? true : false;
- }
// ...
}
@@ -113,22 +106,43 @@ to the database:
$sdm->delete($fabpot);
$sdm->flush();
-## Querying for Documents
-
-Create a query builder that excludes deleted documents:
+## Cascading Soft Deletes
- $qb = $sdm->createQueryBuilder();
+You can easily implement cascading soft deletes by using events in a certain way. Imagine you have a
+User and Post document and you want to soft delete a users posts when you delete him.
-Create a query builder that returns only deleted documents:
+You just need to setup an event listener like the following:
- $qb = $sdm->createDeletedQueryBuilder();
+ use Doctrine\Common\EventSubscriber;
-If you want to modify an existing query builder to only return not deleted documents, or to only return
-deleted documents, you can use the filterQueryBuilder() method:
+ class CascadingSoftDeleteListener implements EventSubscriber
+ {
+ public function preSoftDelete(LifecycleEventArgs $args)
+ {
+ $sdm = $args->getSoftDeleteManager();
+ $document = $args->getDocument();
+ if ($document instanceof User) {
+ $sdm->deleteBy('Post', array('user.id' => $document->getId()));
+ }
+ }
- $qb = $dm->createQueryBuilder();
- $sdm->filterQueryBuilder(SoftDeleteManager::QUERY_NOT_DELETED, $qb);
+ public function preRestore(LifecycleEventArgs $args)
+ {
+ $sdm = $args->getSoftDeleteManager();
+ $document = $args->getDocument();
+ if ($document instanceof User) {
+ $sdm->restoreBy('Post', array('user.id' => $document->getId()));
+ }
+ }
-Or you can show only deleted:
+ public function getSubscribedEvents()
+ {
+ return array(
+ Events::preSoftDelete,
+ Events::preRestore
+ );
+ }
+ }
- $sdm->filterQueryBuilder(SoftDeleteManager::QUERY_DELETED, $qb);
+Now when you delete an instance of User it will also delete any Post documents where they reference
+the User being deleted. If you restore the User, his Post documents will also be restored.
View
112 lib/Doctrine/ODM/MongoDB/SoftDelete/Persister.php
@@ -20,6 +20,7 @@
namespace Doctrine\ODM\MongoDB\SoftDelete;
use Doctrine\ODM\MongoDB\DocumentManager;
+use Doctrine\ODM\MongoDB\Persisters\DocumentPersister;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\MongoDB\Collection;
use MongoDate;
@@ -49,31 +50,53 @@ class Persister
private $collection;
/**
+ * DocumentPersister instance this SoftDelete persister wraps.
+ *
+ * @var Doctrine\ODM\MongoDB\Persisters\DocumentPersister
+ */
+ private $persister;
+
+ /**
* Array of queued documents to be deleted.
*
* @var array
*/
private $queuedDeletes = array();
/**
+ * Array of custom criteria to delete by.
+ *
+ * @var array
+ */
+ private $deleteBy = array();
+
+ /**
* Array of queued documents to be restored.
*
* @var array
*/
private $queuedRestores = array();
/**
+ * Array of custom criteria to restore by.
+ *
+ * @var array
+ */
+ private $restoreBy = array();
+
+ /**
* Constructs a new Persister instance
*
* @param Configuration $configuration
* @param ClassMetadata $class
* @param Collection $collection
*/
- public function __construct(Configuration $configuration, ClassMetadata $class, Collection $collection)
+ public function __construct(Configuration $configuration, ClassMetadata $class, Collection $collection, DocumentPersister $persister)
{
$this->configuration = $configuration;
$this->class = $class;
$this->collection = $collection;
+ $this->persister = $persister;
}
/**
@@ -117,6 +140,26 @@ public function getDeletes()
}
/**
+ * Add an array of criteria to delete by.
+ *
+ * @param array $criteria
+ */
+ public function addDeleteBy(array $criteria)
+ {
+ $this->deleteBy[] = $criteria;
+ }
+
+ /**
+ * Gets the array of criteria to delete by.
+ *
+ * @return array $criteria
+ */
+ public function getDeleteBy()
+ {
+ return $this->deleteBy;
+ }
+
+ /**
* Add a SoftDeleteable document to the queued restores.
*
* @param SoftDeleteable $document
@@ -137,6 +180,26 @@ public function getRestores()
}
/**
+ * Add an array of criteria to restore by.
+ *
+ * @param array $criteria
+ */
+ public function addRestoreBy(array $criteria)
+ {
+ $this->restoreBy[] = $criteria;
+ }
+
+ /**
+ * Gets the array of criteria to restore by.
+ *
+ * @return array $criteria
+ */
+ public function getRestoreBy()
+ {
+ return $this->restoreBy;
+ }
+
+ /**
* Executes the queued deletes.
*
* @param MongoDate $date Date to the deleted field to. Mainly for testing.
@@ -153,17 +216,11 @@ public function executeDeletes(MongoDate $date = null)
'$in' => $ids
)
);
- $newObj = array(
- '$set' => array(
- $this->configuration->getDeletedFieldName() => $date ? $date : new MongoDate()
- )
- );
-
- $this->collection->update($query, $newObj, array(
- 'multiple' => true,
- 'safe' => true
- ));
-
+ $this->deleteQuery($query, $date);
+ foreach ($this->deleteBy as $criteria) {
+ $this->deleteQuery($criteria, $date);
+ }
+ $this->deleteBy = array();
$this->queuedDeletes = array();
}
@@ -182,16 +239,41 @@ public function executeRestores()
'$in' => $ids
)
);
+ $this->restoreQuery($query);
+ foreach ($this->restoreBy as $criteria) {
+ $this->restoreQuery($criteria);
+ }
+ $this->restoreBy = array();
+ $this->queuedRestores = array();
+ }
+
+ private function deleteQuery(array $query, MongoDate $date = null)
+ {
+ $newObj = array(
+ '$set' => array(
+ $this->configuration->getDeletedFieldName() => $date ? $date : new MongoDate()
+ )
+ );
+ return $this->query($query, $newObj);
+ }
+
+ private function restoreQuery(array $query)
+ {
$newObj = array(
'$unset' => array(
$this->configuration->getDeletedFieldName() => true
)
);
- $this->collection->update($query, $newObj, array(
+ return $this->query($query, $newObj);
+ }
+
+ private function query(array $query, array $newObj)
+ {
+ $query = $this->persister->prepareQuery($query);
+ $result = $this->collection->update($query, $newObj, array(
'multiple' => true,
'safe' => true
));
-
- $this->queuedRestores = array();
+ return $result;
}
}
View
306 lib/Doctrine/ODM/MongoDB/SoftDelete/SoftDeleteManager.php
@@ -22,6 +22,8 @@
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Query\Builder;
use Doctrine\Common\EventManager;
+use DateTime;
+use MongoDate;
/**
* The SoftDeleteManager class is responsible for managing the deleted state of a SoftDeleteable instance.
@@ -34,62 +36,76 @@
class SoftDeleteManager
{
/**
- * Query for DELETED documents constant.
+ * The DocumentManager instance.
+ *
+ * @var DocumentManager $dm
*/
- const QUERY_DELETED = 2;
+ private $dm;
/**
- * Query for NOT_DELETED documents constant.
+ * The SoftDelete configuration instance/
+ *
+ * @var Configuration $configuration
*/
- const QUERY_NOT_DELETED = 3;
+ private $configuration;
/**
- * DocumentManager instance this object wraps.
+ * The EventManager instance used for managing events.
*
- * @var DocumentManager $dm
+ * @var EventManager $eventManager
*/
- private $dm;
+ private $eventManager;
/**
- * The SoftDelete Configuration instance.
+ * Array of scheduled document deletes.
*
- * @var Configuration $config
+ * @var array
*/
- private $config;
+ private $documentDeletes = array();
/**
- * The SoftDelete UnitOfWork instance.
+ * Array of scheduled document restores.
*
- * @var UnitOfWork $unitOfWork
+ * @var array
*/
- private $unitOfWork;
+ private $documentRestores = array();
/**
- * The EventManager instance used for managing events.
+ * Array of special criteria to delete by.
*
- * @var EventManager $eventManager
+ * @var array
*/
- private $eventManager;
+ private $deleteBy = array();
+
+ /**
+ * Array of special criteria to restore by.
+ *
+ * @var array
+ */
+ private $restoreBy = array();
/**
- * Constructs a new SoftDeleteManager instance.
+ * Array of lazily instantiated soft delete document persisters.
+ *
+ * @var string
+ */
+ private $persisters = array();
+
+ /**
+ * Constructs a new UnitOfWork instance.
*
* @param DocumentManager $dm
* @param Configuration $configuration
- * @param UnitOfWork $unitOfWork
*/
- public function __construct(DocumentManager $dm, Configuration $configuration, UnitOfWork $unitOfWork, EventManager $eventManager = null)
+ public function __construct(DocumentManager $dm, Configuration $configuration, EventManager $eventManager)
{
$this->dm = $dm;
- $this->config = $configuration;
- $this->unitOfWork = $unitOfWork;
- $this->eventManager = $eventManager ?: new EventManager();
- $this->unitOfWork->setEventManager($this->eventManager);
- $this->unitOfWork->setSoftDeleteManager($this);
+ $this->configuration = $configuration;
+ $this->eventManager = $eventManager;
}
/**
- * Gets the DocumentManager
+ * Gets the DocumentManager instance
*
* @return DocumentManager $dm
*/
@@ -99,118 +115,258 @@ public function getDocumentManager()
}
/**
- * Gets the Configuration
+ * Gets the Configuration instance.
*
- * @return Configuration $config
+ * @return Configuration $configuration
*/
public function getConfiguration()
{
- return $this->config;
+ return $this->configuration;
}
/**
- * Gets the UnitOfWork
+ * Gets the EventManager instance/
*
- * @return UnitOfWork $unitOfWork
+ * @return EventManager $eventManager
*/
- public function getUnitOfWork()
+ public function getEventManager()
{
- return $this->unitOfWork;
+ return $this->eventManager;
}
/**
- * Gets the EventManager
+ * Gets the array of scheduled document deletes.
*
- * @return EventManager $eventManager
+ * @return array $documentDeletes
*/
- public function getEventManager()
+ public function getDocumentDeletes()
{
- return $this->eventManager;
+ return $this->documentDeletes;
}
/**
- * Creates a new query builder instance that will automatically exclude deleted documents
- * by adding a { deletedAt : { $exists : false } } condition.
+ * Gets the array of scheduled document restores.
*
- * @param string $documentName The document class name to create the query builder for.
- * @return Doctrine\MongoDB\ODM\Query\Builder $qb
+ * @return array $documentRestores
*/
- public function createQueryBuilder($documentName = null)
+ public function getDocumentRestores()
{
- return $this->filterQueryBuilder(
- self::QUERY_NOT_DELETED,
- $this->dm->createQueryBuilder($documentName)
- );
+ return $this->documentRestores;
}
/**
- * Creates a new query builder instance that will return only deleted documents
- * by adding a { deletedAt : { $exists : true } } condition.
+ * Checks if a given SoftDeleteable document instance is currently scheduled for delete.
*
- * @param string $documentName The document class name to create the query builder for.
- * @return Doctrine\MongoDB\ODM\Query\Builder $qb
+ * @param SoftDeleteable $document
*/
- public function createDeletedQueryBuilder($documentName = null)
+ public function isScheduledForDelete(SoftDeleteable $document)
{
- return $this->filterQueryBuilder(
- self::QUERY_DELETED,
- $this->dm->createQueryBuilder($documentName)
- );
+ return isset($this->documentDeletes[spl_object_hash($document)]) ? true : false;
}
/**
- * Filter query builder instances to exclude deleted documents.
+ * Checks if a given SoftDeleteable document instance is currently scheduled for restore.
*
- * @param string $type
- * @param Builder $qb
+ * @param SoftDeleteable $document
*/
- public function filterQueryBuilder($type, Builder $qb)
+ public function isScheduledForRestore(SoftDeleteable $document)
{
- switch ($type) {
- case self::QUERY_DELETED:
- $qb->field($this->config->getDeletedFieldName())->exists(true);
- break;
+ return isset($this->documentRestores[spl_object_hash($document)]) ? true : false;
+ }
- case self::QUERY_NOT_DELETED:
- $qb->field($this->config->getDeletedFieldName())->exists(false);
- break;
+ /**
+ * Gets or creates a Persister instance for the given class name.
+ *
+ * @param string $className
+ * @return Persister $persister
+ */
+ public function getDocumentPersister($className)
+ {
+ if (isset($this->persisters[$className])) {
+ return $this->persisters[$className];
}
- return $qb;
+ $class = $this->dm->getClassMetadata($className);
+ $collection = $this->dm->getDocumentCollection($className);
+ $persister = $this->dm->getUnitOfWork()->getDocumentPersister($className);
+ $this->persisters[$className] = new Persister($this->configuration, $class, $collection, $persister);
+ return $this->persisters[$className];
+ }
+
+ /**
+ * Schedule some special criteria to delete some documents by.
+ *
+ * @param string $className
+ * @param array $criteria
+ */
+ public function deleteBy($className, array $criteria)
+ {
+ $this->deleteBy[$className][] = $criteria;
+ }
+
+ /**
+ * Schedule some special criteria to restore some documents by.
+ *
+ * @param string $className
+ * @param array $criteria
+ */
+ public function restoreBy($className, array $criteria)
+ {
+ $this->restoreBy[$className][] = $criteria;
}
/**
- * Schedules a SoftDeleteable document for soft deletion on next flush().
+ * Schedules a SoftDeleteable document instance for deletion on next flush.
*
* @param SoftDeleteable $document
+ * @throws InvalidArgumentException
*/
public function delete(SoftDeleteable $document)
{
- $this->unitOfWork->delete($document);
+ $oid = spl_object_hash($document);
+ if (isset($this->documentDeletes[$oid])) {
+ throw new InvalidArgumentException('Document is already scheduled for delete.');
+ }
+
+ // If scheduled for restore then remove it
+ unset($this->documentRestores[$oid]);
+
+ if ($this->eventManager->hasListeners(Events::preSoftDelete)) {
+ $this->eventManager->dispatchEvent(Events::preSoftDelete, new Event\LifecycleEventArgs($document, $this));
+ }
+
+ $this->documentDeletes[$oid] = $document;
}
/**
- * Schedulds a SoftDeleteable document for soft delete restoration on next flush().
+ * Schedules a SoftDeleteable document instance for restoration on next flush.
*
- * @param SoftDeleteable $document
+ * @param SoftDeleteable $document
+ * @throws InvalidArgumentException
*/
public function restore(SoftDeleteable $document)
{
- $this->unitOfWork->restore($document);
+ $oid = spl_object_hash($document);
+ if (isset($this->documentRestores[$oid])) {
+ throw new InvalidArgumentException('Document is already scheduled for restore.');
+ }
+
+ // If scheduled for delete then remove it
+ unset($this->documentDeletes[$oid]);
+
+ if ($this->eventManager->hasListeners(Events::preRestore)) {
+ $this->eventManager->dispatchEvent(Events::preRestore, new Event\LifecycleEventArgs($document, $this));
+ }
+
+ $this->documentRestores[$oid] = $document;
}
/**
- * Flushes all scheduled deletions and restorations to the database.
+ * Commits all the scheduled deletions and restorations to the database.
*/
public function flush()
{
- $this->unitOfWork->commit();
+ // document deletes
+ if ($this->documentDeletes) {
+ $this->executeDeletes();
+ }
+
+ // document restores
+ if ($this->documentRestores) {
+ $this->executeRestores();
+ }
}
/**
- * Clears the UnitOfWork and erases any currently scheduled deletions or restorations.
+ * Clears the UnitOfWork and forgets any currently scheduled deletions or restorations.
*/
public function clear()
{
- $this->unitOfWork->clear();
+ $this->documentDeletes = array();
+ $this->documentRestores = array();
+ }
+
+ /**
+ * Executes the queued deletions.
+ */
+ private function executeDeletes()
+ {
+ $dateTime = new DateTime();
+ $mongoDate = new MongoDate($dateTime->getTimestamp());
+
+ $deletedFieldName = $this->configuration->getDeletedFieldName();
+
+ $persisters = array();
+ foreach ($this->deleteBy as $className => $criterias) {
+ $persister = $this->getDocumentPersister($className);
+ $persisters[$className] = $persister;
+ foreach ($criterias as $criteria) {
+ $persister->addDeleteBy($criteria);
+ }
+ }
+ $documentDeletes = array();
+ foreach ($this->documentDeletes as $document) {
+ $className = get_class($document);
+ $documentDeletes[$className][] = $document;
+ $persister = $this->getDocumentPersister($className);
+ $persisters[$className] = $persister;
+ $persister->addDelete($document);
+ }
+ foreach ($persisters as $className => $persister) {
+ $persister->executeDeletes($mongoDate);
+
+ $class = $this->dm->getClassMetadata($className);
+
+ if (isset($documentDeletes[$className])) {
+ $documents = $documentDeletes[$className];
+ foreach ($documents as $document) {
+ $class->setFieldValue($document, $deletedFieldName, $dateTime);
+
+ if ($this->eventManager->hasListeners(Events::postSoftDelete)) {
+ $this->eventManager->dispatchEvent(Events::postSoftDelete, new Event\LifecycleEventArgs($document, $this));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Executes the queued restorations.
+ */
+ private function executeRestores()
+ {
+ $deletedFieldName = $this->configuration->getDeletedFieldName();
+
+ $persisters = array();
+ foreach ($this->restoreBy as $className => $criterias) {
+ $persister = $this->getDocumentPersister($className);
+ $persisters[$className] = $persister;
+ foreach ($criterias as $criteria) {
+ $persister->addRestoreBy($criteria);
+ }
+ }
+ $documentRestores = array();
+ foreach ($this->documentRestores as $document) {
+ $className = get_class($document);
+ $documentRestores[$className][] = $document;
+ $persister = $this->getDocumentPersister($className);
+ $persisters[$className] = $persister;
+ $persister->addRestore($document);
+ }
+ foreach ($persisters as $className => $persister) {
+ $persister->executeRestores();
+
+ $class = $this->dm->getClassMetadata($className);
+
+ if (isset($documentRestores[$className])) {
+ $documents = $documentRestores[$className];
+ foreach ($documents as $document) {
+ $class->setFieldValue($document, $deletedFieldName, null);
+
+ if ($this->eventManager->hasListeners(Events::postRestore)) {
+ $this->eventManager->dispatchEvent(Events::postRestore, new Event\LifecycleEventArgs($document, $this));
+ }
+ }
+ }
+ }
}
}
View
7 lib/Doctrine/ODM/MongoDB/SoftDelete/SoftDeleteable.php
@@ -38,11 +38,4 @@
* @return DateTime $deletedAt
*/
function getDeletedAt();
-
- /**
- * Checks whether this object is deleted or not.
- *
- * @return boolean $isDeleted
- */
- function isDeleted();
}
View
342 lib/Doctrine/ODM/MongoDB/SoftDelete/UnitOfWork.php
@@ -1,342 +0,0 @@
-<?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\SoftDelete;
-
-use Doctrine\ODM\MongoDB\DocumentManager;
-use Doctrine\ODM\MongoDB\SoftDelete\Configuration;
-use Doctrine\Common\EventManager;
-use InvalidArgumentException;
-use DateTime;
-
-/**
- * UnitOfWork is responsible for tracking the deleted state of objects and giving you the ability
- * to queue deletions and restorations to be committed.
- *
- * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
- * @link www.doctrine-project.com
- * @since 1.0
- * @author Jonathan H. Wage <jonwage@gmail.com>
- */
-class UnitOfWork
-{
- /**
- * The DocumentManager instance.
- *
- * @var DocumentManager $dm
- */
- private $dm;
-
- /**
- * The SoftDeleteManager instance.
- *
- * @var string
- */
- private $sdm;
-
- /**
- * The SoftDelete configuration instance/
- *
- * @var Configuration $configuration
- */
- private $configuration;
-
- /**
- * The EventManager instance used for managing events.
- *
- * @var EventManager $eventManager
- */
- private $eventManager;
-
- /**
- * Array of scheduled document deletes.
- *
- * @var array
- */
- private $documentDeletes = array();
-
- /**
- * Array of scheduled document restores.
- *
- * @var array
- */
- private $documentRestores = array();
-
- /**
- * Array of lazily instantiated soft delete document persisters.
- *
- * @var string
- */
- private $persisters = array();
-
- /**
- * Constructs a new UnitOfWork instance.
- *
- * @param DocumentManager $dm
- * @param Configuration $configuration
- */
- public function __construct(DocumentManager $dm, Configuration $configuration)
- {
- $this->dm = $dm;
- $this->configuration = $configuration;
- }
-
- /**
- * Sets the SoftDeleteManager this UnitOfWork belongs to.
- *
- * @param SoftDeleteManager $sdm
- */
- public function setSoftDeleteManager(SoftDeleteManager $sdm)
- {
- $this->sdm = $sdm;
- }
-
- /**
- * Gets the SoftDeleteManager this UnitOfWork belongs to.
- *
- * @return SoftDeleteManager $sdm
- */
- public function getSoftDeleteManager()
- {
- return $this->sdm;
- }
-
- /**
- * Sets the UnitOfWork event manager.
- *
- * @param EventManager $eventManager
- */
- public function setEventManager(EventManager $eventManager)
- {
- $this->eventManager = $eventManager;
- }
-
- /**
- * Gets the UnitOfWork event manager.
- *
- * @return EventManager $eventManager
- */
- public function getEventManager()
- {
- return $this->eventManager;
- }
-
- /**
- * Gets the DocumentManager instance
- *
- * @return DocumentManager $dm
- */
- public function getDocumentManager()
- {
- return $this->dm;
- }
-
- /**
- * Gets the array of scheduled document deletes.
- *
- * @return array $documentDeletes
- */
- public function getDocumentDeletes()
- {
- return $this->documentDeletes;
- }
-
- /**
- * Gets the array of scheduled document restores.
- *
- * @return array $documentRestores
- */
- public function getDocumentRestores()
- {
- return $this->documentRestores;
- }
-
- /**
- * Checks if a given SoftDeleteable document instance is currently scheduled for delete.
- *
- * @param SoftDeleteable $document
- */
- public function isScheduledForDelete(SoftDeleteable $document)
- {
- return isset($this->documentDeletes[spl_object_hash($document)]) ? true : false;
- }
-
- /**
- * Checks if a given SoftDeleteable document instance is currently scheduled for restore.
- *
- * @param SoftDeleteable $document
- */
- public function isScheduledForRestore(SoftDeleteable $document)
- {
- return isset($this->documentRestores[spl_object_hash($document)]) ? true : false;
- }
-
- /**
- * Gets or creates a Persister instance for the given class name.
- *
- * @param string $className
- * @return Persister $persister
- */
- public function getDocumentPersister($className)
- {
- if (isset($this->persisters[$className])) {
- return $this->persisters[$className];
- }
- $class = $this->dm->getClassMetadata($className);
- $collection = $this->dm->getDocumentCollection($className);
- $this->persisters[$className] = new Persister($this->configuration, $class, $collection);
- return $this->persisters[$className];
- }
-
- /**
- * Schedules a SoftDeleteable document instance for deletion on next flush.
- *
- * @param SoftDeleteable $document
- * @throws InvalidArgumentException
- */
- public function delete(SoftDeleteable $document)
- {
- $oid = spl_object_hash($document);
- if (isset($this->documentDeletes[$oid])) {
- throw new InvalidArgumentException('Document is already scheduled for delete.');
- }
-
- // If scheduled for restore then remove it
- unset($this->documentRestores[$oid]);
-
- $this->documentDeletes[$oid] = $document;
- }
-
- /**
- * Schedules a SoftDeleteable document instance for restoration on next flush.
- *
- * @param SoftDeleteable $document
- * @throws InvalidArgumentException
- */
- public function restore(SoftDeleteable $document)
- {
- $oid = spl_object_hash($document);
- if (isset($this->documentRestores[$oid])) {
- throw new InvalidArgumentException('Document is already scheduled for restore.');
- }
-
- // If scheduled for delete then remove it
- unset($this->documentDeletes[$oid]);
-
- $this->documentRestores[$oid] = $document;
- }
-
- /**
- * Commits all the scheduled deletions and restorations to the database.
- */
- public function commit()
- {
- // document deletes
- if ($this->documentDeletes) {
- $this->executeDeletes();
- }
-
- // document restores
- if ($this->documentRestores) {
- $this->executeRestores();
- }
- }
-
- /**
- * Clears the UnitOfWork and forgets any currently scheduled deletions or restorations.
- */
- public function clear()
- {
- $this->documentDeletes = array();
- $this->documentRestores = array();
- }
-
- /**
- * Executes the queued deletions.
- */
- private function executeDeletes()
- {
- $deletedFieldName = $this->configuration->getDeletedFieldName();
-
- $documentDeletes = array();
- foreach ($this->documentDeletes as $document) {
- $className = get_class($document);
- $documentDeletes[$className][] = $document;
- }
- foreach ($documentDeletes as $className => $documents) {
- $persister = $this->getDocumentPersister($className);
- foreach ($documents as $document) {
-
- if ($this->eventManager->hasListeners(Events::preSoftDelete)) {
- $this->eventManager->dispatchEvent(Events::preSoftDelete, new Event\LifecycleEventArgs($document, $this->sdm));
- }
-
- $persister->addDelete($document);
- }
- $persister->executeDeletes();
-
- $class = $this->dm->getClassMetadata($className);
-
- $date = new DateTime();
- foreach ($documents as $document) {
- $class->setFieldValue($document, $deletedFieldName, $date);
-
- if ($this->eventManager->hasListeners(Events::postSoftDelete)) {
- $this->eventManager->dispatchEvent(Events::postSoftDelete, new Event\LifecycleEventArgs($document, $this->sdm));
- }
- }
- }
- }
-
- /**
- * Executes the queued restorations.
- */
- private function executeRestores()
- {
- $deletedFieldName = $this->configuration->getDeletedFieldName();
-
- $documentRestores = array();
- foreach ($this->documentRestores as $document) {
- $className = get_class($document);
- $documentRestores[$className][] = $document;
- }
- foreach ($documentRestores as $className => $documents) {
- $persister = $this->getDocumentPersister($className);
- foreach ($documents as $document) {
-
- if ($this->eventManager->hasListeners(Events::preRestore)) {
- $this->eventManager->dispatchEvent(Events::preRestore, new Event\LifecycleEventArgs($document, $this->sdm));
- }
-
- $persister->addRestore($document);
- }
- $persister->executeRestores();
-
- $class = $this->dm->getClassMetadata($className);
-
- foreach ($documents as $document) {
- $class->setFieldValue($document, $deletedFieldName, null);
-
- if ($this->eventManager->hasListeners(Events::postRestore)) {
- $this->eventManager->dispatchEvent(Events::postRestore, new Event\LifecycleEventArgs($document, $this->sdm));
- }
- }
- }
- }
-}
2 lib/vendor/doctrine-mongodb
@@ -1 +1 @@
-Subproject commit a467d22d6ccbcae42aa89f4cdf6d35ea957b5ff9
+Subproject commit 92e26e53e42829f9ea204199a2828e0ff0ed49f7
2 lib/vendor/doctrine-mongodb-odm
@@ -1 +1 @@
-Subproject commit a0667bb05867b101333c6031daeedff80f937b8a
+Subproject commit ee0dd4811b2295d95291451f1b77e82509055568
View
228 tests/Doctrine/ODM/MongoDB/SoftDelete/Tests/FunctionalTest.php
@@ -4,7 +4,6 @@
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Configuration as ODMConfiguration;
-use Doctrine\ODM\MongoDB\SoftDelete\UnitOfWork;
use Doctrine\ODM\MongoDB\SoftDelete\Configuration;
use Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteManager;
use Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteable;
@@ -18,137 +17,167 @@
class FunctionalTest extends PHPUnit_Framework_TestCase
{
+ private $sdm;
+ private $dm;
+
public function setUp()
{
$this->sdm = $this->getTestSoftDeleteManager();
$this->dm = $this->sdm->getDocumentManager();
$this->dm->getDocumentCollection(__NAMESPACE__.'\Seller')->drop();
+ $this->dm->getDocumentCollection(__NAMESPACE__.'\Sellable')->drop();
}
public function testDelete()
{
- $softDeleteable = $this->getTestSoftDeleteable('jwage');
- $this->dm->persist($softDeleteable);
+ $seller = $this->getTestSeller('jwage');
+ $this->dm->persist($seller);
$this->dm->flush();
- $this->sdm->delete($softDeleteable);
+ $this->sdm->delete($seller);
$this->sdm->flush();
- $this->assertTrue($softDeleteable->isDeleted());
- $this->assertInstanceOf('DateTime', $softDeleteable->getDeletedAt());
+ $this->assertInstanceOf('DateTime', $seller->getDeletedAt());
- $check = $this->dm->getDocumentCollection(get_class($softDeleteable))->findOne();
+ $check = $this->dm->getDocumentCollection(get_class($seller))->findOne();
$this->assertTrue(isset($check['deletedAt']));
$this->assertInstanceOf('MongoDate', $check['deletedAt']);
}
public function testDeleteMultiple()
{
- $softDeleteable1 = $this->getTestSoftDeleteable('jwage1');
- $softDeleteable2 = $this->getTestSoftDeleteable('jwage2');
- $this->dm->persist($softDeleteable1);
- $this->dm->persist($softDeleteable2);
+ $seller1 = $this->getTestSeller('jwage1');
+ $seller2 = $this->getTestSeller('jwage2');
+ $this->dm->persist($seller1);
+ $this->dm->persist($seller2);
$this->dm->flush();
- $this->sdm->delete($softDeleteable1);
- $this->sdm->delete($softDeleteable2);
+ $this->sdm->delete($seller1);
+ $this->sdm->delete($seller2);
$this->sdm->flush();
- $this->assertTrue($softDeleteable1->isDeleted());
- $this->assertInstanceOf('DateTime', $softDeleteable1->getDeletedAt());
- $this->assertTrue($softDeleteable2->isDeleted());
- $this->assertInstanceOf('DateTime', $softDeleteable2->getDeletedAt());
+ $this->assertInstanceOf('DateTime', $seller1->getDeletedAt());
+ $this->assertInstanceOf('DateTime', $seller2->getDeletedAt());
- $check1 = $this->dm->getDocumentCollection(get_class($softDeleteable1))->findOne();
+ $check1 = $this->dm->getDocumentCollection(get_class($seller1))->findOne();
$this->assertTrue(isset($check1['deletedAt']));
$this->assertInstanceOf('MongoDate', $check1['deletedAt']);
- $check2 = $this->dm->getDocumentCollection(get_class($softDeleteable2))->findOne();
+ $check2 = $this->dm->getDocumentCollection(get_class($seller2))->findOne();
$this->assertTrue(isset($check2['deletedAt']));
$this->assertInstanceOf('MongoDate', $check2['deletedAt']);
- $this->sdm->restore($softDeleteable1);
- $this->sdm->restore($softDeleteable2);
+ $this->sdm->restore($seller1);
+ $this->sdm->restore($seller2);
$this->sdm->flush();
- $check1 = $this->dm->getDocumentCollection(get_class($softDeleteable1))->findOne();
+ $check1 = $this->dm->getDocumentCollection(get_class($seller1))->findOne();
$this->assertFalse(isset($check1['deletedAt']));
- $check2 = $this->dm->getDocumentCollection(get_class($softDeleteable2))->findOne();
+ $check2 = $this->dm->getDocumentCollection(get_class($seller2))->findOne();
$this->assertFalse(isset($check2['deletedAt']));
}
public function testRestore()
{
- $softDeleteable = $this->getTestSoftDeleteable('jwage');
- $this->dm->persist($softDeleteable);
+ $seller = $this->getTestSeller('jwage');
+ $this->dm->persist($seller);
$this->dm->flush();
- $this->sdm->delete($softDeleteable);
+ $this->sdm->delete($seller);
$this->sdm->flush();
- $check = $this->dm->getDocumentCollection(get_class($softDeleteable))->findOne();
+ $check = $this->dm->getDocumentCollection(get_class($seller))->findOne();
$this->assertTrue(isset($check['deletedAt']));
$this->assertInstanceOf('MongoDate', $check['deletedAt']);
- $this->sdm->restore($softDeleteable);
+ $this->sdm->restore($seller);
$this->sdm->flush();
- $this->assertFalse($softDeleteable->isDeleted());
- $this->assertNull($softDeleteable->getDeletedAt());
+ $this->assertNull($seller->getDeletedAt());
- $check = $this->dm->getDocumentCollection(get_class($softDeleteable))->findOne();
+ $check = $this->dm->getDocumentCollection(get_class($seller))->findOne();
$this->assertFalse(isset($check['deletedAt']));
}
- public function testCreateQueryBuilder()
+ public function testEvents()
{
- $softDeleteable = $this->getTestSoftDeleteable('jwage');
- $this->dm->persist($softDeleteable);
- $this->dm->flush();
+ $eventManager = $this->sdm->getEventManager();
+ $eventSubscriber = new TestEventSubscriber();
+ $eventManager->addEventSubscriber($eventSubscriber);
- $check = $this->sdm->createQueryBuilder(get_class($softDeleteable))
- ->getQuery()
- ->getSingleResult();
- $this->assertNotNull($check);
+ $seller = $this->getTestSeller('jwage');
+ $this->dm->persist($seller);
+ $this->dm->flush();
- $this->sdm->delete($softDeleteable);
+ $this->sdm->delete($seller);
$this->sdm->flush();
- $check = $this->sdm->createQueryBuilder(get_class($softDeleteable))
- ->getQuery()
- ->getSingleResult();
- $this->assertNull($check);
+ $this->assertEquals(array('preSoftDelete', 'postSoftDelete'), $eventSubscriber->called);
- $check = $this->sdm->createDeletedQueryBuilder(get_class($softDeleteable))
- ->getQuery()
- ->getSingleResult();
- $this->assertNotNull($check);
- $this->assertTrue($check->isDeleted());
- $this->assertInstanceOf('DateTime', $check->getDeletedAt());
+ $eventSubscriber->called = array();
+
+ $this->sdm->restore($seller);
+ $this->sdm->flush();
+
+ $this->assertEquals(array('preRestore', 'postRestore'), $eventSubscriber->called);
}
- public function testEvents()
+ public function testCascading()
{
$eventManager = $this->sdm->getEventManager();
- $eventSubscriber = new TestEventSubscriber();
+ $eventSubscriber = new TestCascadeDeleteAndRestore();
$eventManager->addEventSubscriber($eventSubscriber);
- $softDeleteable = $this->getTestSoftDeleteable('jwage');
- $this->dm->persist($softDeleteable);
+ $seller = $this->getTestSeller('jwage');
+ $sellable1 = $this->getTestSellable($seller);
+ $sellable2 = $this->getTestSellable($seller);
+ $this->dm->persist($seller);
+ $this->dm->persist($sellable1);
+ $this->dm->persist($sellable2);
$this->dm->flush();
- $this->sdm->delete($softDeleteable);
+ $this->sdm->delete($seller);
$this->sdm->flush();
- $this->assertEquals(array('preSoftDelete', 'postSoftDelete'), $eventSubscriber->called);
+ $count = $this->dm->createQueryBuilder(get_class($seller))
+ ->field('deletedAt')->exists(false)
+ ->getQuery()
+ ->count();
+ $this->assertEquals(0, $count);
- $eventSubscriber->called = array();
+ $count = $this->dm->createQueryBuilder(get_class($seller))
+ ->field('deletedAt')->exists(true)
+ ->getQuery()
+ ->count();
+ $this->assertEquals(1, $count);
+
+ $count = $this->dm->createQueryBuilder(get_class($sellable1))
+ ->field('deletedAt')->exists(false)
+ ->getQuery()
+ ->count();
+ $this->assertEquals(0, $count);
- $this->sdm->restore($softDeleteable);
+ $count = $this->dm->createQueryBuilder(get_class($sellable1))
+ ->field('deletedAt')->exists(true)
+ ->getQuery()
+ ->count();
+ $this->assertEquals(2, $count);
+
+ $this->sdm->restore($seller);
$this->sdm->flush();
- $this->assertEquals(array('preRestore', 'postRestore'), $eventSubscriber->called);
+ $count = $this->dm->createQueryBuilder(get_class($seller))
+ ->field('deletedAt')->exists(false)
+ ->getQuery()
+ ->count();
+ $this->assertEquals(1, $count);
+
+ $count = $this->dm->createQueryBuilder(get_class($sellable1))
+ ->field('deletedAt')->exists(false)
+ ->getQuery()
+ ->count();
+ $this->assertEquals(2, $count);
}
private function getTestDocumentManager()
@@ -165,22 +194,22 @@ private function getTestDocumentManager()
$configuration->setMetadataDriverImpl($annotationDriver);
$conn = new Connection(null, array(), $configuration);
- return DocumentManager::create($conn, $configuration);
+ return DocumentManager::create($conn, null, $configuration);
}
- public function getTestSoftDeleteable($name)
+ public function getTestSeller($name)
{
return new Seller($name);
}
- public function getTestConfiguration()
+ public function getTestSellable(Seller $seller)
{
- return new Configuration();
+ return new Sellable($seller);
}
- public function getTestUnitOfWork(DocumentManager $dm, Configuration $configuration)
+ public function getTestConfiguration()
{
- return new UnitOfWork($dm, $configuration);
+ return new Configuration();
}
public function getTestEventManager()
@@ -192,9 +221,37 @@ private function getTestSoftDeleteManager()
{
$dm = $this->getTestDocumentManager();
$configuration = $this->getTestConfiguration();
- $unitOfWork = $this->getTestUnitOfWork($dm, $configuration);
$eventManager = $this->getTestEventManager();
- return new SoftDeleteManager($dm, $configuration, $unitOfWork, $eventManager);
+ return new SoftDeleteManager($dm, $configuration, $eventManager);
+ }
+}
+
+class TestCascadeDeleteAndRestore implements \Doctrine\Common\EventSubscriber
+{
+ public function preSoftDelete(LifecycleEventArgs $args)
+ {
+ $sdm = $args->getSoftDeleteManager();
+ $document = $args->getDocument();
+ if ($document instanceof Seller) {
+ $sdm->deleteBy(__NAMESPACE__.'\Sellable', array('seller.id' => $document->getId()));
+ }
+ }
+
+ public function preRestore(LifecycleEventArgs $args)
+ {
+ $sdm = $args->getSoftDeleteManager();
+ $document = $args->getDocument();
+ if ($document instanceof Seller) {
+ $sdm->restoreBy(__NAMESPACE__.'\Sellable', array('seller.id' => $document->getId()));
+ }
+ }
+
+ public function getSubscribedEvents()
+ {
+ return array(
+ Events::preSoftDelete,
+ Events::preRestore
+ );
}
}
@@ -250,6 +307,11 @@ public function __construct($name)
$this->name = $name;
}
+ public function getId()
+ {
+ return $this->id;
+ }
+
public function getName()
{
return $this->name;
@@ -259,9 +321,37 @@ public function getDeletedAt()
{
return $this->deletedAt;
}
+}
- public function isDeleted()
+/** @Document */
+class Sellable implements SoftDeleteable
+{
+ /** @Id */
+ private $id;
+
+ /** @Date @Index */
+ private $deletedAt;
+
+ /** @ReferenceOne(targetDocument="Seller") */
+ private $seller;
+
+ public function __construct(Seller $seller)
+ {
+ $this->seller = $seller;
+ }
+
+ public function getId()
{
- return $this->deletedAt !== null ? true : false;
+ return $this->id;
+ }
+
+ public function getSeller()
+ {
+ return $this->seller;
+ }
+
+ public function getDeletedAt()
+ {
+ return $this->deletedAt;
}
}
View
40 tests/Doctrine/ODM/MongoDB/SoftDelete/Tests/PersisterTest.php
@@ -6,6 +6,7 @@
use Doctrine\ODM\MongoDB\SoftDelete\Persister;
use Doctrine\ODM\MongoDB\SoftDelete\Configuration;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
+use Doctrine\ODM\MongoDB\Persisters\DocumentPersister;
use Doctrine\MongoDB\Collection;
use MongoDate;
@@ -16,7 +17,8 @@ public function testConstructor()
$class = $this->getMockClassMetadata();
$collection = $this->getMockCollection();
$configuration = $this->getMockConfiguration();
- $persister = $this->getTestPersister($configuration, $class, $collection);
+ $documentPersister = $this->getMockDocumentPersister();
+ $persister = $this->getTestPersister($configuration, $class, $collection, $documentPersister);
$this->assertSame($class, $persister->getClass());
$this->assertSame($collection, $persister->getCollection());
}
@@ -26,7 +28,8 @@ public function testAddDelete()
$class = $this->getMockClassMetadata();
$collection = $this->getMockCollection();
$configuration = $this->getMockConfiguration();
- $persister = $this->getTestPersister($configuration, $class, $collection);
+ $documentPersister = $this->getMockDocumentPersister();
+ $persister = $this->getTestPersister($configuration, $class, $collection, $documentPersister);
$mockSoftDeleteable = $this->getMockSoftDeletable();
$persister->addDelete($mockSoftDeleteable);
@@ -39,7 +42,9 @@ public function testAddRestore()
$class = $this->getMockClassMetadata();
$collection = $this->getMockCollection();
$configuration = $this->getMockConfiguration();
- $persister = $this->getTestPersister($configuration, $class, $collection); $mockSoftDeleteable = $this->getMockSoftDeletable();
+ $documentPersister = $this->getMockDocumentPersister();
+ $persister = $this->getTestPersister($configuration, $class, $collection, $documentPersister);
+ $mockSoftDeleteable = $this->getMockSoftDeletable();
$persister->addRestore($mockSoftDeleteable);
$expects = array(spl_object_hash($mockSoftDeleteable) => $mockSoftDeleteable);
@@ -58,11 +63,12 @@ public function testExecuteDeletes()
$date = new MongoDate();
+ $query = array('_id' => array('$in' => array(1)));
$collection = $this->getMockCollection();
$collection->expects($this->once())
->method('update')
->with(
- array('_id' => array('$in' => array(1))),
+ $query,
array('$set' => array(
'deletedAt' => $date
)),
@@ -77,7 +83,11 @@ public function testExecuteDeletes()
->method('getDeletedFieldName')
->will($this->returnValue('deletedAt'));
- $persister = $this->getTestPersister($configuration, $class, $collection);
+ $documentPersister = $this->getMockDocumentPersister();
+ $documentPersister->expects($this->once())
+ ->method('prepareQuery')
+ ->will($this->returnValue($query));
+ $persister = $this->getTestPersister($configuration, $class, $collection, $documentPersister);
$persister->addDelete($mockSoftDeleteable);
$persister->executeDeletes($date);
}
@@ -92,11 +102,12 @@ public function testExecuteRestores()
->with($mockSoftDeleteable)
->will($this->returnValue(1));
+ $query = array('_id' => array('$in' => array(1)));
$collection = $this->getMockCollection();
$collection->expects($this->once())
->method('update')
->with(
- array('_id' => array('$in' => array(1))),
+ $query,
array('$unset' => array(
'deletedAt' => true
)),
@@ -111,7 +122,11 @@ public function testExecuteRestores()
->method('getDeletedFieldName')
->will($this->returnValue('deletedAt'));
- $persister = $this->getTestPersister($configuration, $class, $collection);
+ $documentPersister = $this->getMockDocumentPersister();
+ $documentPersister->expects($this->once())
+ ->method('prepareQuery')
+ ->will($this->returnValue($query));
+ $persister = $this->getTestPersister($configuration, $class, $collection, $documentPersister);
$persister->addRestore($mockSoftDeleteable);
$persister->executeRestores();
}
@@ -144,8 +159,15 @@ private function getMockConfiguration()
->getMock();
}
- private function getTestPersister(Configuration $configuration, ClassMetadata $class, Collection $collection)
+ private function getMockDocumentPersister()
+ {
+ return $this->getMockBuilder('Doctrine\ODM\MongoDB\Persisters\DocumentPersister')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ private function getTestPersister(Configuration $configuration, ClassMetadata $class, Collection $collection, DocumentPersister $persister)
{
- return new Persister($configuration, $class, $collection);
+ return new Persister($configuration, $class, $collection, $persister);
}
}
View
5 tests/Doctrine/ODM/MongoDB/SoftDelete/Tests/SoftDeletableTest.php
@@ -17,12 +17,7 @@ public function testSoftDeleteable()
->method('getDeletedAt')
->will($this->returnValue($date));
- $mockSoftDeleteable->expects($this->once())
- ->method('isDeleted')
- ->will($this->returnValue(true));
-
$this->assertSame($date, $mockSoftDeleteable->getDeletedAt());
- $this->assertTrue($mockSoftDeleteable->isDeleted());
}
private function getMockSoftDeleteable()
View
153 tests/Doctrine/ODM/MongoDB/SoftDelete/Tests/SoftDeleteManagerTest.php
@@ -2,151 +2,53 @@
namespace Doctrine\ODM\MongoDB\SoftDelete\Tests;
-use PHPUnit_Framework_TestCase;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteManager;
use Doctrine\ODM\MongoDB\SoftDelete\Configuration;
-use Doctrine\ODM\MongoDB\SoftDelete\UnitOfWork;
+use Doctrine\Common\EventManager;
+use PHPUnit_Framework_TestCase;
class SoftDeleteManagerTest extends PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$dm = $this->getMockDocumentManager();
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
- $this->assertSame($dm, $sdm->getDocumentManager());
- }
-
- public function testCreateQueryBuilder()
- {
- $mockQb = $this->getMockQb();
-
- $dm = $this->getMockDocumentManager();
- $dm->expects($this->once())
- ->method('createQueryBuilder')
- ->will($this->returnValue($mockQb));
-
- $mockQb->expects($this->once())
- ->method('field')
- ->with('deletedAt')
- ->will($this->returnValue($mockQb));
-
- $mockQb->expects($this->once())
- ->method('exists')
- ->with(false)
- ->will($this->returnValue($mockQb));
-
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
-
- $qb = $sdm->createQueryBuilder();
- $this->assertSame($mockQb, $qb);
- }
-
- public function testCreateDeletedQueryBuilder()
- {
- $mockQb = $this->getMockQb();
-
- $dm = $this->getMockDocumentManager();
- $dm->expects($this->once())
- ->method('createQueryBuilder')
- ->will($this->returnValue($mockQb));
-
- $mockQb->expects($this->once())
- ->method('field')
- ->with('deletedAt')
- ->will($this->returnValue($mockQb));
-
- $mockQb->expects($this->once())
- ->method('exists')
- ->with(true)
- ->will($this->returnValue($mockQb));
-
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
-
- $qb = $sdm->createDeletedQueryBuilder();
- $this->assertSame($mockQb, $qb);
+ $configuration = $this->getMockConfiguration();
+ $eventManager = $this->getMockEventManager();
+ $uow = $this->getTestSoftDeleteManager($dm, $configuration, $eventManager);
+ $this->assertSame($dm, $uow->getDocumentManager());
}
public function testDelete()
{
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
-
$mockSoftDeleteable = $this->getMockSoftDeletable();
-
- $uow->expects($this->once())
- ->method('delete')
- ->with($mockSoftDeleteable);
-
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
-
- $sdm->delete($mockSoftDeleteable);
- }
-
- public function testRestore()
- {
$dm = $this->getMockDocumentManager();
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
-
- $mockSoftDeleteable = $this->getMockSoftDeletable();
-
- $uow->expects($this->once())
- ->method('restore')
- ->with($mockSoftDeleteable);
-
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
-
- $sdm->restore($mockSoftDeleteable);
+ $configuration = $this->getMockConfiguration();
+ $eventManager = $this->getMockEventManager();
+ $uow = $this->getTestSoftDeleteManager($dm, $configuration, $eventManager);
+ $uow->delete($mockSoftDeleteable);
+ $this->assertTrue($uow->isScheduledForDelete($mockSoftDeleteable));
}
- public function testFlush()
+ public function testRestore()
{
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
-
$mockSoftDeleteable = $this->getMockSoftDeletable();
-
- $uow->expects($this->once())
- ->method('commit');
-
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
-
- $sdm->flush();
- }
-
- public function testClear()
- {
$dm = $this->getMockDocumentManager();
- $configuration = $this->getConfiguration();
- $uow = $this->getMockUnitOfWork();
-
- $mockSoftDeleteable = $this->getMockSoftDeletable();
-
- $uow->expects($this->once())
- ->method('clear');
-
- $sdm = $this->getTestSoftDeleteManager($dm, $configuration, $uow);
-
- $sdm->clear();
+ $configuration = $this->getMockConfiguration();
+ $eventManager = $this->getMockEventManager();
+ $uow = $this->getTestSoftDeleteManager($dm, $configuration, $eventManager);
+ $uow->restore($mockSoftDeleteable);
+ $this->assertTrue($uow->isScheduledForRestore($mockSoftDeleteable));
}
- private function getTestSoftDeleteManager(DocumentManager $dm, Configuration $configuration, UnitOfWork $uow)
+ private function getTestSoftDeleteManager(DocumentManager $dm, Configuration $configuration, EventManager $eventManager)
{
- return new SoftDeleteManager($dm, $configuration, $uow);
+ return new SoftDeleteManager($dm, $configuration, $eventManager);
}
- private function getMockSoftDeletable()
+ private function getMockConfiguration()
{
- return $this->getMockBuilder('Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteable')
+ return $this->getMockBuilder('Doctrine\ODM\MongoDB\SoftDelete\Configuration')
->disableOriginalConstructor()
->getMock();
}
@@ -158,21 +60,16 @@ private function getMockDocumentManager()
->getMock();
}
- private function getMockQb()
+ private function getMockSoftDeletable()
{
- return $this->getMockBuilder('Doctrine\ODM\MongoDB\Query\Builder')
+ return $this->getMockBuilder('Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteable')
->disableOriginalConstructor()
->getMock();
}
- private function getConfiguration()
- {
- return new Configuration();
- }
-
- private function getMockUnitOfWork()
+ private function getMockEventManager()
{
- return $this->getMockBuilder('Doctrine\ODM\MongoDB\SoftDelete\UnitOfWork')
+ return $this->getMockBuilder('Doctrine\Common\EventManager')
->disableOriginalConstructor()
->getMock();
}
View
139 tests/Doctrine/ODM/MongoDB/SoftDelete/Tests/UnitOfWorkTest.php
@@ -1,139 +0,0 @@
-<?php
-
-namespace Doctrine\ODM\MongoDB\SoftDelete\Tests;
-
-use Doctrine\ODM\MongoDB\DocumentManager;
-use Doctrine\ODM\MongoDB\SoftDelete\UnitOfWork;
-use Doctrine\ODM\MongoDB\SoftDelete\Configuration;
-use PHPUnit_Framework_TestCase;
-
-class UnitOfWorkTest extends PHPUnit_Framework_TestCase
-{
- public function testConstructor()
- {
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $this->assertSame($dm, $uow->getDocumentManager());
- }
-
- public function testDelete()
- {
- $mockSoftDeleteable = $this->getMockSoftDeletable();
- $mockSoftDeleteable->expects($this->once())
- ->method('isDeleted')
- ->will($this->returnValue(false));
-
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $uow->delete($mockSoftDeleteable);
- $this->assertTrue($uow->isScheduledForDelete($mockSoftDeleteable));
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testDeleteThrowsExceptionIfAlreadyDeleted()
- {
- $mockSoftDeleteable = $this->getMockSoftDeletable();
- $mockSoftDeleteable->expects($this->once())
- ->method('isDeleted')
- ->will($this->returnValue(true));
-
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $uow->delete($mockSoftDeleteable);
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testDeleteThrowsExceptionIfAlreadyScheduledForDelete()
- {
- $mockSoftDeleteable = $this->getMockSoftDeletable();
- $mockSoftDeleteable->expects($this->any())
- ->method('isDeleted')
- ->will($this->returnValue(false));
-
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $uow->delete($mockSoftDeleteable);
- $uow->delete($mockSoftDeleteable);
- }
-
- public function testRestore()
- {
- $mockSoftDeleteable = $this->getMockSoftDeletable();
- $mockSoftDeleteable->expects($this->once())
- ->method('isDeleted')
- ->will($this->returnValue(true));
-
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $uow->restore($mockSoftDeleteable);
- $this->assertTrue($uow->isScheduledForRestore($mockSoftDeleteable));
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testRestoreThrowsExceptionIfNotDeleted()
- {
- $mockSoftDeleteable = $this->getMockSoftDeletable();
- $mockSoftDeleteable->expects($this->once())
- ->method('isDeleted')
- ->will($this->returnValue(false));
-
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $uow->restore($mockSoftDeleteable);
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testRestoreThrowsExceptionIfAlreadyScheduledForRestore()
- {
- $mockSoftDeleteable = $this->getMockSoftDeletable();
- $mockSoftDeleteable->expects($this->any())
- ->method('isDeleted')
- ->will($this->returnValue(false));
-
- $dm = $this->getMockDocumentManager();
- $configuration = $this->getMockConfiguration();
- $uow = $this->getTestUnitOfWork($dm, $configuration);
- $uow->restore($mockSoftDeleteable);
- $uow->restore($mockSoftDeleteable);
- }
-
- private function getTestUnitOfWork(DocumentManager $dm, Configuration $configuration)
- {
- return new UnitOfWork($dm, $configuration);
- }
-
- private function getMockConfiguration()
- {
- return $this->getMockBuilder('Doctrine\ODM\MongoDB\SoftDelete\Configuration')
- ->disableOriginalConstructor()
- ->getMock();
- }
-
- private function getMockDocumentManager()
- {
- return $this->getMockBuilder('Doctrine\ODM\MongoDB\DocumentManager')
- ->disableOriginalConstructor()
- ->getMock();
- }
-
- private function getMockSoftDeletable()
- {
- return $this->getMockBuilder('Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteable')
- ->disableOriginalConstructor()
- ->getMock();
- }
-}

0 comments on commit c2edb9e

Please sign in to comment.
Something went wrong with that request. Please try again.