Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

PagePartBundle/PagePartAdmin/PagePartAdmin.php (1 issue)

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

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
343
     */
344
    public function getPagePartMap()
345
    {
346
        return $this->pageParts;
347
    }
348
349
    /**
350
     * @param PagePartInterface $pagepart
351
     *
352
     * @return string
353
     */
354
    public function getType(PagePartInterface $pagepart)
355
    {
356
        $possiblePagePartTypes = $this->configurator->getPossiblePagePartTypes();
357
        foreach ($possiblePagePartTypes as &$pageparttype) {
358
            if ($pageparttype['class'] == ClassLookup::getClass($pagepart)) {
359
                return $pageparttype['name'];
360
            }
361
        }
362
363
        return 'no name';
364
    }
365
366
    /**
367
     * @param int $id
368
     * @param int $sequenceNumber
369
     *
370
     * @return PagePartInterface
371
     */
372
    public function getPagePart($id, $sequenceNumber)
373
    {
374
        /** @var PagePartRefRepository $ppRefRepo */
375
        $ppRefRepo = $this->em->getRepository('KunstmaanPagePartBundle:PagePartRef');
376
377
        return $ppRefRepo->getPagePart($id, $this->context, $sequenceNumber);
378
    }
379
380
    /**
381
     * @param object $pagepart
382
     *
383
     * @return string
384
     */
385
    public function getClassName($pagepart)
386
    {
387
        return get_class($pagepart);
388
    }
389
}
390