Anonymizer::replacePlaceholders()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace Arrilot\DataAnonymization;
4
5
use Arrilot\DataAnonymization\Database\DatabaseInterface;
6
use Exception;
7
8
class Anonymizer
9
{
10
    /**
11
     * Database interactions object.
12
     *
13
     * @var DatabaseInterface
14
     */
15
    protected $database;
16
17
    /**
18
     * Generator object (e.g \Faker\Factory).
19
     *
20
     * @var mixed
21
     */
22
    protected $generator;
23
24
    /**
25
     * Blueprints for tables.
26
     *
27
     * @var array
28
     */
29
    protected $blueprints = [];
30
31
    /**
32
     * Constructor.
33
     *
34
     * @param DatabaseInterface $database
35
     * @param mixed             $generator
36
     */
37
    public function __construct(DatabaseInterface $database, $generator = null)
38
    {
39
        $this->database = $database;
40
41
        if (is_null($generator) && class_exists('\Faker\Factory')) {
42
            $generator = \Faker\Factory::create();
43
        }
44
45
        if (!is_null($generator)) {
46
            $this->setGenerator($generator);
47
        }
48
    }
49
50
    /**
51
     * Setter for generator.
52
     *
53
     * @param mixed $generator
54
     *
55
     * @return $this
56
     */
57
    public function setGenerator($generator)
58
    {
59
        $this->generator = $generator;
60
61
        return $this;
62
    }
63
64
    /**
65
     * Getter for generator.
66
     *
67
     * @return mixed
68
     */
69
    public function getGenerator()
70
    {
71
        return $this->generator;
72
    }
73
74
    /**
75
     * Perform data anonymization.
76
     *
77
     * @return void
78
     */
79
    public function run()
80
    {
81
        foreach ($this->blueprints as $table => $blueprint) {
82
            $this->applyBlueprint($blueprint);
83
        }
84
    }
85
86
    /**
87
     * Describe a table with a given callback.
88
     *
89
     * @param string   $name
90
     * @param callable $callback
91
     *
92
     * @return void
93
     */
94
    public function table($name, callable $callback)
95
    {
96
        $blueprint = new Blueprint($name, $callback);
97
98
        $this->blueprints[$name] = $blueprint->build();
99
    }
100
101
    /**
102
     * Apply blueprint to the database.
103
     *
104
     * @param Blueprint $blueprint
105
     *
106
     * @return void
107
     */
108
    protected function applyBlueprint(Blueprint $blueprint)
109
    {
110
        foreach ($blueprint->columns as $column) {
111
            $this->updateColumn($blueprint->table, $blueprint->primary, $column);
112
        }
113
    }
114
115
    /**
116
     * Update all needed values of a give column.
117
     *
118
     * @param string $table
119
     * @param array  $primary
120
     * @param array  $column
121
     */
122
    protected function updateColumn($table, $primary, $column)
123
    {
124
        $columns = $this->mergeColumns($primary, $column['name']);
125
        $where = $column['where'];
126
127
        foreach ($this->database->getRows($table, $columns, $where) as $rowNum => $row) {
128
            $this->database->updateByPrimary(
129
                $table,
130
                Helpers::arrayOnly($row, $primary),
131
                $column['name'],
132
                $this->calculateNewValue($column['replace'], $rowNum)
133
            );
134
        }
135
    }
136
137
    /**
138
     * Calculate new value for each row.
139
     *
140
     * @param string|callable $replace
141
     * @param int             $rowNum
142
     *
143
     * @return string
144
     */
145
    protected function calculateNewValue($replace, $rowNum)
146
    {
147
        $value = $this->handlePossibleClosure($replace);
148
149
        return $this->replacePlaceholders($value, $rowNum);
150
    }
151
152
    /**
153
     * Replace placeholders.
154
     *
155
     * @param mixed $value
156
     * @param int   $rowNum
157
     *
158
     * @return mixed
159
     */
160
    protected function replacePlaceholders($value, $rowNum)
161
    {
162
        if (!is_string($value)) {
163
            return $value;
164
        }
165
166
        return str_replace('#row#', $rowNum, $value);
167
    }
168
169
    /**
170
     * @param $replace
171
     *
172
     * @return mixed
173
     */
174
    protected function handlePossibleClosure($replace)
175
    {
176
        if (!is_callable($replace)) {
177
            return $replace;
178
        }
179
180
        if ($this->generator === null) {
181
            throw new Exception('You forgot to set a generator');
182
        }
183
184
        return call_user_func($replace, $this->generator);
185
    }
186
187
    /**
188
     * Merge columns for select.
189
     *
190
     * @param array  $primary
191
     * @param string $columnName
192
     *
193
     * @return array
194
     */
195
    protected function mergeColumns($primary, $columnName)
196
    {
197
        return array_merge($primary, [
198
            $columnName,
199
        ]);
200
    }
201
}
202