Completed
Pull Request — master (#325)
by Paul
09:55
created

CmsExtension::hash()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4285
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
3
namespace Victoire\Bundle\CoreBundle\Twig\Extension;
4
5
use Symfony\Component\Security\Core\SecurityContext;
6
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessPage;
7
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessTemplate;
8
use Victoire\Bundle\BusinessPageBundle\Entity\VirtualBusinessPage;
9
use Victoire\Bundle\CoreBundle\Entity\View;
10
use Victoire\Bundle\CoreBundle\Handler\WidgetExceptionHandler;
11
use Victoire\Bundle\CoreBundle\Helper\CurrentViewHelper;
12
use Victoire\Bundle\CoreBundle\Template\TemplateMapper;
13
use Victoire\Bundle\ViewReferenceBundle\Connector\ViewReferenceRepository;
14
use Victoire\Bundle\ViewReferenceBundle\ViewReference\ViewReference;
15
use Victoire\Bundle\WidgetBundle\Entity\Widget;
16
use Victoire\Bundle\WidgetBundle\Renderer\WidgetRenderer;
17
use Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap;
18
19
/**
20
 * CmsExtension extends Twig with view capabilities.
21
 *
22
 * service: victoire_core.twig.cms_extension
23
 */
24
class CmsExtension extends \Twig_Extension_Core
25
{
26
    protected $widgetRenderer;
27
    protected $templating;
28
    protected $securityContext;
29
    protected $widgetMapBuilder;
30
    protected $widgetExceptionHandler;
31
    protected $currentViewHelper;
32
    protected $twig;
33
34
    /**
35
     * Constructor.
36
     *
37
     * @param WidgetRenderer          $widgetRenderer
38
     * @param TemplateMapper          $templating
39
     * @param SecurityContext         $securityContext
40
     * @param WidgetExceptionHandler  $widgetExceptionHandler
41
     * @param CurrentViewHelper       $currentViewHelper
42
     * @param ViewReferenceRepository $viewReferenceRepository
43
     * @param \Twig_Environment       $twig
44
     */
45
    public function __construct(
46
        WidgetRenderer $widgetRenderer,
47
        TemplateMapper $templating,
48
        SecurityContext $securityContext,
49
        WidgetExceptionHandler $widgetExceptionHandler,
50
        CurrentViewHelper $currentViewHelper,
51
        ViewReferenceRepository $viewReferenceRepository,
52
        \Twig_Environment $twig
53
    ) {
54
        $this->widgetRenderer = $widgetRenderer;
55
        $this->templating = $templating;
56
        $this->securityContext = $securityContext;
57
        $this->widgetExceptionHandler = $widgetExceptionHandler;
58
        $this->currentViewHelper = $currentViewHelper;
59
        $this->viewReferenceRepository = $viewReferenceRepository;
0 ignored issues
show
Bug introduced by
The property viewReferenceRepository does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
60
        $this->twig = $twig;
61
    }
62
63
    /**
64
     * register twig functions.
65
     *
66
     * @return \Twig_SimpleFunction[] The list of extensions
67
     */
68
    public function getFunctions()
69
    {
70
        return [
71
            new \Twig_SimpleFunction('cms_widget_unlink_action', [$this, 'cmsWidgetUnlinkAction'], ['is_safe' => ['html']]),
72
            new \Twig_SimpleFunction('cms_slot_widgets', [$this, 'cmsSlotWidgets'], ['is_safe' => ['html']]),
73
            new \Twig_SimpleFunction('cms_slot_actions', [$this, 'cmsSlotActions'], ['is_safe' => ['html']]),
74
            new \Twig_SimpleFunction('cms_widget', [$this, 'cmsWidget'], ['is_safe' => ['html']]),
75
            new \Twig_SimpleFunction('cms_widget_extra_css_class', [$this, 'cmsWidgetExtraCssClass'], ['is_safe' => ['html']]),
76
            new \Twig_SimpleFunction('is_business_entity_allowed', [$this, 'isBusinessEntityAllowed'], ['is_safe' => ['html']]),
77
        ];
78
    }
79
80
    /**
81
     * register twig filters.
82
     *
83
     * @return \Twig_SimpleFilter[] The list of filters
84
     */
85
    public function getFilters()
86
    {
87
        return [
88
            new \Twig_SimpleFilter('hash', [$this, 'hash']),
89
            new \Twig_SimpleFilter('date', [$this, 'twigVicDateFormatFilter']),
90
91
        ];
92
    }
93
94
    /**
95
     * get extension name.
96
     *
97
     * @return string The name
98
     */
99
    public function getName()
100
    {
101
        return 'cms';
102
    }
103
104
    /**
105
     * render unlink action for a widgetId.
106
     *
107
     * @param int $widgetId The widgetId to unlink
108
     *
109
     * @return string the widget unlink action
110
     */
111
    public function cmsWidgetUnlinkAction($widgetId, $view)
112
    {
113
        $viewReference = $this->viewReferenceRepository->getOneReferenceByParameters(
114
            ['viewId' => $view->getId()]
115
        );
116
        if (!$viewReference && $view->getId() != '') {
117
            $viewReference = new ViewReference($view->getId());
118
        } elseif ($view instanceof VirtualBusinessPage) {
119
            $viewReference = new ViewReference($view->getTemplate()->getId());
0 ignored issues
show
Bug introduced by
The method getId cannot be called on $view->getTemplate() (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
120
        }
121
122
        $view->setReference($viewReference);
123
124
        return $this->widgetRenderer->renderUnlinkActionByWidgetId($widgetId, $view);
125
    }
126
127
    /**
128
     * render all widgets in a slot.
129
     *
130
     * @param string $slotId
131
     * @param string $slotOptions
132
     *
133
     * @return string HTML markup of the widget with action button if needed
134
     */
135
    public function cmsSlotWidgets($slotId, $slotOptions = [])
136
    {
137
        $currentView = $this->currentViewHelper->getCurrentView();
138
139
        $result = '';
140
        $slotOptions = $this->widgetRenderer->computeOptions($slotId, $slotOptions);
0 ignored issues
show
Bug introduced by
It seems like $slotOptions defined by $this->widgetRenderer->c...($slotId, $slotOptions) on line 140 can also be of type string; however, Victoire\Bundle\WidgetBu...derer::computeOptions() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Documentation introduced by
$slotId is of type string, but the function expects a object<Victoire\Bundle\W...tMapBundle\Entity\Slot>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
141
142
        if (!empty($currentView->getBuiltWidgetMap()[$slotId])) {
143
            //parse the widget maps
144
145
            /* @var WidgetMap $widgetMap */
146
            foreach ($currentView->getBuiltWidgetMap()[$slotId] as $widgetMap) {
147
                $widget = null;
148
                $widgetContent = null;
0 ignored issues
show
Unused Code introduced by
$widgetContent is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
149
                //get the widget id
150
                $widgetId = $widgetMap->getWidget()->getId();
151
                try {
152
                    if (!$widgetMap->isAsynchronous()) {
153
                        //get the widget
154
                        $widget = $widgetMap->getWidget();
155
                        //test widget
156
                        if ($widget === null) {
157
                            throw new \Exception('The widget with the id:['.$widgetId.'] was not found.');
158
                        }
159
                        //render this widget
160
                        $result .= $this->cmsWidget($widget);
161
                    } else {
162
                        $result .= $this->widgetRenderer->prepareAsynchronousRender($widgetId);
163
                    }
164
                } catch (\Exception $ex) {
165
                    $result .= $this->widgetExceptionHandler->handle($ex, $currentView, $widget, $widgetId);
0 ignored issues
show
Documentation introduced by
$currentView is of type object<Victoire\Bundle\CoreBundle\Entity\View>, but the function expects a object<Victoire\Bundle\CoreBundle\Handler\View>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
166
                }
167
            }
168
        }
169
        //the container for the slot
170
        $ngSlotControllerName = 'slot'.$slotId.'Controller';
171
        $ngInitLoadActions = $this->isRoleVictoireGranted() ? sprintf('ng-init=\'%s.init("%s", %s)\'', $ngSlotControllerName, $slotId, json_encode($slotOptions)) : '';
172
        $result = sprintf(
173
            '<div class="vic-slot" data-name="%s" id="vic-slot-%s" ng-controller="SlotController as %s" %s>%s</div>',
174
            $slotId,
175
            $slotId,
176
            $ngSlotControllerName,
177
            $ngInitLoadActions,
178
            $result
179
        );
180
181
        return $result;
182
    }
183
184
    /**
185
     * Render a widget.
186
     *
187
     * @param Widget $widget
188
     *
189
     * @return string
190
     */
191
    public function cmsWidget($widget)
192
    {
193
        $widget->setCurrentView($this->currentViewHelper->getCurrentView());
194
195
        try {
196
            $response = $this->widgetRenderer->renderContainer($widget, $widget->getCurrentView());
197
        } catch (\Exception $ex) {
198
            $response = $this->widgetExceptionHandler->handle($ex, $widget);
0 ignored issues
show
Documentation introduced by
$widget is of type object<Victoire\Bundle\W...etBundle\Entity\Widget>, but the function expects a object<Victoire\Bundle\CoreBundle\Handler\View>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
199
        }
200
201
        return $response;
202
    }
203
204
    /**
205
     * hash some string with given algorithm.
206
     *
207
     * @param string $value     The string to hash
208
     * @param string $algorithm The algorithm we have to use to hash the string
209
     *
210
     * @return string
211
     */
212
    public function hash($value, $algorithm = 'md5')
213
    {
214
        try {
215
            return hash($algorithm, $value);
216
        } catch (\Exception $e) {
217
            error_log('Please check that the '.$algorithm.' does exists because it failed when trying to run. We are expecting a valid algorithm such as md5 or sha512 etc. ['.$e->getMessage().']');
218
219
            return $value;
220
        }
221
    }
222
223
    /**
224
     * Converts a date to the given format.
225
     *
226
     * @param string              $format   A format
227
     * @param DateTimeZone|string $timezone A timezone
228
     *
229
     * <pre>
230
     *   {{ post.published_at|date("m/d/Y") }}
231
     * </pre>
232
     *
233
     * @return string The formatted date
234
     */
235
    public function twigVicDateFormatFilter($value, $format = 'F j, Y H:i', $timezone = null)
236
    {
237
        try {
238
            $result = twig_date_format_filter($this->twig, $value, $format, $timezone);
239
        } catch (\Exception $e) {
240
            return $value;
241
        }
242
243
        return $result;
244
    }
245
246
    /**
247
     * Get the extra class for this kind of widget.
248
     *
249
     * @param Widget $widget
250
     *
251
     * @return string The extra classes
252
     */
253
    public function cmsWidgetExtraCssClass(Widget $widget)
254
    {
255
        $extraClass = $this->widgetRenderer->getExtraCssClass($widget);
256
257
        return $extraClass;
258
    }
259
260
    /**
261
     * Is the business entity type allowed for the widget and the view context.
262
     *
263
     * @param string $formEntityName The business entity name
264
     * @param View   $view           The view
265
     *
266
     * @return bool Does the form allows this kind of business entity in this view
267
     */
268
    public function isBusinessEntityAllowed($formEntityName, View $view)
269
    {
270
        //the result
271
        $isBusinessEntityAllowed = false;
272
273
        if ($view instanceof BusinessTemplate || $view instanceof BusinessPage) {
274
            //are we using the same business entity
275
            if ($formEntityName === $view->getBusinessEntityId()) {
276
                $isBusinessEntityAllowed = true;
277
            }
278
        }
279
280
        return $isBusinessEntityAllowed;
281
    }
282
283
    /**
284
     * Does the current user have the role victoire granted.
285
     *
286
     * @return bool
287
     */
288
    protected function isRoleVictoireGranted()
289
    {
290
        $isGranted = false;
291
292
        if ($this->securityContext->isGranted('ROLE_VICTOIRE')) {
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Securi...ityContext::isGranted() has been deprecated with message: since version 2.6, to be removed in 3.0. Use AuthorizationCheckerInterface::isGranted() instead. {@inheritdoc}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
293
            $isGranted = true;
294
        }
295
296
        return $isGranted;
297
    }
298
299
    /**
300
     * Does the current user have the role victoire granted.
301
     *
302
     * @return bool
303
     */
304
    protected function isRoleVictoireDeveloperGranted()
305
    {
306
        $isGranted = false;
307
308
        if ($this->securityContext->isGranted('ROLE_VICTOIRE_DEVELOPER')) {
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Securi...ityContext::isGranted() has been deprecated with message: since version 2.6, to be removed in 3.0. Use AuthorizationCheckerInterface::isGranted() instead. {@inheritdoc}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
309
            $isGranted = true;
310
        }
311
312
        return $isGranted;
313
    }
314
}
315