Skip to content

Commit

Permalink
Merge pull request #1861 from babeou/feature/add-harddelete-option
Browse files Browse the repository at this point in the history
Add an option to enable/disable hard delete
  • Loading branch information
l3pp4rd authored Dec 22, 2017
2 parents 8f20800 + 18dc8a2 commit 32abfe6
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 4 deletions.
10 changes: 7 additions & 3 deletions doc/softdeleteable.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Features:
- Can be nested with other behaviors
- Annotation, Yaml and Xml mapping support for extensions
- Support for 'timeAware' option: When creating an entity set a date of deletion in the future and never worry about cleaning up at expiration time.
- Support for 'hardDelete' option: When deleting a second time it allows to disable hard delete.

Content:

Expand Down Expand Up @@ -80,6 +81,8 @@ Available configuration options:
- **fieldName** - The name of the field that will be used to determine if the object is removed or not (NULL means
it's not removed. A date value means it was removed). NOTE: The field MUST be nullable.

- **hardDelete** - A boolean to enable or disable hard delete after soft delete has already been done. NOTE: Set to true by default.

**Note:** that SoftDeleteable interface is not necessary, except in cases where
you need to identify entity as being SoftDeleteable. The metadata is loaded only once then
cache is activated.
Expand All @@ -93,7 +96,7 @@ use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true)
*/
class Article
{
Expand Down Expand Up @@ -156,6 +159,7 @@ Entity\Article:
soft_deleteable:
field_name: deletedAt
time_aware: false
hard_delete: true
id:
id:
type: integer
Expand Down Expand Up @@ -187,7 +191,7 @@ Entity\Article:

<field name="deletedAt" type="datetime" nullable="true" />

<gedmo:soft-deleteable field-name="deletedAt" time-aware="false" />
<gedmo:soft-deleteable field-name="deletedAt" time-aware="false" hard-delete="true" />
</entity>

</doctrine-mapping>
Expand Down Expand Up @@ -254,7 +258,7 @@ use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;

/**
* @ORM\Entity
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true)
*/
class UsingTrait
{
Expand Down
3 changes: 3 additions & 0 deletions lib/Gedmo/Mapping/Annotation/SoftDeleteable.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ final class SoftDeleteable extends Annotation

/** @var bool */
public $timeAware = false;

/** @var bool */
public $hardDelete = true;
}
8 changes: 8 additions & 0 deletions lib/Gedmo/SoftDeleteable/Mapping/Driver/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ public function readExtendedMetadata($meta, array &$config)
}
$config['timeAware'] = $annot->timeAware;
}

$config['hardDelete'] = false;
if (isset($annot->hardDelete)) {
if (!is_bool($annot->hardDelete)) {
throw new InvalidMappingException("hardDelete must be boolean. ".gettype($annot->hardDelete)." provided.");
}
$config['hardDelete'] = $annot->hardDelete;
}
}

$this->validateFullMetadata($meta, $config);
Expand Down
5 changes: 5 additions & 0 deletions lib/Gedmo/SoftDeleteable/Mapping/Driver/Xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public function readExtendedMetadata($meta, array &$config)
if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'time-aware')) {
$config['timeAware'] = $this->_getBooleanAttribute($xml->{'soft-deleteable'}, 'time-aware');
}

$config['hardDelete'] = false;
if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'hard-delete')) {
$config['hardDelete'] = $this->_getBooleanAttribute($xml->{'soft-deleteable'}, 'hard-delete');
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions lib/Gedmo/SoftDeleteable/Mapping/Driver/Yaml.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ public function readExtendedMetadata($meta, array &$config)
}
$config['timeAware'] = $classMapping['soft_deleteable']['time_aware'];
}

$config['hardDelete'] = false;
if (isset($classMapping['soft_deleteable']['hard_delete'])) {
if (!is_bool($classMapping['soft_deleteable']['hard_delete'])) {
throw new InvalidMappingException("hardDelete must be boolean. ".gettype($classMapping['soft_deleteable']['hard_delete'])." provided.");
}
$config['hardDelete'] = $classMapping['soft_deleteable']['hard_delete'];
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/Gedmo/SoftDeleteable/SoftDeleteableListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public function onFlush(EventArgs $args)
if (isset($config['softDeleteable']) && $config['softDeleteable']) {
$reflProp = $meta->getReflectionProperty($config['fieldName']);
$oldValue = $reflProp->getValue($object);
if ($oldValue instanceof \Datetime) {

if (isset($config['hardDelete']) && $config['hardDelete'] && $oldValue instanceof \Datetime) {
continue; // want to hard delete
}

Expand Down
54 changes: 54 additions & 0 deletions tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNoHardDelete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
namespace SoftDeleteable\Fixture\Entity;

use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @Gedmo\SoftDeleteable(fieldName="deletedAt", hardDelete=false)
*/
class UserNoHardDelete
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;

/**
* @ORM\Column(name="title", type="string")
*/
private $username;

/**
* @ORM\Column(name="deleted_time", type="datetime", nullable=true)
*/
private $deletedAt;

public function getId()
{
return $this->id;
}

public function setUsername($username)
{
$this->username = $username;
}

public function getUsername()
{
return $this->username;
}

public function setDeletedAt($deletedAt)
{
$this->deletedAt = $deletedAt;
}

public function getDeletedAt()
{
return $this->deletedAt;
}
}
39 changes: 39 additions & 0 deletions tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Gedmo\SoftDeleteable;

use SoftDeleteable\Fixture\Entity\UserNoHardDelete;
use Tool\BaseTestCaseORM;
use Doctrine\Common\EventManager;
use SoftDeleteable\Fixture\Entity\Article;
Expand Down Expand Up @@ -35,6 +36,7 @@ class SoftDeleteableEntityTest extends BaseTestCaseORM
const USER_CLASS = 'SoftDeleteable\Fixture\Entity\User';
const MAPPED_SUPERCLASS_CHILD_CLASS = 'SoftDeleteable\Fixture\Entity\Child';
const SOFT_DELETEABLE_FILTER_NAME = 'soft-deleteable';
const USER_NO_HARD_DELETE_CLASS = 'SoftDeleteable\Fixture\Entity\UserNoHardDelete';

private $softDeleteableListener;

Expand Down Expand Up @@ -370,6 +372,42 @@ public function testPostSoftDeleteEventIsDispatched()
$this->em->flush();
}

/**
* @test
*/
public function shouldNotDeleteIfColumnNameDifferFromPropertyName()
{
$repo = $this->em->getRepository(self::USER_NO_HARD_DELETE_CLASS);

$newUser = new UserNoHardDelete();
$username = 'test_user';
$newUser->setUsername($username);

$this->em->persist($newUser);
$this->em->flush();

$user = $repo->findOneBy(array('username' => $username));

$this->assertNull($user->getDeletedAt());

$this->em->remove($user);
$this->em->flush();

$user = $repo->findOneBy(array('username' => $username));
$this->assertNull($user, "User should be filtered out");

// now deactivate filter and attempt to hard delete
$this->em->getFilters()->disable(self::SOFT_DELETEABLE_FILTER_NAME);
$user = $repo->findOneBy(array('username' => $username));
$this->assertNotNull($user, "User should be fetched when filter is disabled");

$this->em->remove($user);
$this->em->flush();

$user = $repo->findOneBy(array('username' => $username));
$this->assertNotNull($user, "User is still available, hard delete done");
}

protected function getUsedEntityFixtures()
{
return array(
Expand All @@ -382,6 +420,7 @@ protected function getUsedEntityFixtures()
self::OTHER_ARTICLE_CLASS,
self::OTHER_COMMENT_CLASS,
self::MAPPED_SUPERCLASS_CHILD_CLASS,
self::USER_NO_HARD_DELETE_CLASS,
);
}
}

0 comments on commit 32abfe6

Please sign in to comment.