Passed
Pull Request — master (#36)
by Louis
02:58
created

EntityDiffGenerator   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 43
c 1
b 0
f 0
dl 0
loc 80
rs 10
wmc 12

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A generateDiffs() 0 29 5
A generateDiff() 0 32 6
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 Louis Fortunier <[email protected]>
11
 *
12
 * The EntityDiffGenerator class is responsible for comparing entities and
13
 * generating a diff preview with the changes needed to migrate from one data to the other.
14
 */
15
class EntityDiffGenerator
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
    public function generateDiffs(string $entityClass, array $entities, array $properties, string $identifier = null): array
30
    {
31
        $toReturn = [];
32
        if ($entities === []) {
33
            return $toReturn;
34
        }
35
        $identifier = $identifier != null ? $identifier : $properties[0];
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $identifier of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
36
        $identifiers = array_map(function ($entity) use ($identifier) {
37
            return $this->accessor->getValue($entity, $identifier);
38
        }, $entities);
39
40
        $entitiesFromDb = $this->entityManager->getRepository($entityClass)
41
            ->createQueryBuilder('o', "o.$identifier")
42
            ->where("o.$identifier IN (:identifiers)")
43
            ->setParameter('identifiers', $identifiers)
44
            ->getQuery()
45
            ->getResult();
46
47
        foreach ($entities as $key => $entity) {
48
            $entityFromDb = null;
49
50
            if (isset($entitiesFromDb[$this->accessor->getValue($entity, $identifier)])) {
51
                $entityFromDb = $entitiesFromDb[$this->accessor->getValue($entity, $identifier)];
52
            }
53
54
            $toReturn[$key] = $this->generateDiff($entity, $entityFromDb, $properties);
55
        }
56
57
        return $toReturn;
58
    }
59
60
    /**
61
     * @param mixed $entity
62
     */
63
    public function generateDiff($entity, $entityFromDb, array $properties): array
64
    {
65
        $isNew = ($entityFromDb === null);
66
        $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...
67
68
        $hasDataChange = false;
69
        foreach ($properties as $property) {
70
            $value = $this->accessor->getValue($entity, $property);
71
            $toReturn['diff'][$property] = $value;
72
73
            if (!$isNew) {
74
                $toReturn['diff_type'] = 'change';
75
76
                $originValue = $this->accessor->getValue($entityFromDb, $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