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, |
|
|
|
|
48
|
|
|
$abstractBusinessTemplates = [] |
49
|
|
|
) { |
50
|
|
|
$this->router = $router; |
51
|
|
|
$this->request = $requestStack->getCurrentRequest(); |
|
|
|
|
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 |
|
|
|
|
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>'; |
|
|
|
|
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() |
|
|
|
|
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
|
|
|
|
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:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.