TYPO3  7.6
EvaluateDisplayConditionsTest.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Prophecy\Prophecy\ObjectProphecy;
20 use TYPO3\CMS\Core\Tests\UnitTestCase;
21 
25 class EvaluateDisplayConditionsTest extends UnitTestCase
26 {
30  protected $subject;
31 
32  protected function setUp()
33  {
34  $this->subject = new EvaluateDisplayConditions();
35  }
36 
41  {
42  $input = [
43  'databaseRow' => [
44  'aField' => 'aField',
45  'bField' => 'bField',
46  'cField' => 1,
47  ],
48  'recordTypeValue' => 'aType',
49  'processedTca' => [
50  'types' => [
51  'aType' => [
52  'showitem' => '--palette--;aPalette;2,bField,cField'
53  ],
54  ],
55  'palettes' => [
56  '2' => array(
57  'showitem' => 'aField',
58  'canNotCollapse' => true
59  ),
60  ],
61  'columns' => [
62  'aField' => [
63  'displayCond' => 'FIELD:cField:=:0',
64  'config' => [
65  'type' => 'input',
66  ]
67  ],
68  'bField' => [
69  'displayCond' => 'FIELD:cField:=:1',
70  'config' => [
71  'type' => 'input',
72  ]
73  ],
74  'cField' => [
75  'config' => [
76  'type' => 'input',
77  ]
78  ]
79  ]
80  ]
81  ];
82 
83  $expected = $input;
84  unset($expected['processedTca']['columns']['aField']);
85 
86  $this->assertSame($expected, $this->subject->addData($input));
87  }
88 
93  {
94  $input = [
95  'databaseRow' => [
96  'aField' => [
97  'data' => [
98  'sGeneral' => [
99  'lDEF' => [
100  'mmType' => [
101  'vDEF' => [
102  0 => 'video',
103  ],
104  ],
105  'mmUseHTML5' => [
106  'vDEF' => '0',
107  ],
108  ],
109  ],
110  'sVideo' => [
111  'lDEF' => [],
112  ],
113  'sAudio' => [
114  'lDEF' => []
115  ],
116  ]
117  ]
118  ],
119  'processedTca' => [
120  'columns' => [
121  'aField' => [
122  'config' => [
123  'type' => 'flex',
124  'ds' => [
125  'meta' => [],
126  'sheets' => [
127  'sGeneral' => [
128  'ROOT' => [
129  'type' => 'array',
130  'el' => [
131  'mmType' => [
132  'config' => [
133  'type' => 'select',
134  'items' => [],
135  ],
136  ],
137  'mmUseHTML5' => [
138  'displayCond' => 'FIELD:mmType:!=:audio',
139  'config' => [
140  'type' => 'check',
141  'default' => '0',
142  'items' => [],
143  ],
144  ],
145  ],
146  'sheetTitle' => 'sGeneral',
147  ],
148  ],
149  'sVideo' => [
150  'ROOT' => [
151  'type' => 'array',
152  'el' => [],
153  'sheetTitle' => 'sVideo',
154  'displayCond' => 'FIELD:sGeneral.mmType:!=:audio',
155  ],
156  ],
157  'sAudio' => [
158  'ROOT' => [
159  'type' => 'array',
160  'el' => [],
161  'sheetTitle' => 'sAudio',
162  'displayCond' => 'FIELD:sGeneral.mmType:=:audio',
163  ],
164  ],
165  ],
166  ],
167  ],
168  ],
169  ],
170  ],
171  ];
172 
173  $expected = $input;
174  unset($expected['processedTca']['columns']['aField']['config']['ds']['sheets']['sAudio']);
175  $this->assertSame($expected, $this->subject->addData($input));
176  }
177 
182  {
183  $input = [
184  'databaseRow' => [
185  'aField' => [
186  'data' => [
187  'sGeneral' => [
188  'lDEF' => [
189  'mmType' => [
190  'vDEF' => [
191  0 => 'audio',
192  ],
193  ],
194  'mmUseHTML5' => [
195  'vDEF' => '0',
196  ],
197  ],
198  ],
199  ]
200  ]
201  ],
202  'processedTca' => [
203  'columns' => [
204  'aField' => [
205  'config' => [
206  'type' => 'flex',
207  'ds_pointerField' => 'list_type,CType',
208  'ds' => [
209  'meta' => [],
210  'sheets' => [
211  'sGeneral' => [
212  'ROOT' => [
213  'type' => 'array',
214  'el' => [
215  'mmType' => [
216  'config' => [
217  'type' => 'select',
218  'items' => [],
219  ],
220  ],
221  'mmUseHTML5' => [
222  'displayCond' => 'FIELD:mmType:!=:audio',
223  'config' => [
224  'type' => 'check',
225  'default' => '0',
226  'items' => [],
227  ],
228  ],
229  'mmUseCurl' => [
230  'displayCond' => 'FIELD:mmType:=:audio',
231  'config' => [
232  'type' => 'check',
233  'default' => '0',
234  'items' => [],
235  ],
236  ],
237  ],
238  'sheetTitle' => 'aTitle',
239  ],
240  ],
241  'secondSheet' => [
242  'ROOT' => [
243  'type' => 'array',
244  'el' => [
245  'foo' => [
246  'config' => [
247  'type' => 'select',
248  'items' => [],
249  ],
250  ],
251  ],
252  'sheetTitle' => 'bTitle',
253  ],
254  ],
255  ],
256  ],
257  ],
258  ],
259  ],
260  ],
261  ];
262 
263  $expected = $input;
264  unset($expected['processedTca']['columns']['aField']['config']['ds']['sheets']['sGeneral']['ROOT']['el']['mmUseHTML5']);
265 
266  $this->assertSame($expected, $this->subject->addData($input));
267  }
268 
272  public function matchHideForNonAdminsReturnsTrueIfBackendUserIsAdmin()
273  {
274  $input = [
275  'databaseRow' => [],
276  'processedTca' => [
277  'columns' => [
278  'aField' => [
279  'displayCond' => 'HIDE_FOR_NON_ADMINS',
280  'config' => [
281  'type' => 'input',
282  ]
283  ],
284  ]
285  ]
286  ];
287 
289  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
290  $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
291  $backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(true);
292 
293  $expected = $input;
294 
295  $this->assertSame($expected, $this->subject->addData($input));
296  }
297 
301  public function matchHideForNonAdminsReturnsFalseIfBackendUserIsNotAdmin()
302  {
303  $input = [
304  'databaseRow' => [],
305  'processedTca' => [
306  'columns' => [
307  'aField' => [
308  'displayCond' => 'HIDE_FOR_NON_ADMINS',
309  'config' => [
310  'type' => 'input',
311  ]
312  ],
313  ]
314  ]
315  ];
316 
318  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
319  $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
320  $backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(false);
321 
322  $expected = $input;
323  unset($expected['processedTca']['columns']['aField']);
324  $this->assertSame($expected, $this->subject->addData($input));
325  }
326 
333  {
334  $input = [
335  'databaseRow' => [],
336  'processedTca' => [
337  'columns' => [
338  'aField' => [
339  'displayCond' => 'HIDE_L10N_SIBLINGS',
340  'config' => [
341  'type' => 'input',
342  ]
343  ],
344  ]
345  ]
346  ];
347 
348  $expected = $input;
349 
350  $this->assertSame($expected, $this->subject->addData($input));
351  }
352 
357  {
358  $input = [
359  'databaseRow' => [],
360  'processedTca' => [
361  'columns' => [
362  'aField' => [
363  'displayCond' => 'HIDE_L10N_SIBLINGS:except_admin',
364  'config' => [
365  'type' => 'input',
366  ]
367  ],
368  ]
369  ]
370  ];
371 
372  $expected = $input;
373 
374  $this->assertSame($expected, $this->subject->addData($input));
375  }
376 
386  public function conditionStringDataProvider()
387  {
388  return [
389  'Invalid condition string' => [
390  'xINVALIDx:',
391  [],
392  false,
393  ],
394  'Not loaded extension compares to loaded as FALSE' => [
395  'EXT:neverloadedext:LOADED:TRUE',
396  [],
397  false,
398  ],
399  'Not loaded extension compares to not loaded as TRUE' => [
400  'EXT:neverloadedext:LOADED:FALSE',
401  [],
402  true,
403  ],
404  'Loaded extension compares to TRUE' => [
405  'EXT:backend:LOADED:TRUE',
406  [],
407  true,
408  ],
409  'Loaded extension compares to FALSE' => [
410  'EXT:backend:LOADED:FALSE',
411  [],
412  false,
413  ],
414  'Field is not greater zero if not given' => [
415  'FIELD:uid:>:0',
416  [],
417  false,
418  ],
419  'Field is not equal 0 if not given' => [
420  'FIELD:uid:=:0',
421  [],
422  false,
423  ],
424  'Field value string comparison' => [
425  'FIELD:foo:=:bar',
426  ['foo' => 'bar'],
427  true,
428  ],
429  'Field value string comparison against list' => [
430  'FIELD:foo:IN:bar,baz',
431  ['foo' => 'baz'],
432  true,
433  ],
434  'Field value comparison of 1 against multi-value field of 5 returns true' => [
435  'FIELD:content:BIT:1',
436  ['content' => '5'],
437  true
438  ],
439  'Field value comparison of 2 against multi-value field of 5 returns false' => [
440  'FIELD:content:BIT:2',
441  ['content' => '5'],
442  false
443  ],
444  'Field value of 5 negated comparison against multi-value field of 5 returns false' => [
445  'FIELD:content:!BIT:5',
446  ['content' => '5'],
447  false
448  ],
449  'Field value comparison for required value is false for different value' => [
450  'FIELD:foo:REQ:FALSE',
451  ['foo' => 'bar'],
452  false,
453  ],
454  'Field value string not equal comparison' => [
455  'FIELD:foo:!=:baz',
456  ['foo' => 'bar'],
457  true,
458  ],
459  'Field value string not equal comparison against list' => [
460  'FIELD:foo:!IN:bar,baz',
461  ['foo' => 'foo'],
462  true,
463  ],
464  'Field value in range' => [
465  'FIELD:uid:-:3-42',
466  ['uid' => '23'],
467  true,
468  ],
469  'Field value greater than' => [
470  'FIELD:uid:>=:42',
471  ['uid' => '23'],
472  false,
473  ],
474  'Field is value for default language without flexform' => [
475  'HIDE_L10N_SIBLINGS',
476  [],
477  true,
478  ],
479  'New is TRUE for new comparison with TRUE' => [
480  'REC:NEW:TRUE',
481  ['uid' => null],
482  true,
483  ],
484  'New is FALSE for new comparison with FALSE' => [
485  'REC:NEW:FALSE',
486  ['uid' => null],
487  false,
488  ],
489  'New is FALSE for not new element' => [
490  'REC:NEW:TRUE',
491  ['uid' => 42],
492  false,
493  ],
494  'New is TRUE for not new element compared to FALSE' => [
495  'REC:NEW:FALSE',
496  ['uid' => 42],
497  true,
498  ],
499  'Version is TRUE for versioned row' => [
500  'VERSION:IS:TRUE',
501  [
502  'uid' => 42,
503  'pid' => -1
504  ],
505  true,
506  ],
507  'Version is TRUE for not versioned row compared with FALSE' => [
508  'VERSION:IS:FALSE',
509  [
510  'uid' => 42,
511  'pid' => 1
512  ],
513  true,
514  ],
515  'Version is TRUE for NULL row compared with TRUE' => [
516  'VERSION:IS:TRUE',
517  [
518  'uid' => null,
519  'pid' => null,
520  ],
521  false,
522  ],
523  'Multiple conditions with AND compare to TRUE if all are OK' => [
524  [
525  'AND' => [
526  'FIELD:testField:>:9',
527  'FIELD:testField:<:11',
528  ],
529  ],
530  [
531  'testField' => 10
532  ],
533  true,
534  ],
535  'Multiple conditions with AND compare to FALSE if one fails' => [
536  [
537  'AND' => [
538  'FIELD:testField:>:9',
539  'FIELD:testField:<:11',
540  ]
541  ],
542  [
543  'testField' => 99
544  ],
545  false,
546  ],
547  'Multiple conditions with OR compare to TRUE if one is OK' => [
548  [
549  'OR' => [
550  'FIELD:testField:<:9',
551  'FIELD:testField:<:11',
552  ],
553  ],
554  [
555  'testField' => 10
556  ],
557  true,
558  ],
559  'Multiple conditions with OR compare to FALSE is all fail' => [
560  [
561  'OR' => [
562  'FIELD:testField:<:9',
563  'FIELD:testField:<:11',
564  ],
565  ],
566  [
567  'testField' => 99
568  ],
569  false,
570  ],
571  'Multiple conditions without operator due to misconfiguration compare to TRUE' => [
572  [
573  '' => [
574  'FIELD:testField:<:9',
575  'FIELD:testField:>:11',
576  ]
577  ],
578  [
579  'testField' => 99
580  ],
581  true,
582  ],
583  'Multiple nested conditions evaluate to TRUE' => [
584  [
585  'AND' => [
586  'FIELD:testField:>:9',
587  'OR' => [
588  'FIELD:testField:<:100',
589  'FIELD:testField:>:-100',
590  ],
591  ],
592  ],
593  [
594  'testField' => 10
595  ],
596  true,
597  ],
598  'Multiple nested conditions evaluate to FALSE' => [
599  [
600  'AND' => [
601  'FIELD:testField:>:9',
602  'OR' => [
603  'FIELD:testField:<:100',
604  'FIELD:testField:>:-100',
605  ],
606  ],
607  ],
608  [
609  'testField' => -999
610  ],
611  false,
612  ],
613  ];
614  }
615 
623  public function matchConditionStrings($condition, array $record, $expectedResult)
624  {
625  $input = [
626  'databaseRow' => $record,
627  'processedTca' => [
628  'columns' => [
629  'testField' => [
630  'displayCond' => $condition,
631  'config' => [
632  'type' => 'input',
633  ]
634  ],
635  ]
636  ]
637  ];
638 
639  $expected = $input;
640  if (!$expectedResult) {
641  unset($expected['processedTca']['columns']['testField']);
642  }
643  $this->assertSame($expected, $this->subject->addData($input));
644  }
645 
654  public function matchConditionStringsWithRecordTestFieldBeingArray($condition, array $record, $expectedResult)
655  {
656  $input = [
657  'processedTca' => [
658  'columns' => [
659  'testField' => [
660  'displayCond' => $condition,
661  'config' => [
662  'type' => 'input',
663  ],
664  ],
665  ],
666  ],
667  ];
668  $input['databaseRow'] = $record ?: ['testField' => ['key' => $record['testField']]];
669 
670  $expected = $input;
671  if (!$expectedResult) {
672  unset($expected['processedTca']['columns']['testField']);
673  }
674  $this->assertSame($expected, $this->subject->addData($input));
675  }
676 
687  {
688  return [
689  'Flexform value invalid comparison' => [
690  'FIELD:foo:=:bar',
691  [
692  'foo' => 'bar',
693  'testField' => [
694  'data' => [
695  'sDEF' => [
696  'lDEF' => [],
697  ],
698  ],
699  ],
700  ],
701  false,
702  ],
703  'Flexform value valid comparison' => [
704  'FIELD:parentRec.foo:=:bar',
705  [
706  'foo' => 'bar',
707  'testField' => [
708  'data' => [
709  'sDEF' => [
710  'lDEF' => [],
711  ],
712  ],
713  ],
714  ],
715  true,
716  ],
717  ];
718  }
719 
727  public function matchFlexformConditionStrings($condition, array $record, $expectedResult)
728  {
729  $input = [
730  'databaseRow' => $record,
731  'processedTca' => [
732  'columns' => [
733  'testField' => [
734  'config' => [
735  'type' => 'flex',
736  'ds' => [
737  'meta' => [],
738  'sheets' => [
739  'sDEF' => [
740  'ROOT' => [
741  'type' => 'array',
742  'el' => [
743  'flexTestField' => [
744  'displayCond' => $condition,
745  'config' => [
746  'type' => 'input',
747  ],
748  ],
749  ],
750  ],
751  ],
752  ]
753  ],
754  ],
755  ],
756  ],
757  ],
758  ];
759 
760  $expected = $input;
761  if (!$expectedResult) {
762  unset($expected['processedTca']['columns']['testField']['config']['ds']['sheets']['sDEF']['ROOT']['el']['flexTestField']);
763  }
764  $this->assertSame($expected, $this->subject->addData($input));
765  }
766 
771  {
772  $input = [
773  'databaseRow' => [
774  'foo' => 'bar',
775  'testField' => [
776  'data' => [
777  'sDEF' => [
778  'lDEF' => [
779  'flex.TestField' => [
780  'vDEF' => [
781  0 => 0,
782  ],
783  ],
784  ],
785  ],
786  ],
787  ],
788  ],
789  'processedTca' => [
790  'columns' => [
791  'testField' => [
792  'config' => [
793  'type' => 'flex',
794  'ds' => [
795  'meta' => [],
796  'sheets' => [
797  'sDEF' => [
798  'ROOT' => [
799  'type' => 'array',
800  'el' => [
801  'flex.TestField' => [
802  'config' => [
803  'type' => 'input',
804  ],
805  ],
806  ],
807  ],
808  ],
809  'sTest' => [
810  'ROOT' => [
811  'type' => 'array',
812  'el' => [],
813  'sheetTitle' => 'sVideo',
814  'displayCond' => 'FIELD:sDEF.flex.TestField:!=:0',
815  ],
816  ],
817  ]
818  ],
819  ],
820  ],
821  ],
822  ],
823  ];
824 
825  $expected = $input;
826  unset($expected['processedTca']['columns']['testField']['config']['ds']['sheets']['sTest']);
827  $this->assertSame($expected, $this->subject->addData($input));
828  }
829 }