[TASK] Protect info extension
[Packages/TYPO3.CMS.git] / typo3 / sysext / info / Classes / Controller / TranslationStatusController.php
1 <?php
2 namespace TYPO3\CMS\Info\Controller;
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\Backend\Routing\UriBuilder;
18 use TYPO3\CMS\Backend\Tree\View\PageTreeView;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
21 use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
22 use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
23 use TYPO3\CMS\Core\Database\ConnectionPool;
24 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
25 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
26 use TYPO3\CMS\Core\Imaging\Icon;
27 use TYPO3\CMS\Core\Imaging\IconFactory;
28 use TYPO3\CMS\Core\Localization\LanguageService;
29 use TYPO3\CMS\Core\Page\PageRenderer;
30 use TYPO3\CMS\Core\Site\Entity\SiteInterface;
31 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
32 use TYPO3\CMS\Core\Type\Bitmask\Permission;
33 use TYPO3\CMS\Core\Utility\GeneralUtility;
34
35 /**
36 * Class for displaying translation status of pages in the tree in Web -> Info
37 */
38 class TranslationStatusController
39 {
40 use PublicPropertyDeprecationTrait;
41 use PublicMethodDeprecationTrait;
42
43 /**
44 * @var array
45 */
46 private $deprecatedPublicProperties = [
47 'pObj' => 'Using TranslationStatusController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
48 'function_key' => 'Using TranslationStatusController::function_key$ is deprecated, property will be removed in TYPO3 v10.',
49 'extClassConf' => 'Using TranslationStatusController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
50 'localLangFile' => 'Using TranslationStatusController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
51 'extObj' => 'Using TranslationStatusController::$extObj is deprecated, property will be removed in TYPO3 v10.',
52 ];
53
54 /**
55 * @var array
56 */
57 private $deprecatedPublicMethods = [
58 'getContentElementCount' => 'Using TranslationStatusController::getContentElementCount() is deprecated and will not be possible anymore in TYPO3 v10.',
59 'getLangStatus' => 'Using TranslationStatusController::getLangStatus() is deprecated and will not be possible anymore in TYPO3 v10.',
60 'renderL10nTable' => 'Using TranslationStatusController::renderL10nTable() is deprecated and will not be possible anymore in TYPO3 v10.',
61 'modMenu' => 'Using TranslationStatusController::modMenu() is deprecated and will not be possible anymore in TYPO3 v10.',
62 'extObjContent' => 'Using TranslationStatusController::extObjContent() is deprecated, method will be removed in TYPO3 v10.',
63 ];
64
65 /**
66 * @var IconFactory
67 */
68 protected $iconFactory;
69
70 /**
71 * @var SiteLanguage[]
72 */
73 protected $siteLanguages;
74
75 /**
76 * @var InfoModuleController Contains a reference to the parent calling object
77 */
78 protected $pObj;
79
80 /**
81 * @var int Value of the GET/POST var 'id'
82 */
83 protected $id;
84
85 /**
86 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
87 */
88 protected $extObj;
89
90 /**
91 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
92 */
93 protected $localLangFile = '';
94
95 /**
96 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
97 */
98 protected $extClassConf;
99
100 /**
101 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
102 */
103 protected $function_key = '';
104
105 /**
106 * Init, called from parent object
107 *
108 * @param InfoModuleController $pObj A reference to the parent (calling) object
109 */
110 public function init($pObj)
111 {
112 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
113 $this->id = (int)GeneralUtility::_GP('id');
114 $this->initializeSiteLanguages();
115 $this->pObj = $pObj;
116 // Local lang:
117 if (!empty($this->localLangFile)) {
118 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
119 $this->getLanguageService()->includeLLFile($this->localLangFile);
120 }
121 // Setting MOD_MENU items as we need them for logging:
122 $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
123 }
124
125 /**
126 * Main, called from parent object
127 *
128 * @return string Output HTML for the module.
129 */
130 public function main()
131 {
132 $theOutput = '<h1>' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_title')) . '</h1>';
133 if ($this->id) {
134 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Info/TranslationStatus');
135
136 // Depth selector:
137 $theOutput .= '<div class="form-inline form-inline-spaced">';
138 $h_func = BackendUtility::getDropdownMenu($this->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
139 $h_func .= BackendUtility::getDropdownMenu($this->id, 'SET[lang]', $this->pObj->MOD_SETTINGS['lang'], $this->pObj->MOD_MENU['lang']);
140 $theOutput .= $h_func;
141 // Add CSH:
142 $theOutput .= BackendUtility::cshItem('_MOD_web_info', 'lang', null, '<div class="form-group"><span class="btn btn-default btn-sm">|</span></div><br />');
143 $theOutput .= '</div>';
144 // Showing the tree:
145 // Initialize starting point of page tree:
146 $treeStartingPoint = (int)$this->id;
147 $treeStartingRecord = BackendUtility::getRecordWSOL('pages', $treeStartingPoint);
148 $depth = $this->pObj->MOD_SETTINGS['depth'];
149 // Initialize tree object:
150 $tree = GeneralUtility::makeInstance(PageTreeView::class);
151 $tree->init('AND ' . $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW));
152 $tree->addField('l18n_cfg');
153 // Creating top icon; the current page
154 $HTML = $this->iconFactory->getIconForRecord('pages', $treeStartingRecord, Icon::SIZE_SMALL)->render();
155 $tree->tree[] = [
156 'row' => $treeStartingRecord,
157 'HTML' => $HTML
158 ];
159 // Create the tree from starting point:
160 if ($depth) {
161 $tree->getTree($treeStartingPoint, $depth, '');
162 }
163 // Render information table:
164 $theOutput .= $this->renderL10nTable($tree);
165 }
166 return $theOutput;
167 }
168
169 /**
170 * Returns the menu array
171 *
172 * @return array
173 */
174 protected function modMenu()
175 {
176 $lang = $this->getLanguageService();
177 $menuArray = [
178 'depth' => [
179 0 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
180 1 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
181 2 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
182 3 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
183 4 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
184 999 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
185 ]
186 ];
187 // Languages:
188 $menuArray['lang'] = [];
189 foreach ($this->siteLanguages as $language) {
190 if ($language->getLanguageId() === 0) {
191 $menuArray['lang'][0] = '[All]';
192 } else {
193 $menuArray['lang'][$language->getLanguageId()] = $language->getTitle();
194 }
195 }
196 return $menuArray;
197 }
198
199 /**
200 * Rendering the localization information table.
201 *
202 * @param array $tree The Page tree data
203 * @return string HTML for the localization information table.
204 */
205 protected function renderL10nTable(&$tree)
206 {
207 $lang = $this->getLanguageService();
208 // Title length:
209 $titleLen = $this->getBackendUser()->uc['titleLen'];
210 // Put together the TREE:
211 $output = '';
212 $newOL_js = [];
213 $langRecUids = [];
214 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
215 foreach ($tree->tree as $data) {
216 $tCells = [];
217 $langRecUids[0][] = $data['row']['uid'];
218 // Page icons / titles etc.
219 $tCells[] = '<td' . ($data['row']['_CSSCLASS'] ? ' class="' . $data['row']['_CSSCLASS'] . '"' : '') . '>' .
220 ($data['depthData'] ?: '') .
221 BackendUtility::wrapClickMenuOnIcon($data['HTML'], 'pages', $data['row']['uid']) .
222 '<a href="#" onclick="' . htmlspecialchars(
223 'top.loadEditId(' . (int)$data['row']['uid'] . ',"&SET[language]=0"); return false;'
224 ) . '" title="' . $lang->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_editPage') . '">' .
225 htmlspecialchars(GeneralUtility::fixed_lgd_cs($data['row']['title'], $titleLen)) .
226 '</a>' .
227 ((string)$data['row']['nav_title'] !== '' ? ' [Nav: <em>' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($data['row']['nav_title'], $titleLen)) . '</em>]' : '') .
228 '</td>';
229 // DEFAULT language:
230 // "View page" link is created:
231 $viewPageLink = '<a href="#" onclick="' . htmlspecialchars(
232 BackendUtility::viewOnClick(
233 $data['row']['uid'],
234 '',
235 null,
236 '',
237 '',
238 '&L=###LANG_UID###'
239 )
240 ) . '" class="btn btn-default" title="' . $lang->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_viewPage') . '">' .
241 $this->iconFactory->getIcon('actions-view', Icon::SIZE_SMALL)->render() . '</a>';
242 $status = GeneralUtility::hideIfDefaultLanguage($data['row']['l18n_cfg']) ? 'danger' : 'success';
243 // Create links:
244 $editUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', [
245 'edit' => [
246 'pages' => [
247 $data['row']['uid'] => 'edit'
248 ]
249 ],
250 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
251 ]);
252 $info = '<a href="#" onclick="' . htmlspecialchars(
253 BackendUtility::viewOnClick(
254 $data['row']['uid'],
255 '',
256 null,
257 '',
258 '',
259 ''
260 )
261 ) . '" class="btn btn-default" title="' . $lang->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_viewPage') . '">' .
262 $this->iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL)->render() . '</a>';
263 $info .= '<a href="' . htmlspecialchars($editUrl)
264 . '" class="btn btn-default" title="' . $lang->sL(
265 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_editDefaultLanguagePage'
266 ) . '">' . $this->iconFactory->getIcon('actions-page-open', Icon::SIZE_SMALL)->render() . '</a>';
267 $info .= '&nbsp;';
268 $info .= GeneralUtility::hideIfDefaultLanguage($data['row']['l18n_cfg']) ? '<span title="' . htmlspecialchars($lang->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.l18n_cfg.I.1')) . '">D</span>' : '&nbsp;';
269 $info .= GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) ? '<span title="' . htmlspecialchars($lang->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.l18n_cfg.I.2')) . '">N</span>' : '&nbsp;';
270 // Put into cell:
271 $tCells[] = '<td class="' . $status . ' col-border-left"><div class="btn-group">' . $info . '</div></td>';
272 $tCells[] = '<td class="' . $status . '" title="' . $lang->sL(
273 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_CEcount'
274 ) . '" align="center">' . $this->getContentElementCount($data['row']['uid'], 0) . '</td>';
275 // Traverse system languages:
276 foreach ($this->siteLanguages as $siteLanguage) {
277 $languageId = $siteLanguage->getLanguageId();
278 if ($languageId === 0) {
279 continue;
280 }
281 if ($this->pObj->MOD_SETTINGS['lang'] == 0 || (int)$this->pObj->MOD_SETTINGS['lang'] === $languageId) {
282 $row = $this->getLangStatus($data['row']['uid'], $languageId);
283 if (is_array($row)) {
284 $langRecUids[$languageId][] = $row['uid'];
285 $status = $row['_HIDDEN'] ? (GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || GeneralUtility::hideIfDefaultLanguage($data['row']['l18n_cfg']) ? 'danger' : '') : 'success';
286 $icon = $this->iconFactory->getIconForRecord('pages', $row, Icon::SIZE_SMALL)->render();
287 $info = $icon . htmlspecialchars(
288 GeneralUtility::fixed_lgd_cs($row['title'], $titleLen)
289 ) . ((string)$row['nav_title'] !== '' ? ' [Nav: <em>' . htmlspecialchars(
290 GeneralUtility::fixed_lgd_cs($row['nav_title'], $titleLen)
291 ) . '</em>]' : '') . ($row['_COUNT'] > 1 ? '<div>' . $lang->sL(
292 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_badThingThereAre'
293 ) . '</div>' : '');
294 $tCells[] = '<td class="' . $status . ' col-border-left">' .
295 '<a href="#" onclick="' . htmlspecialchars(
296 'top.loadEditId(' . (int)$data['row']['uid'] . ',"&SET[language]=' . $languageId . '"); return false;'
297 ) . '" title="' . $lang->sL(
298 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_editPageLang'
299 ) . '">' . $info . '</a></td>';
300 // Edit whole record:
301 // Create links:
302 $editUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', [
303 'edit' => [
304 'pages' => [
305 $row['uid'] => 'edit'
306 ]
307 ],
308 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
309 ]);
310 $info = str_replace('###LANG_UID###', $languageId, $viewPageLink);
311 $info .= '<a href="' . htmlspecialchars($editUrl)
312 . '" class="btn btn-default" title="' . $lang->sL(
313 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_editLanguageOverlayRecord'
314 ) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>';
315 $tCells[] = '<td class="' . $status . '"><div class="btn-group">' . $info . '</div></td>';
316 $tCells[] = '<td class="' . $status . '" title="' . $lang->sL(
317 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_CEcount'
318 ) . '" align="center">' . $this->getContentElementCount($data['row']['uid'], $languageId) . '</td>';
319 } else {
320 $status = GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || GeneralUtility::hideIfDefaultLanguage($data['row']['l18n_cfg']) ? 'danger' : '';
321 $info = '<div class="btn-group"><label class="btn btn-default btn-checkbox">';
322 $info .= '<input type="checkbox" data-lang="' . $languageId . '" name="newOL[' . $languageId . '][' . $data['row']['uid'] . ']" value="1" />';
323 $info .= '<span class="t3-icon fa"></span></label></div>';
324 $newOL_js[$languageId] .=
325 ' +(document.webinfoForm['
326 . GeneralUtility::quoteJSvalue('newOL[' . $languageId . '][' . $data['row']['uid'] . ']')
327 . '].checked ? '
328 . GeneralUtility::quoteJSvalue('&edit[pages][' . $data['row']['uid'] . ']=new')
329 . ' : \'\')'
330 ;
331 $tCells[] = '<td class="' . $status . ' col-border-left">&nbsp;</td>';
332 $tCells[] = '<td class="' . $status . '">&nbsp;</td>';
333 $tCells[] = '<td class="' . $status . '">' . $info . '</td>';
334 }
335 }
336 }
337 $output .= '
338 <tr>
339 ' . implode('
340 ', $tCells) . '
341 </tr>';
342 }
343 // Put together HEADER:
344 $tCells = [];
345 $tCells[] = '<td>' . $lang->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_page') . '</td>';
346 if (is_array($langRecUids[0])) {
347 $editUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', [
348 'edit' => [
349 'pages' => [
350 implode(',', $langRecUids[0]) => 'edit'
351 ]
352 ],
353 'columnsOnly' => 'title,nav_title,l18n_cfg,hidden',
354 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
355 ]);
356 $editIco = '<a href="' . htmlspecialchars($editUrl)
357 . '" class="btn btn-default" title="' . $lang->sL(
358 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_editPageProperties'
359 ) . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
360 } else {
361 $editIco = '';
362 }
363 $tCells[] = '<td class="col-border-left" colspan="2">' . $lang->sL(
364 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_default'
365 ) . '&nbsp;' . $editIco . '</td>';
366 foreach ($this->siteLanguages as $siteLanguage) {
367 $languageId = $siteLanguage->getLanguageId();
368 if ($languageId === 0) {
369 continue;
370 }
371 if ($this->pObj->MOD_SETTINGS['lang'] == 0 || (int)$this->pObj->MOD_SETTINGS['lang'] === $languageId) {
372 // Title:
373 $tCells[] = '<td class="col-border-left">' . htmlspecialchars($siteLanguage->getTitle()) . '</td>';
374 // Edit language overlay records:
375 if (is_array($langRecUids[$languageId])) {
376 $editUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', [
377 'edit' => [
378 'pages' => [
379 implode(',', $langRecUids[$languageId]) => 'edit'
380 ]
381 ],
382 'columnsOnly' => 'title,nav_title,hidden',
383 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
384 ]);
385 $editButton = '<a href="' . htmlspecialchars($editUrl)
386 . '" class="btn btn-default" title="' . $lang->sL(
387 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_renderl10n_editLangOverlays'
388 ) . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
389 } else {
390 $editButton = '';
391 }
392 // Create new overlay records:
393 $params = '&columnsOnly=title,hidden,sys_language_uid&overrideVals[pages][sys_language_uid]=' . $languageId;
394 $onClick = BackendUtility::editOnClick($params);
395 if (!empty($newOL_js[$languageId])) {
396 $onClickArray = explode('?', $onClick, 2);
397 $lastElement = array_pop($onClickArray);
398 $onClickArray[] = '\'' . $newOL_js[$languageId] . ' + \'&' . $lastElement;
399 $onClick = implode('?', $onClickArray);
400 }
401 $newButton = '<a href="#" class="btn btn-default disabled t3js-language-new-' . $languageId . '" onclick="' . htmlspecialchars($onClick)
402 . '" title="' . $lang->sL(
403 'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_getlangsta_createNewTranslationHeaders'
404 ) . '">' . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . '</a>';
405
406 $tCells[] = '<td class="btn-group">' . $editButton . $newButton . '</td>';
407 $tCells[] = '<td>&nbsp;</td>';
408 }
409 }
410
411 $output =
412 '<div class="table-fit">' .
413 '<table class="table table-striped table-hover" id="langTable">' .
414 '<thead>' .
415 '<tr>' .
416 implode('', $tCells) .
417 '</tr>' .
418 '</thead>' .
419 '<tbody>' .
420 $output .
421 '</tbody>' .
422 '</table>' .
423 '</div>';
424 return $output;
425 }
426
427 /**
428 * Selects all system languages (from sys_language)
429 *
430 * @return array System language records in an array.
431 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10
432 */
433 public function getSystemLanguages()
434 {
435 trigger_error('This method will be removed in TYPO3 v10.', E_USER_DEPRECATED);
436 if (!$this->getBackendUser()->isAdmin() && $this->getBackendUser()->groupData['allowed_languages'] !== '') {
437 $allowed_languages = array_flip(explode(',', $this->getBackendUser()->groupData['allowed_languages']));
438 }
439 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
440 ->getQueryBuilderForTable('sys_language')
441 ->select('*')
442 ->from('sys_language')
443 ->orderBy('sorting');
444 $res = $queryBuilder->execute();
445 $outputArray = [];
446 if (is_array($allowed_languages) && !empty($allowed_languages)) {
447 while ($output = $res->fetch()) {
448 if (isset($allowed_languages[$output['uid']])) {
449 $outputArray[] = $output;
450 }
451 }
452 } else {
453 $outputArray = $res->fetchAll();
454 }
455 return $outputArray;
456 }
457
458 /**
459 * Get an alternative language record for a specific page / language
460 *
461 * @param int $pageId Page ID to look up for.
462 * @param int $langId Language UID to select for.
463 * @return array translated pages record
464 */
465 protected function getLangStatus($pageId, $langId)
466 {
467 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
468 ->getQueryBuilderForTable('pages');
469 $queryBuilder
470 ->getRestrictions()
471 ->removeAll()
472 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class))
473 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
474 $result = $queryBuilder
475 ->select('*')
476 ->from('pages')
477 ->where(
478 $queryBuilder->expr()->eq(
479 $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
480 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
481 )
482 )
483 ->andWhere(
484 $queryBuilder->expr()->eq(
485 $GLOBALS['TCA']['pages']['ctrl']['languageField'],
486 $queryBuilder->createNamedParameter($langId, \PDO::PARAM_INT)
487 )
488 )
489 ->execute();
490
491 $row = $result->fetch();
492 BackendUtility::workspaceOL('pages', $row);
493 if (is_array($row)) {
494 $row['_COUNT'] = $queryBuilder->count('uid')->execute()->fetchColumn(0);
495 $row['_HIDDEN'] = $row['hidden'] || (int)$row['endtime'] > 0 && (int)$row['endtime'] < $GLOBALS['EXEC_TIME'] || $GLOBALS['EXEC_TIME'] < (int)$row['starttime'];
496 }
497 $result->closeCursor();
498 return $row;
499 }
500
501 /**
502 * Counting content elements for a single language on a page.
503 *
504 * @param int $pageId Page id to select for.
505 * @param int $sysLang Sys language uid
506 * @return int Number of content elements from the PID where the language is set to a certain value.
507 */
508 protected function getContentElementCount($pageId, $sysLang)
509 {
510 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
511 ->getQueryBuilderForTable('tt_content');
512 $queryBuilder->getRestrictions()
513 ->removeAll()
514 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
515 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
516 $count = $queryBuilder
517 ->count('uid')
518 ->from('tt_content')
519 ->where(
520 $queryBuilder->expr()->eq(
521 'pid',
522 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
523 )
524 )
525 ->andWhere(
526 $queryBuilder->expr()->eq(
527 'sys_language_uid',
528 $queryBuilder->createNamedParameter($sysLang, \PDO::PARAM_INT)
529 )
530 )
531 ->execute()
532 ->fetchColumn(0);
533 return $count ?: '-';
534 }
535
536 /**
537 * Since the AbstractFunctionModule cannot access the current request yet, we'll do it "old school"
538 * to fetch the Site based on the current ID.
539 */
540 protected function initializeSiteLanguages()
541 {
542 /** @var SiteInterface $currentSite */
543 $currentSite = $GLOBALS['TYPO3_REQUEST']->getAttribute('site');
544 $this->siteLanguages = $currentSite->getAvailableLanguages($this->getBackendUser(), false, (int)$this->id);
545 }
546
547 /**
548 * Called from InfoModuleController until deprecation removal in v10
549 *
550 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
551 */
552 public function checkExtObj()
553 {
554 if (is_array($this->extClassConf) && $this->extClassConf['name']) {
555 $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
556 $this->extObj->init($this->pObj, $this->extClassConf);
557 // Re-write:
558 $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info');
559 }
560 }
561
562 /**
563 * Calls the main function inside ANOTHER sub-submodule which might exist.
564 *
565 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
566 */
567 protected function extObjContent()
568 {
569 if (is_object($this->extObj)) {
570 return $this->extObj->main();
571 }
572 }
573
574 /**
575 * @return LanguageService
576 */
577 protected function getLanguageService(): LanguageService
578 {
579 return $GLOBALS['LANG'];
580 }
581
582 /**
583 * Returns the current BE user.
584 *
585 * @return BackendUserAuthentication
586 */
587 protected function getBackendUser(): BackendUserAuthentication
588 {
589 return $GLOBALS['BE_USER'];
590 }
591
592 /**
593 * @return PageRenderer
594 */
595 protected function getPageRenderer(): PageRenderer
596 {
597 return GeneralUtility::makeInstance(PageRenderer::class);
598 }
599 }