‪TYPO3CMS  ‪main
RootlineUtilityTest.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 PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
33 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
34 
35 final class ‪RootlineUtilityTest extends FunctionalTestCase
36 {
38 
39  protected const ‪LANGUAGE_PRESETS = [
40  'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
41  'FR' => ['id' => 1, 'title' => 'French', 'locale' => 'fr_FR.UTF8'],
42  ];
43 
44  protected array ‪$coreExtensionsToLoad = ['workspaces'];
45  protected array ‪$testExtensionsToLoad = [
46  'typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_rootlineutility',
47  ];
48 
49  protected function ‪setUp(): void
50  {
51  parent::setUp();
53  'main',
54  $this->‪buildSiteConfiguration(1, 'https://acme.com/'),
55  [
56  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
57  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
58  ]
59  );
60  self::importCSVDataSet(__DIR__ . '/Fixtures/RootlineUtilityImport.csv');
61  }
62 
63  private function ‪filterExpectedValues(array $incomingData, array ‪$fields): array
64  {
65  $result = [];
66  foreach ($incomingData as $pos => $values) {
67  $filteredValues = [];
68  foreach (‪$fields as $field) {
69  if (isset($values[$field])) {
70  $filteredValues[$field] = $values[$field];
71  }
72  }
73  $result[$pos] = $filteredValues;
74  }
75  return $result;
76  }
77 
78  #[Test]
79  public function ‪verifyCleanReferenceIndex()
80  {
81  // Fix refindex, then compare with import csv again to verify nothing changed.
82  // This is to make sure the import csv is 'clean' - important for the other tests.
83  $this->get(ReferenceIndex::class)->updateIndex(false);
84  $this->assertCSVDataSet(__DIR__ . '/Fixtures/RootlineUtilityImport.csv');
85  }
86 
87  #[Test]
89  {
90  $subject = new ‪RootlineUtility(1, '', new ‪Context());
91  $subjectMethodReflection = (new \ReflectionMethod($subject, 'isMountedPage'));
92  self::assertFalse($subjectMethodReflection->invoke($subject));
93  }
94 
95  #[Test]
97  {
98  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
99  $subjectMethodReflection = (new \ReflectionMethod($subject, 'isMountedPage'));
100  self::assertTrue($subjectMethodReflection->invoke($subject));
101  }
102 
103  #[Test]
105  {
106  $subject = new ‪RootlineUtility(1, '99-99', new ‪Context());
107  $subjectMethodReflection = (new \ReflectionMethod($subject, 'isMountedPage'));
108  self::assertFalse($subjectMethodReflection->invoke($subject));
109  }
110 
111  #[Test]
113  {
114  $this->expectException(\RuntimeException::class);
115  $this->expectExceptionCode(1343464100);
116  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
117  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
118  $subjectMethodReflection->invoke($subject, ['uid' => 1], ['uid' => 99, 'doktype' => ‪PageRepository::DOKTYPE_DEFAULT]);
119  }
120 
121  #[Test]
123  {
124  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
125  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
126  $result = $subjectMethodReflection->invoke(
127  $subject,
128  ['uid' => 1],
129  ['uid' => 99, 'doktype' => ‪PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
130  );
131  self::assertNotEmpty($result);
132  }
133 
134  #[Test]
136  {
137  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
138  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
139  $result = $subjectMethodReflection->invoke(
140  $subject,
141  ['uid' => 1],
142  ['uid' => 99, 'doktype' => ‪PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
143  );
144  self::assertTrue(isset($result['_MOUNTED_FROM']));
145  self::assertSame(1, $result['_MOUNTED_FROM']);
146  }
147 
148  #[Test]
150  {
151  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
152  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
153  $result = $subjectMethodReflection->invoke(
154  $subject,
155  ['uid' => 1],
156  ['uid' => 99, 'doktype' => ‪PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
157  );
158  self::assertTrue(isset($result['_MP_PARAM']));
159  self::assertSame('1-99', $result['_MP_PARAM']);
160  }
161 
162  #[Test]
164  {
165  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
166  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
167  $result = $subjectMethodReflection->invoke(
168  $subject,
169  ['uid' => 1],
170  ['uid' => 99, 'doktype' => ‪PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1]
171  );
172  self::assertTrue(isset($result['_MOUNT_OL']));
173  self::assertTrue($result['_MOUNT_OL']);
174  }
175 
176  #[Test]
178  {
179  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
180  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
181  $result = $subjectMethodReflection->invoke(
182  $subject,
183  ['uid' => 1],
184  [
185  'uid' => 99,
187  'mount_pid' => 1,
188  'mount_pid_ol' => 1,
189  'pid' => 5,
190  'title' => 'TestCase',
191  ]
192  );
193  self::assertTrue(isset($result['_MOUNT_PAGE']));
194  self::assertSame(['uid' => 99, 'pid' => 5, 'title' => 'TestCase'], $result['_MOUNT_PAGE']);
195  }
196 
197  #[Test]
199  {
200  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
201  $subjectMethodReflection = (new \ReflectionMethod($subject, 'processMountedPage'));
202  $mountPointPageData = [
203  'uid' => 99,
205  'mount_pid' => 1,
206  'mount_pid_ol' => 0,
207  ];
208  $result = $subjectMethodReflection->invoke(
209  $subject,
210  ['uid' => 1],
211  $mountPointPageData
212  );
213  // Tests that $mountPointPageData is completely part of $result and keys match.
214  self::assertSame($mountPointPageData, array_intersect_assoc($mountPointPageData, $result));
215  }
216 
217  #[Test]
219  {
220  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
221  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
222  self::assertFalse($subjectMethodReflection->invoke(
223  $subject,
224  [
225  'config' => [
226  'type' => 'group',
227  ],
228  ]
229  ));
230  }
231 
232  #[Test]
234  {
235  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
236  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
237  self::assertTrue($subjectMethodReflection->invoke(
238  $subject,
239  [
240  'config' => [
241  'type' => 'group',
242  'MM' => 'tx_xyz',
243  ],
244  ]
245  ));
246  }
247 
248  #[Test]
250  {
251  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
252  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
253  self::assertFalse($subjectMethodReflection->invoke(
254  $subject,
255  [
256  'config' => [
257  'type' => 'inline',
258  ],
259  ]
260  ));
261  }
262 
263  #[Test]
265  {
266  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
267  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
268  self::assertTrue($subjectMethodReflection->invoke(
269  $subject,
270  [
271  'config' => [
272  'type' => 'inline',
273  'foreign_field' => 'xyz',
274  ],
275  ]
276  ));
277  }
278 
279  #[Test]
281  {
282  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
283  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
284  self::assertTrue($subjectMethodReflection->invoke(
285  $subject,
286  [
287  'config' => [
288  'type' => 'inline',
289  'MM' => 'xyz',
290  ],
291  ]
292  ));
293  }
294 
295  #[Test]
297  {
298  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
299  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
300  self::assertFalse($subjectMethodReflection->invoke(
301  $subject,
302  [
303  'config' => [
304  'type' => 'select',
305  ],
306  ]
307  ));
308  }
309 
310  #[Test]
312  {
313  $subject = new ‪RootlineUtility(1, '1-99', new ‪Context());
314  $subjectMethodReflection = (new \ReflectionMethod($subject, 'columnHasRelationToResolve'));
315  self::assertTrue($subjectMethodReflection->invoke(
316  $subject,
317  [
318  'config' => [
319  'type' => 'select',
320  'MM' => 'xyz',
321  ],
322  ]
323  ));
324  }
325 
326  #[Test]
328  {
329  $cacheFrontend = new ‪NullFrontend('some-frontend');
330  $context = new ‪Context();
331  $context->setAspect('workspace', new ‪WorkspaceAspect(15));
332  $context->setAspect('visibility', new ‪VisibilityAspect(true));
333  $context->setAspect('language', new ‪LanguageAspect(8, 8, ‪LanguageAspect::OVERLAYS_OFF));
334  $subject = new ‪RootlineUtility(42, '47-11', $context);
335  $subjectMethodReflection = (new \ReflectionMethod($subject, 'getCacheIdentifier'));
336  self::assertSame('42_47-11_8_15_0_1', $subjectMethodReflection->invoke($subject));
337  self::assertTrue($cacheFrontend->isValidEntryIdentifier($subjectMethodReflection->invoke($subject)));
338  $context->setAspect('workspace', new ‪WorkspaceAspect(0));
339  $subject = new ‪RootlineUtility(42, '47-11', $context);
340  $subjectMethodReflection = (new \ReflectionMethod($subject, 'getCacheIdentifier'));
341  self::assertSame('42_47-11_8_0_0_1', $subjectMethodReflection->invoke($subject));
342  self::assertTrue($cacheFrontend->isValidEntryIdentifier($subjectMethodReflection->invoke($subject)));
343  }
344 
345  #[Test]
347  {
348  $this->expectException(\LogicException::class);
349  $this->expectExceptionCode(1712572738);
350  unset(‪$GLOBALS['TCA']['pages']['columns']);
351  (new ‪RootlineUtility(1))->get();
352  }
353 
354  #[Test]
356  {
357  $this->expectException(\LogicException::class);
358  $this->expectExceptionCode(1712572738);
359  ‪$GLOBALS['TCA']['pages']['columns'] = 'This is not an array.';
360  (new ‪RootlineUtility(1))->get();
361  }
362 
363  #[Test]
365  {
366  $rootPageUid = 1;
367  $result = (new ‪RootlineUtility($rootPageUid))->get();
368  self::assertCount(1, $result);
369  self::assertSame($rootPageUid, (int)$result[0]['uid']);
370  }
371 
372  #[Test]
374  {
375  $this->expectException(PageNotFoundException::class);
376  $this->expectExceptionCode(1343464101);
377  $context = new ‪Context();
378  $context->setAspect('workspace', new ‪WorkspaceAspect(1));
379  (new ‪RootlineUtility(1002, '', $context))->get();
380  }
381 
382  public static function ‪getResolvesCorrectlyDataProvider(): \Generator
383  {
384  yield 'standard nested page lang default' => [
385  'uid' => 1001,
386  'language' => 0,
387  'workspace' => 0,
388  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title'],
389  'expected' => [
390  2 => [
391  'uid' => 1001,
392  'pid' => 1000,
393  't3ver_oid' => 0,
394  't3ver_wsid' => 0,
395  't3ver_state' => 0,
396  'title' => 'EN Parent 1000 Sub 1',
397  ],
398  1 => [
399  'uid' => 1000,
400  'pid' => 1,
401  't3ver_oid' => 0,
402  't3ver_wsid' => 0,
403  't3ver_state' => 0,
404  'title' => 'EN Parent 1000',
405  ],
406  0 => [
407  'uid' => 1,
408  'pid' => 0,
409  't3ver_oid' => 0,
410  't3ver_wsid' => 0,
411  't3ver_state' => 0,
412  'title' => 'EN Root',
413  ],
414  ],
415  ];
416  yield 'standard nested page lang FR, requesting with default lang id' => [
417  'uid' => 1001,
418  'language' => 1,
419  'workspace' => 0,
420  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title', '_LOCALIZED_UID', '_REQUESTED_OVERLAY_LANGUAGE'],
421  'expected' => [
422  2 => [
423  'uid' => 1001,
424  'pid' => 1000,
425  't3ver_oid' => 0,
426  't3ver_wsid' => 0,
427  't3ver_state' => 0,
428  'title' => 'FR Parent 1000 Sub 1',
429  '_LOCALIZED_UID' => 1002,
430  '_REQUESTED_OVERLAY_LANGUAGE' => 1,
431  ],
432  1 => [
433  'uid' => 1000,
434  'pid' => 1,
435  't3ver_oid' => 0,
436  't3ver_wsid' => 0,
437  't3ver_state' => 0,
438  'title' => 'EN Parent 1000',
439  ],
440  0 => [
441  'uid' => 1,
442  'pid' => 0,
443  't3ver_oid' => 0,
444  't3ver_wsid' => 0,
445  't3ver_state' => 0,
446  'title' => 'EN Root',
447  ],
448  ],
449  ];
450  // @todo: Inconsistent. Compare with above set: When requesting a localized uid directly, 'uid' is the
451  // localized one, and '_LOCALIZED_UID' and '_REQUESTED_OVERLAY_LANGUAGE' are not set at all.
452  yield 'standard nested page lang FR, requesting with FR lang id' => [
453  'uid' => 1002,
454  'language' => 1,
455  'workspace' => 0,
456  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title', '_LOCALIZED_UID', '_REQUESTED_OVERLAY_LANGUAGE'],
457  'expected' => [
458  2 => [
459  'uid' => 1002,
460  'pid' => 1000,
461  't3ver_oid' => 0,
462  't3ver_wsid' => 0,
463  't3ver_state' => 0,
464  'title' => 'FR Parent 1000 Sub 1',
465  ],
466  1 => [
467  'uid' => 1000,
468  'pid' => 1,
469  't3ver_oid' => 0,
470  't3ver_wsid' => 0,
471  't3ver_state' => 0,
472  'title' => 'EN Parent 1000',
473  ],
474  0 => [
475  'uid' => 1,
476  'pid' => 0,
477  't3ver_oid' => 0,
478  't3ver_wsid' => 0,
479  't3ver_state' => 0,
480  'title' => 'EN Root',
481  ],
482  ],
483  ];
484  yield 'new page in workspaces' => [
485  'uid' => 1011,
486  'language' => 0,
487  'workspace' => 2,
488  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title'],
489  'expected' => [
490  2 => [
491  'uid' => 1011,
492  'pid' => 1010,
493  't3ver_oid' => 0,
494  't3ver_wsid' => 2,
495  't3ver_state' => 1,
496  'title' => 'EN WS2-new Parent 1010 Sub 1',
497  ],
498  1 => [
499  'uid' => 1010,
500  'pid' => 1,
501  't3ver_oid' => 0,
502  't3ver_wsid' => 0,
503  't3ver_state' => 0,
504  'title' => 'EN Parent 1010',
505  ],
506  0 => [
507  'uid' => 1,
508  'pid' => 0,
509  't3ver_oid' => 0,
510  't3ver_wsid' => 0,
511  't3ver_state' => 0,
512  'title' => 'EN Root',
513  ],
514  ],
515  ];
516  yield 'moved in workspaces, requesting with live id in live' => [
517  'uid' => 1020,
518  'language' => 0,
519  'workspace' => 0,
520  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title'],
521  'expected' => [
522  1 => [
523  'uid' => 1020,
524  'pid' => 1,
525  't3ver_oid' => 0,
526  't3ver_wsid' => 0,
527  't3ver_state' => 0,
528  'title' => 'EN To Move in WS',
529  ],
530  0 => [
531  'uid' => 1,
532  'pid' => 0,
533  't3ver_oid' => 0,
534  't3ver_wsid' => 0,
535  't3ver_state' => 0,
536  'title' => 'EN Root',
537  ],
538  ],
539  ];
540  yield 'moved in workspaces, requesting with live id in workspace' => [
541  'uid' => 1020,
542  'language' => 0,
543  'workspace' => 2,
544  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title', '_ORIG_uid', '_ORIG_pid'],
545  'expected' => [
546  2 => [
547  'uid' => 1020,
548  'pid' => 1021,
549  't3ver_oid' => 1020,
550  't3ver_wsid' => 2,
551  't3ver_state' => 4,
552  'title' => 'EN WS2-moved Move in WS',
553  '_ORIG_uid' => 1022,
554  '_ORIG_pid' => 1,
555  ],
556  1 => [
557  'uid' => 1021,
558  'pid' => 1,
559  't3ver_oid' => 0,
560  't3ver_wsid' => 0,
561  't3ver_state' => 0,
562  'title' => 'EN Move target',
563  ],
564  0 => [
565  'uid' => 1,
566  'pid' => 0,
567  't3ver_oid' => 0,
568  't3ver_wsid' => 0,
569  't3ver_state' => 0,
570  'title' => 'EN Root',
571  ],
572  ],
573  ];
574  yield 'moved in workspaces, requesting with workspace id in workspace' => [
575  'uid' => 1022,
576  'language' => 0,
577  'workspace' => 2,
578  'testFields' => ['uid', 'pid', 't3ver_oid', 't3ver_wsid', 't3ver_state', 'title', '_ORIG_uid', '_ORIG_pid'],
579  'expected' => [
580  2 => [
581  'uid' => 1020,
582  'pid' => 1021,
583  't3ver_oid' => 1020,
584  't3ver_wsid' => 2,
585  't3ver_state' => 4,
586  'title' => 'EN WS2-moved Move in WS',
587  '_ORIG_uid' => 1022,
588  '_ORIG_pid' => 1,
589  ],
590  1 => [
591  'uid' => 1021,
592  'pid' => 1,
593  't3ver_oid' => 0,
594  't3ver_wsid' => 0,
595  't3ver_state' => 0,
596  'title' => 'EN Move target',
597  ],
598  0 => [
599  'uid' => 1,
600  'pid' => 0,
601  't3ver_oid' => 0,
602  't3ver_wsid' => 0,
603  't3ver_state' => 0,
604  'title' => 'EN Root',
605  ],
606  ],
607  ];
608 
609  yield 'media lang default' => [
610  'uid' => 2001,
611  'language' => 0,
612  'workspace' => 0,
613  'testFields' => ['uid', 'title', 'media'],
614  'expected' => [
615  2 => [
616  'uid' => 2001,
617  'title' => 'EN Parent 2000 Sub 1',
618  'media' => '1001,1000',
619  ],
620  1 => [
621  'uid' => 2000,
622  'title' => 'EN Parent 2000',
623  'media' => '',
624  ],
625  0 => [
626  'uid' => 1,
627  'title' => 'EN Root',
628  'media' => '',
629  ],
630  ],
631  ];
632  yield 'media lang FR, requesting with default lang uid' => [
633  'uid' => 2001,
634  'language' => 1,
635  'workspace' => 0,
636  'testFields' => ['uid', 'title', 'media'],
637  'expected' => [
638  2 => [
639  'uid' => 2001,
640  'title' => 'FR Parent 2000 Sub 1',
641  'media' => '1010,1011',
642  ],
643  1 => [
644  'uid' => 2000,
645  'title' => 'EN Parent 2000',
646  'media' => '',
647  ],
648  0 => [
649  'uid' => 1,
650  'title' => 'EN Root',
651  'media' => '',
652  ],
653  ],
654  ];
655  yield 'media lang FR, requesting with FR lang uid' => [
656  'uid' => 2002,
657  'language' => 1,
658  'workspace' => 0,
659  'testFields' => ['uid', 'title', 'media'],
660  'expected' => [
661  2 => [
662  'uid' => 2002,
663  'title' => 'FR Parent 2000 Sub 1',
664  'media' => '1010,1011',
665  ],
666  1 => [
667  'uid' => 2000,
668  'title' => 'EN Parent 2000',
669  'media' => '',
670  ],
671  0 => [
672  'uid' => 1,
673  'title' => 'EN Root',
674  'media' => '',
675  ],
676  ],
677  ];
678  yield 'media lang default, workspace new' => [
679  'uid' => 2011,
680  'language' => 0,
681  'workspace' => 2,
682  'testFields' => ['uid', 'title', 'media'],
683  'expected' => [
684  2 => [
685  'uid' => 2011,
686  'title' => 'EN WS2-new Parent 2010 Sub 1 with media',
687  'media' => '1101,1100',
688  ],
689  1 => [
690  'uid' => 2010,
691  'title' => 'EN Parent 2010',
692  'media' => '',
693  ],
694  0 => [
695  'uid' => 1,
696  'title' => 'EN Root',
697  'media' => '',
698  ],
699  ],
700  ];
701  yield 'media lang FR, workspace new, requesting with default lang uid' => [
702  'uid' => 2021,
703  'language' => 1,
704  'workspace' => 2,
705  'testFields' => ['uid', 'title', 'media'],
706  'expected' => [
707  2 => [
708  'uid' => 2021,
709  'title' => 'FR WS2-new Parent 2020 Sub 1 with media',
710  'media' => '1201,1200',
711  ],
712  1 => [
713  'uid' => 2020,
714  'title' => 'EN Parent 2020',
715  'media' => '',
716  ],
717  0 => [
718  'uid' => 1,
719  'title' => 'EN Root',
720  'media' => '',
721  ],
722  ],
723  ];
724  yield 'media lang FR, workspace new, requesting with FR lang uid' => [
725  'uid' => 2022,
726  'language' => 1,
727  'workspace' => 2,
728  'testFields' => ['uid', 'title', 'media'],
729  'expected' => [
730  2 => [
731  'uid' => 2022,
732  'title' => 'FR WS2-new Parent 2020 Sub 1 with media',
733  'media' => '1201,1200',
734  ],
735  1 => [
736  'uid' => 2020,
737  'title' => 'EN Parent 2020',
738  'media' => '',
739  ],
740  0 => [
741  'uid' => 1,
742  'title' => 'EN Root',
743  'media' => '',
744  ],
745  ],
746  ];
747  yield 'media lang default, workspace media elements changed, requesting with live uid' => [
748  'uid' => 2031,
749  'language' => 0,
750  'workspace' => 2,
751  'testFields' => ['uid', 'title', 'media'],
752  'expected' => [
753  2 => [
754  'uid' => 2031,
755  'title' => 'EN WS2-changed Parent 2030 Sub 1 with media changed',
756  'media' => '1304,1305,1307',
757  ],
758  1 => [
759  'uid' => 2030,
760  'title' => 'EN Parent 2030',
761  'media' => '',
762  ],
763  0 => [
764  'uid' => 1,
765  'title' => 'EN Root',
766  'media' => '',
767  ],
768  ],
769  ];
770  yield 'media lang default, workspace media elements changed, requesting with workspace uid' => [
771  'uid' => 2032,
772  'language' => 0,
773  'workspace' => 2,
774  'testFields' => ['uid', 'title', 'media'],
775  'expected' => [
776  2 => [
777  'uid' => 2032,
778  'title' => 'EN WS2-changed Parent 2030 Sub 1 with media changed',
779  'media' => '1304,1305,1307',
780  ],
781  1 => [
782  'uid' => 2030,
783  'title' => 'EN Parent 2030',
784  'media' => '',
785  ],
786  0 => [
787  'uid' => 1,
788  'title' => 'EN Root',
789  'media' => '',
790  ],
791  ],
792  ];
793  yield 'media lang FR, workspace media elements changed, requesting with live uid and default lang' => [
794  'uid' => 2041,
795  'language' => 1,
796  'workspace' => 2,
797  'testFields' => ['uid', 'title', 'media'],
798  'expected' => [
799  2 => [
800  'uid' => 2041,
801  'title' => 'FR WS2-changed Parent 2040 Sub 1 with media changed',
802  'media' => '1404,1407,1405',
803  ],
804  1 => [
805  'uid' => 2040,
806  'title' => 'EN Parent 2040',
807  'media' => '',
808  ],
809  0 => [
810  'uid' => 1,
811  'title' => 'EN Root',
812  'media' => '',
813  ],
814  ],
815  ];
816  yield 'media lang FR, workspace media elements changed, requesting with live uid and FR lang' => [
817  'uid' => 2042,
818  'language' => 1,
819  'workspace' => 2,
820  'testFields' => ['uid', 'title', 'media'],
821  'expected' => [
822  2 => [
823  'uid' => 2042,
824  'title' => 'FR WS2-changed Parent 2040 Sub 1 with media changed',
825  'media' => '1404,1407,1405',
826  ],
827  1 => [
828  'uid' => 2040,
829  'title' => 'EN Parent 2040',
830  'media' => '',
831  ],
832  0 => [
833  'uid' => 1,
834  'title' => 'EN Root',
835  'media' => '',
836  ],
837  ],
838  ];
839  yield 'media lang FR, workspace media elements changed, requesting with workspace uid' => [
840  'uid' => 2043,
841  'language' => 1,
842  'workspace' => 2,
843  'testFields' => ['uid', 'title', 'media'],
844  'expected' => [
845  2 => [
846  'uid' => 2043,
847  'title' => 'FR WS2-changed Parent 2040 Sub 1 with media changed',
848  'media' => '1404,1407,1405',
849  ],
850  1 => [
851  'uid' => 2040,
852  'title' => 'EN Parent 2040',
853  'media' => '',
854  ],
855  0 => [
856  'uid' => 1,
857  'title' => 'EN Root',
858  'media' => '',
859  ],
860  ],
861  ];
862 
863  yield 'categories lang default' => [
864  'uid' => 3010,
865  'language' => 0,
866  'workspace' => 0,
867  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
868  'expected' => [
869  2 => [
870  'uid' => 3010,
871  'title' => 'EN Parent 3000 Sub 10',
872  'categories' => '30,10,60,90,120',
873  'categories_other' => '20,30',
874  ],
875  1 => [
876  'uid' => 3000,
877  'title' => 'EN Parent 3000 contains categories',
878  'categories' => '',
879  'categories_other' => '',
880  ],
881  0 => [
882  'uid' => 1,
883  'title' => 'EN Root',
884  'categories' => '',
885  'categories_other' => '',
886  ],
887  ],
888  ];
889  yield 'categories lang FR, requesting with default lang uid' => [
890  'uid' => 3020,
891  'language' => 1,
892  'workspace' => 0,
893  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
894  'expected' => [
895  2 => [
896  'uid' => 3020,
897  'title' => 'FR Parent 3000 Sub 20',
898  'categories' => '30,20,60,90,120',
899  'categories_other' => '10,20',
900  ],
901  1 => [
902  'uid' => 3000,
903  'title' => 'FR Parent 3000 contains categories',
904  'categories' => '',
905  'categories_other' => '',
906  ],
907  0 => [
908  'uid' => 1,
909  'title' => 'EN Root',
910  'categories' => '',
911  'categories_other' => '',
912  ],
913  ],
914  ];
915  yield 'categories lang FR, requesting with FR lang uid' => [
916  'uid' => 3021,
917  'language' => 1,
918  'workspace' => 0,
919  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
920  'expected' => [
921  2 => [
922  'uid' => 3021,
923  'title' => 'FR Parent 3000 Sub 20',
924  'categories' => '30,20,60,90,120',
925  'categories_other' => '10,20',
926  ],
927  1 => [
928  'uid' => 3000,
929  'title' => 'FR Parent 3000 contains categories',
930  'categories' => '',
931  'categories_other' => '',
932  ],
933  0 => [
934  'uid' => 1,
935  'title' => 'EN Root',
936  'categories' => '',
937  'categories_other' => '',
938  ],
939  ],
940  ];
941  yield 'categories lang default, workspace new' => [
942  'uid' => 3030,
943  'language' => 0,
944  'workspace' => 2,
945  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
946  'expected' => [
947  2 => [
948  'uid' => 3030,
949  'title' => 'EN WS2-new Parent 3000 Sub 30',
950  'categories' => '30,10,60,90,120,140',
951  'categories_other' => '20,30',
952  ],
953  1 => [
954  'uid' => 3000,
955  'title' => 'EN Parent 3000 contains categories',
956  'categories' => '',
957  'categories_other' => '',
958  ],
959  0 => [
960  'uid' => 1,
961  'title' => 'EN Root',
962  'categories' => '',
963  'categories_other' => '',
964  ],
965  ],
966  ];
967  yield 'categories lang FR, workspace new, requesting with default lang uid' => [
968  'uid' => 3040,
969  'language' => 1,
970  'workspace' => 2,
971  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
972  'expected' => [
973  2 => [
974  'uid' => 3040,
975  'title' => 'FR WS2-new Parent 3000 Sub 40',
976  'categories' => '30,10,60,90,120,140',
977  'categories_other' => '20,30',
978  ],
979  1 => [
980  'uid' => 3000,
981  'title' => 'FR Parent 3000 contains categories',
982  'categories' => '',
983  'categories_other' => '',
984  ],
985  0 => [
986  'uid' => 1,
987  'title' => 'EN Root',
988  'categories' => '',
989  'categories_other' => '',
990  ],
991  ],
992  ];
993  yield 'categories lang FR, workspace new, requesting with FR lang uid' => [
994  'uid' => 3041,
995  'language' => 1,
996  'workspace' => 2,
997  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
998  'expected' => [
999  2 => [
1000  'uid' => 3041,
1001  'title' => 'FR WS2-new Parent 3000 Sub 40',
1002  'categories' => '30,10,60,90,120,140',
1003  'categories_other' => '20,30',
1004  ],
1005  1 => [
1006  'uid' => 3000,
1007  'title' => 'FR Parent 3000 contains categories',
1008  'categories' => '',
1009  'categories_other' => '',
1010  ],
1011  0 => [
1012  'uid' => 1,
1013  'title' => 'EN Root',
1014  'categories' => '',
1015  'categories_other' => '',
1016  ],
1017  ],
1018  ];
1019  yield 'categories lang default, workspace categories changed, requesting with live uid' => [
1020  'uid' => 3050,
1021  'language' => 0,
1022  'workspace' => 2,
1023  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
1024  'expected' => [
1025  2 => [
1026  'uid' => 3050,
1027  'title' => 'EN WS2-changed Parent 3000 Sub 50',
1028  // @todo missing cases: - a category is changed (eg. title) in ws
1029  // - a category is unhidden, starttime, endtime enabled in ws, while it is not in live
1030  // - this test case for FR, as with 'media lang FR, workspace media elements changed'
1031  // @todo observations: While inline foreign_field localized relations point to the localized records, MM relations do not
1032  // on the local 'category' side. Those need to be overlayed when dealing with localized
1033  // categories. This also has the side effect that hidden,starttime and endtime restrictions
1034  // from the default language kick in, and those of the localized overlays are ignored.
1035  'categories' => '30,60,90,120,140,20',
1036  'categories_other' => '20',
1037  ],
1038  1 => [
1039  'uid' => 3000,
1040  'title' => 'EN Parent 3000 contains categories',
1041  'categories' => '',
1042  'categories_other' => '',
1043  ],
1044  0 => [
1045  'uid' => 1,
1046  'title' => 'EN Root',
1047  'categories' => '',
1048  'categories_other' => '',
1049  ],
1050  ],
1051  ];
1052  yield 'categories lang default, workspace categories changed, requesting with workspace uid' => [
1053  'uid' => 3051,
1054  'language' => 0,
1055  'workspace' => 2,
1056  'testFields' => ['uid', 'title', 'categories', 'categories_other'],
1057  'expected' => [
1058  2 => [
1059  'uid' => 3051,
1060  'title' => 'EN WS2-changed Parent 3000 Sub 50',
1061  'categories' => '30,60,90,120,140,20',
1062  'categories_other' => '20',
1063  ],
1064  1 => [
1065  'uid' => 3000,
1066  'title' => 'EN Parent 3000 contains categories',
1067  'categories' => '',
1068  'categories_other' => '',
1069  ],
1070  0 => [
1071  'uid' => 1,
1072  'title' => 'EN Root',
1073  'categories' => '',
1074  'categories_other' => '',
1075  ],
1076  ],
1077  ];
1078 
1079  yield 'hotel lang default' => [
1080  'uid' => 4010,
1081  'language' => 0,
1082  'workspace' => 0,
1083  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1084  'expected' => [
1085  2 => [
1086  'uid' => 4010,
1087  'title' => 'EN Parent 4000 Sub 10',
1088  'tx_testrootlineutility_hotels' => '1001,1000',
1089  ],
1090  1 => [
1091  'uid' => 4000,
1092  'title' => 'EN Parent 4000',
1093  'tx_testrootlineutility_hotels' => '',
1094  ],
1095  0 => [
1096  'uid' => 1,
1097  'title' => 'EN Root',
1098  'tx_testrootlineutility_hotels' => '',
1099  ],
1100  ],
1101  ];
1102  yield 'hotel lang FR, requesting with default lang uid' => [
1103  'uid' => 4020,
1104  'language' => 1,
1105  'workspace' => 0,
1106  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1107  'expected' => [
1108  2 => [
1109  'uid' => 4020,
1110  'title' => 'FR Parent 4000 Sub 20',
1111  'tx_testrootlineutility_hotels' => '1101,1103,1112,1118,1124,1125',
1112  ],
1113  1 => [
1114  'uid' => 4000,
1115  'title' => 'EN Parent 4000',
1116  'tx_testrootlineutility_hotels' => '',
1117  ],
1118  0 => [
1119  'uid' => 1,
1120  'title' => 'EN Root',
1121  'tx_testrootlineutility_hotels' => '',
1122  ],
1123  ],
1124  ];
1125  yield 'hotel lang FR, requesting with FR lang uid' => [
1126  'uid' => 4021,
1127  'language' => 1,
1128  'workspace' => 0,
1129  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1130  'expected' => [
1131  2 => [
1132  'uid' => 4021,
1133  'title' => 'FR Parent 4000 Sub 20',
1134  'tx_testrootlineutility_hotels' => '1101,1103,1112,1118,1124,1125',
1135  ],
1136  1 => [
1137  'uid' => 4000,
1138  'title' => 'EN Parent 4000',
1139  'tx_testrootlineutility_hotels' => '',
1140  ],
1141  0 => [
1142  'uid' => 1,
1143  'title' => 'EN Root',
1144  'tx_testrootlineutility_hotels' => '',
1145  ],
1146  ],
1147  ];
1148  yield 'hotel lang default, workspace new' => [
1149  'uid' => 4030,
1150  'language' => 0,
1151  'workspace' => 2,
1152  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1153  'expected' => [
1154  2 => [
1155  'uid' => 4030,
1156  'title' => 'EN WS2-new Parent 4000 Sub 30',
1157  'tx_testrootlineutility_hotels' => '1201,1200',
1158  ],
1159  1 => [
1160  'uid' => 4000,
1161  'title' => 'EN Parent 4000',
1162  'tx_testrootlineutility_hotels' => '',
1163  ],
1164  0 => [
1165  'uid' => 1,
1166  'title' => 'EN Root',
1167  'tx_testrootlineutility_hotels' => '',
1168  ],
1169  ],
1170  ];
1171  yield 'hotel lang FR, workspace new, requesting with default lang uid' => [
1172  'uid' => 4040,
1173  'language' => 1,
1174  'workspace' => 2,
1175  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1176  'expected' => [
1177  2 => [
1178  'uid' => 4040,
1179  'title' => 'FR WS2-new Parent 4000 Sub 40',
1180  'tx_testrootlineutility_hotels' => '1301,1303,1312,1318,1324,1325',
1181  ],
1182  1 => [
1183  'uid' => 4000,
1184  'title' => 'EN Parent 4000',
1185  'tx_testrootlineutility_hotels' => '',
1186  ],
1187  0 => [
1188  'uid' => 1,
1189  'title' => 'EN Root',
1190  'tx_testrootlineutility_hotels' => '',
1191  ],
1192  ],
1193  ];
1194  yield 'hotel lang FR, workspace new, requesting with FR lang uid' => [
1195  'uid' => 4041,
1196  'language' => 1,
1197  'workspace' => 2,
1198  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1199  'expected' => [
1200  2 => [
1201  'uid' => 4041,
1202  'title' => 'FR WS2-new Parent 4000 Sub 40',
1203  'tx_testrootlineutility_hotels' => '1301,1303,1312,1318,1324,1325',
1204  ],
1205  1 => [
1206  'uid' => 4000,
1207  'title' => 'EN Parent 4000',
1208  'tx_testrootlineutility_hotels' => '',
1209  ],
1210  0 => [
1211  'uid' => 1,
1212  'title' => 'EN Root',
1213  'tx_testrootlineutility_hotels' => '',
1214  ],
1215  ],
1216  ];
1217  yield 'hotel lang default, workspace hotels changed, requesting with live uid' => [
1218  'uid' => 4050,
1219  'language' => 0,
1220  'workspace' => 2,
1221  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1222  'expected' => [
1223  2 => [
1224  'uid' => 4050,
1225  'title' => 'EN WS2-changed Parent 4000 Sub 50',
1226  'tx_testrootlineutility_hotels' => '1401,1403,1404,1412,1418,1424',
1227  ],
1228  1 => [
1229  'uid' => 4000,
1230  'title' => 'EN Parent 4000',
1231  'tx_testrootlineutility_hotels' => '',
1232  ],
1233  0 => [
1234  'uid' => 1,
1235  'title' => 'EN Root',
1236  'tx_testrootlineutility_hotels' => '',
1237  ],
1238  ],
1239  ];
1240  yield 'hotel lang default, workspace hotels changed, requesting with workspace uid' => [
1241  'uid' => 4051,
1242  'language' => 0,
1243  'workspace' => 2,
1244  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1245  'expected' => [
1246  2 => [
1247  'uid' => 4051,
1248  'title' => 'EN WS2-changed Parent 4000 Sub 50',
1249  'tx_testrootlineutility_hotels' => '1401,1403,1404,1412,1418,1424',
1250  ],
1251  1 => [
1252  'uid' => 4000,
1253  'title' => 'EN Parent 4000',
1254  'tx_testrootlineutility_hotels' => '',
1255  ],
1256  0 => [
1257  'uid' => 1,
1258  'title' => 'EN Root',
1259  'tx_testrootlineutility_hotels' => '',
1260  ],
1261  ],
1262  ];
1263  yield 'hotel lang FR, workspace hotels changed, requesting with live uid and default lang' => [
1264  'uid' => 4060,
1265  'language' => 1,
1266  'workspace' => 2,
1267  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1268  'expected' => [
1269  2 => [
1270  'uid' => 4060,
1271  'title' => 'FR WS2-changed Parent 4000 Sub 60',
1272  'tx_testrootlineutility_hotels' => '1502,1504,1505,1513,1519,1525',
1273  ],
1274  1 => [
1275  'uid' => 4000,
1276  'title' => 'EN Parent 4000',
1277  'tx_testrootlineutility_hotels' => '',
1278  ],
1279  0 => [
1280  'uid' => 1,
1281  'title' => 'EN Root',
1282  'tx_testrootlineutility_hotels' => '',
1283  ],
1284  ],
1285  ];
1286  yield 'hotel lang FR, workspace hotels changed, requesting with live uid and FR lang' => [
1287  'uid' => 4061,
1288  'language' => 1,
1289  'workspace' => 2,
1290  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1291  'expected' => [
1292  2 => [
1293  'uid' => 4061,
1294  'title' => 'FR WS2-changed Parent 4000 Sub 60',
1295  'tx_testrootlineutility_hotels' => '1502,1504,1505,1513,1519,1525',
1296  ],
1297  1 => [
1298  'uid' => 4000,
1299  'title' => 'EN Parent 4000',
1300  'tx_testrootlineutility_hotels' => '',
1301  ],
1302  0 => [
1303  'uid' => 1,
1304  'title' => 'EN Root',
1305  'tx_testrootlineutility_hotels' => '',
1306  ],
1307  ],
1308  ];
1309  yield 'hotel lang FR, workspace hotels changed, requesting with workspace uid' => [
1310  'uid' => 4062,
1311  'language' => 1,
1312  'workspace' => 2,
1313  'testFields' => ['uid', 'title', 'tx_testrootlineutility_hotels'],
1314  'expected' => [
1315  2 => [
1316  'uid' => 4062,
1317  'title' => 'FR WS2-changed Parent 4000 Sub 60',
1318  'tx_testrootlineutility_hotels' => '1502,1504,1505,1513,1519,1525',
1319  ],
1320  1 => [
1321  'uid' => 4000,
1322  'title' => 'EN Parent 4000',
1323  'tx_testrootlineutility_hotels' => '',
1324  ],
1325  0 => [
1326  'uid' => 1,
1327  'title' => 'EN Root',
1328  'tx_testrootlineutility_hotels' => '',
1329  ],
1330  ],
1331  ];
1332  }
1333 
1334  #[DataProvider('getResolvesCorrectlyDataProvider')]
1335  #[Test]
1336  public function ‪getResolvesCorrectly(int ‪$uid, int $language, int $workspace, array $testFields, array $expected): void
1337  {
1338  $context = new ‪Context();
1339  $context->setAspect('workspace', new ‪WorkspaceAspect($workspace));
1340  $context->setAspect('language', new ‪LanguageAspect($language));
1341  $context->setAspect('date', new ‪DateTimeAspect((new \DateTimeImmutable())->setTimestamp(time())));
1342  $result = (new ‪RootlineUtility(‪$uid, '', $context))->get();
1343  self::assertSame($expected, $this->‪filterExpectedValues($result, $testFields));
1344  }
1346  public static function ‪getResolvesHiddenRelationsCorrectlyDataProvider(): \Generator
1347  {
1348  yield 'do not fetch hidden records' => [
1349  'uid' => 5010,
1350  'includeHiddenRecords' => false,
1351  'testFields' => ['uid', 'title', 'categories', 'categories_other', 'tx_testrootlineutility_hotels'],
1352  'expected' => [
1353  2 => [
1354  'uid' => 5010,
1355  'title' => 'EN Parent 5000 Sub 10',
1356  'categories' => '10',
1357  'categories_other' => '',
1358  'tx_testrootlineutility_hotels' => '1600',
1359  ],
1360  1 => [
1361  'uid' => 5000,
1362  'title' => 'EN Parent 5000',
1363  'categories' => '',
1364  'categories_other' => '',
1365  'tx_testrootlineutility_hotels' => '',
1366  ],
1367  0 => [
1368  'uid' => 1,
1369  'title' => 'EN Root',
1370  'categories' => '',
1371  'categories_other' => '',
1372  'tx_testrootlineutility_hotels' => '',
1373  ],
1374  ],
1375  ];
1376  yield 'fetch hidden records' => [
1377  'uid' => 5010,
1378  'includeHiddenRecords' => true,
1379  'testFields' => ['uid', 'title', 'categories', 'categories_other', 'tx_testrootlineutility_hotels'],
1380  'expected' => [
1381  2 => [
1382  'uid' => 5010,
1383  'title' => 'EN Parent 5000 Sub 10',
1384  'categories' => '10,50',
1385  'categories_other' => '',
1386  'tx_testrootlineutility_hotels' => '1600,1601',
1387  ],
1388  1 => [
1389  'uid' => 5000,
1390  'title' => 'EN Parent 5000',
1391  'categories' => '',
1392  'categories_other' => '',
1393  'tx_testrootlineutility_hotels' => '',
1394  ],
1395  0 => [
1396  'uid' => 1,
1397  'title' => 'EN Root',
1398  'categories' => '',
1399  'categories_other' => '',
1400  'tx_testrootlineutility_hotels' => '',
1401  ],
1402  ],
1403  ];
1404  }
1405 
1406  #[DataProvider('getResolvesHiddenRelationsCorrectlyDataProvider')]
1407  #[Test]
1408  public function ‪getResolvesHiddenRelationsCorrectly(int ‪$uid, bool $includeHiddenRecords, array $testFields, array $expected): void
1409  {
1410  $context = new ‪Context();
1411  $context->setAspect('workspace', new ‪WorkspaceAspect(0));
1412  $context->setAspect('language', new ‪LanguageAspect(0));
1413  $context->setAspect('date', new ‪DateTimeAspect((new \DateTimeImmutable())->setTimestamp(time())));
1414  $context->setAspect('visibility', new ‪VisibilityAspect(false, $includeHiddenRecords, false, false));
1415  $result = (new ‪RootlineUtility(‪$uid, '', $context))->get();
1416  self::assertSame($expected, $this->‪filterExpectedValues($result, $testFields));
1417  }
1419  public static function ‪getResolvesStarttimeEndtimeRelationsCorrectlyDataProvider(): \Generator
1420  {
1421  yield 'include scheduled records' => [
1422  'uid' => 6010,
1423  'includeScheduledRecords' => true,
1424  'simulateTime' => 1713132000, // Not relevant with includeScheduledRecords being true here
1425  'testFields' => ['uid', 'title', 'categories', 'categories_other', 'tx_testrootlineutility_hotels'],
1426  'expected' => [
1427  2 => [
1428  'uid' => 6010,
1429  'title' => 'EN Parent 6000 Sub 10',
1430  'categories' => '160,161,162,163',
1431  'categories_other' => '',
1432  'tx_testrootlineutility_hotels' => '1700,1701,1702,1703',
1433  ],
1434  1 => [
1435  'uid' => 6000,
1436  'title' => 'EN Parent 6000',
1437  'categories' => '',
1438  'categories_other' => '',
1439  'tx_testrootlineutility_hotels' => '',
1440  ],
1441  0 => [
1442  'uid' => 1,
1443  'title' => 'EN Root',
1444  'categories' => '',
1445  'categories_other' => '',
1446  'tx_testrootlineutility_hotels' => '',
1447  ],
1448  ],
1449  ];
1450  yield 'simulate time within starttime and endtime restrictions' => [
1451  'uid' => 6010,
1452  'includeScheduledRecords' => false,
1453  'simulateTime' => 1713132000, // 2024-04-15 00:00 UTC - within fixture starttime and endtime restrictions
1454  'testFields' => ['uid', 'title', 'categories', 'categories_other', 'tx_testrootlineutility_hotels'],
1455  'expected' => [
1456  2 => [
1457  'uid' => 6010,
1458  'title' => 'EN Parent 6000 Sub 10',
1459  'categories' => '160,161,162,163',
1460  'categories_other' => '',
1461  'tx_testrootlineutility_hotels' => '1700,1701,1702,1703',
1462  ],
1463  1 => [
1464  'uid' => 6000,
1465  'title' => 'EN Parent 6000',
1466  'categories' => '',
1467  'categories_other' => '',
1468  'tx_testrootlineutility_hotels' => '',
1469  ],
1470  0 => [
1471  'uid' => 1,
1472  'title' => 'EN Root',
1473  'categories' => '',
1474  'categories_other' => '',
1475  'tx_testrootlineutility_hotels' => '',
1476  ],
1477  ],
1478  ];
1479  yield 'simulate time before starttime restrictions' => [
1480  'uid' => 6010,
1481  'includeScheduledRecords' => false,
1482  'simulateTime' => 1712268000, // 2024-04-05 00:00 UTC - before starttime restrictions
1483  'testFields' => ['uid', 'title', 'categories', 'categories_other', 'tx_testrootlineutility_hotels'],
1484  'expected' => [
1485  2 => [
1486  'uid' => 6010,
1487  'title' => 'EN Parent 6000 Sub 10',
1488  'categories' => '160,162',
1489  'categories_other' => '',
1490  'tx_testrootlineutility_hotels' => '1700,1702',
1491  ],
1492  1 => [
1493  'uid' => 6000,
1494  'title' => 'EN Parent 6000',
1495  'categories' => '',
1496  'categories_other' => '',
1497  'tx_testrootlineutility_hotels' => '',
1498  ],
1499  0 => [
1500  'uid' => 1,
1501  'title' => 'EN Root',
1502  'categories' => '',
1503  'categories_other' => '',
1504  'tx_testrootlineutility_hotels' => '',
1505  ],
1506  ],
1507  ];
1508  yield 'simulate time after endtime restrictions' => [
1509  'uid' => 6010,
1510  'includeScheduledRecords' => false,
1511  'simulateTime' => 1713996000, // 2024-04-25 00:00 UTC - after endtime restrictions
1512  'testFields' => ['uid', 'title', 'categories', 'categories_other', 'tx_testrootlineutility_hotels'],
1513  'expected' => [
1514  2 => [
1515  'uid' => 6010,
1516  'title' => 'EN Parent 6000 Sub 10',
1517  'categories' => '160,161',
1518  'categories_other' => '',
1519  'tx_testrootlineutility_hotels' => '1700,1701',
1520  ],
1521  1 => [
1522  'uid' => 6000,
1523  'title' => 'EN Parent 6000',
1524  'categories' => '',
1525  'categories_other' => '',
1526  'tx_testrootlineutility_hotels' => '',
1527  ],
1528  0 => [
1529  'uid' => 1,
1530  'title' => 'EN Root',
1531  'categories' => '',
1532  'categories_other' => '',
1533  'tx_testrootlineutility_hotels' => '',
1534  ],
1535  ],
1536  ];
1537  }
1538 
1539  #[DataProvider('getResolvesStarttimeEndtimeRelationsCorrectlyDataProvider')]
1540  #[Test]
1541  public function ‪getResolvesStarttimeEndtimeRelationsCorrectly(int ‪$uid, bool $includeScheduledRecords, int $simulateTime, array $testFields, array $expected): void
1542  {
1543  $context = new ‪Context();
1544  $context->setAspect('workspace', new ‪WorkspaceAspect(0));
1545  $context->setAspect('language', new ‪LanguageAspect(0));
1546  $context->setAspect('date', new ‪DateTimeAspect((new \DateTimeImmutable())->setTimestamp($simulateTime)));
1547  $context->setAspect('visibility', new ‪VisibilityAspect(false, false, false, $includeScheduledRecords));
1548  $result = (new ‪RootlineUtility(‪$uid, '', $context))->get();
1549  self::assertSame($expected, $this->‪filterExpectedValues($result, $testFields));
1550  }
1551 }
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageWithMountedPageAddsMountPointParameterToReturnValue
‪processMountedPageWithMountedPageAddsMountPointParameterToReturnValue()
Definition: RootlineUtilityTest.php:148
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsGroupFieldAsLocal
‪columnHasRelationToResolveDetectsGroupFieldAsLocal()
Definition: RootlineUtilityTest.php:217
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsInlineFieldAsLocal
‪columnHasRelationToResolveDetectsInlineFieldAsLocal()
Definition: RootlineUtilityTest.php:248
‪TYPO3\CMS\Core\Context\VisibilityAspect
Definition: VisibilityAspect.php:31
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote
‪columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote()
Definition: RootlineUtilityTest.php:232
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:31
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageWithMountedPageAddsMountedFromParameter
‪processMountedPageWithMountedPageAddsMountedFromParameter()
Definition: RootlineUtilityTest.php:134
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote
‪columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote()
Definition: RootlineUtilityTest.php:279
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_DEFAULT
‪const DOKTYPE_DEFAULT
Definition: PageRepository.php:98
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest
Definition: RootlineUtilityTest.php:36
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\LANGUAGE_PRESETS
‪const LANGUAGE_PRESETS
Definition: RootlineUtilityTest.php:38
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getResolvesStarttimeEndtimeRelationsCorrectly
‪getResolvesStarttimeEndtimeRelationsCorrectly(int $uid, bool $includeScheduledRecords, int $simulateTime, array $testFields, array $expected)
Definition: RootlineUtilityTest.php:1540
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait
Definition: SiteBasedTestTrait.php:37
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:48
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote
‪columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote()
Definition: RootlineUtilityTest.php:263
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getResolvesHiddenRelationsCorrectlyDataProvider
‪static getResolvesHiddenRelationsCorrectlyDataProvider()
Definition: RootlineUtilityTest.php:1345
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\writeSiteConfiguration
‪writeSiteConfiguration(string $identifier, array $site=[], array $languages=[], array $errorHandling=[])
Definition: SiteBasedTestTrait.php:50
‪TYPO3\CMS\Core\Utility\RootlineUtility
Definition: RootlineUtility.php:39
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\rootlineFailsForDeletedParentPageInWorkspace
‪rootlineFailsForDeletedParentPageInWorkspace()
Definition: RootlineUtilityTest.php:372
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\verifyCleanReferenceIndex
‪verifyCleanReferenceIndex()
Definition: RootlineUtilityTest.php:78
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildSiteConfiguration
‪buildSiteConfiguration(int $rootPageId, string $base='')
Definition: SiteBasedTestTrait.php:88
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\$testExtensionsToLoad
‪array $testExtensionsToLoad
Definition: RootlineUtilityTest.php:44
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getResolvesStarttimeEndtimeRelationsCorrectlyDataProvider
‪static getResolvesStarttimeEndtimeRelationsCorrectlyDataProvider()
Definition: RootlineUtilityTest.php:1418
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageWithNonMountedPageThrowsException
‪processMountedPageWithNonMountedPageThrowsException()
Definition: RootlineUtilityTest.php:111
‪TYPO3\CMS\Core\Cache\Frontend\NullFrontend
Definition: NullFrontend.php:30
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageWithMountedPageNotThrowsException
‪processMountedPageWithMountedPageNotThrowsException()
Definition: RootlineUtilityTest.php:121
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getResolvesCorrectly
‪getResolvesCorrectly(int $uid, int $language, int $workspace, array $testFields, array $expected)
Definition: RootlineUtilityTest.php:1335
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\isMountedPageWithNonMatchingMountPointParameterReturnsFalse
‪isMountedPageWithNonMatchingMountPointParameterReturnsFalse()
Definition: RootlineUtilityTest.php:103
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_MOUNTPOINT
‪const DOKTYPE_MOUNTPOINT
Definition: PageRepository.php:102
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\isMountedPageWithoutMountPointsReturnsFalse
‪isMountedPageWithoutMountPointsReturnsFalse()
Definition: RootlineUtilityTest.php:87
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\$coreExtensionsToLoad
‪array $coreExtensionsToLoad
Definition: RootlineUtilityTest.php:43
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote
‪columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote()
Definition: RootlineUtilityTest.php:310
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getResolvesCorrectlyDataProvider
‪static getResolvesCorrectlyDataProvider()
Definition: RootlineUtilityTest.php:381
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getResolvesHiddenRelationsCorrectly
‪getResolvesHiddenRelationsCorrectly(int $uid, bool $includeHiddenRecords, array $testFields, array $expected)
Definition: RootlineUtilityTest.php:1407
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage
‪processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage()
Definition: RootlineUtilityTest.php:176
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:57
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\isMountedPageWithMatchingMountPointParameterReturnsTrue
‪isMountedPageWithMatchingMountPointParameterReturnsTrue()
Definition: RootlineUtilityTest.php:95
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageForMountPageIsOverlayAddsMountOLParameter
‪processMountedPageForMountPageIsOverlayAddsMountOLParameter()
Definition: RootlineUtilityTest.php:162
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildLanguageConfiguration
‪buildLanguageConfiguration(string $identifier, string $base, array $fallbackIdentifiers=[], ?string $fallbackType=null)
Definition: SiteBasedTestTrait.php:108
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getForRootPageOnlyReturnsRootPageInformation
‪getForRootPageOnlyReturnsRootPageInformation()
Definition: RootlineUtilityTest.php:363
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildDefaultLanguageConfiguration
‪buildDefaultLanguageConfiguration(string $identifier, string $base)
Definition: SiteBasedTestTrait.php:98
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getCacheIdentifierContainsAllContextParameters
‪getCacheIdentifierContainsAllContextParameters()
Definition: RootlineUtilityTest.php:326
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Tests\Functional\Utility
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\setUp
‪setUp()
Definition: RootlineUtilityTest.php:48
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getWithPagesColumnsTcaNonArrayThrowsException
‪getWithPagesColumnsTcaNonArrayThrowsException()
Definition: RootlineUtilityTest.php:354
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage
‪processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage()
Definition: RootlineUtilityTest.php:197
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\getWithMissingPagesColumnsTcaThrowsException
‪getWithMissingPagesColumnsTcaThrowsException()
Definition: RootlineUtilityTest.php:345
‪TYPO3\CMS\Core\Context\LanguageAspect\OVERLAYS_OFF
‪const OVERLAYS_OFF
Definition: LanguageAspect.php:74
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Core\Exception\Page\PageNotFoundException
Definition: PageNotFoundException.php:23
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\filterExpectedValues
‪filterExpectedValues(array $incomingData, array $fields)
Definition: RootlineUtilityTest.php:62
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:35
‪TYPO3\CMS\Core\Tests\Functional\Utility\RootlineUtilityTest\columnHasRelationToResolveDetectsSelectFieldAsLocal
‪columnHasRelationToResolveDetectsSelectFieldAsLocal()
Definition: RootlineUtilityTest.php:295