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
|
|
|
|