AdminController::processForm()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4286
cc 1
eloc 5
nc 1
nop 3
1
<?php
2
3
namespace Ob\CmsBundle\Controller;
4
5
use Doctrine\Common\Persistence\ObjectManager;
6
use Ob\CmsBundle\Admin\AdminContainer;
7
use Ob\CmsBundle\Admin\AdminInterface;
8
use Ob\CmsBundle\Datagrid\DatagridInterface;
9
use Ob\CmsBundle\Event\CRUDEvent;
10
use Ob\CmsBundle\Event\FormEvent;
11
use Ob\CmsBundle\Export\ExporterInterface;
12
use Ob\CmsBundle\Form\AdminType;
13
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\Form\FormFactoryInterface;
16
use Symfony\Component\Form\FormInterface;
17
use Symfony\Component\HttpFoundation\RedirectResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\HttpFoundation\Session\SessionInterface;
21
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
22
use Symfony\Component\Routing\RouterInterface;
23
24
class AdminController
25
{
26
    /**
27
     * @var EngineInterface
28
     */
29
    private $templating;
30
31
    /**
32
     * @var ObjectManager
33
     */
34
    private $entityManager;
35
36
    /**
37
     * @var FormFactoryInterface
38
     */
39
    private $formFactory;
40
41
    /**
42
     * @var RouterInterface
43
     */
44
    private $router;
45
46
    /**
47
     * @var SessionInterface
48
     */
49
    private $session;
50
51
    /**
52
     * @var AdminContainer
53
     */
54
    private $container;
55
56
    /**
57
     * @var DatagridInterface
58
     */
59
    private $datagrid;
60
61
    /**
62
     * @var array
63
     */
64
    private $templates;
65
66
    /**
67
     * @var ExporterInterface
68
     */
69
    private $exporter;
70
71
    /**
72
     * @var EventDispatcherInterface
73
     */
74
    private $dispatcher;
75
76
    /**
77
     * @param EngineInterface          $templating
78
     * @param ObjectManager            $entityManager
79
     * @param FormFactoryInterface     $formFactory
80
     * @param RouterInterface          $router
81
     * @param SessionInterface         $session
82
     * @param AdminContainer           $container
83
     * @param DatagridInterface        $datagrid
84
     * @param array                    $templates
85
     * @param ExporterInterface        $exporter
86
     * @param EventDispatcherInterface $dispatcher
87
     */
88
    public function __construct(
89
        EngineInterface $templating,
90
        ObjectManager $entityManager,
91
        FormFactoryInterface $formFactory,
92
        RouterInterface $router,
93
        SessionInterface $session,
94
        AdminContainer $container,
95
        DatagridInterface $datagrid,
96
        $templates,
97
        ExporterInterface $exporter,
98
        EventDispatcherInterface $dispatcher
99
    ) {
100
        $this->templating    = $templating;
101
        $this->entityManager = $entityManager;
102
        $this->formFactory   = $formFactory;
103
        $this->router        = $router;
104
        $this->session       = $session;
105
        $this->container     = $container;
106
        $this->datagrid      = $datagrid;
107
        $this->templates     = $templates;
108
        $this->exporter      = $exporter;
109
        $this->dispatcher    = $dispatcher;
110
    }
111
112
    /**
113
     * Render the menu
114
     *
115
     * @param $request
116
     *
117
     * @return Response
118
     */
119
    public function menuAction(Request $request)
120
    {
121
        $menu = $this->container->getClasses();
122
123
        // Get the current module from the URI
124
        $current = explode('?', $request->server->get('REQUEST_URI'));
125
        $current = $current[0];
126
127
        return $this->templating->renderResponse($this->templates['menu'], array(
128
            'items'   => $menu,
129
            'flat'    => true,
130
            'current' => $current,
131
        ));
132
    }
133
134
    /**
135
     * Display the homepage/dashboard
136
     *
137
     * @return Response
138
     */
139
    public function dashboardAction()
140
    {
141
        return $this->templating->renderResponse($this->templates['dashboard']);
142
    }
143
144
    /**
145
     * @param string $name
146
     *
147
     * @return null|AdminInterface
148
     */
149
    private function getAdminClass($name)
150
    {
151
        if (!$adminClass = $this->container->getClass($name)) {
152
            throw new NotFoundHttpException();
153
        }
154
155
        return $adminClass;
156
    }
157
158
    /**
159
     * Display the listing page.
160
     * Handles searches, sorting, actions and pagination on the list of entities.
161
     *
162
     * @param Request $request
163
     * @param string  $name
164
     *
165
     * @return Response
166
     */
167
    public function listAction(Request $request, $name)
168
    {
169
        if ($this->executeAction($request, $name)) {
170
            return new RedirectResponse($this->router->generate('ObCmsBundle_module_list', array('name' => $name)));
171
        }
172
173
        $adminClass = $this->getAdminClass($name);
174
        $entities   = $this->datagrid->getPaginatedEntities($adminClass);
175
        $template   = $adminClass->listTemplate() ?: $this->templates['list'];
176
        $filters    = $this->datagrid->getFilters($adminClass);
177
178
        return $this->templating->renderResponse($template, array(
179
            'module'          => $name,
180
            'adminClass'      => $adminClass,
181
            'entities'        => $entities,
182
            'search'          => $request->query->get('search') ?: null,
183
            'filters'         => $filters,
184
            'selectedFilters' => $request->query->get('filter')
185
        ));
186
    }
187
188
    /**
189
     * Export the listing
190
     *
191
     * @param Request $request
192
     * @param string  $name
193
     * @param string  $format
194
     *
195
     * @return Response
196
     */
197
    public function exportAction(Request $request, $name, $format)
198
    {
199
        $adminClass = $this->getAdminClass($name);
200
        $entities   = $this->datagrid->getEntities($adminClass);
201
202
        $filename = $this->getExportFilename(
203
            $name,
204
            $this->datagrid->getFilters($adminClass),
205
            $request->query->get('filter', array()),
206
            $format
207
        );
208
209
        return $this->exporter->export($filename, $format, $entities, $adminClass->listExport());
210
    }
211
212
    /**
213
     * Builds a file name for the export from the admin class name and the datagrid filters
214
     *
215
     * @param string $className   The name of the admin class
216
     * @param array  $filterNames The list of all datagrid filters available for this admin class
217
     * @param array  $queryFilter The filters used
218
     * @param string $format      The file format to export (e.g. xls)
219
     *
220
     * @return string
221
     */
222
    private function getExportFilename($className, $filterNames, $queryFilter, $format)
223
    {
224
        $now      = new \DateTime();
225
        $filename = $now->format('Y-m-d-') . $className;
226
227
        foreach ($queryFilter as $filter => $value) {
228
            if ($value || $value == "0") {
229
                // The array key and the entity id are not the same,
230
                // so we need to loop through the array to find the
231
                // entity we are looking for.
232
                if (gettype($filterNames[$filter][$value]) == 'object') {
233
                    foreach ($filterNames[$filter] as $object) {
234
                        if ($object->getId() == $value) {
235
                            $filename .= '-' . strtolower($object->__toString());
236
                        }
237
                    }
238
                } else {
239
                    $filename .= '-' . strtolower($filterNames[$filter][$value]);
240
                }
241
            }
242
        }
243
244
        // Remove characters that are not "filename-safe"
245
        $filename = preg_replace('/(\s)/', '-', $filename);
246
        $filename = preg_replace('/([^\w\d\-_~\[\]\(\)])/u', '', $filename);
247
        $filename .= '.' . $format;
248
249
        return $filename;
250
    }
251
252
    /**
253
     * Display the form to create a new entity
254
     *
255
     * @param Request $request
256
     * @param string  $name
257
     *
258
     * @return Response|RedirectResponse
259
     */
260
    public function newAction(Request $request, $name)
261
    {
262
        $adminClass = $this->getAdminClass($name);
263
        $entity     = $adminClass->getClass();
264
        $entity     = new $entity();
265
266
        $this->dispatcher->dispatch('ob_cms.new.init', new CRUDEvent($request, $entity));
267
        $form = $this->getFormForAdmin($request, $adminClass, $entity);
268
        $this->dispatcher->dispatch('ob_cms.form.init', new FormEvent($form, $entity));
269
270
        if ($request->isMethod('POST')) {
271
            if ($form->submit($request)->isValid()) {
272
                $this->processForm($form, $adminClass, $entity);
273
                $this->session->getFlashBag()->add('success', $name . '.create.success');
274
275
                return new RedirectResponse($this->router->generate('ObCmsBundle_module_edit', array(
276
                    'name'    => $name,
277
                    'id'      => $entity->getId(),
278
                    'referer' => $this->getReferer($request, $form)
279
                )));
280
            }
281
        }
282
283
        $template = $adminClass->newTemplate() ?: $this->templates['new'];
284
285
        return $this->templating->renderResponse($template, array(
286
            'module'     => $name,
287
            'adminClass' => $adminClass,
288
            'entity'     => $entity,
289
            'form'       => $form->createView(),
290
            'referer'    => $this->getReferer($request, $form)
291
        ));
292
    }
293
294
    /**
295
     * Display the form to edit an entity
296
     *
297
     * @param Request $request
298
     * @param string  $name
299
     * @param int     $id
300
     *
301
     * @return Response
302
     *
303
     * @throws NotFoundHttpException
304
     */
305
    public function editAction(Request $request, $name, $id)
306
    {
307
        $adminClass = $this->getAdminClass($name);
308
309
        if (!$entity = $this->entityManager->getRepository($adminClass->getClass())->find($id)) {
310
            throw new NotFoundHttpException(sprintf('Unable to find %s entity.', $name));
311
        }
312
313
        $editForm = $this->getFormForAdmin($request, $adminClass, $entity);
314
        $this->dispatcher->dispatch('ob_cms.form.init', new FormEvent($editForm, $entity));
315
316
        if ($request->isMethod('POST')) {
317
            if ($editForm->submit($request)->isValid()) {
318
                $this->processForm($editForm, $adminClass, $entity);
319
                $this->session->getFlashBag()->add('success', $name . '.edit.success');
320
            }
321
        }
322
323
        $template = $adminClass->editTemplate() ?: $this->templates['edit'];
324
325
        return $this->templating->renderResponse($template, array(
326
            'module'     => $name,
327
            'adminClass' => $adminClass,
328
            'entity'     => $entity,
329
            'form'       => $editForm->createView(),
330
            'referer'    => $this->getReferer($request, $editForm)
331
        ));
332
    }
333
334
    /**
335
     * @param Request        $request
336
     * @param AdminInterface $adminClass
337
     * @param object         $entity
338
     *
339
     * @return FormInterface
340
     */
341
    private function getFormForAdmin(Request $request, AdminInterface $adminClass, $entity = null)
342
    {
343
        $formType = $adminClass->formType();
344
        $formType = $formType ? new $formType() : new AdminType($adminClass->formDisplay());
345
        $form     = $this->formFactory->create($formType, $entity);
346
        $form     = $this->addRefererField($request, $form);
347
348
        return $form;
349
    }
350
351
    private function processForm($form, AdminInterface $adminClass, $entity)
352
    {
353
        $adminClass->prePersist($entity, $form);
354
        $this->entityManager->persist($entity);
355
        $this->entityManager->flush();
356
        $adminClass->postPersist($entity, $form);
357
    }
358
359
    /**
360
     * @param Request       $request
361
     * @param FormInterface $form
362
     *
363
     * @return FormInterface
364
     */
365
    private function addRefererField(Request $request, FormInterface $form)
366
    {
367
        $referer = $this->getReferer($request, $form);
368
369
        $form->add('referer', 'hidden', array('mapped' => false));
370
        $form->get('referer')->setData($referer);
371
372
        return $form;
373
    }
374
375
    /**
376
     * @param Request       $request
377
     * @param FormInterface $form
378
     *
379
     * @return string
380
     */
381
    private function getReferer(Request $request, FormInterface $form)
382
    {
383
        if ($form->has('referer')) {
384
            $referer = $form->get('referer')->getData();
385
        } elseif ($request->query->has('referer')) {
386
            $referer = $request->query->get('referer');
387
        } else {
388
            $referer = $request->headers->get("referer");
389
        }
390
391
        return $referer;
392
    }
393
394
    /**
395
     * Executes an action on selected table rows
396
     *
397
     * @param Request $request
398
     * @param string  $name
399
     *
400
     * @return bool
401
     */
402
    private function executeAction(Request $request, $name)
403
    {
404
        $adminClass = $this->getAdminClass($name);
405
406
        if ($request->getMethod() == 'POST') {
407
            $action = $request->get('action');
408
            $ids    = array_keys($request->get('action-checkbox', array()));
409
410
            if (!empty($ids) && $action != '') {
411
                $entities = $this->entityManager->getRepository($adminClass->getClass())->findBy(array('id' => $ids));
412
413
                foreach ($entities as $entity) {
414
                    if ($action == 'delete-action') {
415
                        $this->entityManager->remove($entity);
416
                    } else {
417
                        $entity = $this->executeActionOnAdminOrEntity($adminClass, $entity, $action);
418
                        $this->entityManager->persist($entity);
419
                    }
420
                }
421
                $this->entityManager->flush();
422
423
                return true;
424
            }
425
        }
426
427
        return false;
428
    }
429
430
    /**
431
     * @param AdminInterface $adminClass
432
     * @param object         $entity
433
     * @param string         $action
434
     *
435
     * @return mixed
436
     */
437
    private function executeActionOnAdminOrEntity(AdminInterface $adminClass, $entity, $action)
438
    {
439
        if (method_exists($adminClass, $action)) {
440
            $entity = $adminClass->{$action}($entity);
441
        } else {
442
            if (!method_exists($entity, $action)) {
443
                throw new \InvalidArgumentException(sprintf('The method %s does not exist on entity', $action));
444
            }
445
446
            $entity->{$action}();
447
        }
448
449
        return $entity;
450
    }
451
}
452