Completed
Push — master ( 0eab77...b2f729 )
by Paul
05:35
created

WidgetRenderer::render()   C

Complexity

Conditions 7
Paths 10

Size

Total Lines 40
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 40
rs 6.7272
cc 7
eloc 16
nc 10
nop 2
1
<?php
2
3
namespace Victoire\Bundle\WidgetBundle\Renderer;
4
5
use Doctrine\ORM\EntityManager;
6
use Symfony\Component\DependencyInjection\Container;
7
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessPage;
8
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessTemplate;
9
use Victoire\Bundle\BusinessPageBundle\Helper\BusinessPageHelper;
10
use Victoire\Bundle\CoreBundle\DataCollector\VictoireCollector;
11
use Victoire\Bundle\CoreBundle\Entity\View;
12
use Victoire\Bundle\CoreBundle\Event\WidgetRenderEvent;
13
use Victoire\Bundle\CoreBundle\VictoireCmsEvents;
14
use Victoire\Bundle\ORMBusinessEntityBundle\Entity\ORMBusinessEntity;
15
use Victoire\Bundle\WidgetBundle\Cache\WidgetCache;
16
use Victoire\Bundle\WidgetBundle\Entity\Widget;
17
use Victoire\Bundle\WidgetBundle\Helper\WidgetHelper;
18
use Victoire\Bundle\WidgetMapBundle\Entity\Slot;
19
use Victoire\Bundle\WidgetMapBundle\Helper\WidgetMapHelper;
20
21
class WidgetRenderer
22
{
23
    private $container;
24
    /**
25
     * @var WidgetCache
26
     */
27
    private $widgetCache;
28
    /**
29
     * @var WidgetHelper
30
     */
31
    private $widgetHelper;
32
    /**
33
     * @var VictoireCollector
34
     */
35
    private $victoireCollector;
36
    /**
37
     * @var BusinessPageHelper
38
     */
39
    private $bepHelper;
40
41
    /**
42
     * WidgetRenderer constructor.
43
     *
44
     * @param Container          $container
45
     * @param WidgetCache        $widgetCache
46
     * @param WidgetHelper       $widgetHelper
47
     * @param VictoireCollector  $victoireCollector
48
     * @param BusinessPageHelper $bepHelper
49
     *
50
     * @internal param Client $redis
51
     */
52
    public function __construct(Container $container, WidgetCache $widgetCache, WidgetHelper $widgetHelper, VictoireCollector $victoireCollector, BusinessPageHelper $bepHelper)
53
    {
54
        $this->container = $container;
55
        $this->widgetCache = $widgetCache;
56
        $this->widgetHelper = $widgetHelper;
57
        $this->victoireCollector = $victoireCollector;
58
        $this->bepHelper = $bepHelper;
59
    }
60
61
    /**
62
     * render the Widget.
63
     *
64
     * @param Widget $widget
65
     * @param View   $view
66
     *
67
     * @return widget show
68
     */
69
    public function render(Widget $widget, View $view)
70
    {
71
        //the mode of display of the widget
72
        $mode = $widget->getMode();
73
74
        //if entity is given and it's not the object, retrieve it and set the entity for the widget
75
        if ($mode == Widget::MODE_BUSINESS_ENTITY && $view instanceof BusinessPage) {
76
            $widget->setEntity($view->getEntity());
77
        } elseif ($view instanceof BusinessTemplate) {
78
            //We'll try to find a sample entity to mock the widget behavior
79
            /** @var EntityManager $entityManager */
80
            $entityManager = $this->container->get('doctrine.orm.entity_manager');
81
            if ($view->getBusinessEntity()->getType() === ORMBusinessEntity::TYPE) {
82
                if ($mock = $this->bepHelper->getEntitiesAllowedQueryBuilder($view, $entityManager)->setMaxResults(1)->getQuery()->getOneOrNullResult()) {
83
                    $widget->setEntity($mock);
84
                }
85
            }
86
        }
87
88
        //the templating service
89
        $templating = $this->container->get('templating');
90
91
        //the content of the widget
92
93
        $parameters = $this->container->get('victoire_widget.widget_content_resolver')->getWidgetContent($widget);
94
        /*
95
         * In some cases, for example, WidgetRender in BusinessEntity mode with magic variables {{entity.id}} transformed
96
         * into the real business entity id, then if in the rendered action, we need to flush, it would persist the
97
         * modified widget which really uncomfortable ;)
98
         */
99
        if ($widget->getMode() == Widget::MODE_BUSINESS_ENTITY) {
100
            $this->container->get('doctrine.orm.entity_manager')->refresh($widget);
101
        }
102
103
        //the template displayed is in the widget bundle (with the potential theme)
104
        $showView = 'show'.ucfirst($widget->getTheme());
105
        $templateName = $this->container->get('victoire_widget.widget_helper')->getTemplateName($showView, $widget);
106
107
        return $templating->render($templateName, $parameters);
108
    }
109
110
    /**
111
     * render a widget.
112
     *
113
     * @param Widget $widget
114
     * @param View   $view
115
     *
116
     * @return string
117
     */
118
    public function renderContainer(Widget $widget, View $view)
119
    {
120
        $dispatcher = $this->container->get('event_dispatcher');
121
122
        $dispatcher->dispatch(VictoireCmsEvents::WIDGET_PRE_RENDER, new WidgetRenderEvent($widget));
123
124
        $widgetMap = WidgetMapHelper::getWidgetMapByWidgetAndView($widget, $view);
125
126
        $directive = '';
127
        if ($this->container->get('security.authorization_checker')->isGranted('ROLE_VICTOIRE')) {
128
            $directive = 'widget';
129
        }
130
131
        $id = 'vic-widget-'.$widget->getId().'-container';
132
133
        $html = sprintf('<div %s widget-map="%s" id="%s" class="vic-widget-container" data-id="%s">', $directive, $widgetMap->getId(), $id, $widget->getId());
0 ignored issues
show
Bug introduced by
The method getId 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...
134
135
        if ($this->widgetHelper->isCacheEnabled($widget)) {
136
            $content = $this->widgetCache->fetch($widget);
137
            if (null === $content) {
138
                $content = $this->render($widget, $view);
139
                $this->widgetCache->save($widget, $content);
140
            } else {
141
                $this->victoireCollector->addCachedWidget($widget);
142
            }
143
        } else {
144
            $content = $this->render($widget, $view);
145
        }
146
        $html .= $content;
147
        $html .= '</div>'; //close container
148
149
        $dispatcher->dispatch(VictoireCmsEvents::WIDGET_POST_RENDER, new WidgetRenderEvent($widget, $html));
150
151
        return $html;
152
    }
153
154
    /**
155
     * prepare a widget to be rendered asynchronously.
156
     *
157
     * @param int $widgetId
158
     *
159
     * @return string
160
     */
161
    public function prepareAsynchronousRender($widgetId)
162
    {
163
        $ngControllerName = 'widget'.$widgetId.'AsynchronousLoadCtrl';
164
        $ngDirectives = sprintf('ng-controller="WidgetAsynchronousLoadController as %s" class="vic-widget" ng-init="%s.init(%d)" ng-bind-html="html"', $ngControllerName, $ngControllerName, $widgetId);
165
        $html = sprintf('<div class="vic-widget-container vic-widget-asynchronous" data-id="%d" %s></div>', $widgetId, $ngDirectives);
166
167
        return $html;
168
    }
169
170
    /**
171
     * render widget unlink action.
172
     *
173
     * @param int  $widgetId
174
     * @param View $view
175
     *
176
     * @return string
177
     */
178
    public function renderUnlinkActionByWidgetId($widgetId, $view)
179
    {
180
        return $this->container->get('templating')->render(
181
            'VictoireCoreBundle:Widget:widgetUnlinkAction.html.twig',
182
            [
183
                'widgetId' => $widgetId,
184
                'view'     => $view,
185
            ]
186
        );
187
    }
188
189
    /**
190
     * Compute slot options.
191
     *
192
     * @param int   $slotId
193
     * @param array $options
194
     *
195
     * @return string
196
     */
197
    public function computeOptions($slotId, $options = [])
198
    {
199
        $slots = $this->container->getParameter('victoire_core.slots');
200
201
        $availableWidgets = $this->container->getParameter('victoire_core.widgets');
202
        $widgets = [];
203
204
        //If the slot is declared in config
205
        if (!empty($slots[$slotId]) && !empty($slots[$slotId]['widgets'])) {
206
            //parse declared widgets
207
            $slotWidgets = array_keys($slots[$slotId]['widgets']);
208
        } elseif (!empty($options['availableWidgets'])) {
209
            $slotWidgets = $options['availableWidgets'];
210
        } else {
211
            //parse all widgets
212
            $slotWidgets = array_keys($availableWidgets);
213
        }
214
215
        foreach ($slotWidgets as $slotWidget) {
216
            $widgetParams = $availableWidgets[$slotWidget];
217
            $widgets[$slotWidget]['params'] = $widgetParams;
218
        }
219
        $slots[$slotId]['availableWidgets'] = $widgets;
220
        if (isset($options['max'])) {
221
            $slots[$slotId]['max'] = $options['max'];
222
        }
223
224
        return $slots[$slotId];
225
    }
226
227
    /**
228
     * Get the extra classes for the css.
229
     *
230
     * @return string The classes
231
     */
232
    public function getExtraCssClass(Widget $widget)
233
    {
234
        $cssClass = 'v-widget--'.strtolower($this->container->get('victoire_widget.widget_helper')->getWidgetName($widget));
235
236
        return $cssClass;
237
    }
238
}
239