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