Passed
Push — master ( e1f52f...113f3e )
by Emmanuel
07:00
created

AbstractAnonymizer::setReturnRes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 2
cts 2
cp 1
rs 9.4285
c 0
b 0
f 0
nc 1
cc 1
eloc 3
nop 1
crap 1
1
<?php
2
/**
3
 * neuralyzer : Data Anonymization Library and CLI Tool
4
 *
5
 * PHP Version 7.1
6
 *
7
 * @author Emmanuel Dyan
8
 * @author Rémi Sauvat
9
 * @copyright 2018 Emmanuel Dyan
10
 *
11
 * @package edyan/neuralyzer
12
 *
13
 * @license GNU General Public License v2.0
14
 *
15
 * @link https://github.com/edyan/neuralyzer
16
 */
17
18
namespace Edyan\Neuralyzer\Anonymizer;
19
20
use Edyan\Neuralyzer\Configuration\Reader;
21
use Edyan\Neuralyzer\Exception\NeuralizerConfigurationException;
22
23
/**
24
 * Abstract Anonymizer, that can be implemented as DB Anonymizer for example
25
 * Its goal is only to anonymize any data, from a simple array
26
 * not to write or read it from anywhere
27
 *
28
 */
29
abstract class AbstractAnonymizer
30
{
31
    /**
32
     * Truncate table
33
     */
34
    const TRUNCATE_TABLE = 1;
35
36
    /**
37
     * Update data into table
38
     */
39
    const UPDATE_TABLE = 2;
40
41
    /**
42
     * Insert data into table
43
     */
44
    const INSERT_TABLE = 4;
45
46
47
    /**
48
     * Set the batch size for updates
49
     * @var int
50
     */
51
    protected $batchSize = 1000;
52
53
    /**
54
     * Contains the configuration object
55
     * @var Reader
56
     */
57
    protected $configuration;
58
59
    /**
60
     * Configuration of entities
61
     * @var array
62
     */
63
    protected $configEntites = [];
64
65
    /**
66
     * Current table (entity) to process
67
     * @var string
68
     */
69
    protected $entity;
70
71
    /**
72
     * Current table (entity) Columns
73
     * @var array
74
     */
75
    protected $entityCols;
76
77
    /**
78
     * Limit the number of updates or create
79
     * @var int
80
     */
81
    protected $limit = 0;
82
83
    /**
84
     * Pretend we do the update, but do nothing
85
     * @var bool
86
     */
87
    protected $pretend = true;
88
89
    /**
90
     * Return the generated SQL
91
     * @var bool
92
     */
93
    protected $returnRes = false;
94
95
96
    /**
97 20
     * Process the entity according to the anonymizer type
98
     * @param string        $entity         Entity's name
99 20
     * @param callable|null $callback       Callback function with current row num as parameter
100 20
     * @return array
101 20
     */
102
    abstract public function processEntity(
103
        string $entity,
104
        callable $callback = null
105
    ): array;
106
107
108
    /**
109 16
     * Set the configuration
110
     * @param Reader $configuration
111 16
     */
112
    public function setConfiguration(Reader $configuration): void
113 14
    {
114
        $this->configuration = $configuration;
115 14
        $this->configEntites = $configuration->getConfigValues()['entities'];
116 14
    }
117 4
118
119
    /**
120 14
     * Limit of fake generated records for updates and creates
121 14
     * @param int $limit
122 14
     * @return DB
123 11
     */
124 11
    public function setLimit(int $limit): DB
125 3
    {
126 3
        $this->limit = $limit;
127 3
        if ($this->limit < $this->batchSize) {
128
            $this->batchSize = $this->limit;
129
        }
130
131 14
        return $this;
132
    }
133
134
135
    /**
136
     * Activate or deactivate the pretending mode (dry run)
137
     * @param  bool $pretend
138
     * @return DB
139
     */
140 4
    public function setPretend(bool $pretend): DB
141
    {
142 4
        $this->pretend = $pretend;
143
144 4
        return $this;
145 1
    }
146
147
148 3
    /**
149
     * Return or not a result (like an SQL Query that has
150
     * been generated with fake data)
151
     * @param  bool $returnRes
152
     * @return DB
153
     */
154
    public function setReturnRes(bool $returnRes): DB
155
    {
156
        $this->returnRes = $returnRes;
157 12
158
        return $this;
159 12
    }
160
161 12
162
    /**
163 12
     * Evaluate, from the configuration if I have to update or Truncate the table
164 12
     *
165 12
     * @return int
166 12
     */
167 11
    protected function whatToDoWithEntity(): int
168 11
    {
169 11
        $this->checkEntityIsInConfig();
170
171
        $entityConfig = $this->configEntites[$this->entity];
172 11
173 1
        $actions = 0;
174 1
        if (array_key_exists('delete', $entityConfig) && $entityConfig['delete'] === true) {
175
            $actions |= self::TRUNCATE_TABLE;
176
        }
177 11
178
        if (array_key_exists('cols', $entityConfig)) {
179 11
            switch ($entityConfig['action']) {
180
                case 'update':
181 11
                    $actions |= self::UPDATE_TABLE;
182 11
                    break;
183
                case 'insert':
184
                    $actions |= self::INSERT_TABLE;
185
                    break;
186 10
            }
187
        }
188
189
        return $actions;
190
    }
191
192
193
    /**
194
     * Returns the 'delete_where' parameter for an entity in config (or empty)
195 16
     *
196
     * @return string
197 16
     */
198 1
    public function getWhereConditionInConfig(): string
199 1
    {
200
        $this->checkEntityIsInConfig();
201
202 15
        if (!array_key_exists('delete_where', $this->configEntites[$this->entity])) {
203 1
            return '';
204 1
        }
205
206
        return $this->configEntites[$this->entity]['delete_where'];
207 14
    }
208
209
210
    /**
211
     * Generate fake data for an entity and return it as an Array
212
     *
213
     * @return array
214
     */
215 12
    protected function generateFakeData(): array
216
    {
217 12
        $this->checkEntityIsInConfig();
218 1
219
        $faker = \Faker\Factory::create($this->configuration->getConfigValues()['language']);
220 11
221
        $colsInConfig = $this->configEntites[$this->entity]['cols'];
222
        $row = [];
223
        foreach ($colsInConfig as $colName => $colProps) {
224
            $this->checkColIsInEntity($colName);
225
            $data = call_user_func_array(
226
                [$faker, $colProps['method']],
227
                $colProps['params']
228
            );
229
230
            if (!is_scalar($data)) {
231
                $msg = "You must use faker methods that generate strings: '{$colProps['method']}' forbidden";
232
                throw new NeuralizerConfigurationException($msg);
233
            }
234
235
            $row[$colName] = $data;
236
237
            $colLength = $this->entityCols[$colName]['length'];
238
            // Cut the value if too long ...
239
            if (!empty($colLength) && strlen($data) > $colLength) {
240
                $row[$colName] = substr($data, 0, $this->entityCols[$colName]['length']);
241
            }
242
        }
243
244
        return $row;
245
    }
246
247
248
    /**
249
     * Make sure that entity is defined in the configuration
250
     *
251
     * @throws NeuralizerConfigurationException
252
     */
253
    private function checkEntityIsInConfig(): void
254
    {
255
        if (empty($this->configEntites)) {
256
            throw new NeuralizerConfigurationException(
257
                'No entities found. Have you loaded a configuration file ?'
258
            );
259
        }
260
        if (!array_key_exists($this->entity, $this->configEntites)) {
261
            throw new NeuralizerConfigurationException(
262
                "No configuration for that entity ({$this->entity})"
263
            );
264
        }
265
    }
266
267
    /**
268
     * Verify a column is defined in the real entityCols
269
     *
270
     * @throws NeuralizerConfigurationException
271
     * @param  string $colName [description]
272
     */
273
    private function checkColIsInEntity(string $colName): void
274
    {
275
        if (!array_key_exists($colName, $this->entityCols)) {
276
            throw new NeuralizerConfigurationException("Col $colName does not exist");
277
        }
278
    }
279
}
280