Completed
Push — master ( f8936b...a397e0 )
by Dawid
02:47
created

EntityManager::hasRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
namespace Igni\Storage;
4
5
use Cache\Adapter\Apc\ApcCachePool;
6
use Cache\Adapter\Apcu\ApcuCachePool;
7
use Cache\Adapter\PHPArray\ArrayCachePool;
8
use Igni\Storage\Exception\HydratorException;
9
use Igni\Storage\Exception\RepositoryException;
10
use Igni\Storage\Hydration\HydratorAutoGenerate;
11
use Igni\Storage\Hydration\HydratorFactory;
12
use Igni\Storage\Hydration\ObjectHydrator;
13
use Igni\Storage\Mapping\IdentityMap;
14
use Igni\Storage\Mapping\MetaData\EntityMetaData;
15
use Igni\Storage\Mapping\MetaData\MetaDataFactory;
16
use Igni\Storage\Mapping\MetaData\Strategy\AnnotationMetaDataFactory;
17
use Psr\SimpleCache\CacheInterface;
18
19
class EntityManager implements IdentityMap, RepositoryContainer, MetaDataFactory
20
{
21
    /** @var Entity[] */
22
    private $registry = [];
23
24
    /** @var Repository[] */
25
    private $repositories = [];
26
27
    /** @var HydratorFactory */
28
    private $hydratorFactory;
29
30
    /** @var ObjectHydrator[] */
31
    private $hydrators = [];
32
33
    /** @var MetaDataFactory */
34
    private $metaDataFactory;
35
36
    /** @var string */
37
    private $hydratorDir;
38
39
    /** @var string */
40
    private $hydratorNamespace;
41
42
    /** @var CacheInterface */
43
    private $cache;
44
45
    /**
46
     * EntityManager constructor.
47
     * @param string|null $hydratorDir
48
     * @param string|null $hydratorNamespace
49
     * @param CacheInterface|null $cache
50
     * @param HydratorAutoGenerate|null $hydratorAutoGenerate
51
     * @param MetaDataFactory|null $metaDataFactory
52
     */
53 29
    public function __construct(
54
        string $hydratorDir = null,
55
        string $hydratorNamespace = null,
56
        CacheInterface $cache = null,
57
        HydratorAutoGenerate $hydratorAutoGenerate = null,
58
        MetaDataFactory $metaDataFactory = null
59
    ) {
60 29
        if ($hydratorDir === null) {
61 1
            $hydratorDir = sys_get_temp_dir();
62
        }
63
64 29
        if ($hydratorAutoGenerate === null) {
65 29
            $hydratorAutoGenerate = HydratorAutoGenerate::IF_NOT_EXISTS;
66
        }
67
68 29
        if (!is_writable($hydratorDir)) {
69
            throw new HydratorException("Hydrators cannot be generated, directory ($hydratorDir) is not writable.");
70
        }
71
72 29
        if ($metaDataFactory === null) {
73 29
            $metaDataFactory = new AnnotationMetaDataFactory();
74
        }
75
76 29
        if ($cache === null) {
77 29
            if (extension_loaded('apcu') && ini_get('apc.enabled')) {
78
                $cache = new ApcuCachePool();
79 29
            } elseif (extension_loaded('apc') && ini_get('apc.enabled')) {
80
                $cache = new ApcCachePool();
81
            } else {
82 29
                $cache = new ArrayCachePool();
83
            }
84
        }
85
86 29
        $this->cache = $cache;
87 29
        $this->hydratorDir = $hydratorDir;
88 29
        $this->metaDataFactory = $metaDataFactory;
89 29
        $this->hydratorNamespace = $hydratorNamespace ?? '';
90
91 29
        $this->hydratorFactory = new HydratorFactory($this, $hydratorAutoGenerate);
92 29
    }
93
94 2
    public function getHydratorDir(): string
95
    {
96 2
        return $this->hydratorDir;
97
    }
98
99 18
    public function getHydratorNamespace(): string
100
    {
101 18
        return $this->hydratorNamespace;
102
    }
103
104
    /**
105
     * Creates new entity in the storage.
106
     *
107
     * @param Entity $entity
108
     * @return Entity
109
     */
110 2
    public function create(Entity $entity): Entity
111
    {
112 2
        $this->getRepository(get_class($entity))->create($entity);
113 2
        $this->attach($entity);
114
115 2
        return $entity;
116
    }
117
118
    /**
119
     * Updated entity in the storage.
120
     *
121
     * @param Entity $entity
122
     * @return Entity
123
     */
124 1
    public function update(Entity $entity): Entity
125
    {
126 1
        $this->getRepository(get_class($entity))->update($entity);
127
128 1
        return $entity;
129
    }
130
131
    /**
132
     * Removes entity from the storage.
133
     *
134
     * @param Entity $entity
135
     * @return Entity
136
     */
137 2
    public function remove(Entity $entity): Entity
138
    {
139 2
        $this->getRepository(get_class($entity))->remove($entity);
140 2
        $this->detach($entity);
141
142 2
        return $entity;
143
    }
144
145
    /**
146
     * Retrieves entity by identifier from the storage.
147
     *
148
     * @param string $entity
149
     * @param $id
150
     * @return Entity
151
     */
152 11
    public function get(string $entity, $id): Entity
153
    {
154 11
        $key = $this->getId($entity, $id);
155
156 11
        if ($this->has($entity, $id)) {
157 3
            return $this->registry[$key];
158
        }
159
160 11
        return $this->getRepository($entity)->get($id);
161
    }
162
163 13
    public function getRepository(string $entity): Repository
164
    {
165 13
        if ($this->hasRepository($entity)) {
166 13
            return $this->repositories[$entity];
167
        }
168
169
        throw RepositoryException::forNotRegisteredRepository($entity);
170
    }
171
172 13
    public function hasRepository(string $entity): bool
173
    {
174 13
        return isset($this->repositories[$entity]);
175
    }
176
177 18
    public function addRepository(string $entity, Repository $repository): void
178
    {
179 18
        $this->repositories[$entity] = $repository;
180 18
    }
181
182 11
    public function attach(Entity $entity): Entity
183
    {
184 11
        $key = $this->getId($entity);
185
186 11
        if (!isset($this->registry[$key])) {
187 11
            $this->registry[$key] = $entity;
188
        }
189
190 11
        return $this->registry[$key];
191
    }
192
193 2
    public function detach(Entity $entity): Entity
194
    {
195 2
        $key = $this->getId($entity);
196 2
        if (isset($this->registry[$key])) {
197 2
            unset($this->registry[$key]);
198
        }
199
200 2
        return $entity;
201
    }
202
203
    /**
204
     *
205
     * @param string $class
206
     * @param $id
207
     * @return bool
208
     */
209 13
    public function has(string $class, $id): bool
210
    {
211 13
        $key = $this->getId($class, $id);
212 13
        return isset($this->registry[$key]);
213
    }
214
215
    /**
216
     * Checks if entity lives in the identity map.
217
     *
218
     * @param Entity $entity
219
     * @return bool
220
     */
221 2
    public function contains(Entity $entity): bool
222
    {
223 2
        return in_array($entity, $this->registry, true);
224
    }
225
226
    /**
227
     * Clears identity map.
228
     */
229 1
    public function clear(): void
230
    {
231 1
        $this->registry = [];
232 1
    }
233
234
    /**
235
     * Gets global id for entity which is used for
236
     * later storage in the identity map.
237
     *
238
     * @param $entity
239
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
240
     * @return string
241
     */
242 13
    private function getId($entity, $id = null): string
243
    {
244 13
        if ($entity instanceof Entity) {
245 11
            return get_class($entity) . '@' . $entity->getId()->getValue();
246
        }
247
248
        return "${entity}@${id}";
249
    }
250
251
    /**
252
     * Creates instance of the entity class and hydrates it with passed data.
253
     *
254
     * @param string $entityClass
255
     * @param array $data
256
     * @return object
257
     */
258
    public function hydrate(string $entityClass, array $data)
259
    {
260 2
        $hydrator = $this->getHydrator($entityClass);
261
262 2
        return $hydrator->hydrate($data);
263
    }
264
265
    /**
266
     * Extracts data from passed entity and returns it.
267
     *
268
     * @param $entity
269
     * @return array
270
     */
271
    public function extract($entity): array
272
    {
273 1
        $entityClass = get_class($entity);
274
275 1
        $hydrator = $this->getHydrator($entityClass);
276
277 1
        return $hydrator->extract($entity);
278
    }
279
280
    /**
281
     * Returns hydrator for the given entity.
282
     *
283
     * @param string $entity
284
     * @return ObjectHydrator
285
     */
286
    public function getHydrator(string $entity): ObjectHydrator
287
    {
288 18
        if (!isset($this->hydrators[$entity])) {
289 18
            $this->hydrators[$entity] = $this->hydratorFactory->get($entity);
290
        }
291
292 18
        return $this->hydrators[$entity];
293
    }
294
295
    /**
296
     * Returns entity's mapping metadata information.
297
     *
298
     * @param string|class $entity
0 ignored issues
show
Bug introduced by
The type Igni\Storage\class 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...
299
     * @return EntityMetaData
300
     */
301
    public function getMetaData(string $entity): EntityMetaData
302
    {
303 18
        $key = str_replace('\\', '.', $entity) . '.metadata';
304
305 18
        if (!$this->cache->has($key)) {
306 18
            $metaData = $this->metaDataFactory->getMetaData($entity);
307 18
            $this->cache->set($key, $metaData);
308
        }
309
310 18
        return $this->cache->get($key);
311
    }
312
}
313