‪TYPO3CMS  9.5
FlexFormToolsTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Doctrine\DBAL\Driver\Statement;
19 use Prophecy\Argument;
52 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
53 
57 class ‪FlexFormToolsTest extends UnitTestCase
58 {
62  protected ‪$resetSingletonInstances = true;
63 
67  public function ‪setUp()
68  {
69  parent::setUp();
70  // Underlying static GeneralUtility::xml2array() uses caches that have to be mocked here
71  $cacheManagerProphecy = $this->prophesize(CacheManager::class);
72  $cacheProphecy = $this->prophesize(FrontendInterface::class);
73  $cacheManagerProphecy->getCache('cache_runtime')->willReturn($cacheProphecy->reveal());
74  $cacheProphecy->get(Argument::cetera())->willReturn(false);
75  $cacheProphecy->set(Argument::cetera())->willReturn(false);
76  GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
77  }
78 
83  {
84  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
85  DataStructureIdentifierPreProcessHookThrowException::class,
86  ];
87  $this->expectException(\RuntimeException::class);
88  $this->expectExceptionCode(1478098527);
89  (new ‪FlexFormTools())->getDataStructureIdentifier([], 'aTableName', 'aFieldName', []);
90  }
91 
96  {
97  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
98  DataStructureIdentifierPreProcessHookReturnString::class
99  ];
100  $this->expectException(\RuntimeException::class);
101  $this->expectExceptionCode(1478096535);
102  (new ‪FlexFormTools())->getDataStructureIdentifier([], 'aTableName', 'aFieldName', []);
103  }
104 
109  {
110  $fieldTca = [
111  'config' => [
112  'ds' => [
113  'default' => '<T3DataStructure>...'
114  ],
115  ],
116  ];
117  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
118  DataStructureIdentifierPreProcessHookReturnEmptyArray::class
119  ];
120  $expected = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
121  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []));
122  }
123 
128  {
129  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
130  DataStructureIdentifierPreProcessHookReturnArray::class
131  ];
132  $expected = '{"type":"myExtension","further":"data"}';
133  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier([], 'aTableName', 'aFieldName', []));
134  }
135 
140  {
141  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
142  DataStructureIdentifierPreProcessHookReturnEmptyArray::class,
143  DataStructureIdentifierPreProcessHookReturnArray::class,
144  DataStructureIdentifierPreProcessHookThrowException::class
145  ];
146  $expected = '{"type":"myExtension","further":"data"}';
147  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier([], 'aTableName', 'aFieldName', []));
148  }
149 
154  {
155  $fieldTca = [
156  'config' => [
157  'ds' => [
158  'default' => '<T3DataStructure>...'
159  ],
160  ],
161  ];
162  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
163  DataStructureIdentifierPostProcessHookThrowException::class,
164  ];
165  $this->expectException(\RuntimeException::class);
166  $this->expectExceptionCode(1478342067);
167  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []);
168  }
169 
174  {
175  $fieldTca = [
176  'config' => [
177  'ds' => [
178  'default' => '<T3DataStructure>...'
179  ],
180  ],
181  ];
182  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
183  DataStructureIdentifierPostProcessHookReturnString::class
184  ];
185  $this->expectException(\RuntimeException::class);
186  $this->expectExceptionCode(1478350835);
187  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []);
188  }
189 
194  {
195  $fieldTca = [
196  'config' => [
197  'ds' => [
198  'default' => '<T3DataStructure>...'
199  ],
200  ],
201  ];
202  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
203  DataStructureIdentifierPostProcessHookReturnEmptyArray::class
204  ];
205  $this->expectException(\RuntimeException::class);
206  $this->expectExceptionCode(1478350835);
207  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []);
208  }
209 
214  {
215  $fieldTca = [
216  'config' => [
217  'ds' => [
218  'default' => '<T3DataStructure>...'
219  ],
220  ],
221  ];
222  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
223  DataStructureIdentifierPostProcessHookReturnArray::class
224  ];
225  $expected = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default","myExtensionData":"foo"}';
226  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []));
227  }
228 
233  {
234  $fieldTca = [
235  'config' => [
236  'ds' => 'someStringOnly',
237  // no ds_pointerField,
238  ],
239  ];
240  $this->expectException(\RuntimeException::class);
241  $this->expectExceptionCode(1463826960);
242  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []);
243  }
244 
249  {
250  $fieldTca = [
251  'config' => [
252  'ds' => [
253  'default' => '<T3DataStructure>...'
254  ],
255  ],
256  ];
257  $expected = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
258  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []));
259  }
260 
265  {
266  $fieldTca = [
267  'config' => [
268  'ds' => [],
269  ],
270  ];
271  $this->expectException(InvalidTcaException::class);
272  $this->expectExceptionCode(1463652560);
273  $this->assertSame('default', (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []));
274  }
275 
280  {
281  $fieldTca = [
282  'config' => [
283  'ds' => [],
284  'ds_pointerField' => 'first,second,third',
285  ],
286  ];
287  $this->expectException(\RuntimeException::class);
288  $this->expectExceptionCode(1463577497);
289  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', []);
290  }
291 
296  {
297  $fieldTca = [
298  'config' => [
299  'ds' => [],
300  'ds_pointerField' => 'notExist',
301  ],
302  ];
303  $row = [
304  'foo' => '',
305  ];
306  $this->expectException(\RuntimeException::class);
307  $this->expectExceptionCode(1463578899);
308  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
309  }
310 
315  {
316  $fieldTca = [
317  'config' => [
318  'ds' => [],
319  'ds_pointerField' => 'notExist,second',
320  ],
321  ];
322  $row = [
323  'second' => '',
324  ];
325  $this->expectException(\RuntimeException::class);
326  $this->expectExceptionCode(1463578899);
327  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
328  }
329 
334  {
335  $fieldTca = [
336  'config' => [
337  'ds' => [],
338  'ds_pointerField' => 'first,notExist',
339  ],
340  ];
341  $row = [
342  'first' => '',
343  ];
344  $this->expectException(\RuntimeException::class);
345  $this->expectExceptionCode(1463578900);
346  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
347  }
348 
353  {
354  $fieldTca = [
355  'config' => [
356  'ds' => [
357  'thePointerValue' => 'FILE:...'
358  ],
359  'ds_pointerField' => 'aField'
360  ],
361  ];
362  $row = [
363  'aField' => 'thePointerValue',
364  ];
365  $expected = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"thePointerValue"}';
366  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row));
367  }
368 
373  {
374  $fieldTca = [
375  'config' => [
376  'ds' => [
377  'default' => 'theDataStructure'
378  ],
379  'ds_pointerField' => 'aField'
380  ],
381  ];
382  $row = [
383  'aField' => 'thePointerValue',
384  ];
385  $expected = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
386  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row));
387  }
388 
393  {
394  $fieldTca = [
395  'config' => [
396  'ds' => [
397  'aDifferentDataStructure' => 'aDataStructure'
398  ],
399  'ds_pointerField' => 'aField'
400  ],
401  ];
402  $row = [
403  'uid' => 23,
404  'aField' => 'aNotDefinedDataStructure',
405  ];
406  $this->expectException(InvalidSinglePointerFieldException::class);
407  $this->expectExceptionCode(1463653197);
408  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
409  }
410 
415  {
416  return [
417  'direct match of two fields' => [
418  [
419  // $row
420  'firstField' => 'firstValue',
421  'secondField' => 'secondValue',
422  ],
423  [
424  // registered data structure names
425  'firstValue,secondValue' => '',
426  ],
427  // expected name
428  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"firstValue,secondValue"}'
429  ],
430  'match on first field, * for second' => [
431  [
432  'firstField' => 'firstValue',
433  'secondField' => 'secondValue',
434  ],
435  [
436  'firstValue,*' => '',
437  ],
438  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"firstValue,*"}'
439  ],
440  'match on second field, * for first' => [
441  [
442  'firstField' => 'firstValue',
443  'secondField' => 'secondValue',
444  ],
445  [
446  '*,secondValue' => '',
447  ],
448  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"*,secondValue"}'
449  ],
450  'match on first field only' => [
451  [
452  'firstField' => 'firstValue',
453  'secondField' => 'secondValue',
454  ],
455  [
456  'firstValue' => '',
457  ],
458  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"firstValue"}'
459  ],
460  'fallback to default' => [
461  [
462  'firstField' => 'firstValue',
463  'secondField' => 'secondValue',
464  ],
465  [
466  'default' => '',
467  ],
468  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}'
469  ],
470  'chain falls through with no match on second value to *' => [
471  [
472  'firstField' => 'firstValue',
473  'secondField' => 'noMatch',
474  ],
475  [
476  'firstValue,secondValue' => '',
477  'firstValue,*' => '',
478  ],
479  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"firstValue,*"}'
480  ],
481  'chain falls through with no match on first value to *' => [
482  [
483  'firstField' => 'noMatch',
484  'secondField' => 'secondValue',
485  ],
486  [
487  'firstValue,secondValue' => '',
488  '*,secondValue' => '',
489  ],
490  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"*,secondValue"}'
491  ],
492  'chain falls through with no match on any field to default' => [
493  [
494  'firstField' => 'noMatch',
495  'secondField' => 'noMatchToo',
496  ],
497  [
498  'firstValue,secondValue' => '',
499  'secondValue,*' => '',
500  'default' => '',
501  ],
502  '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}'
503  ],
504  ];
505  }
506 
514  public function ‪getDataStructureIdentifierReturnsValidNameForTwoFieldCombinations(array $row, array $ds, string $expected): void
515  {
516  $fieldTca = [
517  'config' => [
518  'ds' => $ds,
519  'ds_pointerField' => 'firstField,secondField'
520  ],
521  ];
522  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row));
523  }
524 
529  {
530  $fieldTca = [
531  'config' => [
532  'ds' => [
533  'firstValue,secondValue' => '',
534  ],
535  'ds_pointerField' => 'firstField,secondField'
536  ],
537  ];
538  $row = [
539  'uid' => 23,
540  'firstField' => 'noMatch',
541  'secondField' => 'noMatchToo',
542  ];
543  $this->expectException(InvalidCombinedPointerFieldException::class);
544  $this->expectExceptionCode(1463678524);
545  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
546  }
547 
552  {
553  $fieldTca = [
554  'config' => [
555  'ds_pointerField' => 'tx_templavoila_ds',
556  'ds_pointerField_searchParent' => 'pid',
557  ]
558  ];
559  $row = [
560  'uid' => 23,
561  'pid' => 42,
562  'tx_templavoila_ds' => null,
563  ];
564 
565  // Prophecies and revelations for a lot of the database stack classes
566  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
567  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
568  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
569  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
570  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
571  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
572  $statementProphecy = $this->prophesize(Statement::class);
573 
574  // Register connection pool revelation in framework, this is the entry point used by system under test
575  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
576 
577  // Simulate method call flow on database objects and verify correct query is built
578  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
579  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
580  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
581  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
582  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
583  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
584  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
585  $queryBuilderProphecy->createNamedParameter(42, 1)->willReturn(42);
586  $expressionBuilderProphecy->eq('uid', 42)->shouldBeCalled()->willReturn('uid = 42');
587  $queryBuilderProphecy->where('uid = 42')->shouldBeCalled()->willReturn($queryBuilderRevelation);
588  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
589 
590  // Error case that is tested here: Do not return a valid parent row from db -> exception should be thrown
591  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderProphecy);
592  $this->expectException(InvalidParentRowException::class);
593  $this->expectExceptionCode(1463833794);
594  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
595  }
596 
601  {
602  ‪$GLOBALS['BE_USER'] = new ‪BackendUserAuthentication();
603 
604  $fieldTca = [
605  'config' => [
606  'ds_pointerField' => 'tx_templavoila_ds',
607  'ds_pointerField_searchParent' => 'pid',
608  ]
609  ];
610  $initialRow = [
611  'uid' => 3,
612  'pid' => 2,
613  'tx_templavoila_ds' => null,
614  ];
615  $secondRow = [
616  'uid' => 2,
617  'pid' => 1,
618  'tx_templavoila_ds' => null,
619  ];
620  $thirdRow = [
621  'uid' => 1,
622  'pid' => 3,
623  'tx_templavoila_ds' => null,
624  ];
625 
626  // Prophecies and revelations for a lot of the database stack classes
627  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
628  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
629  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
630  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
631  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
632  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
633  $statementProphecy = $this->prophesize(Statement::class);
634 
635  // Register connection pool revelation in framework, this is the entry point used by system under test
636  // Two queries are done, so we need two instances
637  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
638  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
639 
640  // Simulate method call flow on database objects and verify correct query is built
641  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
642  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
643  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
644  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
645  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
646  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
647  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
648  $queryBuilderProphecy->createNamedParameter(2, 1)->willReturn(2);
649  $queryBuilderProphecy->createNamedParameter(1, 1)->willReturn(1);
650  $expressionBuilderProphecy->eq('uid', 2)->shouldBeCalled()->willReturn('uid = 2');
651  $expressionBuilderProphecy->eq('uid', 1)->shouldBeCalled()->willReturn('uid = 1');
652  $queryBuilderProphecy->where('uid = 2')->shouldBeCalled()->willReturn($queryBuilderRevelation);
653  $queryBuilderProphecy->where('uid = 1')->shouldBeCalled()->willReturn($queryBuilderRevelation);
654  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
655  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderProphecy);
656 
657  // First db call returns $secondRow, second returns $thirdRow, which points back to $initialRow -> exception
658  $statementProphecy->fetchColumn(0)->willReturn(1);
659  $statementProphecy->fetch()->willReturn($secondRow, $thirdRow);
660 
661  $this->expectException(InvalidParentRowLoopException::class);
662  $this->expectExceptionCode(1464110956);
663  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $initialRow);
664  }
665 
670  {
671  ‪$GLOBALS['BE_USER'] = new ‪BackendUserAuthentication();
672 
673  $fieldTca = [
674  'config' => [
675  'ds_pointerField' => 'tx_templavoila_ds',
676  'ds_pointerField_searchParent' => 'pid',
677  ]
678  ];
679  $initialRow = [
680  'uid' => 3,
681  'pid' => 2,
682  'tx_templavoila_ds' => null,
683  ];
684  $secondRow = [
685  'uid' => 2,
686  'pid' => 1,
687  'tx_templavoila_ds' => null,
688  ];
689  $thirdRow = [
690  'uid' => 1,
691  'pid' => 0,
692  'tx_templavoila_ds' => null,
693  ];
694 
695  // Prophecies and revelations for a lot of the database stack classes
696  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
697  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
698  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
699  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
700  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
701  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
702  $statementProphecy = $this->prophesize(Statement::class);
703 
704  // Register connection pool revelation in framework, this is the entry point used by system under test
705  // Two queries are done, so we need two instances
706  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
707  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
708 
709  // Simulate method call flow on database objects and verify correct query is built
710  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
711  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
712  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
713  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
714  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
715  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
716  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
717  $queryBuilderProphecy->createNamedParameter(2, 1)->willReturn(2);
718  $queryBuilderProphecy->createNamedParameter(1, 1)->willReturn(1);
719  $expressionBuilderProphecy->eq('uid', 2)->shouldBeCalled()->willReturn('uid = 2');
720  $expressionBuilderProphecy->eq('uid', 1)->shouldBeCalled()->willReturn('uid = 1');
721  $queryBuilderProphecy->where('uid = 2')->shouldBeCalled()->willReturn($queryBuilderRevelation);
722  $queryBuilderProphecy->where('uid = 1')->shouldBeCalled()->willReturn($queryBuilderRevelation);
723  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
724  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderRevelation);
725  $statementProphecy->fetchColumn(0)->shouldBeCalled()->willReturn(1);
726 
727  // First db call returns $secondRow, second returns $thirdRow. $thirdRow has pid 0 and still no ds -> exception
728  $statementProphecy->fetch()->willReturn($secondRow, $thirdRow);
729 
730  $this->expectException(InvalidParentRowRootException::class);
731  $this->expectExceptionCode(1464112555);
732  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $initialRow);
733  }
734 
739  {
740  $fieldTca = [
741  'config' => [
742  'ds_pointerField' => 'aPointerField',
743  ]
744  ];
745  $row = [
746  'aPointerField' => null,
747  ];
748  $this->expectException(InvalidPointerFieldValueException::class);
749  $this->expectExceptionCode(1464114011);
750  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
751  }
752 
757  {
758  $fieldTca = [
759  'config' => [
760  'ds_pointerField' => 'aPointerField',
761  ]
762  ];
763  $row = [
764  'aPointerField' => 3,
765  ];
766  $this->expectException(InvalidTcaException::class);
767  $this->expectExceptionCode(1464115639);
768  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
769  }
770 
775  {
776  $fieldTca = [
777  'config' => [
778  'ds_pointerField' => 'aPointerField',
779  'ds_tableField' => 'misconfigured',
780  ]
781  ];
782  $row = [
783  'aPointerField' => 3,
784  ];
785  $this->expectException(InvalidTcaException::class);
786  $this->expectExceptionCode(1464116002);
787  (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row);
788  }
789 
794  {
795  $fieldTca = [
796  'config' => [
797  'ds_pointerField' => 'aPointerField',
798  ]
799  ];
800  $row = [
801  'uid' => 42,
802  'aPointerField' => '<T3DataStructure>...',
803  ];
804  $expected = '{"type":"record","tableName":"aTableName","uid":42,"fieldName":"aPointerField"}';
805  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row));
806  }
807 
812  {
813  ‪$GLOBALS['BE_USER'] = new ‪BackendUserAuthentication();
814 
815  $fieldTca = [
816  'config' => [
817  'ds_pointerField' => 'tx_templavoila_ds',
818  'ds_pointerField_searchParent' => 'pid',
819  ]
820  ];
821  $initialRow = [
822  'uid' => 3,
823  'pid' => 2,
824  'tx_templavoila_ds' => null,
825  ];
826  $secondRow = [
827  'uid' => 2,
828  'pid' => 1,
829  'tx_templavoila_ds' => 0,
830  ];
831  $thirdRow = [
832  'uid' => 1,
833  'pid' => 0,
834  'tx_templavoila_ds' => '<T3DataStructure>...',
835  ];
836 
837  // Prophecies and revelations for a lot of the database stack classes
838  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
839  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
840  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
841  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
842  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
843  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
844  $statementProphecy = $this->prophesize(Statement::class);
845 
846  // Register connection pool revelation in framework, this is the entry point used by system under test
847  // Two queries are done, so we need two instances
848  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
849  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
850 
851  // Simulate method call flow on database objects and verify correct query is built
852  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
853  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
854  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
855  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
856  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
857  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
858  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
859  $queryBuilderProphecy->createNamedParameter(2, 1)->willReturn(2);
860  $queryBuilderProphecy->createNamedParameter(1, 1)->willReturn(1);
861  $expressionBuilderProphecy->eq('uid', 2)->shouldBeCalled()->willReturn('uid = 2');
862  $expressionBuilderProphecy->eq('uid', 1)->shouldBeCalled()->willReturn('uid = 1');
863  $queryBuilderProphecy->where('uid = 2')->shouldBeCalled()->willReturn($queryBuilderRevelation);
864  $queryBuilderProphecy->where('uid = 1')->shouldBeCalled()->willReturn($queryBuilderRevelation);
865  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
866  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderRevelation);
867  $statementProphecy->fetchColumn(0)->shouldBeCalled()->willReturn(1);
868 
869  // First db call returns $secondRow, second returns $thirdRow. $thirdRow resolves ds
870  $statementProphecy->fetch()->willReturn($secondRow, $thirdRow);
871 
872  $expected = '{"type":"record","tableName":"aTableName","uid":1,"fieldName":"tx_templavoila_ds"}';
873  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $initialRow));
874  }
875 
880  {
881  ‪$GLOBALS['BE_USER'] = new ‪BackendUserAuthentication();
882 
883  $fieldTca = [
884  'config' => [
885  'ds_pointerField' => 'tx_templavoila_ds',
886  'ds_pointerField_searchParent' => 'pid',
887  ]
888  ];
889  $initialRow = [
890  'uid' => 3,
891  'pid' => 2,
892  'tx_templavoila_ds' => null,
893  ];
894  $secondRow = [
895  'uid' => 2,
896  'pid' => 1,
897  'tx_templavoila_ds' => '<T3DataStructure>...',
898  ];
899 
900  // Prophecies and revelations for a lot of the database stack classes
901  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
902  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
903  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
904  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
905  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
906  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
907  $statementProphecy = $this->prophesize(Statement::class);
908 
909  // Register connection pool revelation in framework, this is the entry point used by system under test
910  // Two queries are done, so we need two instances
911  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
912 
913  // Simulate method call flow on database objects and verify correct query is built
914  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
915  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
916  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
917  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
918  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
919  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
920  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
921  $queryBuilderProphecy->createNamedParameter(2, 1)->willReturn(2);
922  $expressionBuilderProphecy->eq('uid', 2)->shouldBeCalled()->willReturn('uid = 2');
923  $queryBuilderProphecy->where('uid = 2')->shouldBeCalled()->willReturn($queryBuilderRevelation);
924  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderRevelation);
925  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
926  $statementProphecy->fetchColumn(0)->shouldBeCalled()->willReturn(1);
927 
928  // First db call returns $secondRow. $secendRow resolves DS and does not look further up
929  $statementProphecy->fetch()->willReturn($secondRow);
930 
931  $expected = '{"type":"record","tableName":"aTableName","uid":2,"fieldName":"tx_templavoila_ds"}';
932  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $initialRow));
933  }
934 
939  {
940  ‪$GLOBALS['BE_USER'] = new ‪BackendUserAuthentication();
941 
942  $fieldTca = [
943  'config' => [
944  'ds_pointerField' => 'tx_templavoila_ds',
945  'ds_pointerField_searchParent' => 'pid',
946  'ds_pointerField_searchParent_subField' => 'tx_templavoila_next_ds',
947  ]
948  ];
949  $initialRow = [
950  'uid' => 3,
951  'pid' => 2,
952  'tx_templavoila_ds' => null,
953  'tx_templavoila_next_ds' => null,
954  ];
955  $secondRow = [
956  'uid' => 2,
957  'pid' => 1,
958  'tx_templavoila_ds' => '<T3DataStructure>...',
959  'tx_templavoila_next_ds' => 'anotherDataStructure',
960  ];
961 
962  // Prophecies and revelations for a lot of the database stack classes
963  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
964  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
965  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
966  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
967  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
968  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
969  $statementProphecy = $this->prophesize(Statement::class);
970 
971  // Register connection pool revelation in framework, this is the entry point used by system under test
972  // Two queries are done, so we need two instances
973  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
974 
975  // Simulate method call flow on database objects and verify correct query is built
976  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
977  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
978  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
979  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
980  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
981  $queryBuilderProphecy->addSelect('tx_templavoila_next_ds')->shouldBeCalled();
982  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
983  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
984  $queryBuilderProphecy->createNamedParameter(2, 1)->willReturn(2);
985  $expressionBuilderProphecy->eq('uid', 2)->shouldBeCalled()->willReturn('uid = 2');
986  $queryBuilderProphecy->where('uid = 2')->shouldBeCalled()->willReturn($queryBuilderRevelation);
987  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderRevelation);
988  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
989  $statementProphecy->fetchColumn(0)->shouldBeCalled()->willReturn(1);
990 
991  // First db call returns $secondRow. $secendRow resolves DS and does not look further up
992  $statementProphecy->fetch()->willReturn($secondRow);
993 
994  $expected = '{"type":"record","tableName":"aTableName","uid":2,"fieldName":"tx_templavoila_next_ds"}';
995  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $initialRow));
996  }
997 
1002  {
1003  $fieldTca = [
1004  'config' => [
1005  'ds_pointerField' => 'aPointerField',
1006  'ds_tableField' => 'foreignTableName:foreignTableField',
1007  ]
1008  ];
1009  $row = [
1010  'uid' => 3,
1011  'pid' => 2,
1012  'aPointerField' => 42,
1013  ];
1014  $expected = '{"type":"record","tableName":"foreignTableName","uid":42,"fieldName":"foreignTableField"}';
1015  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $row));
1016  }
1017 
1022  {
1023  ‪$GLOBALS['BE_USER'] = new ‪BackendUserAuthentication();
1024 
1025  $fieldTca = [
1026  'config' => [
1027  'ds_pointerField' => 'tx_templavoila_ds',
1028  'ds_pointerField_searchParent' => 'pid',
1029  'ds_pointerField_searchParent_subField' => 'tx_templavoila_next_ds',
1030  'ds_tableField' => 'foreignTableName:foreignTableField',
1031  ]
1032  ];
1033  $initialRow = [
1034  'uid' => 3,
1035  'pid' => 2,
1036  'tx_templavoila_ds' => null,
1037  'tx_templavoila_next_ds' => null,
1038  ];
1039  $secondRow = [
1040  'uid' => 2,
1041  'pid' => 1,
1042  'tx_templavoila_ds' => '<T3DataStructure>...',
1043  'tx_templavoila_next_ds' => '42',
1044  ];
1045 
1046  // Prophecies and revelations for a lot of the database stack classes
1047  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
1048  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
1049  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
1050  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
1051  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
1052  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
1053  $statementProphecy = $this->prophesize(Statement::class);
1054 
1055  // Register connection pool revelation in framework, this is the entry point used by system under test
1056  // Two queries are done, so we need two instances
1057  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
1058 
1059  // Simulate method call flow on database objects and verify correct query is built
1060  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1061  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
1062  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
1063  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
1064  $queryBuilderProphecy->select('uid', 'pid', 'tx_templavoila_ds')->shouldBeCalled();
1065  $queryBuilderProphecy->addSelect('tx_templavoila_next_ds')->shouldBeCalled();
1066  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1067  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
1068  $queryBuilderProphecy->createNamedParameter(2, 1)->willReturn(2);
1069  $expressionBuilderProphecy->eq('uid', 2)->shouldBeCalled()->willReturn('uid = 2');
1070  $queryBuilderProphecy->where('uid = 2')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1071  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
1072  $queryBuilderProphecy->count('uid')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1073  $statementProphecy->fetchColumn(0)->shouldBeCalled()->willReturn(1);
1074 
1075  // First db call returns $secondRow. $secendRow resolves DS and does not look further up
1076  $statementProphecy->fetch()->willReturn($secondRow);
1077 
1078  $expected = '{"type":"record","tableName":"foreignTableName","uid":42,"fieldName":"foreignTableField"}';
1079  $this->assertSame($expected, (new ‪FlexFormTools())->getDataStructureIdentifier($fieldTca, 'aTableName', 'aFieldName', $initialRow));
1080  }
1081 
1086  {
1087  $this->expectException(InvalidIdentifierException::class);
1088  $this->expectExceptionCode(1478100828);
1089  (new ‪FlexFormTools())->parseDataStructureByIdentifier('');
1090  }
1091 
1096  {
1097  $this->expectException(\RuntimeException::class);
1098  $this->expectExceptionCode(1478345642);
1099  (new ‪FlexFormTools())->parseDataStructureByIdentifier('egon');
1100  }
1101 
1106  {
1107  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1108  DataStructureParsePreProcessHookThrowException::class,
1109  ];
1110  $this->expectException(\RuntimeException::class);
1111  $this->expectExceptionCode(1478112411);
1112  (new ‪FlexFormTools())->parseDataStructureByIdentifier('{"some":"input"}');
1113  }
1114 
1119  {
1120  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1121  DataStructureParsePreProcessHookReturnObject::class
1122  ];
1123  $this->expectException(\RuntimeException::class);
1124  $this->expectExceptionCode(1478168512);
1125  (new ‪FlexFormTools())->parseDataStructureByIdentifier('{"some":"input"}');
1126  }
1127 
1132  {
1133  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1134  DataStructureParsePreProcessHookReturnEmptyString::class
1135  ];
1136  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1137  <T3DataStructure>
1138  <sheets></sheets>
1139  </T3DataStructure>
1140  ';
1141  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1142  $expected = [
1143  'sheets' => '',
1144  ];
1145  $this->assertSame($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1146  }
1147 
1152  {
1153  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1154  DataStructureParsePreProcessHookReturnString::class
1155  ];
1156  $identifier = '{"type":"myExtension"}';
1157  $expected = [
1158  'sheets' => '',
1159  ];
1160  $this->assertSame($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1161  }
1162 
1167  {
1168  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1169  DataStructureParsePreProcessHookReturnEmptyString::class,
1170  DataStructureParsePreProcessHookReturnString::class,
1171  DataStructureParsePreProcessHookThrowException::class
1172  ];
1173  $identifier = '{"type":"myExtension"}';
1174  $expected = [
1175  'sheets' => '',
1176  ];
1177  $this->assertSame($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1178  }
1179 
1184  {
1185  $this->expectException(InvalidIdentifierException::class);
1186  $this->expectExceptionCode(1478104554);
1187  (new ‪FlexFormTools())->parseDataStructureByIdentifier('{"type":"bernd"}');
1188  }
1189 
1194  {
1195  $this->expectException(\RuntimeException::class);
1196  $this->expectExceptionCode(1478113471);
1197  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName"}';
1198  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1199  }
1200 
1205  {
1206  $this->expectException(InvalidIdentifierException::class);
1207  $this->expectExceptionCode(1478105491);
1208  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1209  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1210  }
1211 
1216  {
1217  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1218  <T3DataStructure>
1219  <sheets></sheets>
1220  </T3DataStructure>
1221  ';
1222  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1223  $expected = [
1224  'sheets' => '',
1225  ];
1226  $this->assertSame($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1227  }
1228 
1233  {
1234  $this->expectException(\RuntimeException::class);
1235  $this->expectExceptionCode(1478113873);
1236  $identifier = '{"type":"record","tableName":"foreignTableName","uid":42}';
1237  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1238  }
1239 
1244  {
1245  // Prophecies and revelations for a lot of the database stack classes
1246  $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
1247  $queryBuilderRevelation = $queryBuilderProphecy->reveal();
1248  $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
1249  $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
1250  $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
1251  $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
1252  $statementProphecy = $this->prophesize(Statement::class);
1253 
1254  // Register connection pool revelation in framework, this is the entry point used by system under test
1255  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
1256 
1257  // Simulate method call flow on database objects and verify correct query is built
1258  $connectionPoolProphecy->getQueryBuilderForTable('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1259  $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
1260  $queryRestrictionContainerProphecy->add(Argument::cetera())->shouldBeCalled();
1261  $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
1262  $queryBuilderProphecy->select('dataprot')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1263  $queryBuilderProphecy->from('aTableName')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1264  $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
1265  $queryBuilderProphecy->createNamedParameter(42, 1)->willReturn(42);
1266  $expressionBuilderProphecy->eq('uid', 42)->shouldBeCalled()->willReturn('uid = 42');
1267  $queryBuilderProphecy->where('uid = 42')->shouldBeCalled()->willReturn($queryBuilderRevelation);
1268  $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
1269  $statementProphecy->fetchColumn(0)->willReturn('
1270  <T3DataStructure>
1271  <sheets></sheets>
1272  </T3DataStructure>
1273  ');
1274  $identifier = '{"type":"record","tableName":"aTableName","uid":42,"fieldName":"dataprot"}';
1275  $expected = [
1276  'sheets' => '',
1277  ];
1278  $this->assertSame($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1279  }
1280 
1285  {
1286  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default']
1287  = 'FILE:EXT:core/Does/Not/Exist.xml';
1288  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1289  $this->expectException(\RuntimeException::class);
1290  $this->expectExceptionCode(1478105826);
1291  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1292  }
1293 
1297  public function ‪parseDataStructureByIdentifierFetchesFromFile(): void
1298  {
1299  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default']
1300  = ' FILE:EXT:core/Tests/Unit/Configuration/FlexForm/Fixtures/DataStructureWithSheet.xml ';
1301  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1302  $expected = [
1303  'sheets' => [
1304  'sDEF' => [
1305  'ROOT' => [
1306  'type' => 'array',
1307  'el' => [
1308  'aFlexField' => [
1309  'TCEforms' => [
1310  'label' => 'aFlexFieldLabel',
1311  'config' => [
1312  'type' => 'input',
1313  ],
1314  ],
1315  ],
1316  ],
1317  'TCEforms' => [
1318  'sheetTitle' => 'aTitle',
1319  ],
1320  ],
1321  ],
1322  ]
1323  ];
1324  $this->assertEquals($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1325  }
1326 
1331  {
1332  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1333  <T3DataStructure>
1334  <sheets>
1335  <bar>
1336  </sheets>
1337  </T3DataStructure>
1338  ';
1339  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1340  $this->expectException(InvalidIdentifierException::class);
1341  $this->expectExceptionCode(1478106090);
1342  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1343  }
1344 
1349  {
1350  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1351  <T3DataStructure>
1352  <ROOT></ROOT>
1353  <sheets></sheets>
1354  </T3DataStructure>
1355  ';
1356  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1357  $this->expectException(\RuntimeException::class);
1358  $this->expectExceptionCode(1440676540);
1359  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1360  }
1361 
1366  {
1367  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1368  <T3DataStructure>
1369  <ROOT>
1370  <TCEforms>
1371  <sheetTitle>aTitle</sheetTitle>
1372  </TCEforms>
1373  <type>array</type>
1374  <el>
1375  <aFlexField>
1376  <TCEforms>
1377  <label>aFlexFieldLabel</label>
1378  <config>
1379  <type>input</type>
1380  </config>
1381  </TCEforms>
1382  </aFlexField>
1383  </el>
1384  </ROOT>
1385  </T3DataStructure>
1386  ';
1387  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1388  $expected = [
1389  'sheets' => [
1390  'sDEF' => [
1391  'ROOT' => [
1392  'type' => 'array',
1393  'el' => [
1394  'aFlexField' => [
1395  'TCEforms' => [
1396  'label' => 'aFlexFieldLabel',
1397  'config' => [
1398  'type' => 'input',
1399  ],
1400  ],
1401  ],
1402  ],
1403  'TCEforms' => [
1404  'sheetTitle' => 'aTitle',
1405  ],
1406  ],
1407  ],
1408  ]
1409  ];
1410  $this->assertEquals($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1411  }
1412 
1417  {
1418  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1419  <T3DataStructure>
1420  <sheets>
1421  <aSheet>
1422  EXT:core/Tests/Unit/Configuration/FlexForm/Fixtures/DataStructureOfSingleSheet.xml
1423  </aSheet>
1424  </sheets>
1425  </T3DataStructure>
1426  ';
1427  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1428  $expected = [
1429  'sheets' => [
1430  'aSheet' => [
1431  'ROOT' => [
1432  'type' => 'array',
1433  'el' => [
1434  'aFlexField' => [
1435  'TCEforms' => [
1436  'label' => 'aFlexFieldLabel',
1437  'config' => [
1438  'type' => 'input',
1439  ],
1440  ],
1441  ],
1442  ],
1443  'TCEforms' => [
1444  'sheetTitle' => 'aTitle',
1445  ],
1446  ],
1447  ],
1448  ]
1449  ];
1450  $this->assertEquals($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1451  }
1452 
1457  {
1458  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1459  <T3DataStructure>
1460  <sheets>
1461  <aSheet>
1462  FILE:EXT:core/Tests/Unit/Configuration/FlexForm/Fixtures/DataStructureOfSingleSheet.xml
1463  </aSheet>
1464  </sheets>
1465  </T3DataStructure>
1466  ';
1467  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1468  $expected = [
1469  'sheets' => [
1470  'aSheet' => [
1471  'ROOT' => [
1472  'type' => 'array',
1473  'el' => [
1474  'aFlexField' => [
1475  'TCEforms' => [
1476  'label' => 'aFlexFieldLabel',
1477  'config' => [
1478  'type' => 'input',
1479  ],
1480  ],
1481  ],
1482  ],
1483  'TCEforms' => [
1484  'sheetTitle' => 'aTitle',
1485  ],
1486  ],
1487  ],
1488  ]
1489  ];
1490  $this->assertEquals($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1491  }
1492 
1497  {
1498  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1499  <T3DataStructure>
1500  <sheets></sheets>
1501  </T3DataStructure>
1502  ';
1503  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1504  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1505  DataStructureParsePostProcessHookThrowException::class,
1506  ];
1507  $this->expectException(\RuntimeException::class);
1508  $this->expectExceptionCode(1478351691);
1509  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1510  }
1511 
1516  {
1517  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1518  <T3DataStructure>
1519  <sheets></sheets>
1520  </T3DataStructure>
1521  ';
1522  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1523  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1524  DataStructureParsePostProcessHookReturnString::class,
1525  ];
1526  $this->expectException(\RuntimeException::class);
1527  $this->expectExceptionCode(1478350806);
1528  (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier);
1529  }
1530 
1535  {
1536  ‪$GLOBALS['TCA']['aTableName']['columns']['aFieldName']['config']['ds']['default'] = '
1537  <T3DataStructure>
1538  <sheets></sheets>
1539  </T3DataStructure>
1540  ';
1541  $identifier = '{"type":"tca","tableName":"aTableName","fieldName":"aFieldName","dataStructureKey":"default"}';
1542  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][FlexFormTools::class]['flexParsing'] = [
1543  DataStructureParsePostProcessHookReturnArray::class,
1544  ];
1545  $expected = [
1546  'sheets' => [
1547  'foo' => 'bar'
1548  ]
1549  ];
1550  $this->assertSame($expected, (new ‪FlexFormTools())->parseDataStructureByIdentifier($identifier));
1551  }
1552 
1557  {
1558  $dataStruct = [
1559  'dummy_field' => [
1560  'TCEforms' => [
1561  'config' => [],
1562  ],
1563  ],
1564  ];
1565  $pA = [
1566  'vKeys' => ['ES'],
1567  'callBackMethod_value' => 'dummy',
1568  ];
1569  $editData = [];
1571  $subject = $this->getMockBuilder(FlexFormTools::class)
1572  ->setMethods(['executeCallBackMethod'])
1573  ->getMock();
1574  $subject->expects($this->never())->method('executeCallBackMethod');
1575  $subject->traverseFlexFormXMLData_recurse($dataStruct, $editData, $pA);
1576  }
1577 
1582  {
1583  $dataStruct = [
1584  'dummy_field' => [
1585  'type' => 'array',
1586  'el' => 'field_not_in_data',
1587  ],
1588  ];
1589  $pA = [
1590  'vKeys' => ['ES'],
1591  'callBackMethod_value' => 'dummy',
1592  ];
1593  $editData = [
1594  'field' => [
1595  'el' => 'dummy',
1596  ],
1597  ];
1598  $editData2 = [];
1600  $subject = $this->createMock(FlexFormTools::class);
1601  $this->assertEquals(
1602  $subject->traverseFlexFormXMLData_recurse($dataStruct, $editData, $pA),
1603  $subject->traverseFlexFormXMLData_recurse($dataStruct, $editData2, $pA)
1604  );
1605  }
1606 }
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierResolvesRecordSyntaxPointer
‪parseDataStructureByIdentifierResolvesRecordSyntaxPointer()
Definition: FlexFormToolsTest.php:1242
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfParentRowLookupFails
‪getDataStructureIdentifierThrowsExceptionIfParentRowLookupFails()
Definition: FlexFormToolsTest.php:550
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierPostProcessHookCanEnrichIdentifier
‪getDataStructureIdentifierPostProcessHookCanEnrichIdentifier()
Definition: FlexFormToolsTest.php:212
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionWithEmptyString
‪parseDataStructureByIdentifierThrowsExceptionWithEmptyString()
Definition: FlexFormToolsTest.php:1084
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePreProcessHookThrowException
Definition: DataStructureParsePreProcessHookThrowException.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPostProcessHookReturnsEmptyArray
‪getDataStructureIdentifierThrowsExceptionIfPostProcessHookReturnsEmptyArray()
Definition: FlexFormToolsTest.php:192
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidParentRowException
Definition: InvalidParentRowException.php:22
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:33
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\traverseFlexFormXmlDataRecurseDoesNotFailOnNotExistingArrayField
‪traverseFlexFormXmlDataRecurseDoesNotFailOnNotExistingArrayField()
Definition: FlexFormToolsTest.php:1580
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionIfPostProcessHookReturnsNoArray
‪parseDataStructureByIdentifierThrowsExceptionIfPostProcessHookReturnsNoArray()
Definition: FlexFormToolsTest.php:1514
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsPointerFieldValueIfDataStructureExists
‪getDataStructureIdentifierReturnsPointerFieldValueIfDataStructureExists()
Definition: FlexFormToolsTest.php:351
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\traverseFlexFormXmlDataRecurseDoesNotFailOnNotExistingField
‪traverseFlexFormXmlDataRecurseDoesNotFailOnNotExistingField()
Definition: FlexFormToolsTest.php:1555
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierCallsRegisteredPostProcessHook
‪getDataStructureIdentifierCallsRegisteredPostProcessHook()
Definition: FlexFormToolsTest.php:152
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPointerFieldStringHasMoreThanTwoFields
‪getDataStructureIdentifierThrowsExceptionIfPointerFieldStringHasMoreThanTwoFields()
Definition: FlexFormToolsTest.php:278
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionForInvalidSyntax
‪parseDataStructureByIdentifierThrowsExceptionForInvalidSyntax()
Definition: FlexFormToolsTest.php:1182
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsDefaultIfDsIsSetButNoDsPointerField
‪getDataStructureIdentifierReturnsDefaultIfDsIsSetButNoDsPointerField()
Definition: FlexFormToolsTest.php:247
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPointerFieldSWithTwoFieldsFirstDoesNotExist
‪getDataStructureIdentifierThrowsExceptionIfPointerFieldSWithTwoFieldsFirstDoesNotExist()
Definition: FlexFormToolsTest.php:313
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePostProcessHookReturnArray
Definition: DataStructureParsePostProcessHookReturnArray.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPreProcessHookThrowException
Definition: DataStructureIdentifierPreProcessHookThrowException.php:22
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidCombinedPointerFieldException
Definition: InvalidCombinedPointerFieldException.php:21
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierFetchesFromFile
‪parseDataStructureByIdentifierFetchesFromFile()
Definition: FlexFormToolsTest.php:1296
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierCallsPostProcessHook
‪parseDataStructureByIdentifierCallsPostProcessHook()
Definition: FlexFormToolsTest.php:1495
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidSinglePointerFieldException
Definition: InvalidSinglePointerFieldException.php:21
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfNoValidPointerFoundUntilRoot
‪getDataStructureIdentifierThrowsExceptionIfNoValidPointerFoundUntilRoot()
Definition: FlexFormToolsTest.php:668
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPostProcessHookThrowException
Definition: DataStructureIdentifierPostProcessHookThrowException.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest
Definition: FlexFormToolsTest.php:58
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierCallsRegisteredHook
‪parseDataStructureByIdentifierCallsRegisteredHook()
Definition: FlexFormToolsTest.php:1104
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePostProcessHookReturnString
Definition: DataStructureParsePostProcessHookReturnString.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPointerFieldSWithTwoFieldsSecondDoesNotExist
‪getDataStructureIdentifierThrowsExceptionIfPointerFieldSWithTwoFieldsSecondDoesNotExist()
Definition: FlexFormToolsTest.php:332
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface
Definition: QueryRestrictionContainerInterface.php:23
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPostProcessHookReturnArray
Definition: DataStructureIdentifierPostProcessHookReturnArray.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierUsesCasualLogicIfHookReturnsNoIdentifier
‪parseDataStructureByIdentifierUsesCasualLogicIfHookReturnsNoIdentifier()
Definition: FlexFormToolsTest.php:1130
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionsIfNoDsPointerFieldIsSetAndDefaultDoesNotExist
‪getDataStructureIdentifierThrowsExceptionsIfNoDsPointerFieldIsSetAndDefaultDoesNotExist()
Definition: FlexFormToolsTest.php:263
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierIfIdentifierDoesNotResolveToArray
‪parseDataStructureByIdentifierIfIdentifierDoesNotResolveToArray()
Definition: FlexFormToolsTest.php:1094
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionIfHookReturnsNoString
‪parseDataStructureByIdentifierThrowsExceptionIfHookReturnsNoString()
Definition: FlexFormToolsTest.php:1117
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidNameForTwoFieldCombinationsDataProvider
‪getDataStructureIdentifierReturnsValidNameForTwoFieldCombinationsDataProvider()
Definition: FlexFormToolsTest.php:413
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfDsIsNotAnArrayAndNoDsPointerField
‪getDataStructureIdentifierThrowsExceptionIfDsIsNotAnArrayAndNoDsPointerField()
Definition: FlexFormToolsTest.php:231
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidIdentifierForParentLookupAndBreaksLoop
‪getDataStructureIdentifierReturnsValidIdentifierForParentLookupAndBreaksLoop()
Definition: FlexFormToolsTest.php:878
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePreProcessHookReturnObject
Definition: DataStructureParsePreProcessHookReturnObject.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidIdentifierForParentLookupAndPrefersSubField
‪getDataStructureIdentifierReturnsValidIdentifierForParentLookupAndPrefersSubField()
Definition: FlexFormToolsTest.php:937
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPostProcessHookReturnEmptyArray
Definition: DataStructureIdentifierPostProcessHookReturnEmptyArray.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePreProcessHookReturnEmptyString
Definition: DataStructureParsePreProcessHookReturnEmptyString.php:22
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidParentRowRootException
Definition: InvalidParentRowRootException.php:21
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfDsTableFieldIsMisconfigured
‪getDataStructureIdentifierThrowsExceptionIfDsTableFieldIsMisconfigured()
Definition: FlexFormToolsTest.php:773
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfParentRowsFormALoop
‪getDataStructureIdentifierThrowsExceptionIfParentRowsFormALoop()
Definition: FlexFormToolsTest.php:599
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierParsesDataStructureReturnedByHook
‪parseDataStructureByIdentifierParsesDataStructureReturnedByHook()
Definition: FlexFormToolsTest.php:1150
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionIfDataStructureFileDoesNotExist
‪parseDataStructureByIdentifierThrowsExceptionIfDataStructureFileDoesNotExist()
Definition: FlexFormToolsTest.php:1283
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidIdentifierException
Definition: InvalidIdentifierException.php:21
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierResolvesExtReferenceForSingleSheetsWithFilePrefix
‪parseDataStructureByIdentifierResolvesExtReferenceForSingleSheetsWithFilePrefix()
Definition: FlexFormToolsTest.php:1455
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionForInvalidTcaSyntaxPointer
‪parseDataStructureByIdentifierThrowsExceptionForInvalidTcaSyntaxPointer()
Definition: FlexFormToolsTest.php:1203
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsStringFromPreProcessHook
‪getDataStructureIdentifierReturnsStringFromPreProcessHook()
Definition: FlexFormToolsTest.php:126
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPreProcessHookReturnsNoArray
‪getDataStructureIdentifierThrowsExceptionIfPreProcessHookReturnsNoArray()
Definition: FlexFormToolsTest.php:94
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfResorvedPointerValueIsIntegerButDsFieldNameIsNotConfigured
‪getDataStructureIdentifierThrowsExceptionIfResorvedPointerValueIsIntegerButDsFieldNameIsNotConfigured()
Definition: FlexFormToolsTest.php:755
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierResolvesExtReferenceForSingleSheets
‪parseDataStructureByIdentifierResolvesExtReferenceForSingleSheets()
Definition: FlexFormToolsTest.php:1415
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPreProcessHookReturnEmptyArray
Definition: DataStructureIdentifierPreProcessHookReturnEmptyArray.php:22
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:36
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierPostProcessHookManipulatesDataStructure
‪parseDataStructureByIdentifierPostProcessHookManipulatesDataStructure()
Definition: FlexFormToolsTest.php:1533
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionForInvalidXmlStructure
‪parseDataStructureByIdentifierThrowsExceptionForInvalidXmlStructure()
Definition: FlexFormToolsTest.php:1329
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidIdentifierForPointerField
‪getDataStructureIdentifierReturnsValidIdentifierForPointerField()
Definition: FlexFormToolsTest.php:792
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:34
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: FlexFormToolsTest.php:61
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfNoValidPointerValueFound
‪getDataStructureIdentifierThrowsExceptionIfNoValidPointerValueFound()
Definition: FlexFormToolsTest.php:737
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\setUp
‪setUp()
Definition: FlexFormToolsTest.php:66
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsStringFromFirstMatchingPreProcessHook
‪getDataStructureIdentifierReturnsStringFromFirstMatchingPreProcessHook()
Definition: FlexFormToolsTest.php:138
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidTcaException
Definition: InvalidTcaException.php:23
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierParsesDataStructureFromFirstMatchingHook
‪parseDataStructureByIdentifierParsesDataStructureFromFirstMatchingHook()
Definition: FlexFormToolsTest.php:1165
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierCreatesDefaultSheet
‪parseDataStructureByIdentifierCreatesDefaultSheet()
Definition: FlexFormToolsTest.php:1364
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePostProcessHookThrowException
Definition: DataStructureParsePostProcessHookThrowException.php:22
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidPointerFieldValueException
Definition: InvalidPointerFieldValueException.php:21
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:21
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPreProcessHookReturnString
Definition: DataStructureIdentifierPreProcessHookReturnString.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPreProcessHookReturnArray
Definition: DataStructureIdentifierPreProcessHookReturnArray.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsDefaultIfPointerFieldValueDoesNotExist
‪getDataStructureIdentifierReturnsDefaultIfPointerFieldValueDoesNotExist()
Definition: FlexFormToolsTest.php:371
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionIfStructureHasBothSheetAndRoot
‪parseDataStructureByIdentifierThrowsExceptionIfStructureHasBothSheetAndRoot()
Definition: FlexFormToolsTest.php:1347
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPostProcessHookReturnsNoArray
‪getDataStructureIdentifierThrowsExceptionIfPostProcessHookReturnsNoArray()
Definition: FlexFormToolsTest.php:172
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierUsesCasualLogicIfPreProcessHookReturnsNoIdentifier
‪getDataStructureIdentifierUsesCasualLogicIfPreProcessHookReturnsNoIdentifier()
Definition: FlexFormToolsTest.php:107
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidParentRowLoopException
Definition: InvalidParentRowLoopException.php:21
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidIdentifierForParentLookup
‪getDataStructureIdentifierReturnsValidIdentifierForParentLookup()
Definition: FlexFormToolsTest.php:810
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierResolvesTcaSyntaxPointer
‪parseDataStructureByIdentifierResolvesTcaSyntaxPointer()
Definition: FlexFormToolsTest.php:1214
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierCallsRegisteredPreProcessHook
‪getDataStructureIdentifierCallsRegisteredPreProcessHook()
Definition: FlexFormToolsTest.php:81
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidIdentifierForTableAndFieldPointerWithParentLookup
‪getDataStructureIdentifierReturnsValidIdentifierForTableAndFieldPointerWithParentLookup()
Definition: FlexFormToolsTest.php:1020
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPointerFieldValueDoesNotExistAndDefaultToo
‪getDataStructureIdentifierThrowsExceptionIfPointerFieldValueDoesNotExistAndDefaultToo()
Definition: FlexFormToolsTest.php:391
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureIdentifierPostProcessHookReturnString
Definition: DataStructureIdentifierPostProcessHookReturnString.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionForIncompleteTcaSyntax
‪parseDataStructureByIdentifierThrowsExceptionForIncompleteTcaSyntax()
Definition: FlexFormToolsTest.php:1192
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionIfPointerFieldWithStringSingleFieldDoesNotExist
‪getDataStructureIdentifierThrowsExceptionIfPointerFieldWithStringSingleFieldDoesNotExist()
Definition: FlexFormToolsTest.php:294
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\Fixtures\DataStructureParsePreProcessHookReturnString
Definition: DataStructureParsePreProcessHookReturnString.php:22
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidNameForTwoFieldCombinations
‪getDataStructureIdentifierReturnsValidNameForTwoFieldCombinations(array $row, array $ds, string $expected)
Definition: FlexFormToolsTest.php:513
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierThrowsExceptionForTwoFieldsWithNoMatchAndNoDefault
‪getDataStructureIdentifierThrowsExceptionForTwoFieldsWithNoMatchAndNoDefault()
Definition: FlexFormToolsTest.php:527
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\getDataStructureIdentifierReturnsValidIdentifierForTableAndFieldPointer
‪getDataStructureIdentifierReturnsValidIdentifierForTableAndFieldPointer()
Definition: FlexFormToolsTest.php:1000
‪TYPO3\CMS\Core\Tests\Unit\Configuration\FlexForm\FlexFormToolsTest\parseDataStructureByIdentifierThrowsExceptionForIncompleteRecordSyntax
‪parseDataStructureByIdentifierThrowsExceptionForIncompleteRecordSyntax()
Definition: FlexFormToolsTest.php:1231