diff --git a/Build/Scripts/duplicateExceptionCodeCheck.sh b/Build/Scripts/duplicateExceptionCodeCheck.sh index 7fcaf88b534bc3a6a2edb2b1a692b5244ace9176..5a152e8fd716ced93b9e93213ee161436521435f 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 cf80b7da69359633637fe6276da2ecd00628b924..261a9d94d35c9eba055cc9beb30eed684cbf811a 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 554998ece1eea6835b01af149579017919c512a5..77e27807377af1c0bbde983bac1ed818b31c7240 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 0000000000000000000000000000000000000000..2bda74a5f9bf47145d1f12d9bf56592403dc5928 --- /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 05d3e5e7a80a80e50b8b7378a4e4c0375c685bb5..5a79c6111d4e10491cf33a4cfb13ff7722f88908 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 e09b543e2580e8e3fed2aed3fbcb1eafe5c949fe..62971b07aeff4ec22ab3fc407212072ee8cf637d 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 6029a1eee01b8e9fec602ce73ba8cc06b79e2fc9..7a565f35bc29291c39c51824986de186c9d31585 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); + } }