PageManager::setContentItemTypes()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
/**
3
 * @copyright Zicht Online <http://zicht.nl>
4
 */
5
6
namespace Zicht\Bundle\PageBundle\Manager;
7
8
use Doctrine\Bundle\DoctrineBundle\Registry;
9
use Doctrine\Common\Persistence\ObjectManager;
10
use Doctrine\Common\Persistence\ObjectRepository;
11
use Doctrine\Common\Util\ClassUtils;
12
use Doctrine\ORM\Mapping\ClassMetadata;
13
use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
14
use Symfony\Component\EventDispatcher\EventDispatcher;
15
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
16
use Zicht\Bundle\PageBundle\Entity\ViewablePageRepository;
17
use Zicht\Bundle\PageBundle\Event;
18
use Zicht\Bundle\PageBundle\Model\PageInterface;
19
use Zicht\Util\Str;
20
21
/**
22
 * Main service for page management
23
 */
24
class PageManager
25
{
26
    /**
27
     * @var array
28
     */
29
    private $mappings;
30
31
    /**
32
     * @var null|PageInterface
33
     */
34
    private $loadedPage;
35
36
    /**
37
     * @var Registry
38
     */
39
    private $doctrine;
40
41
    /**
42
     * @var ObjectManager
43
     */
44
    private $em;
45
46
    /**
47
     * @var EventDispatcher
48
     */
49
    private $eventDispatcher;
50
51
    /**
52
     * @var string
53
     */
54
    private $pageClassName;
55
56
    /**
57
     * @var string
58
     */
59
    private $contentItemClassName;
60
61
    /**
62
     * Construct the page manager with the specified dependencies.
63
     *
64
     * @param Registry $doctrine
65
     * @param EventDispatcher $dispatcher
66
     * @param string $pageClassName
67
     * @param string $contentItemClassName
68
     */
69 16
    public function __construct(Registry $doctrine, $dispatcher, $pageClassName, $contentItemClassName)
70
    {
71 16
        $this->mappings = [];
72 16
        $this->doctrine = $doctrine;
73 16
        $this->em = $doctrine->getManager();
74 16
        $this->eventDispatcher = $dispatcher;
75
76 16
        $this->pageClassName = $pageClassName;
77 16
        $this->contentItemClassName = $contentItemClassName;
78
79 16
        $this->mappings[$pageClassName] = [];
80 16
        $this->mappings[$contentItemClassName] = [];
81 16
    }
82
83
    /**
84
     * Returns the template of the page from the bundle the entity is part of.
85
     *
86
     * @param PageInterface $page
87
     * @return string
88
     *
89
     * @throws \RuntimeException
90
     */
91 2
    public function getTemplate($page)
92
    {
93
        // determine page bundle name.
94 2
        $bundle = $this->getBundleName(ClassUtils::getRealClass(get_class($page)));
95 1
        return sprintf('%s:Page:%s.html.twig', $bundle, $page->getTemplateName());
96
    }
97
98
    /**
99
     * @param string $className
100
     * @return string
101
     * @throws \RuntimeException
102
     */
103 4
    protected function getBundleName($className)
104
    {
105 4
        $parts = explode('\\', $className);
106 4
        $vendor = array_shift($parts);
107 4
        $bundleName = null;
108 4
        foreach ($parts as $part) {
109 3
            if ($part === 'Entity') {
110 3
                break;
111
            }
112 3
            $bundleName = $part;
113 4
        }
114 4
        if (null === $bundleName) {
115 1
            $parentClass = get_parent_class($className);
116 1
            if ($parentClass) {
117
                return $this->getBundleName($parentClass);
118
            }
119
120 1
            throw new \RuntimeException("Could not determine bundle name for " . $className);
121
        }
122 3
        $bundle = $vendor . $bundleName;
123
124 3
        return $bundle;
125
    }
126
127
    /**
128
     * Returns the page class
129
     *
130
     * @return string
131
     */
132 1
    public function getPageClass()
133
    {
134 1
        return $this->pageClassName;
135
    }
136
137
    /**
138
     * Returns the base repository, i.e. the repository of the page class.
139
     *
140
     * @return ObjectRepository
141
     */
142 2
    public function getBaseRepository()
143
    {
144 2
        return $this->em->getRepository($this->pageClassName);
145
    }
146
147
    /**
148
     * Sets the available page types
149
     *
150
     * @param array $pageTypes
151
     */
152 1
    public function setPageTypes($pageTypes)
153
    {
154 1
        $this->mappings[$this->pageClassName] = $pageTypes;
155 1
    }
156
157
    /**
158
     * @return array
159
     */
160
    public function getPageTypes()
161
    {
162
        return $this->mappings[$this->pageClassName];
163
    }
164
165
    /**
166
     * @return array
167
     */
168
    public function getMappings()
169
    {
170
        return $this->mappings;
171
    }
172
173
    /**
174
     * Sets the available content item types.
175
     *
176
     * @param array $contentItemTypes
177
     */
178 1
    public function setContentItemTypes($contentItemTypes)
179
    {
180 1
        $this->mappings[$this->contentItemClassName] = $contentItemTypes;
181 1
    }
182
183
    /**
184
     * Adds the available page types and content item types to the class metadata's discriminatorMap
185
     *
186
     * @param ClassMetadata $c
187
     */
188 2
    public function decorateClassMetaData(ClassMetadata $c)
189
    {
190 2
        $parentClassName = $c->getName();
191
192 2
        if (isset($this->mappings[$parentClassName])) {
193 2
            $c->discriminatorMap = array();
194 2
            $c->discriminatorMap[strtolower(Str::classname($parentClassName))] = $parentClassName;
195 2
            foreach ($this->mappings[$parentClassName] as $className) {
196 2
                $bundlePrefix = Str::infix($this->getBundleName($className), '-');
197 2
                $name = Str::infix(Str::classname(Str::rstrip($className, Str::classname($parentClassName))), '-');
198 2
                $combinedDiscriminator = sprintf('%s-%s', $bundlePrefix, $name);
199 2
                $c->discriminatorMap[$combinedDiscriminator] = $className;
200 2
                $c->subClasses[] = $className;
201 2
            }
202 2
            $c->subClasses = array_unique($c->subClasses);
203 2
        }
204 2
    }
205
206
    /**
207
     * Find a page in the repository and trigger a view event.
208
     *
209
     * @param string $id
210
     * @return mixed
211
     *
212
     * @throws NotFoundHttpException
213
     */
214 3
    public function findForView($id)
215
    {
216 3
        $type = $this->doctrine->getConnection()->fetchColumn('SELECT type FROM page WHERE id=:id', array('id' => $id));
217 3
        if (!$type) {
218 1
            throw new NotFoundHttpException;
219
        }
220 2
        $types = $this->em->getClassMetadata($this->pageClassName)->discriminatorMap;
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
221
222 2
        $class = $types[$type];
223 2
        $repos = $this->em->getRepository($class);
224
225 2
        if ($repos instanceof ViewablePageRepository) {
226
            $ret = $repos->findForView($id);
227
        } else {
228 2
            $ret = $repos->find($id);
229
        }
230
231 2
        if (!$ret) {
232 1
            throw new NotFoundHttpException;
233
        }
234 1
        $this->setLoadedPage($ret);
235 1
        return $ret;
236
    }
237
238
    /**
239
     * Finds a page in the specified repository by the specified conditions.
240
     *
241
     * @param string $repository
242
     * @param array $conditions
243
     * @return null|object
244
     *
245
     * @throws NotFoundHttpException
246
     */
247 2
    public function findPageBy($repository, $conditions)
248
    {
249 2
        $ret = $this->em->getRepository($repository)->findOneBy($conditions);
250 2
        if (!$ret) {
251 1
            throw new NotFoundHttpException;
252
        }
253 1
        return $ret;
254
    }
255
256
    /**
257
     * Returns all pages from the base repository
258
     *
259
     * @return array
260
     */
261 1
    public function findAll()
262
    {
263 1
        return $this->getBaseRepository()->findAll();
264
    }
265
266
    /**
267
     * Set the loaded page, and trigger a view event
268
     *
269
     * @param PageInterface $loadedPage
270
     */
271 3
    public function setLoadedPage($loadedPage)
272
    {
273 3
        $this->dispatch(Event\PageEvents::PAGE_VIEW, new Event\PageViewEvent($loadedPage));
274 3
        $this->loadedPage = $loadedPage;
275 3
    }
276
277
    /**
278
     * Returns the currently loaded page, or default to the specified callback for loading it.
279
     *
280
     * @param callable $default
281
     * @return PageInterface
282
     * @throws NotFoundHttpException
283
     */
284 5
    public function getLoadedPage($default = null)
285
    {
286 5
        if (!$this->loadedPage) {
287 3
            if (is_callable($default)) {
288 2
                $page = call_user_func($default, $this);
289 2
                if ($page !== null) {
290 1
                    $this->setLoadedPage($page);
291 1
                }
292 2
            }
293
294 3
            if (!$this->loadedPage) {
295 2
                throw new NotFoundHttpException("There is no page currently loaded, but it was expected");
296
            }
297 1
        }
298 3
        return $this->loadedPage;
299
    }
300
301
    /**
302
     * Dispatch an event
303
     *
304
     * @param string $type
305
     * @param SymfonyEvent $event
306
     *
307
     * @return SymfonyEvent
308
     */
309 3
    public function dispatch($type, $event)
310
    {
311 3
        return $this->eventDispatcher->dispatch($type, $event);
312
    }
313
}
314