1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace DoctrineElastic; |
4
|
|
|
|
5
|
|
|
use Doctrine\Common\Annotations\AnnotationReader; |
6
|
|
|
use Doctrine\Common\EventManager; |
7
|
|
|
use Doctrine\ORM\Configuration; |
8
|
|
|
use Doctrine\ORM\EntityManagerInterface; |
9
|
|
|
use Doctrine\ORM\Mapping\ClassMetadata; |
10
|
|
|
use Doctrine\ORM\Query\Expr; |
11
|
|
|
use Doctrine\ORM\Query\ResultSetMapping; |
12
|
|
|
use DoctrineElastic\Connection\ElasticConnection; |
13
|
|
|
use DoctrineElastic\Elastic\DoctrineElasticEvents; |
14
|
|
|
use DoctrineElastic\Elastic\ElasticQuery; |
15
|
|
|
use DoctrineElastic\Elastic\ElasticQueryBuilder; |
16
|
|
|
use DoctrineElastic\Listener\DeleteListener; |
17
|
|
|
use DoctrineElastic\Listener\InsertListener; |
18
|
|
|
use DoctrineElastic\Listener\QueryListener; |
19
|
|
|
use DoctrineElastic\Listener\UpdateListener; |
20
|
|
|
use DoctrineElastic\Mapping\Driver\ElasticAnnotationDriver; |
21
|
|
|
use DoctrineElastic\Repository\ElasticRepositoryManager; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* ElasticEntityManager - leading class for all |
25
|
|
|
* |
26
|
|
|
* @author Andsalves <[email protected]> |
27
|
|
|
*/ |
28
|
|
|
class ElasticEntityManager implements EntityManagerInterface { |
29
|
|
|
|
30
|
|
|
/** @var ElasticRepositoryManager */ |
31
|
|
|
protected $repositoryManager; |
32
|
|
|
|
33
|
|
|
/** @var Configuration */ |
34
|
|
|
protected $config; |
35
|
|
|
|
36
|
|
|
/** @var EventManager */ |
37
|
|
|
protected $eventManager; |
38
|
|
|
|
39
|
|
|
/** @var ElasticUnitOfWork */ |
40
|
|
|
protected $unitOfWork; |
41
|
|
|
|
42
|
|
|
/** @var Expr */ |
43
|
|
|
protected $expressionBuilder; |
44
|
|
|
|
45
|
|
|
/** @var ElasticConnection */ |
46
|
|
|
protected $conn; |
47
|
|
|
|
48
|
|
|
/** @var ElasticAnnotationDriver */ |
49
|
|
|
private $annotationDriver; |
50
|
|
|
|
51
|
|
|
public function __construct(ElasticConnection $connection, EventManager $eventManager = null) { |
52
|
|
|
$this->eventManager = $eventManager; |
53
|
|
|
$this->conn = $connection; |
54
|
|
|
|
55
|
|
|
$this->repositoryManager = new ElasticRepositoryManager(); |
56
|
|
|
$this->unitOfWork = new ElasticUnitOfWork($this); |
57
|
|
|
$this->registerEventsListeners(); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
private function registerEventsListeners() { |
61
|
|
|
$this->getEventManager()->addEventListener(array( |
62
|
|
|
DoctrineElasticEvents::beforeInsert, |
63
|
|
|
DoctrineElasticEvents::postInsert, |
64
|
|
|
), new InsertListener()); |
65
|
|
|
|
66
|
|
|
$this->getEventManager()->addEventListener(array( |
67
|
|
|
DoctrineElasticEvents::beforeDelete, |
68
|
|
|
DoctrineElasticEvents::postDelete, |
69
|
|
|
), new DeleteListener()); |
70
|
|
|
|
71
|
|
|
$this->getEventManager()->addEventListener(array( |
72
|
|
|
DoctrineElasticEvents::beforeDelete, |
73
|
|
|
DoctrineElasticEvents::postDelete, |
74
|
|
|
), new UpdateListener()); |
75
|
|
|
|
76
|
|
|
$this->getEventManager()->addEventListener(array( |
77
|
|
|
DoctrineElasticEvents::beforeQuery, |
78
|
|
|
DoctrineElasticEvents::postQuery, |
79
|
|
|
), new QueryListener()); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @return ElasticUnitOfWork |
84
|
|
|
*/ |
85
|
|
|
public function getUnitOfWork() { |
86
|
|
|
return $this->unitOfWork; |
|
|
|
|
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
public function getRepository($className) { |
90
|
|
|
return $this->repositoryManager->getRepository($this, $className); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
public function getReference($entityName, $id) { |
94
|
|
|
if (!is_array($id)) { |
95
|
|
|
$criteria = ['_id' => $id]; |
96
|
|
|
} else { |
97
|
|
|
$criteria = $id; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$persister = $this->getUnitOfWork()->getEntityPersister($entityName); |
101
|
|
|
|
102
|
|
|
return $persister->load($criteria); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
public function find($entityName, $id, $lockMode = null, $lockVersion = null) { |
106
|
|
|
return $this->getReference($entityName, $id); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
public function getCache() { |
110
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* @return ElasticConnection |
115
|
|
|
*/ |
116
|
|
|
public function getConnection() { |
117
|
|
|
return $this->conn; |
|
|
|
|
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
public function getExpressionBuilder() { |
121
|
|
|
if ($this->expressionBuilder === null) { |
122
|
|
|
$this->expressionBuilder = new Expr(); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
return $this->expressionBuilder; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
public function beginTransaction() { |
129
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
public function transactional($func) { |
133
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
public function commit() { |
137
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
public function rollback() { |
141
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
public function createQuery($dql = '') { |
145
|
|
|
$query = new ElasticQuery($this); |
146
|
|
|
|
147
|
|
|
if (!empty($dql)) { |
148
|
|
|
$query->setDQL($dql); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
return $query; |
|
|
|
|
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
public function createNamedQuery($name) { |
155
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public function createNativeQuery($sql, ResultSetMapping $rsm) { |
159
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
public function createNamedNativeQuery($name) { |
163
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
public function createQueryBuilder() { |
167
|
|
|
return new ElasticQueryBuilder($this); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
public function getPartialReference($entityName, $identifier) { |
171
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
public function close() { |
175
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
public function copy($entity, $deep = false) { |
179
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
public function lock($entity, $lockMode, $lockVersion = null) { |
183
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
public function getEventManager() { |
187
|
|
|
if (is_null($this->eventManager)) { |
188
|
|
|
$this->eventManager = new EventManager(); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
return $this->eventManager; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
public function getConfiguration() { |
195
|
|
|
return []; |
|
|
|
|
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
public function isOpen() { |
199
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
public function getHydrator($hydrationMode) { |
203
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
public function newHydrator($hydrationMode = null) { |
207
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
public function getProxyFactory() { |
211
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
public function getFilters() { |
215
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
public function isFiltersStateClean() { |
219
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
public function hasFilters() { |
223
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
public function persist($object) { |
227
|
|
|
return $this->unitOfWork->persist($object); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
public function remove($object) { |
231
|
|
|
return $this->unitOfWork->delete($object); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
public function merge($object) { |
235
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
public function clear($objectName = null) { |
239
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
public function detach($object) { |
243
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
public function refresh($object) { |
247
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
public function flush($entity = null) { |
251
|
|
|
$this->getUnitOfWork()->commit($entity); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
public function getMetadataFactory() { |
255
|
|
|
trigger_error(__METHOD__ . ' method not supported. '); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
public function initializeObject($obj) { |
259
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
public function contains($object) { |
263
|
|
|
trigger_error(__METHOD__ . ' method is not supported. '); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
private function getAnnotationDriver(AnnotationReader $annotationReader = null) { |
267
|
|
|
if (is_null($this->annotationDriver)) { |
268
|
|
|
$this->annotationDriver = new ElasticAnnotationDriver($annotationReader); |
|
|
|
|
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
return $this->annotationDriver; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* @param string $className |
276
|
|
|
* @return ClassMetadata |
277
|
|
|
*/ |
278
|
|
|
public function getClassMetadata($className) { |
279
|
|
|
$metadata = new ClassMetadata($className); |
280
|
|
|
|
281
|
|
|
$this->getAnnotationDriver( |
282
|
|
|
$this->getUnitOfWork()->getEntityPersister($className)->getAnnotionReader() |
283
|
|
|
)->loadMetadataForClass($className, $metadata); |
284
|
|
|
|
285
|
|
|
return $metadata; |
286
|
|
|
} |
287
|
|
|
} |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.