Skip to content

Commit 8054b07

Browse files
committed
Support faker and fixed methods
method can indicate scope for performance improvement
1 parent 59d2075 commit 8054b07

3 files changed

Lines changed: 120 additions & 70 deletions

File tree

src/Anonymizer.php

Lines changed: 92 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -88,95 +88,117 @@ public function execute(PDO $pdo, OutputInterface $output)
8888

8989
foreach ($this->columns as $column) {
9090
$output->writeLn("Anonymizing column: <info>" . $column->identifier() . "</info> ({$column->displayMethod()})");
91-
$method = new \Anonymizer\Method\FakerMethod($column->getArguments());
92-
93-
$stmt = $pdo->prepare("SELECT " . $column->getName() . ' FROM ' . $column->getTableName());
94-
$stmt->execute();
95-
$map = [];
96-
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
97-
$oldValue = $row[$column->getName()];
98-
$newValue = $method->apply($oldValue, $row);
99-
$map[$oldValue] = $newValue;
100-
}
101-
$max = count($map) * (1+count($column->getCascades()));
102-
//print_r($map);
103-
104-
$progress = new ProgressBar($output, $max);
105-
$progress->setRedrawFrequency(1000);
106-
$progress->start();
107-
$missing = [];
108-
109-
// Sanity check
110-
foreach ($column->getCascades() as $cascade) {
111-
$missing[$cascade] = [];
112-
$part = explode('.', $cascade);
113-
if (count($part)!=2) {
114-
throw new RuntimeException("Expected cascade with 2 parts: " . $cascade);
115-
}
116-
$cascadeTable = $part[0];
117-
$cascadeColumn = $part[1];
118-
$stmt = $pdo->prepare("SELECT " . $cascadeColumn . ' FROM ' . $cascadeTable);
119-
$stmt->execute();
120-
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
121-
122-
foreach ($rows as $row) {
123-
$value = $row[$cascadeColumn];
124-
if ($value && !isset($map[$value])) {
125-
$missing[$cascade][] = $value;
126-
}
127-
}
91+
switch ($column->getMethod()) {
92+
case 'faker':
93+
$method = new \Anonymizer\Method\FakerMethod($column->getArguments());
94+
break;
95+
case 'fixed':
96+
$method = new \Anonymizer\Method\FixedMethod($column->getArguments());
97+
break;
98+
default:
99+
throw new RuntimeException("Unsupported method: " . $column->getMethod());
128100
}
129101

130-
// Fix main table
131-
foreach ($map as $oldValue => $newValue) {
132-
//echo $oldValue . ' => ' . $newValue . "\n";
102+
if ($method->getScope()=='table') {
133103
$stmt = $pdo->prepare(
134-
"UPDATE " . $column->getTableName() . ' SET ' . $column->getName() . '=:newValue WHERE ' . $column->getName() . '=:oldValue'
104+
"UPDATE " . $column->getTableName() . ' SET ' . $column->getName() . '=:newValue'
135105
);
136106
$stmt->execute(
137107
[
138-
'oldValue' => $oldValue,
139-
'newValue' => $newValue
108+
'newValue' => $method->apply(null, null)
140109
]
141110
);
142-
$progress->advance();
143-
144111
}
145112

146-
// fix cascades
147-
foreach ($column->getCascades() as $cascade) {
148-
$part = explode('.', $cascade);
149-
if (count($part)!=2) {
150-
throw new RuntimeException("Expected cascade with 2 parts: " . $cascade);
113+
if ($method->getScope()=='row') {
114+
$stmt = $pdo->prepare("SELECT " . $column->getName() . ' FROM ' . $column->getTableName());
115+
$stmt->execute();
116+
$map = [];
117+
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
118+
$oldValue = $row[$column->getName()];
119+
$newValue = $method->apply($oldValue, $row);
120+
$map[$oldValue] = $newValue;
121+
}
122+
$max = count($map) * (1+count($column->getCascades()));
123+
//print_r($map);
124+
125+
$progress = new ProgressBar($output, $max);
126+
$progress->setRedrawFrequency(1000);
127+
$progress->start();
128+
$missing = [];
129+
130+
// Sanity check
131+
foreach ($column->getCascades() as $cascade) {
132+
$missing[$cascade] = [];
133+
$part = explode('.', $cascade);
134+
if (count($part)!=2) {
135+
throw new RuntimeException("Expected cascade with 2 parts: " . $cascade);
136+
}
137+
$cascadeTable = $part[0];
138+
$cascadeColumn = $part[1];
139+
$stmt = $pdo->prepare("SELECT " . $cascadeColumn . ' FROM ' . $cascadeTable);
140+
$stmt->execute();
141+
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
142+
143+
foreach ($rows as $row) {
144+
$value = $row[$cascadeColumn];
145+
if ($value && !isset($map[$value])) {
146+
$missing[$cascade][] = $value;
147+
}
148+
}
151149
}
152-
$cascadeTable = $part[0];
153-
$cascadeColumn = $part[1];
154-
155-
// Fix referencing values
156-
foreach ($map as $oldValue=>$newValue) {
157-
$sql = "UPDATE " . $cascadeTable . ' SET ' . $cascadeColumn . '=:newValue WHERE ' . $cascadeColumn . '=:oldValue';
158-
$subStmt = $pdo->prepare(
159-
$sql
150+
151+
// Fix main table
152+
foreach ($map as $oldValue => $newValue) {
153+
//echo $oldValue . ' => ' . $newValue . "\n";
154+
$stmt = $pdo->prepare(
155+
"UPDATE " . $column->getTableName() . ' SET ' . $column->getName() . '=:newValue WHERE ' . $column->getName() . '=:oldValue'
160156
);
161-
$subStmt->execute(
157+
$stmt->execute(
162158
[
163159
'oldValue' => $oldValue,
164160
'newValue' => $newValue
165161
]
166162
);
167163
$progress->advance();
164+
168165
}
169-
// Fix missing values
170-
foreach ($missing[$cascade] as $k => $missingValue) {
171-
$sql = "UPDATE " . $cascadeTable . ' SET ' . $cascadeColumn . '=null WHERE ' . $cascadeColumn . '=:missingValue';
172-
$subStmt = $pdo->prepare(
173-
$sql
174-
);
175-
$subStmt->execute(
176-
[
177-
'missingValue' => $missingValue
178-
]
179-
);
166+
167+
// fix cascades
168+
foreach ($column->getCascades() as $cascade) {
169+
$part = explode('.', $cascade);
170+
if (count($part)!=2) {
171+
throw new RuntimeException("Expected cascade with 2 parts: " . $cascade);
172+
}
173+
$cascadeTable = $part[0];
174+
$cascadeColumn = $part[1];
175+
176+
// Fix referencing values
177+
foreach ($map as $oldValue=>$newValue) {
178+
$sql = "UPDATE " . $cascadeTable . ' SET ' . $cascadeColumn . '=:newValue WHERE ' . $cascadeColumn . '=:oldValue';
179+
$subStmt = $pdo->prepare(
180+
$sql
181+
);
182+
$subStmt->execute(
183+
[
184+
'oldValue' => $oldValue,
185+
'newValue' => $newValue
186+
]
187+
);
188+
$progress->advance();
189+
}
190+
// Fix missing values
191+
foreach ($missing[$cascade] as $k => $missingValue) {
192+
$sql = "UPDATE " . $cascadeTable . ' SET ' . $cascadeColumn . '=null WHERE ' . $cascadeColumn . '=:missingValue';
193+
$subStmt = $pdo->prepare(
194+
$sql
195+
);
196+
$subStmt->execute(
197+
[
198+
'missingValue' => $missingValue
199+
]
200+
);
201+
}
180202
}
181203
}
182204
}

src/Method/FakerMethod.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class FakerMethod
66
{
77
protected $faker;
88
protected $formatter = 'email';
9+
910
public function __construct($arguments = [])
1011
{
1112
$locale = 'en_US';
@@ -24,4 +25,9 @@ public function apply($value, $row)
2425
$value = $this->faker->unique()->{$this->formatter};
2526
return $value;
2627
}
28+
29+
public function getScope()
30+
{
31+
return 'row';
32+
}
2733
}

src/Method/FixedMethod.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Anonymizer\Method;
4+
5+
class FixedMethod
6+
{
7+
protected $faker;
8+
public function __construct($arguments = [])
9+
{
10+
$this->value = $arguments['value'];
11+
}
12+
13+
public function apply($value, $row)
14+
{
15+
return $this->value;
16+
}
17+
18+
public function getScope()
19+
{
20+
return 'table';
21+
}
22+
}

0 commit comments

Comments
 (0)