Passed
Pull Request — master (#1)
by Flavien
03:14
created

Import::setEntityFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
crap 6
1
<?php
2
3
namespace QualityCode\TransformAndLoadBundle\Services;
4
5
use Symfony\Component\Console\Helper\ProgressBar;
6
use Symfony\Component\Console\Output\OutputInterface;
7
use QualityCode\TransformAndLoadBundle\Services\Import\SchemaDefinitionGroupByEntity;
8
use QualityCode\TransformAndLoadBundle\Services\Import\GetDataFromCsvFile;
9
use Doctrine\ORM\EntityManagerInterface;
10
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
11
use Symfony\Component\PropertyAccess\PropertyAccess;
12
use QualityCode\TransformAndLoadBundle\Import\Transformer\TransformerInterface;
13
use QualityCode\TransformAndLoadBundle\Import\Transformer\TransformerFactory;
14
15
class Import
16
{
17
    /**
18
     * @var EntityManagerInterface
19
     */
20
    private $entityManager;
21
22
    /**
23
     * @var TransformerFactory
24
     */
25
    private $transformerFactory;
26
27
    /**
28
     * @var SchemaDefinitionGroupByEntity
29
     */
30
    private $schemaDefintionToSchemaGroupByEntityConverter;
31
32
    /**
33
     * @var array
34
     */
35
    private $schemaDefinition;
36
37
    /**
38
     * @var array
39
     */
40
    private $schemaDefintiontGroupByEntity;
41
42
    /**
43
     * @var GetDataFromCsvFile
44
     */
45
    private $dataGetterFromCsv;
46
47
    /**
48
     * @var array
49
     */
50
    private $data;
51
52
    /**
53
     * @var int
54
     */
55
    private $dataSize;
56
57
    /**
58
     * @var ProgressBar
59
     */
60
    private $progressBar;
61
62
    /**
63
     * @var PropertyAccessorInterface
64
     */
65
    private $propertyAccessor;
66
67
    /**
68
     * @param EntityManagerInterface        $entityManager
69
     * @param SchemaDefinitionGroupByEntity $schemaDefintionToSchemaGroupByEntity
70
     * @param GetDataFromCsvFile            $dataGetterFromCsv
71
     * @param TransformerFactory            $transformerFactory
72
     */
73
    public function __construct(EntityManagerInterface $entityManager, SchemaDefinitionGroupByEntity $schemaDefintionToSchemaGroupByEntity, GetDataFromCsvFile $dataGetterFromCsv, TransformerFactory $transformerFactory)
74
    {
75
        $this->entityManager = $entityManager;
76
        $this->schemaDefintionToSchemaGroupByEntityConverter = $schemaDefintionToSchemaGroupByEntity;
77
        $this->dataGetterFromCsv = $dataGetterFromCsv;
78
        $this->transformerFactory = $transformerFactory;
79
        $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
80
    }
81
82
    /**
83
     * @param string $fileName
84
     * @param string $delimiter
85
     *
86
     * @return Import
87
     */
88
    protected function setData(string $fileName, string $delimiter)
89
    {
90
        $this->data = $this->dataGetterFromCsv->getData($fileName, $delimiter);
91
        $this->dataSize = sizeof($this->data);
92
93
        return $this;
94
    }
95
96
    /**
97
     * @param array $schemaDefinition
98
     *
99
     * @return Import
100
     */
101
    protected function setSchemaDefinition(array $schemaDefinition)
102
    {
103
        $this->schemaDefintiontGroupByEntity = $this->schemaDefintionToSchemaGroupByEntityConverter->convert($schemaDefinition);
104
        $this->schemaDefinition = $schemaDefinition;
105
106
        return $this;
107
    }
108
109
    /**
110
     * @param array           $schemaDefinition
111
     * @param string          $fileName
112
     * @param OutputInterface $output
113
     */
114
    public function import(array $schemaDefinition, string $fileName, OutputInterface $output)
115
    {
116
        $this->setSchemaDefinition($schemaDefinition);
117
        $this->setData($fileName, $this->schemaDefinition['delimiter']);
118
        $this->entityManager->getConnection()->getConfiguration()->setSQLLogger(null);
119
120
        $i = 1;
121
122
        $this->initProgressBar($output);
123
        foreach ($this->data as $lineNumber => $line) {
124
            $fieldsGroupByEntity = $this->groupFieldsByEntity($line);
125
            $mainEntity = $this->linkEntities($this->buildEntities($fieldsGroupByEntity));
126
            $this->persistEntities($mainEntity, $i);
127
            $this->advanceProgressBar($i++);
128
        }
129
130
        $this->entityManager->flush();
131
        $this->entityManager->clear();
132
    }
133
134
    /**
135
     * @param array $entities
136
     *
137
     * @return mixed
138
     */
139
    protected function linkEntities(array $entities)
140
    {
141
        $mainEntity = $entities[$this->schemaDefinition['main_entity']];
142
        unset($entities[$this->schemaDefinition['main_entity']]);
143
        foreach ($entities as $entityName => $entity) {
144
            $fieldName = $this->schemaDefinition['link_entities_mapping'][$entityName];
145
            $this->propertyAccessor->setValue($mainEntity, $fieldName, $entity);
146
        }
147
148
        return $mainEntity;
149
    }
150
151
    /**
152
     * @param mixed $entity
153
     * @param int   $advance
154
     *
155
     * @return Import
156
     */
157
    protected function persistEntities($entity, int $advance)
158
    {
159
        $this->entityManager->persist($entity);
160
        if (($advance % $this->schemaDefinition['batch_size']) === 0) {
161
            $this->entityManager->flush();
162
            $this->entityManager->clear();
163
        }
164
165
        return $this;
166
    }
167
168
    /**
169
     * @param array $fields
170
     *
171
     * @return array
172
     */
173
    protected function buildEntities(array $fields)
174
    {
175
        $entities = array();
176
177
        foreach ($fields as $entityClassName => $values) {
178
            $entities[$entityClassName] = $this->setEntityFields($values, new $entityClassName());
179
        }
180
181
        return $entities;
182
    }
183
184
    /**
185
     * @param array $values
186
     * @param mixed $entity
187
     *
188
     * @return mixed
189
     */
190
    protected function setEntityFields(array $values, $entity)
191
    {
192
        foreach ($values as $name => $value) {
193
            $this->propertyAccessor->setValue($entity, $name, $value);
194
        }
195
196
        return $entity;
197
    }
198
199
    /**
200
     * @param array $line
201
     *
202
     * @return array
203
     */
204
    protected function groupFieldsByEntity(array $line)
205
    {
206
        $fieldsGroupByEntity = $this->initFieldsGroupByEntity();
207
208
        foreach ($this->schemaDefintiontGroupByEntity as $entityName => $fields) {
209
            foreach ($fields as $name => $config) {
210
                if (array_key_exists($name, $line)) {
211
                    $value = $this->getCellValue($config, $line[$name]);
212
                    $fieldsGroupByEntity[$entityName][$config['mapped_with']] = $value;
213
                }
214
            }
215
        }
216
217
        return $fieldsGroupByEntity;
218
    }
219
220
    /**
221
     * @param array  $config
222
     * @param string $value
223
     *
224
     * @return mixed
225
     */
226
    protected function getCellValue(array $config, string $value)
227
    {
228
        if (!array_key_exists('transform', $config)) {
229
            return $value;
230
        }
231
232
        $transformer = $this->getTransformer($config['transform']);
233
        if (null === $transformer) {
234
            return $value;
235
        }
236
237
        return $transformer->transform($value);
238
    }
239
240
    /**
241
     * @param string $transformerName
242
     *
243
     * @return TransformerInterface
244
     */
245
    protected function getTransformer(string $transformerName)
246
    {
247
        if (!array_key_exists($transformerName, $this->schemaDefinition['transformer'])) {
248
            return null;
249
        }
250
251
        return $this->transformerFactory->create($this->schemaDefinition['transformer'][$transformerName]);
252
    }
253
254
    /**
255
     * @return array
256
     */
257
    protected function initFieldsGroupByEntity()
258
    {
259
        $fieldsGroupByEntity = array();
260
        $keys = array_keys($this->schemaDefintiontGroupByEntity);
261
262
        foreach ($keys as $key) {
263
            $fieldsGroupByEntity[$key] = array();
264
        }
265
266
        return $fieldsGroupByEntity;
267
    }
268
269
    /**
270
     * @param OutputInterface $output
271
     *
272
     * @return \QualityCode\TransformAndLoadBundle\Services\Import
273
     */
274
    protected function initProgressBar(OutputInterface $output)
275
    {
276
        $this->progressBar = new ProgressBar($output, $this->dataSize);
277
        $this->progressBar->start();
278
279
        return $this;
280
    }
281
282
    /**
283
     * @return Import
284
     */
285
    protected function finishProgressBar()
286
    {
287
        $this->progressBar->finish();
288
289
        return $this;
290
    }
291
292
    /**
293
     * @param int $advance
294
     *
295
     * @return Import
296
     */
297
    protected function advanceProgressBar(int $advance)
298
    {
299
        if (($advance % $this->schemaDefinition['batch_size']) === 0) {
300
            $this->progressBar->advance($this->schemaDefinition['batch_size']);
301
        }
302
303
        return $this;
304
    }
305
}
306