PageRepositoryTest.php 23.3 KB
Newer Older
1
<?php
2

3
4
declare(strict_types=1);

5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * This file is part of the TYPO3 CMS project.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */

18
19
namespace TYPO3\CMS\Core\Tests\Functional\Domain\Repository;

20
use Prophecy\Argument;
21
22
use Prophecy\PhpUnit\ProphecyTrait;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
23
use TYPO3\CMS\Core\Context\Context;
24
use TYPO3\CMS\Core\Context\DateTimeAspect;
25
use TYPO3\CMS\Core\Context\LanguageAspect;
26
use TYPO3\CMS\Core\Context\UserAspect;
27
use TYPO3\CMS\Core\Context\WorkspaceAspect;
28
use TYPO3\CMS\Core\Database\ConnectionPool;
29
30
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Domain\Repository\PageRepositoryGetPageHookInterface;
31
use TYPO3\CMS\Core\Utility\GeneralUtility;
32
use TYPO3\CMS\Core\Utility\StringUtility;
33
use TYPO3\CMS\Core\Versioning\VersionState;
34
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
35
36
37
38

/**
 * Test case
 */
39
class PageRepositoryTest extends FunctionalTestCase
40
{
41
42
    use ProphecyTrait;

43
    protected function setUp(): void
44
45
    {
        parent::setUp();
46
        $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
47
48
49
50
51
    }

    /**
     * @test
     */
52
    public function getMenuSingleUidRoot(): void
53
    {
54
        $subject = new PageRepository();
55
        $rows = $subject->getMenu(1);
56
57
58
59
        self::assertArrayHasKey(2, $rows);
        self::assertArrayHasKey(3, $rows);
        self::assertArrayHasKey(4, $rows);
        self::assertCount(3, $rows);
60
61
62
63
64
    }

    /**
     * @test
     */
65
    public function getMenuSingleUidSubpage(): void
66
    {
67
        $subject = new PageRepository();
68
        $rows = $subject->getMenu(2);
69
70
        self::assertArrayHasKey(5, $rows);
        self::assertArrayHasKey(7, $rows);
71
        self::assertCount(2, $rows);
72
73
74
75
76
    }

    /**
     * @test
     */
77
    public function getMenuMultipleUid(): void
78
    {
79
        $subject = new PageRepository();
80
        $rows = $subject->getMenu([2, 3]);
81
82
83
84
        self::assertArrayHasKey(5, $rows);
        self::assertArrayHasKey(7, $rows);
        self::assertArrayHasKey(8, $rows);
        self::assertArrayHasKey(9, $rows);
85
        self::assertCount(4, $rows);
86
87
88
89
90
    }

    /**
     * @test
     */
91
    public function getMenuPageOverlay(): void
92
    {
93
        $subject = new PageRepository(new Context([
94
            'language' => new LanguageAspect(1),
95
        ]));
96

97
        $rows = $subject->getMenu([2, 3]);
98
99
100
101
        self::assertEquals('Attrappe 1-2-5', $rows[5]['title']);
        self::assertEquals('Dummy 1-2-7', $rows[7]['title']);
        self::assertEquals('Dummy 1-3-8', $rows[8]['title']);
        self::assertEquals('Attrappe 1-3-9', $rows[9]['title']);
102
        self::assertCount(4, $rows);
103
104
    }

105
106
107
    /**
     * @test
     */
108
    public function getMenuWithMountPoint(): void
109
110
111
112
113
114
115
116
117
118
119
120
    {
        $subject = new PageRepository();
        $rows = $subject->getMenu([1000]);
        self::assertEquals('root default language', $rows[1003]['title']);
        self::assertEquals('1001', $rows[1003]['uid']);
        self::assertEquals('1001-1003', $rows[1003]['_MP_PARAM']);
        self::assertCount(2, $rows);
    }

    /**
     * @test
     */
121
    public function getMenuPageOverlayWithMountPoint(): void
122
123
    {
        $subject = new PageRepository(new Context([
124
            'language' => new LanguageAspect(1),
125
126
127
128
129
130
131
132
133
        ]));
        $rows = $subject->getMenu([1000]);
        self::assertEquals('root translation', $rows[1003]['title']);
        self::assertEquals('1001', $rows[1003]['uid']);
        self::assertEquals('1002', $rows[1003]['_PAGES_OVERLAY_UID']);
        self::assertEquals('1001-1003', $rows[1003]['_MP_PARAM']);
        self::assertCount(2, $rows);
    }

134
135
136
    /**
     * @test
     */
137
    public function getPageOverlayById(): void
138
    {
139
140
        $subject = new PageRepository();
        $row = $subject->getPageOverlay(1, 1);
141
        $this->assertOverlayRow($row);
142
143
144
        self::assertEquals('Wurzel 1', $row['title']);
        self::assertEquals('901', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
145
146
147
148
149
    }

    /**
     * @test
     */
150
    public function getPageOverlayByIdWithoutTranslation(): void
151
    {
152
153
        $subject = new PageRepository();
        $row = $subject->getPageOverlay(4, 1);
154
155
        self::assertIsArray($row);
        self::assertCount(0, $row);
156
157
158
159
160
    }

    /**
     * @test
     */
161
    public function getPageOverlayByRow(): void
162
    {
163
164
165
        $subject = new PageRepository();
        $orig = $subject->getPage(1);
        $row = $subject->getPageOverlay($orig, 1);
166
        $this->assertOverlayRow($row);
167
168
169
170
        self::assertEquals(1, $row['uid']);
        self::assertEquals('Wurzel 1', $row['title']);
        self::assertEquals('901', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
171
172
173
174
175
    }

    /**
     * @test
     */
176
    public function getPageOverlayByRowWithoutTranslation(): void
177
    {
178
179
180
        $subject = new PageRepository();
        $orig = $subject->getPage(4);
        $row = $subject->getPageOverlay($orig, 1);
181
182
183
        self::assertIsArray($row);
        self::assertEquals(4, $row['uid']);
        self::assertEquals('Dummy 1-4', $row['title']);//original title
184
185
186
187
188
    }

    /**
     * @test
     */
189
    public function getPagesOverlayByIdSingle(): void
190
    {
191
        $subject = new PageRepository(new Context([
192
            'language' => new LanguageAspect(1),
193
        ]));
194
        $rows = $subject->getPagesOverlay([1]);
195
196
197
        self::assertIsArray($rows);
        self::assertCount(1, $rows);
        self::assertArrayHasKey(0, $rows);
198
199
200

        $row = $rows[0];
        $this->assertOverlayRow($row);
201
202
203
        self::assertEquals('Wurzel 1', $row['title']);
        self::assertEquals('901', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
204
205
206
207
208
    }

    /**
     * @test
     */
209
    public function getPagesOverlayByIdMultiple(): void
210
    {
211
        $subject = new PageRepository(new Context([
212
            'language' => new LanguageAspect(1),
213
        ]));
214
        $rows = $subject->getPagesOverlay([1, 5]);
215
216
217
218
        self::assertIsArray($rows);
        self::assertCount(2, $rows);
        self::assertArrayHasKey(0, $rows);
        self::assertArrayHasKey(1, $rows);
219
220
221

        $row = $rows[0];
        $this->assertOverlayRow($row);
222
223
224
        self::assertEquals('Wurzel 1', $row['title']);
        self::assertEquals('901', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
225
226
227

        $row = $rows[1];
        $this->assertOverlayRow($row);
228
229
230
        self::assertEquals('Attrappe 1-2-5', $row['title']);
        self::assertEquals('904', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
231
232
233
234
235
    }

    /**
     * @test
     */
236
    public function getPagesOverlayByIdMultipleSomeNotOverlaid(): void
237
    {
238
        $subject = new PageRepository(new Context([
239
            'language' => new LanguageAspect(1),
240
        ]));
241
        $rows = $subject->getPagesOverlay([1, 4, 5, 8]);
242
243
244
245
        self::assertIsArray($rows);
        self::assertCount(2, $rows);
        self::assertArrayHasKey(0, $rows);
        self::assertArrayHasKey(2, $rows);
246
247
248

        $row = $rows[0];
        $this->assertOverlayRow($row);
249
        self::assertEquals('Wurzel 1', $row['title']);
250
251
252

        $row = $rows[2];
        $this->assertOverlayRow($row);
253
        self::assertEquals('Attrappe 1-2-5', $row['title']);
254
255
256
257
258
    }

    /**
     * @test
     */
259
    public function getPagesOverlayByRowSingle(): void
260
    {
261
262
        $subject = new PageRepository();
        $origRow = $subject->getPage(1);
263

264
        $subject = new PageRepository(new Context([
265
            'language' => new LanguageAspect(1),
266
        ]));
267
        $rows = $subject->getPagesOverlay([$origRow]);
268
269
270
        self::assertIsArray($rows);
        self::assertCount(1, $rows);
        self::assertArrayHasKey(0, $rows);
271
272
273

        $row = $rows[0];
        $this->assertOverlayRow($row);
274
275
276
        self::assertEquals('Wurzel 1', $row['title']);
        self::assertEquals('901', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
277
278
279
280
281
    }

    /**
     * @test
     */
282
    public function groupRestrictedPageCanBeOverlaid(): void
283
284
285
286
287
    {
        $subject = new PageRepository();
        $origRow = $subject->getPage(6, true);

        $subject = new PageRepository(new Context([
288
            'language' => new LanguageAspect(1),
289
290
291
292
293
294
295
296
297
298
299
        ]));
        $rows = $subject->getPagesOverlay([$origRow]);
        self::assertIsArray($rows);
        self::assertCount(1, $rows);
        self::assertArrayHasKey(0, $rows);

        $row = $rows[0];
        $this->assertOverlayRow($row);
        self::assertEquals('Attrappe 1-2-6', $row['title']);
        self::assertEquals('905', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
300
301
302
303
304
    }

    /**
     * @test
     */
305
    public function getPagesOverlayByRowMultiple(): void
306
    {
307
308
309
        $subject = new PageRepository();
        $orig1 = $subject->getPage(1);
        $orig2 = $subject->getPage(5);
310

311
        $subject = new PageRepository(new Context([
312
            'language' => new LanguageAspect(1),
313
        ]));
314
        $rows = $subject->getPagesOverlay([1 => $orig1, 5 => $orig2]);
315
316
317
318
        self::assertIsArray($rows);
        self::assertCount(2, $rows);
        self::assertArrayHasKey(1, $rows);
        self::assertArrayHasKey(5, $rows);
319
320
321

        $row = $rows[1];
        $this->assertOverlayRow($row);
322
323
324
        self::assertEquals('Wurzel 1', $row['title']);
        self::assertEquals('901', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
325
326
327

        $row = $rows[5];
        $this->assertOverlayRow($row);
328
329
330
        self::assertEquals('Attrappe 1-2-5', $row['title']);
        self::assertEquals('904', $row['_PAGES_OVERLAY_UID']);
        self::assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
331
332
333
334
335
    }

    /**
     * @test
     */
336
    public function getPagesOverlayByRowMultipleSomeNotOverlaid(): void
337
    {
338
339
340
341
        $subject = new PageRepository();
        $orig1 = $subject->getPage(1);
        $orig2 = $subject->getPage(7);
        $orig3 = $subject->getPage(9);
342

343
        $subject = new PageRepository(new Context([
344
            'language' => new LanguageAspect(1),
345
        ]));
346
        $rows = $subject->getPagesOverlay([$orig1, $orig2, $orig3]);
347
348
349
350
351
        self::assertIsArray($rows);
        self::assertCount(3, $rows);
        self::assertArrayHasKey(0, $rows);
        self::assertArrayHasKey(1, $rows);
        self::assertArrayHasKey(2, $rows);
352
353
354

        $row = $rows[0];
        $this->assertOverlayRow($row);
355
        self::assertEquals('Wurzel 1', $row['title']);
356
357
358

        $row = $rows[1];
        $this->assertNotOverlayRow($row);
359
        self::assertEquals('Dummy 1-2-7', $row['title']);
360
361
362

        $row = $rows[2];
        $this->assertOverlayRow($row);
363
        self::assertEquals('Attrappe 1-3-9', $row['title']);
364
365
    }

366
367
368
369
370
    /**
     * Tests whether the getPage Hook is called correctly.
     *
     * @test
     */
371
    public function isGetPageHookCalled(): void
372
373
374
375
376
377
378
379
380
381
382
    {
        // Create a hook mock object
        $getPageHookProphet = $this->prophesize(\stdClass::class);
        $getPageHookProphet->willImplement(PageRepositoryGetPageHookInterface::class);
        $getPageHookProphet->getPage_preProcess(42, false, Argument::type(PageRepository::class))->shouldBeCalled();
        $getPageHookMock = $getPageHookProphet->reveal();
        $className = get_class($getPageHookMock);

        // Register hook mock object
        GeneralUtility::addInstance($className, $getPageHookMock);
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPage'][] = $className;
383
384
        $subject = new PageRepository();
        $subject->getPage(42, false);
385
386
387
388
389
    }

    /**
     * @test
     */
390
    public function initSetsPublicPropertyCorrectlyForWorkspacePreview(): void
391
    {
392
393
        $workspaceId = 2;
        $subject = new PageRepository(new Context([
394
            'workspace' => new WorkspaceAspect($workspaceId),
395
        ]));
396
397
398
399

        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');

        $expectedSQL = sprintf(
400
            ' AND (%s = 0) AND ((%s = 0) OR (%s = 2)) AND (%s <> 255)',
401
402
            $connection->quoteIdentifier('pages.deleted'),
            $connection->quoteIdentifier('pages.t3ver_wsid'),
403
404
            $connection->quoteIdentifier('pages.t3ver_wsid'),
            $connection->quoteIdentifier('pages.doktype')
405
406
        );

407
        self::assertSame($expectedSQL, $subject->where_hid_del);
408
409
410
411
412
    }

    /**
     * @test
     */
413
    public function initSetsEnableFieldsCorrectlyForLive(): void
414
    {
415
        $subject = new PageRepository(new Context([
416
            'date' => new DateTimeAspect(new \DateTimeImmutable('@1451779200')),
417
        ]));
418
419
420

        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');
        $expectedSQL = sprintf(
421
            ' AND ((%s = 0) AND (%s <= 0) AND (%s = 0) AND ((%s = 0) OR (%s = 4)) AND (%s = 0) AND (%s <= 1451779200) AND ((%s = 0) OR (%s > 1451779200))) AND (%s <> 255)',
422
423
            $connection->quoteIdentifier('pages.deleted'),
            $connection->quoteIdentifier('pages.t3ver_state'),
424
425
            $connection->quoteIdentifier('pages.t3ver_wsid'),
            $connection->quoteIdentifier('pages.t3ver_oid'),
426
            $connection->quoteIdentifier('pages.t3ver_state'),
427
428
429
            $connection->quoteIdentifier('pages.hidden'),
            $connection->quoteIdentifier('pages.starttime'),
            $connection->quoteIdentifier('pages.endtime'),
430
431
            $connection->quoteIdentifier('pages.endtime'),
            $connection->quoteIdentifier('pages.doktype')
432
433
        );

434
        self::assertSame($expectedSQL, $subject->where_hid_del);
435
436
    }

437
438
439
440
441
442
443
    ////////////////////////////////
    // Tests concerning mountpoints
    ////////////////////////////////
    ///
    /**
     * @test
     */
444
    public function getMountPointInfoForDefaultLanguage(): void
445
446
447
448
449
450
451
452
453
    {
        $subject = new PageRepository();
        $mountPointInfo = $subject->getMountPointInfo(1003);
        self::assertEquals('1001-1003', $mountPointInfo['MPvar']);
    }

    /**
     * @test
     */
454
    public function getMountPointInfoForTranslation(): void
455
456
457
    {
        $mpVar = '1001-1003';
        $subject = new PageRepository(new Context([
458
            'language' => new LanguageAspect(1),
459
460
461
462
463
464
465
466
        ]));
        $mountPointInfo = $subject->getMountPointInfo(1003);
        self::assertEquals($mpVar, $mountPointInfo['MPvar']);

        $mountPointInfo = $subject->getMountPointInfo(1004);
        self::assertEquals($mpVar, $mountPointInfo['MPvar']);
    }

467
468
469
470
471
472
473
    ////////////////////////////////
    // Tests concerning workspaces
    ////////////////////////////////

    /**
     * @test
     */
474
    public function previewShowsPagesFromLiveAndCurrentWorkspace(): void
475
476
477
    {
        // initialization
        $wsid = 987654321;
478
        // simulate calls from \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->determineId()
479
        $subject = new PageRepository(new Context([
480
            'workspace' => new WorkspaceAspect($wsid),
481
        ]));
482

483
        $pageRec = $subject->getPage(11);
484

485
        self::assertEquals(11, $pageRec['uid']);
486
        self::assertEquals(0, $pageRec['t3ver_oid']);
487
        self::assertEquals(987654321, $pageRec['t3ver_wsid']);
488
        self::assertEquals(VersionState::NEW_PLACEHOLDER, $pageRec['t3ver_state']);
489
490
491
492
493
    }

    /**
     * @test
     */
494
    public function getWorkspaceVersionReturnsTheCorrectMethod(): void
495
496
497
498
    {
        // initialization
        $wsid = 987654321;

499
        // simulate calls from \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->determineId()
500
        $subject = new PageRepository(new Context([
501
            'workspace' => new WorkspaceAspect($wsid),
502
        ]));
503

504
        $pageRec = $subject->getWorkspaceVersionOfRecord($wsid, 'pages', 11);
505

506
507
        self::assertEquals(11, $pageRec['uid']);
        self::assertEquals(0, $pageRec['t3ver_oid']);
508
        self::assertEquals(987654321, $pageRec['t3ver_wsid']);
509
        self::assertEquals(VersionState::NEW_PLACEHOLDER, $pageRec['t3ver_state']);
510
511
512
513
514
515
516
517
518
    }

    ////////////////////////////////
    // Tests concerning versioning
    ////////////////////////////////

    /**
     * @test
     */
519
    public function enableFieldsHidesVersionedRecordsAndPlaceholders(): void
520
    {
521
        $table = StringUtility::getUniqueId('aTable');
522
523
        $GLOBALS['TCA'][$table] = [
            'ctrl' => [
524
525
                'versioningWS' => true,
            ],
526
527
        ];

528
        $subject = new PageRepository(new Context());
529

530
        $conditions = $subject->enableFields($table);
531
532
        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);

533
        self::assertThat(
534
            $conditions,
535
            self::stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' <= 0)'),
536
537
            'Versioning placeholders'
        );
538
        self::assertThat(
539
            $conditions,
540
            self::stringContains(' AND ((' . $connection->quoteIdentifier($table . '.t3ver_oid') . ' = 0) OR (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' = 4))'),
541
            'Records with online version'
542
543
544
545
546
547
        );
    }

    /**
     * @test
     */
548
    public function enableFieldsDoesNotHidePlaceholdersInPreview(): void
549
    {
550
        $table = StringUtility::getUniqueId('aTable');
551
552
        $GLOBALS['TCA'][$table] = [
            'ctrl' => [
553
554
                'versioningWS' => true,
            ],
555
556
        ];

557
        $subject = new PageRepository(new Context([
558
            'workspace' => new WorkspaceAspect(13),
559
        ]));
560

561
        $conditions = $subject->enableFields($table);
562
563
        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);

564
        self::assertThat(
565
            $conditions,
566
            self::logicalNot(self::stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' <= 0)')),
567
568
            'No versioning placeholders'
        );
569
        self::assertThat(
570
            $conditions,
571
            self::stringContains(' AND ((' . $connection->quoteIdentifier($table . '.t3ver_oid') . ' = 0) OR (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' = 4))'),
572
            'Records from online versions'
573
574
575
576
577
578
        );
    }

    /**
     * @test
     */
579
    public function enableFieldsDoesFilterToCurrentAndLiveWorkspaceForRecordsInPreview(): void
580
    {
581
        $table = StringUtility::getUniqueId('aTable');
582
583
        $GLOBALS['TCA'][$table] = [
            'ctrl' => [
584
585
                'versioningWS' => true,
            ],
586
587
        ];

588
        $subject = new PageRepository(new Context([
589
            'workspace' => new WorkspaceAspect(2),
590
        ]));
591

592
        $conditions = $subject->enableFields($table);
593
594
        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);

595
        self::assertThat(
596
            $conditions,
597
            self::stringContains(' AND ((' . $connection->quoteIdentifier($table . '.t3ver_wsid') . ' = 0) OR (' . $connection->quoteIdentifier($table . '.t3ver_wsid') . ' = 2))'),
598
599
600
601
            'No versioning placeholders'
        );
    }

602
    protected function assertOverlayRow($row): void
603
    {
604
        self::assertIsArray($row);
605

606
607
608
        self::assertArrayHasKey('_PAGES_OVERLAY', $row);
        self::assertArrayHasKey('_PAGES_OVERLAY_UID', $row);
        self::assertArrayHasKey('_PAGES_OVERLAY_LANGUAGE', $row);
609

610
        self::assertTrue($row['_PAGES_OVERLAY']);
611
612
    }

613
    protected function assertNotOverlayRow($row): void
614
    {
615
        self::assertIsArray($row);
616

617
618
619
        self::assertFalse(isset($row['_PAGES_OVERLAY']));
        self::assertFalse(isset($row['_PAGES_OVERLAY_UID']));
        self::assertFalse(isset($row['_PAGES_OVERLAY_LANGUAGE']));
620
    }
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

    /**
     * @test
     */
    public function getPageIdsRecursiveTest(): void
    {
        // do not use cache_treelist
        $user = new BackendUserAuthentication();
        $user->user = ['uid' => PHP_INT_MAX];
        $subject = new PageRepository(
            new Context([
                'backend.user' => new UserAspect($user),
            ])
        );
        // empty array does not do anything
        $result = $subject->getPageIdsRecursive([], 1);
        self::assertEquals([], $result);
        // pid=0 does not do anything
        $result = $subject->getPageIdsRecursive([0], 1);
        self::assertEquals([0], $result);
        // depth=0 does return given ids int-casted
        $result = $subject->getPageIdsRecursive(['1'], 0);
        self::assertEquals([1], $result);
        $result = $subject->getPageIdsRecursive([1], 1);
        self::assertEquals([1, 2, 3, 4], $result);
        $result = $subject->getPageIdsRecursive([1], 2);
        self::assertEquals([1, 2, 5, 7, 3, 8, 9, 4, 10], $result);
        $result = $subject->getPageIdsRecursive([1000], 99);
        self::assertEquals([1000, 1001], $result);
    }

    /**
     * @test
     */
    public function getDescendantPageIdsRecursiveTest(): void
    {
        // do not use cache_treelist
        $user = new BackendUserAuthentication();
        $user->user = ['uid' => PHP_INT_MAX];
        $subject = new PageRepository(
            new Context([
                'backend.user' => new UserAspect($user),
            ])
        );
        // Negative numbers or "0" do not return anything
        $result = $subject->getDescendantPageIdsRecursive(-1, 1);
        self::assertEquals([], $result);
        $result = $subject->getDescendantPageIdsRecursive(0, 1);
        self::assertEquals([], $result);
        $result = $subject->getDescendantPageIdsRecursive(1, 1);
        self::assertEquals([2, 3, 4], $result);
        $result = $subject->getDescendantPageIdsRecursive(1, 2);
        self::assertEquals([2, 5, 7, 3, 8, 9, 4, 10], $result);
        // "Begin" leaves out a level
        $result = $subject->getDescendantPageIdsRecursive(1, 2, 1);
        self::assertEquals([5, 7, 8, 9, 10], $result);
        // Exclude a branch (3)
        $result = $subject->getDescendantPageIdsRecursive(1, 2, excludePageIds: [3]);
        self::assertEquals([2, 5, 7, 4, 10], $result);
        // Include Page ID 6
        $result = $subject->getDescendantPageIdsRecursive(1, 2, bypassEnableFieldsCheck:true);
        self::assertEquals([2, 5, 6, 7, 3, 8, 9, 4, 10], $result);
    }
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704

    /**
     * @test
     */
    public function getLanguageOverlayResolvesContentWithNullInValues(): void
    {
        $context = new Context();
        $context->setAspect('language', new LanguageAspect(1, 1, LanguageAspect::OVERLAYS_ON_WITH_FLOATING, [0]));
        $subject = new PageRepository($context);
        $record = $subject->getRawRecord('tt_content', 1);
        self::assertSame('Default Content #1', $record['header']);
        $overlaidRecord = $subject->getLanguageOverlay('tt_content', $record);
        self::assertSame(2, $overlaidRecord['_LOCALIZED_UID']);
        self::assertSame('Translated Content #1', $overlaidRecord['header']);

        // Check if "bodytext" is actually overlaid with a NULL value
        $record = $subject->getRawRecord('tt_content', 3);
        $overlaidRecord = $subject->getLanguageOverlay('tt_content', $record);
        self::assertSame('Translated #2', $overlaidRecord['header']);
        self::assertNull($overlaidRecord['bodytext']);
    }
705
}