Completed
Push — master ( d4f264...e03b67 )
by
unknown
02:07 queued 10s
created

DoctrineInsertUpdateLoader::isEntityRelation()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Smart\EtlBundle\Loader;
4
5
use Doctrine\ORM\EntityManager;
6
use Smart\EtlBundle\Exception\Loader\EntityTypeNotHandledException;
7
use Smart\EtlBundle\Exception\Loader\EntityAlreadyRegisteredException;
8
use Symfony\Component\PropertyAccess\PropertyAccess;
9
use Symfony\Component\PropertyAccess\PropertyAccessor;
10
11
/**
12
 * Nicolas Bastien <[email protected]>
13
 */
14
class DoctrineInsertUpdateLoader implements LoaderInterface
15
{
16
    /**
17
     * @var EntityManager
18
     */
19
    protected $entityManager;
20
21
    /**
22
     * @var array
23
     */
24
    protected $references;
25
26
    /**
27
     * @var PropertyAccessor
28
     */
29
    protected $accessor;
30
31
    /**
32
     * List of entities to extract
33
     * [
34
     *      'class' => []
35
     * ]
36
     * @var array
37
     */
38
    protected $entitiesToProcess = [];
39
40 1
    public function __construct($entityManager)
41
    {
42 1
        $this->entityManager = $entityManager;
43 1
        $this->accessor = PropertyAccess::createPropertyAccessor();
44 1
    }
45
46
    /**
47
     * @param string $entityClass
48
     * @param function $identifierCallback
49
     * @param string $identifierProperty : if null this entity will be always insert
50
     * @param array $entityProperties properties to synchronize
51
     * @return $this
52
     */
53 1
    public function addEntityToProcess($entityClass, $identifierCallback, $identifierProperty, array $entityProperties = [])
54
    {
55 1
        if (isset($this->entitiesToProcess[$entityClass])) {
56
            throw new EntityAlreadyRegisteredException($entityClass);
57
        }
58
59 1
        $this->entitiesToProcess[$entityClass] = [
60 1
            'class' => $entityClass,
61 1
            'callback' => $identifierCallback,
62 1
            'identifier' => $identifierProperty,
63 1
            'properties' => $entityProperties
64
        ];
65
66 1
        return $this;
67
    }
68
69
    /**
70
     * @inheritDoc
71
     */
72 1
    public function load(array $data)
73
    {
74 1
        $this->entityManager->beginTransaction();
75
        try {
76 1
            foreach ($data as $object) {
77 1
                $this->processObject($object);
78
            }
79 1
            $this->entityManager->flush();
80 1
            $this->entityManager->commit();
81
        } catch (\Exception $e) {
82
            var_dump('EXCEPTION LOADER : ' . $e->getMessage());
0 ignored issues
show
Security Debugging Code introduced by
var_dump('EXCEPTION LOAD... ' . $e->getMessage()); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
83
            $this->entityManager->rollback();
84
        }
85 1
    }
86
87
    /**
88
     * @param  mixed $object
89
     * @return mixed
90
     * @throws \Exception
91
     * @throws \TypeError
92
     */
93 1
    protected function processObject($object)
94
    {
95 1
        if (!isset($this->entitiesToProcess[get_class($object)])) {
96
            throw new EntityTypeNotHandledException(get_class($object));
97
        }
98 1
        $identifier = $this->entitiesToProcess[get_class($object)]['callback']($object);
99
100
        //Replace relations by their reference
101 1
        foreach ($this->entitiesToProcess[get_class($object)]['properties'] as $property) {
102 1
            $propertyValue = $this->accessor->getValue($object, $property);
103 1
            if ($this->isEntityRelation($propertyValue)) {
104 1
                $relation = $propertyValue; //better understanding
105
106 1
                if (!isset($this->entitiesToProcess[get_class($relation)])) {
107
                    throw new EntityTypeNotHandledException(get_class($relation));
108
                }
109 1
                $relationIdentifier = $this->entitiesToProcess[get_class($relation)]['callback']($relation);
110 1
                if (!isset($this->references[$relationIdentifier])) {
111
                    //new relation should be processed before
112 1
                    $this->processObject($relation);
113
                }
114 1
                $this->accessor->setValue(
115 1
                    $object,
116 1
                    $property,
117 1
                    $this->references[$relationIdentifier]
118
                );
119
            }
120
        }
121
122 1
        $dbObject = null;
123 1
        if (!is_null($this->entitiesToProcess[get_class($object)]['identifier'])) {
124 1
            $dbObject = $this->entityManager->getRepository(get_class($object))->findOneBy([$this->entitiesToProcess[get_class($object)]['identifier'] => $identifier]);
125
        }
126 1
        if ($dbObject === null) {
127 1
            $this->entityManager->persist($object);
128 1
            if (!is_null($identifier)) {
129 1
                $this->references[$identifier] = $object;
130
            }
131
        } else {
132 1
            foreach ($this->entitiesToProcess[get_class($object)]['properties'] as $property) {
133 1
                $this->accessor->setValue($dbObject, $property, $this->accessor->getValue($object, $property));
134
            }
135 1
            $this->references[$identifier] = $dbObject;
136
        }
137
138 1
        return $object;
139
    }
140
141
    /**
142
     * Check if $propertyValue is an entity relation to process
143
     *
144
     * @param  mixed $propertyValue
145
     * @return bool
146
     */
147 1
    protected function isEntityRelation($propertyValue)
148
    {
149 1
        return (is_object($propertyValue) && !($propertyValue instanceof \DateTime));
150
    }
151
}
152