Completed
Push — master ( dab245...a7b618 )
by Gaetano
13:10 queued 08:59
created

EntityManager::getRepository()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.0072

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 12
cts 13
cp 0.9231
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 13
nc 4
nop 1
crap 4.0072
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
47
     */
48 10
    public function registerService(RepositoryInterface $service, $contentTypeIdentifier)
49
    {
50 10
        $this->serviceMap[$contentTypeIdentifier] = $service;
51 10
    }
52
53
    /**
54
     * Registers a php class to be used as wrapper for a given content type
55
     * @var string $className
56
     * @var string $contentTypeIdentifier
57
     * @throws \InvalidArgumentException
58
     *
59
     * @todo validate contentTypeIdentifier as well. Reject null identifier and integers (unless 0 isa valid content type identifier...)
60
     */
61 2
    public function registerClass($className, $contentTypeIdentifier)
62
    {
63 2
        if (!is_subclass_of($className, '\Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface')) {
64
            throw new \InvalidArgumentException("Class '$className' can not be registered as repository because it lacks the necessary interface");
65
        }
66 2
        $this->classMap[$contentTypeIdentifier] = $className;
67 2
    }
68
69
    /**
70
     * Registers a php class to be used as default repository
71
     * @var string $className
72
     * @throws \InvalidArgumentException
73
     */
74 10
    public function registerDefaultClass($className)
75
    {
76 10
        if (!is_subclass_of($className, '\Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface')) {
77
            throw new \InvalidArgumentException("Class '$className' can not be registered as repository because it lacks the necessary interface");
78
        }
79 10
        $this->defaultClass = $className;
80 10
    }
81
82
    /**
83
     * @param string $contentTypeIdentifier as used in the mapping
84
     * @return \Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface
85
     * @throws \UnexpectedValueException
86
     */
87 10
    public function getRepository($contentTypeIdentifier)
88
    {
89 10
        if (isset($this->serviceMap[$contentTypeIdentifier])) {
90 3
            $repo = $this->serviceMap[$contentTypeIdentifier];
91 3
            return $repo->setContentTypeIdentifier($contentTypeIdentifier);
92
        }
93
94
        /// @todo for a small perf gain, we might store the created repo classes in an array
95 10
        if (isset($this->classMap[$contentTypeIdentifier])) {
96 2
            $repoClass = $this->classMap[$contentTypeIdentifier];
97 2
            $repo = new $repoClass($this->repository, $this);
98 2
            return $repo->setContentTypeIdentifier($contentTypeIdentifier);
99
        }
100
101 10
        if ($this->defaultClass != '') {
102 10
            $repoClass = $this->defaultClass;
103 10
            $repo = new $repoClass($this->repository, $this);
104 10
            return $repo->setContentTypeIdentifier($contentTypeIdentifier);
105
        }
106
107
        throw new \UnexpectedValueException("Content type '$contentTypeIdentifier' is not registered with the Entity Manager, can not retrieve a Repository for it");
108
    }
109
110
    /**
111
     * @param int $contentTypeId slightly slower than loading by Identifier, but is useful when used eg. by Entities
112
     * @return \Kaliop\eZObjectWrapperBundle\Core\RepositoryInterface
113
     * @throws \UnexpectedValueException
114
     */
115 7
    public function getRepositoryByContentTypeId($contentTypeId)
116
    {
117 7
        return $this->getRepository($this->getContentTypeIdentifierFromId($contentTypeId));
118
    }
119
120
    /**
121
     * A method added to keep the API friendly to Doctrine users
122
     * @param string $contentTypeIdentifier
123
     * @param mixed $id Content Id
124
     * @return \Kaliop\eZObjectWrapperBundle\Core\EntityInterface
125
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content with the given id does not exist
126
     * @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
127
     */
128 10
    public function find($contentTypeIdentifier, $id)
129
    {
130 10
        return $this->getRepository($contentTypeIdentifier)->find($id);
131
    }
132
133
    /**
134
     * NB: this is slightly slower in execution than using find(), as it does have to look up the content type identifier.
135
     *
136
     * @param Location|Content|ContentInfo $content If you have a Content, by all means pass it in, not just its contentInfo
137
     * @return \Kaliop\eZObjectWrapperBundle\Core\EntityInterface
138
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content with the given id does not exist
139
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If a content type with the given id and status DEFINED can not be found
140
     * @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
141
     */
142 4
    public function load($content)
143
    {
144 4
        switch(true)
145
        {
146 4
            case $content instanceof ContentInfo:
147 2
                return $this
148 2
                    ->getRepositoryByContentTypeId($content->contentTypeId)
149 2
                    ->loadEntityFromContentInfo($content);
150 4
            case $content instanceof Content:
151 4
                return $this
152 4
                    ->getRepositoryByContentTypeId($content->contentInfo->contentTypeId)
153 4
                    ->loadEntityFromContent($content);
154 2
            case $content instanceof Location:
155 2
                return $this
156 2
                    ->getRepositoryByContentTypeId($content->contentInfo->contentTypeId)
157 2
                    ->loadEntityFromLocation($content);
158
        }
159
        throw new \UnexpectedValueException("Can not load an Entity for php object of class " . get_class($content));
160
    }
161
162
    /**
163
     * @param Content[]|Location[]|Contentinfo[]|SearchResult $contents
164
     * @return \Kaliop\eZObjectWrapperBundle\Core\EntityInterface[] they keys of the $contents array get preserved
165
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the content with the given id does not exist
166
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If a content type with the given id and status DEFINED can not be found
167
     * @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
168
     */
169 2
    public function loadMany($contents)
170
    {
171 2
        switch(true)
172
        {
173 2
            case $contents instanceof SearchResult:
174 1
                $entities = array();
175 1
                foreach ($contents->searchHits as $searchHit) {
176 1
                    $entities[] = $this->load($searchHit->valueObject);
177 1
                }
178 1
                return $entities;
179 2
            case is_array($contents):
180 2
                $entities = array();
181 2
                foreach ($contents as $key => $value) {
182 2
                    $entities[$key] = $this->load($value);
183 2
                }
184 2
                return $entities;
185
        }
186 2
        throw new \UnexpectedValueException("Can not load an Entities for php object of class " . get_class($contents));
187
    }
188
189
    /**
190
     * @param mixed $id
191
     * @return string
192
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If a content type with the given id and status DEFINED can not be found
193
     */
194 7
    protected function getContentTypeIdentifierFromId($id)
195
    {
196 7
        if (!isset($this->contentTypeIdentifierCache[$id])) {
197 7
            $contentTypeService = $this->repository->getContentTypeService();
198 7
            $this->contentTypeIdentifierCache[$id] = $contentTypeService->loadContentType($id)->identifier;
199 7
        }
200 7
        return $this->contentTypeIdentifierCache[$id];
201
    }
202
}
203