EntityManager::find()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 2
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')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
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')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
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