Skip to content

Commit 9d33bb6

Browse files
committed
no issue - add new AbstractSingleColumnAnonymizer class which allows to re-use the generated SQL expression
1 parent 391ee40 commit 9d33bb6

10 files changed

+172
-181
lines changed

src/Anonymization/Anonymizer/AbstractEnumAnonymizer.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer;
66

7+
use MakinaCorpus\QueryBuilder\Expression;
78
use MakinaCorpus\QueryBuilder\Vendor;
89
use MakinaCorpus\QueryBuilder\Query\Select;
910
use MakinaCorpus\QueryBuilder\Query\Update;
@@ -12,7 +13,7 @@
1213
* Can not be use alone, check FrFR/PrenomAnonymizer for an
1314
* example on how to extend this Anonymizer for your need.
1415
*/
15-
abstract class AbstractEnumAnonymizer extends AbstractAnonymizer
16+
abstract class AbstractEnumAnonymizer extends AbstractSingleColumnAnonymizer
1617
{
1718
private ?string $sampleTableName = null;
1819

@@ -43,7 +44,7 @@ public function initialize(): void
4344
}
4445

4546
#[\Override]
46-
public function anonymize(Update $update): void
47+
public function createAnonymizeExpression(Update $update): Expression
4748
{
4849
$expr = $update->expression();
4950

@@ -86,7 +87,7 @@ public function anonymize(Update $update): void
8687
$joinAlias
8788
);
8889

89-
$update->set($this->columnName, $expr->column('value', $joinAlias));
90+
return $expr->column('value', $joinAlias);
9091
}
9192

9293
#[\Override]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer;
6+
7+
use MakinaCorpus\QueryBuilder\Expression;
8+
use MakinaCorpus\QueryBuilder\Query\Update;
9+
10+
/**
11+
* Anonymizer that targets a single column.
12+
*
13+
* Using this as a base class will allow more complex anonymizers to re-use
14+
* the generated SQL code of this anonymizer in more complex SQL expressions.
15+
*/
16+
abstract class AbstractSingleColumnAnonymizer extends AbstractAnonymizer
17+
{
18+
#[\Override]
19+
public final function anonymize(Update $update): void
20+
{
21+
$update->set($this->columnName, $this->createAnonymizeExpression($update));
22+
}
23+
24+
/**
25+
* Create anonymization SQL expression, the expression must return a value, even if null.
26+
*/
27+
public abstract function createAnonymizeExpression(Update $update): Expression;
28+
}

src/Anonymization/Anonymizer/Core/ConstantAnonymizer.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\Core;
66

7-
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractAnonymizer;
7+
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractSingleColumnAnonymizer;
88
use MakinaCorpus\DbToolsBundle\Attribute\AsAnonymizer;
9+
use MakinaCorpus\QueryBuilder\Expression;
910
use MakinaCorpus\QueryBuilder\Query\Update;
1011

1112
#[AsAnonymizer(
@@ -18,7 +19,7 @@
1819
- `type`: a SQL type for the given value (default is 'text')
1920
TXT
2021
)]
21-
class ConstantAnonymizer extends AbstractAnonymizer
22+
class ConstantAnonymizer extends AbstractSingleColumnAnonymizer
2223
{
2324
#[\Override]
2425
protected function validateOptions(): void
@@ -27,18 +28,15 @@ protected function validateOptions(): void
2728
}
2829

2930
#[\Override]
30-
public function anonymize(Update $update): void
31+
public function createAnonymizeExpression(Update $update): Expression
3132
{
3233
$expr = $update->expression();
3334

34-
$update->set(
35-
$this->columnName,
36-
$this->getSetIfNotNullExpression(
37-
$expr->cast(
38-
$this->options->get('value'),
39-
$this->options->get('type', 'text')
40-
)
41-
),
35+
return $this->getSetIfNotNullExpression(
36+
$expr->cast(
37+
$this->options->get('value'),
38+
$this->options->get('type', 'text')
39+
)
4240
);
4341
}
4442
}

src/Anonymization/Anonymizer/Core/DateAnonymizer.php

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\Core;
66

7-
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractAnonymizer;
7+
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractSingleColumnAnonymizer;
88
use MakinaCorpus\DbToolsBundle\Attribute\AsAnonymizer;
9+
use MakinaCorpus\QueryBuilder\Expression;
910
use MakinaCorpus\QueryBuilder\Vendor;
1011
use MakinaCorpus\QueryBuilder\Query\Update;
1112

@@ -21,7 +22,7 @@
2122
can work with 'datetime' or 'date' formats.
2223
TXT
2324
)]
24-
class DateAnonymizer extends AbstractAnonymizer
25+
class DateAnonymizer extends AbstractSingleColumnAnonymizer
2526
{
2627
#[\Override]
2728
protected function validateOptions(): void
@@ -51,29 +52,25 @@ protected function validateOptions(): void
5152
}
5253

5354
#[\Override]
54-
public function anonymize(Update $update): void
55+
public function createAnonymizeExpression(Update $update): Expression
5556
{
5657
$format = $this->options->get('format', 'datetime');
5758

5859
$min = $this->options->getDate('min');
5960
$max = $this->options->getDate('max');
6061

6162
if ($min && $max) {
62-
$this->anonymizeWithDateRange($update, $format, $min, $max);
63-
64-
return;
63+
return $this->anonymizeWithDateRange($update, $format, $min, $max);
6564
}
6665

6766
if ($delta = $this->options->getInterval('delta')) {
68-
$this->anonmizeWithDelta($update, $format, $delta);
69-
70-
return;
67+
return $this->anonmizeWithDelta($update, $format, $delta);
7168
}
7269

7370
throw new \InvalidArgumentException("Providing either the 'delta' option, or both 'min' and 'max' options is required.");
7471
}
7572

76-
private function anonymizeWithDateRange(Update $update, string $format, \DateTimeImmutable $min, \DateTimeImmutable $max): void
73+
private function anonymizeWithDateRange(Update $update, string $format, \DateTimeImmutable $min, \DateTimeImmutable $max): Expression
7774
{
7875
$diff = $max->diff($min, true);
7976

@@ -96,10 +93,10 @@ private function anonymizeWithDateRange(Update $update, string $format, \DateTim
9693
$delta /= 2;
9794
$middleDate = $min->add(\DateInterval::createFromDateString(\sprintf("%d %s", $delta, $unit)));
9895

99-
$this->anonymizeWithDeltaAndReferenceDate($update, $format, $middleDate, $delta, $unit);
96+
return $this->anonymizeWithDeltaAndReferenceDate($update, $format, $middleDate, $delta, $unit);
10097
}
10198

102-
private function anonmizeWithDelta(Update $update, string $format, \DateInterval $delta): void
99+
private function anonmizeWithDelta(Update $update, string $format, \DateInterval $delta): Expression
103100
{
104101
// @todo I wish for a better alternative...
105102
// query-builder can deal with \DateInterval by- itself, but we are
@@ -137,43 +134,37 @@ private function anonmizeWithDelta(Update $update, string $format, \DateInterval
137134
$expr = $update->expression();
138135
$columnExpr = $expr->column($this->columnName, $this->tableName);
139136

140-
$this->anonymizeWithDeltaAndReferenceDate($update, $format, $columnExpr, $delta, $unit);
137+
return $this->anonymizeWithDeltaAndReferenceDate($update, $format, $columnExpr, $delta, $unit);
141138
}
142139

143-
private function anonymizeWithDeltaAndReferenceDate(Update $update, string $format, mixed $referenceDate, int $delta, string $unit): void
140+
private function anonymizeWithDeltaAndReferenceDate(Update $update, string $format, mixed $referenceDate, int $delta, string $unit): Expression
144141
{
145142
$expr = $update->expression();
146143

147144
$randomDeltaExpr = $this->getRandomIntExpression($delta, 0 - $delta);
148145

149146
if ($this->databaseSession->vendorIs(Vendor::SQLITE)) {
150-
$update->set(
151-
$this->columnName,
152-
$this->getSetIfNotNullExpression(
153-
$expr->dateAdd(
154-
$referenceDate,
155-
$expr->intervalUnit(
156-
// This additional cast is necessary for SQLite only because it
157-
// will mix up int addition and string concatenation, causing
158-
// the interval string to be malformed. For all other vendors,
159-
// it's a no-op.
160-
$expr->cast($randomDeltaExpr, 'varchar'),
161-
$unit
162-
),
163-
),
147+
return $this->getSetIfNotNullExpression(
148+
$expr->dateAdd(
149+
$referenceDate,
150+
$expr->intervalUnit(
151+
// This additional cast is necessary for SQLite only because it
152+
// will mix up int addition and string concatenation, causing
153+
// the interval string to be malformed. For all other vendors,
154+
// it's a no-op.
155+
$expr->cast($randomDeltaExpr, 'varchar'),
156+
$unit
157+
)
164158
)
165159
);
166160
} else {
167-
$update->set(
168-
$this->columnName,
169-
$this->getSetIfNotNullExpression(
170-
$expr->cast(
171-
$expr->dateAdd(
172-
$referenceDate,
173-
$expr->intervalUnit($randomDeltaExpr, $unit),
174-
),
175-
'date' === $format ? 'date' : 'timestamp',
176-
)
161+
return $this->getSetIfNotNullExpression(
162+
$expr->cast(
163+
$expr->dateAdd(
164+
$referenceDate,
165+
$expr->intervalUnit($randomDeltaExpr, $unit),
166+
),
167+
'date' === $format ? 'date' : 'timestamp',
177168
)
178169
);
179170
}

src/Anonymization/Anonymizer/Core/EmailAnonymizer.php

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\Core;
66

7-
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractAnonymizer;
7+
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractSingleColumnAnonymizer;
88
use MakinaCorpus\DbToolsBundle\Attribute\AsAnonymizer;
9+
use MakinaCorpus\QueryBuilder\Expression;
910
use MakinaCorpus\QueryBuilder\Vendor;
1011
use MakinaCorpus\QueryBuilder\Query\Update;
1112

@@ -17,7 +18,7 @@
1718
Values are salted to prevent reversing the hash with option 'use_salt' (default: true).
1819
TXT
1920
)]
20-
class EmailAnonymizer extends AbstractAnonymizer
21+
class EmailAnonymizer extends AbstractSingleColumnAnonymizer
2122
{
2223
#[\Override]
2324
protected function validateOptions(): void
@@ -27,7 +28,7 @@ protected function validateOptions(): void
2728
}
2829

2930
#[\Override]
30-
public function anonymize(Update $update): void
31+
public function createAnonymizeExpression(Update $update): Expression
3132
{
3233
$expr = $update->expression();
3334

@@ -43,16 +44,13 @@ public function anonymize(Update $update): void
4344
$emailHashExpr = $expr->md5($userExpr);
4445
}
4546

46-
$update->set(
47-
$this->columnName,
48-
$this->getSetIfNotNullExpression(
49-
$expr->concat(
50-
'anon-',
51-
$emailHashExpr,
52-
'@',
53-
$this->options->get('domain', 'example.com'),
54-
),
55-
),
47+
return $this->getSetIfNotNullExpression(
48+
$expr->concat(
49+
'anon-',
50+
$emailHashExpr,
51+
'@',
52+
$this->options->get('domain', 'example.com'),
53+
)
5654
);
5755
}
5856
}

0 commit comments

Comments
 (0)