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