From bfb42cdae1325f46a2cbcb4e54593b13e91f2bff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rn=20Wagner?= <joern.wagner@explicatis.com>
Date: Mon, 21 Dec 2020 20:54:08 +0100
Subject: [PATCH] [TASK] Make first install compatible with PHP 8

Make all the necessary changes to classes used during the first installation to run on PHP 8

Resolves: #93205
Releases: master, 10.4
Change-Id: I93f64b2848e4cea76a4f36d11d394cb09fd8301c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67227
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Benni Mack <benni@typo3.org>
Tested-by: Benjamin Franzke <bfr@qbus.de>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Benjamin Franzke <bfr@qbus.de>
---
 Build/Scripts/duplicateExceptionCodeCheck.sh  |  1 +
 phpstan.neon                                  |  3 +
 .../Classes/Database/Driver/PDOStatement.php  | 24 ++-----
 .../Driver/PDOStatementImplementation.php     | 64 +++++++++++++++++++
 .../core/Classes/Error/ErrorHandler.php       |  8 +--
 .../ConditionMatching/ConditionMatcher.php    |  2 +-
 .../Classes/SystemEnvironment/Check.php       | 11 +++-
 7 files changed, 86 insertions(+), 27 deletions(-)
 create mode 100644 typo3/sysext/core/Classes/Database/Driver/PDOStatementImplementation.php

diff --git a/Build/Scripts/duplicateExceptionCodeCheck.sh b/Build/Scripts/duplicateExceptionCodeCheck.sh
index 7fcaf88b534b..5a152e8fd716 100755
--- a/Build/Scripts/duplicateExceptionCodeCheck.sh
+++ b/Build/Scripts/duplicateExceptionCodeCheck.sh
@@ -19,6 +19,7 @@ ignoreFiles+="sysext/core/Tests/Acceptance/Support/_generated/InstallTesterActio
 ignoreFiles+="sysext/extbase/Classes/Core/Bootstrap.php"
 ignoreFiles+="sysext/form/Classes/Mvc/Property/Exception/TypeConverterException.php"
 ignoreFiles+="sysext/core/Classes/Database/Driver/PDOStatement.php"
+ignoreFiles+="sysext/core/Classes/Database/Driver/PDOStatementImplementation.php"
 ignoreFiles+="sysext/core/Classes/Database/Driver/PDOConnection.php"
 ignoreFiles+="sysext/frontend/Classes/Typolink/PageLinkBuilder.php"
 ignoreFiles+="sysext/backend/Classes/Middleware/BackendUserAuthenticator.php"
diff --git a/phpstan.neon b/phpstan.neon
index cf80b7da6935..261a9d94d35c 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -28,6 +28,9 @@ parameters:
     - %currentWorkingDirectory%/typo3/sysext/*/Configuration/*
 
   ignoreErrors:
+    # PHP8 compatibility, as phpstan cannot detect this yet.
+    - "#Class GdImage not found.#"
+
     # ignored errors for level 0
     - '#Variable \$_EXTKEY might not be defined\.#'
     -
diff --git a/typo3/sysext/core/Classes/Database/Driver/PDOStatement.php b/typo3/sysext/core/Classes/Database/Driver/PDOStatement.php
index 554998ece1ee..77e27807377a 100644
--- a/typo3/sysext/core/Classes/Database/Driver/PDOStatement.php
+++ b/typo3/sysext/core/Classes/Database/Driver/PDOStatement.php
@@ -23,6 +23,12 @@ use PDO;
 
 class PDOStatement extends DoctrineDbalPDOStatement
 {
+    /**
+     * The method fetchAll() is moved into a separate trait to switch method signatures
+     * depending on the PHP major version in use to support PHP8
+     */
+    use PDOStatementImplementation;
+
     /**
      * Map resources to string like is done for e.g. in mysqli driver
      *
@@ -61,24 +67,6 @@ class PDOStatement extends DoctrineDbalPDOStatement
         }
     }
 
-    /**
-     * {@inheritdoc}
-     */
-    public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
-    {
-        try {
-            $records = parent::fetchAll($fetchMode, $fetchArgument, $ctorArgs);
-
-            if ($records !== false) {
-                $records = array_map([$this, 'mapResourceToString'], $records);
-            }
-
-            return $records;
-        } catch (\PDOException $exception) {
-            throw new PDOException($exception);
-        }
-    }
-
     /**
      * {@inheritdoc}
      */
diff --git a/typo3/sysext/core/Classes/Database/Driver/PDOStatementImplementation.php b/typo3/sysext/core/Classes/Database/Driver/PDOStatementImplementation.php
new file mode 100644
index 000000000000..2bda74a5f9bf
--- /dev/null
+++ b/typo3/sysext/core/Classes/Database/Driver/PDOStatementImplementation.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Database\Driver;
+
+use Doctrine\DBAL\Driver\PDO\Exception as PDOException;
+
+if (PHP_VERSION_ID >= 80000) {
+    trait PDOStatementImplementation
+    {
+        /**
+         * {@inheritdoc}
+         */
+        public function fetchAll($mode = null, ...$args)
+        {
+            try {
+                $records = parent::fetchAll($mode, ...$args);
+
+                if ($records !== false) {
+                    $records = array_map([$this, 'mapResourceToString'], $records);
+                }
+
+                return $records;
+            } catch (\PDOException $exception) {
+                throw new PDOException($exception);
+            }
+        }
+    }
+} else {
+    trait PDOStatementImplementation
+    {
+        /**
+         * {@inheritdoc}
+         */
+        public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
+        {
+            try {
+                $records = parent::fetchAll($fetchMode, $fetchArgument, $ctorArgs);
+
+                if ($records !== false) {
+                    $records = array_map([$this, 'mapResourceToString'], $records);
+                }
+
+                return $records;
+            } catch (\PDOException $exception) {
+                throw new PDOException($exception);
+            }
+        }
+    }
+}
diff --git a/typo3/sysext/core/Classes/Error/ErrorHandler.php b/typo3/sysext/core/Classes/Error/ErrorHandler.php
index 05d3e5e7a80a..5a79c6111d4e 100644
--- a/typo3/sysext/core/Classes/Error/ErrorHandler.php
+++ b/typo3/sysext/core/Classes/Error/ErrorHandler.php
@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Core\Error;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Http\ApplicationType;
 use TYPO3\CMS\Core\Log\LogLevel;
@@ -252,11 +253,8 @@ class ErrorHandler implements ErrorHandlerInterface, LoggerAwareInterface
         return GeneralUtility::makeInstance(TimeTracker::class);
     }
 
-    /**
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
-     */
-    protected function getBackendUser()
+    protected function getBackendUser(): ?BackendUserAuthentication
     {
-        return $GLOBALS['BE_USER'];
+        return $GLOBALS['BE_USER'] ?? null;
     }
 }
diff --git a/typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php b/typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
index e09b543e2580..62971b07aeff 100644
--- a/typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
+++ b/typo3/sysext/frontend/Classes/Configuration/TypoScript/ConditionMatching/ConditionMatcher.php
@@ -42,7 +42,7 @@ class ConditionMatcher extends AbstractConditionMatcher
     {
         $this->context = $context ?? GeneralUtility::makeInstance(Context::class);
         $this->pageId = $pageId;
-        $this->rootline = $rootLine ?? (array)$GLOBALS['TSFE']->tmpl->rootLine;
+        $this->rootline = $rootLine ?? (array)$GLOBALS['TSFE']->tmpl->rootLine ?? null;
         $this->initializeExpressionLanguageResolver();
     }
 
diff --git a/typo3/sysext/install/Classes/SystemEnvironment/Check.php b/typo3/sysext/install/Classes/SystemEnvironment/Check.php
index 6029a1eee01b..7a565f35bc29 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/Check.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/Check.php
@@ -642,7 +642,7 @@ class Check implements CheckInterface
     {
         if (function_exists('imagecreatetruecolor')) {
             $imageResource = @imagecreatetruecolor(50, 100);
-            if (is_resource($imageResource)) {
+            if ($this->checkImageResource($imageResource)) {
                 imagedestroy($imageResource);
                 $this->messageQueue->enqueue(new FlashMessage(
                     '',
@@ -676,7 +676,7 @@ class Check implements CheckInterface
         ) {
             // Do not use data:// wrapper to be independent of allow_url_fopen
             $imageResource = @imagecreatefromgif(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.gif');
-            if (is_resource($imageResource)) {
+            if ($this->checkImageResource($imageResource)) {
                 imagedestroy($imageResource);
                 $this->messageQueue->enqueue(new FlashMessage(
                     '',
@@ -731,7 +731,7 @@ class Check implements CheckInterface
         ) {
             // Do not use data:// wrapper to be independent of allow_url_fopen
             $imageResource = @imagecreatefrompng(__DIR__ . '/../../Resources/Public/Images/TestInput/Test.png');
-            if (is_resource($imageResource)) {
+            if ($this->checkImageResource($imageResource)) {
                 imagedestroy($imageResource);
                 $this->messageQueue->enqueue(new FlashMessage(
                     '',
@@ -847,4 +847,9 @@ class Check implements CheckInterface
         }
         return (int)$bytes;
     }
+
+    private function checkImageResource($imageResource): bool
+    {
+        return is_resource($imageResource) || (PHP_MAJOR_VERSION >= 8 && $imageResource instanceof \GdImage);
+    }
 }
-- 
GitLab