getBackendUser(); $view = $this->moduleTemplateFactory->create($request); $view->getDocHeaderComponent()->disable(); $queryParams = $request->getQueryParams(); $this->table = $queryParams['table'] ?? null; $uid = $queryParams['uid'] ?? ''; $permsClause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW); // Determines if table/uid point to database record or file and if user has access to view information $accessAllowed = false; if ($this->tcaSchemaFactory->has($this->table)) { $uid = (int)$uid; // Check permissions and uid value: if ($uid && $backendUser->check('tables_select', $this->table)) { if ((string)$this->table === 'pages') { $this->row = BackendUtility::readPageAccess($uid, $permsClause) ?: []; $accessAllowed = $this->row !== []; } else { $this->row = BackendUtility::getRecordWSOL($this->table, $uid); if ($this->row) { if (isset($this->row['_ORIG_uid'])) { // Make $uid the uid of the versioned record, while $this->row['uid'] is live record uid $uid = (int)$this->row['_ORIG_uid']; } $pageInfo = BackendUtility::readPageAccess((int)$this->row['pid'], $permsClause) ?: []; $accessAllowed = $pageInfo !== [] || ((int)$this->row['pid'] === 0 && $this->tcaSchemaFactory->get($this->table)->getCapability(TcaSchemaCapability::RestrictionRootLevel)->shallIgnoreRootLevelRestriction()); } } } } elseif ($this->table === '_FILE' || $this->table === '_FOLDER' || $this->table === 'sys_file') { $fileOrFolderObject = $this->resourceFactory->retrieveFileOrFolderObject($uid); if ($fileOrFolderObject instanceof Folder) { $this->folderObject = $fileOrFolderObject; $accessAllowed = $this->folderObject->checkActionPermission('read'); $this->type = 'folder'; } elseif ($fileOrFolderObject instanceof File) { $this->fileObject = $fileOrFolderObject; $accessAllowed = $this->fileObject->checkActionPermission('read'); $this->type = 'file'; $this->table = 'sys_file'; $this->row = BackendUtility::getRecordWSOL($this->table, $fileOrFolderObject->getUid()); } } // Rendering of the output via fluid $view->assign('accessAllowed', $accessAllowed); $view->assign('hookContent', ''); if (!$accessAllowed) { return $view->renderResponse('ContentElement/ElementInformation'); } // render type by user func foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/show_item.php']['typeRendering'] ?? [] as $className) { $typeRenderObj = GeneralUtility::makeInstance($className); if (method_exists($typeRenderObj, 'isValid') && method_exists($typeRenderObj, 'render')) { if ($typeRenderObj->isValid($this->type, $this)) { $view->assign('hookContent', $typeRenderObj->render($this->type, $this, $view)); return $view->renderResponse('ContentElement/ElementInformation'); } } } $pageTitle = $this->getPageTitle(); $view->setTitle($pageTitle['table'] . ': ' . $pageTitle['title']); $view->assignMultiple($pageTitle); $view->assignMultiple($this->getPreview($request)); $view->assignMultiple($this->getPropertiesForTable()); $view->assignMultiple($this->getReferences($request, $uid)); $view->assign('returnUrl', GeneralUtility::sanitizeLocalUrl($request->getQueryParams()['returnUrl'] ?? '', $request)); $view->assign('maxTitleLength', $this->getBackendUser()->uc['titleLen'] ?? 20); return $view->renderResponse('ContentElement/ElementInformation'); } /** * Get page title with icon, table title and record title */ public function getPageTitle(): array { $pageTitle = [ 'title' => BackendUtility::getRecordTitle($this->table, $this->row), ]; if ($this->type === 'folder') { $pageTitle['title'] = htmlspecialchars($this->folderObject->getName()); $pageTitle['table'] = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:folder'); $pageTitle['icon'] = $this->iconFactory->getIconForResource($this->folderObject, IconSize::SMALL)->render(); } elseif ($this->type === 'file') { $schema = $this->tcaSchemaFactory->get($this->table); $pageTitle['table'] = $schema->getTitle($this->getLanguageService()->sL(...)); $pageTitle['icon'] = $this->iconFactory->getIconForResource($this->fileObject, IconSize::SMALL)->render(); } else { $schema = $this->tcaSchemaFactory->get($this->table); $pageTitle['table'] = $schema->getTitle($this->getLanguageService()->sL(...)); $pageTitle['icon'] = $this->iconFactory->getIconForRecord($this->table, $this->row, IconSize::SMALL); } return $pageTitle; } public function getTable(): ?string { return $this->table; } public function getRow(): array { return $this->row; } public function getFileObject(): ?File { return $this->fileObject; } public function getFolderObject(): ?Folder { return $this->folderObject; } /** * Get preview for current record */ protected function getPreview(ServerRequestInterface $request): array { $preview = []; // Perhaps @todo in future: Also display preview for records - without fileObject if (!$this->fileObject) { return $preview; } // check if file is marked as missing if ($this->fileObject->isMissing()) { $preview['missingFile'] = $this->fileObject->getName(); } else { $fileRenderer = $this->rendererRegistry->getRenderer($this->fileObject); $preview['url'] = $this->fileObject->getPublicUrl() ?? ''; // Add "edit metadata" button $preview['editMetadataUrl'] = ''; if (($metaDataUid = $this->fileObject->getProperties()['metadata_uid'] ?? false) && $this->fileObject->isIndexed() && $this->fileObject->checkActionPermission('editMeta') && $this->getBackendUser()->check('tables_modify', 'sys_file_metadata') ) { $urlParameters = [ 'edit' => [ 'sys_file_metadata' => [ $metaDataUid => 'edit', ], ], 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), ]; $preview['editMetadataUrl'] = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); } $width = min(590, $this->fileObject->getMetaData()['width'] ?? 590) . 'm'; $height = min(400, $this->fileObject->getMetaData()['height'] ?? 400) . 'm'; // Check if there is a FileRenderer if ($fileRenderer !== null) { $preview['fileRenderer'] = $fileRenderer->render($this->fileObject, $width, $height); // else check if we can create an Image preview } elseif ($this->fileObject->isImage()) { $preview['fileObject'] = $this->fileObject; $preview['width'] = $width; $preview['height'] = $height; } } return $preview; } /** * Get property array for html table */ protected function getPropertiesForTable(): array { $lang = $this->getLanguageService(); $propertiesForTable = []; $propertiesForTable['extraFields'] = $this->getExtraFields(); // Traverse the list of fields to display for the record: $fieldList = $this->getFieldList($this->table, $this->row); $schema = $this->tcaSchemaFactory->has($this->table) ? $this->tcaSchemaFactory->get($this->table) : null; foreach ($fieldList as $name) { $name = trim($name); $uid = $this->row['uid'] ?? 0; if (!$schema?->hasField($name)) { continue; } // @todo Add meaningful information for mfa field. For the time being we don't display anything at all. if ($this->type === 'db' && $name === 'mfa' && in_array($this->table, ['be_users', 'fe_users'], true)) { continue; } // not a real field -> skip if ($this->type === 'file' && $name === 'fileinfo') { continue; } // handled explicitly below with proper byte formatting -> skip if ($this->type === 'file' && $name === 'size') { continue; } // Field does not exist (e.g. having type=none) -> skip if (!array_key_exists($name, $this->row)) { continue; } $label = $lang->sL($schema->getField($name)->getLabel()); $label = $label ?: $name; $propertiesForTable['fields'][] = [ 'fieldValue' => BackendUtility::getProcessedValue($this->table, $name, $this->row[$name], 0, false, false, $uid, true, 0, $this->row), 'fieldLabel' => htmlspecialchars($label), ]; } // additional information for folders and files if ($this->folderObject instanceof Folder || $this->fileObject instanceof File) { // storage if ($this->folderObject instanceof Folder) { $propertiesForTable['fields']['storage'] = [ 'fieldValue' => $this->folderObject->getStorage()->getName(), 'fieldLabel' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file.storage')), ]; } // folder $resourceObject = $this->fileObject ?: $this->folderObject; $parentFolder = $resourceObject->getParentFolder(); $propertiesForTable['fields']['folder'] = [ 'fieldValue' => $parentFolder->getReadablePath(), 'fieldLabel' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:folder')), ]; if ($this->fileObject instanceof File) { // show file dimensions for images if ($this->fileObject->isType(FileType::IMAGE)) { $propertiesForTable['fields']['width'] = [ 'fieldValue' => $this->fileObject->getProperty('width') . 'px', 'fieldLabel' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.width')), ]; $propertiesForTable['fields']['height'] = [ 'fieldValue' => $this->fileObject->getProperty('height') . 'px', 'fieldLabel' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.height')), ]; } // file size $fileSizeInBytes = (int)$this->fileObject->getProperty('size'); $propertiesForTable['fields']['size'] = [ 'fieldValue' => sprintf( '%s (%s)', GeneralUtility::formatSize($fileSizeInBytes, htmlspecialchars($this->getLanguageService()->sL('core.common:byteSizeUnits'))), htmlspecialchars($lang->translate('size_in_bytes', 'core.core', ['numberOfBytes' => GeneralUtility::formatSize($fileSizeInBytes, ' ')])), ), 'fieldLabel' => $lang->sL($schema?->hasField('size') ? $schema->getField('size')->getLabel() : ''), ]; // show the metadata of a file as well $metaData = $this->metaDataRepository->findByFileUid((int)($this->row['uid'] ?? 0)); // If there is no metadata record, skip it if ($metaData !== []) { $fileMetadataSchema = $this->tcaSchemaFactory->get('sys_file_metadata'); $allowedFields = $this->getFieldList('sys_file_metadata', $metaData); foreach ($metaData as $name => $value) { if (!in_array($name, $allowedFields, true)) { continue; } if ($name === 'crdate') { // Is of type=passthrough and already part of // meta information displayed on top of the table continue; } if (!$fileMetadataSchema->hasField($name)) { continue; } $label = $lang->sL($fileMetadataSchema->getField($name)->getLabel()); $label = $label ?: $name; $propertiesForTable['fields'][] = [ 'fieldValue' => BackendUtility::getProcessedValue('sys_file_metadata', $name, $value, 0, false, false, (int)$metaData['uid'], true, 0, $metaData), 'fieldLabel' => htmlspecialchars($label), ]; } } } } return $propertiesForTable; } /** * Get the list of fields that should be shown for the given table */ protected function getFieldList(string $table, array $row): array { $fieldNamesToExclude = []; if ($this->tcaSchemaFactory->has($table)) { $schema = $this->tcaSchemaFactory->get($table); if ($schema->hasCapability(TcaSchemaCapability::AncestorReferenceField)) { $fieldNamesToExclude[] = $schema->getCapability(TcaSchemaCapability::AncestorReferenceField)->getFieldName(); } if ($schema->isLanguageAware()) { $languageCapability = $schema->getCapability(TcaSchemaCapability::Language); $fieldNamesToExclude[] = $languageCapability->getTranslationOriginPointerField()->getName(); if ($languageCapability->hasDiffSourceField()) { $fieldNamesToExclude[] = $languageCapability->getDiffSourceField()?->getName(); } } } return $this->searchableSchemaFieldsCollector->getUniqueFieldList( $table, $this->visibleSchemaFieldsCollector->getFieldNames($table, $row, $fieldNamesToExclude), false ); } /** * Get the extra fields (uid, timestamps, creator) for the table */ protected function getExtraFields(): array { $lang = $this->getLanguageService(); $keyLabelPair = []; if (in_array($this->type, ['folder', 'file'], true)) { if ($this->type === 'file') { $keyLabelPair['uid'] = [ 'value' => (int)$this->row['uid'], ]; $keyLabelPair['creation_date'] = [ 'value' => BackendUtility::datetime($this->row['creation_date']), 'fieldLabel' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.creationDate')), 'isDatetime' => true, ]; $keyLabelPair['modification_date'] = [ 'value' => BackendUtility::datetime($this->row['modification_date']), 'fieldLabel' => htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.timestamp')), 'isDatetime' => true, ]; } else { $keyLabelPair['uid'] = [ 'value' => $this->folderObject->getCombinedIdentifier(), ]; } } else { $keyLabelPair['uid'] = [ 'value' => BackendUtility::getProcessedValueExtra($this->table, 'uid', $this->row['uid']), 'fieldLabel' => rtrim(htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:show_item.php.uid')), ':'), ]; $schema = $this->tcaSchemaFactory->get($this->table); if ($schema->hasCapability(TcaSchemaCapability::CreatedAt)) { $field = $schema->getCapability(TcaSchemaCapability::CreatedAt)->getFieldName(); $keyLabelPair[$field] = [ 'value' => BackendUtility::datetime($this->row[$field]), 'fieldLabel' => rtrim(htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.creationDate')), ':'), 'isDatetime' => true, ]; } if ($schema->hasCapability(TcaSchemaCapability::UpdatedAt)) { $field = $schema->getCapability(TcaSchemaCapability::UpdatedAt)->getFieldName(); $keyLabelPair[$field] = [ 'value' => BackendUtility::datetime($this->row[$field]), 'fieldLabel' => rtrim(htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.timestamp')), ':'), 'isDatetime' => true, ]; } // Show the user who created the record $recordHistory = GeneralUtility::makeInstance(RecordHistory::class); $ownerInformation = $recordHistory->getCreationInformationForRecord($this->table, $this->row); $ownerUid = (int)(is_array($ownerInformation) && $ownerInformation['usertype'] === 'BE' ? $ownerInformation['userid'] : 0); if ($ownerUid) { $creatorRecord = BackendUtility::getRecord('be_users', $ownerUid); if ($creatorRecord) { $keyLabelPair['creatorRecord'] = [ 'value' => $creatorRecord, 'fieldLabel' => rtrim(htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.creationUserId')), ':'), ]; } } } return $keyLabelPair; } /** * Get references section (references from and references to current record) */ protected function getReferences(ServerRequestInterface $request, int|string $uid): array { $references = []; switch ($this->type) { case 'db': { $references['refLines'] = $this->makeRef($this->table, $uid, $request); $references['refFromLines'] = $this->makeRefFrom($this->table, $uid, $request); break; } case 'file': { if ($this->fileObject && $this->fileObject->isIndexed()) { $references['refLines'] = $this->makeRef('_FILE', $this->fileObject, $request); } break; } } return $references; } /** * Get field name for specified table/column name * * @param string $fieldName Column name */ protected function getLabelForTableColumn(TcaSchema $schema, string $fieldName): string { if ($schema->hasField($fieldName)) { $field = $schema->getField($fieldName); $field = $field->getLabel() ? $this->getLanguageService()->sL($field->getLabel()) : $fieldName; if (trim($field) === '') { $field = $fieldName; } } else { $field = $fieldName; } return $field; } /** * Returns the record actions * * @param int $uid * @throws RouteNotFoundException */ protected function getRecordActions(TcaSchema $schema, $uid, ServerRequestInterface $request): array { if ($uid < 0) { return []; } $actions = []; // Edit button $urlParameters = [ 'edit' => [ $schema->getName() => [ $uid => 'edit', ], ], 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), ]; $actions['recordEditUrl'] = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); // History button $urlParameters = [ 'element' => $schema->getName() . ':' . $uid, 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), ]; $actions['recordHistoryUrl'] = (string)$this->uriBuilder->buildUriFromRoute('record_history', $urlParameters); if ($schema->getName() === 'pages') { // Recordlist button $actions['recordsModuleUrl'] = (string)$this->uriBuilder->buildUriFromRoute('records', ['id' => $uid, 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()]); // retrieve record to get page language $record = BackendUtility::getRecord($schema->getName(), $uid); $previewUriBuilder = PreviewUriBuilder::create($record) ->withRootLine(BackendUtility::BEgetRootLine($uid)); // View page button $actions['previewUrlAttributes'] = $previewUriBuilder->serializeDispatcherAttributes(); } return $actions; } /** * Make reference display * * @param string $table Table name * @param int|File $ref Filename or uid * @throws RouteNotFoundException */ protected function makeRef(string $table, $ref, ServerRequestInterface $request): array { $refLines = []; $lang = $this->getLanguageService(); // Files reside in sys_file table if ($table === '_FILE') { $selectTable = 'sys_file'; $selectUid = $ref->getUid(); } else { $selectTable = $table; $selectUid = $ref; } $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('sys_refindex'); $predicates = [ $queryBuilder->expr()->eq( 'ref_table', $queryBuilder->createNamedParameter($selectTable) ), $queryBuilder->expr()->eq( 'ref_uid', $queryBuilder->createNamedParameter($selectUid, Connection::PARAM_INT) ), ]; $backendUser = $this->getBackendUser(); if (!$backendUser->isAdmin()) { $allowedSelectTables = GeneralUtility::trimExplode(',', $backendUser->groupData['tables_select']); $predicates[] = $queryBuilder->expr()->in( 'tablename', $queryBuilder->createNamedParameter($allowedSelectTables, Connection::PARAM_STR_ARRAY) ); } $rows = $queryBuilder ->select('*') ->from('sys_refindex') ->where(...$predicates) ->executeQuery() ->fetchAllAssociative(); // Compile information for title tag: foreach ($rows as $row) { if ($row['tablename'] === 'sys_file_reference') { $row = $this->transformFileReferenceToRecordReference($row); if ($row === null) { continue; } } if (!$this->tcaSchemaFactory->has($row['tablename'])) { continue; } $schema = $this->tcaSchemaFactory->get($row['tablename']); $line = []; $record = BackendUtility::getRecordWSOL($row['tablename'], $row['recuid']); if ($record) { if (!$this->canAccessPage($schema, $record)) { continue; } $parentRecord = BackendUtility::getRecord('pages', $record['pid']); $parentRecordTitle = is_array($parentRecord) ? BackendUtility::getRecordTitle('pages', $parentRecord) : ''; $urlParameters = [ 'edit' => [ $row['tablename'] => [ $row['recuid'] => 'edit', ], ], 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), ]; $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); $line['url'] = $url; $line['icon'] = $this->iconFactory->getIconForRecord($row['tablename'], $record, IconSize::SMALL)->render(); $line['row'] = $row; $line['record'] = $record; $line['recordTitle'] = BackendUtility::getRecordTitle($row['tablename'], $record); $line['parentRecord'] = $parentRecord; $line['parentRecordTitle'] = $parentRecordTitle; $line['title'] = $schema->getTitle($lang->sL(...)) ?: $row['tablename']; $line['labelForTableColumn'] = $this->getLabelForTableColumn($schema, $row['field']); $line['path'] = BackendUtility::getRecordPath($record['pid'], '', 0, 0); $line['actions'] = $this->getRecordActions($schema, $row['recuid'], $request); } else { $line['row'] = $row; $line['title'] = $schema->getTitle($lang->sL(...)) ?: $row['tablename']; $line['labelForTableColumn'] = $this->getLabelForTableColumn($schema, $row['field']); } $refLines[] = $line; } return $refLines; } /** * Make reference display (what this elements points to) * * @param string $table Table name * @param int $ref Filename or uid */ protected function makeRefFrom($table, $ref, ServerRequestInterface $request): array { $refFromLines = []; $lang = $this->getLanguageService(); $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('sys_refindex'); $predicates = [ $queryBuilder->expr()->eq( 'tablename', $queryBuilder->createNamedParameter($table) ), $queryBuilder->expr()->eq( 'recuid', $queryBuilder->createNamedParameter($ref, Connection::PARAM_INT) ), ]; $backendUser = $this->getBackendUser(); if (!$backendUser->isAdmin()) { $allowedSelectTables = GeneralUtility::trimExplode(',', $backendUser->groupData['tables_select']); $predicates[] = $queryBuilder->expr()->in( 'ref_table', $queryBuilder->createNamedParameter($allowedSelectTables, Connection::PARAM_STR_ARRAY) ); } $rows = $queryBuilder ->select('*') ->from('sys_refindex') ->where(...$predicates) ->executeQuery() ->fetchAllAssociative(); // Compile information for title tag: foreach ($rows as $row) { $line = []; $record = BackendUtility::getRecordWSOL($row['ref_table'], $row['ref_uid']); if (!$this->tcaSchemaFactory->has($row['ref_table'])) { continue; } $schema = $this->tcaSchemaFactory->get($row['ref_table']); if ($record) { if (!$this->canAccessPage($schema, $record)) { continue; } $urlParameters = [ 'edit' => [ $row['ref_table'] => [ $row['ref_uid'] => 'edit', ], ], 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), ]; $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); $line['url'] = $url; $line['icon'] = $this->iconFactory->getIconForRecord($row['ref_table'], $record, IconSize::SMALL)->render(); $line['row'] = $row; $line['record'] = $record; $line['recordTitle'] = BackendUtility::getRecordTitle($row['ref_table'], $record); $line['title'] = $schema->getTitle($lang->sL(...)); $line['labelForTableColumn'] = $this->getLabelForTableColumn($schema, $row['field']); $line['path'] = BackendUtility::getRecordPath($record['pid'], '', 0); $line['actions'] = $this->getRecordActions($schema, $row['ref_uid'], $request); } else { $line['row'] = $row; $line['title'] = $schema->getTitle($lang->sL(...)); $line['labelForTableColumn'] = $this->getLabelForTableColumn($schema, $row['field']); } $refFromLines[] = $line; } return $refFromLines; } /** * Convert FAL file reference (sys_file_reference) to reference index (sys_refindex) table format */ protected function transformFileReferenceToRecordReference(array $referenceRecord): ?array { $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('sys_file_reference'); $queryBuilder->getRestrictions()->removeAll(); $fileReference = $queryBuilder ->select('*') ->from('sys_file_reference') ->where( $queryBuilder->expr()->eq( 'uid', $queryBuilder->createNamedParameter($referenceRecord['recuid'], Connection::PARAM_INT) ) ) ->executeQuery() ->fetchAssociative(); return $fileReference ? [ 'recuid' => $fileReference['uid_foreign'], 'tablename' => $fileReference['tablenames'], 'field' => $fileReference['fieldname'], 'flexpointer' => '', 'softref_key' => '', 'sorting' => $fileReference['sorting_foreign'], ] : null; } /** * @param array $record Record to be checked (ensure pid is resolved for workspaces) */ protected function canAccessPage(TcaSchema $schema, array $record): bool { $recordPid = (int)($schema->getName() === 'pages' ? $record['uid'] : $record['pid']); $isInWebMount = (bool)$this->getBackendUser()->isInWebMount($schema->getName() === 'pages' ? $record : $record['pid']); return $isInWebMount || ($recordPid === 0 && $schema->getCapability(TcaSchemaCapability::RestrictionRootLevel)->shallIgnoreRootLevelRestriction()); } protected function getLanguageService(): LanguageService { return $GLOBALS['LANG']; } protected function getBackendUser(): BackendUserAuthentication { return $GLOBALS['BE_USER']; } }