Completed
Push — master ( 2f0398...5c44ed )
by
unknown
13s
created

DoctrineInsertUpdateLoader::processObject()   C

Complexity

Conditions 17
Paths 99

Size

Total Lines 71
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 42
CRAP Score 17.0857

Importance

Changes 0
Metric Value
cc 17
eloc 45
nc 99
nop 1
dl 0
loc 71
ccs 42
cts 45
cp 0.9333
crap 17.0857
rs 5.2166
c 0
b 0
f 0

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 Smart\EtlBundle\Loader;
4
5
use Doctrine\ORM\EntityManager;
6
use Smart\EtlBundle\Entity\ImportableInterface;
7
use Smart\EtlBundle\Exception\Loader\EntityTypeNotHandledException;
8
use Smart\EtlBundle\Exception\Loader\EntityAlreadyRegisteredException;
9
use Symfony\Component\PropertyAccess\PropertyAccess;
10
use Symfony\Component\PropertyAccess\PropertyAccessor;
11
12
/**
13
 * Nicolas Bastien <[email protected]>
14
 */
15
class DoctrineInsertUpdateLoader implements LoaderInterface
16
{
17
    /**
18
     * @var EntityManager
19
     */
20
    protected $entityManager;
21
22
    /**
23
     * @var array
24
     */
25
    protected $references;
26
27
    /**
28
     * @var PropertyAccessor
29
     */
30
    protected $accessor;
31
32
    /**
33
     * List of entities to extract
34
     * [
35
     *      'class' => []
36
     * ]
37
     * @var array
38
     */
39
    protected $entitiesToProcess = [];
40
41 1
    public function __construct($entityManager)
42
    {
43 1
        $this->entityManager = $entityManager;
44 1
        $this->accessor = PropertyAccess::createPropertyAccessor();
45 1
    }
46
47
    /**
48
     * @param string $entityClass
49
     * @param function $identifierCallback
0 ignored issues
show
Bug introduced by
The type Smart\EtlBundle\Loader\function was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
50
     * @param string $identifierProperty : if null this entity will be always insert
51
     * @param array $entityProperties properties to synchronize
52
     * @return $this
53
     */
54 1
    public function addEntityToProcess($entityClass, $identifierCallback, $identifierProperty, array $entityProperties = [])
55
    {
56 1
        if (isset($this->entitiesToProcess[$entityClass])) {
57
            throw new EntityAlreadyRegisteredException($entityClass);
58
        }
59
60 1
        $this->entitiesToProcess[$entityClass] = [
61 1
            'class' => $entityClass,
62 1
            'callback' => $identifierCallback,
63 1
            'identifier' => $identifierProperty,
64 1
            'properties' => $entityProperties
65
        ];
66
67 1
        return $this;
68
    }
69
70
    /**
71
     * @inheritDoc
72
     */
73 1
    public function load(array $data)
74
    {
75 1
        $this->entityManager->beginTransaction();
76
        try {
77 1
            foreach ($data as $object) {
78 1
                $this->processObject($object);
79
            }
80 1
            $this->entityManager->flush();
81 1
            $this->entityManager->commit();
82
        } catch (\Exception $e) {
83
            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?
Loading history...
84
            $this->entityManager->rollback();
85
        }
86 1
    }
87
88
    /**
89
     * @param  ImportableInterface $object
90
     * @return ImportableInterface
91
     * @throws \Exception
92
     * @throws \TypeError
93
     */
94 1
    protected function processObject($object)
95
    {
96 1
        if (!isset($this->entitiesToProcess[get_class($object)])) {
97
            throw new EntityTypeNotHandledException(get_class($object));
98
        }
99 1
        $identifier = $this->entitiesToProcess[get_class($object)]['callback']($object);
100
101
        //Replace relations by their reference
102 1
        foreach ($this->entitiesToProcess[get_class($object)]['properties'] as $property) {
103 1
            $propertyValue = $this->accessor->getValue($object, $property);
104 1
            if ($this->isEntityRelation($propertyValue)) {
105 1
                $relation = $propertyValue; //better understanding
106
107 1
                if (!isset($this->entitiesToProcess[get_class($relation)])) {
108
                    throw new EntityTypeNotHandledException(get_class($relation));
109
                }
110 1
                $relationIdentifier = $this->entitiesToProcess[get_class($relation)]['callback']($relation);
111 1
                if (!isset($this->references[$relationIdentifier])) {
112
                    //new relation should be processed before
113 1
                    $this->processObject($relation);
114
                }
115 1
                $this->accessor->setValue(
116 1
                    $object,
117 1
                    $property,
118 1
                    $this->references[$relationIdentifier]
119
                );
120 1
            } elseif ($propertyValue instanceof \Traversable) {
121 1
                foreach ($propertyValue as $k => $v) {
122 1
                    if ($this->isEntityRelation($v)) {
123 1
                        if (!isset($this->entitiesToProcess[get_class($v)])) {
124
                            throw new EntityTypeNotHandledException(get_class($v));
125
                        }
126 1
                        $relationIdentifier = $this->entitiesToProcess[get_class($v)]['callback']($v);
127 1
                        if (!isset($this->references[$relationIdentifier])) {
128
                            //new relation should be processed before
129 1
                            $this->processObject($v);
130
                        }
131 1
                        $propertyValue[$k] = $this->references[$relationIdentifier];
132
                    }
133
                }
134 1
                $this->accessor->setValue(
135 1
                    $object,
136 1
                    $property,
137 1
                    $propertyValue
138
                );
139
            }
140
        }
141
142 1
        $dbObject = null;
143 1
        if (!is_null($this->entitiesToProcess[get_class($object)]['identifier'])) {
144 1
            $dbObject = $this->entityManager->getRepository(get_class($object))->findOneBy([$this->entitiesToProcess[get_class($object)]['identifier'] => $identifier]);
145
        }
146 1
        if ($dbObject === null) {
147 1
            if (!$object->isImported()) {
148 1
                $object->setImportedAt(new \DateTime());
149
            }
150 1
            $this->entityManager->persist($object);
151 1
            if (!is_null($identifier)) {
152 1
                $this->references[$identifier] = $object;
153
            }
154
        } else {
155 1
            foreach ($this->entitiesToProcess[get_class($object)]['properties'] as $property) {
156 1
                $this->accessor->setValue($dbObject, $property, $this->accessor->getValue($object, $property));
157
            }
158 1
            if (!$dbObject->isImported()) {
159 1
                $dbObject->setImportedAt(new \DateTime());
160
            }
161 1
            $this->references[$identifier] = $dbObject;
162
        }
163
164 1
        return $object;
165
    }
166
167
    /**
168
     * Check if $propertyValue is an entity relation to process
169
     *
170
     * @param  mixed $propertyValue
171
     * @return bool
172
     */
173 1
    protected function isEntityRelation($propertyValue)
174
    {
175 1
        return (is_object($propertyValue) && !($propertyValue instanceof \DateTime) && !($propertyValue instanceof \Traversable));
176
    }
177
}
178