ceef2cdd250ec184e680c07d7b149dcb980bd8af
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Functional / Page / PageRepositoryTest.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Tests\Functional\Page;
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\Argument;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Tests\FunctionalTestCase;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Frontend\Page\PageRepository;
22 use TYPO3\CMS\Frontend\Page\PageRepositoryGetPageHookInterface;
23
24 /**
25 * Test case
26 */
27 class PageRepositoryTest extends FunctionalTestCase
28 {
29 protected $coreExtensionsToLoad = ['frontend'];
30
31 /**
32 * @var \TYPO3\CMS\Frontend\Page\PageRepository
33 */
34 protected $pageRepo;
35
36 protected function setUp()
37 {
38 parent::setUp();
39 $GLOBALS['TSFE']->gr_list = '';
40 $this->importDataSet(__DIR__ . '/../Fixtures/pages.xml');
41 $this->pageRepo = new PageRepository();
42 $this->pageRepo->init(false);
43 }
44
45 /**
46 * @test
47 */
48 public function getMenuSingleUidRoot()
49 {
50 $rows = $this->pageRepo->getMenu(1, 'uid, title');
51 $this->assertArrayHasKey(2, $rows);
52 $this->assertArrayHasKey(3, $rows);
53 $this->assertArrayHasKey(4, $rows);
54 $this->assertCount(3, $rows);
55 }
56
57 /**
58 * @test
59 */
60 public function getMenuSingleUidSubpage()
61 {
62 $rows = $this->pageRepo->getMenu(2, 'uid, title');
63 $this->assertArrayHasKey(5, $rows);
64 $this->assertArrayHasKey(6, $rows);
65 $this->assertArrayHasKey(7, $rows);
66 $this->assertCount(3, $rows);
67 }
68
69 /**
70 * @test
71 */
72 public function getMenuMulipleUid()
73 {
74 $rows = $this->pageRepo->getMenu([2, 3], 'uid, title');
75 $this->assertArrayHasKey(5, $rows);
76 $this->assertArrayHasKey(6, $rows);
77 $this->assertArrayHasKey(7, $rows);
78 $this->assertArrayHasKey(8, $rows);
79 $this->assertArrayHasKey(9, $rows);
80 $this->assertCount(5, $rows);
81 }
82
83 /**
84 * @test
85 */
86 public function getMenuPageOverlay()
87 {
88 $this->pageRepo->sys_language_uid = 1;
89
90 $rows = $this->pageRepo->getMenu([2, 3], 'uid, title');
91 $this->assertEquals('Attrappe 1-2-5', $rows[5]['title']);
92 $this->assertEquals('Attrappe 1-2-6', $rows[6]['title']);
93 $this->assertEquals('Dummy 1-2-7', $rows[7]['title']);
94 $this->assertEquals('Dummy 1-3-8', $rows[8]['title']);
95 $this->assertEquals('Attrappe 1-3-9', $rows[9]['title']);
96 $this->assertCount(5, $rows);
97 }
98
99 /**
100 * @test
101 */
102 public function getPageOverlayById()
103 {
104 $row = $this->pageRepo->getPageOverlay(1, 1);
105 $this->assertOverlayRow($row);
106 $this->assertEquals('Wurzel 1', $row['title']);
107 $this->assertEquals('901', $row['_PAGES_OVERLAY_UID']);
108 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
109 }
110
111 /**
112 * @test
113 */
114 public function getPageOverlayByIdWithoutTranslation()
115 {
116 $row = $this->pageRepo->getPageOverlay(4, 1);
117 $this->assertInternalType('array', $row);
118 $this->assertCount(0, $row);
119 }
120
121 /**
122 * @test
123 */
124 public function getPageOverlayByRow()
125 {
126 $orig = $this->pageRepo->getPage(1);
127 $row = $this->pageRepo->getPageOverlay($orig, 1);
128 $this->assertOverlayRow($row);
129 $this->assertEquals(1, $row['uid']);
130 $this->assertEquals('Wurzel 1', $row['title']);
131 $this->assertEquals('901', $row['_PAGES_OVERLAY_UID']);
132 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
133 }
134
135 /**
136 * @test
137 */
138 public function getPageOverlayByRowWithoutTranslation()
139 {
140 $orig = $this->pageRepo->getPage(4);
141 $row = $this->pageRepo->getPageOverlay($orig, 1);
142 $this->assertInternalType('array', $row);
143 $this->assertEquals(4, $row['uid']);
144 $this->assertEquals('Dummy 1-4', $row['title']);//original title
145 }
146
147 /**
148 * @test
149 */
150 public function getPagesOverlayByIdSingle()
151 {
152 $this->pageRepo->sys_language_uid = 1;
153 $rows = $this->pageRepo->getPagesOverlay([1]);
154 $this->assertInternalType('array', $rows);
155 $this->assertCount(1, $rows);
156 $this->assertArrayHasKey(0, $rows);
157
158 $row = $rows[0];
159 $this->assertOverlayRow($row);
160 $this->assertEquals('Wurzel 1', $row['title']);
161 $this->assertEquals('901', $row['_PAGES_OVERLAY_UID']);
162 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
163 }
164
165 /**
166 * @test
167 */
168 public function getPagesOverlayByIdMultiple()
169 {
170 $this->pageRepo->sys_language_uid = 1;
171 $rows = $this->pageRepo->getPagesOverlay([1, 5]);
172 $this->assertInternalType('array', $rows);
173 $this->assertCount(2, $rows);
174 $this->assertArrayHasKey(0, $rows);
175 $this->assertArrayHasKey(1, $rows);
176
177 $row = $rows[0];
178 $this->assertOverlayRow($row);
179 $this->assertEquals('Wurzel 1', $row['title']);
180 $this->assertEquals('901', $row['_PAGES_OVERLAY_UID']);
181 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
182
183 $row = $rows[1];
184 $this->assertOverlayRow($row);
185 $this->assertEquals('Attrappe 1-2-5', $row['title']);
186 $this->assertEquals('904', $row['_PAGES_OVERLAY_UID']);
187 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
188 }
189
190 /**
191 * @test
192 */
193 public function getPagesOverlayByIdMultipleSomeNotOverlaid()
194 {
195 $this->pageRepo->sys_language_uid = 1;
196 $rows = $this->pageRepo->getPagesOverlay([1, 4, 5, 8]);
197 $this->assertInternalType('array', $rows);
198 $this->assertCount(2, $rows);
199 $this->assertArrayHasKey(0, $rows);
200 $this->assertArrayHasKey(2, $rows);
201
202 $row = $rows[0];
203 $this->assertOverlayRow($row);
204 $this->assertEquals('Wurzel 1', $row['title']);
205
206 $row = $rows[2];
207 $this->assertOverlayRow($row);
208 $this->assertEquals('Attrappe 1-2-5', $row['title']);
209 }
210
211 /**
212 * @test
213 */
214 public function getPagesOverlayByRowSingle()
215 {
216 $origRow = $this->pageRepo->getPage(1);
217
218 $this->pageRepo->sys_language_uid = 1;
219 $rows = $this->pageRepo->getPagesOverlay([$origRow]);
220 $this->assertInternalType('array', $rows);
221 $this->assertCount(1, $rows);
222 $this->assertArrayHasKey(0, $rows);
223
224 $row = $rows[0];
225 $this->assertOverlayRow($row);
226 $this->assertEquals('Wurzel 1', $row['title']);
227 $this->assertEquals('901', $row['_PAGES_OVERLAY_UID']);
228 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
229 }
230
231 /**
232 * @test
233 */
234 public function getPagesOverlayByRowMultiple()
235 {
236 $orig1 = $this->pageRepo->getPage(1);
237 $orig2 = $this->pageRepo->getPage(5);
238
239 $this->pageRepo->sys_language_uid = 1;
240 $rows = $this->pageRepo->getPagesOverlay([1 => $orig1, 5 => $orig2]);
241 $this->assertInternalType('array', $rows);
242 $this->assertCount(2, $rows);
243 $this->assertArrayHasKey(1, $rows);
244 $this->assertArrayHasKey(5, $rows);
245
246 $row = $rows[1];
247 $this->assertOverlayRow($row);
248 $this->assertEquals('Wurzel 1', $row['title']);
249 $this->assertEquals('901', $row['_PAGES_OVERLAY_UID']);
250 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
251
252 $row = $rows[5];
253 $this->assertOverlayRow($row);
254 $this->assertEquals('Attrappe 1-2-5', $row['title']);
255 $this->assertEquals('904', $row['_PAGES_OVERLAY_UID']);
256 $this->assertEquals(1, $row['_PAGES_OVERLAY_LANGUAGE']);
257 }
258
259 /**
260 * @test
261 */
262 public function getPagesOverlayByRowMultipleSomeNotOverlaid()
263 {
264 $orig1 = $this->pageRepo->getPage(1);
265 $orig2 = $this->pageRepo->getPage(7);
266 $orig3 = $this->pageRepo->getPage(9);
267
268 $this->pageRepo->sys_language_uid = 1;
269 $rows = $this->pageRepo->getPagesOverlay([$orig1, $orig2, $orig3]);
270 $this->assertInternalType('array', $rows);
271 $this->assertCount(3, $rows);
272 $this->assertArrayHasKey(0, $rows);
273 $this->assertArrayHasKey(1, $rows);
274 $this->assertArrayHasKey(2, $rows);
275
276 $row = $rows[0];
277 $this->assertOverlayRow($row);
278 $this->assertEquals('Wurzel 1', $row['title']);
279
280 $row = $rows[1];
281 $this->assertNotOverlayRow($row);
282 $this->assertEquals('Dummy 1-2-7', $row['title']);
283
284 $row = $rows[2];
285 $this->assertOverlayRow($row);
286 $this->assertEquals('Attrappe 1-3-9', $row['title']);
287 }
288
289 /**
290 * Tests whether the getPage Hook is called correctly.
291 *
292 * @test
293 */
294 public function isGetPageHookCalled()
295 {
296 // Create a hook mock object
297 $getPageHookProphet = $this->prophesize(\stdClass::class);
298 $getPageHookProphet->willImplement(PageRepositoryGetPageHookInterface::class);
299 $getPageHookProphet->getPage_preProcess(42, false, Argument::type(PageRepository::class))->shouldBeCalled();
300 $getPageHookMock = $getPageHookProphet->reveal();
301 $className = get_class($getPageHookMock);
302
303 // Register hook mock object
304 GeneralUtility::addInstance($className, $getPageHookMock);
305 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_page.php']['getPage'][] = $className;
306 $this->pageRepo->getPage(42, false);
307 }
308
309 /**
310 * @test
311 */
312 public function initSetsPublicPropertyCorrectlyForWorkspacePreview()
313 {
314 $this->pageRepo->versioningPreview = true;
315 $this->pageRepo->versioningWorkspaceId = 2;
316 $this->pageRepo->init(false);
317
318 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');
319
320 $expectedSQL = sprintf(
321 ' AND (%s = 0) AND ((%s = 0) OR (%s = 2))',
322 $connection->quoteIdentifier('pages.deleted'),
323 $connection->quoteIdentifier('pages.t3ver_wsid'),
324 $connection->quoteIdentifier('pages.t3ver_wsid')
325 );
326
327 $this->assertSame($expectedSQL, $this->pageRepo->where_hid_del);
328 }
329
330 /**
331 * @test
332 */
333 public function initSetsPublicPropertyCorrectlyForLive()
334 {
335 $GLOBALS['SIM_ACCESS_TIME'] = 123;
336
337 $this->pageRepo->versioningPreview = false;
338 $this->pageRepo->versioningWorkspaceId = 0;
339 $this->pageRepo->init(false);
340
341 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');
342 $expectedSQL = sprintf(
343 ' AND (%s = 0) AND (%s <= 0) AND (%s = 0) AND (%s <= 123) AND ((%s = 0) OR (%s > 123))',
344 $connection->quoteIdentifier('pages.deleted'),
345 $connection->quoteIdentifier('pages.t3ver_state'),
346 $connection->quoteIdentifier('pages.hidden'),
347 $connection->quoteIdentifier('pages.starttime'),
348 $connection->quoteIdentifier('pages.endtime'),
349 $connection->quoteIdentifier('pages.endtime')
350 );
351
352 $this->assertSame($expectedSQL, $this->pageRepo->where_hid_del);
353 }
354
355 ////////////////////////////////
356 // Tests concerning workspaces
357 ////////////////////////////////
358
359 /**
360 * @test
361 */
362 public function noPagesFromWorkspaceAreShownLive()
363 {
364 // initialization
365 $wsid = 987654321;
366
367 // simulate calls from \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->fetch_the_id()
368 $this->pageRepo->versioningPreview = false;
369 $this->pageRepo->versioningWorkspaceId = $wsid;
370 $this->pageRepo->init(false);
371
372 $this->assertSame([], $this->pageRepo->getPage(11));
373 }
374
375 /**
376 * @test
377 */
378 public function previewShowsPagesFromLiveAndCurrentWorkspace()
379 {
380 // initialization
381 $wsid = 987654321;
382
383 // simulate calls from \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->fetch_the_id()
384 $this->pageRepo->versioningPreview = true;
385 $this->pageRepo->versioningWorkspaceId = $wsid;
386 $this->pageRepo->init(false);
387
388 $pageRec = $this->pageRepo->getPage(11);
389
390 $this->assertSame(11, $pageRec['uid']);
391 $this->assertSame(11, $pageRec['t3ver_oid']);
392 $this->assertSame(987654321, $pageRec['t3ver_wsid']);
393 $this->assertSame(-1, $pageRec['t3ver_state']);
394 $this->assertSame('First draft version', $pageRec['t3ver_label']);
395 }
396
397 /**
398 * @test
399 */
400 public function getWorkspaceVersionReturnsTheCorrectMethod()
401 {
402 // initialization
403 $wsid = 987654321;
404
405 // simulate calls from \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->fetch_the_id()
406 $this->pageRepo->versioningPreview = true;
407 $this->pageRepo->versioningWorkspaceId = $wsid;
408 $this->pageRepo->init(false);
409
410 $pageRec = $this->pageRepo->getWorkspaceVersionOfRecord($wsid, 'pages', 11);
411
412 $this->assertSame(12, $pageRec['uid']);
413 $this->assertSame(11, $pageRec['t3ver_oid']);
414 $this->assertSame(987654321, $pageRec['t3ver_wsid']);
415 $this->assertSame(-1, $pageRec['t3ver_state']);
416 $this->assertSame('First draft version', $pageRec['t3ver_label']);
417 }
418
419 ////////////////////////////////
420 // Tests concerning versioning
421 ////////////////////////////////
422
423 /**
424 * @test
425 */
426 public function enableFieldsHidesVersionedRecordsAndPlaceholders()
427 {
428 $table = $this->getUniqueId('aTable');
429 $GLOBALS['TCA'][$table] = [
430 'ctrl' => [
431 'versioningWS' => true
432 ]
433 ];
434
435 $this->pageRepo->versioningPreview = false;
436 $this->pageRepo->init(false);
437
438 $conditions = $this->pageRepo->enableFields($table);
439 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
440
441 $this->assertThat(
442 $conditions,
443 $this->stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' <= 0)'),
444 'Versioning placeholders'
445 );
446 $this->assertThat(
447 $conditions,
448 $this->stringContains(' AND (' . $connection->quoteIdentifier($table . '.pid') . ' <> -1)'),
449 'Records from page -1'
450 );
451 }
452
453 /**
454 * @test
455 */
456 public function enableFieldsDoesNotHidePlaceholdersInPreview()
457 {
458 $table = $this->getUniqueId('aTable');
459 $GLOBALS['TCA'][$table] = [
460 'ctrl' => [
461 'versioningWS' => true
462 ]
463 ];
464
465 $this->pageRepo->versioningPreview = true;
466 $this->pageRepo->init(false);
467
468 $conditions = $this->pageRepo->enableFields($table);
469 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
470
471 $this->assertThat(
472 $conditions,
473 $this->logicalNot($this->stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' <= 0)')),
474 'No versioning placeholders'
475 );
476 $this->assertThat(
477 $conditions,
478 $this->stringContains(' AND (' . $connection->quoteIdentifier($table . '.pid') . ' <> -1)'),
479 'Records from page -1'
480 );
481 }
482
483 /**
484 * @test
485 */
486 public function enableFieldsDoesFilterToCurrentAndLiveWorkspaceForRecordsInPreview()
487 {
488 $table = $this->getUniqueId('aTable');
489 $GLOBALS['TCA'][$table] = [
490 'ctrl' => [
491 'versioningWS' => true
492 ]
493 ];
494
495 $this->pageRepo->versioningPreview = true;
496 $this->pageRepo->versioningWorkspaceId = 2;
497 $this->pageRepo->init(false);
498
499 $conditions = $this->pageRepo->enableFields($table);
500 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
501
502 $this->assertThat(
503 $conditions,
504 $this->stringContains(' AND ((' . $connection->quoteIdentifier($table . '.t3ver_wsid') . ' = 0) OR (' . $connection->quoteIdentifier($table . '.t3ver_wsid') . ' = 2))'),
505 'No versioning placeholders'
506 );
507 }
508
509 /**
510 * @test
511 */
512 public function enableFieldsDoesNotHideVersionedRecordsWhenCheckingVersionOverlays()
513 {
514 $table = $this->getUniqueId('aTable');
515 $GLOBALS['TCA'][$table] = [
516 'ctrl' => [
517 'versioningWS' => true
518 ]
519 ];
520
521 $this->pageRepo->versioningPreview = true;
522 $this->pageRepo->init(false);
523
524 $conditions = $this->pageRepo->enableFields($table, -1, [], true);
525 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
526
527 $this->assertThat(
528 $conditions,
529 $this->logicalNot($this->stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_state') . ' <= 0)')),
530 'No versioning placeholders'
531 );
532 $this->assertThat(
533 $conditions,
534 $this->logicalNot($this->stringContains(' AND (' . $connection->quoteIdentifier($table . '.pid') . ' <> -1)')),
535 'No necords from page -1'
536 );
537 }
538
539 protected function assertOverlayRow($row)
540 {
541 $this->assertInternalType('array', $row);
542
543 $this->assertArrayHasKey('_PAGES_OVERLAY', $row);
544 $this->assertArrayHasKey('_PAGES_OVERLAY_UID', $row);
545 $this->assertArrayHasKey('_PAGES_OVERLAY_LANGUAGE', $row);
546
547 $this->assertTrue($row['_PAGES_OVERLAY']);
548 }
549
550 protected function assertNotOverlayRow($row)
551 {
552 $this->assertInternalType('array', $row);
553
554 $this->assertFalse(isset($row['_PAGES_OVERLAY']));
555 $this->assertFalse(isset($row['_PAGES_OVERLAY_UID']));
556 $this->assertFalse(isset($row['_PAGES_OVERLAY_LANGUAGE']));
557 }
558 }