Passed
Push — 0.4 ( 487c21 )
by jean
05:10
created

EntityResolver::resolve()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
nc 8
nop 3
dl 0
loc 20
ccs 11
cts 11
cp 1
crap 5
rs 9.2888
c 0
b 0
f 0
1
<?php
2
3
namespace Darkilliant\ImportBundle\Resolver;
4
5
use Doctrine\Common\Persistence\ManagerRegistry;
6
use Doctrine\ORM\EntityManager;
7
8
class EntityResolver
9
{
10
    /** @var array */
11
    private $config;
12
13
    /** @var ManagerRegistry */
14
    private $registry;
15
16
    private $cache = [];
17
18
    /**
19
     * @var array
20
     */
21
    private $cacheable;
22
23 4
    public function __construct(ManagerRegistry $registry, array $config, array $cacheable)
24
    {
25 4
        $this->registry = $registry;
26 4
        $this->config = $config;
27 4
        $this->cacheable = $cacheable;
28 4
    }
29
30 3
    public function resolve($class, array $data, array $config = null)
31
    {
32 3
        if (null === $config) {
33 3
            $config = $this->config[$class] ?? [];
34
        }
35
36 3
        $where = $this->buildWhere($config, $data);
37 3
        if (empty($where)) {
38 1
            return null;
39
        }
40
41 2
        if (!$this->isCacheable($class)) {
42 1
            return $this->fetchFromRepository($class, $where);
43
        }
44
45 1
        if (!$this->isCacheBuilded($class)) {
46 1
            $this->cache[$class] = $this->buildCache($class, $where);
47
        }
48
49 1
        return $this->fetchFromCache($class, $where);
50
    }
51
52 2
    public function clear($class = null)
53
    {
54 2
        if (null === $class) {
55 1
            $this->cache = [];
56
57 1
            return;
58
        }
59
60 2
        if (isset($this->cache[$class])) {
61 1
            $this->cache[$class] = [];
62
63 1
            return;
64
        }
65
66 1
        return;
67
    }
68
69 1
    private function fetchFromCache(string $class, array $where)
70
    {
71 1
        $searchCompostiteKey = implode('_', array_values($where));
72
73 1
        $entityId = $this->cache[$class][$searchCompostiteKey] ?? null;
74
75
        /** @var EntityManager $objectManager */
76 1
        $objectManager = $this->registry->getManagerForClass($class);
77
78 1
        if (null !== $entityId) {
79
            $entity = $objectManager
80 1
                ->getUnitOfWork()
81 1
                ->createEntity($class, ['id' => $entityId]);
82
            $objectManager
83 1
                ->getUnitOfWork()
84 1
                ->setOriginalEntityData(
85 1
                    $entity,
86 1
                    $this->getFakeOriginalData($objectManager, $entity)
87
                );
88
89 1
            return $entity;
90
        }
91
92 1
        return null;
93
    }
94
95 3
    private function buildWhere(array $config, array $data): array
96
    {
97 3
        $where = [];
98 3
        foreach ($config as $key => $fieldName) {
99 3
            $dataFieldName = (is_integer($key)) ? $fieldName : $key;
100 3
            if (!empty($data[$dataFieldName])) {
101 3
                $where[$fieldName] = $data[$dataFieldName];
102
            }
103
        }
104
105 3
        return $where;
106
    }
107
108 2
    private function isCacheable($class)
109
    {
110 2
        return $this->cacheable[$class] ?? false;
111
    }
112
113 1
    private function isCacheBuilded($class)
114
    {
115 1
        return isset($this->cache[$class]);
116
    }
117
118 1
    private function buildCache($class, $where): array
119
    {
120
        /** @var EntityManager $objectManager */
121 1
        $objectManager = $this->registry->getManagerForClass($class);
122
123 1
        $selectFields = [];
124 1
        foreach ($where as $fieldName => $fieldValue) {
125 1
            $selectFields[] = sprintf('o.%s', $fieldName);
126
        }
127
128 1
        $qb = $objectManager->createQueryBuilder()
129 1
            ->select('o.id, '.implode(', ', $selectFields))
130 1
            ->from($class, 'o')
131 1
            ->indexBy('o', 'o.id');
132
133 1
        $result = $qb->getQuery()->getArrayResult();
134
135 1
        $cache = [];
136 1
        foreach ($result as $resultItem) {
137 1
            $compositeValues = $resultItem;
138 1
            if (!isset($where['id'])) {
139 1
                unset($compositeValues['id']);
140
            }
141 1
            $compositeKey = implode('_', array_values($compositeValues));
142
143 1
            $cache[$compositeKey] = $resultItem['id'];
144
        }
145
146 1
        return $cache;
147
    }
148
149 1
    private function fetchFromRepository($class, $where)
150
    {
151 1
        $objectManager = $this->registry->getManagerForClass($class);
152
153 1
        return $objectManager->getRepository($class)->findOneBy($where);
154
    }
155
156 1
    private function getFakeOriginalData(EntityManager $em, $entity)
157
    {
158 1
        $class = $em->getClassMetadata(get_class($entity));
159
160 1
        $field = [];
161
162 1
        foreach ($class->reflFields as $name => $refProp) {
163 1
            $field[$name] = null;
164
        }
165
166 1
        return $field;
167
    }
168
}
169