[TASK] Protect tstemplate extension 40/58240/2
authorChristian Kuhn <lolli@schwarzbu.ch>
Sun, 9 Sep 2018 15:42:23 +0000 (17:42 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Mon, 10 Sep 2018 11:36:24 +0000 (13:36 +0200)
The patch disentangles the tstemplate extension controller
classes. The main controller class no longer extends
BaseScriptClass and the sub controllers no longer extend
AbstractFunctionModule. The classes set as many properties
and methods to protected to allow further refactoring of this
module in v10.

Resolves: #86207
Releases: master
Change-Id: If9ad462a423be5f0e370e0894ebb848b822ee66b
Reviewed-on: https://review.typo3.org/58240
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/core/Classes/TypoScript/ExtendedTemplateService.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-86207-ProtectedTstemplateExtension.rst [new file with mode: 0644]
typo3/sysext/tstemplate/Classes/Controller/TemplateAnalyzerModuleFunctionController.php
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateConstantEditorModuleFunctionController.php
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateInformationModuleFunctionController.php
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateModuleController.php
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateObjectBrowserModuleFunctionController.php

index 29994f9..c1a0d50 100644 (file)
@@ -423,7 +423,7 @@ class ExtendedTemplateService extends TemplateService
                 $HTML .= $depthData . '<li>';
                 if ($PM !== 'join') {
                     $urlParameters = [
-                        'id' => $GLOBALS['SOBE']->id,
+                        'id' => (int)GeneralUtility::_GP('id'),
                         'tsbr[' . $depth . ']' => $deeper ? 0 : 1
                     ];
                     if (GeneralUtility::_GP('breakPointLN')) {
@@ -439,7 +439,7 @@ class ExtendedTemplateService extends TemplateService
                 } else {
                     if ($this->linkObjects) {
                         $urlParameters = [
-                            'id' => $GLOBALS['SOBE']->id,
+                            'id' => (int)GeneralUtility::_GP('id'),
                             'sObj' => $depth
                         ];
                         if (GeneralUtility::_GP('breakPointLN')) {
@@ -659,13 +659,13 @@ class ExtendedTemplateService extends TemplateService
             $BTM = $a == $c ? 'top' : '';
             $HTML .= $depthData;
             $alttext = '[' . $row['templateID'] . ']';
-            $alttext .= $row['pid'] ? ' - ' . BackendUtility::getRecordPath($row['pid'], $GLOBALS['SOBE']->perms_clause, 20) : '';
+            $alttext .= $row['pid'] ? ' - ' . BackendUtility::getRecordPath($row['pid'], '1=1', 20) : '';
             $icon = strpos($row['templateID'], 'sys') === 0
                 ? '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIconForRecord('sys_template', $row, Icon::SIZE_SMALL)->render() . '</span>'
                 : '<span title="' . htmlspecialchars($alttext) . '">' . $iconFactory->getIcon('mimetypes-x-content-template-static', Icon::SIZE_SMALL)->render() . '</span>';
             if (in_array($row['templateID'], $this->clearList_const) || in_array($row['templateID'], $this->clearList_setup)) {
                 $urlParameters = [
-                    'id' => $GLOBALS['SOBE']->id,
+                    'id' => (int)GeneralUtility::_GP('id'),
                     'template' => $row['templateID']
                 ];
                 $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86207-ProtectedTstemplateExtension.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86207-ProtectedTstemplateExtension.rst
new file mode 100644 (file)
index 0000000..2377fc2
--- /dev/null
@@ -0,0 +1,112 @@
+.. include:: ../../Includes.txt
+
+====================================================
+Deprecation: #86207 - Protected tstemplate extension
+====================================================
+
+See :issue:`86207`
+
+Description
+===========
+
+To allow refactoring of the Web -> Template module in TYPO3 v10, the involved controller classes
+have been disentangled and better encapsulated:
+
+* Class :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\BaseScriptClass` anymore
+* Class :php:`TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+* Class :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateConstantEditorModuleFunctionController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+* Class :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+* Class :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateObjectBrowserModuleFunctionController`
+  does not extend :php:`TYPO3\CMS\Backend\Module\AbstractFunctionModule` anymore
+
+Setting an instance of class :php:`TypoScriptTemplateModuleController` 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\Tstemplate\Controller\TypoScriptTemplateModuleController->textExtensions`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->pageinfo`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->id`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->modTSconfig`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->content`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->extObj`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->access`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->perms_clause`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->extClassConf`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->edit`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->modMenu_type`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->MCONF`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->CMD`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController->sObj`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController->pObj`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController->function_key`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController->extClassConf`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController->localLangFile`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateConstantEditorModuleFunctionController->pObj`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateConstantEditorModuleFunctionController->function_key`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateConstantEditorModuleFunctionController->extClassConf`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateConstantEditorModuleFunctionController->localLangFile`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController->pObj`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController->function_key`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController->extClassConf`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController->localLangFile`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController->tce_processed`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateObjectBrowserModuleFunctionController->pObj`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateObjectBrowserModuleFunctionController->function_key`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateObjectBrowserModuleFunctionController->extClassConf`
+* :php:`TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateObjectBrowserModuleFunctionController->localLangFile`
+
+The following class methods have been set from public to protected and will not be accessible in TYPO3 v10 anymore:
+
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->getExternalItemConfig()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->init()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->clearCache()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->main()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->setInPageArray()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->menuConfig()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->mergeExternalItems()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->handleExternalFunctionValue()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->checkExtObj()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->extObjContent()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->getExtObjContent()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->checkSubExtObj()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateModuleController->extObjHeader()`
+* :php:`TYPO3CMSTstemplateControllerTemplateAnalyzerModuleFunctionControllerinitialize_editor()`
+* :php:`TYPO3CMSTstemplateControllerTemplateAnalyzerModuleFunctionControllermodMenu()`
+* :php:`TYPO3CMSTstemplateControllerTemplateAnalyzerModuleFunctionControllerhandleExternalFunctionValue()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateConstantEditorModuleFunctionControllerinitialize_editor()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateConstantEditorModuleFunctionControllerhandleExternalFunctionValue()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateInformationModuleFunctionControllerinitialize_editor()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateInformationModuleFunctionControllertableRowData()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateInformationModuleFunctionControllerhandleExternalFunctionValue()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateObjectBrowserModuleFunctionControllerinitialize_editor()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateObjectBrowserModuleFunctionControllermodMenu()`
+* :php:`TYPO3CMSTstemplateControllerTypoScriptTemplateObjectBrowserModuleFunctionControllerhandleExternalFunctionValue()`
+
+
+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
+======================
+
+There are not many extensions that extend the `tstemplate` extension with own modules, it is relatively
+unlikely that instances are affected by this.
+
+
+Migration
+=========
+
+If extending the `tstemplate` 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:tstemplate
\ No newline at end of file
index f5041ac..62d999f 100644 (file)
@@ -14,8 +14,10 @@ namespace TYPO3\CMS\Tstemplate\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
+use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
@@ -24,12 +26,34 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
 /**
  * TypoScript template analyzer
  */
-class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
+class TemplateAnalyzerModuleFunctionController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using TemplateAnalyzerModuleFunctionController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using TemplateAnalyzerModuleFunctionController::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using TemplateAnalyzerModuleFunctionController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using TemplateAnalyzerModuleFunctionController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'initialize_editor' => 'Using TemplateAnalyzerModuleFunctionController::initialize_editor() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modMenu' => 'Using TemplateAnalyzerModuleFunctionController::modMenu() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'handleExternalFunctionValue' => 'Using TemplateAnalyzerModuleFunctionController::handleExternalFunctionValue() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * @var TypoScriptTemplateModuleController
      */
-    public $pObj;
+    protected $pObj;
 
     /**
      * @var string
@@ -48,15 +72,57 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
     protected $templateService;
 
     /**
-     * Init
+     * @var int GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * 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']
+     *
+     * @see init()
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    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.
+     */
+    protected $extClassConf;
+
+    /**
+     * If this value is set it points to a key in the TBE_MODULES_EXT array (not on the top level..) where another classname/filepath/title can be defined for sub-subfunctions.
+     * This is a little hard to explain, so see it in action; it used in the extension 'func_wizards' in order to provide yet a layer of interfacing with the backend module.
+     * The extension 'func_wizards' has this description: 'Adds the 'Wizards' item to the function menu in Web>Func. This is just a framework for wizard extensions.' - so as you can see it is designed to allow further connectivity - 'level 2'
+     *
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
      *
      * @param TypoScriptTemplateModuleController $pObj
      */
     public function init($pObj)
     {
-        parent::init($pObj);
+        $this->pObj = $pObj;
+        // Local lang:
+        if (!empty($this->localLangFile)) {
+            // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+            $this->getLanguageService()->includeLLFile($this->localLangFile);
+        }
+        // Setting MOD_MENU items as we need them for logging:
+        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
         $this->localLanguageFilePath = 'EXT:tstemplate/Resources/Private/Language/locallang_analyzer.xlf';
         $this->pObj->modMenu_setDefaultList .= ',ts_analyzer_checkLinenum,ts_analyzer_checkSyntax';
+        $this->id = (int)GeneralUtility::_GP('id');
     }
 
     /**
@@ -64,7 +130,7 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
      *
      * @return array
      */
-    public function modMenu()
+    protected function modMenu()
     {
         return [
             'ts_analyzer_checkSetup' => '1',
@@ -83,7 +149,7 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
      * @param int $templateUid
      * @return bool
      */
-    public function initialize_editor($pageId, $templateUid = 0)
+    protected function initialize_editor($pageId, $templateUid = 0)
     {
         // Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
         $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
@@ -101,7 +167,7 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
     }
 
     /**
-     * Main
+     * Main, called from parent object
      *
      * @return string
      */
@@ -118,7 +184,7 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
             $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage'];
         }
 
-        $assigns['existTemplate'] = $this->initialize_editor($this->pObj->id, $template_uid);
+        $assigns['existTemplate'] = $this->initialize_editor($this->id, $template_uid);
         if ($assigns['existTemplate']) {
             $assigns['siteTitle'] = trim($this->templateRow['sitetitle']);
             $assigns['templateRecord'] = $this->templateRow;
@@ -137,7 +203,7 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
         )), '');
 
         $urlParameters = [
-            'id' => $this->pObj->id,
+            'id' => $this->id,
             'template' => 'all'
         ];
         /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
@@ -170,7 +236,7 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
 
         foreach ($assigns['checkboxes'] as $key => $conf) {
             $assigns['checkboxes'][$key]['label'] = BackendUtility::getFuncCheck(
-                $this->pObj->id,
+                $this->id,
                 'SET[' . $key . ']',
                 $this->pObj->MOD_SETTINGS[$key],
                 '',
@@ -238,4 +304,27 @@ class TemplateAnalyzerModuleFunctionController extends AbstractFunctionModule
 
         return $view->render();
     }
+
+    /**
+     * If $this->function_key is set (which means there are two levels of object connectivity) then
+     * $this->extClassConf is loaded with the TBE_MODULES_EXT configuration for that sub-sub-module
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected function handleExternalFunctionValue()
+    {
+        // Must clean first to make sure the correct key is set...
+        $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_ts');
+        if ($this->function_key) {
+            $this->extClassConf = $this->pObj->getExternalItemConfig('web_ts', $this->function_key, $this->pObj->MOD_SETTINGS[$this->function_key]);
+        }
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
 }
index dfb6a0c..1ed329d 100644 (file)
@@ -14,9 +14,12 @@ namespace TYPO3\CMS\Tstemplate\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
+use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
@@ -25,12 +28,33 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
 /**
  * TypoScript Constant editor
  */
-class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractFunctionModule
+class TypoScriptTemplateConstantEditorModuleFunctionController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using TypoScriptTemplateConstantEditorModuleFunctionController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using TypoScriptTemplateConstantEditorModuleFunctionController::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using TypoScriptTemplateConstantEditorModuleFunctionController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using TypoScriptTemplateConstantEditorModuleFunctionController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'initialize_editor' => 'Using TypoScriptTemplateConstantEditorModuleFunctionController::initialize_editor() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'handleExternalFunctionValue' => 'Using TypoScriptTemplateConstantEditorModuleFunctionController::handleExternalFunctionValue() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * @var TypoScriptTemplateModuleController
      */
-    public $pObj;
+    protected $pObj;
 
     /**
      * The currently selected sys_template record
@@ -49,6 +73,56 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
     protected $constants;
 
     /**
+     * @var int GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * 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']
+     *
+     * @see init()
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    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.
+     */
+    protected $extClassConf;
+
+    /**
+     * If this value is set it points to a key in the TBE_MODULES_EXT array (not on the top level..) where another classname/filepath/title can be defined for sub-subfunctions.
+     * This is a little hard to explain, so see it in action; it used in the extension 'func_wizards' in order to provide yet a layer of interfacing with the backend module.
+     * The extension 'func_wizards' has this description: 'Adds the 'Wizards' item to the function menu in Web>Func. This is just a framework for wizard extensions.' - so as you can see it is designed to allow further connectivity - 'level 2'
+     *
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
+     *
+     * @param TypoScriptTemplateModuleController $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.
+            $this->getLanguageService()->includeLLFile($this->localLangFile);
+        }
+        $this->id = (int)GeneralUtility::_GP('id');
+    }
+
+    /**
      * Initialize editor
      *
      * Initializes the module.
@@ -58,7 +132,7 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
      * @param int $template_uid
      * @return bool
      */
-    public function initialize_editor($pageId, $template_uid = 0)
+    protected function initialize_editor($pageId, $template_uid = 0)
     {
         $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
 
@@ -83,7 +157,7 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
     }
 
     /**
-     * Main
+     * Main, called from parent object
      *
      * @return string
      */
@@ -92,7 +166,7 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
         $assigns = [];
         $assigns['LLPrefix'] = 'LLL:EXT:tstemplate/Resources/Private/Language/locallang_ceditor.xlf:';
         // Create extension template
-        $this->pObj->createTemplate($this->pObj->id);
+        $this->pObj->createTemplate($this->id);
         // Checking for more than one template an if, set a menu...
         $manyTemplatesMenu = $this->pObj->templateMenu();
         $template_uid = 0;
@@ -101,7 +175,7 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
         }
 
         // initialize
-        $existTemplate = $this->initialize_editor($this->pObj->id, $template_uid);
+        $existTemplate = $this->initialize_editor($this->id, $template_uid);
         if ($existTemplate) {
             $assigns['siteTitle'] = trim($this->templateRow['sitetitle']);
             $assigns['templateRecord'] = $this->templateRow;
@@ -109,7 +183,6 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
                 $assigns['manyTemplatesMenu'] = $manyTemplatesMenu;
             }
 
-            $this->getPageRenderer();
             $saveId = $this->templateRow['_ORIG_uid'] ?: $this->templateRow['uid'];
             // Update template ?
             if (GeneralUtility::_POST('_savedok')) {
@@ -127,23 +200,23 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
                     $tce->clear_cacheCmd('all');
                     // re-read the template ...
                     // re-read the constants as they have changed
-                    $this->initialize_editor($this->pObj->id, $template_uid);
+                    $this->initialize_editor($this->id, $template_uid);
                 }
             }
             // Resetting the menu (start). I wonder if this in any way is a violation of the menu-system. Haven't checked. But need to do it here, because the menu is dependent on the categories available.
             $this->pObj->MOD_MENU['constant_editor_cat'] = $this->templateService->ext_getCategoryLabelArray();
-            $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), $this->pObj->MCONF['name']);
+            $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_ts');
             // Resetting the menu (stop)
             $assigns['title'] = $this->pObj->linkWrapTemplateTitle($this->templateRow['title'], 'constants');
             if (!empty($this->pObj->MOD_MENU['constant_editor_cat'])) {
-                $assigns['constantsMenu'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[constant_editor_cat]', $this->pObj->MOD_SETTINGS['constant_editor_cat'], $this->pObj->MOD_MENU['constant_editor_cat']);
+                $assigns['constantsMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[constant_editor_cat]', $this->pObj->MOD_SETTINGS['constant_editor_cat'], $this->pObj->MOD_MENU['constant_editor_cat']);
             }
             // Category and constant editor config:
             $category = $this->pObj->MOD_SETTINGS['constant_editor_cat'];
 
             $printFields = trim($this->templateService->ext_printFields($this->constants, $category));
             foreach ($this->templateService->getInlineJavaScript() as $name => $inlineJavaScript) {
-                $this->pageRenderer->addJsInlineCode($name, $inlineJavaScript);
+                $this->getPageRenderer()->addJsInlineCode($name, $inlineJavaScript);
             }
 
             if ($printFields) {
@@ -161,4 +234,35 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
         }
         return $theOutput;
     }
+
+    /**
+     * If $this->function_key is set (which means there are two levels of object connectivity) then
+     * $this->extClassConf is loaded with the TBE_MODULES_EXT configuration for that sub-sub-module
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected function handleExternalFunctionValue()
+    {
+        // Must clean first to make sure the correct key is set...
+        $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_ts');
+        if ($this->function_key) {
+            $this->extClassConf = $this->pObj->getExternalItemConfig('web_ts', $this->function_key, $this->pObj->MOD_SETTINGS[$this->function_key]);
+        }
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * @return PageRenderer
+     */
+    protected function getPageRenderer(): PageRenderer
+    {
+        return GeneralUtility::makeInstance(PageRenderer::class);
+    }
 }
index 272aad1..ed6e12f 100644 (file)
@@ -14,7 +14,9 @@ namespace TYPO3\CMS\Tstemplate\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait;
+use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -24,19 +26,43 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
 /**
  * This class displays the Info/Modify screen of the Web > Template module
  */
-class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunctionModule
+class TypoScriptTemplateInformationModuleFunctionController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using TypoScriptTemplateInformationModuleFunctionController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using TypoScriptTemplateInformationModuleFunctionController::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using TypoScriptTemplateInformationModuleFunctionController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using TypoScriptTemplateInformationModuleFunctionController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+        'tce_processed' => 'Using TypoScriptTemplateInformationModuleFunctionController::$tce_processed is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'initialize_editor' => 'Using TypoScriptTemplateInformationModuleFunctionController::initialize_editor() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'tableRowData' => 'Using TypoScriptTemplateInformationModuleFunctionController::tableRowData() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'handleExternalFunctionValue' => 'Using TypoScriptTemplateInformationModuleFunctionController::handleExternalFunctionValue() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * Indicator for t3editor, whether data is stored
      *
      * @var bool
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
      */
-    public $tce_processed = false;
+    protected $tce_processed = false;
 
     /**
      * @var TypoScriptTemplateModuleController
      */
-    public $pObj;
+    protected $pObj;
 
     /**
      * The currently selected sys_template record
@@ -50,6 +76,56 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
     protected $templateService;
 
     /**
+     * @var int GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * 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']
+     *
+     * @see init()
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    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.
+     */
+    protected $extClassConf;
+
+    /**
+     * If this value is set it points to a key in the TBE_MODULES_EXT array (not on the top level..) where another classname/filepath/title can be defined for sub-subfunctions.
+     * This is a little hard to explain, so see it in action; it used in the extension 'func_wizards' in order to provide yet a layer of interfacing with the backend module.
+     * The extension 'func_wizards' has this description: 'Adds the 'Wizards' item to the function menu in Web>Func. This is just a framework for wizard extensions.' - so as you can see it is designed to allow further connectivity - 'level 2'
+     *
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
+     *
+     * @param TypoScriptTemplateModuleController $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.
+            $this->getLanguageService()->includeLLFile($this->localLangFile);
+        }
+        $this->id = (int)GeneralUtility::_GP('id');
+    }
+
+    /**
      * Gets the data for a row of a HTML table in the fluid template
      *
      * @param string $label The label to be shown (e.g. 'Title:', 'Sitetitle:')
@@ -58,10 +134,10 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
      * @param int $id The field/variable to be sent on clicking the edit icon (e.g. 'title', 'sitetitle')
      * @return array Data for a row of a HTML table
      */
-    public function tableRowData($label, $data, $field, $id)
+    protected function tableRowData($label, $data, $field, $id)
     {
         $urlParameters = [
-            'id' => $this->pObj->id,
+            'id' => $this->id,
             'edit' => [
                 'sys_template' => [
                     $id => 'edit'
@@ -93,7 +169,7 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
      * @param int $template_uid The uid of the template record to be rendered (only if more than one template on the current page)
      * @return bool Returns TRUE if a template record was found, otherwise FALSE
      */
-    public function initialize_editor($pageId, $template_uid = 0)
+    protected function initialize_editor($pageId, $template_uid = 0)
     {
         $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
 
@@ -106,15 +182,7 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
     }
 
     /**
-     * @return LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * The main processing method if this class
+     * Main, called from parent object
      *
      * @return string Information of the template status or the taken actions as HTML string
      */
@@ -127,7 +195,7 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
             $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage'];
         }
         // Initialize
-        $existTemplate = $this->initialize_editor($this->pObj->id, $template_uid);
+        $existTemplate = $this->initialize_editor($this->id, $template_uid);
         $saveId = 0;
         if ($existTemplate) {
             $saveId = $this->templateRow['_ORIG_uid'] ?: $this->templateRow['uid'];
@@ -135,11 +203,11 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
         /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
         $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
         // Create extension template
-        $newId = $this->pObj->createTemplate($this->pObj->id, $saveId);
+        $newId = $this->pObj->createTemplate($this->id, $saveId);
         if ($newId) {
             // Switch to new template
             $urlParameters = [
-                'id' => $this->pObj->id,
+                'id' => $this->id,
                 'SET[templatesOnPage]' => $newId
             ];
             $url = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
@@ -192,4 +260,27 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
         }
         return $theOutput;
     }
+
+    /**
+     * If $this->function_key is set (which means there are two levels of object connectivity) then
+     * $this->extClassConf is loaded with the TBE_MODULES_EXT configuration for that sub-sub-module
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected function handleExternalFunctionValue()
+    {
+        // Must clean first to make sure the correct key is set...
+        $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_ts');
+        if ($this->function_key) {
+            $this->extClassConf = $this->pObj->getExternalItemConfig('web_ts', $this->function_key, $this->pObj->MOD_SETTINGS[$this->function_key]);
+        }
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
 }
index 38ba4e5..eca778e 100644 (file)
@@ -16,10 +16,13 @@ namespace TYPO3\CMS\Tstemplate\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\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\Database\Query\QueryBuilder;
@@ -27,6 +30,10 @@ use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
 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\Page\PageRenderer;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -38,32 +45,78 @@ use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
 /**
  * Module: TypoScript Tools
  */
-class TypoScriptTemplateModuleController extends BaseScriptClass
+class TypoScriptTemplateModuleController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
     /**
-     * @var string
+     * @var array
      */
-    public $perms_clause;
+    private $deprecatedPublicProperties = [
+        'textExtensions' => 'Using TypoScriptTemplateModuleController::$textExtensions is deprecated and will not be possible anymore in TYPO3 v10.',
+        'pageinfo' => 'Using TypoScriptTemplateModuleController::$pageinfo is deprecated and will not be possible anymore in TYPO3 v10.',
+        'id' => 'Using TypoScriptTemplateModuleController::$id is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modTSconfig' => 'Using TypoScriptTemplateModuleController::$modTSconfig is deprecated and will not be possible anymore in TYPO3 v10.',
+        'content' => 'Using TypoScriptTemplateModuleController::$content is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObj' => 'Using TypoScriptTemplateModuleController::$extObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'access' => 'Using TypoScriptTemplateModuleController::$access is deprecated and will not be possible anymore in TYPO3 v10.',
+        'perms_clause' => 'Using TypoScriptTemplateModuleController::$perms_clause is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extClassConf' => 'Using TypoScriptTemplateModuleController::$extClassConf is deprecated and will not be possible anymore in TYPO3 v10.',
+        'edit' => 'Using TypoScriptTemplateModuleController::$edit is deprecated, property will be removed in TYPO3 v10.',
+        'modMenu_type' => 'Using TypoScriptTemplateModuleController::$modMenu_type is deprecated, property will be removed in TYPO3 v10.',
+        'MCONF' => 'Using TypoScriptTemplateModuleController::$MCONF is deprecated, property will be removed in TYPO3 v10.',
+        'CMD' => 'Using TypoScriptTemplateModuleController::$CMD is deprecated, property will be removed in TYPO3 v10.',
+        'sObj' => 'Using TypoScriptTemplateModuleController::$sObj is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'getExternalItemConfig' => 'Using TypoScriptTemplateModuleController::getExternalItemConfig() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'init' => 'Using TypoScriptTemplateModuleController::init() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'clearCache' => 'Using TypoScriptTemplateModuleController::clearCache() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'main' => 'Using TypoScriptTemplateModuleController::main() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'setInPageArray' => 'Using TypoScriptTemplateModuleController::setInPageArray() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'menuConfig' => 'Using TypoScriptTemplateModuleController::menuConfig() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'mergeExternalItems' => 'Using TypoScriptTemplateModuleController::mergeExternalItems() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'handleExternalFunctionValue' => 'Using TypoScriptTemplateModuleController::handleExternalFunctionValue() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'checkExtObj' => 'Using TypoScriptTemplateModuleController::checkExtObj() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'extObjContent' => 'Using TypoScriptTemplateModuleController::extObjContent() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'getExtObjContent' => 'Using TypoScriptTemplateModuleController::getExtObjContent() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'checkSubExtObj' => 'Using TypoScriptTemplateModuleController::checkSubExtObj() is deprecated, method will be removed in TYPO3 v10.',
+        'extObjHeader' => 'Using TypoScriptTemplateModuleController::extObjHeader() is deprecated, method will be removed in TYPO3 v10.',
+    ];
 
     /**
      * @var string
      */
-    public $sObj;
+    protected $perms_clause;
 
     /**
      * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
      */
-    public $edit;
+    protected $sObj;
 
     /**
      * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
      */
-    public $textExtensions = 'html,htm,txt,css,tmpl,inc,js';
+    protected $edit;
 
     /**
      * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected $textExtensions = 'html,htm,txt,css,tmpl,inc,js';
+
+    /**
+     * @var string Written by client classes.
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10. Remove last usages, too.
      */
-    public $modMenu_type = '';
+    protected $modMenu_type = '';
 
     /**
      * @var string
@@ -71,19 +124,19 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     public $modMenu_dontValidateList = '';
 
     /**
-     * @var string
+     * @var string Written by client classes
      */
     public $modMenu_setDefaultList = '';
 
     /**
      * @var array
      */
-    public $pageinfo = [];
+    protected $pageinfo = [];
 
     /**
      * @var bool
      */
-    public $access = false;
+    protected $access = false;
 
     /**
      * The name of the module
@@ -105,6 +158,75 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     protected $templateService;
 
     /**
+     * Loaded with the global array $MCONF which holds some module configuration from the conf.php file of backend modules.
+     *
+     * @var array
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected $MCONF = [];
+
+    /**
+     * @var int 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.
+     */
+    protected $CMD;
+
+    /**
+     * 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, used in client classes
+     *
+     * @see $MOD_MENU
+     * @var array
+     */
+    public $MOD_SETTINGS = [];
+
+    /**
+     * Module TSconfig based on PAGE TSconfig / USER TSconfig
+     *
+     * @var array
+     */
+    protected $modTSconfig;
+
+    /**
+     * Contains module configuration parts from TBE_MODULES_EXT if found
+     *
+     * @see handleExternalFunctionValue()
+     * @var array
+     */
+    protected $extClassConf;
+
+    /**
+     * Generally used for accumulating the output content of backend modules
+     *
+     * @var string
+     */
+    protected $content = '';
+
+    /**
+     * May contain an instance of a 'Function menu module' which connects to this backend module.
+     *
+     * @see checkExtObj()
+     * @var \object
+     */
+    protected $extObj;
+
+    /**
      * Constructor
      */
     public function __construct()
@@ -112,6 +234,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
         $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
         $this->getLanguageService()->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang.xlf');
 
+        // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
         $this->MCONF = [
             'name' => $this->moduleName
         ];
@@ -129,11 +252,16 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     /**
      * Init
      */
-    public function init()
+    protected function init()
     {
-        parent::init();
+        // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+        $this->CMD = GeneralUtility::_GP('CMD');
+        $this->menuConfig();
+        $this->handleExternalFunctionValue();
         $this->id = (int)GeneralUtility::_GP('id');
+        // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
         $this->sObj = GeneralUtility::_GP('sObj');
+        // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
         $this->edit = GeneralUtility::_GP('edit');
         $this->perms_clause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW);
     }
@@ -141,10 +269,9 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     /**
      * Clear cache
      */
-    public function clearCache()
+    protected function clearCache()
     {
         if (GeneralUtility::_GP('clear_all_cache')) {
-            /** @var DataHandler $tce */
             $tce = GeneralUtility::makeInstance(DataHandler::class);
             $tce->start([], []);
             $tce->clear_cacheCmd('all');
@@ -154,15 +281,14 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     /**
      * Main
      */
-    public function main()
+    protected function main()
     {
         // Access check...
         // The page will show only if there is a valid page and if this page may be viewed by the user
         $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
         $this->access = is_array($this->pageinfo);
         $view = $this->getFluidTemplateObject('tstemplate');
-        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         if ($this->id && $this->access) {
             $urlParameters = [
                 'id' => $this->id,
@@ -264,8 +390,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     {
         $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
         $menu->setIdentifier('WebFuncJumpMenu');
-        /** @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()
@@ -298,7 +423,9 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
      */
     public function mainAction(ServerRequestInterface $request): ResponseInterface
     {
+        // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
         $GLOBALS['SOBE'] = $this;
+
         $this->init();
 
         // Checking for first level external objects
@@ -339,8 +466,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
                     'template' => 'all',
                     'createExtension' => 'new'
                 ];
-                /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-                $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+                $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
                 $newButton = $buttonBar->makeLinkButton()
                     ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters))
                     ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.pagetitle'))
@@ -363,36 +489,34 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
                     ))
                     ->setShowLabelText(true);
                 $buttonBar->addButton($saveButton);
-            } elseif ($this->extClassConf['name'] === TypoScriptTemplateObjectBrowserModuleFunctionController::class) {
-                if (!empty($this->sObj)) {
-                    // BACK
-                    $urlParameters = [
-                        'id' => $this->id
-                    ];
-                    /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-                    $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
-                    $backButton = $buttonBar->makeLinkButton()
-                        ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters))
-                        ->setClasses('typo3-goBack')
-                        ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
-                        ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
-                            'actions-view-go-back',
-                            Icon::SIZE_SMALL
-                        ));
-                    $buttonBar->addButton($backButton);
-                }
+            } elseif ($this->extClassConf['name'] === TypoScriptTemplateObjectBrowserModuleFunctionController::class
+                && !empty(GeneralUtility::_GP('sObj'))
+            ) {
+                // back button in edit mode of object browser. "sObj" is set by ExtendedTemplateService
+                $urlParameters = [
+                    'id' => $this->id
+                ];
+                $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+                $backButton = $buttonBar->makeLinkButton()
+                    ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters))
+                    ->setClasses('typo3-goBack')
+                    ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
+                    ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
+                        'actions-view-go-back',
+                        Icon::SIZE_SMALL
+                    ));
+                $buttonBar->addButton($backButton);
             }
         }
         // Shortcut
         $shortcutButton = $buttonBar->makeShortcutButton()
-            ->setModuleName($this->MCONF['name'])
+            ->setModuleName('web_ts')
             ->setGetVariables(['id', 'route']);
         $buttonBar->addButton($shortcutButton);
     }
 
-    // OTHER FUNCTIONS:
     /**
-     * Wrap title for link in template
+     * Wrap title for link in template, called from client classes.
      *
      * @param string $title
      * @param string $onlyKey
@@ -403,8 +527,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
         $urlParameters = [
             'id' => $this->id
         ];
-        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
         if ($onlyKey) {
             $title = '<a href="' . htmlspecialchars($aHref . '&e[' . $onlyKey . ']=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController') . '">' . htmlspecialchars($title) . '</a>';
@@ -415,7 +538,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     }
 
     /**
-     * No template
+     * No template, called from client classes.
      *
      * @param int $newStandardTemplate
      * @return string
@@ -455,8 +578,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
             $urlParameters = [
                 'id' => $previousPage['uid']
             ];
-            /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-            $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
+            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
             $previousPage['aHref'] = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
             $moduleContent['previousPage'] = $previousPage;
         }
@@ -466,7 +588,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     }
 
     /**
-     * Render template menu
+     * Render template menu, called from client classes.
      *
      * @return string
      */
@@ -484,7 +606,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
         $this->MOD_SETTINGS = BackendUtility::getModuleData(
             $this->MOD_MENU,
             GeneralUtility::_GP('SET'),
-            $this->MCONF['name'],
+            'web_ts',
             $this->modMenu_type,
             $this->modMenu_dontValidateList,
             $this->modMenu_setDefaultList
@@ -498,7 +620,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     }
 
     /**
-     * Create template
+     * Create template, called from client classes.
      *
      * @param int $id
      * @param int $actTemplateId
@@ -507,7 +629,6 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
     public function createTemplate($id, $actTemplateId = 0)
     {
         $recData = [];
-        /** @var DataHandler $tce */
         $tce = GeneralUtility::makeInstance(DataHandler::class);
 
         if (GeneralUtility::_GP('createExtension')) {
@@ -561,7 +682,7 @@ page.10.value = HELLO WORLD!
      * @param array $rlArr Rootline array
      * @param array $row Record of sys_template
      */
-    public function setInPageArray(&$pArray, $rlArr, $row)
+    protected function setInPageArray(&$pArray, $rlArr, $row)
     {
         ksort($rlArr);
         reset($rlArr);
@@ -649,7 +770,6 @@ page.10.value = HELLO WORLD!
      */
     protected function getFluidTemplateObject($extensionName, $templateName = 'Main')
     {
-        /** @var StandaloneView $view */
         $view = GeneralUtility::makeInstance(StandaloneView::class);
         $view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName($extensionName);
         $view->getRenderingContext()->setControllerAction($templateName);
@@ -698,4 +818,191 @@ page.10.value = HELLO WORLD!
         }
         return null;
     }
+
+    /**
+     * 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.
+     *
+     * @see init(), $MOD_MENU, $MOD_SETTINGS, \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData(), mergeExternalItems()
+     */
+    protected function menuConfig()
+    {
+        // Page / user TSconfig settings and blinding of menu-items
+        $this->modTSconfig['properties'] = BackendUtility::getPagesTSconfig($this->id)['mod.']['web_ts.'] ?? [];
+        $this->MOD_MENU['function'] = $this->mergeExternalItems('web_ts', '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_ts', $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
+     * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), menuConfig()
+     */
+    protected function mergeExternalItems($modName, $menuKey, $menuArr)
+    {
+        $mergeArray = $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey];
+        if (is_array($mergeArray)) {
+            foreach ($mergeArray as $k => $v) {
+                if (((string)$v['ws'] === '' || $this->getBackendUser()->workspace === 0 && GeneralUtility::inList($v['ws'], 'online')) || $this->getBackendUser()->workspace === -1 && GeneralUtility::inList($v['ws'], 'offline') || $this->getBackendUser()->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)
+     * @see getExternalItemConfig(), init()
+     */
+    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_ts', $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.
+     * @see handleExternalFunctionValue()
+     */
+    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.
+     *
+     * @see handleExternalFunctionValue(), \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), $extObj
+     */
+    protected function checkExtObj()
+    {
+        if (is_array($this->extClassConf) && $this->extClassConf['name']) {
+            $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
+            $this->extObj->init($this);
+            // Re-write:
+            $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), 'web_ts', $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.
+     */
+    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.
+     */
+    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) {
+            $flashMessage = GeneralUtility::makeInstance(
+                FlashMessage::class,
+                $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:no_modules_registered'),
+                $this->getLanguageService()->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;
+    }
+
+    /**
+     * Returns the Language Service
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * Returns the Backend User
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * @return PageRenderer
+     */
+    protected function getPageRenderer(): PageRenderer
+    {
+        return GeneralUtility::makeInstance(PageRenderer::class);
+    }
 }
index a3e98eb..229b214 100644 (file)
@@ -14,12 +14,16 @@ namespace TYPO3\CMS\Tstemplate\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
 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\DataHandling\DataHandler;
 use TYPO3\CMS\Core\Exception;
+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\TypoScript\ExtendedTemplateService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
@@ -28,8 +32,30 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
 /**
  * This class displays the submodule "TypoScript Object Browser" inside the Web > Template module
  */
-class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFunctionModule
+class TypoScriptTemplateObjectBrowserModuleFunctionController
 {
+    use PublicPropertyDeprecationTrait;
+    use PublicMethodDeprecationTrait;
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicProperties = [
+        'pObj' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::$pObj is deprecated and will not be possible anymore in TYPO3 v10.',
+        'function_key' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::$function_key is deprecated, property will be removed in TYPO3 v10.',
+        'extClassConf' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::$extClassConf is deprecated, property will be removed in TYPO3 v10.',
+        'localLangFile' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::$localLangFile is deprecated, property will be removed in TYPO3 v10.',
+    ];
+
+    /**
+     * @var array
+     */
+    private $deprecatedPublicMethods = [
+        'initialize_editor' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::initialize_editor() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'modMenu' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::modMenu() is deprecated and will not be possible anymore in TYPO3 v10.',
+        'handleExternalFunctionValue' => 'Using TypoScriptTemplateObjectBrowserModuleFunctionController::handleExternalFunctionValue() is deprecated, method will be removed in TYPO3 v10.',
+    ];
+
     /**
      * @var string
      */
@@ -38,7 +64,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
     /**
      * @var TypoScriptTemplateModuleController
      */
-    public $pObj;
+    protected $pObj;
 
     /**
      * The currently selected sys_template record
@@ -52,16 +78,58 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
     protected $templateService;
 
     /**
-     * Init
+     * @var int GET/POST var 'id'
+     */
+    protected $id;
+
+    /**
+     * 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']
+     *
+     * @see init()
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    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.
+     */
+    protected $extClassConf;
+
+    /**
+     * If this value is set it points to a key in the TBE_MODULES_EXT array (not on the top level..) where another classname/filepath/title can be defined for sub-subfunctions.
+     * This is a little hard to explain, so see it in action; it used in the extension 'func_wizards' in order to provide yet a layer of interfacing with the backend module.
+     * The extension 'func_wizards' has this description: 'Adds the 'Wizards' item to the function menu in Web>Func. This is just a framework for wizard extensions.' - so as you can see it is designed to allow further connectivity - 'level 2'
+     *
+     * @var string
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected $function_key = '';
+
+    /**
+     * Init, called from parent object
      *
      * @param TypoScriptTemplateModuleController $pObj
      */
     public function init($pObj)
     {
-        parent::init($pObj);
+        $this->pObj = $pObj;
+        // Local lang:
+        if (!empty($this->localLangFile)) {
+            // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+            $this->getLanguageService()->includeLLFile($this->localLangFile);
+        }
+        // Setting MOD_MENU items as we need them for logging:
+        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
         $this->pObj->modMenu_dontValidateList .= ',ts_browser_toplevel_setup,ts_browser_toplevel_const,ts_browser_TLKeys_setup,ts_browser_TLKeys_const';
         $this->pObj->modMenu_setDefaultList .= ',ts_browser_fixedLgd,ts_browser_showComments';
         $this->localLanguageFilePath = 'EXT:tstemplate/Resources/Private/Language/locallang_objbrowser.xlf';
+        $this->id = (int)GeneralUtility::_GP('id');
     }
 
     /**
@@ -69,7 +137,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
      *
      * @return array
      */
-    public function modMenu()
+    protected function modMenu()
     {
         $lang = $this->getLanguageService();
         $lang->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang_objbrowser.xlf');
@@ -104,7 +172,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
                 } else {
                     unset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][key($addKey)]);
                 }
-                $this->getBackendUserAuthentication()->pushModuleData($this->pObj->MCONF['name'], $this->pObj->MOD_SETTINGS);
+                $this->getBackendUserAuthentication()->pushModuleData('web_ts', $this->pObj->MOD_SETTINGS);
             }
             if (!empty($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType])) {
                 $modMenu['ts_browser_toplevel_' . $bType]['-'] = '---';
@@ -123,7 +191,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
      * @param int $template_uid
      * @return bool
      */
-    public function initialize_editor($pageId, $template_uid = 0)
+    protected function initialize_editor($pageId, $template_uid = 0)
     {
         // Defined global here!
         $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
@@ -140,7 +208,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
     }
 
     /**
-     * Main
+     * Main, called from parent object
      *
      * @return string
      */
@@ -156,7 +224,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage'];
         }
         $bType = $this->pObj->MOD_SETTINGS['ts_browser_type'];
-        $existTemplate = $this->initialize_editor($this->pObj->id, $template_uid);
+        $existTemplate = $this->initialize_editor($this->id, $template_uid);
         // initialize
         $assigns = [];
         $assigns['LLPrefix'] = 'LLL:' . $this->localLanguageFilePath . ':';
@@ -217,7 +285,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
                     // Clear the cache (note: currently only admin-users can clear the cache in tce_main.php)
                     $tce->clear_cacheCmd('all');
                     // re-read the template ...
-                    $this->initialize_editor($this->pObj->id, $template_uid);
+                    $this->initialize_editor($this->id, $template_uid);
                 }
             }
         }
@@ -234,13 +302,15 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             $update = 1;
         }
         if ($update) {
-            $this->getBackendUserAuthentication()->pushModuleData($this->pObj->MCONF['name'], $this->pObj->MOD_SETTINGS);
+            $this->getBackendUserAuthentication()->pushModuleData('web_ts', $this->pObj->MOD_SETTINGS);
         }
         $this->templateService->matchAlternative = $this->pObj->MOD_SETTINGS['tsbrowser_conditions'];
         $this->templateService->matchAlternative[] = 'dummydummydummydummydummydummydummydummydummydummydummy';
         // This is just here to make sure that at least one element is in the array so that the tsparser actually uses this array to match.
         $this->templateService->constantMode = $this->pObj->MOD_SETTINGS['ts_browser_const'];
-        if ($this->pObj->sObj && $this->templateService->constantMode) {
+        // "sObj" is set by ExtendedTemplateService to edit single keys
+        $sObj = GeneralUtility::_GP('sObj');
+        if (!empty($sObj) && $this->templateService->constantMode) {
             $this->templateService->constantMode = 'untouched';
         }
         $this->templateService->regexMode = $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'];
@@ -261,9 +331,9 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             $theSetup = $this->templateService->setup_constants;
         }
         // EDIT A VALUE:
-        $assigns['typoScriptPath'] = $this->pObj->sObj;
-        if ($this->pObj->sObj) {
-            list($theSetup, $theSetupValue) = $this->templateService->ext_getSetup($theSetup, $this->pObj->sObj ? $this->pObj->sObj : '');
+        $assigns['typoScriptPath'] = $sObj;
+        if (!empty($sObj)) {
+            list($theSetup, $theSetupValue) = $this->templateService->ext_getSetup($theSetup, $sObj);
             $assigns['theSetupValue'] = $theSetupValue;
             if ($existTemplate === false) {
                 $noTemplateMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noCurrentTemplate'), $lang->getLL('edit'), FlashMessage::ERROR);
@@ -271,20 +341,20 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             }
             // Links:
             $urlParameters = [
-                'id' => $this->pObj->id
+                'id' => $this->id
             ];
             /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
             $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
             $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
             $assigns['moduleUrl'] = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
-            $assigns['isNotInTopLevelKeyList'] = !isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$this->pObj->sObj]);
+            $assigns['isNotInTopLevelKeyList'] = !isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$sObj]);
             $assigns['hasProperties'] = !empty($theSetup);
-            if (!$this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$this->pObj->sObj]) {
+            if (!$this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$sObj]) {
                 if (!empty($theSetup)) {
-                    $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($this->pObj->sObj) . ']=1&SET[ts_browser_toplevel_' . $bType . ']=' . rawurlencode($this->pObj->sObj);
+                    $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($sObj) . ']=1&SET[ts_browser_toplevel_' . $bType . ']=' . rawurlencode($sObj);
                 }
             } else {
-                $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($this->pObj->sObj) . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0';
+                $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($sObj) . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0';
             }
         } else {
             $this->templateService->tsbrowser_depthKeys = $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType];
@@ -307,14 +377,14 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             }
             $assigns['hasTsBrowserTypes'] = is_array($this->pObj->MOD_MENU['ts_browser_type']) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1;
             if (is_array($this->pObj->MOD_MENU['ts_browser_type']) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1) {
-                $assigns['browserTypeDropdownMenu'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[ts_browser_type]', $bType, $this->pObj->MOD_MENU['ts_browser_type']);
+                $assigns['browserTypeDropdownMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_type]', $bType, $this->pObj->MOD_MENU['ts_browser_type']);
             }
             $assigns['hasTopLevelInObjectList'] = is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1;
             if (is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1) {
-                $assigns['objectListDropdownMenu'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[ts_browser_toplevel_' . $bType . ']', $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType], $this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]);
+                $assigns['objectListDropdownMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_toplevel_' . $bType . ']', $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType], $this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]);
             }
 
-            $assigns['regexSearchCheckbox'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_regexsearch]', $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'], '', '', 'id="checkTs_browser_regexsearch"');
+            $assigns['regexSearchCheckbox'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_regexsearch]', $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'], '', '', 'id="checkTs_browser_regexsearch"');
             $assigns['postSearchField'] = $POST['search_field'];
             $theKey = $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType];
             if (!$theKey || !str_replace('-', '', $theKey)) {
@@ -324,7 +394,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             $tree = $this->templateService->ext_getObjTree($theSetup, $theKey, '', '', $theSetupValue, $this->pObj->MOD_SETTINGS['ts_browser_alphaSort']);
             $tree = $this->templateService->substituteCMarkers($tree);
             $urlParameters = [
-                'id' => $this->pObj->id
+                'id' => $this->id
             ];
             /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
             $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
@@ -352,11 +422,11 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
 
             // second row options
             $assigns['isSetupAndCropLinesDisabled'] = $bType === 'setup' && !$this->pObj->MOD_SETTINGS['ts_browser_fixedLgd'];
-            $assigns['checkBoxShowComments'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_showComments]', $this->pObj->MOD_SETTINGS['ts_browser_showComments'], '', '', 'id="checkTs_browser_showComments"');
-            $assigns['checkBoxAlphaSort'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_alphaSort]', $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'], '', '', 'id="checkTs_browser_alphaSort"');
-            $assigns['checkBoxCropLines'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_fixedLgd]', $this->pObj->MOD_SETTINGS['ts_browser_fixedLgd'], '', '', 'id="checkTs_browser_fixedLgd"');
+            $assigns['checkBoxShowComments'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_showComments]', $this->pObj->MOD_SETTINGS['ts_browser_showComments'], '', '', 'id="checkTs_browser_showComments"');
+            $assigns['checkBoxAlphaSort'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_alphaSort]', $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'], '', '', 'id="checkTs_browser_alphaSort"');
+            $assigns['checkBoxCropLines'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_fixedLgd]', $this->pObj->MOD_SETTINGS['ts_browser_fixedLgd'], '', '', 'id="checkTs_browser_fixedLgd"');
             if ($bType === 'setup' && !$this->pObj->MOD_SETTINGS['ts_browser_fixedLgd']) {
-                $assigns['dropdownDisplayConstants'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[ts_browser_const]', $this->pObj->MOD_SETTINGS['ts_browser_const'], $this->pObj->MOD_MENU['ts_browser_const']);
+                $assigns['dropdownDisplayConstants'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_const]', $this->pObj->MOD_SETTINGS['ts_browser_const'], $this->pObj->MOD_MENU['ts_browser_const']);
             }
 
             // Conditions:
@@ -375,8 +445,7 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
             }
             // Ending section displayoptions
         }
-        $this->getPageRenderer();
-        $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
+        $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
         $view = GeneralUtility::makeInstance(StandaloneView::class);
         $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
             'EXT:tstemplate/Resources/Private/Templates/TemplateObjectBrowserModuleFunction.html'
@@ -399,4 +468,43 @@ class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFu
         $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
         $defaultFlashMessageQueue->enqueue($flashMessage);
     }
+
+    /**
+     * If $this->function_key is set (which means there are two levels of object connectivity) then
+     * $this->extClassConf is loaded with the TBE_MODULES_EXT configuration for that sub-sub-module
+     *
+     * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
+     */
+    protected function handleExternalFunctionValue()
+    {
+        // Must clean first to make sure the correct key is set...
+        $this->pObj->MOD_SETTINGS = BackendUtility::getModuleData($this->pObj->MOD_MENU, GeneralUtility::_GP('SET'), 'web_ts');
+        if ($this->function_key) {
+            $this->extClassConf = $this->pObj->getExternalItemConfig('web_ts', $this->function_key, $this->pObj->MOD_SETTINGS[$this->function_key]);
+        }
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUserAuthentication(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * @return PageRenderer
+     */
+    protected function getPageRenderer(): PageRenderer
+    {
+        return GeneralUtility::makeInstance(PageRenderer::class);
+    }
 }