Completed
Push — master ( 5d51b4...87fdd9 )
by Paul
10s
created

LinkExtension::victoireMenuLink()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 4
1
<?php
2
3
namespace Victoire\Bundle\WidgetBundle\Twig;
4
5
use Doctrine\ORM\EntityManager;
6
use Symfony\Bundle\FrameworkBundle\Routing\Router;
7
use Symfony\Component\HttpFoundation\RequestStack;
8
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
9
use Victoire\Bundle\BusinessEntityBundle\Helper\BusinessEntityHelper;
10
use Victoire\Bundle\BusinessPageBundle\Helper\BusinessPageHelper;
11
use Victoire\Bundle\CoreBundle\Entity\Link;
12
use Victoire\Bundle\PageBundle\Helper\PageHelper;
13
use Victoire\Bundle\ViewReferenceBundle\ViewReference\ViewReference;
14
15
/**
16
 * Twig extension for rendering a link.
17
 */
18
class LinkExtension extends \Twig_Extension
19
{
20
    protected $router;
21
    protected $analytics;
22
    protected $businessEntityHelper; // @victoire_business_page.business_entity_helper
23
    protected $BusinessPageHelper; // @victoire_business_page.business_page_helper
24
    protected $pageHelper;
25
    protected $em; // @doctrine.orm.entity_manager
26
    protected $abstractBusinessTemplates;
27
28
    /**
29
     * LinkExtension constructor.
30
     *
31
     * @param Router       $router
32
     * @param RequestStack $requestStack
33
     * @param $analytics
34
     * @param BusinessEntityHelper $businessEntityHelper
35
     * @param BusinessPageHelper   $BusinessPageHelper
36
     * @param PageHelper           $pageHelper
37
     * @param EntityManager        $em
38
     * @param array                $abstractBusinessTemplates
39
     */
40
    public function __construct(
41
        Router $router,
42
        RequestStack $requestStack,
43
        $analytics,
44
        BusinessEntityHelper $businessEntityHelper,
45
        BusinessPageHelper $BusinessPageHelper,
46
        PageHelper $pageHelper,
47
        EntityManager $em,
0 ignored issues
show
Bug introduced by
You have injected the EntityManager via parameter $em. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

The EntityManager might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
48
        $abstractBusinessTemplates = []
49
    ) {
50
        $this->router = $router;
51
        $this->request = $requestStack->getCurrentRequest();
0 ignored issues
show
Bug introduced by
The property request 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...
52
        $this->analytics = $analytics;
53
        $this->businessEntityHelper = $businessEntityHelper;
54
        $this->BusinessPageHelper = $BusinessPageHelper;
55
        $this->pageHelper = $pageHelper;
56
        $this->em = $em;
57
        $this->abstractBusinessTemplates = $abstractBusinessTemplates;
58
    }
59
60
    /**
61
     * Returns a list of functions to add to the existing list.
62
     *
63
     * @return \Twig_SimpleFunction[] An array of functions
64
     */
65
    public function getFunctions()
66
    {
67
        return [
68
            new \Twig_SimpleFunction('vic_link_url', [$this, 'victoireLinkUrl']),
69
            new \Twig_SimpleFunction('vic_link', [$this, 'victoireLink'], ['is_safe' => ['html']]),
70
            new \Twig_SimpleFunction('vic_menu_link', [$this, 'victoireMenuLink'], ['is_safe' => ['html']]),
71
            new \Twig_SimpleFunction('vic_business_link', [$this, 'victoireBusinessLink'], ['is_safe' => ['html']]),
72
        ];
73
    }
74
75
    /**
76
     * Generate the complete link (with the a tag).
77
     *
78
     * @param array  $parameters   The link parameters (go to LinkTrait to have the list)
79
     * @param string $avoidRefresh Do we have to refresh or not ?
80
     * @param array  $url          Fallback url
81
     *
82
     * @return string
83
     */
84
    public function victoireLinkUrl($parameters, $avoidRefresh = true, $url = '#')
85
    {
86
        $referenceType = isset($parameters['referenceType']) ? $parameters['referenceType'] : UrlGeneratorInterface::ABSOLUTE_PATH;
87
88
        $viewReference = isset($parameters['viewReference']) ? $parameters['viewReference'] : null;
89
        switch ($parameters['linkType']) {
90
            case 'viewReference':
91
                if ($viewReference instanceof ViewReference) {
92
                    $viewReference = $viewReference->getId();
93
                }
94
95
                if (!empty($parameters['viewReferencePage'])) {
96
                    $page = $parameters['viewReferencePage'];
97
                } else {
98
                    $page = $this->pageHelper->findPageByParameters([
99
                        'id'     => $viewReference,
100
                        'locale' => $parameters['locale'],
101
                    ]);
102
                }
103
104
                $linkUrl = $this->router->generate(
105
                    'victoire_core_page_show', [
106
                        '_locale' => $page->getReference($parameters['locale'])->getLocale(),
107
                        'url'     => $page->getReference($parameters['locale'])->getUrl(),
108
                    ],
109
                    $referenceType
110
                );
111
                if ($this->request->getRequestUri() != $linkUrl || !$avoidRefresh) {
112
                    $url = $linkUrl;
113
                }
114
                break;
115
            case 'route':
116
                $url = $this->router->generate($parameters['route'], $parameters['routeParameters'], $referenceType);
117
                break;
118
            case Link::TYPE_WIDGET:
119
                $attachedWidget = $parameters[Link::TYPE_WIDGET];
120
                //fallback when a widget is deleted cascading the relation as null (widget_id = null)
121
                if ($attachedWidget && method_exists($attachedWidget->getView(), 'getUrl')) {
122
123
                    //create base url
124
                    $url = $this->router->generate('victoire_core_page_show', ['_locale' => $attachedWidget->getView()->getLocale(), 'url' => $attachedWidget->getView()->getUrl()], $referenceType);
125
126
                    //If widget in the same view
127
                    if (rtrim($this->request->getRequestUri(), '/') == rtrim($url, '/')) {
128
                        $url = '';
129
                    }
130
                    //Add anchor part
131
                    $url .= '#vic-widget-'.$attachedWidget->getId().'-container-anchor';
132
                }
133
                break;
134
            default:
135
                $url = $parameters['url'];
136
        }
137
138
        return $url;
139
    }
140
141
    /**
142
     * Generate the complete link (with the a tag).
143
     *
144
     * @param array  $parameters The link parameters (go to LinkTrait to have the list)
145
     * @param string $label      link label
146
     * @param array  $attr       custom attributes
147
     *
148
     * @return string
149
     */
150
    public function victoireLink($parameters, $label, $attr = [], $currentClass = 'active', $url = '#')
151
    {
152
        $referenceLink = UrlGeneratorInterface::ABSOLUTE_PATH;
153
        $attachedWidget = isset($parameters[Link::TYPE_WIDGET]) ? $parameters[Link::TYPE_WIDGET] : null;
154
155
        if ($parameters['linkType'] == Link::TYPE_WIDGET && $attachedWidget && method_exists($attachedWidget->getView(), 'getUrl')) {
156
            $viewUrl = $this->router->generate('victoire_core_page_show', ['_locale' => $attachedWidget->getView()->getLocale(), 'url' => $attachedWidget->getView()->getUrl()], $referenceLink);
157
            if (rtrim($this->request->getRequestUri(), '/') == rtrim($viewUrl, '/')) {
158
                $attr['data-scroll'] = 'smooth';
159
            }
160
        }
161
162
        //Avoid to refresh page if not needed
163
        if ($this->request->getRequestUri() == $this->victoireLinkUrl($parameters, false)) {
164
            $this->addAttr('class', $currentClass, $attr);
165
        }
166
167
        //Build the target attribute
168
        if ($parameters['target'] == 'ajax-modal') {
169
            $attr['data-toggle'] = 'ajax-modal';
170
        } elseif ($parameters['target'] == '') {
171
            $attr['target'] = '_parent';
172
        } else {
173
            $attr['target'] = $parameters['target'];
174
        }
175
176
        //Add the analytics tracking code attribute
177
        if (isset($parameters['analyticsTrackCode'])) {
178
            $this->addAttr('onclick', $parameters['analyticsTrackCode'], $attr);
179
        }
180
181
        $url = $this->victoireLinkUrl($parameters, true, $url);
182
        //Creates a new twig environment
183
        $twig = new \Twig_Environment(new \Twig_Loader_Array(['linkTemplate' => '{{ link|raw }}']));
184
185
        return $twig->render('linkTemplate', ['link' => '<a href="'.$url.'" '.$this->formatAttributes($attr).'>'.$label.'</a>']);
186
    }
187
188
    /**
189
     * Generate the complete menu link item (with the li tag).
190
     *
191
     * @param array  $parameters The link parameters (go to LinkTrait to have the list)
192
     * @param string $label      link label
193
     * @param array  $attr       custom attributes
0 ignored issues
show
Bug introduced by
There is no parameter named $attr. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
194
     *
195
     * @return string
196
     */
197
    public function victoireMenuLink($parameters, $label, $linkAttr = [], $listAttr = [])
198
    {
199
        if ($this->request->getRequestUri() == $this->victoireLinkUrl($parameters, false)) {
200
            $this->addAttr('class', 'active', $listAttr);
201
        }
202
203
        return '<li '.$this->formatAttributes($listAttr).'>'.$this->victoireLink($parameters, $label, $linkAttr, false, '#top').'</li>';
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
204
    }
205
206
    public function victoireBusinessLink($businessEntityInstance, $templateId = null, $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
207
    {
208
        if (isset($this->abstractBusinessTemplates[$templateId])) {
209
            $templateId = $this->abstractBusinessTemplates[$templateId];
210
        }
211
        if (!$templateId) {
212
            $templateId = $this->BusinessPageHelper
213
                ->guessBestPatternIdForEntity(new \ReflectionClass($businessEntityInstance), $businessEntityInstance->getId(), $this->em);
214
        }
215
216
        $page = $this->pageHelper->findPageByParameters([
217
            'templateId' => $templateId,
218
            'entityId'   => $businessEntityInstance->getId(),
219
        ]);
220
221
        $parameters = [
222
            'linkType'        => 'route',
223
            'route'           => 'victoire_core_page_show',
224
            'routeParameters' => [
225
                'url' => $page->getReference()->getUrl(),
226
                '_locale' => $page->getLocale()
0 ignored issues
show
Bug introduced by
The method getLocale() does not seem to exist on object<Victoire\Bundle\CoreBundle\Entity\View>.

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...
227
            ],
228
            'referenceType' => $referenceType,
229
        ];
230
231
        return $this->victoireLinkUrl($parameters);
232
    }
233
234
    /**
235
     * Add a given attribute to given attributes.
236
     *
237
     * @param string $label
238
     * @param string $value
239
     * @param array  $attr  The current attributes array
240
     *
241
     * @return LinkExtension
242
     **/
243
    protected function addAttr($label, $value, &$attr)
244
    {
245
        if (!isset($attr[$label])) {
246
            $attr[$label] = '';
247
        } else {
248
            $attr[$label] .= ' ';
249
        }
250
        $attr[$label] .= $value;
251
252
        return $this;
253
    }
254
255
    /**
256
     * Returns the name of the extension.
257
     *
258
     * @return string The extension name
259
     */
260
    public function getName()
261
    {
262
        return 'victoire_link_extension';
263
    }
264
265
    private function formatAttributes($attributes)
266
    {
267
        array_walk($attributes, function (&$item, $key) {
268
            if (is_array($item)) {
269
                $item = implode($item, ' ');
270
            }
271
            $item = $key.'="'.$item.'"';
272
        });
273
274
        return implode($attributes, ' ');
275
    }
276
}
277