Completed
Push — master ( 91fdab...75a7b9 )
by
unknown
13:37
created

PagePartBundle/PagePartAdmin/PagePartAdmin.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\PagePartBundle\PagePartAdmin;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\EntityManagerInterface;
7
use Kunstmaan\AdminBundle\Entity\EntityInterface;
8
use Kunstmaan\PagePartBundle\Entity\PagePartRef;
9
use Kunstmaan\PagePartBundle\Event\Events;
10
use Kunstmaan\PagePartBundle\Event\PagePartEvent;
11
use Kunstmaan\PagePartBundle\Helper\HasPagePartsInterface;
12
use Kunstmaan\PagePartBundle\Helper\PagePartInterface;
13
use Kunstmaan\PagePartBundle\Repository\PagePartRefRepository;
14
use Kunstmaan\UtilitiesBundle\Helper\ClassLookup;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\Form\FormBuilderInterface;
17
use Symfony\Component\HttpFoundation\Request;
18
19
/**
20
 * PagePartAdmin
21
 */
22
class PagePartAdmin
23
{
24
    /**
25
     * @var PagePartAdminConfiguratorInterface
26
     */
27
    protected $configurator;
28
29
    /**
30
     * @var EntityManager|EntityManagerInterface
31
     */
32
    protected $em;
33
34
    /**
35
     * @var HasPagePartsInterface
36
     */
37
    protected $page;
38
39
    /**
40
     * @var string
41
     */
42
    protected $context;
43
44
    /**
45
     * @var ContainerInterface
46
     */
47
    protected $container;
48
49
    /**
50
     * @var PagePartInterface[]
51
     */
52
    protected $pageParts = array();
53
54
    /**
55
     * @var PagePartRef[]
56
     */
57
    protected $pagePartRefs = array();
58
59
    /**
60
     * @var PagePartInterface[]
61
     */
62
    protected $newPageParts = array();
63
64
    /**
65
     * @param PagePartAdminConfiguratorInterface $configurator The configurator
66
     * @param EntityManagerInterface             $em           The entity manager
67
     * @param HasPagePartsInterface              $page         The page
68
     * @param null|string                        $context      The context
69
     * @param null|ContainerInterface            $container    The container
70
     *
71
     * @throws \InvalidArgumentException
72
     */
73
    public function __construct(PagePartAdminConfiguratorInterface $configurator, EntityManagerInterface $em, HasPagePartsInterface $page, $context = null, ContainerInterface $container = null)
74
    {
75
        if (!($page instanceof EntityInterface)) {
76
            throw new \InvalidArgumentException("Page must be an instance of EntityInterface.");
77
        }
78
79
        $this->configurator = $configurator;
80
        $this->em = $em;
81
        $this->page = $page;
82
        $this->container = $container;
83
84
        if ($context) {
85
            $this->context = $context;
86
        } else {
87
            if ($this->configurator->getContext()) {
88
                $this->context = $this->configurator->getContext();
89
            } else {
90
                $this->context = 'main';
91
            }
92
        }
93
94
        $this->initializePageParts();
95
    }
96
97
    /**
98
     * Get all pageparts from the database, and store them.
99
     */
100
    private function initializePageParts()
101
    {
102
        // Get all the pagepartrefs
103
        /** @var PagePartRefRepository $ppRefRepo */
104
        $ppRefRepo = $this->em->getRepository('KunstmaanPagePartBundle:PagePartRef');
105
        $ppRefs = $ppRefRepo->getPagePartRefs($this->page, $this->context);
106
107
        // Group pagepartrefs per type
108
        $types = array();
109
        foreach ($ppRefs as $pagePartRef) {
110
            $types[$pagePartRef->getPagePartEntityname()][] = $pagePartRef->getPagePartId();
111
            $this->pagePartRefs[$pagePartRef->getId()] = $pagePartRef;
112
        }
113
114
        // Fetch all the pageparts (only one query per pagepart type)
115
        /** @var EntityInterface[] $pageParts */
116
        $pageParts = array();
117 View Code Duplication
        foreach ($types as $classname => $ids) {
118
            $result = $this->em->getRepository($classname)->findBy(array('id' => $ids));
119
            $pageParts = array_merge($pageParts, $result);
120
        }
121
122
        // Link the pagepartref to the pagepart
123
        foreach ($this->pagePartRefs as $pagePartRef) {
124
            foreach ($pageParts as $key => $pagePart) {
125
                if (ClassLookup::getClass($pagePart) == $pagePartRef->getPagePartEntityname()
126
                    && $pagePart->getId() == $pagePartRef->getPagePartId()
127
                ) {
128
                    $this->pageParts[$pagePartRef->getId()] = $pagePart;
129
                    unset($pageParts[$key]);
130
                    break;
131
                }
132
            }
133
        }
134
    }
135
136
    /**
137
     * @return EntityInterface
0 ignored issues
show
Should the return type not be HasPagePartsInterface?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
138
     */
139
    public function getPage()
140
    {
141
        return $this->page;
142
    }
143
144
    /**
145
     * @param Request $request
146
     */
147
    public function preBindRequest(Request $request)
148
    {
149
        // Fetch all sub-entities that should be removed
150
        $subPagePartsToDelete = array();
151
        foreach (array_keys($request->request->all()) as $key) {
152
            // Example value: delete_pagepartadmin_74_tags_3
153
            if (preg_match("/^delete_pagepartadmin_(\\d+)_(\\w+)_(\\d+)$/i", $key, $matches)) {
154
                $subPagePartsToDelete[$matches[1]][] = array('name' => $matches[2], 'id' => $matches[3]);
155
            }
156
        }
157
158
        $doFlush = false;
159
        foreach ($this->pagePartRefs as $pagePartRef) {
160
            // Remove pageparts
161
            if ('true' == $request->get($pagePartRef->getId().'_deleted')) {
162
                $pagePart = $this->pageParts[$pagePartRef->getId()];
163
                $this->em->remove($pagePart);
164
                $this->em->remove($pagePartRef);
165
166
                unset($this->pageParts[$pagePartRef->getId()]);
167
                unset($this->pagePartRefs[$pagePartRef->getId()]);
168
                $doFlush = true;
169
            }
170
171
            // Remove sub-entities from pageparts
172
            if (array_key_exists($pagePartRef->getId(), $subPagePartsToDelete)) {
173
                $pagePart = $this->pageParts[$pagePartRef->getId()];
174
                foreach ($subPagePartsToDelete[$pagePartRef->getId()] as $deleteInfo) {
175
                    /** @var EntityInterface[] $objects */
176
                    $objects = call_user_func(array($pagePart, 'get'.ucfirst($deleteInfo['name'])));
177
178
                    foreach ($objects as $object) {
179
                        if ($object->getId() == $deleteInfo['id']) {
180
                            $this->em->remove($object);
181
                            $doFlush = true;
182
                        }
183
                    }
184
                }
185
            }
186
        }
187
188
        if ($doFlush) {
189
            $this->em->flush();
190
        }
191
192
        // Create the objects for the new pageparts
193
        $this->newPageParts = array();
194
        $newRefIds = $request->get($this->context.'_new');
195
196
        if (is_array($newRefIds)) {
197
            foreach ($newRefIds as $newId) {
198
                $type = $request->get($this->context.'_type_'.$newId);
199
                $this->newPageParts[$newId] = new $type();
200
            }
201
        }
202
203
        // Sort pageparts again
204
        $sequences = $request->get($this->context.'_sequence');
205
        if (!is_null($sequences)) {
206
            $tempPageparts = $this->pageParts;
207
            $this->pageParts = array();
208
            foreach ($sequences as $sequence) {
209
                if (array_key_exists($sequence, $this->newPageParts)) {
210
                    $this->pageParts[$sequence] = $this->newPageParts[$sequence];
211
                } elseif (array_key_exists($sequence, $tempPageparts)) {
212
                    $this->pageParts[$sequence] = $tempPageparts[$sequence];
213
                } else
214
                    $this->pageParts[$sequence] = $this->getPagePart($sequence, array_search($sequence, $sequences) + 1);
215
            }
216
217
            unset($tempPageparts);
218
        }
219
    }
220
221
    /**
222
     * @param Request $request
223
     */
224
    public function bindRequest(Request $request)
225
    {
226
    }
227
228
    /**
229
     * @param FormBuilderInterface $formbuilder
230
     */
231
    public function adaptForm(FormBuilderInterface $formbuilder)
232
    {
233
        $data = $formbuilder->getData();
234
235
        foreach ($this->pageParts as $pagePartRefId => $pagePart) {
236
            $data['pagepartadmin_' . $pagePartRefId] = $pagePart;
237
            $formbuilder->add('pagepartadmin_' . $pagePartRefId, $pagePart->getDefaultAdminType());
238
        }
239
240
        foreach ($this->newPageParts as $newPagePartRefId => $newPagePart) {
241
            $data['pagepartadmin_' . $newPagePartRefId] = $newPagePart;
242
            $formbuilder->add('pagepartadmin_' . $newPagePartRefId, $newPagePart->getDefaultAdminType());
243
        }
244
245
        $formbuilder->setData($data);
246
    }
247
248
    /**
249
     * @param Request $request
250
     */
251
    public function persist(Request $request)
252
    {
253
        /** @var PagePartRefRepository $ppRefRepo */
254
        $ppRefRepo = $this->em->getRepository('KunstmaanPagePartBundle:PagePartRef');
255
256
        // Add new pageparts on the correct position + Re-order and save pageparts if needed
257
        $sequences = $request->get($this->context.'_sequence', []);
258
        $sequencescount = count($sequences);
259
        for ($i = 0; $i < $sequencescount; $i++) {
260
            $pagePartRefId = $sequences[$i];
261
262
            if (array_key_exists($pagePartRefId, $this->newPageParts)) {
263
                $pagePart = $this->newPageParts[$pagePartRefId];
264
                $this->em->persist($pagePart);
265
                $this->em->flush($pagePart);
266
267
                $ppRefRepo->addPagePart($this->page, $pagePart, ($i + 1), $this->context, false);
268
269
            } elseif (array_key_exists($pagePartRefId, $this->pagePartRefs)) {
270
                $pagePartRef = $this->pagePartRefs[$pagePartRefId];
271
                if ($pagePartRef instanceof PagePartRef && $pagePartRef->getSequencenumber() != ($i + 1)) {
272
                    $pagePartRef->setSequencenumber($i + 1);
273
                    $pagePartRef->setContext($this->context);
274
                    $this->em->persist($pagePartRef);
275
                }
276
                $pagePart = $pagePartRef->getPagePart($this->em);
277
            }
278
279
            if (isset($pagePart)) {
280
                $this->container->get('event_dispatcher')->dispatch(
281
                    Events::POST_PERSIST,
282
                    new PagePartEvent($pagePart)
283
                );
284
            }
285
        }
286
    }
287
288
    /**
289
     * @return null|string
290
     */
291
    public function getContext()
292
    {
293
        return $this->context;
294
    }
295
296
    /**
297
     * This getter returns an array holding info on page part types that can be added to the page.
298
     * The types are filtererd here, based on the amount of page parts of a certain type that can be added to the page.
299
     *
300
     * @return array
301
     */
302
    public function getPossiblePagePartTypes()
303
    {
304
        $possiblePPTypes = $this->configurator->getPossiblePagePartTypes();
305
        $result = array();
306
307
        // filter page part types that can only be added x times to the page context.
308
        // to achieve this, provide a 'pagelimit' parameter when adding the pp type in your PagePartAdminConfiguration
309
        if (!empty($possiblePPTypes)) {
310
            foreach ($possiblePPTypes as $possibleTypeData) {
311
                if (array_key_exists('pagelimit', $possibleTypeData)) {
312
                    $pageLimit = $possibleTypeData['pagelimit'];
313
                    /** @var PagePartRefRepository $entityRepository */
314
                    $entityRepository = $this->em->getRepository('KunstmaanPagePartBundle:PagePartRef');
315
                    $formPPCount = $entityRepository->countPagePartsOfType(
316
                        $this->page,
317
                        $possibleTypeData['class'],
318
                        $this->configurator->getContext()
319
                    );
320
                    if ($formPPCount < $pageLimit) {
321
                        $result[] = $possibleTypeData;
322
                    }
323
                } else {
324
                    $result[] = $possibleTypeData;
325
                }
326
            }
327
        }
328
329
        return $result;
330
    }
331
332
    /**
333
     * @return string
334
     */
335
    public function getName()
336
    {
337
        return $this->configurator->getName();
338
    }
339
340
    /**
341
     * @return array
342
     */
343
    public function getPagePartMap()
344
    {
345
        return $this->pageParts;
346
    }
347
348
    /**
349
     * @param PagePartInterface $pagepart
350
     *
351
     * @return string
352
     */
353
    public function getType(PagePartInterface $pagepart)
354
    {
355
        $possiblePagePartTypes = $this->configurator->getPossiblePagePartTypes();
356
        foreach ($possiblePagePartTypes as &$pageparttype) {
357
            if ($pageparttype['class'] == ClassLookup::getClass($pagepart)) {
358
                return $pageparttype['name'];
359
            }
360
        }
361
362
        return "no name";
363
    }
364
365
    /**
366
     * @param int $id
367
     * @param int $sequenceNumber
368
     *
369
     * @return PagePartInterface
0 ignored issues
show
Should the return type not be PagePartInterface|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
370
     */
371
    public function getPagePart($id, $sequenceNumber)
372
    {
373
        /** @var PagePartRefRepository $ppRefRepo */
374
        $ppRefRepo = $this->em->getRepository('KunstmaanPagePartBundle:PagePartRef');
375
376
        return $ppRefRepo->getPagePart($id, $this->context, $sequenceNumber);
377
    }
378
379
    /**
380
     * @param object $pagepart
381
     *
382
     * @return string
383
     */
384
    public function getClassName($pagepart)
385
    {
386
        return get_class($pagepart);
387
    }
388
389
}