From 051f1e1d2ec2bf6b7e5640133d452b58f11e273e Mon Sep 17 00:00:00 2001
From: Oliver Klee <typo3-coding@oliverklee.de>
Date: Tue, 5 Jul 2022 12:07:18 +0200
Subject: [PATCH] [BUGFIX] Fix type annotations concerning storage folder
 identifiers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Storage folder identifiers can also be int-like strings, which causes
them to automatically get cast to int when used as array keys.

Our types annotations need to reflect this in order to keep developers
and static analysis for taking those array keys to be always strings
(which can lead to type errors and has recently done so).

Resolves: #97858
Relates: #97851
Relates: #97711
Releases: main, 11.5
Change-Id: If0fbfab5792446cfe10564803d8d540dd3cc6bb5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75033
Tested-by: Nikita Hovratov <nikita.h@live.de>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Simon Schaufelberger <simonschaufi+typo3@gmail.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Nikita Hovratov <nikita.h@live.de>
Reviewed-by: Simon Schaufelberger <simonschaufi+typo3@gmail.com>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
---
 .../core/Classes/Resource/Driver/DriverInterface.php       | 3 ++-
 typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php  | 7 +++++--
 typo3/sysext/core/Classes/Resource/Folder.php              | 4 +---
 typo3/sysext/core/Classes/Resource/FolderInterface.php     | 4 +---
 typo3/sysext/core/Classes/Resource/ResourceStorage.php     | 3 ++-
 typo3/sysext/core/Classes/Resource/Utility/ListUtility.php | 2 +-
 6 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/typo3/sysext/core/Classes/Resource/Driver/DriverInterface.php b/typo3/sysext/core/Classes/Resource/Driver/DriverInterface.php
index c522cb758b39..78d04e5ebf21 100644
--- a/typo3/sysext/core/Classes/Resource/Driver/DriverInterface.php
+++ b/typo3/sysext/core/Classes/Resource/Driver/DriverInterface.php
@@ -437,7 +437,8 @@ interface DriverInterface
      *                     If a driver does not support the given property, it
      *                     should fall back to "name".
      * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
-     * @return array of Folder Identifier
+     * @return array<string|int, string> folder identifiers (where key and value are identical, but int-like identifiers
+     *         will get converted to int array keys)
      */
     public function getFoldersInFolder($folderIdentifier, $start = 0, $numberOfItems = 0, $recursive = false, array $folderNameFilterCallbacks = [], $sort = '', $sortRev = false);
 
diff --git a/typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php b/typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php
index cc934127817a..b2d85a9d1593 100644
--- a/typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php
+++ b/typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php
@@ -356,7 +356,8 @@ class LocalDriver extends AbstractHierarchicalFilesystemDriver implements Stream
      *                     If a driver does not support the given property, it
      *                     should fall back to "name".
      * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
-     * @return array
+     * @return array<string|int, string> folder identifiers (where key and value are identical, but int-like identifiers
+     *         will get converted to int array keys)
      * @throws \InvalidArgumentException
      */
     protected function getDirectoryItemList($folderIdentifier, $start, $numberOfItems, array $filterMethods, $includeFiles = true, $includeDirs = true, $recursive = false, $sort = '', $sortRev = false)
@@ -399,6 +400,7 @@ class LocalDriver extends AbstractHierarchicalFilesystemDriver implements Stream
                 if ($start > 0) {
                     $start--;
                 } else {
+                    // The identifier can also be an int-like string, resulting in int array keys.
                     $items[$iteratorItem['identifier']] = $iteratorItem['identifier'];
                     // Decrement item counter to make sure we only return $numberOfItems
                     // we cannot do this earlier in the method (unlike moving the iterator forward) because we only add the
@@ -503,7 +505,8 @@ class LocalDriver extends AbstractHierarchicalFilesystemDriver implements Stream
      *                     If a driver does not support the given property, it
      *                     should fall back to "name".
      * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
-     * @return array of Folder Identifier
+     * @return array<string|int, string> folder identifiers (where key and value are identical, but int-like identifiers
+     *         will get converted to int array keys)
      */
     public function getFoldersInFolder($folderIdentifier, $start = 0, $numberOfItems = 0, $recursive = false, array $folderNameFilterCallbacks = [], $sort = '', $sortRev = false)
     {
diff --git a/typo3/sysext/core/Classes/Resource/Folder.php b/typo3/sysext/core/Classes/Resource/Folder.php
index a547cc694dc0..20d37cb6f94c 100644
--- a/typo3/sysext/core/Classes/Resource/Folder.php
+++ b/typo3/sysext/core/Classes/Resource/Folder.php
@@ -282,13 +282,11 @@ class Folder implements FolderInterface
     }
 
     /**
-     * Returns a list of subfolders
-     *
      * @param int $start The item to start at
      * @param int $numberOfItems The number of items to return
      * @param int $filterMode The filter mode to use for the filelist.
      * @param bool $recursive
-     * @return Folder[]
+     * @return array<string|int, Folder>
      */
     public function getSubfolders($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive = false)
     {
diff --git a/typo3/sysext/core/Classes/Resource/FolderInterface.php b/typo3/sysext/core/Classes/Resource/FolderInterface.php
index 59ca1d43d157..aaed937479d1 100644
--- a/typo3/sysext/core/Classes/Resource/FolderInterface.php
+++ b/typo3/sysext/core/Classes/Resource/FolderInterface.php
@@ -33,9 +33,7 @@ interface FolderInterface extends ResourceInterface
     const ROLE_USER_MOUNT = 'user-mount';
 
     /**
-     * Returns a list of all subfolders
-     *
-     * @return Folder[]
+     * @return array<string|int, Folder>
      */
     public function getSubfolders();
 
diff --git a/typo3/sysext/core/Classes/Resource/ResourceStorage.php b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
index 246b2f08a8f5..0de4937d9c77 100644
--- a/typo3/sysext/core/Classes/Resource/ResourceStorage.php
+++ b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
@@ -2427,7 +2427,7 @@ class ResourceStorage implements ResourceStorageInterface
      *                     If a driver does not support the given property, it
      *                     should fall back to "name".
      * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
-     * @return Folder[]
+     * @return array<string|int, Folder>
      */
     public function getFoldersInFolder(Folder $folder, $start = 0, $maxNumberOfItems = 0, $useFilters = true, $recursive = false, $sort = '', $sortRev = false)
     {
@@ -2445,6 +2445,7 @@ class ResourceStorage implements ResourceStorageInterface
 
         $folders = [];
         foreach ($folderIdentifiers as $folderIdentifier) {
+            // The folder identifier can also be an int-like string, resulting in int array keys.
             $folders[$folderIdentifier] = $this->getFolder($folderIdentifier, true);
         }
         return $folders;
diff --git a/typo3/sysext/core/Classes/Resource/Utility/ListUtility.php b/typo3/sysext/core/Classes/Resource/Utility/ListUtility.php
index b5a6530c6e40..4809e973ec98 100644
--- a/typo3/sysext/core/Classes/Resource/Utility/ListUtility.php
+++ b/typo3/sysext/core/Classes/Resource/Utility/ListUtility.php
@@ -28,7 +28,7 @@ class ListUtility
      * Resolve special folders (by their role) into localised string
      *
      * @param Folder[] $folders
-     * @return array<string, Folder> array with Folders using the Folder name (with our without role) as key
+     * @return array<string|int, Folder> Folders using the Folder name (with or without role) as key
      */
     public static function resolveSpecialFolderNames(array $folders)
     {
-- 
GitLab