Completed
Pull Request — 0.3 (#19)
by jean
03:36
created

EntityResolver::fetchFromRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
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 3
    public function __construct(ManagerRegistry $registry, array $config, array $cacheable)
24
    {
25 3
        $this->registry = $registry;
26 3
        $this->config = $config;
27 3
        $this->cacheable = $cacheable;
28 3
    }
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 1
    private function fetchFromCache(string $class, array $where)
53
    {
54 1
        $searchCompostiteKey = implode('_', array_values($where));
55
56 1
        $entityId = $this->cache[$class][$searchCompostiteKey] ?? null;
57
58
        /** @var EntityManager $objectManager */
59 1
        $objectManager = $this->registry->getManagerForClass($class);
60
61 1
        if (null !== $entityId) {
62
            $entity = $objectManager
63 1
                ->getUnitOfWork()
64 1
                ->createEntity($class, ['id' => $entityId]);
65
            $objectManager
66 1
                ->getUnitOfWork()
67 1
                ->setOriginalEntityData(
68 1
                    $entity,
69 1
                    $this->getFakeOriginalData($objectManager, $entity)
70
                );
71
72 1
            return $entity;
73
        }
74
75 1
        return null;
76
    }
77
78 3
    private function buildWhere(array $config, array $data): array
79
    {
80 3
        $where = [];
81 3
        foreach ($config as $key => $fieldName) {
82 3
            $dataFieldName = (is_integer($key)) ? $fieldName : $key;
83 3
            if (!empty($data[$dataFieldName])) {
84 3
                $where[$fieldName] = $data[$dataFieldName];
85
            }
86
        }
87
88 3
        return $where;
89
    }
90
91 2
    private function isCacheable($class)
92
    {
93 2
        return $this->cacheable[$class] ?? false;
94
    }
95
96 1
    private function isCacheBuilded($class)
97
    {
98 1
        return isset($this->cache[$class]);
99
    }
100
101 1
    private function buildCache($class, $where): array
102
    {
103
        /** @var EntityManager $objectManager */
104 1
        $objectManager = $this->registry->getManagerForClass($class);
105
106 1
        $selectFields = [];
107 1
        foreach ($where as $fieldName => $fieldValue) {
108 1
            $selectFields[] = sprintf('o.%s', $fieldName);
109
        }
110
111 1
        $qb = $objectManager->createQueryBuilder()
112 1
            ->select('o.id, '.implode(', ', $selectFields))
113 1
            ->from($class, 'o')
114 1
            ->indexBy('o', 'o.id');
115
116 1
        $result = $qb->getQuery()->getArrayResult();
117
118 1
        $cache = [];
119 1
        foreach ($result as $resultItem) {
120 1
            $compositeValues = $resultItem;
121 1
            if (!isset($where['id'])) {
122 1
                unset($compositeValues['id']);
123
            }
124 1
            $compositeKey = implode('_', array_values($compositeValues));
125
126 1
            $cache[$compositeKey] = $resultItem['id'];
127
        }
128
129 1
        return $cache;
130
    }
131
132 1
    private function fetchFromRepository($class, $where)
133
    {
134 1
        $objectManager = $this->registry->getManagerForClass($class);
135
136 1
        return $objectManager->getRepository($class)->findOneBy($where);
137
    }
138
139 1
    private function getFakeOriginalData(EntityManager $em, $entity)
140
    {
141 1
        $class = $em->getClassMetadata(get_class($entity));
142
143 1
        $field = [];
144
145 1
        foreach ($class->reflFields as $name => $refProp) {
146 1
            $field[$name] = null;
147
        }
148
149 1
        return $field;
150
    }
151
}
152