[TASK] Protect info extension 41/58241/2
authorChristian Kuhn <lolli@schwarzbu.ch>
Sun, 9 Sep 2018 19:04:16 +0000 (21:04 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Mon, 10 Sep 2018 11:36:41 +0000 (13:36 +0200)
Last patch in the protect controller patch series. This time the
Web->Info module controller no longer extends BaseScriptClass and
the single sub controller classed don't extend AbstractFunctionModule
anymore. The patch sets as much as possible to protected to allow
further refactoring of these classes in v10.

Resolves: #86210
Releases: master
Change-Id: I5c474e6cc0bc093c58b2e939e408b47020547a6b
Reviewed-on: https://review.typo3.org/58241
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/belog/Classes/Module/BackendLogModuleBootstrap.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-86210-ProtectedInfoExtension.rst [new file with mode: 0644]
typo3/sysext/info/Classes/Controller/InfoModuleController.php
typo3/sysext/info/Classes/Controller/InfoPageTyposcriptConfigController.php
typo3/sysext/info/Classes/Controller/PageInformationController.php
typo3/sysext/info/Classes/Controller/TranslationStatusController.php
typo3/sysext/linkvalidator/Classes/Report/LinkValidatorReport.php
typo3/sysext/sys_note/Classes/Hook/InfoModuleHook.php

index ded6db1..799cdea 100644 (file)
@@ -14,6 +14,9 @@ namespace TYPO3\CMS\Belog\Module;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Core\Bootstrap;
+
 /**
  * This class is a wrapper for WebInfo controller of belog.
  * It is registered in ext_tables.php with \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction()
@@ -25,20 +28,6 @@ namespace TYPO3\CMS\Belog\Module;
 class BackendLogModuleBootstrap
 {
     /**
-     * Dummy method, called by SCbase external object handling
-     */
-    public function init()
-    {
-    }
-
-    /**
-     * Dummy method, called by SCbase external object handling
-     */
-    public function checkExtObj()
-    {
-    }
-
-    /**
      * Bootstrap extbase and jump to WebInfo controller
      *
      * @return string
@@ -55,10 +44,9 @@ class BackendLogModuleBootstrap
         // Overwriting $_GET was the most simple solution here until extbase
         // provides a clean way to solve this.
         $_GET['tx_belog_system_beloglog']['controller'] = 'BackendLog';
-        $_GET['tx_belog_system_beloglog']['pageId'] = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
+        $_GET['tx_belog_system_beloglog']['pageId'] = GeneralUtility::_GP('id');
         $_GET['tx_belog_system_beloglog']['layout'] = 'Plain';
-        /** @var \TYPO3\CMS\Extbase\Core\Bootstrap $extbaseBootstrap */
-        $extbaseBootstrap = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Core\Bootstrap::class);
+        $extbaseBootstrap = GeneralUtility::makeInstance(Bootstrap::class);
         return $extbaseBootstrap->run('', $configuration);
     }
 }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86210-ProtectedInfoExtension.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86210-ProtectedInfoExtension.rst
new file mode 100644 (file)
index 0000000..62e222a
--- /dev/null
@@ -0,0 +1,114 @@
+.. include:: ../../Includes.txt
+
+==============================================
+Deprecation: #86210 - Protected info extension
+==============================================
+
+See :issue:`86210`
+
+Description
+===========
+
+To allow refactoring of the Web -> Info module in TYPO3 v10, the involved controller classes
+have been disentangled and better encapsulated:
+
+* Class :php:`TYPO3\CMS\Info\Controller\InfoModuleController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\BaseScriptClass` anymore
+* Class :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+* Class :php:`TYPO3\CMS\Info\Controller\PageInformationController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+* Class :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+* Class :php:`TYPO3\CMS\Info\Controller\TranslationStatusController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+
+Setting an instance of class :php:`InfoModuleController` as global object :php:`$GLOBALS['SOBE']`
+has been deprecated and will be removed in TYPO3 v10.
+
+The following class properties have been set from public to protected and will not be accessible in TYPO3 v10 anymore:
+
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->perms_clause`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->modTSconfig`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->modMenu_setDefaultList`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->modMenu_dontValidateList`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->modMenu_type`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->extClassConf`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->extObj`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->content`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->pObj`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->id`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->CMD`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->doc`
+* :php:`TYPO3\CMS\Info\Controller\InfoModuleController->MCONF`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->pObj`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->doc`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->function_key`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->extClassConf`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->localLangFile`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->extObj`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->pObj`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->function_key`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->extClassConf`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->localLangFile`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->extObj`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->pObj`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->function_key`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->extClassConf`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->localLangFile`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->extObj`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->pObj`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->function_key`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->extClassConf`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->localLangFile`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->extObj`
+
+The following class methods have been set from public to protected and will not be accessible in TYPO3 v10 anymore:
+
+* :php:`TYPO3CMSInfoControllerInfoModuleController->main()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->init()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->getModuleTemplate()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->menuConfig()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->handleExternalFunctionValue()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->mergeExternalItems()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->getExternalItemConfig()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->extObjContent()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->getExtObjContent()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->checkExtObj()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->extObjHeader()`
+* :php:`TYPO3CMSInfoControllerInfoModuleController->checkSubExtObj()`
+* :php:`TYPO3\CMS\Linkvalidator\Report\LinkValidatorReport->extObjContent()`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->modMenu()`
+* :php:`TYPO3\CMS\Info\Controller\PageInformationController->extObjContent()`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->modMenu()`
+* :php:`TYPO3\CMS\Info\Controller\InfoPageTyposcriptConfigController->extObjContent()`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->getContentElementCount()`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->getLangStatus()`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->renderL10nTable()`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->modMenu()`
+* :php:`TYPO3\CMS\Info\Controller\TranslationStatusController->extObjContent()`
+
+
+Impact
+======
+
+If an extension accesses one of the above protected properties or calls one of the above protected methods,
+a :php:`E_USER_DEPRECATED` error will be triggered.
+
+
+Affected Installations
+======================
+
+Various extensions extend the Web -> Info module. Those typically call
+:php:`ExtensionManagementUtility::insertModuleFunction('web_info', ...)` in :file:`ext_tables.php` or
+:file:`ext_localconf.php`. Those instances may need adaptions.
+
+
+Migration
+=========
+
+If extending the `info` module with an own extension, the extension should be adapted to not call
+the above methods or properties any longer. Most usages can be easily adapted, for instance
+to retrieve the current page id, use :php:`GeneralUtility::_GP('id')` instead of :php:`$this->pObj->id`.
+
+.. index:: Backend, PHP-API, NotScanned, ext:info
\ No newline at end of file
index 37caec7..ed903b9 100644 (file)
@@ -16,12 +16,20 @@ namespace TYPO3\CMS\Info\Controller;
 
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
-use TYPO3\CMS\Backend\Module\BaseScriptClass;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
+use TYPO3\CMS\Backend\Template\DocumentTemplate;
 use TYPO3\CMS\Backend\Template\ModuleTemplate;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 use TYPO3\CMS\Core\Http\HtmlResponse;
 use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\Messaging\FlashMessage;
+use TYPO3\CMS\Core\Messaging\FlashMessageService;
+use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
@@ -29,22 +37,52 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
  * Script Class for the Web > Info module
  * This class creates the framework to which other extensions can connect their sub-modules
  */
-class InfoModuleController extends BaseScriptClass
+class InfoModuleController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
     /**
      * @var array
      */
-    public $pageinfo;
+    private $deprecatedPublicProperties = [
+        'perms_clause' => 'Using InfoModuleController::$perms_clause is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modTSconfig' => 'Using InfoModuleController::$modTSconfig is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modMenu_setDefaultList' => 'Using InfoModuleController::$modMenu_setDefaultList is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modMenu_dontValidateList' => 'Using InfoModuleController::$modMenu_dontValidateList is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modMenu_type' => 'Using InfoModuleController::$modMenu_type$ is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extClassConf' => 'Using InfoModuleController::extClassConf$ is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObj' => 'Using InfoModuleController::$extObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'content' => 'Using InfoModuleController::$content is deprecated and will not be possible anymore in TYPO3 v10.',
+        'pObj' => 'Using InfoModuleController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'id' => 'Using InfoModuleController::id$ is deprecated and will not be possible anymore in TYPO3 v10.',
+        'CMD' => 'Using InfoModuleController::$CMD is deprecated, property will be removed in TYPO3 v10.',
+        'doc' => 'Using InfoModuleController::$doc is deprecated, property will be removed in TYPO3 v10.',
+        'MCONF' => 'Using InfoModuleController::$MCONF is deprecated, property will be removed in TYPO3 v10.',
+    ];
 
     /**
-     * @var \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @var array
      */
-    protected $backendUser;
+    private $deprecatedPublicMethods = [
+        'main' => 'Using InfoModuleController::main() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'init' => 'Using InfoModuleController::init() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'getModuleTemplate' => 'Using InfoModuleController::getModuleTemplate() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'menuConfig' => 'Using InfoModuleController::menuConfig() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'handleExternalFunctionValue' => 'Using InfoModuleController::handleExternalFunctionValue() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'mergeExternalItems' => 'Using InfoModuleController::mergeExternalItems() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'getExternalItemConfig' => 'Using InfoModuleController::getExternalItemConfig() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObjContent' => 'Using InfoModuleController::extObjContent() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'getExtObjContent' => 'Using InfoModuleController::getExtObjContent() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'checkExtObj' => 'Using InfoModuleController::checkExtObj() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObjHeader' => 'Using InfoModuleController::extObjHeader() is deprecated, method will be removed in TYPO3 v10.',
+        'checkSubExtObj' => 'Using InfoModuleController::checkSubExtObj() is deprecated, method will be removed in TYPO3 v10.',
+    ];
 
     /**
-     * @var \TYPO3\CMS\Core\Localization\LanguageService
+     * @var array Used by client classes.
      */
-    protected $languageService;
+    public $pageinfo;
 
     /**
      * The name of the module
@@ -66,28 +104,143 @@ class InfoModuleController extends BaseScriptClass
     protected $view;
 
     /**
+     * Loaded with the global array $MCONF which holds some module configuration from the conf.php file of backend modules.
+     *
+     * @var array
+     */
+    protected $MCONF = [];
+
+    /**
+     * @var int Value of the GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * The value of GET/POST var, 'CMD'
+     *
+     * @var mixed
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $CMD;
+
+    /**
+     * A WHERE clause for selection records from the pages table based on read-permissions of the current backend user.
+     *
+     * @var string
+     */
+    protected $perms_clause;
+
+    /**
+     * The module menu items array. Each key represents a key for which values can range between the items in the array of that key.
+     * Written by client classes.
+     *
+     * @var array
+     */
+    public $MOD_MENU = [
+        'function' => []
+    ];
+
+    /**
+     * Current settings for the keys of the MOD_MENU array
+     * Written by client classes.
+     *
+     * @var array
+     */
+    public $MOD_SETTINGS = [];
+
+    /**
+     * Module TSconfig based on PAGE TSconfig / USER TSconfig
+     *
+     * @var array
+     */
+    protected $modTSconfig;
+
+    /**
+     * If type is 'ses' then the data is stored as session-lasting data. This means that it'll be wiped out the next time the user logs in.
+     * Can be set from extension classes of this class before the init() function is called.
+     *
+     * @var string
+     */
+    protected $modMenu_type = '';
+
+    /**
+     * dontValidateList can be used to list variables that should not be checked if their value is found in the MOD_MENU array. Used for dynamically generated menus.
+     * Can be set from extension classes of this class before the init() function is called.
+     *
+     * @var string
+     */
+    protected $modMenu_dontValidateList = '';
+
+    /**
+     * List of default values from $MOD_MENU to set in the output array (only if the values from MOD_MENU are not arrays)
+     * Can be set from extension classes of this class before the init() function is called.
+     *
+     * @var string
+     */
+    protected $modMenu_setDefaultList = '';
+
+    /**
+     * @var array Contains module configuration parts from TBE_MODULES_EXT if found
+     */
+    protected $extClassConf;
+
+    /**
+     * Generally used for accumulating the output content of backend modules
+     *
+     * @var string
+     */
+    protected $content = '';
+
+    /**
+     * @var DocumentTemplate
+     */
+    protected $doc;
+
+    /**
+     * May contain an instance of a 'Function menu module' which connects to this backend module.
+     *
+     * @var \object
+     */
+    protected $extObj;
+
+    /**
      * Constructor
      */
     public function __construct()
     {
         $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
-        $this->languageService = $GLOBALS['LANG'];
-        $this->languageService->includeLLFile('EXT:info/Resources/Private/Language/locallang_mod_web_info.xlf');
-
-        $this->backendUser = $GLOBALS['BE_USER'];
+        $languageService = $this->getLanguageService();
+        $languageService->includeLLFile('EXT:info/Resources/Private/Language/locallang_mod_web_info.xlf');
 
+        // @deprecated and will be removed in TYPO3 v10.0.
         $this->MCONF = [
             'name' => $this->moduleName,
         ];
     }
 
     /**
+     * Initializes the backend module by setting internal variables, initializing the menu.
+     */
+    protected function init()
+    {
+        $this->id = (int)GeneralUtility::_GP('id');
+        // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+        $this->CMD = GeneralUtility::_GP('CMD');
+        $this->perms_clause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW);
+        $this->menuConfig();
+        $this->handleExternalFunctionValue();
+    }
+
+    /**
      * Initialize module header etc and call extObjContent function
      */
-    public function main()
+    protected function main()
     {
-        // We leave this here because of dependencies to submodules
-        $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
+        // since TYPO3 v9, will be removed in TYPO3 v10.0.
+        $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
+
+        $languageService = $this->getLanguageService();
+        $backendUser = $this->getBackendUser();
 
         // The page will show only if there is a valid page and if this page
         // may be viewed by the user
@@ -96,8 +249,8 @@ class InfoModuleController extends BaseScriptClass
             $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
         }
         $access = is_array($this->pageinfo);
-        if ($this->id && $access || $this->backendUser->isAdmin() && !$this->id) {
-            if ($this->backendUser->isAdmin() && !$this->id) {
+        if ($this->id && $access || $backendUser->isAdmin() && !$this->id) {
+            if ($backendUser->isAdmin() && !$this->id) {
                 $this->pageinfo = ['title' => '[root-level]', 'uid' => 0, 'pid' => 0];
             }
             // JavaScript
@@ -114,17 +267,16 @@ class InfoModuleController extends BaseScriptClass
             $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
 
             $this->view = $this->getFluidTemplateObject();
-            /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-            $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
             $this->view->assign('moduleName', (string)$uriBuilder->buildUriFromRoute($this->moduleName));
             $this->view->assign('functionMenuModuleContent', $this->getExtObjContent());
-            // Setting up the buttons and markers for docheader
+            // Setting up the buttons and markers for doc header
             $this->getButtons();
             $this->generateMenu();
             $this->content .= $this->view->render();
         } else {
             // If no access or if ID == zero
-            $this->content = $this->moduleTemplate->header($this->languageService->getLL('title'));
+            $this->content = $this->moduleTemplate->header($languageService->getLL('title'));
         }
     }
 
@@ -137,13 +289,16 @@ class InfoModuleController extends BaseScriptClass
      */
     public function mainAction(ServerRequestInterface $request): ResponseInterface
     {
+        // @deprecated and will be removed in TYPO3 v10.0.
         $GLOBALS['SOBE'] = $this;
+
         $this->init();
 
         // Checking for first level external objects
         $this->checkExtObj();
 
         // Checking second level external objects
+        // @deprecated and will be removed in TYPO3 v10.0.
         $this->checkSubExtObj();
         $this->main();
 
@@ -156,6 +311,7 @@ class InfoModuleController extends BaseScriptClass
      */
     protected function getButtons()
     {
+        $languageService = $this->getLanguageService();
         $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
         // View page
         $viewButton = $buttonBar->makeLinkButton()
@@ -165,7 +321,7 @@ class InfoModuleController extends BaseScriptClass
                 '',
                 BackendUtility::BEgetRootLine($this->pageinfo['uid'])
             ))
-            ->setTitle($this->languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
+            ->setTitle($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
             ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-page', Icon::SIZE_SMALL));
         $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
         // Shortcut
@@ -199,8 +355,7 @@ class InfoModuleController extends BaseScriptClass
     {
         $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
         $menu->setIdentifier('WebInfoJumpMenu');
-        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         foreach ($this->MOD_MENU['function'] as $controller => $title) {
             $item = $menu
                 ->makeMenuItem()
@@ -230,7 +385,7 @@ class InfoModuleController extends BaseScriptClass
      *
      * @return ModuleTemplate
      */
-    public function getModuleTemplate()
+    protected function getModuleTemplate()
     {
         return $this->moduleTemplate;
     }
@@ -242,7 +397,6 @@ class InfoModuleController extends BaseScriptClass
      */
     protected function getFluidTemplateObject()
     {
-        /** @var StandaloneView $view */
         $view = GeneralUtility::makeInstance(StandaloneView::class);
         $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Layouts')]);
         $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Partials')]);
@@ -253,4 +407,181 @@ class InfoModuleController extends BaseScriptClass
         $view->getRequest()->setControllerExtensionName('info');
         return $view;
     }
+
+    /**
+     * Initializes the internal MOD_MENU array setting and unsetting items based on various conditions. It also merges in external menu items from the global array TBE_MODULES_EXT (see mergeExternalItems())
+     * Then MOD_SETTINGS array is cleaned up (see \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()) so it contains only valid values. It's also updated with any SET[] values submitted.
+     * Also loads the modTSconfig internal variable.
+     */
+    protected function menuConfig()
+    {
+        // Page / user TSconfig settings and blinding of menu-items
+        $this->modTSconfig['properties'] = BackendUtility::getPagesTSconfig($this->id)['mod.']['web_info.'] ?? [];
+        $this->MOD_MENU['function'] = $this->mergeExternalItems('web_info', 'function', $this->MOD_MENU['function']);
+        $blindActions = $this->modTSconfig['properties']['menu.']['function.'] ?? [];
+        foreach ($blindActions as $key => $value) {
+            if (!$value && array_key_exists($key, $this->MOD_MENU['function'])) {
+                unset($this->MOD_MENU['function'][$key]);
+            }
+        }
+        $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info', $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList);
+    }
+
+    /**
+     * Merges menu items from global array $TBE_MODULES_EXT
+     *
+     * @param string $modName Module name for which to find value
+     * @param string $menuKey Menu key, eg. 'function' for the function menu.
+     * @param array $menuArr The part of a MOD_MENU array to work on.
+     * @return array Modified array part.
+     * @access private
+     */
+    protected function mergeExternalItems($modName, $menuKey, $menuArr)
+    {
+        $mergeArray = $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey];
+        if (is_array($mergeArray)) {
+            $backendUser = $this->getBackendUser();
+            foreach ($mergeArray as $k => $v) {
+                if (((string)$v['ws'] === '' || $backendUser->workspace === 0 && GeneralUtility::inList($v['ws'], 'online'))
+                    || $backendUser->workspace === -1 && GeneralUtility::inList($v['ws'], 'offline')
+                    || $backendUser->workspace > 0 && GeneralUtility::inList($v['ws'], 'custom')
+                ) {
+                    $menuArr[$k] = $this->getLanguageService()->sL($v['title']);
+                }
+            }
+        }
+        return $menuArr;
+    }
+
+    /**
+     * Loads $this->extClassConf with the configuration for the CURRENT function of the menu.
+     *
+     * @param string $MM_key The key to MOD_MENU for which to fetch configuration. 'function' is default since it is first and foremost used to get information per "extension object" (I think that is what its called)
+     * @param string $MS_value The value-key to fetch from the config array. If NULL (default) MOD_SETTINGS[$MM_key] will be used. This is useful if you want to force another function than the one defined in MOD_SETTINGS[function]. Call this in init() function of your Script Class: handleExternalFunctionValue('function', $forcedSubModKey)
+     */
+    protected function handleExternalFunctionValue($MM_key = 'function', $MS_value = null)
+    {
+        if ($MS_value === null) {
+            $MS_value = $this->MOD_SETTINGS[$MM_key];
+        }
+        $this->extClassConf = $this->getExternalItemConfig('web_info', $MM_key, $MS_value);
+    }
+
+    /**
+     * Returns configuration values from the global variable $TBE_MODULES_EXT for the module given.
+     * For example if the module is named "web_info" and the "function" key ($menuKey) of MOD_SETTINGS is "stat" ($value) then you will have the values
+     * of $TBE_MODULES_EXT['webinfo']['MOD_MENU']['function']['stat'] returned.
+     *
+     * @param string $modName Module name
+     * @param string $menuKey Menu key, eg. "function" for the function menu. See $this->MOD_MENU
+     * @param string $value Optionally the value-key to fetch from the array that would otherwise have been returned if this value was not set. Look source...
+     * @return mixed The value from the TBE_MODULES_EXT array.
+     */
+    protected function getExternalItemConfig($modName, $menuKey, $value = '')
+    {
+        if (isset($GLOBALS['TBE_MODULES_EXT'][$modName])) {
+            return (string)$value !== ''
+                ? $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey][$value]
+                : $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey];
+        }
+        return null;
+    }
+
+    /**
+     * Creates an instance of the class found in $this->extClassConf['name'] in $this->extObj if any (this should hold three keys, "name", "path" and "title" if a "Function menu module" tries to connect...)
+     * This value in extClassConf might be set by an extension (in an ext_tables/ext_localconf file) which thus "connects" to a module.
+     * The array $this->extClassConf is set in handleExternalFunctionValue() based on the value of MOD_SETTINGS[function]
+     * If an instance is created it is initiated with $this passed as value and $this->extClassConf as second argument. Further the $this->MOD_SETTING is cleaned up again after calling the init function.
+     */
+    protected function checkExtObj()
+    {
+        if (is_array($this->extClassConf) && $this->extClassConf['name']) {
+            $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
+            if (is_callable([$this->extObj, 'init'])) {
+                $this->extObj->init($this);
+            }
+            // Re-write:
+            $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info', $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList);
+        }
+    }
+
+    /**
+     * Calls the checkExtObj function in sub module if present.
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected function checkSubExtObj()
+    {
+        if (is_object($this->extObj) && is_callable([$this->extObj, 'checkExtObj'])) {
+            $this->extObj->checkExtObj();
+        }
+    }
+
+    /**
+     * Calls the 'header' function inside the "Function menu module" if present.
+     * A header function might be needed to add JavaScript or other stuff in the head. This can't be done in the main function because the head is already written.
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected function extObjHeader()
+    {
+        if (is_callable([$this->extObj, 'head'])) {
+            $this->extObj->head();
+        }
+    }
+
+    /**
+     * Calls the 'main' function inside the "Function menu module" if present
+     */
+    protected function extObjContent()
+    {
+        if ($this->extObj === null) {
+            $languageService = $this->getLanguageService();
+            $flashMessage = GeneralUtility::makeInstance(
+                FlashMessage::class,
+                $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:no_modules_registered'),
+                $languageService->getLL('title'),
+                FlashMessage::ERROR
+            );
+            $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
+            /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */
+            $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
+            $defaultFlashMessageQueue->enqueue($flashMessage);
+        } else {
+            if (is_callable([$this->extObj, 'main'])) {
+                $this->content .= $this->extObj->main();
+            }
+        }
+    }
+
+    /**
+     * Return the content of the 'main' function inside the "Function menu module" if present
+     *
+     * @return string
+     */
+    protected function getExtObjContent()
+    {
+        $savedContent = $this->content;
+        $this->content = '';
+        $this->extObjContent();
+        $newContent = $this->content;
+        $this->content = $savedContent;
+        return $newContent;
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
 }
index 90e5b5d..796feae 100644 (file)
@@ -14,21 +14,50 @@ namespace TYPO3\CMS\Info\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
+use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
- * Page TSconfig viewer
+ * Page TSconfig viewer in Web -> Info
  */
-class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule
+class InfoPageTyposcriptConfigController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using InfoPageTyposcriptConfigController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using InfoPageTyposcriptConfigController::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using InfoPageTyposcriptConfigController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using InfoPageTyposcriptConfigController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+        'extObj' => 'Using InfoPageTyposcriptConfigController::$extObj is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'modMenu' => 'Using InfoPageTyposcriptConfigController::modMenu() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObjContent' => 'Using InfoPageTyposcriptConfigController::extObjContent() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * @var IconFactory
      */
@@ -40,60 +69,66 @@ class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\Abstr
     protected $view;
 
     /**
-     * Constructor
+     * @var InfoModuleController Contains a reference to the parent calling object
      */
-    public function __construct()
-    {
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-        $this->getLanguageService()->includeLLFile('EXT:info/Resources/Private/Language/InfoPageTsConfig.xlf');
+    protected $pObj;
 
-        $this->view = $this->getFluidTemplateObject();
-    }
+    /**
+     * @var int Value of the GET/POST var 'id'
+     */
+    protected $id;
 
     /**
-     * Function menu initialization
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extObj;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $localLangFile = '';
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extClassConf;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
      *
-     * @return array Menu array
+     * @param InfoModuleController $pObj A reference to the parent (calling) object
      */
-    public function modMenu()
+    public function init($pObj)
     {
-        $lang = $this->getLanguageService();
-        $modMenuAdd = [
-            'tsconf_parts' => [
-                0 => $lang->getLL('tsconf_parts_0'),
-                1 => $lang->getLL('tsconf_parts_1'),
-                '1a' => $lang->getLL('tsconf_parts_1a'),
-                '1b' => $lang->getLL('tsconf_parts_1b'),
-                '1c' => $lang->getLL('tsconf_parts_1c'),
-                '1d' => $lang->getLL('tsconf_parts_1d'),
-                '1e' => $lang->getLL('tsconf_parts_1e'),
-                '1f' => $lang->getLL('tsconf_parts_1f'),
-                '1g' => $lang->getLL('tsconf_parts_1g'),
-                2 => 'RTE.',
-                5 => 'TCEFORM.',
-                6 => 'TCEMAIN.',
-                3 => 'TSFE.',
-                4 => 'user.',
-                99 => $lang->getLL('tsconf_configFields')
-            ],
-            'tsconf_alphaSort' => '1'
-        ];
-        if (!$this->getBackendUser()->isAdmin()) {
-            unset($modMenuAdd['tsconf_parts'][99]);
+        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+        $languageService = $this->getLanguageService();
+        $languageService->includeLLFile('EXT:info/Resources/Private/Language/InfoPageTsConfig.xlf');
+        $this->view = $this->getFluidTemplateObject();
+        $this->pObj = $pObj;
+        // Local lang:
+        if (!empty($this->localLangFile)) {
+            // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+            $languageService->includeLLFile($this->localLangFile);
         }
-        return $modMenuAdd;
+        $this->id = (int)GeneralUtility::_GP('id');
+        // Setting MOD_MENU items as we need them for logging:
+        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
     }
 
     /**
-     * Main function of class
+     * Main, called from parent object
      *
      * @return string HTML output
      */
     public function main()
     {
         $pageId = (int)GeneralUtility::_GP('id');
-        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
 
         if ($pageId === 0) {
             $this->view->assign('pageZero', 1);
@@ -103,7 +138,7 @@ class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\Abstr
             }
         } else {
             if ($this->pObj->MOD_SETTINGS['tsconf_parts'] == 99) {
-                $TSparts = BackendUtility::getRawPagesTSconfig($this->pObj->id);
+                $TSparts = BackendUtility::getRawPagesTSconfig($this->id);
                 $lines = [];
                 $pUids = [];
 
@@ -132,7 +167,7 @@ class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\Abstr
                             $line['title'] = BackendUtility::wrapClickMenuOnIcon($icon, 'pages', $row['uid'])
                                 . ' ' . htmlspecialchars(BackendUtility::getRecordTitle('pages', $row));
                         }
-                        $tsparser = GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::class);
+                        $tsparser = GeneralUtility::makeInstance(TypoScriptParser::class);
                         $tsparser->lineNumberOffset = 0;
                         $line['content'] = $tsparser->doSyntaxHighlight(trim($v) . LF);
                         $lines[] = $line;
@@ -165,11 +200,11 @@ class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\Abstr
             } else {
                 $this->view->assign('tsconfParts99', 0);
                 // Defined global here!
-                $tmpl = GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\ExtendedTemplateService::class);
+                $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
                 $tmpl->ext_expandAllNotes = 1;
                 $tmpl->ext_noPMicons = 1;
 
-                $pageTsConfig = BackendUtility::getPagesTSconfig($this->pObj->id);
+                $pageTsConfig = BackendUtility::getPagesTSconfig($this->id);
                 switch ($this->pObj->MOD_SETTINGS['tsconf_parts']) {
                     case '1':
                         $pageTsConfig = $pageTsConfig['mod.'] ?? [];
@@ -217,13 +252,47 @@ class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\Abstr
                 $this->view->assign('csh', BackendUtility::cshItem('_MOD_web_info', 'tsconfig_hierarchy', null, '|'));
                 $this->view->assign('tree', $tmpl->ext_getObjTree($pageTsConfig, '', '', '', '', $this->pObj->MOD_SETTINGS['tsconf_alphaSort']));
             }
-            $this->view->assign('alphaSort', BackendUtility::getFuncCheck($this->pObj->id, 'SET[tsconf_alphaSort]', $this->pObj->MOD_SETTINGS['tsconf_alphaSort'], '', '', 'id="checkTsconf_alphaSort"'));
-            $this->view->assign('dropdownMenu', BackendUtility::getDropdownMenu($this->pObj->id, 'SET[tsconf_parts]', $this->pObj->MOD_SETTINGS['tsconf_parts'], $this->pObj->MOD_MENU['tsconf_parts']));
+            $this->view->assign('alphaSort', BackendUtility::getFuncCheck($this->id, 'SET[tsconf_alphaSort]', $this->pObj->MOD_SETTINGS['tsconf_alphaSort'], '', '', 'id="checkTsconf_alphaSort"'));
+            $this->view->assign('dropdownMenu', BackendUtility::getDropdownMenu($this->id, 'SET[tsconf_parts]', $this->pObj->MOD_SETTINGS['tsconf_parts'], $this->pObj->MOD_MENU['tsconf_parts']));
         }
         return $this->view->render();
     }
 
     /**
+     * Function menu initialization
+     *
+     * @return array Menu array
+     */
+    protected function modMenu()
+    {
+        $lang = $this->getLanguageService();
+        $modMenuAdd = [
+            'tsconf_parts' => [
+                0 => $lang->getLL('tsconf_parts_0'),
+                1 => $lang->getLL('tsconf_parts_1'),
+                '1a' => $lang->getLL('tsconf_parts_1a'),
+                '1b' => $lang->getLL('tsconf_parts_1b'),
+                '1c' => $lang->getLL('tsconf_parts_1c'),
+                '1d' => $lang->getLL('tsconf_parts_1d'),
+                '1e' => $lang->getLL('tsconf_parts_1e'),
+                '1f' => $lang->getLL('tsconf_parts_1f'),
+                '1g' => $lang->getLL('tsconf_parts_1g'),
+                2 => 'RTE.',
+                5 => 'TCEFORM.',
+                6 => 'TCEMAIN.',
+                3 => 'TSFE.',
+                4 => 'user.',
+                99 => $lang->getLL('tsconf_configFields')
+            ],
+            'tsconf_alphaSort' => '1'
+        ];
+        if (!$this->getBackendUser()->isAdmin()) {
+            unset($modMenuAdd['tsconf_parts'][99]);
+        }
+        return $modMenuAdd;
+    }
+
+    /**
      * Renders table rows of all pages containing TSConfig together with its rootline
      *
      * @return array
@@ -350,41 +419,63 @@ class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\Abstr
     }
 
     /**
-     * Returns LanguageService
+     * returns a new standalone view, shorthand function
      *
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
+     * @return StandaloneView
      */
-    protected function getLanguageService()
+    protected function getFluidTemplateObject()
     {
-        return $GLOBALS['LANG'];
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Layouts')]);
+        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Partials')]);
+        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Templates')]);
+
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Templates/PageTsConfig.html'));
+
+        $view->getRequest()->setControllerExtensionName('info');
+        return $view;
     }
 
     /**
-     * Returns the current BE user.
+     * Called from InfoModuleController until deprecation removal in v10
      *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
      */
-    protected function getBackendUser()
+    public function checkExtObj()
     {
-        return $GLOBALS['BE_USER'];
+        if (is_array($this->extClassConf) && $this->extClassConf['name']) {
+            $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
+            $this->extObj->init($this->pObj, $this->extClassConf);
+            // Re-write:
+            $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info');
+        }
     }
 
     /**
-     * returns a new standalone view, shorthand function
+     * Calls the main function inside ANOTHER sub-submodule which might exist.
      *
-     * @return StandaloneView
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
      */
-    protected function getFluidTemplateObject()
+    protected function extObjContent()
     {
-        /** @var StandaloneView $view */
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Layouts')]);
-        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Partials')]);
-        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Templates')]);
+        if (is_object($this->extObj)) {
+            return $this->extObj->main();
+        }
+    }
 
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Templates/PageTsConfig.html'));
+    /**
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
 
-        $view->getRequest()->setControllerExtensionName('info');
-        return $view;
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
     }
 }
index 38f1bd6..7ff3fa1 100644 (file)
@@ -18,56 +18,106 @@ use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Backend\View\PageLayoutView;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
+use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\Site\Entity\NullSite;
 use TYPO3\CMS\Core\Site\Entity\PseudoSite;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
- * Class for displaying page information (records, page record properties)
+ * Class for displaying page information (records, page record properties) in Web -> Info
  */
-class PageInformationController extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule
+class PageInformationController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
 
-    /** @var array */
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using PageInformationController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using PageInformationController::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using PageInformationController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using PageInformationController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+        'extObj' => 'Using PageInformationController::$extObj is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'modMenu' => 'Using PageInformationController::modMenu() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObjContent' => 'Using PageInformationController::extObjContent() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
     protected $fieldConfiguration = [];
 
     /**
-     * Returns the menu array
+     * @var int Value of the GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * @var InfoModuleController Contains a reference to the parent calling object
+     */
+    protected $pObj;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extObj;
+
+    /**
+     * Can be hardcoded to the name of a locallang.xlf file (from the same directory as the class file) to use/load
+     * and is included / added to $GLOBALS['LOCAL_LANG']
      *
-     * @return array
+     * @var string
      */
-    public function modMenu()
-    {
-        $menu = [
-            'pages' => [],
-            'depth' => [
-                0 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
-                1 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
-                2 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
-                3 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
-                4 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
-                999 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
-            ]
-        ];
+    protected $localLangFile = '';
 
-        // Using $GLOBALS['TYPO3_REQUEST'] since $request is not available at this point
-        // @todo: Refactor AbstractFunctionModule mess and have $request available
-        $this->fillFieldConfiguration($this->pObj->id, $GLOBALS['TYPO3_REQUEST']);
-        foreach ($this->fieldConfiguration as $key => $item) {
-            $menu['pages'][$key] = $item['label'];
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extClassConf;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
+     *
+     * @param InfoModuleController $pObj A reference to the parent (calling) object
+     */
+    public function init($pObj)
+    {
+        $this->pObj = $pObj;
+        // Local lang:
+        if (!empty($this->localLangFile)) {
+            // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+            $this->getLanguageService()->includeLLFile($this->localLangFile);
         }
-        return $menu;
+        $this->id = (int)GeneralUtility::_GP('id');
+        // Setting MOD_MENU items as we need them for logging:
+        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
     }
 
     /**
-     * MAIN function for page information display
+     * Main, called from parent object
      *
      * @return string Output HTML for the module.
      */
     public function main()
     {
-        $theOutput = '<h1>' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:page_title')) . '</h1>';
+        $languageService = $this->getLanguageService();
+        $theOutput = '<h1>' . htmlspecialchars($languageService->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:page_title')) . '</h1>';
         $dblist = GeneralUtility::makeInstance(PageLayoutView::class);
         $dblist->descrTable = '_MOD_web_info';
         $dblist->thumbs = 0;
@@ -86,9 +136,9 @@ class PageInformationController extends \TYPO3\CMS\Backend\Module\AbstractFuncti
         // PAGES:
         $this->pObj->MOD_SETTINGS['pages_levels'] = $this->pObj->MOD_SETTINGS['depth'];
         // ONLY for the sake of dblist module which uses this value.
-        $h_func = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
-        $h_func .= BackendUtility::getDropdownMenu($this->pObj->id, 'SET[pages]', $this->pObj->MOD_SETTINGS['pages'], $this->pObj->MOD_MENU['pages']);
-        $dblist->start($this->pObj->id, 'pages', 0);
+        $h_func = BackendUtility::getDropdownMenu($this->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
+        $h_func .= BackendUtility::getDropdownMenu($this->id, 'SET[pages]', $this->pObj->MOD_SETTINGS['pages'], $this->pObj->MOD_MENU['pages']);
+        $dblist->start($this->id, 'pages', 0);
         $dblist->generateList();
 
         $theOutput .= '<div class="form-inline form-inline-spaced">'
@@ -101,6 +151,7 @@ class PageInformationController extends \TYPO3\CMS\Backend\Module\AbstractFuncti
 
         // Additional footer content
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/web_info/class.tx_cms_webinfo.php']['drawFooterHook'] ?? [] as $hook) {
+            // @todo: request object should be submitted here as soon as it is available in v10.
             $params = [];
             $theOutput .= GeneralUtility::callUserFunction($hook, $params, $this);
         }
@@ -108,6 +159,34 @@ class PageInformationController extends \TYPO3\CMS\Backend\Module\AbstractFuncti
     }
 
     /**
+     * Returns the menu array
+     *
+     * @return array
+     */
+    protected function modMenu()
+    {
+        $menu = [
+            'pages' => [],
+            'depth' => [
+                0 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
+                1 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
+                2 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
+                3 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
+                4 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
+                999 => $GLOBALS['LANG']->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
+            ]
+        ];
+
+        // Using $GLOBALS['TYPO3_REQUEST'] since $request is not available at this point
+        // @todo: Refactor mess and have $request available
+        $this->fillFieldConfiguration($this->id, $GLOBALS['TYPO3_REQUEST']);
+        foreach ($this->fieldConfiguration as $key => $item) {
+            $menu['pages'][$key] = $item['label'];
+        }
+        return $menu;
+    }
+
+    /**
      * Function, which returns all tables to
      * which the user has access. Also a set of standard tables (pages, sys_filemounts, etc...)
      * are filtered out. So what is left is basically all tables which makes sense to list content from.
@@ -168,10 +247,45 @@ class PageInformationController extends \TYPO3\CMS\Backend\Module\AbstractFuncti
     }
 
     /**
+     * Called from InfoModuleController until deprecation removal in v10
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    public function checkExtObj()
+    {
+        if (is_array($this->extClassConf) && $this->extClassConf['name']) {
+            $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
+            $this->extObj->init($this->pObj, $this->extClassConf);
+            // Re-write:
+            $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info');
+        }
+    }
+
+    /**
+     * Calls the main function inside ANOTHER sub-submodule which might exist.
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected function extObjContent()
+    {
+        if (is_object($this->extObj)) {
+            return $this->extObj->main();
+        }
+    }
+
+    /**
      * @return BackendUserAuthentication
      */
-    protected function getBackendUser()
+    protected function getBackendUser(): BackendUserAuthentication
     {
         return $GLOBALS['BE_USER'];
     }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
 }
index eae7fa4..e9040ee 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 namespace TYPO3\CMS\Info\Controller;
 
 /*
@@ -15,24 +14,54 @@ namespace TYPO3\CMS\Info\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Backend\Tree\View\PageTreeView;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
-use TYPO3\CMS\Core\Site\Entity\Site;
+use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Site\Entity\SiteInterface;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
- * Class for displaying translation status of pages in the tree.
+ * Class for displaying translation status of pages in the tree in Web -> Info
  */
-class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule
+class TranslationStatusController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using TranslationStatusController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using TranslationStatusController::function_key$ is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using TranslationStatusController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using TranslationStatusController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+        'extObj' => 'Using TranslationStatusController::$extObj is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'getContentElementCount' => 'Using TranslationStatusController::getContentElementCount() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'getLangStatus' => 'Using TranslationStatusController::getLangStatus() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'renderL10nTable' => 'Using TranslationStatusController::renderL10nTable() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modMenu' => 'Using TranslationStatusController::modMenu() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObjContent' => 'Using TranslationStatusController::extObjContent() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * @var IconFactory
      */
@@ -44,66 +73,77 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
     protected $siteLanguages;
 
     /**
-     * Construct for initialize class variables
+     * @var InfoModuleController Contains a reference to the parent calling object
      */
-    public function __construct()
-    {
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-        $this->initializeSiteLanguages();
-    }
+    protected $pObj;
 
     /**
-     * Returns the menu array
+     * @var int Value of the GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extObj;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $localLangFile = '';
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extClassConf;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
      *
-     * @return array
+     * @param InfoModuleController $pObj A reference to the parent (calling) object
      */
-    public function modMenu()
+    public function init($pObj)
     {
-        $lang = $this->getLanguageService();
-        $menuArray = [
-            'depth' => [
-                0 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
-                1 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
-                2 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
-                3 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
-                4 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
-                999 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
-            ]
-        ];
-        // Languages:
-        $menuArray['lang'] = [];
-        foreach ($this->siteLanguages as $language) {
-            if ($language->getLanguageId() === 0) {
-                $menuArray['lang'][0] = '[All]';
-            } else {
-                $menuArray['lang'][$language->getLanguageId()] = $language->getTitle();
-            }
+        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+        $this->id = (int)GeneralUtility::_GP('id');
+        $this->initializeSiteLanguages();
+        $this->pObj = $pObj;
+        // Local lang:
+        if (!empty($this->localLangFile)) {
+            // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+            $this->getLanguageService()->includeLLFile($this->localLangFile);
         }
-        return $menuArray;
+        // Setting MOD_MENU items as we need them for logging:
+        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
     }
 
     /**
-     * MAIN function for page information of localization
+     * Main, called from parent object
      *
      * @return string Output HTML for the module.
      */
     public function main()
     {
         $theOutput = '<h1>' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_title')) . '</h1>';
-        if ($this->pObj->id) {
+        if ($this->id) {
             $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Info/TranslationStatus');
 
             // Depth selector:
             $theOutput .= '<div class="form-inline form-inline-spaced">';
-            $h_func = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
-            $h_func .= BackendUtility::getDropdownMenu($this->pObj->id, 'SET[lang]', $this->pObj->MOD_SETTINGS['lang'], $this->pObj->MOD_MENU['lang']);
+            $h_func = BackendUtility::getDropdownMenu($this->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
+            $h_func .= BackendUtility::getDropdownMenu($this->id, 'SET[lang]', $this->pObj->MOD_SETTINGS['lang'], $this->pObj->MOD_MENU['lang']);
             $theOutput .= $h_func;
             // Add CSH:
             $theOutput .= BackendUtility::cshItem('_MOD_web_info', 'lang', null, '<div class="form-group"><span class="btn btn-default btn-sm">|</span></div><br />');
             $theOutput .= '</div>';
             // Showing the tree:
             // Initialize starting point of page tree:
-            $treeStartingPoint = (int)$this->pObj->id;
+            $treeStartingPoint = (int)$this->id;
             $treeStartingRecord = BackendUtility::getRecordWSOL('pages', $treeStartingPoint);
             $depth = $this->pObj->MOD_SETTINGS['depth'];
             // Initialize tree object:
@@ -127,12 +167,42 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
     }
 
     /**
+     * Returns the menu array
+     *
+     * @return array
+     */
+    protected function modMenu()
+    {
+        $lang = $this->getLanguageService();
+        $menuArray = [
+            'depth' => [
+                0 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
+                1 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
+                2 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
+                3 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
+                4 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
+                999 => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
+            ]
+        ];
+        // Languages:
+        $menuArray['lang'] = [];
+        foreach ($this->siteLanguages as $language) {
+            if ($language->getLanguageId() === 0) {
+                $menuArray['lang'][0] = '[All]';
+            } else {
+                $menuArray['lang'][$language->getLanguageId()] = $language->getTitle();
+            }
+        }
+        return $menuArray;
+    }
+
+    /**
      * Rendering the localization information table.
      *
      * @param array $tree The Page tree data
      * @return string HTML for the localization information table.
      */
-    public function renderL10nTable(&$tree)
+    protected function renderL10nTable(&$tree)
     {
         $lang = $this->getLanguageService();
         // Title length:
@@ -141,8 +211,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
         $output = '';
         $newOL_js = [];
         $langRecUids = [];
-        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         foreach ($tree->tree as $data) {
             $tCells = [];
             $langRecUids[0][] = $data['row']['uid'];
@@ -393,7 +462,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
      * @param int $langId Language UID to select for.
      * @return array translated pages record
      */
-    public function getLangStatus($pageId, $langId)
+    protected function getLangStatus($pageId, $langId)
     {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('pages');
@@ -436,7 +505,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
      * @param int $sysLang Sys language uid
      * @return int Number of content elements from the PID where the language is set to a certain value.
      */
-    public function getContentElementCount($pageId, $sysLang)
+    protected function getContentElementCount($pageId, $sysLang)
     {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('tt_content');
@@ -465,11 +534,47 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
     }
 
     /**
-     * Returns LanguageService
+     * Since the AbstractFunctionModule cannot access the current request yet, we'll do it "old school"
+     * to fetch the Site based on the current ID.
+     */
+    protected function initializeSiteLanguages()
+    {
+        /** @var SiteInterface $currentSite */
+        $currentSite = $GLOBALS['TYPO3_REQUEST']->getAttribute('site');
+        $this->siteLanguages = $currentSite->getAvailableLanguages($this->getBackendUser(), false, (int)$this->id);
+    }
+
+    /**
+     * Called from InfoModuleController until deprecation removal in v10
      *
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
      */
-    protected function getLanguageService()
+    public function checkExtObj()
+    {
+        if (is_array($this->extClassConf) && $this->extClassConf['name']) {
+            $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
+            $this->extObj->init($this->pObj, $this->extClassConf);
+            // Re-write:
+            $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info');
+        }
+    }
+
+    /**
+     * Calls the main function inside ANOTHER sub-submodule which might exist.
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected function extObjContent()
+    {
+        if (is_object($this->extObj)) {
+            return $this->extObj->main();
+        }
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
     {
         return $GLOBALS['LANG'];
     }
@@ -477,21 +582,18 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc
     /**
      * Returns the current BE user.
      *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @return BackendUserAuthentication
      */
-    protected function getBackendUser()
+    protected function getBackendUser(): BackendUserAuthentication
     {
         return $GLOBALS['BE_USER'];
     }
 
     /**
-     * Since the AbstractFunctionModule cannot access the current request yet, we'll do it "old school"
-     * to fetch the Site based on the current ID.
+     * @return PageRenderer
      */
-    protected function initializeSiteLanguages()
+    protected function getPageRenderer(): PageRenderer
     {
-        /** @var SiteInterface $currentSite */
-        $currentSite = $GLOBALS['TYPO3_REQUEST']->getAttribute('site');
-        $this->siteLanguages = $currentSite->getAvailableLanguages($this->getBackendUser(), false, (int)$this->pObj->id);
+        return GeneralUtility::makeInstance(PageRenderer::class);
     }
 }
index d2a0607..3476174 100644 (file)
@@ -18,26 +18,54 @@ use Doctrine\DBAL\Driver\Statement;
 use TYPO3\CMS\Backend\Template\DocumentTemplate;
 use TYPO3\CMS\Backend\Template\ModuleTemplate;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageService;
+use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Info\Controller\InfoModuleController;
 use TYPO3\CMS\Linkvalidator\LinkAnalyzer;
 
 /**
- * Module 'Linkvalidator' for the 'linkvalidator' extension
+ * Module 'Link validator' as sub module of Web -> Info
  */
-class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule
+class LinkValidatorReport
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using LinkValidatorReport::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'doc' => 'Using LinkValidatorReport::$doc is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using LinkValidatorReport::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using LinkValidatorReport::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using LinkValidatorReport::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+        'extObj' => 'Using LinkValidatorReport::$extObj is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'extObjContent' => 'Using LinkValidatorReport::extObjContent() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * @var DocumentTemplate
      */
-    public $doc;
+    protected $doc;
 
     /**
      * Information about the current page record
@@ -133,7 +161,62 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
     protected $iconFactory;
 
     /**
-     * Main method of modfuncreport
+     * @var int Value of the GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * @var InfoModuleController Contains a reference to the parent calling object
+     */
+    protected $pObj;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extObj;
+
+    /**
+     * Can be hardcoded to the name of a locallang.xlf file (from the same directory as the class file) to use/load
+     * and is included / added to $GLOBALS['LOCAL_LANG']
+     *
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $localLangFile = '';
+
+    /**
+     * Contains module configuration parts from TBE_MODULES_EXT if found
+     *
+     * @see handleExternalFunctionValue()
+     * @var array
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $extClassConf;
+
+    /**
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
+     *
+     * @param InfoModuleController $pObj A reference to the parent (calling) object
+     */
+    public function init($pObj)
+    {
+        $languageService = $this->getLanguageService();
+        $this->pObj = $pObj;
+        // Local lang:
+        if (!empty($this->localLangFile)) {
+            // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+            $languageService->includeLLFile($this->localLangFile);
+        }
+        $this->id = (int)GeneralUtility::_GP('id');
+    }
+
+    /**
+     * Main, called from parent object
      *
      * @return string Module content
      */
@@ -152,8 +235,8 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
 
         // get searchLevel (number of levels of pages to check / show results)
         $this->searchLevel[$prefix] = GeneralUtility::_GP($prefix . '_search_levels');
-        if (isset($this->pObj->id)) {
-            $this->modTS = BackendUtility::getPagesTSconfig($this->pObj->id)['mod.']['linkvalidator.'] ?? [];
+        if (isset($this->id)) {
+            $this->modTS = BackendUtility::getPagesTSconfig($this->id)['mod.']['linkvalidator.'] ?? [];
         }
         if (isset($this->searchLevel[$prefix])) {
             $this->pObj->MOD_SETTINGS[$prefix . '_searchlevel'] = $this->searchLevel[$prefix];
@@ -166,7 +249,6 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
 
         // which linkTypes to check (internal, file, external, ...)
         $set = GeneralUtility::_GP($prefix . '_SET');
-        $this->pObj->handleExternalFunctionValue();
 
         foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['linkvalidator']['checkLinks'] ?? [] as $linkType => $value) {
             // Compile list of all available types. Used for checking with button "Check Links".
@@ -205,20 +287,28 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         $this->getPageRenderer()->addInlineLanguageLabelFile('EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf');
 
         if ($this->modTS['showCheckLinkTab'] == 1) {
-            $this->updateListHtml = '<input class="btn btn-default t3js-update-button" type="submit" name="updateLinkList" id="updateLinkList" value="' . htmlspecialchars($this->getLanguageService()->getLL('label_update')) . '" data-notification-message="' . htmlspecialchars($this->getLanguageService()->getLL('label_update-link-list')) . '"/>';
+            $this->updateListHtml = '<input class="btn btn-default t3js-update-button" type="submit" name="updateLinkList" id="updateLinkList" value="'
+                . htmlspecialchars($this->getLanguageService()->getLL('label_update'))
+                . '" data-notification-message="'
+                . htmlspecialchars($this->getLanguageService()->getLL('label_update-link-list'))
+                . '"/>';
         }
-        $this->refreshListHtml = '<input class="btn btn-default t3js-update-button" type="submit" name="refreshLinkList" id="refreshLinkList" value="' . htmlspecialchars($this->getLanguageService()->getLL('label_refresh')) . '" data-notification-message="' . htmlspecialchars($this->getLanguageService()->getLL('label_refresh-link-list')) . '"/>';
+        $this->refreshListHtml = '<input class="btn btn-default t3js-update-button" type="submit" name="refreshLinkList" id="refreshLinkList" value="'
+            . htmlspecialchars($this->getLanguageService()->getLL('label_refresh'))
+            . '" data-notification-message="'
+            . htmlspecialchars($this->getLanguageService()->getLL('label_refresh-link-list'))
+            . '"/>';
         $this->linkAnalyzer = GeneralUtility::makeInstance(LinkAnalyzer::class);
         $this->updateBrokenLinks();
 
-        $brokenLinkOverView = $this->linkAnalyzer->getLinkCounts($this->pObj->id);
+        $brokenLinkOverView = $this->linkAnalyzer->getLinkCounts($this->id);
         $this->checkOptionsHtml['report'] = $this->getCheckOptions($brokenLinkOverView, 'report');
         $this->checkOptionsHtml['check'] = $this->getCheckOptions($brokenLinkOverView, 'check');
         $this->render();
 
         $pageTile = '';
-        if ($this->pObj->id) {
-            $pageRecord = BackendUtility::getRecord('pages', $this->pObj->id);
+        if ($this->id) {
+            $pageRecord = BackendUtility::getRecord('pages', $this->id);
             $pageTile = '<h1>' . htmlspecialchars(BackendUtility::getRecordTitle('pages', $pageRecord)) . '</h1>';
         }
 
@@ -232,16 +322,17 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function createTabs()
     {
+        $languageService = $this->getLanguageService();
         $menuItems = [
             0 => [
-                'label' => $this->getLanguageService()->getLL('Report'),
+                'label' => $languageService->getLL('Report'),
                 'content' => $this->flush(true)
             ],
         ];
 
         if ((bool)$this->modTS['showCheckLinkTab']) {
             $menuItems[1] = [
-                'label' => $this->getLanguageService()->getLL('CheckLink'),
+                'label' => $languageService->getLL('CheckLink'),
                 'content' => $this->flush()
             ];
         }
@@ -262,14 +353,15 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
         $this->doc->setModuleTemplate('EXT:linkvalidator/Resources/Private/Templates/mod_template.html');
 
-        $this->pageRecord = BackendUtility::readPageAccess($this->pObj->id, $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW));
-        if ($this->pObj->id && is_array($this->pageRecord) || !$this->pObj->id && $this->isCurrentUserAdmin()) {
+        $this->pageRecord = BackendUtility::readPageAccess($this->id, $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW));
+        if ($this->id && is_array($this->pageRecord) || !$this->id && $this->isCurrentUserAdmin()) {
             $this->isAccessibleForCurrentUser = true;
         }
 
-        $this->getPageRenderer()->addCssFile('EXT:linkvalidator/Resources/Public/Css/linkvalidator.css', 'stylesheet', 'screen');
-        $this->getPageRenderer()->loadJquery();
-        $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Linkvalidator/Linkvalidator');
+        $pageRenderer = $this->getPageRenderer();
+        $pageRenderer->addCssFile('EXT:linkvalidator/Resources/Public/Css/linkvalidator.css', 'stylesheet', 'screen');
+        $pageRenderer->loadJquery();
+        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Linkvalidator/Linkvalidator');
 
         $this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
 
@@ -298,14 +390,14 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         if (!$rootLineHidden || $this->modTS['checkhidden'] == 1) {
             // Get children pages
             $pageList = $this->linkAnalyzer->extGetTreeList(
-                $this->pObj->id,
+                $this->id,
                 $this->searchLevel['check'],
                 0,
                 $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW),
                 $this->modTS['checkhidden']
             );
             if ($this->pObj->pageinfo['hidden'] == 0 || $this->modTS['checkhidden']) {
-                $pageList .= $this->pObj->id;
+                $pageList .= $this->id;
             }
 
             $this->linkAnalyzer->init($searchFields, $pageList, $this->modTS);
@@ -326,12 +418,12 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         if ($this->isAccessibleForCurrentUser) {
             $this->content = $this->renderBrokenLinksTable();
         } else {
+            $languageService = $this->getLanguageService();
             // If no access or if ID == zero
-            /** @var FlashMessage $message */
             $message = GeneralUtility::makeInstance(
                 FlashMessage::class,
-                $this->getLanguageService()->getLL('no.access'),
-                $this->getLanguageService()->getLL('no.access.title'),
+                $languageService->getLL('no.access'),
+                $languageService->getLL('no.access.title'),
                 FlashMessage::ERROR
             );
             /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */
@@ -366,15 +458,16 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function getLevelSelector($prefix = 'report')
     {
+        $languageService = $this->getLanguageService();
         // Build level selector
         $options = [];
         $availableOptions = [
-            0 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
-            1 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
-            2 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
-            3 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
-            4 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
-            999 => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
+            0 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
+            1 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
+            2 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
+            3 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
+            4 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
+            999 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
         ];
         foreach ($availableOptions as $optionValue => $optionLabel) {
             $options[] = '<option value="' . $optionValue . '"' . ($optionValue === (int)$this->searchLevel[$prefix] ? ' selected="selected"' : '') . '>' . htmlspecialchars($optionLabel) . '</option>';
@@ -405,7 +498,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
 
         $rootLineHidden = $this->linkAnalyzer->getRootLineIsHidden($this->pObj->pageinfo);
         if (!$rootLineHidden || (bool)$this->modTS['checkhidden']) {
-            $pageList = $this->getPageList($this->pObj->id);
+            $pageList = $this->getPageList($this->id);
             $result = false;
             if (!empty($linkTypes)) {
                 $result = $this->getLinkValidatorBrokenLinks($pageList, $linkTypes);
@@ -510,15 +603,15 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function getNoBrokenLinkMessage(array $brokenLinksMarker)
     {
-        $brokenLinksMarker['LIST_HEADER'] = '<h3>' . htmlspecialchars($this->getLanguageService()->getLL('list.header')) . '</h3>';
+        $languageService = $this->getLanguageService();
+        $brokenLinksMarker['LIST_HEADER'] = '<h3>' . htmlspecialchars($languageService->getLL('list.header')) . '</h3>';
         /** @var FlashMessage $message */
         $message = GeneralUtility::makeInstance(
             FlashMessage::class,
-            $this->getLanguageService()->getLL('list.no.broken.links'),
-            $this->getLanguageService()->getLL('list.no.broken.links.title'),
+            $languageService->getLL('list.no.broken.links'),
+            $languageService->getLL('list.no.broken.links.title'),
             FlashMessage::OK
         );
-        /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */
         $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
         /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */
         $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
@@ -534,14 +627,15 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function startTable()
     {
+        $languageService = $this->getLanguageService();
         // Listing head
         $makerTableHead = [
-            'tablehead_path' => $this->getLanguageService()->getLL('list.tableHead.path'),
-            'tablehead_element' => $this->getLanguageService()->getLL('list.tableHead.element'),
-            'tablehead_headlink' => $this->getLanguageService()->getLL('list.tableHead.headlink'),
-            'tablehead_linktarget' => $this->getLanguageService()->getLL('list.tableHead.linktarget'),
-            'tablehead_linkmessage' => $this->getLanguageService()->getLL('list.tableHead.linkmessage'),
-            'tablehead_lastcheck' => $this->getLanguageService()->getLL('list.tableHead.lastCheck'),
+            'tablehead_path' => $languageService->getLL('list.tableHead.path'),
+            'tablehead_element' => $languageService->getLL('list.tableHead.element'),
+            'tablehead_headlink' => $languageService->getLL('list.tableHead.headlink'),
+            'tablehead_linktarget' => $languageService->getLL('list.tableHead.linktarget'),
+            'tablehead_linkmessage' => $languageService->getLL('list.tableHead.linkmessage'),
+            'tablehead_lastcheck' => $languageService->getLL('list.tableHead.lastCheck'),
         ];
 
         // Add CSH to the header of each column
@@ -549,7 +643,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
             $makerTableHead[$column] = BackendUtility::wrapInHelp('linkvalidator', $column, $label);
         }
         // Add section header
-        $makerTableHead['list_header'] = '<h3>' . htmlspecialchars($this->getLanguageService()->getLL('list.header')) . '</h3>';
+        $makerTableHead['list_header'] = '<h3>' . htmlspecialchars($languageService->getLL('list.header')) . '</h3>';
         return $makerTableHead;
     }
 
@@ -563,6 +657,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function renderTableRow($table, array $row, $brokenLinksItemTemplate)
     {
+        $languageService = $this->getLanguageService();
         $markerArray = [];
         $fieldName = '';
         // Restore the linktype object
@@ -570,7 +665,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
 
         // Construct link to edit the content element
         $requestUri = GeneralUtility::getIndpEnv('REQUEST_URI') .
-            '&id=' . $this->pObj->id .
+            '&id=' . $this->id .
             '&search_levels=' . $this->searchLevel['report'];
         /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
         $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
@@ -584,12 +679,12 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
             'returnUrl' => $requestUri
         ]);
         $actionLinkOpen = '<a href="' . htmlspecialchars($url);
-        $actionLinkOpen .= '" title="' . htmlspecialchars($this->getLanguageService()->getLL('list.edit')) . '">';
+        $actionLinkOpen .= '" title="' . htmlspecialchars($languageService->getLL('list.edit')) . '">';
         $actionLinkClose = '</a>';
         $elementHeadline = $row['headline'];
         // Get the language label for the field from TCA
         if ($GLOBALS['TCA'][$table]['columns'][$row['field']]['label']) {
-            $fieldName = $this->getLanguageService()->sL($GLOBALS['TCA'][$table]['columns'][$row['field']]['label']);
+            $fieldName = $languageService->sL($GLOBALS['TCA'][$table]['columns'][$row['field']]['label']);
             // Crop colon from end if present
             if (substr($fieldName, '-1', '1') === ':') {
                 $fieldName = substr($fieldName, '0', strlen($fieldName) - 1);
@@ -600,11 +695,11 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         // column "Element"
         $element = '<span title="' . htmlspecialchars($table . ':' . $row['record_uid']) . '">' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
         if (empty($elementHeadline)) {
-            $element .= '<i>' . htmlspecialchars($this->getLanguageService()->getLL('list.no.headline')) . '</i>';
+            $element .= '<i>' . htmlspecialchars($languageService->getLL('list.no.headline')) . '</i>';
         } else {
             $element .= htmlspecialchars($elementHeadline);
         }
-        $element .= ' ' . htmlspecialchars(sprintf($this->getLanguageService()->getLL('list.field'), $fieldName));
+        $element .= ' ' . htmlspecialchars(sprintf($languageService->getLL('list.field'), $fieldName));
         $markerArray['actionlinkOpen'] = $actionLinkOpen;
         $markerArray['actionlinkClose'] = $actionLinkClose;
         $markerArray['actionlinkIcon'] = $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render();
@@ -614,7 +709,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         $markerArray['linktarget'] = htmlspecialchars($hookObj->getBrokenUrl($row));
         $response = unserialize($row['url_response']);
         if ($response['valid']) {
-            $linkMessage = '<span class="valid">' . htmlspecialchars($this->getLanguageService()->getLL('list.msg.ok')) . '</span>';
+            $linkMessage = '<span class="valid">' . htmlspecialchars($languageService->getLL('list.msg.ok')) . '</span>';
         } else {
             $linkMessage = '<span class="error">'
                 . nl2br(
@@ -632,7 +727,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
 
         $lastRunDate = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $row['last_check']);
         $lastRunTime = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $row['last_check']);
-        $markerArray['lastcheck'] = htmlspecialchars(sprintf($this->getLanguageService()->getLL('list.msg.lastRun'), $lastRunDate, $lastRunTime));
+        $markerArray['lastcheck'] = htmlspecialchars(sprintf($languageService->getLL('list.msg.lastRun'), $lastRunDate, $lastRunTime));
 
         // Return the table html code as string
         return $this->templateService->substituteMarkerArray($brokenLinksItemTemplate, $markerArray, '###|###', true, true);
@@ -647,6 +742,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function getCheckOptions(array $brokenLinkOverView, $prefix = 'report')
     {
+        $languageService = $this->getLanguageService();
         $markerArray = [];
         if (!empty($prefix)) {
             $additionalAttr = ' class="' . $prefix . '"';
@@ -655,8 +751,8 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
         }
         $checkOptionsTemplate = $this->templateService->getSubpart($this->doc->moduleTemplate, '###CHECKOPTIONS_SECTION###');
         $hookSectionTemplate = $this->templateService->getSubpart($checkOptionsTemplate, '###HOOK_SECTION###');
-        $markerArray['statistics_header'] = '<h3>' . htmlspecialchars($this->getLanguageService()->getLL('report.statistics.header')) . '</h3>';
-        $markerArray['total_count_label'] = BackendUtility::wrapInHelp('linkvalidator', 'checkboxes', $this->getLanguageService()->getLL('overviews.nbtotal'));
+        $markerArray['statistics_header'] = '<h3>' . htmlspecialchars($languageService->getLL('report.statistics.header')) . '</h3>';
+        $markerArray['total_count_label'] = BackendUtility::wrapInHelp('linkvalidator', 'checkboxes', $languageService->getLL('overviews.nbtotal'));
         $markerArray['total_count'] = $brokenLinkOverView['brokenlinkCount'] ?: '0';
 
         $linktypes = GeneralUtility::trimExplode(',', $this->modTS['linktypes'], true);
@@ -672,7 +768,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
                             'count' => $brokenLinkOverView[$type] ?: '0',
                         ];
 
-                        $translation = $this->getLanguageService()->getLL('hooks.' . $type) ?: $type;
+                        $translation = $languageService->getLL('hooks.' . $type) ?: $type;
 
                         $checked = $this->checkOpt[$prefix][$type] ? 'checked="checked"' : '';
 
@@ -728,7 +824,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
     {
         $result = '';
         if ($this->getBackendUser()->mayMakeShortcut()) {
-            $result = $this->doc->makeShortcutIcon('', 'function', $this->pObj->MCONF['name']);
+            $result = $this->doc->makeShortcutIcon('', 'function', 'web_info');
         }
         return $result;
     }
@@ -741,14 +837,18 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function getTemplateMarkers()
     {
+        $languageService = $this->getLanguageService();
         return [
-            'FUNC_TITLE' => $this->getLanguageService()->getLL('report.func.title'),
-            'CHECKOPTIONS_TITLE' => $this->getLanguageService()->getLL('report.statistics.header'),
+            'FUNC_TITLE' => $languageService->getLL('report.func.title'),
+            'CHECKOPTIONS_TITLE' => $languageService->getLL('report.statistics.header'),
             'FUNC_MENU' => $this->getLevelSelector('report'),
             'CONTENT' => $this->content,
             'CHECKOPTIONS' => $this->checkOptionsHtml['report'],
-            'ID' => '<input type="hidden" name="id" value="' . $this->pObj->id . '" />',
-            'REFRESH' => '<input type="submit" class="btn btn-default t3js-update-button" name="refreshLinkList" id="refreshLinkList" value="' . htmlspecialchars($this->getLanguageService()->getLL('label_refresh')) . '" data-notification-message="' . htmlspecialchars($this->getLanguageService()->getLL('label_refresh-link-list')) . '" />',
+            'ID' => '<input type="hidden" name="id" value="' . $this->id . '" />',
+            'REFRESH' => '<input type="submit" class="btn btn-default t3js-update-button" name="refreshLinkList" id="refreshLinkList" value="'
+                . htmlspecialchars($languageService->getLL('label_refresh'))
+                . '" data-notification-message="'
+                . htmlspecialchars($languageService->getLL('label_refresh-link-list')) . '" />',
             'UPDATE' => '',
         ];
     }
@@ -761,15 +861,20 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
      */
     protected function getTemplateMarkersCheck()
     {
+        $languageService = $this->getLanguageService();
         return [
-            'FUNC_TITLE' => $this->getLanguageService()->getLL('checklinks.func.title'),
-            'CHECKOPTIONS_TITLE' => $this->getLanguageService()->getLL('checklinks.statistics.header'),
+            'FUNC_TITLE' => $languageService->getLL('checklinks.func.title'),
+            'CHECKOPTIONS_TITLE' => $languageService->getLL('checklinks.statistics.header'),
             'FUNC_MENU' => $this->getLevelSelector('check'),
             'CONTENT' => '',
             'CHECKOPTIONS' => $this->checkOptionsHtml['check'],
-            'ID' => '<input type="hidden" name="id" value="' . $this->pObj->id . '" />',
+            'ID' => '<input type="hidden" name="id" value="' . $this->id . '" />',
             'REFRESH' => '',
-            'UPDATE' => '<input type="submit" class="btn btn-default t3js-update-button" name="updateLinkList" id="updateLinkList" value="' . htmlspecialchars($this->getLanguageService()->getLL('label_update')) . '" data-notification-message="' . htmlspecialchars($this->getLanguageService()->getLL('label_update-link-list')) . '"/>',
+            'UPDATE' => '<input type="submit" class="btn btn-default t3js-update-button" name="updateLinkList" id="updateLinkList" value="'
+                . htmlspecialchars($languageService->getLL('label_update'))
+                . '" data-notification-message="'
+                . htmlspecialchars($languageService->getLL('label_update-link-list'))
+                . '"/>',
         ];
     }
 
@@ -784,22 +889,53 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu
     }
 
     /**
-     * Returns LanguageService
+     * Called from InfoModuleController until deprecation removal in v10
      *
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
      */
-    protected function getLanguageService()
+    public function checkExtObj()
     {
-        return $GLOBALS['LANG'];
+        if (is_array($this->extClassConf) && $this->extClassConf['name']) {
+            $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
+            $this->extObj->init($this->pObj, $this->extClassConf);
+            // Re-write:
+            $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_info');
+        }
     }
 
     /**
-     * Returns the current BE user.
+     * Calls the main function inside ANOTHER sub-submodule which might exist.
      *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
+     */
+    protected function extObjContent()
+    {
+        if (is_object($this->extObj)) {
+            return $this->extObj->main();
+        }
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * @return BackendUserAuthentication
      */
-    protected function getBackendUser()
+    protected function getBackendUser(): BackendUserAuthentication
     {
         return $GLOBALS['BE_USER'];
     }
+
+    /**
+     * @return PageRenderer
+     */
+    protected function getPageRenderer(): PageRenderer
+    {
+        return GeneralUtility::makeInstance(PageRenderer::class);
+    }
 }
index 43a29c6..9f5510f 100644 (file)
@@ -26,13 +26,12 @@ class InfoModuleHook
     /**
      * Add sys_notes as additional content to the footer of the info module
      *
-     * @param array $params
-     * @param \TYPO3\CMS\Info\Controller\PageInformationController $parentObject
      * @return string
      */
-    public function render(array $params = [], \TYPO3\CMS\Info\Controller\PageInformationController $parentObject)
+    public function render()
     {
         $controller = GeneralUtility::makeInstance(NoteController::class);
-        return $controller->listAction($parentObject->pObj->id);
+        $id = (int)GeneralUtility::_GP('id');
+        return $controller->listAction($id);
     }
 }