[BUGFIX] Determine default language as origin correctly
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Functional / Controller / Page / LocalizationControllerTest.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Backend\Tests\Functional\Controller\Page;
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\Backend\Controller\Page\LocalizationController;
20 use TYPO3\CMS\Core\Core\Bootstrap;
21 use TYPO3\CMS\Core\DataHandling\DataHandler;
22 use TYPO3\CMS\Core\Http\ServerRequest;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService;
25
26 /**
27 * Test case for TYPO3\CMS\Backend\Controller\Page\LocalizationController
28 */
29 class LocalizationControllerTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
30 {
31 /**
32 * @var string
33 */
34 protected $assertionDataSetDirectory = 'typo3/sysext/backend/Tests/Functional/Controller/Page/Localization/CSV/DataSet/';
35
36 /**
37 * @var LocalizationController|\PHPUnit_Framework_MockObject_MockObject
38 */
39 protected $subject;
40
41 /**
42 * @var \TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService
43 */
44 protected $actionService;
45
46 /**
47 * @var \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
48 */
49 protected $backendUser;
50
51 /**
52 * @var array
53 */
54 protected $coreExtensionsToLoad = ['workspaces'];
55
56 /**
57 * Sets up this test case.
58 */
59 protected function setUp(): void
60 {
61 parent::setUp();
62
63 $this->backendUser = $this->setUpBackendUserFromFixture(1);
64 $this->backendUser->workspace = 0;
65
66 Bootstrap::initializeLanguageObject();
67 $this->actionService = GeneralUtility::makeInstance(ActionService::class);
68
69 $this->importDataSet(__DIR__ . '/Fixtures/pages.xml');
70 $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_language.xml');
71 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/backend/Tests/Functional/Controller/Page/Fixtures/tt_content-default-language.xml');
72
73 $this->subject = $this->getMockBuilder(LocalizationController::class)
74 ->setMethods(['getPageColumns'])
75 ->getMock();
76 }
77
78 /**
79 * @test
80 * see DataSet/TranslatedFromDefault.csv
81 */
82 public function recordsGetTranslatedFromDefaultLanguage(): void
83 {
84 $params = [
85 'pageId' => 1,
86 'srcLanguageId' => 0,
87 'destLanguageId' => 1,
88 'uidList' => [1, 2, 3],
89 'action' => LocalizationController::ACTION_LOCALIZE,
90 ];
91 $this->callInaccessibleMethod($this->subject, 'process', $params);
92 $this->assertAssertionDataSet('TranslatedFromDefault');
93 }
94
95 /**
96 * @test
97 */
98 public function recordsGetTranslatedFromDifferentTranslation(): void
99 {
100 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/backend/Tests/Functional/Controller/Page/Fixtures/tt_content-danish-language.xml');
101
102 $params = [
103 'pageId' => 1,
104 'srcLanguageId' => 1,
105 'destLanguageId' => 2,
106 'uidList' => [4, 5, 6], // uids of tt_content-danish-language
107 'action' => LocalizationController::ACTION_LOCALIZE,
108 ];
109 $this->callInaccessibleMethod($this->subject, 'process', $params);
110 $this->assertAssertionDataSet('TranslatedFromTranslation');
111 }
112
113 /**
114 * @test
115 */
116 public function recordsGetCopiedFromDefaultLanguage(): void
117 {
118 $params = [
119 'pageId' => 1,
120 'srcLanguageId' => 0,
121 'destLanguageId' => 2,
122 'uidList' => [1, 2, 3],
123 'action' => LocalizationController::ACTION_COPY,
124 ];
125 $this->callInaccessibleMethod($this->subject, 'process', $params);
126 $this->assertAssertionDataSet('CopiedFromDefault');
127 }
128
129 /**
130 * @test
131 */
132 public function recordsGetCopiedFromAnotherLanguage(): void
133 {
134 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/backend/Tests/Functional/Controller/Page/Fixtures/tt_content-danish-language.xml');
135
136 $params = [
137 'pageId' => 1,
138 'srcLanguageId' => 1,
139 'destLanguageId' => 2,
140 'uidList' => [4, 5, 6], // uids of tt_content-danish-language
141 'action' => LocalizationController::ACTION_COPY,
142 ];
143 $this->callInaccessibleMethod($this->subject, 'process', $params);
144 $this->assertAssertionDataSet('CopiedFromTranslation');
145 }
146
147 /**
148 * @test
149 */
150 public function copyingNewContentFromLanguageIntoExistingLocalizationHasSameOrdering(): void
151 {
152 $params = [
153 'pageId' => 1,
154 'srcLanguageId' => 0,
155 'destLanguageId' => 1,
156 'uidList' => [1, 2, 3],
157 'action' => LocalizationController::ACTION_COPY,
158 ];
159 $this->callInaccessibleMethod($this->subject, 'process', $params);
160
161 // Create another content element in default language
162 $data = [
163 'tt_content' => [
164 'NEW123456' => [
165 'sys_language_uid' => 0,
166 'header' => 'Test content 2.5',
167 'pid' => -2,
168 'colPos' => 0,
169 ],
170 ],
171 ];
172 $dataHandler = new DataHandler();
173 $dataHandler->start($data, []);
174 $dataHandler->process_datamap();
175 $dataHandler->process_cmdmap();
176 $newContentElementUid = $dataHandler->substNEWwithIDs['NEW123456'];
177
178 // Copy the new content element
179 $params = [
180 'pageId' => 1,
181 'srcLanguageId' => 0,
182 'destLanguageId' => 1,
183 'uidList' => [$newContentElementUid],
184 'action' => LocalizationController::ACTION_COPY,
185 ];
186 $this->callInaccessibleMethod($this->subject, 'process', $params);
187 $this->assertAssertionDataSet('CreatedElementOrdering');
188 }
189
190 /**
191 * @test
192 */
193 public function defaultLanguageIsFoundAsOriginLanguage(): void
194 {
195 $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/backend/Tests/Functional/Controller/Page/Fixtures/tt_content-danish-language.xml');
196
197 // Create another content element in default language
198 $data = [
199 'tt_content' => [
200 'NEW123456' => [
201 'sys_language_uid' => 0,
202 'header' => 'New content element',
203 'pid' => 1,
204 'colPos' => 0,
205 ],
206 ],
207 ];
208 $dataHandler = new DataHandler();
209 $dataHandler->start($data, []);
210 $dataHandler->process_datamap();
211 $dataHandler->process_cmdmap();
212
213 $request = (new ServerRequest())->withQueryParams([
214 'pageId' => 1, // page uid, the records are stored on
215 'languageId' => 1 // current language id
216 ]);
217
218 $usedLanguages = (string)$this->subject->getUsedLanguagesInPage($request)->getBody();
219 $this->assertThat($usedLanguages, $this->stringContains('"uid":0'));
220 }
221
222 /**
223 * @test
224 */
225 public function recordLocalizeSummaryRespectsWorkspaceEncapsulationForDeletedRecords(): void
226 {
227 // Delete record 2 within workspace 1
228 $this->backendUser->workspace = 1;
229 $this->actionService->deleteRecord('tt_content', 2);
230
231 $expectedRecords = [
232 '0' => [
233 ['uid' => 1],
234 ],
235 '1' => [
236 ['uid' => 3],
237 ],
238 ];
239
240 $localizeSummary = $this->getReducedRecordLocalizeSummary();
241
242 $this->assertEquals($expectedRecords, $localizeSummary);
243 }
244
245 /**
246 * @test
247 */
248 public function recordLocalizeSummaryRespectsWorkspaceEncapsulationForMovedRecords(): void
249 {
250 // Move record 2 to page 2 within workspace 1
251 $this->backendUser->workspace = 1;
252 $this->actionService->moveRecord('tt_content', 2, 2);
253
254 $expectedRecords = [
255 '0' => [
256 ['uid' => 1],
257 ],
258 '1' => [
259 ['uid' => 3],
260 ],
261 ];
262
263 $localizeSummary = $this->getReducedRecordLocalizeSummary();
264
265 $this->assertEquals($expectedRecords, $localizeSummary);
266 }
267
268 /**
269 * Get record localized summary list reduced to list of uids
270 *
271 * @return array
272 */
273 protected function getReducedRecordLocalizeSummary(): array
274 {
275 $request = (new ServerRequest())->withQueryParams([
276 'pageId' => 1, // page uid, the records are stored on
277 'destLanguageId' => 1, // destination language uid
278 'languageId' => 0 // source language uid
279 ]);
280
281 $this->subject->method('getPageColumns')->willReturn([
282 0 => 'Column 0',
283 1 => 'Column 1',
284 ]);
285
286 $recordLocalizeSummaryResponse = $this->subject->getRecordLocalizeSummary($request);
287
288 // Reduce the fetched record summary to list of uids
289 if ($recordLocalizeSummary = json_decode((string)$recordLocalizeSummaryResponse->getBody(), true)) {
290 foreach ($recordLocalizeSummary['records'] as $colPos => $records) {
291 foreach ($records as $key => $record) {
292 $recordLocalizeSummary['records'][$colPos][$key] = array_intersect_key($record, ['uid' => '']);
293 }
294 }
295 }
296
297 return $recordLocalizeSummary['records'];
298 }
299
300 /**
301 * @param string $dataSetName
302 */
303 protected function assertAssertionDataSet(string $dataSetName)
304 {
305 $fileName = rtrim($this->assertionDataSetDirectory, '/') . '/' . $dataSetName . '.csv';
306 $fileName = GeneralUtility::getFileAbsFileName($fileName);
307 $this->assertCSVDataSet($fileName);
308 }
309 }