[!!!][TASK] Remove deprecated output-related code from EXT:backend
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Domain / Repository / Localization / LocalizationRepository.php
1 <?php
2 namespace TYPO3\CMS\Backend\Domain\Repository\Localization;
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\Database\Connection;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
20 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
21 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23
24 /**
25 * Repository for record localizations
26 */
27 class LocalizationRepository
28 {
29 /**
30 * Fetch the language from which the records of a colPos in a certain language were initially localized
31 *
32 * @param int $pageId
33 * @param int $colPos
34 * @param int $localizedLanguage
35 * @return array|false
36 */
37 public function fetchOriginLanguage($pageId, $colPos, $localizedLanguage)
38 {
39 $queryBuilder = $this->getQueryBuilderWithWorkspaceRestriction('tt_content');
40
41 $constraints = [
42 $queryBuilder->expr()->eq(
43 'tt_content.colPos',
44 $queryBuilder->createNamedParameter($colPos, \PDO::PARAM_INT)
45 ),
46 $queryBuilder->expr()->eq(
47 'tt_content.pid',
48 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
49 ),
50 $queryBuilder->expr()->eq(
51 'tt_content.sys_language_uid',
52 $queryBuilder->createNamedParameter($localizedLanguage, \PDO::PARAM_INT)
53 ),
54 ];
55 $constraints += $this->getAllowedLanguageConstraintsForBackendUser();
56
57 $queryBuilder->select('tt_content_orig.sys_language_uid')
58 ->from('tt_content')
59 ->join(
60 'tt_content',
61 'tt_content',
62 'tt_content_orig',
63 $queryBuilder->expr()->eq(
64 'tt_content.l10n_source',
65 $queryBuilder->quoteIdentifier('tt_content_orig.uid')
66 )
67 )
68 ->join(
69 'tt_content_orig',
70 'sys_language',
71 'sys_language',
72 $queryBuilder->expr()->eq(
73 'tt_content_orig.sys_language_uid',
74 $queryBuilder->quoteIdentifier('sys_language.uid')
75 )
76 )
77 ->where(...$constraints)
78 ->groupBy('tt_content_orig.sys_language_uid');
79
80 return $queryBuilder->execute()->fetch();
81 }
82
83 /**
84 * Returns number of localized records in given page, colPos and language
85 * Records which were added to the language directly (not through translation) are not counted.
86 *
87 * @param int $pageId
88 * @param int $colPos
89 * @param int $languageId
90 * @return int
91 */
92 public function getLocalizedRecordCount($pageId, $colPos, $languageId)
93 {
94 $queryBuilder = $this->getQueryBuilderWithWorkspaceRestriction('tt_content');
95
96 $rowCount = $queryBuilder->count('uid')
97 ->from('tt_content')
98 ->where(
99 $queryBuilder->expr()->eq(
100 'tt_content.sys_language_uid',
101 $queryBuilder->createNamedParameter($languageId, \PDO::PARAM_INT)
102 ),
103 $queryBuilder->expr()->eq(
104 'tt_content.colPos',
105 $queryBuilder->createNamedParameter($colPos, \PDO::PARAM_INT)
106 ),
107 $queryBuilder->expr()->eq(
108 'tt_content.pid',
109 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
110 ),
111 $queryBuilder->expr()->neq(
112 'tt_content.l10n_source',
113 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
114 )
115 )
116 ->execute()
117 ->fetchColumn(0);
118
119 return (int)$rowCount;
120 }
121
122 /**
123 * Fetch all available languages
124 *
125 * @param int $pageId
126 * @param int $colPos
127 * @param int $languageId
128 * @return array
129 */
130 public function fetchAvailableLanguages($pageId, $colPos, $languageId)
131 {
132 $queryBuilder = $this->getQueryBuilderWithWorkspaceRestriction('tt_content');
133
134 $constraints = [
135 $queryBuilder->expr()->eq(
136 'tt_content.sys_language_uid',
137 $queryBuilder->quoteIdentifier('sys_language.uid')
138 ),
139 $queryBuilder->expr()->eq(
140 'tt_content.colPos',
141 $queryBuilder->createNamedParameter($colPos, \PDO::PARAM_INT)
142 ),
143 $queryBuilder->expr()->eq(
144 'tt_content.pid',
145 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
146 ),
147 $queryBuilder->expr()->neq(
148 'sys_language.uid',
149 $queryBuilder->createNamedParameter($languageId, \PDO::PARAM_INT)
150 )
151 ];
152 $constraints += $this->getAllowedLanguageConstraintsForBackendUser();
153
154 $queryBuilder->select('sys_language.uid')
155 ->from('tt_content')
156 ->from('sys_language')
157 ->where(...$constraints)
158 ->groupBy('sys_language.uid')
159 ->orderBy('sys_language.sorting');
160
161 $result = $queryBuilder->execute()->fetchAll();
162
163 return $result;
164 }
165
166 /**
167 * Builds additional query constraints to exclude hidden languages and
168 * limit a backend user to its allowed languages (unless the user is an admin)
169 *
170 * @return array
171 */
172 protected function getAllowedLanguageConstraintsForBackendUser(): array
173 {
174 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language');
175 $constraints = [];
176
177 $backendUser = $this->getBackendUser();
178 if (!$backendUser->isAdmin()) {
179 if (!empty($GLOBALS['TCA']['sys_language']['ctrl']['enablecolumns']['disabled'])) {
180 $constraints[] = $queryBuilder->expr()->eq(
181 'sys_language.' . $GLOBALS['TCA']['sys_language']['ctrl']['enablecolumns']['disabled'],
182 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
183 );
184 }
185
186 if (!empty($backendUser->user['allowed_languages'])) {
187 $constraints[] = $queryBuilder->expr()->in(
188 'sys_language.uid',
189 $queryBuilder->createNamedParameter(
190 GeneralUtility::intExplode(',', $backendUser->user['allowed_languages'], true),
191 Connection::PARAM_INT_ARRAY
192 )
193 );
194 }
195 }
196
197 return $constraints;
198 }
199
200 /**
201 * Get records for copy process
202 *
203 * @param int $pageId
204 * @param int $colPos
205 * @param int $destLanguageId
206 * @param int $languageId
207 * @param string $fields
208 * @return \Doctrine\DBAL\Driver\Statement
209 */
210 public function getRecordsToCopyDatabaseResult($pageId, $colPos, $destLanguageId, $languageId, $fields = '*')
211 {
212 $originalUids = [];
213
214 // Get original uid of existing elements triggered language / colpos
215 $queryBuilder = $this->getQueryBuilderWithWorkspaceRestriction('tt_content');
216
217 $originalUidsStatement = $queryBuilder
218 ->select('l10n_source')
219 ->from('tt_content')
220 ->where(
221 $queryBuilder->expr()->eq(
222 'sys_language_uid',
223 $queryBuilder->createNamedParameter($destLanguageId, \PDO::PARAM_INT)
224 ),
225 $queryBuilder->expr()->eq(
226 'tt_content.colPos',
227 $queryBuilder->createNamedParameter($colPos, \PDO::PARAM_INT)
228 ),
229 $queryBuilder->expr()->eq(
230 'tt_content.pid',
231 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
232 )
233 )
234 ->execute();
235
236 while ($origUid = $originalUidsStatement->fetchColumn(0)) {
237 $originalUids[] = (int)$origUid;
238 }
239
240 $queryBuilder->select(...GeneralUtility::trimExplode(',', $fields, true))
241 ->from('tt_content')
242 ->where(
243 $queryBuilder->expr()->eq(
244 'tt_content.sys_language_uid',
245 $queryBuilder->createNamedParameter($languageId, \PDO::PARAM_INT)
246 ),
247 $queryBuilder->expr()->eq(
248 'tt_content.colPos',
249 $queryBuilder->createNamedParameter($colPos, \PDO::PARAM_INT)
250 ),
251 $queryBuilder->expr()->eq(
252 'tt_content.pid',
253 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
254 )
255 )
256 ->orderBy('tt_content.sorting');
257
258 if (!empty($originalUids)) {
259 $queryBuilder
260 ->andWhere(
261 $queryBuilder->expr()->notIn(
262 'tt_content.uid',
263 $queryBuilder->createNamedParameter($originalUids, Connection::PARAM_INT_ARRAY)
264 )
265 );
266 }
267
268 return $queryBuilder->execute();
269 }
270
271 /**
272 * Returns the current BE user.
273 *
274 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
275 */
276 protected function getBackendUser()
277 {
278 return $GLOBALS['BE_USER'];
279 }
280
281 /**
282 * Get a QueryBuilder for the given table with preconfigured restrictions
283 * to not retrieve workspace placeholders or deleted records.
284 *
285 * @param string $tableName
286 * @return \TYPO3\CMS\Core\Database\Query\QueryBuilder
287 */
288 protected function getQueryBuilderWithWorkspaceRestriction(string $tableName): QueryBuilder
289 {
290 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
291 $queryBuilder->getRestrictions()
292 ->removeAll()
293 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
294 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
295
296 return $queryBuilder;
297 }
298 }