TYPO3 CMS  TYPO3_6-2
TemplateParserPatternTest.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License, either version 3 *
9  * of the License, or (at your option) any later version. *
10  * *
11  * The TYPO3 project - inspiring people to share! *
12  * */
13 
18 
23  $pattern = str_replace('FLUID_NAMESPACE_SEPARATOR', preg_quote(\TYPO3\CMS\Fluid\Fluid::LEGACY_NAMESPACE_SEPARATOR), \TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SCAN_PATTERN_NAMESPACEDECLARATION);
24  $this->assertEquals(preg_match($pattern, '{namespace acme=Tx_AcmeMyPackage_Bla_blubb}'), 1, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did not match a namespace declaration (1).');
25  $this->assertEquals(preg_match($pattern, '{namespace acme=Tx_AcmeMyPackage_Bla_Blubb }'), 1, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did not match a namespace declaration (2).');
26  $this->assertEquals(preg_match($pattern, ' {namespace foo = Tx_Foo_Bla3_Blubb } '), 1, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did not match a namespace declaration (3).');
27  $this->assertEquals(preg_match($pattern, ' \\{namespace fblubb = Tx_Fluid_Bla3_Blubb }'), 0, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did match a namespace declaration even if it was escaped. (1)');
28  $this->assertEquals(preg_match($pattern, '\\{namespace typo3 = Tx_TYPO3_Bla3_Blubb }'), 0, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did match a namespace declaration even if it was escaped. (2)');
29  }
30 
35  $pattern = str_replace('FLUID_NAMESPACE_SEPARATOR', preg_quote(\TYPO3\CMS\Fluid\Fluid::NAMESPACE_SEPARATOR), \TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SCAN_PATTERN_NAMESPACEDECLARATION);
36  $this->assertEquals(preg_match($pattern, '{namespace acme=Acme.MyPackage\Bla\blubb}'), 1, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did not match a namespace declaration (1).');
37  $this->assertEquals(preg_match($pattern, '{namespace acme=Acme.MyPackage\Bla\Blubb }'), 1, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did not match a namespace declaration (2).');
38  $this->assertEquals(preg_match($pattern, ' {namespace foo = Foo\Bla3\Blubb } '), 1, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did not match a namespace declaration (3).');
39  $this->assertEquals(preg_match($pattern, ' \\{namespace fblubb = TYPO3.Fluid\Bla3\Blubb }'), 0, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did match a namespace declaration even if it was escaped. (1)');
40  $this->assertEquals(preg_match($pattern, '\\{namespace typo3 = TYPO3.TYPO3\Bla3\Blubb }'), 0, 'The SCAN_PATTERN_NAMESPACEDECLARATION pattern did match a namespace declaration even if it was escaped. (2)');
41  }
42 
46  public function testSPLIT_PATTERN_DYNAMICTAGS() {
47  $pattern = $this->insertNamespaceIntoRegularExpression(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SPLIT_PATTERN_TEMPLATE_DYNAMICTAGS, array('typo3', 't3', 'f'));
48 
49  $source = '<html><head> <f:a.testing /> <f:blablubb> {testing}</f4:blz> </t3:hi.jo>';
50  $expected = array('<html><head> ', '<f:a.testing />', ' ', '<f:blablubb>', ' {testing}</f4:blz> ', '</t3:hi.jo>');
51  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly with simple tags.');
52 
53  $source = 'hi<f:testing attribute="Hallo>{yep}" nested:attribute="jup" />ja';
54  $expected = array('hi', '<f:testing attribute="Hallo>{yep}" nested:attribute="jup" />', 'ja');
55  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly with > inside an attribute.');
56 
57  $source = 'hi<f:testing attribute="Hallo\\"{yep}" nested:attribute="jup" />ja';
58  $expected = array('hi', '<f:testing attribute="Hallo\\"{yep}" nested:attribute="jup" />', 'ja');
59  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly if a " is inside a double-quoted string.');
60 
61  $source = 'hi<f:testing attribute=\'Hallo>{yep}\' nested:attribute="jup" />ja';
62  $expected = array('hi', '<f:testing attribute=\'Hallo>{yep}\' nested:attribute="jup" />', 'ja');
63  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly with single quotes as attribute delimiters.');
64 
65  $source = 'hi<f:testing attribute=\'Hallo\\\'{yep}\' nested:attribute="jup" />ja';
66  $expected = array('hi', '<f:testing attribute=\'Hallo\\\'{yep}\' nested:attribute="jup" />', 'ja');
67  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly if \' is inside a single-quoted attribute.');
68 
69  $source = 'Hallo <f:testing><![CDATA[<f:notparsed>]]></f:testing>';
70  $expected = array('Hallo ', '<f:testing>', '<![CDATA[<f:notparsed>]]>', '</f:testing>');
71  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly if there is a CDATA section the parser should ignore.');
72 
73  $veryLongViewHelper ='<f:form enctype="multipart/form-data" onsubmit="void(0)" onreset="void(0)" action="someAction" arguments="{arg1: \'val1\', arg2: \'val2\'}" controller="someController" package="YourCompanyName.somePackage" subpackage="YourCompanyName.someSubpackage" section="someSection" format="txt" additionalParams="{param1: \'val1\', param2: \'val2\'}" absolute="true" addQueryString="true" argumentsToBeExcludedFromQueryString="{0: \'foo\'}" />';
74  $source = $veryLongViewHelper . 'Begin' . $veryLongViewHelper . 'End';
75  $expected = array($veryLongViewHelper, 'Begin', $veryLongViewHelper, 'End');
76  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly if the VH has lots of arguments.');
77 
78  $source = '<f:a.testing data-bar="foo"> <f:a.testing>';
79  $expected = array('<f:a.testing data-bar="foo">', ' ', '<f:a.testing>');
80  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_DYNAMICTAGS pattern did not split the input string correctly with data- attribute.');
81  }
82 
86  public function testSCAN_PATTERN_DYNAMICTAG() {
87  $pattern = $this->insertNamespaceIntoRegularExpression(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SCAN_PATTERN_TEMPLATE_VIEWHELPERTAG, array('f'));
88  $source = '<f:crop attribute="Hallo">';
89  $expected = array(
90  0 => '<f:crop attribute="Hallo">',
91  'NamespaceIdentifier' => 'f',
92  1 => 'f',
93  'MethodIdentifier' => 'crop',
94  2 => 'crop',
95  'Attributes' => ' attribute="Hallo"',
96  3 => ' attribute="Hallo"',
97  'Selfclosing' => '',
98  4 => ''
99  );
100  preg_match($pattern, $source, $matches);
101  $this->assertEquals($expected, $matches, 'The SCAN_PATTERN_DYNAMICTAG does not match correctly.');
102 
103  $pattern = $this->insertNamespaceIntoRegularExpression(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SCAN_PATTERN_TEMPLATE_VIEWHELPERTAG, array('f'));
104  $source = '<f:crop data-attribute="Hallo">';
105  $expected = array (
106  0 => '<f:crop data-attribute="Hallo">',
107  'NamespaceIdentifier' => 'f',
108  1 => 'f',
109  'MethodIdentifier' => 'crop',
110  2 => 'crop',
111  'Attributes' => ' data-attribute="Hallo"',
112  3 => ' data-attribute="Hallo"',
113  'Selfclosing' => '',
114  4 => ''
115  );
116  preg_match($pattern, $source, $matches);
117  $this->assertEquals($expected, $matches, 'The SCAN_PATTERN_DYNAMICTAG does not match correctly with data- attributes.');
118 
119  $source = '<f:base />';
120  $expected = array(
121  0 => '<f:base />',
122  'NamespaceIdentifier' => 'f',
123  1 => 'f',
124  'MethodIdentifier' => 'base',
125  2 => 'base',
126  'Attributes' => '',
127  3 => '',
128  'Selfclosing' => '/',
129  4 => '/'
130  );
131  preg_match($pattern, $source, $matches);
132  $this->assertEquals($expected, $matches, 'The SCAN_PATTERN_DYNAMICTAG does not match correctly when there is a space before the self-closing tag.');
133 
134  $source = '<f:crop attribute="Ha\\"llo"/>';
135  $expected = array(
136  0 => '<f:crop attribute="Ha\\"llo"/>',
137  'NamespaceIdentifier' => 'f',
138  1 => 'f',
139  'MethodIdentifier' => 'crop',
140  2 => 'crop',
141  'Attributes' => ' attribute="Ha\\"llo"',
142  3 => ' attribute="Ha\\"llo"',
143  'Selfclosing' => '/',
144  4 => '/'
145  );
146  preg_match($pattern, $source, $matches);
147  $this->assertEquals($expected, $matches, 'The SCAN_PATTERN_DYNAMICTAG does not match correctly with self-closing tags.');
148 
149  $source = '<f:link.uriTo complex:attribute="Ha>llo" a="b" c=\'d\'/>';
150  $expected = array(
151  0 => '<f:link.uriTo complex:attribute="Ha>llo" a="b" c=\'d\'/>',
152  'NamespaceIdentifier' => 'f',
153  1 => 'f',
154  'MethodIdentifier' => 'link.uriTo',
155  2 => 'link.uriTo',
156  'Attributes' => ' complex:attribute="Ha>llo" a="b" c=\'d\'',
157  3 => ' complex:attribute="Ha>llo" a="b" c=\'d\'',
158  'Selfclosing' => '/',
159  4 => '/'
160  );
161  preg_match($pattern, $source, $matches);
162  $this->assertEquals($expected, $matches, 'The SCAN_PATTERN_DYNAMICTAG does not match correctly with complex attributes and > inside the attributes.');
163  }
164 
169  $pattern = $this->insertNamespaceIntoRegularExpression(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SCAN_PATTERN_TEMPLATE_CLOSINGVIEWHELPERTAG, array('f'));
170  $this->assertEquals(preg_match($pattern, '</f:bla>'), 1, 'The SCAN_PATTERN_CLOSINGDYNAMICTAG does not match a tag it should match.');
171  $this->assertEquals(preg_match($pattern, '</f:bla.a >'), 1, 'The SCAN_PATTERN_CLOSINGDYNAMICTAG does not match a tag (with spaces included) it should match.');
172  $this->assertEquals(preg_match($pattern, '</t:bla>'), 0, 'The SCAN_PATTERN_CLOSINGDYNAMICTAG does match match a tag it should not match.');
173  }
174 
178  public function testSPLIT_PATTERN_TAGARGUMENTS() {
180  $source = ' test="Hallo" argument:post="\'Web" other=\'Single"Quoted\' data-foo="bar"';
181  $this->assertEquals(preg_match_all($pattern, $source, $matches, PREG_SET_ORDER), 4, 'The SPLIT_PATTERN_TAGARGUMENTS does not match correctly.');
182  $this->assertEquals('data-foo', $matches[3]['Argument']);
183  }
184 
189  $pattern = $this->insertNamespaceIntoRegularExpression(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::$SPLIT_PATTERN_SHORTHANDSYNTAX, array('f'));
190 
191  $source = 'some string{Object.bla}here as well';
192  $expected = array('some string', '{Object.bla}', 'here as well');
193  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with a simple example.');
194 
195  $source = 'some {}string\\{Object.bla}here as well';
196  $expected = array('some {}string\\', '{Object.bla}','here as well');
197  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with an escaped example. (1)');
198 
199  $source = 'some {f:viewHelper()} as well';
200  $expected = array('some ', '{f:viewHelper()}', ' as well');
201  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with an escaped example. (2)');
202 
203  $source = 'abc {f:for(arg1: post)} def';
204  $expected = array('abc ', '{f:for(arg1: post)}', ' def');
205  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with an escaped example.(3)');
206 
207  $source = 'abc {bla.blubb->f:for(param:42)} def';
208  $expected = array('abc ', '{bla.blubb->f:for(param:42)}', ' def');
209  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with an escaped example.(4)');
210 
211 
212  $source = 'abc {f:for(bla:"post{{")} def';
213  $expected = array('abc ', '{f:for(bla:"post{{")}', ' def');
214  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with an escaped example.(5)');
215 
216  $source = 'abc {f:for(param:"abc\\"abc")} def';
217  $expected = array('abc ', '{f:for(param:"abc\\"abc")}', ' def');
218  $this->assertEquals(preg_split($pattern, $source, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX pattern did not split the input string correctly with an escaped example.(6)');
219  }
220 
226 
227  $source = 'f:for(each: bla)';
228  $expected = array(
229  0 => array(
230  0 => 'f:for(each: bla)',
231  1 => 'f',
232  'NamespaceIdentifier' => 'f',
233  2 => 'for',
234  'MethodIdentifier' => 'for',
235  3 => 'each: bla',
236  'ViewHelperArguments' => 'each: bla'
237  )
238  );
239  preg_match_all($pattern, $source, $matches, PREG_SET_ORDER);
240  $this->assertEquals($matches, $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX_VIEWHELPER');
241 
242  $source = 'f:for(each: bla)->g:bla(a:"b\\"->(f:a()", cd: {a:b})';
243  $expected = array(
244  0 => array(
245  0 => 'f:for(each: bla)',
246  1 => 'f',
247  'NamespaceIdentifier' => 'f',
248  2 => 'for',
249  'MethodIdentifier' => 'for',
250  3 => 'each: bla',
251  'ViewHelperArguments' => 'each: bla'
252  ),
253  1 => array(
254  0 => 'g:bla(a:"b\\"->(f:a()", cd: {a:b})',
255  1 => 'g',
256  'NamespaceIdentifier' => 'g',
257  2 => 'bla',
258  'MethodIdentifier' => 'bla',
259  3 => 'a:"b\\"->(f:a()", cd: {a:b}',
260  'ViewHelperArguments' => 'a:"b\\"->(f:a()", cd: {a:b}'
261  )
262  );
263  preg_match_all($pattern, $source, $matches, PREG_SET_ORDER);
264  $this->assertEquals($matches, $expected, 'The SPLIT_PATTERN_SHORTHANDSYNTAX_VIEWHELPER');
265  }
266 
272  $this->assertEquals(preg_match($pattern, '{object}'), 1, 'Object accessor not identified!');
273  $this->assertEquals(preg_match($pattern, '{oBject1}'), 1, 'Object accessor not identified if there is a number and capitals inside!');
274  $this->assertEquals(preg_match($pattern, '{object.recursive}'), 1, 'Object accessor not identified if there is a dot inside!');
275  $this->assertEquals(preg_match($pattern, '{object-with-dash.recursive_value}'), 1, 'Object accessor not identified if there is a _ or - inside!');
276  $this->assertEquals(preg_match($pattern, '{f:for()}'), 1, 'Object accessor not identified if it contains only of a ViewHelper.');
277  $this->assertEquals(preg_match($pattern, '{f:for()->f:for2()}'), 1, 'Object accessor not identified if it contains only of a ViewHelper (nested).');
278  $this->assertEquals(preg_match($pattern, '{abc->f:for()}'), 1, 'Object accessor not identified if there is a ViewHelper inside!');
279  $this->assertEquals(preg_match($pattern, '{bla-blubb.recursive_value->f:for()->f:for()}'), 1, 'Object accessor not identified if there is a recursive ViewHelper inside!');
280  $this->assertEquals(preg_match($pattern, '{f:for(arg1:arg1value, arg2: "bla\\"blubb")}'), 1, 'Object accessor not identified if there is an argument inside!');
281  $this->assertEquals(preg_match($pattern, '{dash:value}'), 0, 'Object accessor identified, but was array!');
282  //$this->assertEquals(preg_match($pattern, '{}'), 0, 'Object accessor identified, and it was empty!');
283  }
284 
290  $this->assertEquals(preg_match($pattern, '{a:b}'), 1, 'Array syntax not identified!');
291  $this->assertEquals(preg_match($pattern, '{a:b, c : d}'), 1, 'Array syntax not identified in case there are multiple properties!');
292  $this->assertEquals(preg_match($pattern, '{a : 123}'), 1, 'Array syntax not identified when a number is passed as argument!');
293  $this->assertEquals(preg_match($pattern, '{a:"String"}'), 1, 'Array syntax not identified in case of a double quoted string!');
294  $this->assertEquals(preg_match($pattern, '{a:\'String\'}'), 1, 'Array syntax not identified in case of a single quoted string!');
295 
296  $expected = '{a:{bla:{x:z}, b: a}}';
297  preg_match($pattern, $expected, $match);
298  $this->assertEquals($match[0], $expected, 'If nested arrays appear, the string is not parsed correctly.');
299 
300  $expected = '{a:"{bla{{}"}';
301  preg_match($pattern, $expected, $match);
302  $this->assertEquals($match[0], $expected, 'If nested strings with {} inside appear, the string is not parsed correctly.');
303  }
304 
310 
311  $source = '{a: b, e: {c:d, e:f}}';
312  preg_match_all($pattern, $source, $matches, PREG_SET_ORDER);
313 
314  $expected = array(
315  0 => array(
316  0 => 'a: b',
317  'ArrayPart' => 'a: b',
318  1 => 'a: b',
319  'Key' => 'a',
320  2 => 'a',
321  'QuotedString' => '',
322  3 => '',
323  'VariableIdentifier' => 'b',
324  4 => 'b'
325  ),
326  1 => array(
327  0 => 'e: {c:d, e:f}',
328  'ArrayPart' => 'e: {c:d, e:f}',
329  1 => 'e: {c:d, e:f}',
330  'Key' => 'e',
331  2 => 'e',
332  'QuotedString' => '',
333  3 => '',
334  'VariableIdentifier' => '',
335  4 => '',
336  'Number' => '',
337  5 => '',
338  'Subarray' => 'c:d, e:f',
339  6 => 'c:d, e:f'
340  )
341  );
342  $this->assertEquals($matches, $expected, 'The regular expression splitting the array apart does not work!');
343  }
344 
350  public function testSCAN_PATTERN_CDATA() {
352  $this->assertEquals(preg_match($pattern, '<!-- Test -->'), 0, 'The SCAN_PATTERN_CDATA matches a comment, but it should not.');
353  $this->assertEquals(preg_match($pattern, '<![CDATA[This is some ]]>'), 1, 'The SCAN_PATTERN_CDATA does not match a simple CDATA string.');
354  $this->assertEquals(preg_match($pattern, '<![CDATA[This is<bla:test> some ]]>'), 1, 'The SCAN_PATTERN_CDATA does not match a CDATA string with tags inside..');
355  }
356 
364  protected function insertNamespaceIntoRegularExpression($regularExpression, $namespace) {
365  return str_replace('NAMESPACE', implode('|', $namespace), $regularExpression);
366  }
367 }
const NAMESPACE_SEPARATOR
Definition: Fluid.php:19
const LEGACY_NAMESPACE_SEPARATOR
Definition: Fluid.php:18