DiffGenerator::generateDiffs()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 15
c 1
b 0
f 0
nc 4
nop 4
dl 0
loc 26
rs 9.7666
1
<?php
2
3
namespace Smart\EtlBundle\Generator;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Symfony\Component\PropertyAccess\PropertyAccess;
7
use Symfony\Component\PropertyAccess\PropertyAccessor;
8
9
/**
10
 * @author Mathieu Ducrot <[email protected]>
11
 *
12
 * The DiffGenerator class is responsible for comparing a raw data with data pulled from the manager on the entity and
13
 * generating a diff preview with the changes needed to migrate from one data to the other.
14
 */
15
class DiffGenerator
16
{
17
    /** @var EntityManagerInterface */
18
    protected $entityManager;
19
20
    /** @var PropertyAccessor */
21
    protected $accessor;
22
23
    public function __construct(EntityManagerInterface $entityManager)
24
    {
25
        $this->entityManager = $entityManager;
26
        $this->accessor = PropertyAccess::createPropertyAccessor();
27
    }
28
29
    /**
30
     * @param array $multiArrayData multidimensional array data containing one entity data per row
31
     * @TODO $identifierCallback can be remove once DiffGenerator will work with multiEntityData instead of Array
32
     */
33
    public function generateDiffs(string $entityClass, array $multiArrayData, string $identifier = null, $identifierCallback = null)
34
    {
35
        $toReturn = [];
36
        if ($multiArrayData === []) {
37
            return $toReturn;
38
        }
39
40
        $identifier = $identifier ?? array_keys($multiArrayData[0])[0];
41
        // todo enhance entity query by only getting the one that identier are matching from $multiArrayData
42
        $entitiesFromDb = $this->entityManager->getRepository($entityClass)
43
            ->createQueryBuilder('o', "o.$identifier")
44
            ->getQuery()
45
            ->getResult()
46
        ;
47
48
        foreach ($multiArrayData as $key => $row) {
49
            if ($identifierCallback === null) {
50
                $entityFromDb = $entitiesFromDb[reset($row)] ?? null;
51
            } else {
52
                $entityFromDb = $entitiesFromDb[$identifierCallback($row)] ?? null;
53
            }
54
55
            $toReturn[$key] = $this->generateDiff($entityFromDb, $row);
56
        }
57
58
        return $toReturn;
59
    }
60
61
    /**
62
     * @param mixed $entity
63
     */
64
    public function generateDiff($entity, array $data): array
65
    {
66
        $isNew = ($entity === null);
67
        $toReturn['diff_type'] = 'new';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$toReturn was never initialized. Although not strictly required by PHP, it is generally a good practice to add $toReturn = array(); before regardless.
Loading history...
68
69
        $hasDataChange = false;
70
        foreach ($data as $property => $value) {
71
            $toReturn['diff'][$property] = $value;
72
73
            if (!$isNew) {
74
                $toReturn['diff_type'] = 'change';
75
76
                $originValue = $this->accessor->getValue($entity, $property);
77
                $hasChange = ($originValue != $value);
78
                $toReturn['diff'][$property] = [
79
                    'value' => $value,
80
                    'origin_value' => $originValue,
81
                    'has_change' => $hasChange,
82
                ];
83
84
                if ($hasChange) {
85
                    $hasDataChange = true;
86
                }
87
            }
88
        }
89
90
        if (!$isNew && !$hasDataChange) {
91
            $toReturn['diff_type'] = 'unchanged';
92
        }
93
94
        return $toReturn;
95
    }
96
}
97