Completed
Pull Request — master (#343)
by Leny
16:04 queued 08:22
created

WidgetController::stylizeAction()   C

Complexity

Conditions 9
Paths 26

Size

Total Lines 69
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 69
rs 6.2192
cc 9
eloc 45
nc 26
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Victoire\Bundle\WidgetBundle\Controller;
4
5
use Exception;
6
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
7
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
8
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
9
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
10
use Symfony\Component\HttpFoundation\JsonResponse;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessTemplate;
14
use Victoire\Bundle\CoreBundle\Controller\VictoireAlertifyControllerTrait;
15
use Victoire\Bundle\ViewReferenceBundle\ViewReference\ViewReference;
16
use Victoire\Bundle\WidgetBundle\Entity\Widget;
17
use Victoire\Bundle\WidgetBundle\Form\WidgetStyleType;
18
use Victoire\Bundle\WidgetMapBundle\Exception\WidgetMapNotFoundException;
19
use Victoire\Bundle\WidgetMapBundle\Helper\WidgetMapHelper;
20
21
/**
22
 * Widget Controller.
23
 */
24
class WidgetController extends Controller
25
{
26
    use VictoireAlertifyControllerTrait;
27
28
    /**
29
     * Show a widget.
30
     *
31
     * @param Request $request
32
     * @param Widget  $widget
33
     * @param int     $viewReferenceId
34
     *
35
     * @Route("/victoire-dcms-public/widget/show/{id}/{viewReferenceId}", name="victoire_core_widget_show", options={"expose"=true})
36
     * @Template()
37
     * @ParamConverter("id", class="VictoireWidgetBundle:Widget")
38
     *
39
     * @throws Exception
40
     *
41
     * @return Response
42
     */
43
    public function showAction(Request $request, Widget $widget, $viewReferenceId)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
44
    {
45
        //the response is for the ajax.js from the AppVentus Ajax Bundle
46
        try {
47
            $view = $this->container->get('victoire_page.page_helper')->findPageByParameters(['id' => $viewReferenceId]);
48
            $this->container->get('victoire_core.current_view')->setCurrentView($view);
49
            $response = new JsonResponse([
50
                    'html'    => $this->get('victoire_widget.widget_renderer')->render($widget, $view),
51
                    'update'  => 'vic-widget-'.$widget->getId().'-container',
52
                    'success' => false,
53
                ]
54
            );
55
        } catch (Exception $ex) {
56
            $response = $this->getJsonReponseFromException($ex);
57
        }
58
59
        return $response;
60
    }
61
62
    /**
63
     * API widgets function.
64
     *
65
     * @param string $widgetIds       the widget ids to fetch in json
66
     * @param int    $viewReferenceId
67
     *
68
     * @Route("/victoire-dcms-public/api/widgets/{widgetIds}/{viewReferenceId}", name="victoire_core_widget_apiWidgets", options={"expose"=true})
69
     *
70
     * @return JsonResponse
71
     */
72
    public function apiWidgetsAction($widgetIds, $viewReferenceId)
73
    {
74
        $view = $this->container->get('victoire_page.page_helper')->findPageByParameters(['id' => $viewReferenceId]);
75
        $response = [];
76
        $widgets = $this->get('doctrine.orm.entity_manager')->getRepository('VictoireWidgetBundle:Widget')
77
            ->findBy(['id' => json_decode($widgetIds)]);
78
79
        foreach ($widgets as $widget) {
80
            $response[$widget->getId()] = $this->get('victoire_widget.widget_renderer')->render($widget, $view);
81
        }
82
83
        return new JsonResponse($response);
84
    }
85
86
    /**
87
     * New Widget.
88
     *
89
     * @param string $type          The type of the widget we edit
90
     * @param int    $viewReference The view reference where attach the widget
91
     * @param string $slot          The slot where attach the widget
92
     *
93
     * @return JsonResponse
94
     *
95
     * @Route("/victoire-dcms/widget/new/{type}/{viewReference}/{slot}/{position}/{parentWidgetMap}", name="victoire_core_widget_new", defaults={"slot":null, "position":null, "parentWidgetMap":null}, options={"expose"=true})
96
     * @Template()
97
     */
98
    public function newAction($type, $viewReference, $slot = null, $position = null, $parentWidgetMap = null)
99
    {
100
        try {
101
            $view = $this->getViewByReferenceId($viewReference);
102
103 View Code Duplication
            if (!$reference = $this->container->get('victoire_view_reference.repository')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
104
                ->getOneReferenceByParameters(['id' => $viewReference])) {
105
                $reference = new ViewReference($viewReference);
106
            }
107
            $view->setReference($reference);
108
109
            $response = new JsonResponse(
110
                $this->get('victoire_widget.widget_manager')->newWidget(Widget::MODE_STATIC, $type, $slot, $view, $position, $parentWidgetMap)
111
            );
112
        } catch (Exception $ex) {
113
            $response = $this->getJsonReponseFromException($ex);
114
        }
115
116
        return $response;
117
    }
118
119
    /**
120
     * Create a widget.
121
     * This action needs 2 routes to handle the presence or not of "businessEntityId" and 'parentWidgetMap'
122
     * that are both integers but "businessEntityId" present only in !static mode.
123
     *
124
     * @param string $type             The type of the widget we edit
125
     * @param int    $viewReference    The view reference where attach the widget
126
     * @param string $slot             The slot where attach the widget
127
     * @param string $businessEntityId The BusinessEntity::id (can be null if the submitted form is in static mode)
128
     *
129
     * @return JsonResponse
130
     * @Route("/victoire-dcms/widget/create/static/{type}/{viewReference}/{slot}/{position}/{parentWidgetMap}", name="victoire_core_widget_create_static", defaults={"mode":"static", "slot":null, "businessEntityId":null, "position":null, "parentWidgetMap":null, "_format": "json"})
131
     * @Route("/victoire-dcms/widget/create/{mode}/{type}/{viewReference}/{slot}/{businessEntityId}/{position}/{parentWidgetMap}", name="victoire_core_widget_create", defaults={"slot":null, "businessEntityId":null, "position":null, "parentWidgetMap":null, "_format": "json"})
132
     * @Template()
133
     */
134
    public function createAction($mode, $type, $viewReference, $slot = null, $position = null, $parentWidgetMap = null, $businessEntityId = null)
135
    {
136
        try {
137
            //services
138
            $view = $this->getViewByReferenceId($viewReference);
139
140
            $isNewPage = $view->getId() === null ? true : false;
141
142 View Code Duplication
            if (!$reference = $this->container->get('victoire_view_reference.repository')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
                ->getOneReferenceByParameters(['id' => $viewReference])) {
144
                $reference = new ViewReference($viewReference);
145
            }
146
147
            $view->setReference($reference);
148
            $this->get('victoire_core.current_view')->setCurrentView($view);
149
150
            $this->congrat($this->get('translator')->trans('victoire.success.message', [], 'victoire'));
151
            $response = $this->get('widget_manager')->createWidget($mode, $type, $slot, $view, $businessEntityId, $position, $parentWidgetMap);
152
153
            if ($isNewPage) {
154
                $response = new JsonResponse([
155
                    'success'  => true,
156
                    'redirect' => $this->generateUrl(
157
                        'victoire_core_page_show',
158
                        [
159
                            'url' => $reference->getUrl(),
160
                        ]
161
                    ),
162
                ]);
163
            } else {
164
                $response = new JsonResponse($response);
165
            }
166
        } catch (Exception $ex) {
167
            $response = $this->getJsonReponseFromException($ex);
168
        }
169
170
        return $response;
171
    }
172
173
    /**
174
     * Edit a widget.
175
     *
176
     * @param Widget $widget           The widget to edit
177
     * @param int    $viewReference    The current view
178
     * @param string $businessEntityId The BusinessEntity::id (can be null if the submitted form is in static mode)
179
     *
180
     * @return JsonResponse
181
     *
182
     * @Route("/victoire-dcms/widget/edit/{id}/{viewReference}/{mode}/{businessEntityId}", name="victoire_core_widget_edit", options={"expose"=true})
183
     * @Route("/victoire-dcms/widget/update/{id}/{viewReference}/{mode}/{businessEntityId}", name="victoire_core_widget_update", defaults={"businessEntityId": null})
184
     * @Template()
185
     */
186
    public function editAction(Widget $widget, $viewReference, $mode = Widget::MODE_STATIC, $businessEntityId = null)
187
    {
188
        $view = $this->getViewByReferenceId($viewReference);
189
        $this->get('victoire_widget_map.builder')->build($view, $this->get('doctrine.orm.entity_manager'));
190
        $widgetView = WidgetMapHelper::getWidgetMapByWidgetAndView($widget, $view)->getView();
0 ignored issues
show
Bug introduced by
The method getView does only exist in Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap, but not in Victoire\Bundle\WidgetMa...getMapNotFoundException.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
191
        $this->get('victoire_widget_map.widget_data_warmer')->warm($this->getDoctrine()->getManager(), $view);
192
193
        if ($view instanceof BusinessTemplate && !$reference = $this->get('victoire_view_reference.repository')
194
            ->getOneReferenceByParameters(['viewId' => $view->getId()])) {
195
            $reference = new ViewReference($viewReference);
196
            $widgetView->setReference($reference);
197
        }
198
        $widget->setCurrentView($widgetView);
199
        $this->get('victoire_core.current_view')->setCurrentView($view);
200
        try {
201
            $response = new JsonResponse(
202
                $this->get('widget_manager')->editWidget(
203
                    $this->get('request'),
204
                    $widget,
205
                    $view,
206
                    $businessEntityId,
207
                    $mode
208
                )
209
            );
210
211
            $this->congrat($this->get('translator')->trans('victoire.success.message', [], 'victoire'));
212
        } catch (Exception $ex) {
213
            $response = $this->getJsonReponseFromException($ex);
214
        }
215
216
        return $response;
217
    }
218
219
    /**
220
     * Stylize a widget.
221
     *
222
     * @param Widget $widget        The widget to stylize
223
     * @param int    $viewReference The current view
224
     *
225
     * @return JsonResponse
226
     *
227
     * @Route("/victoire-dcms/widget/stylize/{id}/{viewReference}", name="victoire_core_widget_stylize", options={"expose"=true})
228
     * @Template()
229
     */
230
    public function stylizeAction(Request $request, Widget $widget, $viewReference)
231
    {
232
        $view = $this->getViewByReferenceId($viewReference);
233
        $this->get('victoire_widget_map.builder')->build($view, $this->get('doctrine.orm.entity_manager'));
234
235
        try {
236
            $widgetView = WidgetMapHelper::getWidgetMapByWidgetAndView($widget, $view)->getView();
0 ignored issues
show
Bug introduced by
The method getView does only exist in Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap, but not in Victoire\Bundle\WidgetMa...getMapNotFoundException.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
237
        } catch (WidgetMapNotFoundException $e) {
238
            return new JsonResponse([
239
                'success' => false,
240
                'message' => $e->getMessage(),
241
            ]);
242
        }
243
244
        $widgetViewReference = $this->container->get('victoire_view_reference.repository')
245
            ->getOneReferenceByParameters(['viewId' => $view->getId()]);
246
247
        $widgetView->setReference($widgetViewReference);
248
        $this->get('victoire_core.current_view')->setCurrentView($view);
249
        try {
250
            $form = $this->get('form.factory')->create(WidgetStyleType::class, $widget, [
251
                    'method' => 'POST',
252
                    'action' => $this->generateUrl(
253
                        'victoire_core_widget_stylize',
254
                        [
255
                            'id'            => $widget->getId(),
256
                            'viewReference' => $viewReference,
257
                        ]
258
                    ),
259
                ]
260
            );
261
            $form->handleRequest($this->get('request'));
262
263
            if ($request->query->get('novalidate', false) === false && $form->isValid()) {
264
                if ($form->has('deleteBackground') && $form->get('deleteBackground')->getData()) {
265
                    // @todo: dynamic responsive key
266
                    foreach (['', 'XS', 'SM', 'MD', 'LG'] as $key) {
267
                        $widget->{'deleteBackground'.$key}();
268
                    }
269
                }
270
                $this->get('doctrine.orm.entity_manager')->flush();
271
                $params = [
272
                    'view'        => $view,
273
                    'success'     => true,
274
                    'html'        => $this->get('victoire_widget.widget_renderer')->render($widget, $view),
275
                    'widgetId'    => $widget->getId(),
276
                    'viewCssHash' => $view->getCssHash(),
277
                ];
278
            } else {
279
                $template = ($request->query->get('novalidate', false) !== false) ? 'VictoireCoreBundle:Widget/Form/stylize:form.html.twig' : 'VictoireCoreBundle:Widget/Form:stylize.html.twig';
280
                $params = [
281
                    'success'  => !$form->isSubmitted(),
282
                    'html'     => $this->get('victoire_core.template_mapper')->render(
283
                        $template,
284
                        [
285
                            'view'   => $view,
286
                            'form'   => $form->createView(),
287
                            'widget' => $widget,
288
                        ]
289
                    ),
290
                ];
291
            }
292
            $response = new JsonResponse($params);
293
        } catch (Exception $ex) {
294
            $response = $this->getJsonReponseFromException($ex);
295
        }
296
297
        return $response;
298
    }
299
300
    /**
301
     * Delete a Widget.
302
     *
303
     * @param Widget $widget        The widget to delete
304
     * @param int    $viewReference The current view
305
     *
306
     * @return JsonResponse response
307
     * @Route("/victoire-dcms/widget/delete/{id}/{viewReference}", name="victoire_core_widget_delete", defaults={"_format": "json"})
308
     * @Template()
309
     */
310
    public function deleteAction(Widget $widget, $viewReference)
311
    {
312
        $view = $this->getViewByReferenceId($viewReference);
313
        try {
314
            $widgetId = $widget->getId();
315
            $this->get('widget_manager')->deleteWidget($widget, $view);
316
317
            return new JsonResponse([
318
                    'success'  => true,
319
                    'message'  => $this->get('translator')->trans('victoire_widget.delete.success', [], 'victoire'),
320
                    'widgetId' => $widgetId,
321
                ]
322
            );
323
        } catch (Exception $ex) {
324
            return $this->getJsonReponseFromException($ex);
325
        }
326
    }
327
328
    /**
329
     * Unlink a Widget by id
330
     * -> used to unlink an invalid widget after a bad widget unplug.
331
     *
332
     * @param int $id            The widgetId to unlink
333
     * @param int $viewReference The current viewReference
334
     *
335
     * @return JsonResponse response
336
     * @Route("/victoire-dcms/widget/unlink/{id}/{viewReference}", name="victoire_core_widget_unlink", defaults={"_format": "json"}, options={"expose"=true})
337
     * @Template()
338
     */
339
    public function unlinkAction($id, $viewReference)
340
    {
341
        $view = $this->getViewByReferenceId($viewReference);
342
        try {
343
            $this->get('victoire_widget.widget_helper')->deleteById($id);
344
            $this->get('doctrine.orm.entity_manager')->flush();
345
346
            if ($view instanceof Template) {
347
                $redirect = $this->generateUrl('victoire_template_show', ['slug' => $view->getSlug()]);
0 ignored issues
show
Bug introduced by
The method getSlug() does not seem to exist on object<Sensio\Bundle\Fra...Configuration\Template>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
348
            } elseif ($view instanceof BusinessTemplate) {
349
                $redirect = $this->generateUrl('victoire_business_template_show', ['id' => $view->getId()]);
350
            } else {
351
                $viewReference = $this->container->get('victoire_view_reference.repository')
352
                    ->getOneReferenceByParameters(['viewId' => $view->getId()]);
353
354
                $redirect = $this->generateUrl('victoire_core_page_show', [
355
                        'url' => $viewReference->getUrl(),
356
                    ]);
357
            }
358
359
            return new JsonResponse([
360
                    'success'  => true,
361
                    'redirect' => $redirect,
362
                ]);
363
        } catch (Exception $ex) {
364
            return $this->getJsonReponseFromException($ex);
365
        }
366
    }
367
368
    /**
369
     * Update widget positions accross the view. If moved widget is a Reference, ask to detach the view from template.
370
     *
371
     * @param int $viewReference The current viewReference
372
     *
373
     * @return JsonResponse
374
     * @Route("/victoire-dcms/widget/updatePosition/{viewReference}", name="victoire_core_widget_update_position", options={"expose"=true})
375
     */
376
    public function updatePositionAction(Request $request, $viewReference)
377
    {
378
        $view = $this->getViewByReferenceId($viewReference);
379
        try {
380
            //the sorted order for the widgets
381
            $sortedWidget = $request->get('sorted');
382
            $em = $this->get('doctrine.orm.entity_manager');
383
            if (!$view->getId()) {
384
                //This view does not have an id, so it's a non persisted BEP. To keep this new order, well have to persist it.
385
                $em->persist($view);
386
                $em->flush();
387
            }
388
            $this->get('victoire_widget_map.builder')->build($view);
389
            //recompute the order for the widgets
390
            $this->get('victoire_widget_map.manager')->move($view, $sortedWidget);
391
            $em->flush();
392
393
            $this->get('victoire_widget_map.builder')->build($view);
394
            $availablePositions = $this->get('victoire_widget_map.builder')->getAvailablePosition($view);
395
396
            $response = new JsonResponse(['success' => true, 'availablePositions' => $availablePositions]);
397
        } catch (Exception $ex) {
398
            $response = $this->getJsonReponseFromException($ex);
399
        }
400
401
        return $response;
402
    }
403
404
    /**
405
     * Update widget positions accross the view. If moved widget is a Reference, ask to detach the view from template.
406
     *
407
     * @param int $viewReference The current viewReference
408
     *
409
     * @return JsonResponse
410
     * @Route("/victoire-dcms/widget/get-available-positions/{viewReference}", name="victoire_core_widget_get_available_positions", options={"expose"=true})
411
     */
412
    public function getAvailablePositionsAction(Request $request, $viewReference)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
413
    {
414
        $view = $this->getViewByReferenceId($viewReference);
415
416
        $this->get('victoire_widget_map.builder')->build($view);
417
        $availablePositions = $this->get('victoire_widget_map.builder')->getAvailablePosition($view);
418
419
        return new JsonResponse($availablePositions);
420
    }
421
422
    /**
423
     * Get the json response by the exception and the current user.
424
     *
425
     * @param Exception $ex
426
     *
427
     * @return JsonResponse
428
     */
429
    protected function getJsonReponseFromException(Exception $ex)
430
    {
431
        //services
432
        $securityContext = $this->get('security.context');
433
        $logger = $this->get('logger');
434
435
        //can we see the debug
436
        $isDebugAllowed = $securityContext->isGranted('ROLE_VICTOIRE_PAGE_DEBUG');
437
438
        //whatever is the exception, we log it
439
        $logger->error($ex->getMessage());
440
        $logger->error($ex->getTraceAsString());
441
442
        if ($isDebugAllowed) {
443
            throw $ex;
444
        } else {
445
            //translate the message
446
            $translator = $this->get('translator');
447
448
            //get the translated message
449
            $message = $translator->trans('error_occured', [], 'victoire');
450
451
            $response = new JsonResponse(
452
                [
453
                    'success' => false,
454
                    'message' => $message,
455
                ]
456
            );
457
        }
458
459
        return $response;
460
    }
461
462
    /**
463
     * @param int $referenceId
464
     */
465
    protected function getViewByReferenceId($referenceId)
466
    {
467
        return $this->get('victoire_page.page_helper')->findPageByParameters(['id' => $referenceId]);
468
    }
469
}
470