From 2c359febf2895af2c8b2fc357ba48d49c65cc0b1 Mon Sep 17 00:00:00 2001
From: Benjamin Franzke <bfr@qbus.de>
Date: Sun, 30 Jan 2022 15:40:41 +0100
Subject: [PATCH] [TASK] Add PHPStan plugin for psr/container
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The plugins adds a dynamic return type resolver for the
ContainerInterface::get() method and is especially useful
in core ServiceProviders once we enable phpstan level 5
as invalid parameter usage will then be detected.

The plugin already revealed wrong interface usage in
functional MFA tests which are fixed as a drive by.

Commands executed:

  composer req --dev bnf/phpstan-psr-container:^1.0
  Build/Scripts/runTests.sh -s phpstanGenerateBaseline

Releases: main, 11.5
Resolves: #96691
Change-Id: I4149a75e9a94ba61218e18c0639c03a06a7c53c1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/73222
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 Build/phpstan/phpstan-baseline.neon           | 33 ++++++-----
 Build/phpstan/phpstan.neon                    |  1 +
 composer.json                                 |  1 +
 composer.lock                                 | 59 ++++++++++++++++++-
 .../Provider/RecoveryCodesProviderTest.php    |  4 +-
 .../Mfa/Provider/TotpProviderTest.php         |  4 +-
 6 files changed, 83 insertions(+), 19 deletions(-)

diff --git a/Build/phpstan/phpstan-baseline.neon b/Build/phpstan/phpstan-baseline.neon
index c125d890be2a..6bd8f18bb73f 100644
--- a/Build/phpstan/phpstan-baseline.neon
+++ b/Build/phpstan/phpstan-baseline.neon
@@ -2626,23 +2626,13 @@ parameters:
 			path: ../../typo3/sysext/extbase/Tests/Functional/Mvc/Controller/ActionControllerTest.php
 
 		-
-			message: "#^Call to an undefined method TYPO3\\\\CMS\\\\Extbase\\\\Mvc\\\\RequestInterface\\:\\:getControllerActionName\\(\\)\\.$#"
-			count: 6
-			path: ../../typo3/sysext/extbase/Tests/Functional/Mvc/Web/RequestBuilderTest.php
-
-		-
-			message: "#^Call to an undefined method TYPO3\\\\CMS\\\\Extbase\\\\Mvc\\\\RequestInterface\\:\\:getControllerName\\(\\)\\.$#"
-			count: 2
-			path: ../../typo3/sysext/extbase/Tests/Functional/Mvc/Web/RequestBuilderTest.php
-
-		-
-			message: "#^Call to an undefined method TYPO3\\\\CMS\\\\Extbase\\\\Mvc\\\\RequestInterface\\:\\:getFormat\\(\\)\\.$#"
-			count: 3
-			path: ../../typo3/sysext/extbase/Tests/Functional/Mvc/Web/RequestBuilderTest.php
+			message: "#^Method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryInterface\\:\\:logicalAnd\\(\\) invoked with 2 parameters, 1 required\\.$#"
+			count: 1
+			path: ../../typo3/sysext/extbase/Tests/Functional/Persistence/CountTest.php
 
 		-
 			message: "#^Method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryInterface\\:\\:logicalOr\\(\\) invoked with 2 parameters, 1 required\\.$#"
-			count: 1
+			count: 2
 			path: ../../typo3/sysext/extbase/Tests/Functional/Persistence/CountTest.php
 
 		-
@@ -2655,6 +2645,21 @@ parameters:
 			count: 1
 			path: ../../typo3/sysext/extbase/Tests/Functional/Persistence/QueryLocalizedDataTest.php
 
+		-
+			message: "#^Method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryInterface\\:\\:logicalAnd\\(\\) invoked with 2 parameters, 1 required\\.$#"
+			count: 1
+			path: ../../typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php
+
+		-
+			message: "#^Method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryInterface\\:\\:logicalAnd\\(\\) invoked with 3 parameters, 1 required\\.$#"
+			count: 1
+			path: ../../typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php
+
+		-
+			message: "#^Method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryInterface\\:\\:logicalOr\\(\\) invoked with 2 parameters, 1 required\\.$#"
+			count: 2
+			path: ../../typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php
+
 		-
 			message: "#^PHPDoc tag @param has invalid value \\(\\$queryRequest\\)\\: Unexpected token \"\\$queryRequest\", expected type at offset 126$#"
 			count: 2
diff --git a/Build/phpstan/phpstan.neon b/Build/phpstan/phpstan.neon
index 19c23af42c29..166146c5d40a 100644
--- a/Build/phpstan/phpstan.neon
+++ b/Build/phpstan/phpstan.neon
@@ -1,5 +1,6 @@
 includes:
   - phpstan-baseline.neon
+  - ../../vendor/bnf/phpstan-psr-container/extension.neon
   - ../../vendor/friendsoftypo3/phpstan-typo3/extension.neon
   - ../../vendor/jangregor/phpstan-prophecy/extension.neon
   - ../../vendor/phpstan/phpstan-phpunit/extension.neon
diff --git a/composer.json b/composer.json
index 94f7d9524ed8..85eb22e89460 100644
--- a/composer.json
+++ b/composer.json
@@ -102,6 +102,7 @@
 		"typo3fluid/fluid": "^2.7.1"
 	},
 	"require-dev": {
+		"bnf/phpstan-psr-container": "^1.0",
 		"codeception/codeception": "^4.1.22",
 		"codeception/lib-asserts": "^1.13.2",
 		"codeception/module-asserts": "^1.3.1",
diff --git a/composer.lock b/composer.lock
index e80b6908bcc2..ab3bf62eeb4b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "a7f818359e4001c3164549b7cb254c8e",
+    "content-hash": "ac7d5bd0f7bef5d1626382a8508a679d",
     "packages": [
         {
             "name": "bacon/bacon-qr-code",
@@ -5203,6 +5203,63 @@
             },
             "time": "2021-02-04T12:44:21+00:00"
         },
+        {
+            "name": "bnf/phpstan-psr-container",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/bnf/phpstan-psr-container.git",
+                "reference": "15f001a5a4462e5125af13124d700f024f5355d5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/bnf/phpstan-psr-container/zipball/15f001a5a4462e5125af13124d700f024f5355d5",
+                "reference": "15f001a5a4462e5125af13124d700f024f5355d5",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0|^8.0",
+                "phpstan/phpstan": "^1.0",
+                "psr/container": "^1.0"
+            },
+            "type": "phpstan-extension",
+            "extra": {
+                "phpstan": {
+                    "includes": [
+                        "extension.neon"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Bnf\\PhpstanPsrContainer\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-2.0+"
+            ],
+            "authors": [
+                {
+                    "name": "Benjamin Franzke",
+                    "email": "benjaminfranzke@gmail.com",
+                    "homepage": "https://bnfr.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "PHPStan dynamic return type extension for PSR-11 ContainerInterface",
+            "keywords": [
+                "PHPStan",
+                "PSR-11",
+                "service-provider",
+                "static"
+            ],
+            "support": {
+                "issues": "https://github.com/bnf/phpstan-psr-container/issues",
+                "source": "https://github.com/bnf/phpstan-psr-container/tree/1.0.0"
+            },
+            "time": "2021-11-25T07:37:18+00:00"
+        },
         {
             "name": "codeception/codeception",
             "version": "4.1.22",
diff --git a/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/RecoveryCodesProviderTest.php b/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/RecoveryCodesProviderTest.php
index c2cdbb83e0b6..187cc28b6cc6 100644
--- a/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/RecoveryCodesProviderTest.php
+++ b/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/RecoveryCodesProviderTest.php
@@ -18,7 +18,7 @@ declare(strict_types=1);
 namespace TYPO3\CMS\Core\Tests\Functional\Authentication\Mfa\Provider;
 
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderManifest;
+use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderManifestInterface;
 use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderPropertyManager;
 use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry;
 use TYPO3\CMS\Core\Authentication\Mfa\MfaViewType;
@@ -35,7 +35,7 @@ use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 class RecoveryCodesProviderTest extends FunctionalTestCase
 {
     private BackendUserAuthentication $user;
-    private MfaProviderManifest $subject;
+    private MfaProviderManifestInterface $subject;
 
     protected $configurationToUseInTestInstance = [
         'BE' => [
diff --git a/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/TotpProviderTest.php b/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/TotpProviderTest.php
index dd9da0690e62..d9da4f005183 100644
--- a/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/TotpProviderTest.php
+++ b/typo3/sysext/core/Tests/Functional/Authentication/Mfa/Provider/TotpProviderTest.php
@@ -18,7 +18,7 @@ declare(strict_types=1);
 namespace TYPO3\CMS\Core\Tests\Functional\Authentication\Mfa\Provider;
 
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderManifest;
+use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderManifestInterface;
 use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderPropertyManager;
 use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry;
 use TYPO3\CMS\Core\Authentication\Mfa\MfaViewType;
@@ -32,7 +32,7 @@ use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 class TotpProviderTest extends FunctionalTestCase
 {
     private BackendUserAuthentication $user;
-    private MfaProviderManifest $subject;
+    private MfaProviderManifestInterface $subject;
 
     protected function setUp(): void
     {
-- 
GitLab