Completed
Push — master ( a1f222...7ceccc )
by Emmanuel
03:50
created

AbstractAnonymizer::initFaker()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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