From 30755cfdbd7695aa5f315dd7c09562f287381872 Mon Sep 17 00:00:00 2001
From: Alexander Schnitzler <git@alexanderschnitzler.de>
Date: Mon, 11 May 2020 17:33:41 +0200
Subject: [PATCH] [TASK] Fix phpstan checkFunctionArgumentTypes errors in
 ext:core Database

This patch fixes incompatible type usage in function arguments
and is preparatory work for introducing native type hints and
strict mode in all core files.

Releases: master, 10.4
Resolves: #92273
Change-Id: Ifb45f980a08efd79f5e3f288e0f20e1ac283e1f0
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65664
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 phpstan.neon                                  | 91 +++++++++++++++++++
 .../Query/Expression/ExpressionBuilder.php    |  4 +-
 .../Classes/Database/Query/QueryHelper.php    |  6 +-
 .../core/Classes/Database/ReferenceIndex.php  |  6 +-
 .../core/Classes/Database/RelationHandler.php | 29 +++---
 .../Database/Schema/ConnectionMigrator.php    | 14 ++-
 .../SchemaColumnDefinitionListener.php        |  6 +-
 .../SchemaIndexDefinitionListener.php         |  2 +-
 .../Classes/Database/Schema/Parser/Parser.php | 10 +-
 .../Classes/Database/Schema/SqlReader.php     |  4 +-
 .../Classes/Database/SoftReferenceIndex.php   |  4 +-
 11 files changed, 139 insertions(+), 37 deletions(-)

diff --git a/phpstan.neon b/phpstan.neon
index 255d7ff7b1e6..cf80b7da6935 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -160,3 +160,94 @@ parameters:
       message: "#^Instanceof between TYPO3\\\\CMS\\\\Core\\\\Resource\\\\File and TYPO3\\\\CMS\\\\Core\\\\Resource\\\\FileReference will always evaluate to false\\.$#"
       count: 1
       path: typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
+
+    # Ignored errors for level 5
+    -
+      message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, string given\\.$#"
+      count: 2
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#1 \\$input of function array_slice expects array, string given\\.$#"
+      count: 2
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#1 \\$stack of function array_shift expects array, string given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, string given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#3 \\.\\.\\.\\$args of function array_merge expects array, string given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$suffix of method TYPO3\\\\CMS\\\\Core\\\\Database\\\\QueryGenerator\\:\\:cleanInputVal\\(\\) expects string, int given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#3 \\$draw of method TYPO3\\\\CMS\\\\Core\\\\Database\\\\QueryGenerator\\:\\:mkOperatorSelect\\(\\) expects bool, int given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$first of method TYPO3\\\\CMS\\\\Core\\\\Database\\\\QueryGenerator\\:\\:getQuerySingle\\(\\) expects bool, int given\\.$#"
+      count: 2
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$item of static method TYPO3\\\\CMS\\\\Core\\\\Utility\\\\GeneralUtility\\:\\:inList\\(\\) expects string, \\(float\\|int\\) given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$first of method TYPO3\\\\CMS\\\\Core\\\\Database\\\\QueryGenerator\\:\\:getUserDefQuery\\(\\) expects bool, int given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$time of static method DateTime\\:\\:createFromFormat\\(\\) expects string, int\\|string given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$replace of function str_replace expects array\\|string, int given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#1 \\$str of function trim expects string, array\\|string given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$timestamp of function date expects int, int\\|false given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryGenerator.php
+
+    -
+      message: "#^Parameter \\#2 \\$storeIndex of method TYPO3\\\\CMS\\\\Core\\\\Database\\\\QueryView\\:\\:loadStoreQueryConfigs\\(\\) expects int, string given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryView.php
+
+    -
+      message: "#^Parameter \\#2 \\$index of method TYPO3\\\\CMS\\\\Core\\\\Database\\\\QueryView\\:\\:addToStoreQueryConfigs\\(\\) expects int, int\\|string\\|null given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryView.php
+
+    -
+      message: "#^Parameter \\#2 \\$timestamp of function strftime expects int, string given\\.$#"
+      count: 3
+      path: typo3/sysext/core/Classes/Database/QueryView.php
+
+    -
+      message: "#^Parameter \\#1 \\$constraint of static method TYPO3\\\\CMS\\\\Core\\\\Database\\\\Query\\\\QueryHelper\\:\\:stripLogicalOperatorPrefix\\(\\) expects string, string\\|null given\\.$#"
+      count: 1
+      path: typo3/sysext/core/Classes/Database/QueryView.php
diff --git a/typo3/sysext/core/Classes/Database/Query/Expression/ExpressionBuilder.php b/typo3/sysext/core/Classes/Database/Query/Expression/ExpressionBuilder.php
index 4401243f9b29..6d384c682146 100644
--- a/typo3/sysext/core/Classes/Database/Query/Expression/ExpressionBuilder.php
+++ b/typo3/sysext/core/Classes/Database/Query/Expression/ExpressionBuilder.php
@@ -64,7 +64,7 @@ class ExpressionBuilder
     /**
      * Creates a conjunction of the given boolean expressions
      *
-     * @param array<int,mixed> $expressions Optional clause. Requires at least one defined when converting to string.
+     * @param string ...$expressions Optional clause. Requires at least one defined when converting to string.
      *
      * @return CompositeExpression
      */
@@ -76,7 +76,7 @@ class ExpressionBuilder
     /**
      * Creates a disjunction of the given boolean expressions.
      *
-     * @param array<int,mixed> $expressions Optional clause. Requires at least one defined when converting to string.
+     * @param string ...$expressions Optional clause. Requires at least one defined when converting to string.
      *
      * @return CompositeExpression
      */
diff --git a/typo3/sysext/core/Classes/Database/Query/QueryHelper.php b/typo3/sysext/core/Classes/Database/Query/QueryHelper.php
index a4fc30dca06f..6d8bde9d7d5d 100644
--- a/typo3/sysext/core/Classes/Database/Query/QueryHelper.php
+++ b/typo3/sysext/core/Classes/Database/Query/QueryHelper.php
@@ -125,9 +125,9 @@ class QueryHelper
             $tableName = strtok($input, $quoteCharacter);
         }
 
-        $tableAlias = strtok($quoteCharacter);
+        $tableAlias = (string)strtok($quoteCharacter);
         if (strtolower($tableAlias) === 'as') {
-            $tableAlias = strtok($quoteCharacter);
+            $tableAlias = (string)strtok($quoteCharacter);
             // Skip the next token which must be ON
             strtok(' ');
             $joinCondition = strtok('');
@@ -145,7 +145,7 @@ class QueryHelper
         // that the quoted table alias contains whitespace.
         $firstCharacterOfTableAlias = $tableAlias[0] ?? null;
         if ($firstCharacterOfTableAlias === '`' || $firstCharacterOfTableAlias === '"') {
-            $tableAlias = substr($tableAlias, 1, -1);
+            $tableAlias = substr((string)$tableAlias, 1, -1);
         }
 
         $tableAlias = $tableAlias ?: $tableName;
diff --git a/typo3/sysext/core/Classes/Database/ReferenceIndex.php b/typo3/sysext/core/Classes/Database/ReferenceIndex.php
index 291125dd4d3b..7c01f147c455 100644
--- a/typo3/sysext/core/Classes/Database/ReferenceIndex.php
+++ b/typo3/sysext/core/Classes/Database/ReferenceIndex.php
@@ -454,7 +454,7 @@ class ReferenceIndex implements LoggerAwareInterface
         }
         return $this->createEntryDataUsingRecord(
             (string)$table,
-            $this->getRecordRawCached($table, $uid),
+            $this->getRecordRawCached($table, $uid) ?: [],
             (string)$field,
             (string)$flexPointer,
             $deleted ? (int)$deleted : 0,
@@ -527,7 +527,7 @@ class ReferenceIndex implements LoggerAwareInterface
         }
         $this->createEntryDataForDatabaseRelationsUsingRecord(
             (string)$table,
-            $this->getRecordRawCached($table, $uid),
+            $this->getRecordRawCached($table, $uid) ?: [],
             (string)$fieldName,
             (string)$flexPointer,
             $deleted ? (int)$deleted : 0,
@@ -570,7 +570,7 @@ class ReferenceIndex implements LoggerAwareInterface
         }
         $this->createEntryDataForSoftReferencesUsingRecord(
             (string)$table,
-            $this->getRecordRawCached($table, $uid),
+            $this->getRecordRawCached($table, $uid) ?: [],
             (string)$fieldName,
             (string)$flexPointer,
             $deleted ? (int)$deleted : 0,
diff --git a/typo3/sysext/core/Classes/Database/RelationHandler.php b/typo3/sysext/core/Classes/Database/RelationHandler.php
index fdf32c14faa4..979325a7288d 100644
--- a/typo3/sysext/core/Classes/Database/RelationHandler.php
+++ b/typo3/sysext/core/Classes/Database/RelationHandler.php
@@ -58,7 +58,7 @@ class RelationHandler
     /**
      * Contains items in a numeric array (table/id for each). Tablenames here might be "_NO_TABLE"
      *
-     * @var array
+     * @var array<int, array<string, mixed>>
      */
     public $itemArray = [];
 
@@ -494,7 +494,7 @@ class RelationHandler
             );
         } elseif (count($this->tableArray) === 1) {
             reset($this->tableArray);
-            $table = key($this->tableArray);
+            $table = (string)key($this->tableArray);
             $connection = $this->getConnectionForTableName($table);
             $maxBindParameters = PlatformInformation::getMaxBindParameters($connection->getDatabasePlatform());
 
@@ -578,7 +578,7 @@ class RelationHandler
         }
         if ($this->MM_table_where) {
             $queryBuilder->andWhere(
-                QueryHelper::stripLogicalOperatorPrefix(str_replace('###THIS_UID###', (int)$uid, $this->MM_table_where))
+                QueryHelper::stripLogicalOperatorPrefix(str_replace('###THIS_UID###', (string)$uid, $this->MM_table_where))
             );
         }
         foreach ($this->MM_match_fields as $field => $value) {
@@ -654,7 +654,7 @@ class RelationHandler
             if ($this->MM_table_where) {
                 $additionalWhere->add(
                     QueryHelper::stripLogicalOperatorPrefix(
-                        str_replace('###THIS_UID###', (int)$uid, $this->MM_table_where)
+                        str_replace('###THIS_UID###', (string)$uid, $this->MM_table_where)
                     )
                 );
             }
@@ -896,7 +896,7 @@ class RelationHandler
             // Add WHERE clause if configured
             if ($this->MM_table_where) {
                 $queryBuilder->andWhere(
-                    QueryHelper::stripLogicalOperatorPrefix(str_replace('###THIS_UID###', (int)$uid, $this->MM_table_where))
+                    QueryHelper::stripLogicalOperatorPrefix(str_replace('###THIS_UID###', (string)$uid, $this->MM_table_where))
                 );
             }
             // Select, update or delete only those relations that match the configured fields
@@ -1030,7 +1030,7 @@ class RelationHandler
         $rows = [];
         $result = $queryBuilder->execute();
         while ($row = $result->fetch()) {
-            $rows[$row['uid']] = $row;
+            $rows[(int)$row['uid']] = $row;
         }
         if (!empty($rows)) {
             // Retrieve the parsed and prepared ORDER BY configuration for the resolver
@@ -1098,7 +1098,7 @@ class RelationHandler
                 }
                 $isOnSymmetricSide = false;
                 if ($symmetric_field) {
-                    $isOnSymmetricSide = self::isOnSymmetricSide($parentUid, $conf, $row);
+                    $isOnSymmetricSide = self::isOnSymmetricSide((string)$parentUid, $conf, $row);
                 }
                 $updateValues = $foreign_match_fields;
                 // No update to the uid is requested, so this is the normal behaviour
@@ -1426,7 +1426,7 @@ class RelationHandler
     /**
      * Handles a purge callback on $this->itemArray
      *
-     * @param callable $purgeCallback
+     * @param string $purgeCallback
      * @return bool Whether items have been purged
      */
     protected function purgeItemArrayHandler($purgeCallback)
@@ -1438,7 +1438,12 @@ class RelationHandler
                 continue;
             }
 
-            $purgedItemIds = call_user_func([$this, $purgeCallback], $itemTableName, $itemIds);
+            $purgedItemIds = [];
+            $callable =[$this, $purgeCallback];
+            if (is_callable($callable)) {
+                $purgedItemIds = call_user_func($callable, $itemTableName, $itemIds);
+            }
+
             $removedItemIds = array_diff($itemIds, $purgedItemIds);
             foreach ($removedItemIds as $removedItemId) {
                 $this->removeFromItemArray($itemTableName, $removedItemId);
@@ -1462,7 +1467,7 @@ class RelationHandler
     protected function purgeVersionedIds($tableName, array $ids)
     {
         $ids = $this->sanitizeIds($ids);
-        $ids = array_combine($ids, $ids);
+        $ids = (array)array_combine($ids, $ids);
         $connection = $this->getConnectionForTableName($tableName);
         $maxBindParameters = PlatformInformation::getMaxBindParameters($connection->getDatabasePlatform());
 
@@ -1505,7 +1510,7 @@ class RelationHandler
     protected function purgeLiveVersionedIds($tableName, array $ids)
     {
         $ids = $this->sanitizeIds($ids);
-        $ids = array_combine($ids, $ids);
+        $ids = (array)array_combine($ids, $ids);
         $connection = $this->getConnectionForTableName($tableName);
         $maxBindParameters = PlatformInformation::getMaxBindParameters($connection->getDatabasePlatform());
 
@@ -1549,7 +1554,7 @@ class RelationHandler
     protected function purgeDeletePlaceholder($tableName, array $ids)
     {
         $ids = $this->sanitizeIds($ids);
-        $ids = array_combine($ids, $ids);
+        $ids = array_combine($ids, $ids) ?: [];
         $connection = $this->getConnectionForTableName($tableName);
         $maxBindParameters = PlatformInformation::getMaxBindParameters($connection->getDatabasePlatform());
 
diff --git a/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php b/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php
index 1a52f1984d27..67bc45567e7c 100644
--- a/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php
+++ b/typo3/sysext/core/Classes/Database/Schema/ConnectionMigrator.php
@@ -164,7 +164,7 @@ class ConnectionMigrator
                     $indexColumns = array_map(
                         function ($columnName) {
                             // Strip MySQL prefix length information to get real column names
-                            $columnName = preg_replace('/\(\d+\)$/', '', $columnName);
+                            $columnName = preg_replace('/\(\d+\)$/', '', $columnName) ?? '';
                             // Strip mssql '[' and ']' from column names
                             $columnName = ltrim($columnName, '[');
                             $columnName = rtrim($columnName, ']');
@@ -252,6 +252,7 @@ class ConnectionMigrator
 
         // Collect the table names that have been mapped to this connection.
         $connectionName = $this->connectionName;
+        /** @var string[] $tablesForConnection */
         $tablesForConnection = array_keys(
             array_filter(
                 $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'],
@@ -575,7 +576,9 @@ class ConnectionMigrator
                         continue;
                     }
 
-                    $changedColumn->fromColumn = $this->buildQuotedColumn($changedColumn->fromColumn);
+                    if ($changedColumn->fromColumn !== null) {
+                        $changedColumn->fromColumn = $this->buildQuotedColumn($changedColumn->fromColumn);
+                    }
 
                     // Get the current SQL declaration for the column
                     $currentColumn = $fromTable->getColumn($changedColumn->getOldColumnName()->getName());
@@ -823,6 +826,9 @@ class ConnectionMigrator
                 // Treat each removed foreign key with a new diff to get a dedicated suggestions
                 // just for this foreign key.
                 foreach ($changedTable->removedForeignKeys as $removedForeignKey) {
+                    if (is_string($removedForeignKey)) {
+                        continue;
+                    }
                     $fkIndex = $index . ':fk_' . $removedForeignKey->getName();
                     $changedTables[$fkIndex] = GeneralUtility::makeInstance(
                         TableDiff::class,
@@ -1081,9 +1087,9 @@ class ConnectionMigrator
     /**
      * Helper for buildSchemaDiff to filter an array of TableDiffs against a list of valid table names.
      *
-     * @param TableDiff[]|Table[] $tableDiffs
+     * @param \Doctrine\DBAL\Schema\TableDiff[]|Table[] $tableDiffs
      * @param string[] $validTableNames
-     * @return TableDiff[]
+     * @return \Doctrine\DBAL\Schema\TableDiff[]
      * @throws \InvalidArgumentException
      */
     protected function removeUnrelatedTables(array $tableDiffs, array $validTableNames): array
diff --git a/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaColumnDefinitionListener.php b/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaColumnDefinitionListener.php
index 2625393d5cb4..3c77a763b5b5 100644
--- a/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaColumnDefinitionListener.php
+++ b/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaColumnDefinitionListener.php
@@ -106,7 +106,7 @@ class SchemaColumnDefinitionListener
      */
     protected function getUnquotedEnumerationValues(string $typeDefinition): array
     {
-        $valuesDefinition = preg_replace('#^(enum|set)\((.*)\)\s*$#i', '$2', $typeDefinition);
+        $valuesDefinition = preg_replace('#^(enum|set)\((.*)\)\s*$#i', '$2', $typeDefinition) ?? '';
         $quoteChar = $valuesDefinition[0];
         $separator = $quoteChar . ',' . $quoteChar;
 
@@ -114,9 +114,9 @@ class SchemaColumnDefinitionListener
             '#' . $quoteChar . ',\s*' . $quoteChar . '#',
             $separator,
             $valuesDefinition
-        );
+        ) ?? '';
 
-        $values = explode($quoteChar . ',' . $quoteChar, substr($valuesDefinition, 1, -1));
+        $values = explode($quoteChar . ',' . $quoteChar, substr($valuesDefinition, 1, -1)) ?: [];
 
         return array_map(
             function (string $value) use ($quoteChar) {
diff --git a/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaIndexDefinitionListener.php b/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaIndexDefinitionListener.php
index 5c3f8cd5b518..a52cbdafab19 100644
--- a/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaIndexDefinitionListener.php
+++ b/typo3/sysext/core/Classes/Database/Schema/EventListener/SchemaIndexDefinitionListener.php
@@ -38,7 +38,7 @@ class SchemaIndexDefinitionListener
      */
     public function onSchemaIndexDefinition(SchemaIndexDefinitionEventArgs $event)
     {
-        if (strpos($event->getConnection()->getServerVersion(), 'MySQL') !== 0) {
+        if (strpos((string)$event->getConnection()->getServerVersion(), 'MySQL') !== 0) {
             return;
         }
 
diff --git a/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php b/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php
index 6853d266cce2..ab4819a98f8a 100644
--- a/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php
+++ b/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php
@@ -135,12 +135,12 @@ class Parser
         if ($lookaheadType !== $token) {
             // If parameter is not identifier (1-99) must be exact match
             if ($token < Lexer::T_IDENTIFIER) {
-                $this->syntaxError($this->lexer->getLiteral($token));
+                $this->syntaxError((string)$this->lexer->getLiteral($token));
             }
 
             // If parameter is keyword (200+) must be exact match
             if ($token > Lexer::T_IDENTIFIER) {
-                $this->syntaxError($this->lexer->getLiteral($token));
+                $this->syntaxError((string)$this->lexer->getLiteral($token));
             }
 
             // If parameter is MATCH then FULL, PARTIAL or SIMPLE must follow
@@ -149,11 +149,11 @@ class Parser
                 && $lookaheadType !== Lexer::T_PARTIAL
                 && $lookaheadType !== Lexer::T_SIMPLE
             ) {
-                $this->syntaxError($this->lexer->getLiteral($token));
+                $this->syntaxError((string)$this->lexer->getLiteral($token));
             }
 
             if ($token === Lexer::T_ON && $lookaheadType !== Lexer::T_DELETE && $lookaheadType !== Lexer::T_UPDATE) {
-                $this->syntaxError($this->lexer->getLiteral($token));
+                $this->syntaxError((string)$this->lexer->getLiteral($token));
             }
         }
 
@@ -239,7 +239,7 @@ class Parser
     public function semanticalError($message = '', $token = null)
     {
         if ($token === null) {
-            $token = $this->lexer->lookahead;
+            $token = $this->lexer->lookahead ?? [];
         }
 
         // Minimum exposed chars ahead of token
diff --git a/typo3/sysext/core/Classes/Database/Schema/SqlReader.php b/typo3/sysext/core/Classes/Database/Schema/SqlReader.php
index a42fdb3b4758..9a1d9d120632 100644
--- a/typo3/sysext/core/Classes/Database/Schema/SqlReader.php
+++ b/typo3/sysext/core/Classes/Database/Schema/SqlReader.php
@@ -64,10 +64,10 @@ class SqlReader
         foreach ($this->packageManager->getActivePackages() as $package) {
             $packagePath = $package->getPackagePath();
             if (@file_exists($packagePath . 'ext_tables.sql')) {
-                $sqlString[] = file_get_contents($packagePath . 'ext_tables.sql');
+                $sqlString[] = (string)file_get_contents($packagePath . 'ext_tables.sql');
             }
             if ($withStatic && @file_exists($packagePath . 'ext_tables_static+adt.sql')) {
-                $sqlString[] = file_get_contents($packagePath . 'ext_tables_static+adt.sql');
+                $sqlString[] = (string)file_get_contents($packagePath . 'ext_tables_static+adt.sql');
             }
         }
 
diff --git a/typo3/sysext/core/Classes/Database/SoftReferenceIndex.php b/typo3/sysext/core/Classes/Database/SoftReferenceIndex.php
index fccfc54e2fc7..6fa54017d646 100644
--- a/typo3/sysext/core/Classes/Database/SoftReferenceIndex.php
+++ b/typo3/sysext/core/Classes/Database/SoftReferenceIndex.php
@@ -395,10 +395,10 @@ class SoftReferenceIndex implements SingletonInterface
     {
         $elements = [];
         // Files starting with EXT:
-        $parts = preg_split('/([^[:alnum:]"\']+)(EXT:[[:alnum:]_]+\\/[^[:space:]"\',]*)/', ' ' . $content . ' ', 10000, PREG_SPLIT_DELIM_CAPTURE);
+        $parts = preg_split('/([^[:alnum:]"\']+)(EXT:[[:alnum:]_]+\\/[^[:space:]"\',]*)/', ' ' . $content . ' ', 10000, PREG_SPLIT_DELIM_CAPTURE) ?: [];
         foreach ($parts as $idx => $value) {
             if ($idx % 3 == 2) {
-                $this->makeTokenID($idx);
+                $this->makeTokenID((string)$idx);
                 $elements[$idx] = [];
                 $elements[$idx]['matchString'] = $value;
             }
-- 
GitLab