From 063c2e4286f2f574c6026a7656d0b3b1be2b0769 Mon Sep 17 00:00:00 2001 From: Oliver Hader Date: Thu, 22 Sep 2022 12:52:51 +0200 Subject: [PATCH] [TASK] Prevent undefined array key warnings in ext:filelist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change addresses several "undefined array key" issues that have been identified by PsalmPHP (see issue #98321). Resolves: #98411 Related: #98321 Releases: main, 11.5 Change-Id: Iec52d5b511c8c4af9fa97e3a5081a7a1ac1e5e3d Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75843 Tested-by: core-ci Tested-by: Christian Kuhn Tested-by: Stefan Bürk Tested-by: Oliver Hader Reviewed-by: Oliver Klee Reviewed-by: Christian Kuhn Reviewed-by: Stefan Bürk Reviewed-by: Oliver Hader --- .../TranslationConfigurationProvider.php | 3 ++- .../sysext/core/Classes/Site/Entity/Site.php | 11 +++++++--- .../ItemProviders/FileProvider.php | 2 +- .../Controller/File/EditFileController.php | 2 +- .../Controller/File/RenameFileController.php | 7 ++++--- .../Controller/File/ReplaceFileController.php | 7 ++++--- typo3/sysext/filelist/Classes/FileList.php | 21 ++++++++++++------- 7 files changed, 33 insertions(+), 20 deletions(-) diff --git a/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php b/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php index d908ce4f3435..9c35e4fd45cd 100644 --- a/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php +++ b/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php @@ -29,6 +29,7 @@ /** * Contains translation tools * + * @phpstan-type LanguageRef -1|0|positive-int * @internal The whole class is subject to be removed, fetch all language info from the current site object. */ class TranslationConfigurationProvider @@ -40,7 +41,7 @@ class TranslationConfigurationProvider * The property flagIcon returns a string . * * @param int $pageId Page id (used to get TSconfig configuration setting flag and label for default language) - * @return array Array with languages (uid, title, ISOcode, flagIcon) + * @return array Array with languages */ public function getSystemLanguages($pageId = 0) { diff --git a/typo3/sysext/core/Classes/Site/Entity/Site.php b/typo3/sysext/core/Classes/Site/Entity/Site.php index fe0580077565..5ab7451217f3 100644 --- a/typo3/sysext/core/Classes/Site/Entity/Site.php +++ b/typo3/sysext/core/Classes/Site/Entity/Site.php @@ -35,6 +35,8 @@ /** * Entity representing a single site with available languages + * + * @phpstan-type LanguageRef -1|0|positive-int */ class Site implements SiteInterface { @@ -64,7 +66,7 @@ class Site implements SiteInterface protected $configuration; /** - * @var SiteLanguage[] + * @var array */ protected $languages; @@ -208,7 +210,7 @@ public function getRootPageId(): int /** * Returns all available languages of this site * - * @return SiteLanguage[] + * @return array */ public function getLanguages(): array { @@ -224,7 +226,7 @@ public function getLanguages(): array /** * Returns all available languages of this site, even the ones disabled for frontend usages * - * @return SiteLanguage[] + * @return array */ public function getAllLanguages(): array { @@ -254,6 +256,9 @@ public function getDefaultLanguage(): SiteLanguage return reset($this->languages); } + /** + * @return array + */ public function getAvailableLanguages(BackendUserAuthentication $user, bool $includeAllLanguagesFlag = false, int $pageId = null): array { $availableLanguages = []; diff --git a/typo3/sysext/filelist/Classes/ContextMenu/ItemProviders/FileProvider.php b/typo3/sysext/filelist/Classes/ContextMenu/ItemProviders/FileProvider.php index a1fd896839f6..4780113b1ba1 100644 --- a/typo3/sysext/filelist/Classes/ContextMenu/ItemProviders/FileProvider.php +++ b/typo3/sysext/filelist/Classes/ContextMenu/ItemProviders/FileProvider.php @@ -418,7 +418,7 @@ protected function getAdditionalAttributes(string $itemName): array if ($itemName === 'delete' && $this->backendUser->jsConfirmation(JsConfirmation::DELETE)) { $title = $this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:delete'); - $recordInfo = GeneralUtility::fixed_lgd_cs($this->record->getName(), (int)$this->backendUser->uc['titleLen']); + $recordInfo = GeneralUtility::fixed_lgd_cs($this->record->getName(), (int)($this->backendUser->uc['titleLen'] ?? 0)); if ($this->isFolder()) { if ($this->backendUser->shallDisplayDebugInformation()) { $recordInfo .= ' [' . $this->record->getIdentifier() . ']'; diff --git a/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php b/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php index 1f1da1952283..1eebe30de845 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php @@ -161,7 +161,7 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface $view->assignMultiple([ 'moduleUrlTceFile' => (string)$this->uriBuilder->buildUriFromRoute('tce_file'), 'fileName' => $file->getName(), - 'form' => $formResultCompiler->addCssFiles() . $resultArray['html'] . $formResultCompiler->printNeededJSFunctions(), + 'form' => $formResultCompiler->addCssFiles() . ($resultArray['html'] ?? '') . $formResultCompiler->printNeededJSFunctions(), ]); $content = $view->render('File/EditFile'); diff --git a/typo3/sysext/filelist/Classes/Controller/File/RenameFileController.php b/typo3/sysext/filelist/Classes/Controller/File/RenameFileController.php index 8a1a89ceebe3..be5f4b91e476 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/RenameFileController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/RenameFileController.php @@ -125,10 +125,11 @@ protected function init(ServerRequestInterface $request): void // rename the folder if ($this->fileOrFolderObject instanceof Folder) { $parsedUrl = parse_url($this->returnUrl); - $queryParts = GeneralUtility::explodeUrl2Array(urldecode($parsedUrl['query'])); - if ($queryParts['id'] === $this->fileOrFolderObject->getCombinedIdentifier()) { + $queryParts = GeneralUtility::explodeUrl2Array(urldecode($parsedUrl['query'] ?? '')); + $queryPartsId = $queryParts['id'] ?? null; + if ($queryPartsId === $this->fileOrFolderObject->getCombinedIdentifier()) { $this->returnUrl = str_replace( - urlencode($queryParts['id']), + urlencode($queryPartsId), urlencode($this->fileOrFolderObject->getStorage()->getRootLevelFolder()->getCombinedIdentifier()), $this->returnUrl ); diff --git a/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php b/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php index b296b5aab928..a772ed7fc0d5 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php @@ -117,10 +117,11 @@ protected function init(ServerRequestInterface $request): void // rename the folder if ($this->fileOrFolderObject instanceof Folder) { $parsedUrl = parse_url($this->returnUrl); - $queryParts = GeneralUtility::explodeUrl2Array(urldecode($parsedUrl['query'])); - if ($queryParts['id'] === $this->fileOrFolderObject->getCombinedIdentifier()) { + $queryParts = GeneralUtility::explodeUrl2Array(urldecode($parsedUrl['query'] ?? '')); + $queryPartsId = $queryParts['id'] ?? null; + if ($queryPartsId === $this->fileOrFolderObject->getCombinedIdentifier()) { $this->returnUrl = str_replace( - urlencode($queryParts['id']), + urlencode($queryPartsId), urlencode($this->fileOrFolderObject->getStorage()->getRootLevelFolder()->getCombinedIdentifier()), $this->returnUrl ); diff --git a/typo3/sysext/filelist/Classes/FileList.php b/typo3/sysext/filelist/Classes/FileList.php index d3c39bfaed73..14f6fee766cd 100644 --- a/typo3/sysext/filelist/Classes/FileList.php +++ b/typo3/sysext/filelist/Classes/FileList.php @@ -761,21 +761,24 @@ public function formatFileList(array $files) * Fetch the translations for a sys_file_metadata record * * @param array $metaDataRecord - * @return array keys are the site language ids, values are the $rows + * @return array> keys are the site language ids, values are the $rows */ protected function getTranslationsForMetaData($metaDataRecord) { + $languageField = $GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'] ?? ''; + $languageParentField = $GLOBALS['TCA']['sys_file_metadata']['ctrl']['transOrigPointerField'] ?? ''; + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_metadata'); $queryBuilder->getRestrictions()->removeAll(); $translationRecords = $queryBuilder->select('*') ->from('sys_file_metadata') ->where( $queryBuilder->expr()->eq( - $GLOBALS['TCA']['sys_file_metadata']['ctrl']['transOrigPointerField'], + $languageParentField, $queryBuilder->createNamedParameter($metaDataRecord['uid'] ?? 0, \PDO::PARAM_INT) ), $queryBuilder->expr()->gt( - $GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField'], + $languageField, $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) ) ) @@ -784,7 +787,8 @@ protected function getTranslationsForMetaData($metaDataRecord) $translations = []; foreach ($translationRecords as $record) { - $translations[$record[$GLOBALS['TCA']['sys_file_metadata']['ctrl']['languageField']]] = $record; + $languageId = $record[$languageField]; + $translations[$languageId] = $record; } return $translations; } @@ -1125,7 +1129,7 @@ public function makeEdit($fileOrFolderObject) if (empty($title)) { preg_match('/aria-label="([^"]*)"/', $action, $title); } - if (!empty($title[1] ?? '')) { + if (!empty($title[1])) { $action = str_replace( [ '', @@ -1138,7 +1142,7 @@ public function makeEdit($fileOrFolderObject) ); // In case we added the title as tag content, we can remove the attribute, // since this is duplicated and would trigger a tooltip with the same content. - if (!empty($title[0] ?? '')) { + if (!empty($title[0])) { $action = str_replace($title[0], '', $action); } $cellOutput .= '
  • ' . $action . '
  • '; @@ -1267,12 +1271,13 @@ protected function makeTranslations(File $file): string // Set options for "create new" action of a new translation $title = sprintf($this->getLanguageService()->getLL('createMetadataForLanguage'), $language['title']); $actionType = 'new'; + $metaDataRecordId = (int)($metaDataRecord['uid'] ?? 0); $url = BackendUtility::getLinkToDataHandlerAction( - '&cmd[sys_file_metadata][' . $metaDataRecord['uid'] . '][localize]=' . $languageId, + '&cmd[sys_file_metadata][' . $metaDataRecordId . '][localize]=' . $languageId, (string)$this->uriBuilder->buildUriFromRoute( 'record_edit', [ - 'justLocalized' => 'sys_file_metadata:' . $metaDataRecord['uid'] . ':' . $languageId, + 'justLocalized' => 'sys_file_metadata:' . $metaDataRecordId . ':' . $languageId, 'returnUrl' => $this->listURL(), ] )