1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Admingenerator\GeneratorBundle\Twig\Extension; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* @author Cedric LOMBARDOT |
7
|
|
|
* @author Piotr Gołębiewski <[email protected]> |
8
|
|
|
* @author Stéphane Escandell |
9
|
|
|
*/ |
10
|
|
|
class EchoExtension extends \Twig_Extension |
|
|
|
|
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* @var bool |
14
|
|
|
*/ |
15
|
|
|
private $useExpression; |
16
|
|
|
|
17
|
|
|
public function __construct($useExpression = false) |
18
|
|
|
{ |
19
|
|
|
$this->useExpression = $useExpression; |
20
|
|
|
} |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* {@inheritdoc} |
24
|
|
|
*/ |
25
|
|
|
public function getFunctions() |
26
|
|
|
{ |
27
|
|
|
return array( |
28
|
|
|
'echo_if_granted' => new \Twig_SimpleFunction('echo_if_granted', array($this, 'getEchoIfGranted')), |
|
|
|
|
29
|
|
|
'echo_path' => new \Twig_SimpleFunction('echo_path', array($this, 'getEchoPath')), |
|
|
|
|
30
|
|
|
'echo_trans' => new \Twig_SimpleFunction('echo_trans', array($this, 'getEchoTrans')), |
|
|
|
|
31
|
|
|
'echo_render' => new \Twig_SimpleFunction('echo_render', array($this, 'getEchoRender')) |
|
|
|
|
32
|
|
|
); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* {@inheritdoc} |
37
|
|
|
*/ |
38
|
|
|
public function getFilters() |
39
|
|
|
{ |
40
|
|
|
return array( |
41
|
|
|
'convert_as_form' => new \Twig_SimpleFilter('convert_as_form', array($this, 'convertAsForm')), |
|
|
|
|
42
|
|
|
); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Try to convert options of form given as string from yaml to a good object |
47
|
|
|
* > Transforms PHP call into PHP : |
48
|
|
|
* addFormOptions: |
49
|
|
|
* myOption: __php(MyStaticClass::myCustomFunction()) |
50
|
|
|
* |
51
|
|
|
* > Tranforms [query_builder|query] into valid Closure: |
52
|
|
|
* addFormOptions: |
53
|
|
|
* query_builder: function($er) { return $er->createMyCustomQueryBuilder(); } |
54
|
|
|
* |
55
|
|
|
* |
56
|
|
|
* @param string $options the string as php |
57
|
|
|
* @param string $formType the form type |
58
|
|
|
* |
59
|
|
|
* @return string the new options |
60
|
|
|
*/ |
61
|
|
|
public function convertAsForm($options, $formType) |
62
|
|
|
{ |
63
|
|
|
// Transforms PHP call into PHP (simple copy/paste) |
64
|
|
|
preg_match("/'__php\((.+?)\)'/i", stripslashes($options), $matches); |
65
|
|
|
if (count($matches)) { |
66
|
|
|
$options = preg_replace("/'__php\((.+?)\)'/i", $matches[1], $options); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
// Query builder: remove quotes around closure |
70
|
|
|
// Should we really check formType or can we just |
71
|
|
|
// look for query_builder option? |
72
|
|
View Code Duplication |
if (preg_match("/EntityType$/i", $formType)) { |
|
|
|
|
73
|
|
|
preg_match("/'query_builder' => '(.+?)}',/i", $options, $matches); |
74
|
|
|
|
75
|
|
|
if (count($matches) > 0) { |
76
|
|
|
$options = str_replace("'query_builder' => '$matches[1]}'", "'query_builder' => ".stripslashes($matches[1]).'}', $options); |
77
|
|
|
} |
78
|
|
|
preg_match("/'query_builder' => '(.+?)',/i", $options, $matches); |
79
|
|
|
|
80
|
|
|
if (count($matches) > 0) { |
81
|
|
|
$options = str_replace("'query_builder' => '$matches[1]'", "'query_builder' => ".stripslashes($matches[1]), $options); |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// Same question here |
86
|
|
View Code Duplication |
if (preg_match("/ModelType$/i", $formType)) { |
|
|
|
|
87
|
|
|
preg_match("/'query' => '(.+?)}',/i", $options, $matches); |
88
|
|
|
|
89
|
|
|
if (count($matches) > 0) { |
90
|
|
|
$options = str_replace("'query' => '$matches[1]}'", "'query' => ".stripslashes($matches[1]).'}', $options); |
91
|
|
|
} |
92
|
|
|
preg_match("/'query' => '(.+?)',/i", $options, $matches); |
93
|
|
|
|
94
|
|
|
if (count($matches) > 0) { |
95
|
|
|
$options = str_replace("'query' => '$matches[1]'", "'query' => ".stripslashes($matches[1]), $options); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
return $options; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Print "trans" tag for string $str with parameters $parameters |
104
|
|
|
* for catalog $catalog. |
105
|
|
|
* |
106
|
|
|
* @param $str |
107
|
|
|
* @param array $parameters |
108
|
|
|
* @param string $catalog |
109
|
|
|
* @return string |
110
|
|
|
*/ |
111
|
|
|
public function getEchoTrans($str, array $parameters = array(), $catalog = 'Admingenerator', $escape = null) |
112
|
|
|
{ |
113
|
|
|
$transParameters='{}'; |
114
|
|
|
$bag_parameters=array(); |
115
|
|
|
|
116
|
|
|
if ($parameterBag = $this->getParameterBag($str)) { |
117
|
|
|
$str = $parameterBag['string']; |
118
|
|
|
$bag_parameters = $parameterBag['params']; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
if (!empty($parameters) || !empty($bag_parameters)) { |
122
|
|
|
$transParameters="{"; |
123
|
|
|
|
124
|
|
|
foreach ($parameters as $key => $value) { |
125
|
|
|
$transParameters.= "'%".$key."%': '".str_replace("'", "\'", $value)."',"; |
126
|
|
|
} |
127
|
|
|
foreach ($bag_parameters as $key => $value) { |
128
|
|
|
$transParameters.= "'%".$key."%': ".str_replace("'", "\'", $value).","; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
$transParameters.="}"; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
return sprintf( |
135
|
|
|
'{{ "%s"|trans(%s, "%s")%s }}', |
136
|
|
|
str_replace('"', '\"', $str), |
137
|
|
|
$transParameters, |
138
|
|
|
$catalog, |
139
|
|
|
$escape ? sprintf('|escape("%s")', $escape) : '|raw' |
140
|
|
|
); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Print "echo tag with path call" to the path $path with params $params. |
145
|
|
|
* |
146
|
|
|
* @param $path |
147
|
|
|
* @param array $params |
148
|
|
|
* @param array|string $filters |
149
|
|
|
* @return string |
150
|
|
|
*/ |
151
|
|
|
public function getEchoPath($path, $params = null, $filters = null) |
152
|
|
|
{ |
153
|
|
|
if (null === $params) { |
154
|
|
|
return (null === $filters) |
155
|
|
|
? strtr('{{ path("%%path%%") }}', array('%%path%%' => $path)) |
156
|
|
|
: strtr( |
157
|
|
|
'{{ path("%%path%%")|%%filters%% }}', |
158
|
|
|
array( |
159
|
|
|
'%%path%%' => $path, |
160
|
|
|
'%%filters%%' => (is_array($filters) ? implode('|', $filters) : $filters) |
161
|
|
|
) |
162
|
|
|
); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
$params = preg_replace('/\{\{\s+?([\w\.]+)\s+?\}\}/i', '$1', $params); |
166
|
|
|
|
167
|
|
|
return (null === $filters) |
168
|
|
|
? strtr('{{ path("%%path%%", %%params%%) }}', array('%%path%%' => $path, '%%params%%' => $params)) |
169
|
|
|
: strtr( |
170
|
|
|
'{{ path("%%path%%", %%params%%)|%%filters%% }}', |
171
|
|
|
array( |
172
|
|
|
'%%path%%' => $path, |
173
|
|
|
'%%params%%' => $params, |
174
|
|
|
'%%filters%%' => (is_array($filters) ? implode('|', $filters) : $filters) |
175
|
|
|
) |
176
|
|
|
); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Print "if" tag with condition to is_expr_granted('$credentials') |
181
|
|
|
* If $modelName is not null, append the $modelName to the function call. |
182
|
|
|
* |
183
|
|
|
* @param $credentials |
184
|
|
|
* @param null $modelName |
185
|
|
|
* @return string |
186
|
|
|
*/ |
187
|
|
|
public function getEchoIfGranted($credentials, $modelName = null) |
188
|
|
|
{ |
189
|
|
|
if ('AdmingenAllowed' == $credentials) { |
190
|
|
|
return "{% if (true) %}"; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return sprintf( |
194
|
|
|
"{%% if %s('%s'%s) %%}", |
195
|
|
|
$this->useExpression ? 'is_expr_granted' : 'is_granted', |
196
|
|
|
$credentials, |
197
|
|
|
$modelName ? ', '.$modelName.' is defined ? '.$modelName.' : null' : '' |
198
|
|
|
); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Print "echo tag with render call" to the controller $controller |
203
|
|
|
* with $params parameters. |
204
|
|
|
* |
205
|
|
|
* @param $controller |
206
|
|
|
* @param array $params |
207
|
|
|
* @return string |
208
|
|
|
*/ |
209
|
|
|
public function getEchoRender($controller, array $params = array()) |
210
|
|
|
{ |
211
|
|
|
$params = $this->getTwigAssociativeArray($params); |
212
|
|
|
|
213
|
|
|
return '{{ render(controller("'.$controller.'", '.$params.')) }}'; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Reads parameters from subject and removes parameter bag from string. |
218
|
|
|
* |
219
|
|
|
* @return array |
220
|
|
|
* [string] -> string for echo trans |
221
|
|
|
* [params] -> parameters for echo trans |
222
|
|
|
* |
223
|
|
|
* @return false if subject did not match any of following patterns |
224
|
|
|
* |
225
|
|
|
* ############################## |
226
|
|
|
* Backwards compability pattern: |
227
|
|
|
* |
228
|
|
|
* replaces twig tags {{ parameter_name }} with parameters. |
229
|
|
|
* |
230
|
|
|
* example: You're editing {{ Book.title }} written by {{ Book.author.name }}! |
231
|
|
|
* |
232
|
|
|
* results in: |
233
|
|
|
* string -> You're editing %Book.title% written by %Book.author.name%! |
234
|
|
|
* params -> |
235
|
|
|
* [Book.title] -> Book.title |
236
|
|
|
* [Book.author.name] -> Book.author.name |
237
|
|
|
* |
238
|
|
|
* ################################### |
239
|
|
|
* Feature - key-value syntax pattern: |
240
|
|
|
* |{ %param_key%: param_value, %param_key2%: param_value2, %param_key3%: param_value3 }| |
241
|
|
|
* |
242
|
|
|
* where param_key and param_value consist of any number a-z, A-Z, 0-9 or . (dot) characters |
243
|
|
|
* |
244
|
|
|
* example: You're editing %book% written by %author%!|{ %book%: Book.title, %author%: Book.author.name }| |
245
|
|
|
* results in: |
246
|
|
|
* string -> You're editing %book% written by %author%! |
247
|
|
|
* params -> |
248
|
|
|
* [book] -> Book.title |
249
|
|
|
* [author] -> Book.author.name |
250
|
|
|
* |
251
|
|
|
* example: book.edit.title|{ %book%: Book.title, %author%: Book.author.name }| * |
252
|
|
|
* results in: |
253
|
|
|
* string -> book.edit.title |
254
|
|
|
* params -> |
255
|
|
|
* [book] -> Book.title |
256
|
|
|
* [author] -> Book.author.name |
257
|
|
|
* |
258
|
|
|
* ################################### |
259
|
|
|
* Feature - abbreviated syntax pattern: |
260
|
|
|
* |{ param_value, param_value2, param_value3 }| |
261
|
|
|
* |
262
|
|
|
* where param_value consists of any number a-z, A-Z, 0-9 or . (dot) characters |
263
|
|
|
* |
264
|
|
|
* example: You're editing %Book.title% written by %Book.author.name%!|{ Book.title, Book.author.name }| |
265
|
|
|
* results in: |
266
|
|
|
* string -> You're editing %Book.title% written by %Book.author.name%! |
267
|
|
|
* params -> |
268
|
|
|
* [Book.title] -> Book.title |
269
|
|
|
* [Book.author.name] -> Book.author.name |
270
|
|
|
* |
271
|
|
|
* example: book.edit.title|{ Book.title, Book.author.name }| |
272
|
|
|
* results in: |
273
|
|
|
* string -> book.edit.title |
274
|
|
|
* params -> |
275
|
|
|
* [Book.title] -> Book.title |
276
|
|
|
* [Book.author.name] -> Book.author.name |
277
|
|
|
*/ |
278
|
|
|
private function getParameterBag($subject) |
279
|
|
|
{ |
280
|
|
|
// Backwards compability - replace twig tags with parameters |
281
|
|
|
$pattern_bc = '/\{\{\s(?<param>[a-zA-Z0-9.]+)\s\}\}+/'; |
282
|
|
|
|
283
|
|
|
if (preg_match_all($pattern_bc, $subject, $match_params)) { |
284
|
|
|
$string = preg_filter($pattern_bc, '%\1%', $subject); |
285
|
|
|
|
286
|
|
|
$param = array(); |
287
|
|
|
foreach ($match_params['param'] as $value) { |
288
|
|
|
$param[$value] = $value; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
return array( |
292
|
|
|
'string' => $string, |
293
|
|
|
'params' => $param |
294
|
|
|
); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
# Feature - read key/value syntax parameters |
298
|
|
|
$pattern_string = '/^(?<string>[^|]+)(?<parameter_bag>\|\{(\s?%[a-zA-Z0-9.]+%:\s[a-zA-Z0-9.]+,?\s?)+\s?\}\|)\s*$/'; |
299
|
|
|
$pattern_params = '/(?>(?<=(\|\{\s|.,\s))%(?<key>[a-zA-Z0-9.]+)%:\s(?<value>[a-zA-Z0-9.]+)(?=(,\s.|\s\}\|)))+/'; |
300
|
|
|
|
301
|
|
View Code Duplication |
if (preg_match($pattern_string, $subject, $match_string)) { |
|
|
|
|
302
|
|
|
$string = $match_string['string']; |
303
|
|
|
$parameter_bag = $match_string['parameter_bag']; |
304
|
|
|
|
305
|
|
|
$param = array(); |
306
|
|
|
preg_match_all($pattern_params, $parameter_bag, $match_params, PREG_SET_ORDER); |
307
|
|
|
|
308
|
|
|
foreach ($match_params as $match) { |
|
|
|
|
309
|
|
|
$param[$match['key']] = $match['value']; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
return array( |
313
|
|
|
'string' => $string, |
314
|
|
|
'params' => $param |
315
|
|
|
); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
# Feature - read abbreviated syntax parameters |
319
|
|
|
$abbreviated_pattern_string = '/^(?<string>[^|]+)(?<parameter_bag>\|\{(\s?[a-zA-Z0-9.]+,?\s?)+\s?\}\|)\s*$/'; |
320
|
|
|
$abbreviated_pattern_params = '/(?>(?<=(\|\{\s|.,\s))(?<param>[a-zA-Z0-9.]+)(?=(,\s.|\s\}\|)))+?/'; |
321
|
|
|
|
322
|
|
View Code Duplication |
if (preg_match($abbreviated_pattern_string, $subject, $match_string)) { |
|
|
|
|
323
|
|
|
$string = $match_string['string']; |
324
|
|
|
$parameter_bag = $match_string['parameter_bag']; |
325
|
|
|
|
326
|
|
|
$param = array(); |
327
|
|
|
preg_match_all($abbreviated_pattern_params, $parameter_bag, $match_params); |
328
|
|
|
|
329
|
|
|
foreach ($match_params['param'] as $value) { |
330
|
|
|
$param[$value] = $value; |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
return array( |
334
|
|
|
'string' => $string, |
335
|
|
|
'params' => $param |
336
|
|
|
); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
// If subject does not match any pattern, return false |
340
|
|
|
return false; |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* Converts an assoc array to a twig array expression (string) . |
345
|
|
|
* Only in case a value contains '{{' and '}}' the value won't be |
346
|
|
|
* wrapped in quotes. |
347
|
|
|
* |
348
|
|
|
* An array like: |
349
|
|
|
* <code> |
350
|
|
|
* $array = array('a' => 'b', 'c' => 'd', 'e' => '{{f}}'); |
351
|
|
|
* </code> |
352
|
|
|
* |
353
|
|
|
* Will be converted to: |
354
|
|
|
* <code> |
355
|
|
|
* "{ a: 'b', c: 'd', e: f }" |
356
|
|
|
* </code> |
357
|
|
|
* |
358
|
|
|
* @return string |
359
|
|
|
*/ |
360
|
|
|
private function getTwigAssociativeArray(array $hashmap) |
361
|
|
|
{ |
362
|
|
|
$contents = array(); |
363
|
|
|
foreach ($hashmap as $key => $value) { |
364
|
|
|
if (!strstr($value, '{{') || !strstr($value, '}}')) { |
365
|
|
|
$value = "'$value'"; |
366
|
|
|
} else { |
367
|
|
|
$value = trim(str_replace(array('{{', '}}'), '', $value)); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
$contents[] = "$key: $value"; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
return '{ ' . implode(', ', $contents) . ' }'; |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* Returns the name of the extension. |
378
|
|
|
* |
379
|
|
|
* @return string The extension name |
380
|
|
|
*/ |
381
|
|
|
public function getName() |
382
|
|
|
{ |
383
|
|
|
return 'admingenerator_echo'; |
384
|
|
|
} |
385
|
|
|
} |
386
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.