Failed Conditions
Pull Request — 0.3 (#20)
by jean
12:27
created

EntityResolver::fetchFromCache()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 24
ccs 12
cts 12
cp 1
crap 2
rs 9.536
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
    public function getClassInCache()
70
    {
71 1
        return array_keys($this->cache);
72
    }
73 1
74
    private function fetchFromCache(string $class, array $where)
75
    {
76 1
        $searchCompostiteKey = implode('_', array_values($where));
77
78 1
        $entityId = $this->cache[$class][$searchCompostiteKey] ?? null;
79
80 1
        /** @var EntityManager $objectManager */
81 1
        $objectManager = $this->registry->getManagerForClass($class);
82
83 1
        if (null !== $entityId) {
84 1
            $entity = $objectManager
85 1
                ->getUnitOfWork()
86 1
                ->createEntity($class, ['id' => $entityId]);
87
            $objectManager
88
                ->getUnitOfWork()
89 1
                ->setOriginalEntityData(
90
                    $entity,
91
                    $this->getFakeOriginalData($objectManager, $entity)
92 1
                );
93
94
            return $entity;
95 3
        }
96
97 3
        return null;
98 3
    }
99 3
100 3
    private function buildWhere(array $config, array $data): array
101 3
    {
102
        $where = [];
103
        foreach ($config as $key => $fieldName) {
104
            $dataFieldName = (is_integer($key)) ? $fieldName : $key;
105 3
            if (!empty($data[$dataFieldName])) {
106
                $where[$fieldName] = $data[$dataFieldName];
107
            }
108 2
        }
109
110 2
        return $where;
111
    }
112
113 1
    private function isCacheable($class)
114
    {
115 1
        return $this->cacheable[$class] ?? false;
116
    }
117
118 1
    private function isCacheBuilded($class)
119
    {
120
        return isset($this->cache[$class]);
121 1
    }
122
123 1
    private function buildCache($class, $where): array
124 1
    {
125 1
        /** @var EntityManager $objectManager */
126
        $objectManager = $this->registry->getManagerForClass($class);
127
128 1
        $selectFields = [];
129 1
        foreach ($where as $fieldName => $fieldValue) {
130 1
            $selectFields[] = sprintf('o.%s', $fieldName);
131 1
        }
132
133 1
        $qb = $objectManager->createQueryBuilder()
134
            ->select('o.id, '.implode(', ', $selectFields))
135 1
            ->from($class, 'o')
136 1
            ->indexBy('o', 'o.id');
137 1
138 1
        $result = $qb->getQuery()->getArrayResult();
139 1
140
        $cache = [];
141 1
        foreach ($result as $resultItem) {
142
            $compositeValues = $resultItem;
143 1
            if (!isset($where['id'])) {
144
                unset($compositeValues['id']);
145
            }
146 1
            $compositeKey = implode('_', array_values($compositeValues));
147
148
            $cache[$compositeKey] = $resultItem['id'];
149 1
        }
150
151 1
        return $cache;
152
    }
153 1
154
    private function fetchFromRepository($class, $where)
155
    {
156 1
        $objectManager = $this->registry->getManagerForClass($class);
157
158 1
        return $objectManager->getRepository($class)->findOneBy($where);
159
    }
160 1
161
    private function getFakeOriginalData(EntityManager $em, $entity)
162 1
    {
163 1
        $class = $em->getClassMetadata(get_class($entity));
164
165
        $field = [];
166 1
167
        foreach ($class->reflFields as $name => $refProp) {
168
            $field[$name] = null;
169
        }
170
171
        return $field;
172
    }
173
}
174