From 13a93b2fe9beff99c07ebfd12d88a46f92e6ba24 Mon Sep 17 00:00:00 2001
From: Alexander Schnitzler <git@alexanderschnitzler.de>
Date: Sat, 25 Jan 2020 17:52:28 +0100
Subject: [PATCH] [TASK] Use a reference variable to pass $this into hooks

Unfortunately phpstan looses the correct type of $this
as soon as $this is passed into a hooked as a hook method
parameter without a specific type. This leads to phpstan
losing the information about available methods and properties
of $this.

Releases: master
Resolves: #90204
Change-Id: I6fdb4f07dd970a1602a7afbbf662b29f2a927a15
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63036
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
---
 .../Classes/Controller/FrontendLoginController.php       | 9 ++++++---
 .../Classes/ContentObject/ContentObjectRenderer.php      | 9 ++++++---
 .../Classes/Controller/TypoScriptFrontendController.php  | 3 ++-
 typo3/sysext/frontend/Classes/Imaging/GifBuilder.php     | 3 ++-
 typo3/sysext/indexed_search/Classes/Hook/CrawlerHook.php | 3 ++-
 .../sysext/linkvalidator/Classes/Task/ValidatorTask.php  | 3 ++-
 6 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/typo3/sysext/felogin/Classes/Controller/FrontendLoginController.php b/typo3/sysext/felogin/Classes/Controller/FrontendLoginController.php
index b57048a63434..5a2f78faa178 100644
--- a/typo3/sysext/felogin/Classes/Controller/FrontendLoginController.php
+++ b/typo3/sysext/felogin/Classes/Controller/FrontendLoginController.php
@@ -197,7 +197,8 @@ class FrontendLoginController extends AbstractPlugin
                 ];
                 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['beforeRedirect'] ?? [] as $_funcRef) {
                     if ($_funcRef) {
-                        GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+                        $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+                        GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
                     }
                 }
                 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->redirectUrl);
@@ -208,7 +209,8 @@ class FrontendLoginController extends AbstractPlugin
             $_params = [
                 'content' => $content
             ];
-            $content = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+            $content = GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
         }
         return $this->conf['wrapContentInBaseClass'] ? $this->pi_wrapInBaseClass($content) : $content;
     }
@@ -830,7 +832,8 @@ class FrontendLoginController extends AbstractPlugin
                     foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['logout_confirmed'] ?? [] as $_funcRef) {
                         $_params = [];
                         if ($_funcRef) {
-                            GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+                            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+                            GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
                         }
                     }
                     switch ($redirMethod) {
diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
index 587b49f0545b..81f52ad35629 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
@@ -2898,7 +2898,8 @@ class ContentObjectRenderer implements LoggerAwareInterface
                 'lifetime' => $lifetime,
                 'tags' => $tags
             ];
-            GeneralUtility::callUserFunction($_funcRef, $params, $this);
+            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+            GeneralUtility::callUserFunction($_funcRef, $params, $ref);
         }
         $cacheFrontend->set($key, $content, $tags, $lifetime);
         return $content;
@@ -4716,7 +4717,8 @@ class ContentObjectRenderer implements LoggerAwareInterface
                 if (!$hookObject instanceof ContentObjectGetDataHookInterface) {
                     throw new \UnexpectedValueException('$hookObject must implement interface ' . ContentObjectGetDataHookInterface::class, 1195044480);
                 }
-                $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $this);
+                $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+                $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $ref);
             }
         }
         return $retVal;
@@ -5125,7 +5127,8 @@ class ContentObjectRenderer implements LoggerAwareInterface
             'tagAttributes' => &$tagAttributes
         ];
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] ?? [] as $_funcRef) {
-            GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+            GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
         }
 
         // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
index e6794af3ab5c..aa3165932e0d 100644
--- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
+++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
@@ -2155,7 +2155,8 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     {
         $_params = [];
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_preProcess'] ?? [] as $_funcRef) {
-            GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+            GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
         }
 
         // Rendering charset of HTML page.
diff --git a/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php b/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
index 06d37ef9a075..9040b8a4117a 100644
--- a/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
+++ b/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
@@ -125,7 +125,8 @@ class GifBuilder extends GraphicalFunctions
             // line as TEXT obj, see extension julle_gifbconf
             foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'] ?? [] as $_funcRef) {
                 $_params = $this->setup;
-                $this->setup = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
+                $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+                $this->setup = GeneralUtility::callUserFunction($_funcRef, $_params, $ref);
             }
             // Initializing global Char Range Map
             $this->charRangeMap = [];
diff --git a/typo3/sysext/indexed_search/Classes/Hook/CrawlerHook.php b/typo3/sysext/indexed_search/Classes/Hook/CrawlerHook.php
index 1a5d86696b3d..3c377b1fdc73 100644
--- a/typo3/sysext/indexed_search/Classes/Hook/CrawlerHook.php
+++ b/typo3/sysext/indexed_search/Classes/Hook/CrawlerHook.php
@@ -234,7 +234,8 @@ class CrawlerHook
                             $hookObj = GeneralUtility::makeInstance($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['crawler'][$cfgRec['type']]);
                             $this->pObj = $pObj;
                             // For addQueueEntryForHook()
-                            $hookObj->indexOperation($cfgRec, $session_data, $params, $this);
+                            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+                            $hookObj->indexOperation($cfgRec, $session_data, $params, $ref);
                         }
                 }
                 // Save process data which might be modified:
diff --git a/typo3/sysext/linkvalidator/Classes/Task/ValidatorTask.php b/typo3/sysext/linkvalidator/Classes/Task/ValidatorTask.php
index 58630eea31b8..ef246de3329c 100644
--- a/typo3/sysext/linkvalidator/Classes/Task/ValidatorTask.php
+++ b/typo3/sysext/linkvalidator/Classes/Task/ValidatorTask.php
@@ -443,7 +443,8 @@ class ValidatorTask extends AbstractTask
                 'pObj' => &$this,
                 'markerArray' => $markerArray
             ];
-            $newMarkers = GeneralUtility::callUserFunction($userFunc, $params, $this);
+            $ref = $this; // introduced for phpstan to not lose type information when passing $this into callUserFunction
+            $newMarkers = GeneralUtility::callUserFunction($userFunc, $params, $ref);
             if (is_array($newMarkers)) {
                 $markerArray = $newMarkers + $markerArray;
             }
-- 
GitLab