|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Kaliop\eZObjectWrapperBundle\Core; |
|
4
|
|
|
|
|
5
|
|
|
use eZ\Publish\API\Repository\Repository as eZRepository; |
|
6
|
|
|
use eZ\Publish\API\Repository\Values\Content\Location; |
|
7
|
|
|
use eZ\Publish\API\Repository\Values\Content\Content; |
|
8
|
|
|
use eZ\Publish\API\Repository\Values\Content\ContentInfo; |
|
9
|
|
|
use eZ\Publish\API\Repository\Values\Content\Search\SearchResult; |
|
10
|
|
|
|
|
11
|
|
|
/** |
|
12
|
|
|
* A simple entity manager, inspired by the Doctrine one |
|
13
|
|
|
* |
|
14
|
|
|
* @todo add methods to automatically create an Entity of the good type given a Content, Location, Id or RemoteId ? |
|
15
|
|
|
*/ |
|
16
|
|
|
class EntityManager |
|
17
|
|
|
{ |
|
18
|
|
|
/** |
|
19
|
|
|
* @var \eZ\Publish\API\Repository\Repository $repository |
|
20
|
|
|
*/ |
|
21
|
|
|
protected $repository; |
|
22
|
|
|
protected $classMap; |
|
23
|
|
|
protected $serviceMap; |
|
24
|
|
|
protected $defaultClass; |
|
25
|
|
|
protected $contentTypeIdentifierCache = array(); |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* @param eZRepository $repository |
|
29
|
|
|
* @param array $classMap array of classes exposing a RepositoryInterface |
|
30
|
|
|
* @param RepositoryManagerInterface[] $serviceMap array of services exposing a RepositoryInterface |
|
31
|
|
|
*/ |
|
32
|
10 |
|
public function __construct(eZRepository $repository, array $classMap=array(), array $serviceMap=array()) |
|
33
|
|
|
{ |
|
34
|
10 |
|
$this->repository = $repository; |
|
35
|
10 |
|
foreach ($classMap as $contentTypeIdentifier => $className) { |
|
36
|
|
|
$this->registerClass($className, $contentTypeIdentifier); |
|
37
|
10 |
|
} |
|
38
|
10 |
|
foreach ($serviceMap as $contentTypeIdentifier => $service) { |
|
39
|
|
|
$this->registerService($service, $contentTypeIdentifier); |
|
40
|
10 |
|
} |
|
41
|
10 |
|
} |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* Registers an existing service to be used as repository for a given content type |
|
45
|
|
|
* @var RepositoryInterface $service |
|
46
|
|
|
* @var string $contentTypeIdentifier when null, we will ask the Repository to see if it already has its own $contentTypeIdentifier set up |
|
47
|
|
|
*/ |
|
48
|
10 |
|
public function registerService(RepositoryInterface $service, $contentTypeIdentifier) |
|
49
|
|
|
{ |
|
50
|
10 |
|
if ($contentTypeIdentifier == null && is_callable(array($service, 'getContentTypeIdentifier'))) { |
|
51
|
10 |
|
$contentTypeIdentifier = $service->getContentTypeIdentifier(); |
|
52
|
|
|
} |
|
53
|
|
|
if ($contentTypeIdentifier == null) { |
|
54
|
|
|
throw new \InvalidArgumentException("Service can not be registered as repository for NULL Content Type Identifier"); |
|
55
|
|
|
} |
|
56
|
|
|
$this->serviceMap[$contentTypeIdentifier] = $service; |
|
57
|
|
|
} |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* Registers a php class to be used as wrapper for a given content type |
|
61
|
2 |
|
* @var string $className |
|
62
|
|
|
* @var string $contentTypeIdentifier |
|
63
|
2 |
|
* @throws \InvalidArgumentException |
|
64
|
|
|
* |
|
65
|
|
|
* @todo improve validation of contentTypeIdentifiers (is '0' a valid content type identifier?...) |
|
66
|
2 |
|
*/ |
|
67
|
2 |
|
public function registerClass($className, $contentTypeIdentifier) |
|
68
|
|
|
{ |
|
69
|
|
|
if (!is_subclass_of($className, '\Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface')) { |
|
|
|
|
|
|
70
|
|
|
throw new \InvalidArgumentException("Class '$className' can not be registered as repository because it lacks the necessary interface"); |
|
71
|
|
|
} |
|
72
|
|
|
if ($contentTypeIdentifier == null) { |
|
73
|
|
|
throw new \InvalidArgumentException("Class '$className' can not be registered as repository for NULL Content Type Identifier"); |
|
74
|
10 |
|
} |
|
75
|
|
|
$this->classMap[$contentTypeIdentifier] = $className; |
|
76
|
10 |
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
10 |
|
* Registers a php class to be used as default repository |
|
80
|
10 |
|
* @var string $className |
|
81
|
|
|
* @throws \InvalidArgumentException |
|
82
|
|
|
*/ |
|
83
|
|
|
public function registerDefaultClass($className) |
|
84
|
|
|
{ |
|
85
|
|
|
if (!is_subclass_of($className, '\Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface')) { |
|
|
|
|
|
|
86
|
|
|
throw new \InvalidArgumentException("Class '$className' can not be registered as default repository because it lacks the necessary interface"); |
|
87
|
10 |
|
} |
|
88
|
|
|
$this->defaultClass = $className; |
|
89
|
10 |
|
} |
|
90
|
3 |
|
|
|
91
|
3 |
|
/** |
|
92
|
|
|
* @param string $contentTypeIdentifier as used in the mapping |
|
93
|
|
|
* @return \Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface |
|
94
|
|
|
* @throws \UnexpectedValueException |
|
95
|
10 |
|
*/ |
|
96
|
2 |
|
public function getRepository($contentTypeIdentifier) |
|
97
|
2 |
|
{ |
|
98
|
2 |
|
if (isset($this->serviceMap[$contentTypeIdentifier])) { |
|
99
|
|
|
$repo = $this->serviceMap[$contentTypeIdentifier]; |
|
100
|
|
|
return $repo->setContentTypeIdentifier($contentTypeIdentifier); |
|
101
|
10 |
|
} |
|
102
|
10 |
|
|
|
103
|
10 |
|
/// @todo for a small perf gain, we might store the created repo classes in an array |
|
104
|
10 |
|
if (isset($this->classMap[$contentTypeIdentifier])) { |
|
105
|
|
|
$repoClass = $this->classMap[$contentTypeIdentifier]; |
|
106
|
|
|
$repo = new $repoClass($this->repository, $this); |
|
107
|
|
|
return $repo->setContentTypeIdentifier($contentTypeIdentifier); |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
if ($this->defaultClass != '') { |
|
111
|
|
|
$repoClass = $this->defaultClass; |
|
112
|
|
|
$repo = new $repoClass($this->repository, $this); |
|
113
|
|
|
return $repo->setContentTypeIdentifier($contentTypeIdentifier); |
|
114
|
|
|
} |
|
115
|
7 |
|
|
|
116
|
|
|
throw new \UnexpectedValueException("Content type '$contentTypeIdentifier' is not registered with the Entity Manager, can not retrieve a Repository for it"); |
|
117
|
7 |
|
} |
|
118
|
|
|
|
|
119
|
|
|
/** |
|
120
|
|
|
* @param int $contentTypeId slightly slower than loading by Identifier, but is useful when used eg. by Entities |
|
121
|
|
|
* @return \Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface |
|
122
|
|
|
* @throws \UnexpectedValueException |
|
123
|
|
|
*/ |
|
124
|
|
|
public function getRepositoryByContentTypeId($contentTypeId) |
|
125
|
|
|
{ |
|
126
|
|
|
return $this->getRepository($this->getContentTypeIdentifierFromId($contentTypeId)); |
|
127
|
|
|
} |
|
128
|
10 |
|
|
|
129
|
|
|
/** |
|
130
|
10 |
|
* A method added to keep the API friendly to Doctrine users |
|
131
|
|
|
* @param string $contentTypeIdentifier |
|
132
|
|
|
* @param mixed $id Content Id |
|
133
|
|
|
* @return \Kaliop\eZObjectWrapperBundle\Core\EntityInterface |
|
134
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content with the given id does not exist |
|
135
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions |
|
136
|
|
|
*/ |
|
137
|
|
|
public function find($contentTypeIdentifier, $id) |
|
138
|
|
|
{ |
|
139
|
|
|
return $this->getRepository($contentTypeIdentifier)->find($id); |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
4 |
|
/** |
|
143
|
|
|
* NB: this is slightly slower in execution than using find(), as it does have to look up the content type identifier. |
|
144
|
4 |
|
* |
|
145
|
|
|
* @param Location|Content|ContentInfo $content If you have a Content, by all means pass it in, not just its contentInfo |
|
146
|
4 |
|
* @return \Kaliop\eZObjectWrapperBundle\Core\EntityInterface |
|
147
|
2 |
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content with the given id does not exist |
|
148
|
2 |
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If a content type with the given id and status DEFINED can not be found |
|
149
|
2 |
|
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions |
|
150
|
4 |
|
*/ |
|
151
|
4 |
|
public function load($content) |
|
152
|
4 |
|
{ |
|
153
|
4 |
|
switch(true) |
|
154
|
2 |
|
{ |
|
155
|
2 |
|
case $content instanceof ContentInfo: |
|
156
|
2 |
|
return $this |
|
157
|
2 |
|
->getRepositoryByContentTypeId($content->contentTypeId) |
|
158
|
|
|
->loadEntityFromContentInfo($content); |
|
159
|
|
|
case $content instanceof Content: |
|
160
|
|
|
return $this |
|
161
|
|
|
->getRepositoryByContentTypeId($content->contentInfo->contentTypeId) |
|
162
|
|
|
->loadEntityFromContent($content); |
|
163
|
|
|
case $content instanceof Location: |
|
164
|
|
|
return $this |
|
165
|
|
|
->getRepositoryByContentTypeId($content->contentInfo->contentTypeId) |
|
166
|
|
|
->loadEntityFromLocation($content); |
|
167
|
|
|
} |
|
168
|
|
|
throw new \UnexpectedValueException("Can not load an Entity for php object of class " . get_class($content)); |
|
169
|
2 |
|
} |
|
170
|
|
|
|
|
171
|
2 |
|
/** |
|
172
|
|
|
* @param Content[]|Location[]|Contentinfo[]|SearchResult $contents |
|
173
|
2 |
|
* @return \Kaliop\eZObjectWrapperBundle\Core\EntityInterface[] they keys of the $contents array get preserved |
|
174
|
1 |
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content with the given id does not exist |
|
175
|
1 |
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If a content type with the given id and status DEFINED can not be found |
|
176
|
1 |
|
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions |
|
177
|
1 |
|
*/ |
|
178
|
1 |
|
public function loadMany($contents) |
|
179
|
2 |
|
{ |
|
180
|
2 |
|
switch(true) |
|
181
|
2 |
|
{ |
|
182
|
2 |
|
case $contents instanceof SearchResult: |
|
183
|
2 |
|
$entities = array(); |
|
184
|
2 |
|
foreach ($contents->searchHits as $searchHit) { |
|
185
|
|
|
$entities[] = $this->load($searchHit->valueObject); |
|
186
|
2 |
|
} |
|
187
|
|
|
return $entities; |
|
188
|
|
|
case is_array($contents): |
|
189
|
|
|
$entities = array(); |
|
190
|
|
|
foreach ($contents as $key => $value) { |
|
191
|
|
|
$entities[$key] = $this->load($value); |
|
192
|
|
|
} |
|
193
|
|
|
return $entities; |
|
194
|
7 |
|
} |
|
195
|
|
|
throw new \UnexpectedValueException("Can not load an Entities for php object of class " . get_class($contents)); |
|
196
|
7 |
|
} |
|
197
|
7 |
|
|
|
198
|
7 |
|
/** |
|
199
|
7 |
|
* @param mixed $id |
|
200
|
7 |
|
* @return string |
|
201
|
|
|
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If a content type with the given id and status DEFINED can not be found |
|
202
|
|
|
*/ |
|
203
|
|
|
protected function getContentTypeIdentifierFromId($id) |
|
204
|
|
|
{ |
|
205
|
|
|
if (!isset($this->contentTypeIdentifierCache[$id])) { |
|
206
|
|
|
$contentTypeService = $this->repository->getContentTypeService(); |
|
207
|
|
|
$this->contentTypeIdentifierCache[$id] = $contentTypeService->loadContentType($id)->identifier; |
|
208
|
|
|
} |
|
209
|
|
|
return $this->contentTypeIdentifierCache[$id]; |
|
210
|
|
|
} |
|
211
|
|
|
} |
|
212
|
|
|
|