TYPO3  7.6
TemplateParserTest.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Fluid\Tests\Unit\Core\Parser;
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  * */
14 use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
15 
22 class TemplateParserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
23 {
29  {
30  $templateParser = new \TYPO3\CMS\Fluid\Core\Parser\TemplateParser();
31  $templateParser->parse(123);
32  }
33 
38  {
39  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
40  $templateParser->_call('extractNamespaceDefinitions', ' \\{namespace f4=F7\\Rocks} {namespace f4=TYPO3\Rocks\Really}');
41  $expected = array(
42  'f' => \TYPO3\CMS\Fluid\ViewHelpers::class,
43  'f4' => 'TYPO3\Rocks\Really'
44  );
45  $this->assertEquals($expected, $templateParser->getNamespaces(), 'Namespaces do not match.');
46  }
47 
52  {
53  $mockSettings = array(
54  'namespaces' => array(
55  'http://domain.tld/ns/my/viewhelpers' => 'My\Namespace',
56  'http://otherdomain.tld/ns/other/viewhelpers' => 'My\Other\Namespace'
57  )
58  );
59  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
60  $templateParser->injectSettings($mockSettings);
61  $templateParser->_call('extractNamespaceDefinitions', 'Some content <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f5="http://domain.tld/ns/my/viewhelpers"
62  xmlns:xyz="http://otherdomain.tld/ns/other/viewhelpers" />');
63  $expected = array(
64  'f' => \TYPO3\CMS\Fluid\ViewHelpers::class,
65  'f5' => 'My\Namespace',
66  'xyz' => 'My\Other\Namespace'
67  );
68  $this->assertEquals($expected, $templateParser->getNamespaces(), 'Namespaces do not match.');
69  }
70 
75  {
76  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
77  $templateParser->_call('extractNamespaceDefinitions', '<xml xmlns="http://www.w3.org/1999/xhtml" xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers" />');
78  $expected = array(
79  'f' => \TYPO3\CMS\Fluid\ViewHelpers::class,
80  'xyz' => 'Some\Package\ViewHelpers'
81  );
82  $this->assertEquals($expected, $templateParser->getNamespaces(), 'Namespaces do not match.');
83  }
84 
89  {
90  $mockSettings = array(
91  'namespaces' => array(
92  'http://domain.tld/ns/my/viewhelpers' => 'My\Namespace'
93  )
94  );
95  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
96  $templateParser->injectSettings($mockSettings);
97  $templateParser->_call('extractNamespaceDefinitions', '<xml xmlns="http://www.w3.org/1999/xhtml" xmlns:f5="http://domain.tld/ns/my/viewhelpers"
98  xmlns:xyz="http://otherdomain.tld/ns/other/viewhelpers" />');
99  $expected = array(
100  'f' => \TYPO3\CMS\Fluid\ViewHelpers::class,
101  'f5' => 'My\Namespace'
102  );
103  $this->assertEquals($expected, $templateParser->getNamespaces(), 'Namespaces do not match.');
104  }
105 
110  {
111  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
112  $templateParser->_call('extractNamespaceDefinitions', '<foo xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://domain.tld/this/will/be/ignored" />');
113  $expected = array(
114  'f' => \TYPO3\CMS\Fluid\ViewHelpers::class
115  );
116  $this->assertEquals($expected, $templateParser->getNamespaces(), 'Namespaces do not match.');
117  }
118 
124  {
125  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
126  $templateParser->_call('extractNamespaceDefinitions', '{namespace typo3=TYPO3\CMS\Fluid\Blablubb} {namespace typo3= TYPO3\Rocks\Blu}');
127  }
128 
134  {
135  $mockSettings = array(
136  'namespaces' => array(
137  'http://domain.tld/ns/my/viewhelpers' => 'My\Namespace'
138  )
139  );
140  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
141  $templateParser->injectSettings($mockSettings);
142  $templateParser->_call('extractNamespaceDefinitions', '<foo xmlns="http://www.w3.org/1999/xhtml" xmlns:typo3="http://domain.tld/ns/my/viewhelpers" />{namespace typo3=TYPO3\CMS\Fluid\Blablubb}');
143  }
144 
150  {
151  $mockSettings = array(
152  'namespaces' => array(
153  'http://domain.tld/ns/my/viewhelpers' => 'My\Namespace'
154  )
155  );
156  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
157  $templateParser->injectSettings($mockSettings);
158  $templateParser->_call('extractNamespaceDefinitions', '{namespace typo3=TYPO3\CMS\Fluid\Blablubb} <foo xmlns="http://www.w3.org/1999/xhtml" xmlns:typo3="http://domain.tld/ns/my/viewhelpers" />');
159  }
160 
168  public function extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiers(array $expectedFoundIdentifiers, $templateString, array $namespaces)
169  {
170  $mockSettings = array(
171  'namespaces' => $namespaces
172  );
173 
175  $templateParser = $this->getAccessibleMock(TemplateParser::class, array('removeXmlnsViewHelperNamespaceDeclarations'));
176  $templateParser->injectSettings($mockSettings);
177 
178  // this verifies that the method is called with the correct found identifiers
179  // and also that the templateString was not modified before calling removeXmlnsViewHelperNamespaceDeclarations
180  $templateParser
181  ->expects($this->once())
182  ->method('removeXmlnsViewHelperNamespaceDeclarations')
183  ->with($templateString, $expectedFoundIdentifiers)
184  ->willReturnArgument(0);
185  $templateParser->_call('extractNamespaceDefinitions', $templateString);
186  }
187 
192  {
193  return [
194  'bothViewHelperNamespacesDefinitionsOnlyProvideXmlnsViewHelpersUsingNonDefaultPatternViewHelpers' => array(
195  ['foo'],
196  '{namespace typo3=TYPO3\\CMS\\Fluid\\Blablubb} <div xmlns:foo="http://domain.tld/ns/foo/viewhelpers">Content</div>',
197  ['http://domain.tld/ns/foo/viewhelpers' => 'My\\Namespace']
198  ),
199  'bothViewHelperNamespacesDefinitionsOnlyProvideXmlnsViewHelpersUsingDefaultPatternViewHelpers' => array(
200  ['xyz'],
201  '{namespace typo3=TYPO3\\CMS\\Fluid\\Blablubb} <div xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">Content</div>',
202  []
203  ),
204  'xmlnsIdentifiersWithWhitespaces' => array(
205  [' ', 'foo bar', '"x y z"'],
206  '
207  <div xmlns: ="http://typo3.org/ns/Some/Package/ViewHelpers"
208  xmlns:foo bar="http://domain.tld/ns/foobar/viewhelpers"
209  xmlns:"x y z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
210 
211  Content
212  </div>
213  ',
214  ['http://domain.tld/ns/foobar/viewhelpers' => 'My\\Namespace']
215  ),
216  'xmlnsWithEqualsSign' => array(
217  ['=', 'foo=bar', '"x=y=z"'],
218  '
219  <div xmlns:=="http://typo3.org/ns/Some/Package/ViewHelpers"
220  xmlns:foo=bar="http://domain.tld/ns/foobar/viewhelpers"
221  xmlns:"x=y=z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
222 
223  Content
224  </div>
225  ',
226  ['http://domain.tld/ns/foobar/viewhelpers' => 'My\\Namespace']
227  ),
228  'nonViewHelpersXmlnsAreNotIncludedButDefaultPatternAndNonDefaultAreIncluded' => array(
229  ['xyz', 'foo'],
230  '<div xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers"
231  xmlns:foo="http://domain.tld/ns/foo/viewhelpers"
232  xmlns:bar="http://typo3.org/foo/bar">
233 
234  Content
235  </div>',
236  ['http://domain.tld/ns/foo/viewhelpers' => 'My\\Namespace']
237  ),
238  'nonViewHelpersInBetweenViewHelperXmlnsAreNotIncludedButDefaultPatternAndNonDefaultAreIncluded' => array(
239  ['xyz', 'foo'],
240  '<div xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers"
241  xmlns:bar="http://typo3.org/foo/bar"
242  xmlns:foo="http://domain.tld/ns/foo/viewhelpers">
243 
244  Content
245  </div>',
246  ['http://domain.tld/ns/foo/viewhelpers' => 'My\\Namespace']
247  ),
248  'fluidNamespaceIsFound' => array(
249  ['f'],
250  '<div xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">Content</div>',
251  []
252  ),
253  'xmlnsWithoutIdentifierIsIgnored' => array(
254  [],
255  '<div xmlns="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">Content</div>',
256  []
257  ),
258  'htmlTagAlsoFindsIdentifiers' => array(
259  ['f', 'xyz'],
260  '<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
261  xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">
262 
263  Content
264  </html>',
265  []
266  ),
267  'htmlTagWithNamespaceTypo3FluidAttributeTagAlsoFindsIdentifiers' => array(
268  ['f', 'xyz'],
269  '<html data-namespace-typo3-fluid="true"
270  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
271  xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">
272 
273  Content
274  </html>',
275  []
276  ),
277  'nonHtmlTagAlsoFindsIdentifiers' => array(
278  ['f', 'xyz'],
279  '<typo3-root
280  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
281  xmlns:xyz="http://typo3.org/ns/Some/Package/ViewHelpers">
282 
283  Content
284  </typo3-root>',
285  []
286  ),
287  ];
288  }
289 
297  public function removeXmlnsViewHelperNamespaceDeclarationsWorks($expectedOut, array $foundIdentifiers, $templateString)
298  {
299  $templateParser = $this->getAccessibleMock(TemplateParser::class, array('dummy'));
300  $templateString = $templateParser->_call('removeXmlnsViewHelperNamespaceDeclarations', $templateString, $foundIdentifiers);
301 
302  // remove tabs and trim because expected result and given have a different tab count in dataProvider which is not relevant for the parser (xml and html)
303  $this->assertSame(trim(str_replace("\t", '', $expectedOut)), trim(str_replace("\t", '', $templateString)));
304  }
305 
312  {
313  return [
314  'onlyViewHelperXmlns' => array(
315  '
316  <div >
317  <f:if condition="{demo}">Hello World</f:if>
318  </div>
319  ',
320  ['f', 'fe'],
321  '<div xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
322  xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers">
323  <f:if condition="{demo}">Hello World</f:if>
324  </div>'
325  ),
326  'xmlnsViewHelpersFoundWithNonViewHelperXmlnsAtBeginning' => array(
327  '
328  <div xmlns:z="http://www.typo3.org/foo" >
329  <f:if condition="{demo}">Hello World</f:if>
330  </div>
331  ',
332  ['f', 'fe'],
333  '
334  <div xmlns:z="http://www.typo3.org/foo"
335  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
336  xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers">
337  <f:if condition="{demo}">Hello World</f:if>
338  </div>
339  '
340  ),
341  'xmlnsViewHelpersFoundWithNonViewHelperXmlnsAtEnd' => array(
342  '
343  <div xmlns:z="http://www.typo3.org/foo">
344  <f:if condition="{demo}">Hello World</f:if>
345  </div>
346  ',
347  ['f', 'fe'],
348  '
349  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
350  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
351  xmlns:z="http://www.typo3.org/foo">
352  <f:if condition="{demo}">Hello World</f:if>
353  </div>
354  '
355  ),
356  'xmlnsViewHelpersFoundWithMultipleNonViewHelperXmlns' => array(
357  '
358  <div xmlns:y="http://www.typo3.org/bar" xmlns:z="http://www.typo3.org/foo">
359  <f:if condition="{demo}">Hello World</f:if>
360  </div>
361  ',
362  ['f', 'fe'],
363  '
364  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
365  xmlns:y="http://www.typo3.org/bar"
366  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
367  xmlns:z="http://www.typo3.org/foo">
368  <f:if condition="{demo}">Hello World</f:if>
369  </div>
370  '
371  ),
372  'xmlnsViewHelpersFoundWithNonViewHelperXmlnsBetween' => array(
373  '
374  <div xmlns:z="http://www.typo3.org/foo" >
375  <f:if condition="{demo}">Hello World</f:if>
376  </div>
377  ',
378  ['fe', 'f'],
379  '
380  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
381  xmlns:z="http://www.typo3.org/foo"
382  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">
383  <f:if condition="{demo}">Hello World</f:if>
384  </div>
385  '
386  ),
387  'removeHtmlTagWithAttributeButNoXmlnsViewHelpersFound' => array(
388  '<f:if condition="{demo}">Hello World</f:if>',
389  [],
390  '
391  <html data-namespace-typo3-fluid="true">
392  <f:if condition="{demo}">Hello World</f:if>
393  </html>
394  '
395  ),
396  'doNotRemoveHtmlTagBecauseHtmlTagNotMarkedAsFluidNamespaceDefinitionTag' => array(
397  '
398  <html xmlns:z="http://www.typo3.org/foo">
399  <f:if condition="{demo}">Hello World</f:if>
400  </html>
401  ',
402  ['fe', 'f'],
403  '
404  <html xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
405  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
406  xmlns:z="http://www.typo3.org/foo">
407  <f:if condition="{demo}">Hello World</f:if>
408  </html>
409  '
410  ),
411  'doNotModifyHtmlTagBecauseViewHelperXmlnsNotFoundInTagAndNotMarkedForRemoval' => array(
412  '
413  <html xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
414  xmlns:z="http://www.typo3.org/foo">
415  <f:if condition="{demo}">Hello World</f:if>
416  </html>
417  ',
418  ['f'], // required because without any found namespaces the method will not do any replacements
419  '
420  <html xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
421  xmlns:z="http://www.typo3.org/foo">
422  <f:if condition="{demo}">Hello World</f:if>
423  </html>
424  '
425  ),
426  'removeHtmlTagBecauseXmlnsFoundInTagAndMarkedAsFluidViewHelperDefinitionTag' => array(
427  '<f:if condition="{demo}">Hello World</f:if>',
428  ['fe'],
429  '
430  <html data-namespace-typo3-fluid="true"
431  xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
432  xmlns:z="http://www.typo3.org/foo">
433  <f:if condition="{demo}">Hello World</f:if>
434  </html>
435  '
436  ),
437  'removeHtmlTagBecauseXmlnsFoundInDifferentTagAndMarkedAsFluidViewHelperDefinitionTag' => array(
438  '<f:if condition="{demo}">Hello World</f:if>',
439  ['f'],
440  '
441  <html data-namespace-typo3-fluid="true" xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
442  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
443  xmlns:z="http://www.typo3.org/foo">
444  <f:if condition="{demo}">Hello World</f:if>
445  </html>
446  '
447  ),
448  'producesExcpedtedOutputIfFouundIdentifiersAreWrongButContainNoExistingNonViewHelperXmlns' => array(
449  '
450  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers" xmlns:z="http://www.typo3.org/foo">
451  <f:if condition="{demo}">Hello World</f:if>
452  </div>
453  ',
454  ['f', 'i'],
455  '
456  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
457  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
458  xmlns:z="http://www.typo3.org/foo">
459  <f:if condition="{demo}">Hello World</f:if>
460  </div>
461  '
462  ),
463  // this test verifies that the expected output can be wrong if the foundNameSpaces are incorrect
464  // which is why extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiers
465  // tests if the correct identifiers are found
466  'removesNonViewHelperNamespaceIfFoundIdentifiersAreWrong' => array(
467  '
468  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers" >
469  <f:if condition="{demo}">Hello World</f:if>
470  </div>
471  ',
472  ['f', 'z'],
473  '
474  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
475  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
476  xmlns:z="http://www.typo3.org/foo">
477  <f:if condition="{demo}">Hello World</f:if>
478  </div>
479  '
480  ),
481  // this verifies that the scan pattern was correctly quoted for the regular expression
482  // because if the regular expression delimiter were to be modified in the pattern,
483  // the corresponding preg_quote will fail without adaptions
484  'xmlnsWithScanPatternAsIdentifier' => array(
485  '
486  <div >
487  <f:if condition="{demo}">Hello World</f:if>
488  </div>
489  ',
491  '
492  <div xmlns:' . TemplateParser::$SCAN_PATTERN_REMOVE_VIEWHELPERS_XMLNSDECLARATIONS . '="http://typo3.org/ns/TYPO3/CMS\Demo/ViewHelpers">
493  <f:if condition="{demo}">Hello World</f:if>
494  </div>
495  '
496  ),
497  // these scenarios also need to because even if the foundIdentifiers are
498  // invalid the method should still work as expected,
499  // Furthermore, currently these patterns are allowed for foundIdentifiers
500  // see also test extractNamespaceDefinitionsCallsRemoveXmlnsViewHelperNamespaceDeclarationsWithCorrectFoundIdentifiers
501  'xmlnsIdentifiersWithWhitespaces' => array(
502  '
503  <div xmlns:none xyz="http://domain.tld/ns/NoneXyz/viewhelpers" >
504 
505  <f:if condition="{demo}">Hello World</f:if>
506  </div>
507  ',
508  [' ', 'foo bar', '"x y z"'],
509  '
510  <div xmlns: ="http://typo3.org/ns/Some/Package/ViewHelpers"
511  xmlns:foo bar="http://domain.tld/ns/foobar/viewhelpers"
512  xmlns:none xyz="http://domain.tld/ns/NoneXyz/viewhelpers"
513  xmlns:"x y z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
514 
515  <f:if condition="{demo}">Hello World</f:if>
516  </div>
517  '
518  ),
519  'xmlnsWithRegularExpressionAsIdentifier' => array(
520  '
521  <div xmlns:z="http://www.typo3.org/foo">
522  <f:if condition="{demo}">Hello World</f:if>
523  </div>
524  ',
525  ['f', 'fe', '.*.?\\s'],
526  '
527  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
528  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
529  xmlns:.*.?\\s="http://typo3.org/ns/TYPO3/CMS\Demo/ViewHelpers"
530  xmlns:z="http://www.typo3.org/foo">
531  <f:if condition="{demo}">Hello World</f:if>
532  </div>
533  '
534  ),
535  'xmlnsWithRegularExpressionDelimiterAsIdentifier' => array(
536  '
537  <div xmlns:z="http://www.typo3.org/foo">
538  <f:if condition="{demo}">Hello World</f:if>
539  </div>
540  ',
541  ['f', 'fe', '/'],
542  '
543  <div xmlns:fe="http://typo3.org/ns/TYPO3/CMS/Frontend/ViewHelpers"
544  xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
545  xmlns:/="http://typo3.org/ns/TYPO3/CMS\Demo/ViewHelpers"
546  xmlns:z="http://www.typo3.org/foo">
547  <f:if condition="{demo}">Hello World</f:if>
548  </div>
549  '
550  ),
551  'xmlnsWithEqualsSign' => array(
552  '
553  <div xmlns:none=xyz="http://domain.tld/ns/NoneXyz/viewhelpers" >
554 
555  <f:if condition="{demo}">Hello World</f:if>
556  </div>
557  ',
558  ['=', 'foo=bar', '"x=y=z"'],
559  '
560  <div xmlns:=="http://typo3.org/ns/Some/Package/ViewHelpers"
561  xmlns:foo=bar="http://domain.tld/ns/foobar/viewhelpers"
562  xmlns:none=xyz="http://domain.tld/ns/NoneXyz/viewhelpers"
563  xmlns:"x=y=z"="http://typo3.org/ns/My/Xyz/ViewHelpers">
564 
565  <f:if condition="{demo}">Hello World</f:if>
566  </div>
567  '
568  )
569  ];
570  }
571 
576  {
577  $mockTemplateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'), array(), '', false);
578  $result = $mockTemplateParser->_call('resolveViewHelperName', 'f', 'foo.bar.baz');
579  $expected = 'TYPO3\CMS\Fluid\ViewHelpers\Foo\Bar\BazViewHelper';
580  $this->assertEquals($expected, $result, 'The name of the View Helper Name could not be resolved.');
581  }
582 
587  {
588  $mockTemplateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'), array(), '', false);
589  $actual = $mockTemplateParser->_call('resolveViewHelperName', 'f', 'myown');
590  $expected = 'TYPO3\CMS\Fluid\ViewHelpers\MyownViewHelper';
591  $this->assertEquals($expected, $actual);
592  }
593 
596  public function quotedStrings()
597  {
598  return array(
599  array('"no quotes here"', 'no quotes here'),
600  array("'no quotes here'", 'no quotes here'),
601  array("'this \"string\" had \\'quotes\\' in it'", 'this "string" had \'quotes\' in it'),
602  array('"this \\"string\\" had \'quotes\' in it"', 'this "string" had \'quotes\' in it'),
603  array('"a weird \"string\" \'with\' *freaky* \\\\stuff', 'a weird "string" \'with\' *freaky* \\stuff'),
604  array('\'\\\'escaped quoted string in string\\\'\'', '\'escaped quoted string in string\'')
605  );
606  }
607 
612  public function unquoteStringReturnsUnquotedStrings($quoted, $unquoted)
613  {
614  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
615  $this->assertEquals($unquoted, $templateParser->_call('unquoteString', $quoted));
616  }
617 
620  public function templatesToSplit()
621  {
622  return array(
623  array('TemplateParserTestFixture01-shorthand'),
624  array('TemplateParserTestFixture06'),
625  array('TemplateParserTestFixture14')
626  );
627  }
628 
634  {
635  $template = file_get_contents(__DIR__ . '/Fixtures/' . $templateName . '.html', FILE_TEXT);
636  $expectedResult = require(__DIR__ . '/Fixtures/' . $templateName . '-split.php');
637  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
638  $this->assertSame($expectedResult, $templateParser->_call('splitTemplateAtDynamicTags', $template), 'Filed for ' . $templateName);
639  }
640 
645  {
646  $mockRootNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode::class);
647 
648  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
649  $mockState->expects($this->once())->method('setRootNode')->with($mockRootNode);
650  $mockState->expects($this->once())->method('pushNodeToStack')->with($mockRootNode);
651  $mockState->expects($this->once())->method('countNodeStack')->will($this->returnValue(1));
652 
653  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
654  $mockObjectManager->expects($this->at(0))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class)->will($this->returnValue($mockState));
655  $mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode::class)->will($this->returnValue($mockRootNode));
656 
657  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
658  $templateParser->_set('objectManager', $mockObjectManager);
659  $templateParser->_call('buildObjectTree', array(), \TYPO3\CMS\Fluid\Core\Parser\TemplateParser::CONTEXT_OUTSIDE_VIEWHELPER_ARGUMENTS);
660  }
661 
667  {
668  $mockRootNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode::class);
669 
670  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
671  $mockState->expects($this->once())->method('countNodeStack')->will($this->returnValue(2));
672 
673  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
674  $mockObjectManager->expects($this->at(0))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class)->will($this->returnValue($mockState));
675  $mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode::class)->will($this->returnValue($mockRootNode));
676 
677  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
678  $templateParser->_set('objectManager', $mockObjectManager);
679  $templateParser->_call('buildObjectTree', array(), \TYPO3\CMS\Fluid\Core\Parser\TemplateParser::CONTEXT_OUTSIDE_VIEWHELPER_ARGUMENTS);
680  }
681 
686  {
687  $mockRootNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode::class);
688  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
689  $mockState->expects($this->once())->method('countNodeStack')->will($this->returnValue(1));
690  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
691  $mockObjectManager->expects($this->at(0))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class)->will($this->returnValue($mockState));
692  $mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode::class)->will($this->returnValue($mockRootNode));
693 
694  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('textHandler', 'openingViewHelperTagHandler', 'closingViewHelperTagHandler', 'textAndShorthandSyntaxHandler'));
695  $templateParser->_set('objectManager', $mockObjectManager);
696  $templateParser->expects($this->at(0))->method('textAndShorthandSyntaxHandler')->with($mockState, 'The first part is simple');
697  $templateParser->expects($this->at(1))->method('textHandler')->with($mockState, '<f:for each="{a: {a: 0, b: 2, c: 4}}" as="array"><f:for each="{array}" as="value">{value} </f:for>');
698  $templateParser->expects($this->at(2))->method('openingViewHelperTagHandler')->with($mockState, 'f', 'format.printf', ' arguments="{number : 362525200}"', false);
699  $templateParser->expects($this->at(3))->method('textAndShorthandSyntaxHandler')->with($mockState, '%.3e');
700  $templateParser->expects($this->at(4))->method('closingViewHelperTagHandler')->with($mockState, 'f', 'format.printf');
701  $templateParser->expects($this->at(5))->method('textAndShorthandSyntaxHandler')->with($mockState, 'and here goes some {text} that could have {shorthand}');
702 
703  $splitTemplate = $templateParser->_call('splitTemplateAtDynamicTags', 'The first part is simple<![CDATA[<f:for each="{a: {a: 0, b: 2, c: 4}}" as="array"><f:for each="{array}" as="value">{value} </f:for>]]><f:format.printf arguments="{number : 362525200}">%.3e</f:format.printf>and here goes some {text} that could have {shorthand}');
704  $templateParser->_call('buildObjectTree', $splitTemplate, \TYPO3\CMS\Fluid\Core\Parser\TemplateParser::CONTEXT_OUTSIDE_VIEWHELPER_ARGUMENTS);
705  }
706 
711  {
712  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
713  $mockState->expects($this->never())->method('popNodeFromStack');
714 
715  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('parseArguments', 'initializeViewHelperAndAddItToStack'));
716  $templateParser->expects($this->once())->method('parseArguments')->with(array('arguments'))->will($this->returnValue(array('parsedArguments')));
717  $templateParser->expects($this->once())->method('initializeViewHelperAndAddItToStack')->with($mockState, 'namespaceIdentifier', 'methodIdentifier', array('parsedArguments'));
718 
719  $templateParser->_call('openingViewHelperTagHandler', $mockState, 'namespaceIdentifier', 'methodIdentifier', array('arguments'), false);
720  }
721 
726  {
727  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
728  $mockState->expects($this->once())->method('popNodeFromStack')->will($this->returnValue($this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NodeInterface::class)));
729 
730  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('parseArguments', 'initializeViewHelperAndAddItToStack'));
731 
732  $templateParser->_call('openingViewHelperTagHandler', $mockState, '', '', array(), true);
733  }
734 
739  {
740  $mockViewHelper = $this->getMock(\TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper::class);
741  $mockViewHelperNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class, array(), array(), '', false);
742 
743  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NodeInterface::class);
744  $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($mockViewHelperNode);
745 
746  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
747  $mockObjectManager->expects($this->at(0))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\MyownViewHelper')->will($this->returnValue($mockViewHelper));
748  $mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class)->will($this->returnValue($mockViewHelperNode));
749 
750  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
751  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
752  $mockState->expects($this->once())->method('pushNodeToStack')->with($mockViewHelperNode);
753 
754  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('abortIfUnregisteredArgumentsExist', 'abortIfRequiredArgumentsAreMissing', 'rewriteBooleanNodesInArgumentsObjectTree'));
755  $templateParser->_set('objectManager', $mockObjectManager);
756 
757  $templateParser->_call('initializeViewHelperAndAddItToStack', $mockState, 'f', 'myown', array('arguments'));
758  }
759 
764  {
765  $expectedArguments = array('expectedArguments');
766  $argumentsObjectTree = array('arguments');
767 
768  $mockViewHelper = $this->getMock(\TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper::class);
769  $mockViewHelper->expects($this->once())->method('prepareArguments')->will($this->returnValue($expectedArguments));
770  $mockViewHelperNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class, array(), array(), '', false);
771 
772  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NodeInterface::class);
773 
774  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
775  $mockObjectManager->expects($this->at(0))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\MyownViewHelper')->will($this->returnValue($mockViewHelper));
776  $mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class)->will($this->returnValue($mockViewHelperNode));
777 
778  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
779  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
780 
781  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('abortIfUnregisteredArgumentsExist', 'abortIfRequiredArgumentsAreMissing', 'rewriteBooleanNodesInArgumentsObjectTree'));
782  $templateParser->_set('objectManager', $mockObjectManager);
783  $templateParser->expects($this->once())->method('abortIfUnregisteredArgumentsExist')->with($expectedArguments, $argumentsObjectTree);
784  $templateParser->expects($this->once())->method('abortIfRequiredArgumentsAreMissing')->with($expectedArguments, $argumentsObjectTree);
785 
786  $templateParser->_call('initializeViewHelperAndAddItToStack', $mockState, 'f', 'myown', $argumentsObjectTree);
787  }
788 
793  {
794  $mockViewHelper = $this->getMock(\TYPO3\CMS\Fluid\Tests\Unit\Core\Parser\Fixtures\PostParseFacetViewHelper::class, array('prepareArguments'));
795  $mockViewHelperNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class, array(), array(), '', false);
796 
797  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NodeInterface::class);
798  $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($mockViewHelperNode);
799 
800  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
801  $mockObjectManager->expects($this->at(0))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\MyownViewHelper')->will($this->returnValue($mockViewHelper));
802  $mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class)->will($this->returnValue($mockViewHelperNode));
803 
804  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
805  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
806  $mockState->expects($this->once())->method('getVariableContainer')->will($this->returnValue($this->getMock(\TYPO3\CMS\Fluid\Core\ViewHelper\TemplateVariableContainer::class)));
807 
808  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('abortIfUnregisteredArgumentsExist', 'abortIfRequiredArgumentsAreMissing', 'rewriteBooleanNodesInArgumentsObjectTree'));
809  $templateParser->_set('objectManager', $mockObjectManager);
810 
811  $templateParser->_call('initializeViewHelperAndAddItToStack', $mockState, 'f', 'myown', array('arguments'));
812  $this->assertTrue(\TYPO3\CMS\Fluid\Tests\Unit\Core\Parser\Fixtures\PostParseFacetViewHelper::$wasCalled, 'PostParse was not called!');
813  }
814 
820  {
821  $expected = array(new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('firstArgument', 'string', '', false));
822  $actual = array('firstArgument' => 'foo', 'secondArgument' => 'bar');
823 
824  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
825 
826  $templateParser->_call('abortIfUnregisteredArgumentsExist', $expected, $actual);
827  }
828 
833  {
834  $expectedArguments = array(
835  new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('name1', 'string', 'desc', false),
836  new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('name2', 'string', 'desc', true)
837  );
838  $actualArguments = array(
839  'name1' => 'bla'
840  );
841 
842  $mockTemplateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
843 
844  $mockTemplateParser->_call('abortIfUnregisteredArgumentsExist', $expectedArguments, $actualArguments);
845  // dummy assertion to avoid "did not perform any assertions" error
846  $this->assertTrue(true);
847  }
848 
854  {
855  $expected = array(
856  new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('firstArgument', 'string', '', false),
857  new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('secondArgument', 'string', '', true)
858  );
859 
860  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
861 
862  $templateParser->_call('abortIfRequiredArgumentsAreMissing', $expected, array());
863  }
864 
869  {
870  $expectedArguments = array(
871  new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('name1', 'string', 'desc', false),
872  new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('name2', 'string', 'desc', true)
873  );
874  $actualArguments = array(
875  'name2' => 'bla'
876  );
877 
878  $mockTemplateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
879 
880  $mockTemplateParser->_call('abortIfRequiredArgumentsAreMissing', $expectedArguments, $actualArguments);
881  // dummy assertion to avoid "did not perform any assertions" error
882  $this->assertTrue(true);
883  }
884 
890  {
891  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NodeInterface::class, array(), array(), '', false);
892  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
893  $mockState->expects($this->once())->method('popNodeFromStack')->will($this->returnValue($mockNodeOnStack));
894 
895  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
896 
897  $templateParser->_call('closingViewHelperTagHandler', $mockState, 'f', 'method');
898  }
899 
905  {
906  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode::class, array(), array(), '', false);
907  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
908  $mockState->expects($this->once())->method('popNodeFromStack')->will($this->returnValue($mockNodeOnStack));
909 
910  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
911 
912  $templateParser->_call('closingViewHelperTagHandler', $mockState, 'f', 'method');
913  }
914 
919  {
920  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
921  $mockState->expects($this->exactly(2))->method('popNodeFromStack')->will($this->returnValue($this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NodeInterface::class)));
922 
923  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('recursiveArrayHandler', 'postProcessArgumentsForObjectAccessor', 'initializeViewHelperAndAddItToStack'));
924  $templateParser->expects($this->at(0))->method('recursiveArrayHandler')->with('format: "H:i"')->will($this->returnValue(array('format' => 'H:i')));
925  $templateParser->expects($this->at(1))->method('postProcessArgumentsForObjectAccessor')->with(array('format' => 'H:i'))->will($this->returnValue(array('processedArguments')));
926  $templateParser->expects($this->at(2))->method('initializeViewHelperAndAddItToStack')->with($mockState, 'f', 'format.date', array('processedArguments'));
927  $templateParser->expects($this->at(3))->method('initializeViewHelperAndAddItToStack')->with($mockState, 'f', 'base', array());
928 
929  $templateParser->_call('objectAccessorHandler', $mockState, '', '', 'f:base() f:format.date(format: "H:i")', '');
930  }
931 
936  {
937  $objectAccessorNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::class, array(), array(), '', false);
938 
939  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
940  $mockObjectManager->expects($this->once())->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::class, 'objectAccessorString')->will($this->returnValue($objectAccessorNode));
941 
942  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode::class, array(), array(), '', false);
943  $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($objectAccessorNode);
944  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
945  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
946 
947  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
948  $templateParser->_set('objectManager', $mockObjectManager);
949 
950  $templateParser->_call('objectAccessorHandler', $mockState, 'objectAccessorString', '', '', '');
951  }
952 
957  {
958  $objectAccessorNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ObjectAccessorNode::class, array(), array(), '', false);
959  $objectAccessorNodeInterceptor = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\InterceptorInterface::class);
960  $objectAccessorNodeInterceptor->expects($this->once())->method('process')->with($objectAccessorNode)->will($this->returnArgument(0));
961 
962  $parserConfiguration = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\Configuration::class);
963  $parserConfiguration->expects($this->once())->method('getInterceptors')->with(\TYPO3\CMS\Fluid\Core\Parser\InterceptorInterface::INTERCEPT_OBJECTACCESSOR)->will($this->returnValue(array($objectAccessorNodeInterceptor)));
964 
965  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
966  $mockObjectManager->expects($this->once())->method('get')->will($this->returnValue($objectAccessorNode));
967 
968  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode::class, array(), array(), '', false);
969  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
970  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
971 
972  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
973  $templateParser->_set('objectManager', $mockObjectManager);
974  $templateParser->_set('configuration', $parserConfiguration);
975 
976  $templateParser->_call('objectAccessorHandler', $mockState, 'objectAccessorString', '', '', '');
977  }
978 
981  public function argumentsStrings()
982  {
983  return array(
984  array('a="2"', array('a' => '2')),
985  array('a="2" b="foobar \' with \\" quotes"', array('a' => '2', 'b' => 'foobar \' with " quotes')),
986  array(' arguments="{number : 362525200}"', array('arguments' => '{number : 362525200}'))
987  );
988  }
989 
996  public function parseArgumentsWorksAsExpected($argumentsString, array $expected)
997  {
998  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('buildArgumentObjectTree'));
999  $templateParser->expects($this->any())->method('buildArgumentObjectTree')->will($this->returnArgument(0));
1000 
1001  $this->assertSame($expected, $templateParser->_call('parseArguments', $argumentsString));
1002  }
1003 
1008  {
1009  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
1010  $mockObjectManager->expects($this->once())->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode::class, 'a very plain string')->will($this->returnValue('theTextNode'));
1011 
1012  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('dummy'));
1013  $templateParser->_set('objectManager', $mockObjectManager);
1014 
1015  $this->assertEquals('theTextNode', $templateParser->_call('buildArgumentObjectTree', 'a very plain string'));
1016  }
1017 
1022  {
1023  $objectTree = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
1024  $objectTree->expects($this->once())->method('getRootNode')->will($this->returnValue('theRootNode'));
1025 
1026  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('splitTemplateAtDynamicTags', 'buildObjectTree'));
1027  $templateParser->expects($this->at(0))->method('splitTemplateAtDynamicTags')->with('a <very> {complex} string')->will($this->returnValue('split string'));
1028  $templateParser->expects($this->at(1))->method('buildObjectTree')->with('split string')->will($this->returnValue($objectTree));
1029 
1030  $this->assertEquals('theRootNode', $templateParser->_call('buildArgumentObjectTree', 'a <very> {complex} string'));
1031  }
1032 
1037  {
1038  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
1039  $mockObjectManager->expects($this->any())->method('get')->will($this->returnArgument(1));
1040  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
1041 
1042  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('objectAccessorHandler', 'arrayHandler', 'textHandler'));
1043  $templateParser->_set('objectManager', $mockObjectManager);
1044  $templateParser->expects($this->at(0))->method('objectAccessorHandler')->with($mockState, 'someThing.absolutely', '', '', '');
1045  $templateParser->expects($this->at(1))->method('textHandler')->with($mockState, ' "fishy" is \'going\' ');
1046  $templateParser->expects($this->at(2))->method('arrayHandler')->with($mockState, 'on: "here"');
1047 
1048  $text = '{someThing.absolutely} "fishy" is \'going\' {on: "here"}';
1049  $templateParser->_call('textAndShorthandSyntaxHandler', $mockState, $text, \TYPO3\CMS\Fluid\Core\Parser\TemplateParser::CONTEXT_INSIDE_VIEWHELPER_ARGUMENTS);
1050  }
1051 
1056  {
1057  $arrayNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ArrayNode::class, array(), array(array()));
1058  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode::class, array(), array(), '', false);
1059  $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($arrayNode);
1060  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
1061  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
1062 
1063  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
1064  $mockObjectManager->expects($this->once())->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ArrayNode::class, 'processedArrayText')->will($this->returnValue($arrayNode));
1065 
1066  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('recursiveArrayHandler'));
1067  $templateParser->_set('objectManager', $mockObjectManager);
1068  $templateParser->expects($this->once())->method('recursiveArrayHandler')->with('arrayText')->will($this->returnValue('processedArrayText'));
1069 
1070  $templateParser->_call('arrayHandler', $mockState, 'arrayText');
1071  }
1072 
1075  public function arrayTexts()
1076  {
1077  return array(
1078  array(
1079  'key1: "foo", key2: \'bar\', key3: someVar, key4: 123, key5: { key6: "baz" }',
1080  array('key1' => 'foo', 'key2' => 'bar', 'key3' => 'someVar', 'key4' => 123.0, 'key5' => array('key6' => 'baz'))
1081  ),
1082  array(
1083  'key1: "\'foo\'", key2: \'\\\'bar\\\'\'',
1084  array('key1' => '\'foo\'', 'key2' => '\'bar\'')
1085  )
1086  );
1087  }
1088 
1093  public function recursiveArrayHandlerReturnsExpectedArray($arrayText, $expectedArray)
1094  {
1095  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
1096  $mockObjectManager->expects($this->any())->method('get')->will($this->returnArgument(1));
1097 
1098  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('buildArgumentObjectTree'));
1099  $templateParser->_set('objectManager', $mockObjectManager);
1100  $templateParser->expects($this->any())->method('buildArgumentObjectTree')->will($this->returnArgument(0));
1101 
1102  $this->assertSame($expectedArray, $templateParser->_call('recursiveArrayHandler', $arrayText));
1103  }
1104 
1109  {
1110  $textNode = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode::class, array(), array(), '', false);
1111  $textInterceptor = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\InterceptorInterface::class);
1112  $textInterceptor->expects($this->once())->method('process')->with($textNode)->will($this->returnArgument(0));
1113 
1114  $parserConfiguration = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\Configuration::class);
1115  $parserConfiguration->expects($this->once())->method('getInterceptors')->with(\TYPO3\CMS\Fluid\Core\Parser\InterceptorInterface::INTERCEPT_TEXT)->will($this->returnValue(array($textInterceptor)));
1116 
1117  $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
1118  $mockObjectManager->expects($this->once())->method('get')->with(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode::class, 'string')->will($this->returnValue($textNode));
1119 
1120  $mockNodeOnStack = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode::class, array(), array(), '', false);
1121  $mockNodeOnStack->expects($this->once())->method('addChildNode')->with($textNode);
1122  $mockState = $this->getMock(\TYPO3\CMS\Fluid\Core\Parser\ParsingState::class);
1123  $mockState->expects($this->once())->method('getNodeFromStack')->will($this->returnValue($mockNodeOnStack));
1124 
1125  $templateParser = $this->getAccessibleMock(\TYPO3\CMS\Fluid\Core\Parser\TemplateParser::class, array('splitTemplateAtDynamicTags', 'buildObjectTree'));
1126  $templateParser->_set('objectManager', $mockObjectManager);
1127  $templateParser->_set('configuration', $parserConfiguration);
1128 
1129  $templateParser->_call('textHandler', $mockState, 'string');
1130  }
1131 }