From 59f7df946d8a7fff8204f3f6204b8eb3628bb57d Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Mon, 30 Sep 2024 15:02:40 +0200 Subject: [PATCH 01/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/Mapping/Annotation/SoftDeleteable.php | 6 +++++- src/SoftDeleteable/Filter/SoftDeleteableFilter.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Mapping/Annotation/SoftDeleteable.php b/src/Mapping/Annotation/SoftDeleteable.php index 709d9c4e7f..3017278371 100644 --- a/src/Mapping/Annotation/SoftDeleteable.php +++ b/src/Mapping/Annotation/SoftDeleteable.php @@ -35,10 +35,12 @@ final class SoftDeleteable implements GedmoAnnotation public bool $hardDelete = true; + public $deletedValue = null; + /** * @param array $data */ - public function __construct(array $data = [], string $fieldName = 'deletedAt', bool $timeAware = false, bool $hardDelete = true) + public function __construct(array $data = [], string $fieldName = 'deletedAt', bool $timeAware = false, bool $hardDelete = true, $deletedValue = null) { if ([] !== $data) { Deprecation::trigger( @@ -53,6 +55,7 @@ public function __construct(array $data = [], string $fieldName = 'deletedAt', b $this->fieldName = $this->getAttributeValue($data, 'fieldName', $args, 1, $fieldName); $this->timeAware = $this->getAttributeValue($data, 'timeAware', $args, 2, $timeAware); $this->hardDelete = $this->getAttributeValue($data, 'hardDelete', $args, 3, $hardDelete); + $this->deletedValue = $this->getAttributeValue($data, 'deletedValue', $args, 4, $deletedValue); return; } @@ -60,5 +63,6 @@ public function __construct(array $data = [], string $fieldName = 'deletedAt', b $this->fieldName = $fieldName; $this->timeAware = $timeAware; $this->hardDelete = $hardDelete; + $this->deletedValue = $deletedValue; } } diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index 12ed75f48d..9e942965f3 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,7 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' IS NULL'; + $addCondSql = $targetTableAlias.'.'.$column.' '.$config['deletedValue'] === null ? 'IS NULL' : '= ' . $config['deletedValue']; if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } From c1285437c1a697ecb9899740a182550030bbd9ee Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Mon, 30 Sep 2024 16:22:47 +0200 Subject: [PATCH 02/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/SoftDeleteable/Filter/SoftDeleteableFilter.php | 2 +- src/SoftDeleteable/Mapping/Driver/Attribute.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index 9e942965f3..a27b93b407 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,7 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' '.$config['deletedValue'] === null ? 'IS NULL' : '= ' . $config['deletedValue']; + $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '= ' . $config['deletedValue'] : 'IS NULL'); if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } diff --git a/src/SoftDeleteable/Mapping/Driver/Attribute.php b/src/SoftDeleteable/Mapping/Driver/Attribute.php index 8358f1b35b..a5d953ccc8 100644 --- a/src/SoftDeleteable/Mapping/Driver/Attribute.php +++ b/src/SoftDeleteable/Mapping/Driver/Attribute.php @@ -62,6 +62,10 @@ public function readExtendedMetadata($meta, array &$config) $config['hardDelete'] = $annot->hardDelete; } + + if (isset($annot->deletedValue)) { + $config['deletedValue'] = $annot->deletedValue; + } } $this->validateFullMetadata($meta, $config); From 4d5f0d5b0b5563164ae0f014cda16d985718494e Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Mon, 30 Sep 2024 16:29:53 +0200 Subject: [PATCH 03/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/SoftDeleteable/Filter/SoftDeleteableFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index a27b93b407..bcd85150ba 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,7 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '= ' . $config['deletedValue'] : 'IS NULL'); + $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '!= ' . $config['deletedValue'] : 'IS NULL'); if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } From 0fe2e476acdfafdbf459e917dcc3a0043318906d Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Mon, 30 Sep 2024 16:33:01 +0200 Subject: [PATCH 04/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/SoftDeleteable/Filter/SoftDeleteableFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index bcd85150ba..a27b93b407 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,7 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '!= ' . $config['deletedValue'] : 'IS NULL'); + $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '= ' . $config['deletedValue'] : 'IS NULL'); if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } From 7b30fc65ff7068fb25dbdf4caf69f1265d511b07 Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Mon, 30 Sep 2024 17:02:18 +0200 Subject: [PATCH 05/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/Mapping/Annotation/SoftDeleteable.php | 4 ++-- src/SoftDeleteable/Mapping/Driver/Attribute.php | 4 ++++ src/SoftDeleteable/Mapping/Driver/Xml.php | 5 +++++ src/SoftDeleteable/Mapping/Driver/Yaml.php | 8 ++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Mapping/Annotation/SoftDeleteable.php b/src/Mapping/Annotation/SoftDeleteable.php index 3017278371..453fe5352a 100644 --- a/src/Mapping/Annotation/SoftDeleteable.php +++ b/src/Mapping/Annotation/SoftDeleteable.php @@ -35,12 +35,12 @@ final class SoftDeleteable implements GedmoAnnotation public bool $hardDelete = true; - public $deletedValue = null; + public ?string $deletedValue = null; /** * @param array $data */ - public function __construct(array $data = [], string $fieldName = 'deletedAt', bool $timeAware = false, bool $hardDelete = true, $deletedValue = null) + public function __construct(array $data = [], string $fieldName = 'deletedAt', bool $timeAware = false, bool $hardDelete = true, ?string $deletedValue = null) { if ([] !== $data) { Deprecation::trigger( diff --git a/src/SoftDeleteable/Mapping/Driver/Attribute.php b/src/SoftDeleteable/Mapping/Driver/Attribute.php index a5d953ccc8..0037274a3b 100644 --- a/src/SoftDeleteable/Mapping/Driver/Attribute.php +++ b/src/SoftDeleteable/Mapping/Driver/Attribute.php @@ -64,6 +64,10 @@ public function readExtendedMetadata($meta, array &$config) } if (isset($annot->deletedValue)) { + if (!is_string($annot->deletedValue)) { + throw new InvalidMappingException('deletedValue must be string. '.gettype($annot->deletedValue).' provided.'); + } + $config['deletedValue'] = $annot->deletedValue; } } diff --git a/src/SoftDeleteable/Mapping/Driver/Xml.php b/src/SoftDeleteable/Mapping/Driver/Xml.php index 451733fd4c..84e7ba1ad8 100644 --- a/src/SoftDeleteable/Mapping/Driver/Xml.php +++ b/src/SoftDeleteable/Mapping/Driver/Xml.php @@ -58,6 +58,11 @@ public function readExtendedMetadata($meta, array &$config) if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'hard-delete')) { $config['hardDelete'] = $this->_getBooleanAttribute($xml->{'soft-deleteable'}, 'hard-delete'); } + + $config['deletedValue'] = null; + if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'deleted-value')) { + $config['deletedValue'] = $this->_getAttribute($xml->{'soft-deleteable'}, 'deleted-value'); + } } } diff --git a/src/SoftDeleteable/Mapping/Driver/Yaml.php b/src/SoftDeleteable/Mapping/Driver/Yaml.php index e2790b1b66..42710113bd 100644 --- a/src/SoftDeleteable/Mapping/Driver/Yaml.php +++ b/src/SoftDeleteable/Mapping/Driver/Yaml.php @@ -70,6 +70,14 @@ public function readExtendedMetadata($meta, array &$config) } $config['hardDelete'] = $classMapping['soft_deleteable']['hard_delete']; } + + $config['deletedValue'] = null; + if (isset($classMapping['soft_deleteable']['deleted_value'])) { + if (!is_string($classMapping['soft_deleteable']['deleted_value'])) { + throw new InvalidMappingException('deletedValue must be string. ' . gettype($classMapping['soft_deleteable']['deleted_value']) . ' provided.'); + } + $config['deletedValue'] = $classMapping['soft_deleteable']['deleted_value']; + } } } From 59ce39e919d822e584d6cf02ce4a67c98f6c7c5f Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Tue, 1 Oct 2024 13:07:14 +0200 Subject: [PATCH 06/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/SoftDeleteable/Filter/SoftDeleteableFilter.php | 2 +- src/SoftDeleteable/Mapping/Driver/Yaml.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index a27b93b407..60f50eb7b7 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,7 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '= ' . $config['deletedValue'] : 'IS NULL'); + $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '= '.$config['deletedValue'] : 'IS NULL'); if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } diff --git a/src/SoftDeleteable/Mapping/Driver/Yaml.php b/src/SoftDeleteable/Mapping/Driver/Yaml.php index 42710113bd..22af468c08 100644 --- a/src/SoftDeleteable/Mapping/Driver/Yaml.php +++ b/src/SoftDeleteable/Mapping/Driver/Yaml.php @@ -74,7 +74,7 @@ public function readExtendedMetadata($meta, array &$config) $config['deletedValue'] = null; if (isset($classMapping['soft_deleteable']['deleted_value'])) { if (!is_string($classMapping['soft_deleteable']['deleted_value'])) { - throw new InvalidMappingException('deletedValue must be string. ' . gettype($classMapping['soft_deleteable']['deleted_value']) . ' provided.'); + throw new InvalidMappingException('deletedValue must be string. '.gettype($classMapping['soft_deleteable']['deleted_value']).' provided.'); } $config['deletedValue'] = $classMapping['soft_deleteable']['deleted_value']; } From 6264492faf44d45e971fb68d7dfad8464399220c Mon Sep 17 00:00:00 2001 From: Barthold Bos Date: Thu, 3 Oct 2024 12:55:26 +0200 Subject: [PATCH 07/16] Make deleted value configurable for SoftDeleteableFilter.php --- src/Mapping/Annotation/SoftDeleteable.php | 8 ++++---- src/SoftDeleteable/Filter/SoftDeleteableFilter.php | 2 +- src/SoftDeleteable/Mapping/Driver/Attribute.php | 8 ++++---- src/SoftDeleteable/Mapping/Driver/Xml.php | 4 ++-- src/SoftDeleteable/Mapping/Driver/Yaml.php | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Mapping/Annotation/SoftDeleteable.php b/src/Mapping/Annotation/SoftDeleteable.php index 453fe5352a..ff48c2d4cb 100644 --- a/src/Mapping/Annotation/SoftDeleteable.php +++ b/src/Mapping/Annotation/SoftDeleteable.php @@ -35,12 +35,12 @@ final class SoftDeleteable implements GedmoAnnotation public bool $hardDelete = true; - public ?string $deletedValue = null; + public ?string $nonDeletedColumnValue = null; /** * @param array $data */ - public function __construct(array $data = [], string $fieldName = 'deletedAt', bool $timeAware = false, bool $hardDelete = true, ?string $deletedValue = null) + public function __construct(array $data = [], string $fieldName = 'deletedAt', bool $timeAware = false, bool $hardDelete = true, ?string $nonDeletedColumnValue = null) { if ([] !== $data) { Deprecation::trigger( @@ -55,7 +55,7 @@ public function __construct(array $data = [], string $fieldName = 'deletedAt', b $this->fieldName = $this->getAttributeValue($data, 'fieldName', $args, 1, $fieldName); $this->timeAware = $this->getAttributeValue($data, 'timeAware', $args, 2, $timeAware); $this->hardDelete = $this->getAttributeValue($data, 'hardDelete', $args, 3, $hardDelete); - $this->deletedValue = $this->getAttributeValue($data, 'deletedValue', $args, 4, $deletedValue); + $this->nonDeletedColumnValue = $this->getAttributeValue($data, 'nonDeletedColumnValue', $args, 4, $nonDeletedColumnValue); return; } @@ -63,6 +63,6 @@ public function __construct(array $data = [], string $fieldName = 'deletedAt', b $this->fieldName = $fieldName; $this->timeAware = $timeAware; $this->hardDelete = $hardDelete; - $this->deletedValue = $deletedValue; + $this->nonDeletedColumnValue = $nonDeletedColumnValue; } } diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index 60f50eb7b7..9aee725b5b 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,7 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['deletedValue']) ? '= '.$config['deletedValue'] : 'IS NULL'); + $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['nonDeletedColumnValue']) ? '= '.$config['nonDeletedColumnValue'] : 'IS NULL'); if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } diff --git a/src/SoftDeleteable/Mapping/Driver/Attribute.php b/src/SoftDeleteable/Mapping/Driver/Attribute.php index 0037274a3b..e64c4674f5 100644 --- a/src/SoftDeleteable/Mapping/Driver/Attribute.php +++ b/src/SoftDeleteable/Mapping/Driver/Attribute.php @@ -63,12 +63,12 @@ public function readExtendedMetadata($meta, array &$config) $config['hardDelete'] = $annot->hardDelete; } - if (isset($annot->deletedValue)) { - if (!is_string($annot->deletedValue)) { - throw new InvalidMappingException('deletedValue must be string. '.gettype($annot->deletedValue).' provided.'); + if (isset($annot->nonDeletedColumnValue)) { + if (!is_string($annot->nonDeletedColumnValue)) { + throw new InvalidMappingException('nonDeletedColumnValue must be string. '.gettype($annot->nonDeletedColumnValue).' provided.'); } - $config['deletedValue'] = $annot->deletedValue; + $config['nonDeletedColumnValue'] = $annot->nonDeletedColumnValue; } } diff --git a/src/SoftDeleteable/Mapping/Driver/Xml.php b/src/SoftDeleteable/Mapping/Driver/Xml.php index 84e7ba1ad8..1f5f3bfbb4 100644 --- a/src/SoftDeleteable/Mapping/Driver/Xml.php +++ b/src/SoftDeleteable/Mapping/Driver/Xml.php @@ -59,9 +59,9 @@ public function readExtendedMetadata($meta, array &$config) $config['hardDelete'] = $this->_getBooleanAttribute($xml->{'soft-deleteable'}, 'hard-delete'); } - $config['deletedValue'] = null; + $config['nonDeletedColumnValue'] = null; if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'deleted-value')) { - $config['deletedValue'] = $this->_getAttribute($xml->{'soft-deleteable'}, 'deleted-value'); + $config['nonDeletedColumnValue'] = $this->_getAttribute($xml->{'soft-deleteable'}, 'non-deleted-column-value'); } } } diff --git a/src/SoftDeleteable/Mapping/Driver/Yaml.php b/src/SoftDeleteable/Mapping/Driver/Yaml.php index 22af468c08..2f6356f7df 100644 --- a/src/SoftDeleteable/Mapping/Driver/Yaml.php +++ b/src/SoftDeleteable/Mapping/Driver/Yaml.php @@ -71,12 +71,12 @@ public function readExtendedMetadata($meta, array &$config) $config['hardDelete'] = $classMapping['soft_deleteable']['hard_delete']; } - $config['deletedValue'] = null; + $config['nonDeletedColumnValue'] = null; if (isset($classMapping['soft_deleteable']['deleted_value'])) { if (!is_string($classMapping['soft_deleteable']['deleted_value'])) { - throw new InvalidMappingException('deletedValue must be string. '.gettype($classMapping['soft_deleteable']['deleted_value']).' provided.'); + throw new InvalidMappingException('nonDeletedColumnValue must be string. '.gettype($classMapping['soft_deleteable']['deleted_value']).' provided.'); } - $config['deletedValue'] = $classMapping['soft_deleteable']['deleted_value']; + $config['nonDeletedColumnValue'] = $classMapping['soft_deleteable']['non_deleted_column_value']; } } } From d6f7acc3d8de36402d434ad36ac68c2ce8c3e736 Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 2 Jul 2025 17:09:38 +0200 Subject: [PATCH 08/16] . add tests --- src/SoftDeleteable/Mapping/Driver/Xml.php | 2 +- src/SoftDeleteable/Mapping/Driver/Yaml.php | 6 +++--- .../Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml | 2 +- .../Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml | 2 ++ tests/Gedmo/Mapping/Fixture/SoftDeleteable.php | 2 +- tests/Gedmo/Mapping/SoftDeleteableMappingTest.php | 2 ++ 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/SoftDeleteable/Mapping/Driver/Xml.php b/src/SoftDeleteable/Mapping/Driver/Xml.php index 1f5f3bfbb4..d8ceefc284 100644 --- a/src/SoftDeleteable/Mapping/Driver/Xml.php +++ b/src/SoftDeleteable/Mapping/Driver/Xml.php @@ -60,7 +60,7 @@ public function readExtendedMetadata($meta, array &$config) } $config['nonDeletedColumnValue'] = null; - if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'deleted-value')) { + if ($this->_isAttributeSet($xml->{'soft-deleteable'}, 'non-deleted-column-value')) { $config['nonDeletedColumnValue'] = $this->_getAttribute($xml->{'soft-deleteable'}, 'non-deleted-column-value'); } } diff --git a/src/SoftDeleteable/Mapping/Driver/Yaml.php b/src/SoftDeleteable/Mapping/Driver/Yaml.php index 2f6356f7df..41b142b53f 100644 --- a/src/SoftDeleteable/Mapping/Driver/Yaml.php +++ b/src/SoftDeleteable/Mapping/Driver/Yaml.php @@ -72,9 +72,9 @@ public function readExtendedMetadata($meta, array &$config) } $config['nonDeletedColumnValue'] = null; - if (isset($classMapping['soft_deleteable']['deleted_value'])) { - if (!is_string($classMapping['soft_deleteable']['deleted_value'])) { - throw new InvalidMappingException('nonDeletedColumnValue must be string. '.gettype($classMapping['soft_deleteable']['deleted_value']).' provided.'); + if (isset($classMapping['soft_deleteable']['non_deleted_column_value'])) { + if (!is_string($classMapping['soft_deleteable']['non_deleted_column_value'])) { + throw new InvalidMappingException('nonDeletedColumnValue must be string. '.gettype($classMapping['soft_deleteable']['non_deleted_column_value']).' provided.'); } $config['nonDeletedColumnValue'] = $classMapping['soft_deleteable']['non_deleted_column_value']; } diff --git a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml index f7590b6efc..e4436d4782 100644 --- a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml +++ b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml @@ -5,6 +5,6 @@ - + diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml index d4a29f7ac2..217abe0622 100644 --- a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml @@ -14,3 +14,5 @@ Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteable: deletedAt: type: datetime nullable: true + deletedValue: + nonDeletedColumnValue: '0' diff --git a/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php b/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php index 3e3372e786..6ffa9cde11 100644 --- a/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php +++ b/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php @@ -21,7 +21,7 @@ * @Gedmo\SoftDeleteable(fieldName="deletedAt") */ #[ORM\Entity] -#[Gedmo\SoftDeleteable(fieldName: 'deletedAt')] +#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', nonDeletedColumnValue: '0')] class SoftDeleteable { /** diff --git a/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php b/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php index 0b868de5c2..fbf27aa2ec 100644 --- a/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php +++ b/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php @@ -77,5 +77,7 @@ public function testSoftDeleteableMapping(string $className): void static::assertFalse($config['timeAware']); static::assertArrayHasKey('fieldName', $config); static::assertSame('deletedAt', $config['fieldName']); + static::assertArrayHasKey('nonDeletedColumnValue', $config); + static::assertSame('0', $config['nonDeletedColumnValue']); } } From f514989834991358a3f31b62cd3550fd528f1a7d Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 2 Jul 2025 17:14:17 +0200 Subject: [PATCH 09/16] . add tests --- .../Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml index 217abe0622..545f28faa7 100644 --- a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml @@ -5,6 +5,7 @@ Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteable: gedmo: soft_deleteable: field_name: deletedAt + nonDeletedColumnValue: '0' id: id: type: integer @@ -14,5 +15,3 @@ Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteable: deletedAt: type: datetime nullable: true - deletedValue: - nonDeletedColumnValue: '0' From 77aaf28dd844e065a33c743b0770aaac10236d51 Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 2 Jul 2025 17:20:18 +0200 Subject: [PATCH 10/16] . add tests --- doc/softdeleteable.md | 8 +++++--- ...edmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/softdeleteable.md b/doc/softdeleteable.md index 445231efb8..a75948497b 100644 --- a/doc/softdeleteable.md +++ b/doc/softdeleteable.md @@ -87,6 +87,8 @@ it's not removed. A date value means it was removed). NOTE: The field MUST be nu - **hardDelete** - A boolean to enable or disable hard delete after soft delete has already been done. NOTE: Set to true by default. +- **nonDeletedColumnValue** - The value that is seen as not deleted, default: null + **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. @@ -104,10 +106,10 @@ use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true) + * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true, nonDeletedColumnValue=null) */ #[ORM\Entity] -#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', timeAware: false, hardDelete: true)] +#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', timeAware: false, hardDelete: true, nonDeletedColumnValue: null)] class Article { /** @@ -183,7 +185,7 @@ class Article - + diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml index 545f28faa7..55fb966866 100644 --- a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml @@ -5,7 +5,7 @@ Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteable: gedmo: soft_deleteable: field_name: deletedAt - nonDeletedColumnValue: '0' + non_deleted_column_value: '0' id: id: type: integer From 7e2b01797da897106e48731aedfd5d6df42eb9cd Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Tue, 22 Jul 2025 16:09:07 +0200 Subject: [PATCH 11/16] Add non-deleted-value to ODM filter, add test --- .../Filter/ODM/SoftDeleteableFilter.php | 5 +- .../Filter/SoftDeleteableFilter.php | 3 +- .../Fixture/Entity/UserNonDeletedValue.php | 75 +++++++++++++++++++ .../SoftDeleteableEntityTest.php | 31 ++++++++ 4 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php diff --git a/src/SoftDeleteable/Filter/ODM/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/ODM/SoftDeleteableFilter.php index 12d80c0b4b..5e09fc83a6 100644 --- a/src/SoftDeleteable/Filter/ODM/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/ODM/SoftDeleteableFilter.php @@ -60,18 +60,19 @@ public function addFilterCriteria(ClassMetadata $targetEntity): array } $column = $targetEntity->getFieldMapping($config['fieldName']); + $nonDeletedValue = $config['nonDeletedColumnValue'] ?? null; if (isset($config['timeAware']) && $config['timeAware']) { return [ '$or' => [ - [$column['fieldName'] => null], + [$column['fieldName'] => $nonDeletedValue], [$column['fieldName'] => ['$gt' => new \DateTime()]], ], ]; } return [ - $column['fieldName'] => null, + $column['fieldName'] => $nonDeletedValue, ]; } diff --git a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php index 9aee725b5b..7537caf6d9 100644 --- a/src/SoftDeleteable/Filter/SoftDeleteableFilter.php +++ b/src/SoftDeleteable/Filter/SoftDeleteableFilter.php @@ -70,7 +70,8 @@ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAli $column = $quoteStrategy->getColumnName($config['fieldName'], $targetEntity, $platform); - $addCondSql = $targetTableAlias.'.'.$column.' '.(isset($config['nonDeletedColumnValue']) ? '= '.$config['nonDeletedColumnValue'] : 'IS NULL'); + $nonDeletedSql = isset($config['nonDeletedColumnValue']) ? '= "'.$config['nonDeletedColumnValue'].'"': 'IS NULL'; + $addCondSql = $targetTableAlias.'.'.$column.' '.$nonDeletedSql; if (isset($config['timeAware']) && $config['timeAware']) { $addCondSql = "({$addCondSql} OR {$targetTableAlias}.{$column} > {$platform->getCurrentTimestampSQL()})"; } diff --git a/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php b/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php new file mode 100644 index 0000000000..23dbe143c9 --- /dev/null +++ b/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php @@ -0,0 +1,75 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\SoftDeleteable\Fixture\Entity; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * + * @Gedmo\SoftDeleteable(fieldName="deletedAt", nonDeletedColumnValue: "0") + */ +#[ORM\Entity] +#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00')] +class UserNonDeletedValue +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\GeneratedValue(strategy="IDENTITY") + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'IDENTITY')] + #[ORM\Column(type: Types::INTEGER)] + private $id; + + /** + * @ORM\Column(name="title", type="string") + */ + #[ORM\Column(name: 'title', type: Types::STRING)] + private ?string $username = null; + + /** + * @ORM\Column(name="deleted_time", type="datetime", nullable=true) + */ + #[ORM\Column(name: 'deleted_time', type: Types::DATETIME_MUTABLE, nullable: true)] + private ?\DateTime $deletedAt = null; + + public function getId(): ?int + { + return $this->id; + } + + public function setUsername(?string $username): void + { + $this->username = $username; + } + + public function getUsername(): ?string + { + return $this->username; + } + + public function setDeletedAt(?\DateTime $deletedAt): void + { + $this->deletedAt = $deletedAt; + } + + public function getDeletedAt(): ?\DateTime + { + return $this->deletedAt; + } +} diff --git a/tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php b/tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php index d377e68e56..523adda865 100644 --- a/tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php +++ b/tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php @@ -28,6 +28,7 @@ use Gedmo\Tests\SoftDeleteable\Fixture\Entity\Page; use Gedmo\Tests\SoftDeleteable\Fixture\Entity\User; use Gedmo\Tests\SoftDeleteable\Fixture\Entity\UserNoHardDelete; +use Gedmo\Tests\SoftDeleteable\Fixture\Entity\UserNonDeletedValue; use Gedmo\Tests\SoftDeleteable\Fixture\Listener\WithLifecycleEventArgsFromORMTypeListener; use Gedmo\Tests\SoftDeleteable\Fixture\Listener\WithoutTypeListener; use Gedmo\Tests\SoftDeleteable\Fixture\Listener\WithPreAndPostSoftDeleteEventArgsTypeListener; @@ -610,6 +611,35 @@ public function testShouldNotDeleteIfColumnNameDifferFromPropertyName(): void static::assertNotNull($user, 'User is still available, hard delete done'); } + public function testShouldBeMarkedAsSoftDeletedWithDifferentNonDeletedValueSet(): void + { + $repo = $this->em->getRepository(UserNonDeletedValue::class); + $newUser = new UserNonDeletedValue(); + $username = 'test_user'; + $newUser->setUsername($username); + // '1970-01-01 00:00:00' + $date = (new \DateTime())->setTimestamp(0); + $newUser->setDeletedAt($date); + + $this->em->persist($newUser); + $this->em->flush(); + + $user = $repo->findOneBy(['username' => $username]); + static::assertSame($date, $user->getDeletedAt()); + + $this->em->remove($user); + $this->em->flush(); + + $user = $repo->findOneBy(['username' => $username]); + static::assertNull($user, 'User should be filtered out'); + + // deactivate filter to fetch softdeleted entity + $this->em->getFilters()->disable(self::SOFT_DELETEABLE_FILTER_NAME); + $user = $repo->findOneBy(['username' => $username]); + static::assertNotNull($user, 'User should be fetched when filter is disabled'); + static::assertGreaterThan(0, $user->getDeletedAt()->getTimestamp()); + } + protected function getUsedEntityFixtures(): array { return [ @@ -623,6 +653,7 @@ protected function getUsedEntityFixtures(): array OtherComment::class, Child::class, UserNoHardDelete::class, + UserNonDeletedValue::class, ]; } From ca03dc253f69c821e26883a2cdb9867ce635c429 Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 27 Aug 2025 13:32:07 +0200 Subject: [PATCH 12/16] revert changes to existing unittests --- .../Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml | 2 +- .../Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml | 1 - tests/Gedmo/Mapping/Fixture/SoftDeleteable.php | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml index e4436d4782..f7590b6efc 100644 --- a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml +++ b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteable.dcm.xml @@ -5,6 +5,6 @@ - + diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml index 55fb966866..d4a29f7ac2 100644 --- a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteable.dcm.yml @@ -5,7 +5,6 @@ Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteable: gedmo: soft_deleteable: field_name: deletedAt - non_deleted_column_value: '0' id: id: type: integer diff --git a/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php b/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php index 6ffa9cde11..3e3372e786 100644 --- a/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php +++ b/tests/Gedmo/Mapping/Fixture/SoftDeleteable.php @@ -21,7 +21,7 @@ * @Gedmo\SoftDeleteable(fieldName="deletedAt") */ #[ORM\Entity] -#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', nonDeletedColumnValue: '0')] +#[Gedmo\SoftDeleteable(fieldName: 'deletedAt')] class SoftDeleteable { /** From 4682272be57d12bddfe051f2c3a3d178f6dd03fc Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 27 Aug 2025 13:36:51 +0200 Subject: [PATCH 13/16] revert changes to existing unittests --- tests/Gedmo/Mapping/SoftDeleteableMappingTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php b/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php index fbf27aa2ec..0b868de5c2 100644 --- a/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php +++ b/tests/Gedmo/Mapping/SoftDeleteableMappingTest.php @@ -77,7 +77,5 @@ public function testSoftDeleteableMapping(string $className): void static::assertFalse($config['timeAware']); static::assertArrayHasKey('fieldName', $config); static::assertSame('deletedAt', $config['fieldName']); - static::assertArrayHasKey('nonDeletedColumnValue', $config); - static::assertSame('0', $config['nonDeletedColumnValue']); } } From ec2280146d07e655d7f21de41d7d70920eb42767 Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 27 Aug 2025 14:33:26 +0200 Subject: [PATCH 14/16] Add NonDeletedValue test for ODM --- .../Fixture/Document/UserNonDeletedValue.php | 74 +++++++++++++++++++ .../Fixture/Entity/UserNonDeletedValue.php | 2 +- .../SoftDeleteableDocumentTest.php | 33 +++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tests/Gedmo/SoftDeleteable/Fixture/Document/UserNonDeletedValue.php diff --git a/tests/Gedmo/SoftDeleteable/Fixture/Document/UserNonDeletedValue.php b/tests/Gedmo/SoftDeleteable/Fixture/Document/UserNonDeletedValue.php new file mode 100644 index 0000000000..ae3a544755 --- /dev/null +++ b/tests/Gedmo/SoftDeleteable/Fixture/Document/UserNonDeletedValue.php @@ -0,0 +1,74 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\SoftDeleteable\Fixture\Document; + +use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; +use Doctrine\ODM\MongoDB\Types\Type; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ODM\Document(collection="users") + * + * @Gedmo\SoftDeleteable(fieldName="deletedAt" hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00') + */ +#[ODM\Document(collection: 'users')] +#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00')] +class UserNonDeletedValue +{ + /** + * @var \DateTime|null + * + * @ODM\Field(type="date") + */ + #[ODM\Field(type: Type::DATE)] + protected $deletedAt; + /** + * @var string|null + * + * @ODM\Id + */ + #[ODM\Id] + private $id; + + /** + * @ODM\Field(type="string") + */ + #[ODM\Field(type: Type::STRING)] + private ?string $username = null; + + public function setDeletedAt(\DateTime $deletedAt): self + { + $this->deletedAt = $deletedAt; + + return $this; + } + + public function getDeletedAt(): ?\DateTime + { + return $this->deletedAt; + } + + public function getId(): ?string + { + return $this->id; + } + + public function setUsername(?string $username): void + { + $this->username = $username; + } + + public function getUsername(): ?string + { + return $this->username; + } +} diff --git a/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php b/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php index 23dbe143c9..cd1b9b14bf 100644 --- a/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php +++ b/tests/Gedmo/SoftDeleteable/Fixture/Entity/UserNonDeletedValue.php @@ -18,7 +18,7 @@ /** * @ORM\Entity * - * @Gedmo\SoftDeleteable(fieldName="deletedAt", nonDeletedColumnValue: "0") + * @Gedmo\SoftDeleteable(fieldName="deletedAt", hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00') */ #[ORM\Entity] #[Gedmo\SoftDeleteable(fieldName: 'deletedAt', hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00')] diff --git a/tests/Gedmo/SoftDeleteable/SoftDeleteableDocumentTest.php b/tests/Gedmo/SoftDeleteable/SoftDeleteableDocumentTest.php index b2c1fe4da6..9f8c553e64 100644 --- a/tests/Gedmo/SoftDeleteable/SoftDeleteableDocumentTest.php +++ b/tests/Gedmo/SoftDeleteable/SoftDeleteableDocumentTest.php @@ -16,6 +16,7 @@ use Gedmo\SoftDeleteable\SoftDeleteableListener; use Gedmo\Tests\SoftDeleteable\Fixture\Document\User; use Gedmo\Tests\SoftDeleteable\Fixture\Document\UserTimeAware; +use Gedmo\Tests\SoftDeleteable\Fixture\Document\UserNonDeletedValue; use Gedmo\Tests\SoftDeleteable\Fixture\Listener\WithLifecycleEventArgsFromODMTypeListener; use Gedmo\Tests\SoftDeleteable\Fixture\Listener\WithoutTypeListener; use Gedmo\Tests\SoftDeleteable\Fixture\Listener\WithPreAndPostSoftDeleteEventArgsTypeListener; @@ -72,6 +73,38 @@ public function testShouldSoftlyDeleteIfColumnNameDifferFromPropertyName(): void static::assertNull($user); } + public function testShouldBeMarkedAsSoftDeletedWithDifferentNonDeletedValueSet(): void + { + $repo = $this->dm->getRepository(UserNonDeletedValue::class); + $newUser = new UserNonDeletedValue(); + $username = 'test_user'; + $newUser->setUsername($username); + // '1970-01-01 00:00:00' + $date = (new \DateTime())->setTimestamp(0); + $newUser->setDeletedAt($date); + + $this->dm->persist($newUser); + $this->dm->flush(); + + $user = $repo->findOneBy(['username' => $username]); + static::assertSame($date, $user->getDeletedAt()); + + $this->dm->remove($user); + $this->dm->flush(); + + $user = $repo->findOneBy(['username' => $username]); + static::assertNull($user, 'User should be filtered out'); + + // deactivate filter to fetch softdeleted entity + $filter = $this->dm->getFilterCollection()->getFilter(self::SOFT_DELETEABLE_FILTER_NAME); + static::assertInstanceOf(SoftDeleteableFilter::class, $filter); + $filter->disableForDocument(UserNonDeletedValue::class); + + $user = $repo->findOneBy(['username' => $username]); + static::assertNotNull($user, 'User should be fetched when filter is disabled'); + static::assertGreaterThan(0, $user->getDeletedAt()->getTimestamp()); + } + /** * Tests the filter by enabling and disabling it between * some user persists actions. From d6b976047413d6dc6c27149b5be67a218de4f939 Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 27 Aug 2025 15:28:03 +0200 Subject: [PATCH 15/16] Add NonDeletedValue test for Mappings --- ...oftDeleteableNonDeletedColumnValue.dcm.xml | 10 +++ ...oftDeleteableNonDeletedColumnValue.dcm.yml | 18 ++++ .../SoftDeleteableNonDeletedColumnValue.php | 85 +++++++++++++++++++ .../SoftDeleteableNonDeletedColumnValue.php | 25 ++++++ .../SoftDeleteableNonDeletedColumnValue.php | 25 ++++++ ...ftDeleteableMappingNonDeletedValueTest.php | 77 +++++++++++++++++ 6 files changed, 240 insertions(+) create mode 100644 tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteableNonDeletedColumnValue.dcm.xml create mode 100644 tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteableNonDeletedColumnValue.dcm.yml create mode 100644 tests/Gedmo/Mapping/Fixture/SoftDeleteableNonDeletedColumnValue.php create mode 100644 tests/Gedmo/Mapping/Fixture/Xml/SoftDeleteableNonDeletedColumnValue.php create mode 100644 tests/Gedmo/Mapping/Fixture/Yaml/SoftDeleteableNonDeletedColumnValue.php create mode 100644 tests/Gedmo/Mapping/SoftDeleteableMappingNonDeletedValueTest.php diff --git a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteableNonDeletedColumnValue.dcm.xml b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteableNonDeletedColumnValue.dcm.xml new file mode 100644 index 0000000000..73b5a7ab45 --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.SoftDeleteableNonDeletedColumnValue.dcm.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteableNonDeletedColumnValue.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteableNonDeletedColumnValue.dcm.yml new file mode 100644 index 0000000000..c6089e958b --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.SoftDeleteableNonDeletedColumnValue.dcm.yml @@ -0,0 +1,18 @@ +--- +Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteableNonDeletedColumnValue: + type: entity + table: soft_deleteables + gedmo: + soft_deleteable: + field_name: deletedAt + hard_delete: false + non_deleted_column_value: '1970-01-01 00:00:00' + id: + id: + type: integer + generator: + strategy: AUTO + fields: + deletedAt: + type: datetime + nullable: true diff --git a/tests/Gedmo/Mapping/Fixture/SoftDeleteableNonDeletedColumnValue.php b/tests/Gedmo/Mapping/Fixture/SoftDeleteableNonDeletedColumnValue.php new file mode 100644 index 0000000000..e5102322e2 --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/SoftDeleteableNonDeletedColumnValue.php @@ -0,0 +1,85 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * + * @Gedmo\SoftDeleteable(fieldName="deletedAt", hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00') + */ +#[ORM\Entity] +#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', hardDelete: false, nonDeletedColumnValue: '1970-01-01 00:00:00')] +class SoftDeleteableNonDeletedColumnValue +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: Types::INTEGER)] + private $id; + + private ?string $title = null; + + private ?string $code = null; + + /** + * @var string|null + */ + private $slug; + + /** + * @var \DateTime|null + * + * @ORM\Column(name="deleted_at", type="datetime", nullable=true) + */ + #[ORM\Column(name: 'deleted_at', type: Types::DATETIME_MUTABLE, nullable: true)] + private $deletedAt; + + public function getId(): ?int + { + return $this->id; + } + + public function setTitle(?string $title): void + { + $this->title = $title; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setCode(?string $code): void + { + $this->code = $code; + } + + public function getCode(): ?string + { + return $this->code; + } + + public function getSlug(): ?string + { + return $this->slug; + } +} diff --git a/tests/Gedmo/Mapping/Fixture/Xml/SoftDeleteableNonDeletedColumnValue.php b/tests/Gedmo/Mapping/Fixture/Xml/SoftDeleteableNonDeletedColumnValue.php new file mode 100644 index 0000000000..86fbc6c8fb --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Xml/SoftDeleteableNonDeletedColumnValue.php @@ -0,0 +1,25 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Xml; + +class SoftDeleteableNonDeletedColumnValue +{ + /** + * @var int + */ + private $id; + + /** + * @var \DateTime|null + */ + private $deletedAt; +} diff --git a/tests/Gedmo/Mapping/Fixture/Yaml/SoftDeleteableNonDeletedColumnValue.php b/tests/Gedmo/Mapping/Fixture/Yaml/SoftDeleteableNonDeletedColumnValue.php new file mode 100644 index 0000000000..cae52c2381 --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Yaml/SoftDeleteableNonDeletedColumnValue.php @@ -0,0 +1,25 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Yaml; + +class SoftDeleteableNonDeletedColumnValue +{ + /** + * @var int + */ + private $id; + + /** + * @var \DateTime|null + */ + private $deletedAt; +} diff --git a/tests/Gedmo/Mapping/SoftDeleteableMappingNonDeletedValueTest.php b/tests/Gedmo/Mapping/SoftDeleteableMappingNonDeletedValueTest.php new file mode 100644 index 0000000000..61e8e551db --- /dev/null +++ b/tests/Gedmo/Mapping/SoftDeleteableMappingNonDeletedValueTest.php @@ -0,0 +1,77 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping; + +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\Driver\YamlDriver; +use Gedmo\Mapping\ExtensionMetadataFactory; +use Gedmo\SoftDeleteable\SoftDeleteableListener; +use Gedmo\Tests\Mapping\Fixture\SoftDeleteableNonDeletedColumnValue as AnnotatedSoftDeleteable; +use Gedmo\Tests\Mapping\Fixture\Xml\SoftDeleteableNonDeletedColumnValue as XmlSoftDeleteable; +use Gedmo\Tests\Mapping\Fixture\Yaml\SoftDeleteableNonDeletedColumnValue as YamlSoftDeleteable; + +/** + * These are mapping tests for SoftDeleteable extension + * + * @author Gustavo Falco + * @author Gediminas Morkevicius + */ +final class SoftDeleteableMappingNonDeletedValueTest extends ORMMappingTestCase +{ + private EntityManager $em; + + protected function setUp(): void + { + ORMMappingTestCase::setUp(); + + $listener = new SoftDeleteableListener(); + $listener->setCacheItemPool($this->cache); + + $this->em = $this->getBasicEntityManager(); + $this->em->getEventManager()->addEventSubscriber($listener); + } + + /** + * @return \Generator + */ + public static function dataSoftDeleteableObject(): \Generator + { + yield 'Model with XML mapping' => [XmlSoftDeleteable::class]; + + if (PHP_VERSION_ID >= 80000) { + yield 'Model with attributes' => [AnnotatedSoftDeleteable::class]; + } elseif (class_exists(AnnotationDriver::class)) { + yield 'Model with annotations' => [AnnotatedSoftDeleteable::class]; + } + + if (class_exists(YamlDriver::class)) { + yield 'Model with YAML mapping' => [YamlSoftDeleteable::class]; + } + } + + /** + * @param class-string $className + * + * @dataProvider dataSoftDeleteableObject + */ + public function testSoftDeleteableMapping(string $className): void + { + // Force metadata class loading. + $this->em->getClassMetadata($className); + $cacheId = ExtensionMetadataFactory::getCacheId($className, 'Gedmo\SoftDeleteable'); + $config = $this->cache->getItem($cacheId)->get(); + + static::assertArrayHasKey('nonDeletedColumnValue', $config); + static::assertSame('1970-01-01 00:00:00', $config['nonDeletedColumnValue']); + } +} From 635e7544e8e943d710a1e6d5b23329e731d178cc Mon Sep 17 00:00:00 2001 From: Ruben Kluft Date: Wed, 27 Aug 2025 15:33:56 +0200 Subject: [PATCH 16/16] update nondeletedcolumn value docs in readme --- doc/softdeleteable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/softdeleteable.md b/doc/softdeleteable.md index a75948497b..651926e5f6 100644 --- a/doc/softdeleteable.md +++ b/doc/softdeleteable.md @@ -185,7 +185,7 @@ class Article - +