‪TYPO3CMS  ‪main
LocalizationController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
27 use TYPO3\CMS\Backend\Utility\BackendUtility;
33 use TYPO3\CMS\Core\Imaging\IconSize;
36 
43 {
47  public const ‪ACTION_COPY = 'copyFromLanguage';
48 
52  public const ‪ACTION_LOCALIZE = 'localize';
53 
57  protected ‪$iconFactory;
58 
63 
67  protected ‪$eventDispatcher;
68 
72  public function ‪__construct()
73  {
74  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
75  $this->localizationRepository = GeneralUtility::makeInstance(LocalizationRepository::class);
76  $this->eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
77  }
78 
82  public function ‪getUsedLanguagesInPage(ServerRequestInterface $request): ResponseInterface
83  {
84  $params = $request->getQueryParams();
85  if (!isset($params['pageId'], $params['languageId'])) {
86  return new ‪JsonResponse(null, 400);
87  }
88 
89  $pageId = (int)$params['pageId'];
90  $languageId = (int)$params['languageId'];
91 
92  $translationProvider = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
93  $systemLanguages = $translationProvider->getSystemLanguages($pageId);
94 
95  $availableLanguages = [];
96 
97  // First check whether column has localized records
98  $elementsInColumnCount = $this->localizationRepository->getLocalizedRecordCount($pageId, $languageId);
99  $result = [];
100  if ($elementsInColumnCount !== 0) {
101  // check elements in column - empty if source records do not exist anymore
102  $result = $this->localizationRepository->fetchOriginLanguage($pageId, $languageId);
103  if ($result !== []) {
104  $availableLanguages[] = $systemLanguages[$result['sys_language_uid']];
105  }
106  }
107  if ($elementsInColumnCount === 0 || $result === []) {
108  $fetchedAvailableLanguages = $this->localizationRepository->fetchAvailableLanguages($pageId, $languageId);
109  foreach ($fetchedAvailableLanguages as $language) {
110  if (isset($systemLanguages[$language['sys_language_uid']])) {
111  $availableLanguages[] = $systemLanguages[$language['sys_language_uid']];
112  }
113  }
114  }
115  // Language "All" should not appear as a source of translations (see bug 92757) and keys should be sequential
116  $availableLanguages = array_values(
117  array_filter($availableLanguages, static function (array $languageRecord): bool {
118  return (int)$languageRecord['uid'] !== -1;
119  })
120  );
121 
122  // Pre-render all flag icons
123  foreach ($availableLanguages as &$language) {
124  if ($language['flagIcon'] === 'empty-empty') {
125  $language['flagIcon'] = '';
126  } else {
127  $language['flagIcon'] = $this->iconFactory->getIcon($language['flagIcon'], IconSize::SMALL)->render();
128  }
129  }
130 
131  return new JsonResponse($availableLanguages);
132  }
133 
137  public function ‪getRecordLocalizeSummary(ServerRequestInterface $request): ResponseInterface
138  {
139  $params = $request->getQueryParams();
140  if (!isset($params['pageId'], $params['destLanguageId'], $params['languageId'])) {
141  return new JsonResponse(null, 400);
142  }
143 
144  $pageId = (int)$params['pageId'];
145  $destLanguageId = (int)$params['destLanguageId'];
146  $languageId = (int)$params['languageId'];
147 
148  $records = [];
149  $result = $this->localizationRepository->getRecordsToCopyDatabaseResult(
150  $pageId,
151  $destLanguageId,
152  $languageId,
153  '*'
154  );
155 
156  $flatRecords = [];
157  while ($row = $result->fetchAssociative()) {
158  BackendUtility::workspaceOL('tt_content', $row, -99, true);
159  if (!$row || VersionState::tryFrom($row['t3ver_state'] ?? 0) === VersionState::DELETE_PLACEHOLDER) {
160  continue;
161  }
162  $colPos = $row['colPos'];
163  if (!isset($records[$colPos])) {
164  $records[$colPos] = [];
165  }
166  $records[$colPos][] = [
167  'icon' => $this->iconFactory->getIconForRecord('tt_content', $row, IconSize::SMALL)->render(),
168  'title' => $row[‪$GLOBALS['TCA']['tt_content']['ctrl']['label']],
169  'uid' => $row['uid'],
170  ];
171  $flatRecords[] = $row;
172  }
173 
174  $columns = $this->‪getPageColumns($pageId, $flatRecords, $params);
175  $event = new AfterRecordSummaryForLocalizationEvent($records, $columns);
176  $this->eventDispatcher->dispatch($event);
177 
178  return new JsonResponse([
179  'records' => $event->getRecords(),
180  'columns' => $event->getColumns(),
181  ]);
182  }
183 
184  public function ‪localizeRecords(ServerRequestInterface $request): ResponseInterface
185  {
186  $params = $request->getQueryParams();
187  if (!isset($params['pageId'], $params['srcLanguageId'], $params['destLanguageId'], $params['action'], $params['uidList'])) {
188  return new ‪JsonResponse(null, 400);
189  }
190 
191  if ($params['action'] !== static::ACTION_COPY && $params['action'] !== static::ACTION_LOCALIZE) {
192  $response = new ‪Response('php://temp', 400, ['Content-Type' => 'application/json; charset=utf-8']);
193  $response->getBody()->write('Invalid action "' . $params['action'] . '" called.');
194  return $response;
195  }
196 
197  // Filter transmitted but invalid uids
198  $params['uidList'] = $this->‪filterInvalidUids(
199  (int)$params['pageId'],
200  (int)$params['destLanguageId'],
201  (int)$params['srcLanguageId'],
202  $params['uidList']
203  );
204 
205  $this->‪process($params);
206 
207  return new JsonResponse([]);
208  }
209 
214  protected function ‪filterInvalidUids(
215  int $pageId,
216  int $destLanguageId,
217  int $srcLanguageId,
218  array $transmittedUidList
219  ): array {
220  // Get all valid uids that can be processed
221  $validUidList = $this->localizationRepository->getRecordsToCopyDatabaseResult(
222  $pageId,
223  $destLanguageId,
224  $srcLanguageId,
225  'uid'
226  );
227 
228  return array_intersect(array_unique($transmittedUidList), array_column($validUidList->fetchAllAssociative(), 'uid'));
229  }
230 
236  protected function ‪process($params): void
237  {
238  $destLanguageId = (int)$params['destLanguageId'];
239 
240  // Build command map
241  $cmd = [
242  'tt_content' => [],
243  ];
244 
245  if (isset($params['uidList']) && is_array($params['uidList'])) {
246  foreach ($params['uidList'] as $currentUid) {
247  if ($params['action'] === static::ACTION_LOCALIZE) {
248  $cmd['tt_content'][$currentUid] = [
249  'localize' => $destLanguageId,
250  ];
251  } else {
252  $cmd['tt_content'][$currentUid] = [
253  'copyToLanguage' => $destLanguageId,
254  ];
255  }
256  }
257  }
258 
259  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
260  $dataHandler->start([], $cmd);
261  $dataHandler->process_cmdmap();
262  }
263 
264  protected function ‪getPageColumns(int $pageId, array $flatRecords, array $params): array
265  {
266  $columns = [];
267  $backendLayoutView = GeneralUtility::makeInstance(BackendLayoutView::class);
268  $backendLayout = $backendLayoutView->getBackendLayoutForPage($pageId);
269 
270  foreach ($backendLayout->getUsedColumns() as $columnPos => $columnLabel) {
271  $columns[$columnPos] = ‪$GLOBALS['LANG']->sL($columnLabel);
272  }
273 
274  $event = new AfterPageColumnsSelectedForLocalizationEvent($columns, array_values($backendLayout->getColumnPositionNumbers()), $backendLayout, $flatRecords, $params);
275  $this->eventDispatcher->dispatch($event);
276 
277  return [
278  'columns' => $event->getColumns(),
279  'columnList' => $event->getColumnList(),
280  ];
281  }
282 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:94
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\localizeRecords
‪localizeRecords(ServerRequestInterface $request)
Definition: LocalizationController.php:181
‪TYPO3\CMS\Backend\Controller\Event\AfterRecordSummaryForLocalizationEvent
Definition: AfterRecordSummaryForLocalizationEvent.php:21
‪TYPO3\CMS\Backend\Controller\Event\AfterPageColumnsSelectedForLocalizationEvent
Definition: AfterPageColumnsSelectedForLocalizationEvent.php:30
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\__construct
‪__construct()
Definition: LocalizationController.php:69
‪TYPO3\CMS\Backend\Domain\Repository\Localization\LocalizationRepository
Definition: LocalizationRepository.php:36
‪TYPO3\CMS\Core\Versioning\VersionState
‪VersionState
Definition: VersionState.php:22
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\getRecordLocalizeSummary
‪getRecordLocalizeSummary(ServerRequestInterface $request)
Definition: LocalizationController.php:134
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\getPageColumns
‪getPageColumns(int $pageId, array $flatRecords, array $params)
Definition: LocalizationController.php:261
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Backend\Controller\Page
Definition: LocalizationController.php:18
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\$iconFactory
‪IconFactory $iconFactory
Definition: LocalizationController.php:56
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\getUsedLanguagesInPage
‪getUsedLanguagesInPage(ServerRequestInterface $request)
Definition: LocalizationController.php:79
‪TYPO3\CMS\Core\Http\Response
Definition: Response.php:32
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController
Definition: LocalizationController.php:43
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\ACTION_LOCALIZE
‪const ACTION_LOCALIZE
Definition: LocalizationController.php:52
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\filterInvalidUids
‪filterInvalidUids(int $pageId, int $destLanguageId, int $srcLanguageId, array $transmittedUidList)
Definition: LocalizationController.php:211
‪TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider
Definition: TranslationConfigurationProvider.php:39
‪TYPO3\CMS\Backend\View\BackendLayoutView
Definition: BackendLayoutView.php:38
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:28
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\ACTION_COPY
‪const ACTION_COPY
Definition: LocalizationController.php:47
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: LocalizationController.php:64
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\process
‪process($params)
Definition: LocalizationController.php:233
‪TYPO3\CMS\Backend\Controller\Page\LocalizationController\$localizationRepository
‪LocalizationRepository $localizationRepository
Definition: LocalizationController.php:60