[!!!][TASK] Drop "documentation" extension
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Utility / RootlineUtilityTest.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Core\Tests\Unit\Utility;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use TYPO3\CMS\Core\Cache\CacheManager;
20 use TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend;
21 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23 use TYPO3\CMS\Core\Utility\RootlineUtility;
24 use TYPO3\CMS\Frontend\Page\PageRepository;
25 use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
26 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
27
28 /**
29 * Test case
30 */
31 class RootlineUtilityTest extends UnitTestCase
32 {
33 /**
34 * @var RootlineUtility|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject
35 */
36 protected $subject;
37
38 /**
39 * @var PageRepository|\PHPUnit_Framework_MockObject_MockObject
40 */
41 protected $pageContextMock;
42
43 /**
44 * @throws \ReflectionException
45 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
46 */
47 protected function setUp(): void
48 {
49 $cacheManagerProphecy = $this->prophesize(CacheManager::class);
50 GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
51 $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
52 $cacheManagerProphecy->getCache('cache_rootline')->willReturn($cacheFrontendProphecy->reveal());
53
54 $this->pageContextMock = $this->createMock(PageRepository::class);
55 $this->subject = $this->getAccessibleMock(
56 RootlineUtility::class,
57 ['enrichWithRelationFields'],
58 [1, '', $this->pageContextMock]
59 );
60 }
61
62 /**
63 *
64 */
65 protected function tearDown(): void
66 {
67 RootlineUtility::purgeCaches();
68 GeneralUtility::purgeInstances();
69 parent::tearDown();
70 }
71
72 /**
73 * Tests that $subsetCandidate is completely part of $superset
74 * and keys match.
75 *
76 * @see (A ^ B) = A <=> A c B
77 * @param array $subsetCandidate
78 * @param array $superset
79 */
80 protected function assertIsSubset(array $subsetCandidate, array $superset): void
81 {
82 $this->assertSame($subsetCandidate, array_intersect_assoc($subsetCandidate, $superset));
83 }
84
85 /**
86 * @test
87 */
88 public function isMountedPageWithoutMountPointsReturnsFalse(): void
89 {
90 $this->subject->__construct(1);
91 $this->assertFalse($this->subject->isMountedPage());
92 }
93
94 /**
95 * @test
96 */
97 public function isMountedPageWithMatchingMountPointParameterReturnsTrue(): void
98 {
99 $this->subject->__construct(1, '1-99');
100 $this->assertTrue($this->subject->isMountedPage());
101 }
102
103 /**
104 * @test
105 */
106 public function isMountedPageWithNonMatchingMountPointParameterReturnsFalse(): void
107 {
108 $this->subject->__construct(1, '99-99');
109 $this->assertFalse($this->subject->isMountedPage());
110 }
111
112 /**
113 * @test
114 */
115 public function processMountedPageWithNonMountedPageThrowsException(): void
116 {
117 $this->expectException(\RuntimeException::class);
118 $this->expectExceptionCode(1343464100);
119
120 $this->subject->__construct(1, '1-99');
121 $this->subject->_call(
122 'processMountedPage',
123 ['uid' => 1],
124 ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_DEFAULT]
125 );
126 }
127
128 /**
129 * @test
130 */
131 public function processMountedPageWithMountedPageNotThrowsException(): void
132 {
133 $this->subject->__construct(1, '1-99');
134 $this->assertNotEmpty($this->subject->_call(
135 'processMountedPage',
136 ['uid' => 1],
137 ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
138 ));
139 }
140
141 /**
142 * @test
143 */
144 public function processMountedPageWithMountedPageAddsMountedFromParameter(): void
145 {
146 $this->subject->__construct(1, '1-99');
147 $result = $this->subject->_call(
148 'processMountedPage',
149 ['uid' => 1],
150 ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
151 );
152 $this->assertTrue(isset($result['_MOUNTED_FROM']));
153 $this->assertSame(1, $result['_MOUNTED_FROM']);
154 }
155
156 /**
157 * @test
158 */
159 public function processMountedPageWithMountedPageAddsMountPointParameterToReturnValue(): void
160 {
161 $this->subject->__construct(1, '1-99');
162 $result = $this->subject->_call(
163 'processMountedPage',
164 ['uid' => 1],
165 ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1]
166 );
167 $this->assertTrue(isset($result['_MP_PARAM']));
168 $this->assertSame('1-99', $result['_MP_PARAM']);
169 }
170
171 /**
172 * @test
173 */
174 public function processMountedPageForMountPageIsOverlayAddsMountOLParameter(): void
175 {
176 $this->subject->__construct(1, '1-99');
177 $result = $this->subject->_call(
178 'processMountedPage',
179 ['uid' => 1],
180 ['uid' => 99, 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1]
181 );
182 $this->assertTrue(isset($result['_MOUNT_OL']));
183 $this->assertSame(true, $result['_MOUNT_OL']);
184 }
185
186 /**
187 * @test
188 */
189 public function processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage(): void
190 {
191 $this->subject->__construct(1, '1-99');
192 $result = $this->subject->_call('processMountedPage', ['uid' => 1], [
193 'uid' => 99,
194 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT,
195 'mount_pid' => 1,
196 'mount_pid_ol' => 1,
197 'pid' => 5,
198 'title' => 'TestCase'
199 ]);
200 $this->assertTrue(isset($result['_MOUNT_PAGE']));
201 $this->assertSame(['uid' => 99, 'pid' => 5, 'title' => 'TestCase'], $result['_MOUNT_PAGE']);
202 }
203
204 /**
205 * @test
206 */
207 public function processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage(): void
208 {
209 $mountPointPageData = [
210 'uid' => 99,
211 'doktype' => PageRepository::DOKTYPE_MOUNTPOINT,
212 'mount_pid' => 1,
213 'mount_pid_ol' => 0
214 ];
215 $this->subject->__construct(1, '1-99');
216 $result = $this->subject->_call('processMountedPage', ['uid' => 1], $mountPointPageData);
217 $this->assertIsSubset($mountPointPageData, $result);
218 }
219
220 /**
221 * @test
222 */
223 public function columnHasRelationToResolveDetectsGroupFieldAsLocal(): void
224 {
225 $this->assertFalse($this->subject->_call('columnHasRelationToResolve', [
226 'type' => 'group'
227 ]));
228 }
229
230 /**
231 * @test
232 */
233 public function columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote2(): void
234 {
235 $this->assertTrue($this->subject->_call('columnHasRelationToResolve', [
236 'config' => [
237 'type' => 'group',
238 'MM' => 'tx_xyz'
239 ]
240 ]));
241 }
242
243 /**
244 * @test
245 */
246 public function columnHasRelationToResolveDetectsInlineFieldAsLocal(): void
247 {
248 $this->assertFalse($this->subject->_call('columnHasRelationToResolve', [
249 'config' => [
250 'type' => 'inline'
251 ]
252 ]));
253 }
254
255 /**
256 * @test
257 */
258 public function columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote(): void
259 {
260 $this->assertTrue($this->subject->_call('columnHasRelationToResolve', [
261 'config' => [
262 'type' => 'inline',
263 'foreign_field' => 'xyz'
264 ]
265 ]));
266 }
267
268 /**
269 * @test
270 */
271 public function columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote(): void
272 {
273 $this->assertTrue($this->subject->_call('columnHasRelationToResolve', [
274 'config' => [
275 'type' => 'inline',
276 'MM' => 'xyz'
277 ]
278 ]));
279 }
280
281 /**
282 * @test
283 */
284 public function columnHasRelationToResolveDetectsSelectFieldAsLocal(): void
285 {
286 $this->assertFalse($this->subject->_call('columnHasRelationToResolve', [
287 'config' => [
288 'type' => 'select'
289 ]
290 ]));
291 }
292
293 /**
294 * @test
295 */
296 public function columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote(): void
297 {
298 $this->assertTrue($this->subject->_call('columnHasRelationToResolve', [
299 'config' => [
300 'type' => 'select',
301 'MM' => 'xyz'
302 ]
303 ]));
304 }
305
306 /**
307 * @test
308 */
309 public function getCacheIdentifierContainsAllContextParameters(): void
310 {
311 $this->pageContextMock->sys_language_uid = 8;
312 $this->pageContextMock->versioningWorkspaceId = 15;
313 $this->subject->__construct(42, '47-11', $this->pageContextMock);
314 $this->assertSame('42_47-11_8_15', $this->subject->getCacheIdentifier());
315 $this->subject->__construct(42, '47-11', $this->pageContextMock);
316 $this->assertSame('42_47-11_8_15', $this->subject->getCacheIdentifier());
317 $this->pageContextMock->versioningWorkspaceId = 0;
318 $this->subject->__construct(42, '47-11', $this->pageContextMock);
319 $this->assertSame('42_47-11_8_0', $this->subject->getCacheIdentifier());
320 }
321
322 /**
323 * @test
324 * @throws \ReflectionException
325 */
326 public function getCacheIdentifierReturnsValidIdentifierWithCommasInMountPointParameter(): void
327 {
328 /** @var AbstractFrontend $cacheFrontendMock */
329 $cacheFrontendMock = $this->getMockForAbstractClass(
330 AbstractFrontend::class,
331 [],
332 '',
333 false
334 );
335 $this->pageContextMock->sys_language_uid = 8;
336 $this->pageContextMock->versioningWorkspaceId = 15;
337 $this->subject->__construct(42, '47-11,48-12', $this->pageContextMock);
338 $this->assertTrue($cacheFrontendMock->isValidEntryIdentifier($this->subject->getCacheIdentifier()));
339 }
340 }