Importer::import()   F
last analyzed

Complexity

Conditions 11
Paths 517

Size

Total Lines 68
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 11

Importance

Changes 0
Metric Value
eloc 42
c 0
b 0
f 0
dl 0
loc 68
rs 3.8208
ccs 35
cts 35
cp 1
cc 11
nc 517
nop 2
crap 11

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Import;
4
5
use App\Entity\ImportDateTime;
6
use App\Repository\ImportDateTypeRepositoryInterface;
7
use App\Request\ValidationFailedException;
8
use DateTime;
9
use Psr\Log\LoggerInterface;
10
use Symfony\Component\Validator\Validator\ValidatorInterface;
11
use Throwable;
12
13
class Importer {
14
15
    public function __construct(private ValidatorInterface $validator, private ImportDateTypeRepositoryInterface $importDateTimeRepository, private LoggerInterface $logger)
16
    {
17
    }
18
19 10
    /**
20 10
     * @param object $data
21 10
     * @throws ValidationFailedException
22 10
     */
23 10
    private function validateOrThrow($data) {
24
        $violations = $this->validator->validate($data);
25
26
        if(count($violations) === 0) {
27
            // Validation passed
28
            return;
29 8
        }
30 8
31
        throw new ValidationFailedException($violations);
32 8
    }
33
34 8
35
    /**
36
     * @param object $data
37
     * @throws ImportException
38
     * @throws ValidationFailedException
39
     */
40
    public function import($data, ImportStrategyInterface $strategy): ImportResult {
41
        $this->validateOrThrow($data);
42
43
        try {
44
            if($strategy instanceof InitializeStrategyInterface) {
45
                $strategy->initialize($data);
46
            }
47
48 8
            $repository = $strategy->getRepository();
49 8
            $repository->beginTransaction();
50
51
            $currentEntities = $strategy->getExistingEntities($data);
52 8
            $updatedEntitiesIds = [];
53 3
54
            $addedEntities = [];
55
            $updatedEntities = [];
56 8
            $removedEntities = [];
57 8
            $ignoredEntities = [];
58
59 8
            $entities = $strategy->getData($data);
60 8
61
            // ADD/UPDATE ENTITIES
62 8
            foreach ($entities as $object) {
63 8
                $entity = $strategy->getExistingEntity($object, $currentEntities);
64 8
65 8
                if ($entity !== null) {
66
                    $updatedEntities[] = $entity;
67 8
                    $strategy->updateEntity($entity, $object, $data);
68
                    $updatedEntitiesIds[] = $strategy->getEntityId($entity);
69
                } else {
70 8
                    $entity = $strategy->createNewEntity($object, $data);
71 8
                    $addedEntities[] = $entity;
72
                }
73 8
74 5
                $strategy->persist($entity);
75 5
            }
76 5
77
            // REMOVE ENTITIES
78 7
            if(!$strategy instanceof NonRemovalImportStrategyInterface || $strategy->preventRemoval($data) === false) {
79 7
                foreach ($currentEntities as $entity) {
80
                    $id = $strategy->getEntityId($entity);
81
82 8
                    if (!in_array($id, $updatedEntitiesIds)) {
83
                        if($strategy->remove($entity, $data) === true) {
84
                            $removedEntities[] = $entity;
85
                        } else {
86 7
                            $updatedEntities[] = $entity;
87 7
                        }
88 5
                    }
89
                }
90 5
            }
91 4
92 4
            $repository->commit();
93
94
            $result = new ImportResult($addedEntities, $updatedEntities, $removedEntities, $ignoredEntities, $data);
95
96
            if($strategy instanceof PostActionStrategyInterface) {
97 7
                $strategy->onFinished($result);
98
            }
99 7
100
            return $result;
101 7
        } catch (Throwable $e) {
102 2
            $this->logger->error('Import fehlgeschagen.', [
103
                'exception' => $e
104
            ]);
105 7
            throw new ImportException($e->getMessage(), $e->getCode(), $e);
106 1
        } finally {
107 1
            $this->updateImportDateTime($strategy->getEntityClassName());
108 1
        }
109
    }
110 1
111
    /**
112 8
     * @param object $data
113
     * @throws ImportException
114
     */
115
    public function replaceImport($data, ReplaceImportStrategyInterface $strategy): ImportResult {
116
        $this->validateOrThrow($data);
117
118
        try {
119
            if($strategy instanceof InitializeStrategyInterface) {
120
                $strategy->initialize($data);
121
            }
122
123
            $repository = $strategy->getRepository();
124
            $repository->beginTransaction();
125
126
            $strategy->removeAll($data);
127
128
            $addedEntities = [];
129
            $ignoredEntities = [];
130
131
            $entities = $strategy->getData($data);
132
133
            foreach ($entities as $object) {
134
                try {
135
                    $strategy->persist($object, $data);
136
                    $addedEntities[] = $object;
137
                } catch (EntityIgnoredException $e) {
138
                    $ignoredEntities[] = $e->getEntity();
139
                }
140
            }
141
142
            $repository->commit();
143
144
            return new ImportResult($addedEntities, [], [], $ignoredEntities, $data);
145
        } catch (Throwable $e) {
146
            throw new ImportException($e->getMessage(), $e->getCode(), $e);
147
        } finally {
148
            $this->updateImportDateTime($strategy->getEntityClassName());
149
        }
150
    }
151
152
    private function updateImportDateTime(string $className): void {
153
        $dateTime = $this->importDateTimeRepository->findOneByEntityClass($className);
154
155
        if($dateTime === null) {
156
            $dateTime = (new ImportDateTime())
157 8
                ->setEntityClass($className);
158 8
159
        }
160 8
161 8
        $dateTime->setUpdatedAt(new DateTime('now'));
162 8
163
        $this->importDateTimeRepository->persist($dateTime);
164
    }
165
}