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