1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved. |
5
|
|
|
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace SprykerShop\Yves\ShopUi\Twig; |
9
|
|
|
|
10
|
|
|
use Spryker\Shared\Kernel\Store; |
11
|
|
|
use Spryker\Shared\Twig\TwigExtension; |
12
|
|
|
use Spryker\Shared\Twig\TwigFilter; |
13
|
|
|
use SprykerShop\Yves\ShopUi\Twig\Assets\AssetsUrlProviderInterface; |
14
|
|
|
use SprykerShop\Yves\ShopUi\Twig\Node\ShopUiDefineTwigNode; |
15
|
|
|
use SprykerShop\Yves\ShopUi\Twig\TokenParser\ShopUiDefineTwigTokenParser; |
16
|
|
|
use Twig\TwigFunction; |
17
|
|
|
|
18
|
|
|
class ShopUiTwigExtension extends TwigExtension |
19
|
|
|
{ |
20
|
|
|
public const FUNCTION_GET_PUBLIC_FOLDER_PATH = 'publicPath'; |
21
|
|
|
public const FUNCTION_GET_QA_ATTRIBUTE = 'qa'; |
22
|
|
|
public const FUNCTION_GET_QA_ATTRIBUTE_SUB = 'qa_*'; |
23
|
|
|
|
24
|
|
|
public const FUNCTION_GET_UI_MODEL_COMPONENT_TEMPLATE = 'model'; |
25
|
|
|
public const FUNCTION_GET_UI_ATOM_COMPONENT_TEMPLATE = 'atom'; |
26
|
|
|
public const FUNCTION_GET_UI_MOLECULE_COMPONENT_TEMPLATE = 'molecule'; |
27
|
|
|
public const FUNCTION_GET_UI_ORGANISM_COMPONENT_TEMPLATE = 'organism'; |
28
|
|
|
public const FUNCTION_GET_UI_TEMPLATE_COMPONENT_TEMPLATE = 'template'; |
29
|
|
|
public const FUNCTION_GET_UI_VIEW_COMPONENT_TEMPLATE = 'view'; |
30
|
|
|
public const DEFAULT_MODULE = 'ShopUi'; |
31
|
|
|
|
32
|
|
|
protected const FILTER_TRIM_LOCALE = 'trimLocale'; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var \Spryker\Shared\Kernel\Store |
36
|
|
|
*/ |
37
|
|
|
protected $store; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var \SprykerShop\Yves\ShopUi\Twig\Assets\AssetsUrlProviderInterface|null |
41
|
|
|
*/ |
42
|
|
|
protected $assetsUrlProvider; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
protected $localesFilterPattern; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @param \Spryker\Shared\Kernel\Store $store |
51
|
|
|
* @param \SprykerShop\Yves\ShopUi\Twig\Assets\AssetsUrlProviderInterface|null $assetsUrlProvider |
52
|
|
|
*/ |
53
|
|
|
public function __construct(Store $store, ?AssetsUrlProviderInterface $assetsUrlProvider = null) |
54
|
|
|
{ |
55
|
|
|
$this->store = $store; |
56
|
|
|
$this->assetsUrlProvider = $assetsUrlProvider; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @return string[] |
61
|
|
|
*/ |
62
|
|
|
public function getGlobals(): array |
63
|
|
|
{ |
64
|
|
|
return [ |
65
|
|
|
'required' => ShopUiDefineTwigNode::REQUIRED_VALUE, |
66
|
|
|
]; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @return \Twig\TwigFilter[] |
71
|
|
|
*/ |
72
|
|
|
public function getFilters(): array |
73
|
|
|
{ |
74
|
|
|
return [ |
75
|
|
|
new TwigFilter(static::FILTER_TRIM_LOCALE, function (string $filterValue): string { |
76
|
|
|
return $this->trimLocale($filterValue); |
77
|
|
|
}), |
78
|
|
|
]; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @return \Twig\TwigFunction[] |
83
|
|
|
*/ |
84
|
|
|
public function getFunctions(): array |
85
|
|
|
{ |
86
|
|
|
return [ |
87
|
|
|
new TwigFunction(self::FUNCTION_GET_PUBLIC_FOLDER_PATH, function ($relativePath) { |
88
|
|
|
$publicFolderPath = $this->getPublicFolderPath(); |
89
|
|
|
|
90
|
|
|
return $publicFolderPath . $relativePath; |
91
|
|
|
}, [ |
92
|
|
|
$this, |
93
|
|
|
self::FUNCTION_GET_PUBLIC_FOLDER_PATH, |
94
|
|
|
]), |
95
|
|
|
|
96
|
|
|
new TwigFunction(self::FUNCTION_GET_QA_ATTRIBUTE, function (array $qaValues = []) { |
97
|
|
|
return $this->getQaAttribute($qaValues); |
98
|
|
|
}, [ |
99
|
|
|
$this, |
100
|
|
|
self::FUNCTION_GET_QA_ATTRIBUTE, |
101
|
|
|
'is_safe' => ['html'], |
102
|
|
|
'is_variadic' => true, |
103
|
|
|
]), |
104
|
|
|
|
105
|
|
|
new TwigFunction(self::FUNCTION_GET_QA_ATTRIBUTE_SUB, function ($qaName, array $qaValues = []) { |
106
|
|
|
return $this->getQaAttribute($qaValues, $qaName); |
107
|
|
|
}, [ |
108
|
|
|
$this, |
109
|
|
|
self::FUNCTION_GET_QA_ATTRIBUTE_SUB, |
110
|
|
|
'is_safe' => ['html'], |
111
|
|
|
'is_variadic' => true, |
112
|
|
|
]), |
113
|
|
|
|
114
|
|
|
new TwigFunction(self::FUNCTION_GET_UI_MODEL_COMPONENT_TEMPLATE, function ($modelName) { |
115
|
|
|
return $this->getModelTemplate($modelName); |
116
|
|
|
}, [ |
117
|
|
|
$this, |
118
|
|
|
self::FUNCTION_GET_UI_MODEL_COMPONENT_TEMPLATE, |
119
|
|
|
]), |
120
|
|
|
|
121
|
|
|
new TwigFunction(self::FUNCTION_GET_UI_ATOM_COMPONENT_TEMPLATE, function ($componentName, $componentModule = self::DEFAULT_MODULE) { |
122
|
|
|
return $this->getComponentTemplate($componentModule, 'atoms', $componentName); |
123
|
|
|
}, [ |
124
|
|
|
$this, |
125
|
|
|
self::FUNCTION_GET_UI_ATOM_COMPONENT_TEMPLATE, |
126
|
|
|
]), |
127
|
|
|
|
128
|
|
|
new TwigFunction(self::FUNCTION_GET_UI_MOLECULE_COMPONENT_TEMPLATE, function ($componentName, $componentModule = self::DEFAULT_MODULE) { |
129
|
|
|
return $this->getComponentTemplate($componentModule, 'molecules', $componentName); |
130
|
|
|
}, [ |
131
|
|
|
$this, |
132
|
|
|
self::FUNCTION_GET_UI_MOLECULE_COMPONENT_TEMPLATE, |
133
|
|
|
]), |
134
|
|
|
|
135
|
|
|
new TwigFunction(self::FUNCTION_GET_UI_ORGANISM_COMPONENT_TEMPLATE, function ($componentName, $componentModule = self::DEFAULT_MODULE) { |
136
|
|
|
return $this->getComponentTemplate($componentModule, 'organisms', $componentName); |
137
|
|
|
}, [ |
138
|
|
|
$this, |
139
|
|
|
self::FUNCTION_GET_UI_ORGANISM_COMPONENT_TEMPLATE, |
140
|
|
|
]), |
141
|
|
|
|
142
|
|
|
new TwigFunction(self::FUNCTION_GET_UI_TEMPLATE_COMPONENT_TEMPLATE, function ($templateName, $templateModule = self::DEFAULT_MODULE) { |
143
|
|
|
return $this->getTemplateTemplate($templateModule, $templateName); |
144
|
|
|
}, [ |
145
|
|
|
$this, |
146
|
|
|
self::FUNCTION_GET_UI_TEMPLATE_COMPONENT_TEMPLATE, |
147
|
|
|
]), |
148
|
|
|
|
149
|
|
|
new TwigFunction(self::FUNCTION_GET_UI_VIEW_COMPONENT_TEMPLATE, function ($viewName, $viewModule = self::DEFAULT_MODULE) { |
150
|
|
|
return $this->getViewTemplate($viewModule, $viewName); |
151
|
|
|
}, [ |
152
|
|
|
$this, |
153
|
|
|
self::FUNCTION_GET_UI_VIEW_COMPONENT_TEMPLATE, |
154
|
|
|
]), |
155
|
|
|
]; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* @return \Twig\TokenParser\AbstractTokenParser[] |
160
|
|
|
*/ |
161
|
|
|
public function getTokenParsers(): array |
162
|
|
|
{ |
163
|
|
|
return [ |
164
|
|
|
new ShopUiDefineTwigTokenParser(), |
165
|
|
|
]; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* @return string |
170
|
|
|
*/ |
171
|
|
|
protected function getPublicFolderPath(): string |
172
|
|
|
{ |
173
|
|
|
if ($this->assetsUrlProvider) { |
174
|
|
|
return $this->assetsUrlProvider->getAssetsUrl(); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
return '/assets/'; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* @param array $qaValues |
182
|
|
|
* @param string|null $qaName |
183
|
|
|
* |
184
|
|
|
* @return string |
185
|
|
|
*/ |
186
|
|
|
protected function getQaAttribute(array $qaValues = [], ?string $qaName = null): string |
187
|
|
|
{ |
188
|
|
|
$value = ''; |
189
|
|
|
|
190
|
|
|
if (empty($qaValues)) { |
191
|
|
|
return ''; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
foreach ($qaValues as $qaValue) { |
195
|
|
|
if (!empty($qaValue)) { |
196
|
|
|
$value .= $qaValue . ' '; |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
if (empty($qaName)) { |
201
|
|
|
return 'data-qa="' . trim($value) . '"'; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
return 'data-qa-' . $qaName . '="' . trim($value) . '"'; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* @param string $modelName |
209
|
|
|
* |
210
|
|
|
* @return string |
211
|
|
|
*/ |
212
|
|
|
protected function getModelTemplate(string $modelName): string |
213
|
|
|
{ |
214
|
|
|
return '@ShopUi/models/' . $modelName . '.twig'; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @param string $componentModule |
219
|
|
|
* @param string $componentType |
220
|
|
|
* @param string $componentName |
221
|
|
|
* |
222
|
|
|
* @return string |
223
|
|
|
*/ |
224
|
|
|
protected function getComponentTemplate(string $componentModule, string $componentType, string $componentName): string |
225
|
|
|
{ |
226
|
|
|
return '@' . $componentModule . '/components/' . $componentType . '/' . $componentName . '/' . $componentName . '.twig'; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* @param string $templateModule |
231
|
|
|
* @param string $templateName |
232
|
|
|
* |
233
|
|
|
* @return string |
234
|
|
|
*/ |
235
|
|
|
protected function getTemplateTemplate(string $templateModule, string $templateName): string |
236
|
|
|
{ |
237
|
|
|
return '@' . $templateModule . '/templates/' . $templateName . '/' . $templateName . '.twig'; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* @param string $viewModule |
242
|
|
|
* @param string $viewName |
243
|
|
|
* |
244
|
|
|
* @return string |
245
|
|
|
*/ |
246
|
|
|
protected function getViewTemplate(string $viewModule, string $viewName): string |
247
|
|
|
{ |
248
|
|
|
return '@' . $viewModule . '/views/' . $viewName . '/' . $viewName . '.twig'; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @param string $filterValue |
253
|
|
|
* |
254
|
|
|
* @return string |
255
|
|
|
*/ |
256
|
|
|
protected function trimLocale(string $filterValue): string |
257
|
|
|
{ |
258
|
|
|
return preg_replace( |
259
|
|
|
$this->getLocalePattern(), |
260
|
|
|
'/', |
261
|
|
|
$filterValue |
262
|
|
|
); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* @return string |
267
|
|
|
*/ |
268
|
|
|
protected function getLocalePattern(): string |
269
|
|
|
{ |
270
|
|
|
if ($this->localesFilterPattern) { |
271
|
|
|
return $this->localesFilterPattern; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
$locale = $this->store->getCurrentLocale(); |
275
|
|
|
$this->localesFilterPattern = '#^\/(' . strtok($locale, '_') . ')\/#'; |
276
|
|
|
|
277
|
|
|
return $this->localesFilterPattern; |
278
|
|
|
} |
279
|
|
|
} |
280
|
|
|
|