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