[TASK] Create own response instance in controller actions
[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\Backend\Utility\BackendUtility;
22 use TYPO3\CMS\Core\DataHandling\DataHandler;
23 use TYPO3\CMS\Core\Http\HtmlResponse;
24 use TYPO3\CMS\Core\Http\JsonResponse;
25 use TYPO3\CMS\Core\Imaging\Icon;
26 use TYPO3\CMS\Core\Imaging\IconFactory;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28 use TYPO3\CMS\Core\Versioning\VersionState;
29
30 /**
31 * LocalizationController handles the AJAX requests for record localization
32 */
33 class LocalizationController
34 {
35 /**
36 * @var string
37 */
38 const ACTION_COPY = 'copyFromLanguage';
39
40 /**
41 * @var string
42 */
43 const ACTION_LOCALIZE = 'localize';
44
45 /**
46 * @var IconFactory
47 */
48 protected $iconFactory;
49
50 /**
51 * @var LocalizationRepository
52 */
53 protected $localizationRepository;
54
55 /**
56 * Constructor
57 */
58 public function __construct()
59 {
60 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
61 $this->localizationRepository = GeneralUtility::makeInstance(LocalizationRepository::class);
62 }
63
64 /**
65 * Get used languages in a colPos of a page
66 *
67 * @param ServerRequestInterface $request
68 * @return ResponseInterface
69 */
70 public function getUsedLanguagesInPageAndColumn(ServerRequestInterface $request): ResponseInterface
71 {
72 $params = $request->getQueryParams();
73 if (!isset($params['pageId'], $params['colPos'], $params['languageId'])) {
74 return new HtmlResponse('', 400);
75 }
76
77 $pageId = (int)$params['pageId'];
78 $colPos = (int)$params['colPos'];
79 $languageId = (int)$params['languageId'];
80
81 /** @var TranslationConfigurationProvider $translationProvider */
82 $translationProvider = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
83 $systemLanguages = $translationProvider->getSystemLanguages($pageId);
84
85 $availableLanguages = [];
86
87 // First check whether column has localized records
88 $elementsInColumnCount = $this->localizationRepository->getLocalizedRecordCount($pageId, $colPos, $languageId);
89
90 if ($elementsInColumnCount === 0) {
91 $fetchedAvailableLanguages = $this->localizationRepository->fetchAvailableLanguages($pageId, $colPos, $languageId);
92 $availableLanguages[] = $systemLanguages[0];
93
94 foreach ($fetchedAvailableLanguages as $language) {
95 if (isset($systemLanguages[$language['uid']])) {
96 $availableLanguages[] = $systemLanguages[$language['uid']];
97 }
98 }
99 } else {
100 $result = $this->localizationRepository->fetchOriginLanguage($pageId, $colPos, $languageId);
101 $availableLanguages[] = $systemLanguages[$result['sys_language_uid']];
102 }
103
104 // Pre-render all flag icons
105 foreach ($availableLanguages as &$language) {
106 if ($language['flagIcon'] === 'empty-empty') {
107 $language['flagIcon'] = '';
108 } else {
109 $language['flagIcon'] = $this->iconFactory->getIcon($language['flagIcon'], Icon::SIZE_SMALL)->render();
110 }
111 }
112
113 return (new JsonResponse())->setPayload($availableLanguages);
114 }
115
116 /**
117 * Get a prepared summary of records being translated
118 *
119 * @param ServerRequestInterface $request
120 * @return ResponseInterface
121 */
122 public function getRecordLocalizeSummary(ServerRequestInterface $request): ResponseInterface
123 {
124 $params = $request->getQueryParams();
125 if (!isset($params['pageId'], $params['colPos'], $params['destLanguageId'], $params['languageId'])) {
126 return new HtmlResponse('', 400);
127 }
128
129 $records = [];
130 $result = $this->localizationRepository->getRecordsToCopyDatabaseResult(
131 $params['pageId'],
132 $params['colPos'],
133 $params['destLanguageId'],
134 $params['languageId'],
135 '*'
136 );
137
138 while ($row = $result->fetch()) {
139 BackendUtility::workspaceOL('tt_content', $row, -99, true);
140 if (!$row || VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
141 continue;
142 }
143 $records[] = [
144 'icon' => $this->iconFactory->getIconForRecord('tt_content', $row, Icon::SIZE_SMALL)->render(),
145 'title' => $row[$GLOBALS['TCA']['tt_content']['ctrl']['label']],
146 'uid' => $row['uid']
147 ];
148 }
149
150 return (new JsonResponse())->setPayload($records);
151 }
152
153 /**
154 * @param ServerRequestInterface $request
155 * @return ResponseInterface
156 */
157 public function localizeRecords(ServerRequestInterface $request): ResponseInterface
158 {
159 $params = $request->getQueryParams();
160 if (!isset($params['pageId'], $params['srcLanguageId'], $params['destLanguageId'], $params['action'], $params['uidList'])) {
161 return new HtmlResponse('', 400);
162 }
163
164 if ($params['action'] !== static::ACTION_COPY && $params['action'] !== static::ACTION_LOCALIZE) {
165 return new HtmlResponse('Invalid action "' . $params['action'] . '" called.', 400);
166 }
167
168 // Filter transmitted but invalid uids
169 $params['uidList'] = $this->filterInvalidUids(
170 (int)$params['pageId'],
171 (int)$params['colPos'],
172 (int)$params['destLanguageId'],
173 (int)$params['srcLanguageId'],
174 $params['uidList']
175 );
176
177 $this->process($params);
178
179 return (new JsonResponse())->setPayload([]);
180 }
181
182 /**
183 * Gets all possible UIDs of a page, colPos and language that might be processed and removes invalid UIDs that might
184 * be smuggled in.
185 *
186 * @param int $pageId
187 * @param int $colPos
188 * @param int $destLanguageId
189 * @param int $srcLanguageId
190 * @param array $transmittedUidList
191 * @return array
192 */
193 protected function filterInvalidUids(
194 int $pageId,
195 int $colPos,
196 int $destLanguageId,
197 int $srcLanguageId,
198 array $transmittedUidList
199 ): array {
200 // Get all valid uids that can be processed
201 $validUidList = $result = $this->localizationRepository->getRecordsToCopyDatabaseResult(
202 $pageId,
203 $colPos,
204 $destLanguageId,
205 $srcLanguageId,
206 'uid'
207 );
208
209 return array_intersect(array_unique($transmittedUidList), array_column($validUidList->fetchAll(), 'uid'));
210 }
211
212 /**
213 * Processes the localization actions
214 *
215 * @param array $params
216 */
217 protected function process($params)
218 {
219 $destLanguageId = (int)$params['destLanguageId'];
220
221 // Build command map
222 $cmd = [
223 'tt_content' => []
224 ];
225
226 if (isset($params['uidList']) && is_array($params['uidList'])) {
227 foreach ($params['uidList'] as $currentUid) {
228 if ($params['action'] === static::ACTION_LOCALIZE) {
229 $cmd['tt_content'][$currentUid] = [
230 'localize' => $destLanguageId
231 ];
232 } else {
233 $cmd['tt_content'][$currentUid] = [
234 'copyToLanguage' => $destLanguageId,
235 ];
236 }
237 }
238 }
239
240 $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
241 $dataHandler->start([], $cmd);
242 $dataHandler->process_cmdmap();
243 }
244 }