AdminController::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 1 Features 2
Metric Value
c 8
b 1
f 2
dl 0
loc 23
rs 9.0857
cc 1
eloc 21
nc 1
nop 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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