Permalink
Browse files

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

…scading deletes to related documents.
  • Loading branch information...
jwage committed Feb 15, 2011
1 parent 5631161 commit c2edb9e9224baa924b2f621c86124a897bab312c
View
@@ -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.
@@ -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;
@@ -48,32 +49,54 @@ 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;
}
/**
@@ -116,6 +139,26 @@ public function getDeletes()
return $this->queuedDeletes;
}
+ /**
+ * 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.
*
@@ -136,6 +179,26 @@ public function getRestores()
return $this->queuedRestores;
}
+ /**
+ * 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.
*
@@ -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;
}
}
Oops, something went wrong.

0 comments on commit c2edb9e

Please sign in to comment.