[TASK] Add a function for clearing the rootline caches
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Utility / RootlineUtilityTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Utility;
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 TYPO3\CMS\Core\Utility\RootlineUtility;
18
19 /**
20 * Testcase for class \TYPO3\CMS\Core\Utility\RootlineUtility
21 *
22 * @author Steffen Ritter <steffen.ritter@typo3.org>
23 */
24 class RootlineUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
25
26 /**
27 * @var RootlineUtility|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject
28 */
29 protected $fixture;
30
31 /**
32 * @var \TYPO3\CMS\Frontend\Page\PageRepository|\PHPUnit_Framework_MockObject_MockObject
33 */
34 protected $pageContextMock;
35
36 protected function setUp() {
37 $this->pageContextMock = $this->getMock('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
38 $this->fixture = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Utility\\RootlineUtility', array('enrichWithRelationFields'), array(1, '', $this->pageContextMock));
39 }
40
41 protected function tearDown() {
42 parent::tearDown();
43 RootlineUtility::purgeCaches();
44 }
45
46 /***
47 *
48 * UTILITY FUNCTIONS
49 *
50 */
51 /**
52 * Tests that $subsetCandidate is completely part of $superset
53 * and keys match.
54 *
55 * @see (A ^ B) = A <=> A c B
56 * @param array $subsetCandidate
57 * @param array $superset
58 */
59 protected function assertIsSubset(array $subsetCandidate, array $superset) {
60 $this->assertSame($subsetCandidate, array_intersect_assoc($subsetCandidate, $superset));
61 }
62
63 /***
64 *
65 * >TEST CASES
66 *
67 */
68 /**
69 * @test
70 */
71 public function isMountedPageWithoutMountPointsReturnsFalse() {
72 $this->fixture->__construct(1);
73 $this->assertFalse($this->fixture->isMountedPage());
74 }
75
76 /**
77 * @test
78 */
79 public function isMountedPageWithMatchingMountPointParameterReturnsTrue() {
80 $this->fixture->__construct(1, '1-99');
81 $this->assertTrue($this->fixture->isMountedPage());
82 }
83
84 /**
85 * @test
86 */
87 public function isMountedPageWithNonMatchingMountPointParameterReturnsFalse() {
88 $this->fixture->__construct(1, '99-99');
89 $this->assertFalse($this->fixture->isMountedPage());
90 }
91
92 /**
93 * @test
94 * @expectedException \RuntimeException
95 */
96 public function processMountedPageWithNonMountedPageThrowsException() {
97 $this->fixture->__construct(1, '1-99');
98 $this->fixture->_call('processMountedPage', array('uid' => 1), array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_DEFAULT));
99 }
100
101 /**
102 * @test
103 */
104 public function processMountedPageWithMountedPageNotThrowsException() {
105 $this->fixture->__construct(1, '1-99');
106 $this->assertNotEmpty($this->fixture->_call('processMountedPage', array('uid' => 1), array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1)));
107 }
108
109 /**
110 * @test
111 */
112 public function processMountedPageWithMountedPageAddsMountedFromParameter() {
113 $this->fixture->__construct(1, '1-99');
114 $result = $this->fixture->_call('processMountedPage', array('uid' => 1), array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1));
115 $this->assertTrue(isset($result['_MOUNTED_FROM']));
116 $this->assertSame(1, $result['_MOUNTED_FROM']);
117 }
118
119 /**
120 * @test
121 */
122 public function processMountedPageWithMountedPageAddsMountPointParameterToReturnValue() {
123 $this->fixture->__construct(1, '1-99');
124 $result = $this->fixture->_call('processMountedPage', array('uid' => 1), array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1));
125 $this->assertTrue(isset($result['_MP_PARAM']));
126 $this->assertSame('1-99', $result['_MP_PARAM']);
127 }
128
129 /**
130 * @test
131 */
132 public function processMountedPageForMountPageIsOverlayAddsMountOLParameter() {
133 $this->fixture->__construct(1, '1-99');
134 $result = $this->fixture->_call('processMountedPage', array('uid' => 1), array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1));
135 $this->assertTrue(isset($result['_MOUNT_OL']));
136 $this->assertSame(TRUE, $result['_MOUNT_OL']);
137 }
138
139 /**
140 * @test
141 */
142 public function processMountedPageForMountPageIsOverlayAddsDataInformationAboutMountPage() {
143 $this->fixture->__construct(1, '1-99');
144 $result = $this->fixture->_call('processMountedPage', array('uid' => 1), array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 1, 'pid' => 5, 'title' => 'TestCase'));
145 $this->assertTrue(isset($result['_MOUNT_PAGE']));
146 $this->assertSame(array('uid' => 99, 'pid' => 5, 'title' => 'TestCase'), $result['_MOUNT_PAGE']);
147 }
148
149 /**
150 * @test
151 */
152 public function processMountedPageForMountPageWithoutOverlayReplacesMountedPageWithMountPage() {
153 $mountPointPageData = array('uid' => 99, 'doktype' => \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_MOUNTPOINT, 'mount_pid' => 1, 'mount_pid_ol' => 0);
154 $this->fixture->__construct(1, '1-99');
155 $result = $this->fixture->_call('processMountedPage', array('uid' => 1), $mountPointPageData);
156 $this->assertIsSubset($mountPointPageData, $result);
157 }
158
159 /**
160 * @test
161 */
162 public function columnHasRelationToResolveDetectsGroupFieldAsLocal() {
163 $this->assertFalse($this->fixture->_call('columnHasRelationToResolve', array(
164 'type' => 'group'
165 )));
166 }
167
168 /**
169 * @test
170 */
171 public function columnHasRelationToResolveDetectsGroupFieldWithMMAsRemote2() {
172 $this->assertTrue($this->fixture->_call('columnHasRelationToResolve', array(
173 'config' => array(
174 'type' => 'group',
175 'MM' => 'tx_xyz'
176 )
177 )));
178 }
179
180 /**
181 * @test
182 */
183 public function columnHasRelationToResolveDetectsInlineFieldAsLocal() {
184 $this->assertFalse($this->fixture->_call('columnHasRelationToResolve', array(
185 'config' => array(
186 'type' => 'inline'
187 )
188 )));
189 }
190
191 /**
192 * @test
193 */
194 public function columnHasRelationToResolveDetectsInlineFieldWithForeignKeyAsRemote() {
195 $this->assertTrue($this->fixture->_call('columnHasRelationToResolve', array(
196 'config' => array(
197 'type' => 'inline',
198 'foreign_field' => 'xyz'
199 )
200 )));
201 }
202
203 /**
204 * @test
205 */
206 public function columnHasRelationToResolveDetectsInlineFieldWithFMMAsRemote() {
207 $this->assertTrue($this->fixture->_call('columnHasRelationToResolve', array(
208 'config' => array(
209 'type' => 'inline',
210 'MM' => 'xyz'
211 )
212 )));
213 }
214
215 /**
216 * @test
217 */
218 public function columnHasRelationToResolveDetectsSelectFieldAsLocal() {
219 $this->assertFalse($this->fixture->_call('columnHasRelationToResolve', array(
220 'config' => array(
221 'type' => 'select'
222 )
223 )));
224 }
225
226 /**
227 * @test
228 */
229 public function columnHasRelationToResolveDetectsSelectFieldWithMMAsRemote() {
230 $this->assertTrue($this->fixture->_call('columnHasRelationToResolve', array(
231 'config' => array(
232 'type' => 'select',
233 'MM' => 'xyz'
234 )
235 )));
236 }
237
238 /**
239 * @test
240 */
241 public function getCacheIdentifierContainsAllContextParameters() {
242 $this->pageContextMock->sys_language_uid = 8;
243 $this->pageContextMock->versioningWorkspaceId = 15;
244 $this->pageContextMock->versioningPreview = TRUE;
245 $this->fixture->__construct(42, '47-11', $this->pageContextMock);
246 $this->assertSame('42_47-11_8_15_1', $this->fixture->getCacheIdentifier());
247 $this->pageContextMock->versioningPreview = FALSE;
248 $this->fixture->__construct(42, '47-11', $this->pageContextMock);
249 $this->assertSame('42_47-11_8_15_0', $this->fixture->getCacheIdentifier());
250 $this->pageContextMock->versioningWorkspaceId = 0;
251 $this->fixture->__construct(42, '47-11', $this->pageContextMock);
252 $this->assertSame('42_47-11_8_0_0', $this->fixture->getCacheIdentifier());
253 }
254
255 /**
256 * @test
257 */
258 public function getCacheIdentifierReturnsValidIdentifierWithCommasInMountPointParameter() {
259 /** @var \TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend $cacheFrontendMock */
260 $cacheFrontendMock = $this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Cache\\Frontend\\AbstractFrontend', array(), '', FALSE);
261 $this->pageContextMock->sys_language_uid = 8;
262 $this->pageContextMock->versioningWorkspaceId = 15;
263 $this->pageContextMock->versioningPreview = TRUE;
264 $this->fixture->__construct(42, '47-11,48-12', $this->pageContextMock);
265 $this->assertTrue($cacheFrontendMock->isValidEntryIdentifier($this->fixture->getCacheIdentifier()));
266 }
267
268 /**
269 * @test
270 */
271 public function getRecordArrayFetchesTranslationWhenLanguageIdIsSet() {
272 $pageData = array(
273 'uid' => 1,
274 'title' => 'Original',
275 );
276 $pageDataTranslated = array(
277 'uid' => 1,
278 'title' => 'Translated',
279 '_PAGES_OVERLAY_UID' => '2',
280 );
281
282 $this->fixture
283 ->expects($this->any())
284 ->method('enrichWithRelationFields')
285 ->with(2, $pageDataTranslated)
286 ->will($this->returnArgument(1));
287
288 $databaseConnectionMock = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection');
289 $databaseConnectionMock
290 ->expects($this->once())
291 ->method('exec_SELECTgetSingleRow')
292 ->will(
293 $this->returnValue($pageData)
294 );
295 $this->fixture->_set('databaseConnection',
296 $databaseConnectionMock
297 );
298
299 $this->pageContextMock
300 ->expects($this->any())
301 ->method('getPageOverlay')
302 ->will($this->returnValue($pageDataTranslated));
303
304 $this->fixture->_set('languageUid', 1);
305 $this->assertSame($pageDataTranslated, $this->fixture->_call('getRecordArray', 1));
306 }
307
308 /**
309 * @test
310 */
311 public function enrichWithRelationFieldsCreatesWhereClauseForDisabledField() {
312 $mockDatabaseConnection = $this->getMock('\TYPO3\CMS\Core\Database\DatabaseConnection', array('exec_SELECTgetRows'), array(), '', FALSE);
313 $subject = $this->getAccessibleMock('\TYPO3\CMS\Core\Utility\RootlineUtility', array('columnHasRelationToResolve'), array(1, '', $this->pageContextMock));
314 $subject->_set('databaseConnection', $mockDatabaseConnection);
315 $GLOBALS['TYPO3_CONF_VARS']['FE']['pageOverlayFields'] = '';
316 $foreign_table = uniqid('foreign_table');
317 $foreign_field = uniqid('foreign_field');
318 $GLOBALS['TCA'][$foreign_table]['ctrl']['enablecolumns']['disabled'] = uniqid('disabled');
319 $GLOBALS['TCA']['pages']['columns'] = array(
320 'test' => array(
321 'config' => array(
322 'foreign_table' => $foreign_table,
323 'foreign_field' => $foreign_field
324 )
325 )
326 );
327 $expected = array(
328 $foreign_field . ' = 0',
329 $foreign_table . '.' . $GLOBALS['TCA'][$foreign_table]['ctrl']['enablecolumns']['disabled'] . ' = 0'
330 );
331 $this->pageContextMock->expects($this->once())->method('deleteClause')->will($this->returnValue(''));
332 $mockDatabaseConnection->expects(
333 $this->once())->
334 method('exec_SELECTgetRows')->
335 with('uid', $foreign_table, implode(' AND ', $expected), '', '', '', '')->
336 // the return value does not matter much, it is only here to prevent error messages from further code execution
337 will($this->returnValue(array('uid' => 17))
338 );
339 $subject->expects($this->once())->method('columnHasRelationToResolve')->will($this->returnValue(TRUE));
340 $subject->_call('enrichWithRelationFields', 17, array());
341 }
342 }