Completed
Push — master ( ae5e03...0447ee )
by Jeroen
10:35 queued 04:37
created

PagePartBundle/PagePartAdmin/PagePartAdmin.php (1 issue)

Check for loose comparison of strings.

Best Practice Bug Major

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 string|null                        $context      The context
69
     * @param ContainerInterface|null            $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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $context of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
85
            $this->context = $context;
86
        } elseif ($this->configurator->getContext()) {
87
            $this->context = $this->configurator->getContext();
88
        } else {
89
            $this->context = 'main';
90
        }
91
92
        $this->initializePageParts();
93
    }
94
95
    /**
96
     * Get all pageparts from the database, and store them.
97
     */
98
    private function initializePageParts()
99
    {
100
        // Get all the pagepartrefs
101
        /** @var PagePartRefRepository $ppRefRepo */
102
        $ppRefRepo = $this->em->getRepository(PagePartRef::class);
103
        $ppRefs = $ppRefRepo->getPagePartRefs($this->page, $this->context);
104
105
        // Group pagepartrefs per type
106
        $types = array();
107
        foreach ($ppRefs as $pagePartRef) {
108
            $types[$pagePartRef->getPagePartEntityname()][] = $pagePartRef->getPagePartId();
109
            $this->pagePartRefs[$pagePartRef->getId()] = $pagePartRef;
110
        }
111
112
        // Fetch all the pageparts (only one query per pagepart type)
113
        /** @var EntityInterface[] $pageParts */
114
        $pageParts = array();
115 View Code Duplication
        foreach ($types as $classname => $ids) {
116
            $result = $this->em->getRepository($classname)->findBy(array('id' => $ids));
117
            $pageParts = array_merge($pageParts, $result);
118
        }
119
120
        // Link the pagepartref to the pagepart
121
        foreach ($this->pagePartRefs as $pagePartRef) {
122
            foreach ($pageParts as $key => $pagePart) {
123
                if (ClassLookup::getClass($pagePart) == $pagePartRef->getPagePartEntityname()
124
                    && $pagePart->getId() == $pagePartRef->getPagePartId()
125
                ) {
126
                    $this->pageParts[$pagePartRef->getId()] = $pagePart;
127
                    unset($pageParts[$key]);
128
129
                    break;
130
                }
131
            }
132
        }
133
    }
134
135
    /**
136
     * @return EntityInterface
137
     */
138
    public function getPage()
139
    {
140
        return $this->page;
141
    }
142
143
    /**
144
     * @param Request $request
145
     */
146
    public function preBindRequest(Request $request)
147
    {
148
        // Fetch all sub-entities that should be removed
149
        $subPagePartsToDelete = array();
150
        foreach (array_keys($request->request->all()) as $key) {
151
            // Example value: delete_pagepartadmin_74_tags_3
152
            if (preg_match('/^delete_pagepartadmin_(\\d+)_(\\w+)_(\\d+)$/i', $key, $matches)) {
153
                $subPagePartsToDelete[$matches[1]][] = array('name' => $matches[2], 'id' => $matches[3]);
154
            }
155
        }
156
157
        $doFlush = false;
158
        foreach ($this->pagePartRefs as $pagePartRef) {
159
            // Remove pageparts
160
            if ('true' == $request->get($pagePartRef->getId().'_deleted')) {
161
                $pagePart = $this->pageParts[$pagePartRef->getId()];
162
                $this->em->remove($pagePart);
163
                $this->em->remove($pagePartRef);
164
165
                unset($this->pageParts[$pagePartRef->getId()], $this->pagePartRefs[$pagePartRef->getId()]);
166
                $doFlush = true;
167
            }
168
169
            // Remove sub-entities from pageparts
170
            if (\array_key_exists($pagePartRef->getId(), $subPagePartsToDelete)) {
171
                $pagePart = $this->pageParts[$pagePartRef->getId()];
172
                foreach ($subPagePartsToDelete[$pagePartRef->getId()] as $deleteInfo) {
173
                    /** @var EntityInterface[] $objects */
174
                    $objects = \call_user_func(array($pagePart, 'get'.ucfirst($deleteInfo['name'])));
175
176
                    foreach ($objects as $object) {
177
                        if ($object->getId() == $deleteInfo['id']) {
178
                            $this->em->remove($object);
179
                            $doFlush = true;
180
                        }
181
                    }
182
                }
183
            }
184
        }
185
186
        if ($doFlush) {
187
            $this->em->flush();
188
        }
189
190
        // Create the objects for the new pageparts
191
        $this->newPageParts = array();
192
        $newRefIds = $request->get($this->context.'_new');
193
194
        if (\is_array($newRefIds)) {
195
            foreach ($newRefIds as $newId) {
196
                $type = $request->get($this->context.'_type_'.$newId);
197
                $this->newPageParts[$newId] = new $type();
198
            }
199
        }
200
201
        // Sort pageparts again
202
        $sequences = $request->get($this->context.'_sequence');
203
        if (!\is_null($sequences)) {
204
            $tempPageparts = $this->pageParts;
205
            $this->pageParts = array();
206
            foreach ($sequences as $sequence) {
207
                if (\array_key_exists($sequence, $this->newPageParts)) {
208
                    $this->pageParts[$sequence] = $this->newPageParts[$sequence];
209
                } elseif (\array_key_exists($sequence, $tempPageparts)) {
210
                    $this->pageParts[$sequence] = $tempPageparts[$sequence];
211
                } else {
212
                    $this->pageParts[$sequence] = $this->getPagePart($sequence, array_search($sequence, $sequences) + 1);
213
                }
214
            }
215
216
            unset($tempPageparts);
217
        }
218
    }
219
220
    /**
221
     * @param Request $request
222
     */
223
    public function bindRequest(Request $request)
224
    {
225
    }
226
227
    /**
228
     * @param FormBuilderInterface $formbuilder
229
     */
230
    public function adaptForm(FormBuilderInterface $formbuilder)
231
    {
232
        $data = $formbuilder->getData();
233
234
        foreach ($this->pageParts as $pagePartRefId => $pagePart) {
235
            $data['pagepartadmin_' . $pagePartRefId] = $pagePart;
236
            $formbuilder->add('pagepartadmin_' . $pagePartRefId, $pagePart->getDefaultAdminType());
237
        }
238
239
        foreach ($this->newPageParts as $newPagePartRefId => $newPagePart) {
240
            $data['pagepartadmin_' . $newPagePartRefId] = $newPagePart;
241
            $formbuilder->add('pagepartadmin_' . $newPagePartRefId, $newPagePart->getDefaultAdminType());
242
        }
243
244
        $formbuilder->setData($data);
245
    }
246
247
    /**
248
     * @param Request $request
249
     */
250
    public function persist(Request $request)
251
    {
252
        /** @var PagePartRefRepository $ppRefRepo */
253
        $ppRefRepo = $this->em->getRepository(PagePartRef::class);
254
255
        // Add new pageparts on the correct position + Re-order and save pageparts if needed
256
        $sequences = $request->get($this->context.'_sequence', []);
257
        $sequencescount = \count($sequences);
258
        for ($i = 0; $i < $sequencescount; ++$i) {
259
            $pagePartRefId = $sequences[$i];
260
261
            if (\array_key_exists($pagePartRefId, $this->newPageParts)) {
262
                $pagePart = $this->newPageParts[$pagePartRefId];
263
                $this->em->persist($pagePart);
264
                $this->em->flush($pagePart);
265
266
                $ppRefRepo->addPagePart($this->page, $pagePart, $i + 1, $this->context, false);
267
            } elseif (\array_key_exists($pagePartRefId, $this->pagePartRefs)) {
268
                $pagePartRef = $this->pagePartRefs[$pagePartRefId];
269
                if ($pagePartRef instanceof PagePartRef && $pagePartRef->getSequencenumber() != ($i + 1)) {
270
                    $pagePartRef->setSequencenumber($i + 1);
271
                    $pagePartRef->setContext($this->context);
272
                    $this->em->persist($pagePartRef);
273
                }
274
                $pagePart = $pagePartRef->getPagePart($this->em);
275
            }
276
277
            if (isset($pagePart)) {
278
                $this->container->get('event_dispatcher')->dispatch(
279
                    Events::POST_PERSIST,
280
                    new PagePartEvent($pagePart)
281
                );
282
            }
283
        }
284
    }
285
286
    /**
287
     * @return string|null
288
     */
289
    public function getContext()
290
    {
291
        return $this->context;
292
    }
293
294
    /**
295
     * This getter returns an array holding info on page part types that can be added to the page.
296
     * The types are filtererd here, based on the amount of page parts of a certain type that can be added to the page.
297
     *
298
     * @return array
299
     */
300
    public function getPossiblePagePartTypes()
301
    {
302
        $possiblePPTypes = $this->configurator->getPossiblePagePartTypes();
303
        $result = array();
304
305
        // filter page part types that can only be added x times to the page context.
306
        // to achieve this, provide a 'pagelimit' parameter when adding the pp type in your PagePartAdminConfiguration
307
        if (!empty($possiblePPTypes)) {
308
            foreach ($possiblePPTypes as $possibleTypeData) {
309
                if (\array_key_exists('pagelimit', $possibleTypeData)) {
310
                    $pageLimit = $possibleTypeData['pagelimit'];
311
                    /** @var PagePartRefRepository $entityRepository */
312
                    $entityRepository = $this->em->getRepository(PagePartRef::class);
313
                    $formPPCount = $entityRepository->countPagePartsOfType(
314
                        $this->page,
315
                        $possibleTypeData['class'],
316
                        $this->configurator->getContext()
317
                    );
318
                    if ($formPPCount < $pageLimit) {
319
                        $result[] = $possibleTypeData;
320
                    }
321
                } else {
322
                    $result[] = $possibleTypeData;
323
                }
324
            }
325
        }
326
327
        return $result;
328
    }
329
330
    /**
331
     * @return string
332
     */
333
    public function getName()
334
    {
335
        return $this->configurator->getName();
336
    }
337
338
    /**
339
     * @return array
340
     */
341
    public function getPagePartMap()
342
    {
343
        return $this->pageParts;
344
    }
345
346
    /**
347
     * @param PagePartInterface $pagepart
348
     *
349
     * @return string
350
     */
351
    public function getType(PagePartInterface $pagepart)
352
    {
353
        $possiblePagePartTypes = $this->configurator->getPossiblePagePartTypes();
354
        foreach ($possiblePagePartTypes as &$pageparttype) {
355
            if ($pageparttype['class'] == ClassLookup::getClass($pagepart)) {
356
                return $pageparttype['name'];
357
            }
358
        }
359
360
        return 'no name';
361
    }
362
363
    /**
364
     * @param int $id
365
     * @param int $sequenceNumber
366
     *
367
     * @return PagePartInterface
368
     */
369
    public function getPagePart($id, $sequenceNumber)
370
    {
371
        /** @var PagePartRefRepository $ppRefRepo */
372
        $ppRefRepo = $this->em->getRepository(PagePartRef::class);
373
374
        return $ppRefRepo->getPagePart($id, $this->context, $sequenceNumber);
375
    }
376
377
    /**
378
     * @param object $pagepart
379
     *
380
     * @return string
381
     */
382
    public function getClassName($pagepart)
383
    {
384
        return \get_class($pagepart);
385
    }
386
}
387