[BUGFIX] Ensure correct sorting when using the localization wizard
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / Page / LocalizationController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider;
20 use TYPO3\CMS\Backend\Domain\Repository\Localization\LocalizationRepository;
21 use TYPO3\CMS\Core\DataHandling\DataHandler;
22 use TYPO3\CMS\Core\Imaging\Icon;
23 use TYPO3\CMS\Core\Imaging\IconFactory;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25
26 /**
27 * LocalizationController handles the AJAX requests for record localization
28 */
29 class LocalizationController
30 {
31 /**
32 * @const string
33 */
34 const ACTION_COPY = 'copyFromLanguage';
35
36 /**
37 * @const string
38 */
39 const ACTION_LOCALIZE = 'localize';
40
41 /**
42 * @var IconFactory
43 */
44 protected $iconFactory;
45
46 /**
47 * @var LocalizationRepository
48 */
49 protected $localizationRepository;
50
51 /**
52 * Constructor
53 */
54 public function __construct()
55 {
56 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
57 $this->localizationRepository = GeneralUtility::makeInstance(LocalizationRepository::class);
58 }
59
60 /**
61 * Get used languages in a colPos of a page
62 *
63 * @param ServerRequestInterface $request
64 * @param ResponseInterface $response
65 * @return ResponseInterface
66 */
67 public function getUsedLanguagesInPageAndColumn(ServerRequestInterface $request, ResponseInterface $response)
68 {
69 $params = $request->getQueryParams();
70 if (!isset($params['pageId'], $params['colPos'], $params['languageId'])) {
71 $response = $response->withStatus(500);
72 return $response;
73 }
74
75 $pageId = (int)$params['pageId'];
76 $colPos = (int)$params['colPos'];
77 $languageId = (int)$params['languageId'];
78
79 /** @var TranslationConfigurationProvider $translationProvider */
80 $translationProvider = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
81 $systemLanguages = $translationProvider->getSystemLanguages($pageId);
82
83 $availableLanguages = [];
84
85 // First check whether column has localized records
86 $elementsInColumnCount = $this->localizationRepository->getLocalizedRecordCount($pageId, $colPos, $languageId);
87
88 if ($elementsInColumnCount === 0) {
89 $fetchedAvailableLanguages = $this->localizationRepository->fetchAvailableLanguages($pageId, $colPos, $languageId);
90 $availableLanguages[] = $systemLanguages[0];
91
92 foreach ($fetchedAvailableLanguages as $language) {
93 if (isset($systemLanguages[$language['uid']])) {
94 $availableLanguages[] = $systemLanguages[$language['uid']];
95 }
96 }
97 } else {
98 $result = $this->localizationRepository->fetchOriginLanguage($pageId, $colPos, $languageId);
99 $availableLanguages[] = $systemLanguages[$result['sys_language_uid']];
100 }
101
102 // Pre-render all flag icons
103 foreach ($availableLanguages as &$language) {
104 if ($language['flagIcon'] === 'empty-empty') {
105 $language['flagIcon'] = '';
106 } else {
107 $language['flagIcon'] = $this->iconFactory->getIcon($language['flagIcon'], Icon::SIZE_SMALL)->render();
108 }
109 }
110
111 $response->getBody()->write(json_encode($availableLanguages));
112 return $response;
113 }
114
115 /**
116 * Get a prepared summary of records being translated
117 *
118 * @param ServerRequestInterface $request
119 * @param ResponseInterface $response
120 * @return ResponseInterface
121 */
122 public function getRecordLocalizeSummary(ServerRequestInterface $request, ResponseInterface $response)
123 {
124 $params = $request->getQueryParams();
125 if (!isset($params['pageId'], $params['colPos'], $params['destLanguageId'], $params['languageId'])) {
126 $response = $response->withStatus(500);
127 return $response;
128 }
129
130 $records = [];
131 $databaseConnection = $this->getDatabaseConnection();
132 $res = $this->localizationRepository->getRecordsToCopyDatabaseResult($params['pageId'], $params['colPos'], $params['destLanguageId'], $params['languageId'], '*');
133 while ($row = $databaseConnection->sql_fetch_assoc($res)) {
134 $records[] = [
135 'icon' => $this->iconFactory->getIconForRecord('tt_content', $row, Icon::SIZE_SMALL)->render(),
136 'title' => $row[$GLOBALS['TCA']['tt_content']['ctrl']['label']],
137 'uid' => $row['uid']
138 ];
139 }
140 $databaseConnection->sql_free_result($res);
141
142 $response->getBody()->write(json_encode($records));
143 return $response;
144 }
145
146 /**
147 * @param ServerRequestInterface $request
148 * @param ResponseInterface $response
149 * @return ResponseInterface
150 */
151 public function getRecordUidsToCopy(ServerRequestInterface $request, ResponseInterface $response)
152 {
153 $params = $request->getQueryParams();
154 if (!isset($params['pageId'], $params['colPos'], $params['languageId'])) {
155 $response = $response->withStatus(500);
156 return $response;
157 }
158
159 $pageId = (int)$params['pageId'];
160 $colPos = (int)$params['colPos'];
161 $languageId = (int)$params['languageId'];
162 $databaseConnection = $this->getDatabaseConnection();
163
164 $res = $this->localizationRepository->getRecordsToCopyDatabaseResult($pageId, $colPos, $languageId, 'uid');
165 $uids = [];
166 while ($row = $databaseConnection->sql_fetch_assoc($res)) {
167 $uids[] = (int)$row['uid'];
168 }
169 $databaseConnection->sql_free_result($res);
170
171 $response->getBody()->write(json_encode($uids));
172 return $response;
173 }
174
175 /**
176 * @param ServerRequestInterface $request
177 * @param ResponseInterface $response
178 * @return ResponseInterface
179 */
180 public function localizeRecords(ServerRequestInterface $request, ResponseInterface $response)
181 {
182 $params = $request->getQueryParams();
183 if (!isset($params['pageId'], $params['srcLanguageId'], $params['destLanguageId'], $params['action'], $params['uidList'])) {
184 $response = $response->withStatus(500);
185 return $response;
186 }
187
188 if ($params['action'] !== static::ACTION_COPY && $params['action'] !== static::ACTION_LOCALIZE) {
189 $response->getBody()->write('Invalid action "' . $params['action'] . '" called.');
190 $response = $response->withStatus(500);
191 return $response;
192 }
193
194 $pageId = (int)$params['pageId'];
195 $srcLanguageId = (int)$params['srcLanguageId'];
196 $destLanguageId = (int)$params['destLanguageId'];
197
198 // Build command map
199 $cmd = [
200 'tt_content' => []
201 ];
202
203 for ($i = 0, $count = count($params['uidList']); $i < $count; ++$i) {
204 $currentUid = $params['uidList'][$i];
205
206 if ($params['action'] === static::ACTION_LOCALIZE) {
207 if ($srcLanguageId === 0) {
208 $cmd['tt_content'][$currentUid] = [
209 'localize' => $destLanguageId
210 ];
211 } else {
212 $previousUid = $this->localizationRepository->getPreviousLocalizedRecordUid(
213 'tt_content',
214 $currentUid,
215 $pageId,
216 $srcLanguageId,
217 $destLanguageId
218 );
219 $cmd['tt_content'][$currentUid] = [
220 'copy' => [
221 'action' => 'paste',
222 'target' => -$previousUid,
223 'update' => [
224 'sys_language_uid' => $destLanguageId
225 ]
226 ]
227 ];
228 }
229 } else {
230 $previousUid = $this->localizationRepository->getPreviousLocalizedRecordUid(
231 'tt_content',
232 $currentUid,
233 $pageId,
234 $srcLanguageId,
235 $destLanguageId
236 );
237 $cmd['tt_content'][$currentUid] = [
238 'copy' => [
239 'action' => 'paste',
240 'target' => -$previousUid,
241 'update' => [
242 'sys_language_uid' => $destLanguageId,
243 'l18n_parent' => 0
244 ]
245 ]
246 ];
247 }
248 }
249
250 /** @var DataHandler $dataHandler */
251 $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
252 $dataHandler->start([], $cmd);
253 $dataHandler->process_cmdmap();
254
255 $response->getBody()->write(json_encode([]));
256 return $response;
257 }
258
259 /**
260 * Returns the database connection
261 *
262 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
263 */
264 protected function getDatabaseConnection()
265 {
266 return $GLOBALS['TYPO3_DB'];
267 }
268 }