1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Bankiru\Api\Doctrine; |
4
|
|
|
|
5
|
|
|
use Bankiru\Api\Doctrine\Exception\MappingException; |
6
|
|
|
use Bankiru\Api\Doctrine\Mapping\ApiMetadata; |
7
|
|
|
use Bankiru\Api\Doctrine\Mapping\EntityMetadata; |
8
|
|
|
use Bankiru\Api\Doctrine\Proxy\ProxyFactory; |
9
|
|
|
use Doctrine\Common\Persistence\ObjectRepository; |
10
|
|
|
|
11
|
|
|
class EntityManager implements ApiEntityManager |
12
|
|
|
{ |
13
|
|
|
/** @var EntityMetadataFactory */ |
14
|
|
|
private $metadataFactory; |
15
|
|
|
/** @var Configuration */ |
16
|
|
|
private $configuration; |
17
|
|
|
/** @var ObjectRepository[] */ |
18
|
|
|
private $repositories = []; |
19
|
|
|
/** @var UnitOfWork */ |
20
|
|
|
private $unitOfWork; |
21
|
|
|
/** @var ProxyFactory */ |
22
|
|
|
private $proxyFactory; |
23
|
|
|
/** @var ApiEntityCache */ |
24
|
|
|
private $entityCache; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* EntityManager constructor. |
28
|
|
|
* |
29
|
|
|
* @param Configuration $configuration |
30
|
|
|
*/ |
31
|
14 |
|
public function __construct(Configuration $configuration) |
32
|
|
|
{ |
33
|
14 |
|
$this->configuration = $configuration; |
34
|
|
|
|
35
|
14 |
|
$this->metadataFactory = $configuration->getMetadataFactory(); |
36
|
14 |
|
$this->metadataFactory->setEntityManager($this); |
37
|
|
|
|
38
|
14 |
|
$this->unitOfWork = new UnitOfWork($this); |
39
|
14 |
|
$this->proxyFactory = new ProxyFactory($this); |
40
|
|
|
|
41
|
14 |
|
if (null !== ($cache = $this->configuration->getApiCache())) { |
42
|
1 |
|
$this->entityCache = new ApiEntityCache( |
43
|
1 |
|
$this, |
44
|
1 |
|
$cache, |
45
|
1 |
|
$this->configuration->getApiCacheLogger() |
46
|
1 |
|
); |
47
|
1 |
|
} |
48
|
14 |
|
} |
49
|
|
|
|
50
|
|
|
/** {@inheritdoc} */ |
51
|
14 |
|
public function getConfiguration() |
52
|
|
|
{ |
53
|
14 |
|
return $this->configuration; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** {@inheritdoc} */ |
57
|
11 |
|
public function getEntityCache() |
58
|
|
|
{ |
59
|
11 |
|
return $this->entityCache; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** {@inheritdoc} */ |
63
|
10 |
|
public function find($className, $id) |
64
|
|
|
{ |
65
|
10 |
|
$id = $this->fixScalarId($id, $className); |
66
|
|
|
|
67
|
|
|
/** @var EntityMetadata $metadata */ |
68
|
10 |
|
$metadata = $this->getClassMetadata($className); |
69
|
10 |
View Code Duplication |
if (false !== ($entity = $this->getUnitOfWork()->tryGetById($id, $metadata->rootEntityName))) { |
|
|
|
|
70
|
|
|
return $entity instanceof $metadata->name ? $entity : null; |
71
|
1 |
|
} |
72
|
|
|
|
73
|
10 |
|
return $this->getUnitOfWork()->getEntityPersister($className)->loadById($id); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param array|mixed $id |
78
|
|
|
* |
79
|
|
|
* @return array |
80
|
|
|
* @throws MappingException |
81
|
|
|
*/ |
82
|
11 |
View Code Duplication |
private function fixScalarId($id, $className) |
|
|
|
|
83
|
|
|
{ |
84
|
11 |
|
if (is_array($id)) { |
85
|
5 |
|
return $id; |
86
|
|
|
} |
87
|
|
|
|
88
|
10 |
|
$id = (array)$id; |
89
|
|
|
|
90
|
10 |
|
$identifiers = $this->getClassMetadata($className)->getIdentifierFieldNames(); |
91
|
10 |
|
if (count($id) !== count($identifiers)) { |
92
|
|
|
throw MappingException::invalidIdentifierStructure(); |
93
|
|
|
} |
94
|
|
|
|
95
|
10 |
|
return array_combine($identifiers, (array)$id); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* {@inheritdoc} |
100
|
|
|
* @return ApiMetadata |
101
|
|
|
*/ |
102
|
14 |
|
public function getClassMetadata($className) |
103
|
|
|
{ |
104
|
14 |
|
return $this->getMetadataFactory()->getMetadataFor($className); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** {@inheritdoc} */ |
108
|
14 |
|
public function getMetadataFactory() |
109
|
|
|
{ |
110
|
14 |
|
return $this->metadataFactory; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** {@inheritdoc} */ |
114
|
14 |
|
public function getUnitOfWork() |
115
|
|
|
{ |
116
|
14 |
|
return $this->unitOfWork; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** {@inheritdoc} */ |
120
|
|
|
public function persist($object) |
121
|
|
|
{ |
122
|
|
|
throw new \BadMethodCallException('Persisting object is not supported'); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** {@inheritdoc} */ |
126
|
|
|
public function remove($object) |
127
|
|
|
{ |
128
|
|
|
//Todo: support object deletion via API (@scaytrase) |
129
|
|
|
throw new \BadMethodCallException('Removing object is not supported'); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** {@inheritdoc} */ |
133
|
|
|
public function merge($object) |
134
|
|
|
{ |
135
|
|
|
throw new \BadMethodCallException('Merge is not supported'); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** {@inheritdoc} */ |
139
|
|
|
public function clear($objectName = null) |
140
|
|
|
{ |
141
|
|
|
throw new \BadMethodCallException('Clearing EM is not supported'); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** {@inheritdoc} */ |
145
|
|
|
public function detach($object) |
146
|
|
|
{ |
147
|
|
|
throw new \BadMethodCallException('Detach object is not supported'); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** {@inheritdoc} */ |
151
|
|
|
public function refresh($object) |
152
|
|
|
{ |
153
|
|
|
$this->getRepository(get_class($object))->find($object->getId()); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** {@inheritdoc} */ |
157
|
13 |
|
public function getRepository($className) |
158
|
|
|
{ |
159
|
13 |
|
if (!array_key_exists($className, $this->repositories)) { |
160
|
|
|
/** @var ApiMetadata $metadata */ |
161
|
13 |
|
$metadata = $this->getClassMetadata($className); |
162
|
13 |
|
$repositoryClass = $metadata->getRepositoryClass(); |
163
|
|
|
/** @noinspection PhpInternalEntityUsedInspection */ |
164
|
13 |
|
$this->repositories[$className] = new $repositoryClass($this, $className); |
165
|
13 |
|
} |
166
|
|
|
|
167
|
13 |
|
return $this->repositories[$className]; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** {@inheritdoc} */ |
171
|
|
|
public function flush() |
172
|
|
|
{ |
173
|
|
|
throw new \BadMethodCallException('Flush is not supported'); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** {@inheritdoc} */ |
177
|
|
|
public function initializeObject($obj) |
178
|
|
|
{ |
179
|
|
|
// Todo: generate proxy class here (@scaytrase) |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** {@inheritdoc} */ |
183
|
|
|
public function contains($object) |
184
|
|
|
{ |
185
|
|
|
return false; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* Gets a reference to the entity identified by the given type and identifier |
190
|
|
|
* without actually loading it, if the entity is not yet loaded. |
191
|
|
|
* |
192
|
|
|
* @param string $entityName The name of the entity type. |
193
|
|
|
* @param mixed $id The entity identifier. |
194
|
|
|
* |
195
|
|
|
* @return object The entity reference. |
196
|
|
|
*/ |
197
|
6 |
|
public function getReference($entityName, $id) |
198
|
|
|
{ |
199
|
6 |
|
$id = $this->fixScalarId($id, $entityName); |
200
|
|
|
|
201
|
|
|
/** @var EntityMetadata $metadata */ |
202
|
5 |
|
$metadata = $this->getClassMetadata($entityName); |
203
|
5 |
View Code Duplication |
if (false !== ($entity = $this->getUnitOfWork()->tryGetById($id, $metadata->rootEntityName))) { |
|
|
|
|
204
|
4 |
|
return $entity instanceof $metadata->name ? $entity : null; |
205
|
|
|
} |
206
|
|
|
|
207
|
3 |
|
$proxy = $this->getProxyFactory()->getProxy($entityName, $id); |
208
|
3 |
|
$this->getUnitOfWork()->registerManaged($proxy, $id, null); |
209
|
|
|
|
210
|
3 |
|
return $proxy; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** {@inheritdoc} */ |
214
|
3 |
|
public function getProxyFactory() |
215
|
|
|
{ |
216
|
3 |
|
return $this->proxyFactory; |
217
|
|
|
} |
218
|
|
|
} |
219
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.