[TASK] Cleanup and deprecate TYPO3_DB occurrences
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Module / BaseScriptClass.php
1 <?php
2 namespace TYPO3\CMS\Backend\Module;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
19 use TYPO3\CMS\Core\Database\DatabaseConnection;
20 use TYPO3\CMS\Core\Messaging\FlashMessage;
21 use TYPO3\CMS\Core\Messaging\FlashMessageService;
22 use TYPO3\CMS\Core\Page\PageRenderer;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Lang\LanguageService;
25
26 /**
27 * Parent class for 'ScriptClasses' in backend modules.
28 *
29 * EXAMPLE PROTOTYPE
30 *
31 * As for examples there are lots of them if you search for classes which extends \TYPO3\CMS\Backend\Module\BaseScriptClass
32 * However you can see a prototype example of how a module might use this class in an index.php file typically hosting a backend module.
33 *
34 * NOTICE: This example only outlines the basic structure of how this class is used.
35 * You should consult the documentation and other real-world examples for some actual things to do when building modules.
36 *
37 * TYPICAL SETUP OF A BACKEND MODULE:
38 *
39 * PrototypeController EXTENDS THE CLASS \TYPO3\CMS\Backend\Module\BaseScriptClass with a main() and printContent() function:
40 *
41 * namespace Vendor\Prototype\Controller;
42 *
43 * class PrototypeController extends \TYPO3\CMS\Backend\Module\BaseScriptClass {
44 * public function __construct() {
45 * $this->getLanguageService()->includeLLFile('EXT:prototype/Resources/Private/Language/locallang.xlf');
46 * $this->getBackendUser()->modAccess($GLOBALS['MCONF'], TRUE);
47 * }
48 * }
49 *
50 * MAIN FUNCTION - HERE YOU CREATE THE MODULE CONTENT IN $this->content
51 * public function main() {
52 * TYPICALLY THE INTERNAL VAR, $this->doc is instantiated like this:
53 * $this->doc = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
54 * ... AND OF COURSE A LOT OF OTHER THINGS GOES ON - LIKE PUTTING CONTENT INTO $this->content
55 * $this->content='';
56 * }
57 * PRINT CONTENT - DONE AS THE LAST THING
58 * public function printContent() {
59 * echo $this->content;
60 * }
61 *
62 * MAKE INSTANCE OF THE SCRIPT CLASS AND CALL init()
63 * $GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Vendor\Prototype\Controller\PrototypeController::class);
64 * $GLOBALS['SOBE']->init();
65 *
66 *
67 * THEN WE WILL CHECK IF THERE IS A 'SUBMODULE' REGISTERED TO BE INITIALIZED AS WELL:
68 * $GLOBALS['SOBE']->checkExtObj();
69 *
70 * THEN WE CALL THE main() METHOD AND THIS SHOULD SPARK THE CREATION OF THE MODULE OUTPUT.
71 * $GLOBALS['SOBE']->main();
72 * FINALLY THE printContent() FUNCTION WILL OUTPUT THE ACCUMULATED CONTENT
73 * $GLOBALS['SOBE']->printContent();
74 */
75 class BaseScriptClass
76 {
77 /**
78 * Loaded with the global array $MCONF which holds some module configuration from the conf.php file of backend modules.
79 *
80 * @see init()
81 * @var array
82 */
83 public $MCONF = [];
84
85 /**
86 * The integer value of the GET/POST var, 'id'. Used for submodules to the 'Web' module (page id)
87 *
88 * @see init()
89 * @var int
90 */
91 public $id;
92
93 /**
94 * The value of GET/POST var, 'CMD'
95 *
96 * @see init()
97 * @var mixed
98 */
99 public $CMD;
100
101 /**
102 * A WHERE clause for selection records from the pages table based on read-permissions of the current backend user.
103 *
104 * @see init()
105 * @var string
106 */
107 public $perms_clause;
108
109 /**
110 * The module menu items array. Each key represents a key for which values can range between the items in the array of that key.
111 *
112 * @see init()
113 * @var array
114 */
115 public $MOD_MENU = [
116 'function' => []
117 ];
118
119 /**
120 * Current settings for the keys of the MOD_MENU array
121 *
122 * @see $MOD_MENU
123 * @var array
124 */
125 public $MOD_SETTINGS = [];
126
127 /**
128 * Module TSconfig based on PAGE TSconfig / USER TSconfig
129 *
130 * @see menuConfig()
131 * @var array
132 */
133 public $modTSconfig;
134
135 /**
136 * 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.
137 * Can be set from extension classes of this class before the init() function is called.
138 *
139 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()
140 * @var string
141 */
142 public $modMenu_type = '';
143
144 /**
145 * 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.
146 * Can be set from extension classes of this class before the init() function is called.
147 *
148 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()
149 * @var string
150 */
151 public $modMenu_dontValidateList = '';
152
153 /**
154 * List of default values from $MOD_MENU to set in the output array (only if the values from MOD_MENU are not arrays)
155 * Can be set from extension classes of this class before the init() function is called.
156 *
157 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()
158 * @var string
159 */
160 public $modMenu_setDefaultList = '';
161
162 /**
163 * Contains module configuration parts from TBE_MODULES_EXT if found
164 *
165 * @see handleExternalFunctionValue()
166 * @var array
167 */
168 public $extClassConf;
169
170 /**
171 * Generally used for accumulating the output content of backend modules
172 *
173 * @var string
174 */
175 public $content = '';
176
177 /**
178 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
179 */
180 public $doc;
181
182 /**
183 * May contain an instance of a 'Function menu module' which connects to this backend module.
184 *
185 * @see checkExtObj()
186 * @var AbstractFunctionModule
187 */
188 public $extObj;
189
190 /**
191 * @var PageRenderer
192 */
193 protected $pageRenderer = null;
194
195 /**
196 * Initializes the backend module by setting internal variables, initializing the menu.
197 *
198 * @return void
199 * @see menuConfig()
200 */
201 public function init()
202 {
203 // Name might be set from outside
204 if (!$this->MCONF['name']) {
205 $this->MCONF = $GLOBALS['MCONF'];
206 }
207 $this->id = (int)GeneralUtility::_GP('id');
208 $this->CMD = GeneralUtility::_GP('CMD');
209 $this->perms_clause = $this->getBackendUser()->getPagePermsClause(1);
210 $this->menuConfig();
211 $this->handleExternalFunctionValue();
212 }
213
214 /**
215 * 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())
216 * 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.
217 * Also loads the modTSconfig internal variable.
218 *
219 * @return void
220 * @see init(), $MOD_MENU, $MOD_SETTINGS, \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData(), mergeExternalItems()
221 */
222 public function menuConfig()
223 {
224 // Page/be_user TSconfig settings and blinding of menu-items
225 $this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->MCONF['name']);
226 $this->MOD_MENU['function'] = $this->mergeExternalItems($this->MCONF['name'], 'function', $this->MOD_MENU['function']);
227 $this->MOD_MENU['function'] = BackendUtility::unsetMenuItems($this->modTSconfig['properties'], $this->MOD_MENU['function'], 'menu.function');
228 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->MCONF['name'], $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList);
229 }
230
231 /**
232 * Merges menu items from global array $TBE_MODULES_EXT
233 *
234 * @param string $modName Module name for which to find value
235 * @param string $menuKey Menu key, eg. 'function' for the function menu.
236 * @param array $menuArr The part of a MOD_MENU array to work on.
237 * @return array Modified array part.
238 * @access private
239 * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), menuConfig()
240 */
241 public function mergeExternalItems($modName, $menuKey, $menuArr)
242 {
243 $mergeArray = $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey];
244 if (is_array($mergeArray)) {
245 foreach ($mergeArray as $k => $v) {
246 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')) {
247 $menuArr[$k] = $this->getLanguageService()->sL($v['title']);
248 }
249 }
250 }
251 return $menuArr;
252 }
253
254 /**
255 * Loads $this->extClassConf with the configuration for the CURRENT function of the menu.
256 *
257 * @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)
258 * @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)
259 * @return void
260 * @see getExternalItemConfig(), init()
261 */
262 public function handleExternalFunctionValue($MM_key = 'function', $MS_value = null)
263 {
264 if ($MS_value === null) {
265 $MS_value = $this->MOD_SETTINGS[$MM_key];
266 }
267 $this->extClassConf = $this->getExternalItemConfig($this->MCONF['name'], $MM_key, $MS_value);
268 }
269
270 /**
271 * Returns configuration values from the global variable $TBE_MODULES_EXT for the module given.
272 * 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.
273 *
274 * @param string $modName Module name
275 * @param string $menuKey Menu key, eg. "function" for the function menu. See $this->MOD_MENU
276 * @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...
277 * @return mixed The value from the TBE_MODULES_EXT array.
278 * @see handleExternalFunctionValue()
279 */
280 public function getExternalItemConfig($modName, $menuKey, $value = '')
281 {
282 if (isset($GLOBALS['TBE_MODULES_EXT'][$modName])) {
283 return (string)$value !== '' ? $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey][$value] : $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey];
284 }
285 return null;
286 }
287
288 /**
289 * 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...)
290 * This value in extClassConf might be set by an extension (in an ext_tables/ext_localconf file) which thus "connects" to a module.
291 * The array $this->extClassConf is set in handleExternalFunctionValue() based on the value of MOD_SETTINGS[function]
292 * 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.
293 *
294 * @return void
295 * @see handleExternalFunctionValue(), \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), $extObj
296 */
297 public function checkExtObj()
298 {
299 if (is_array($this->extClassConf) && $this->extClassConf['name']) {
300 $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
301 $this->extObj->init($this, $this->extClassConf);
302 // Re-write:
303 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->MCONF['name'], $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList);
304 }
305 }
306
307 /**
308 * Calls the checkExtObj function in sub module if present.
309 *
310 * @return void
311 */
312 public function checkSubExtObj()
313 {
314 if (is_object($this->extObj)) {
315 $this->extObj->checkExtObj();
316 }
317 }
318
319 /**
320 * Calls the 'header' function inside the "Function menu module" if present.
321 * 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.
322 *
323 * @return void
324 */
325 public function extObjHeader()
326 {
327 if (is_callable([$this->extObj, 'head'])) {
328 $this->extObj->head();
329 }
330 }
331
332 /**
333 * Calls the 'main' function inside the "Function menu module" if present
334 *
335 * @return void
336 */
337 public function extObjContent()
338 {
339 if ($this->extObj === null) {
340 $flashMessage = GeneralUtility::makeInstance(
341 FlashMessage::class,
342 $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:no_modules_registered'),
343 $this->getLanguageService()->getLL('title'),
344 FlashMessage::ERROR
345 );
346 /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
347 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
348 /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
349 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
350 $defaultFlashMessageQueue->enqueue($flashMessage);
351 } else {
352 $this->extObj->pObj = $this;
353 if (is_callable([$this->extObj, 'main'])) {
354 $this->content .= $this->extObj->main();
355 }
356 }
357 }
358
359 /**
360 * Return the content of the 'main' function inside the "Function menu module" if present
361 *
362 * @return string
363 */
364 public function getExtObjContent()
365 {
366 $savedContent = $this->content;
367 $this->content = '';
368 $this->extObjContent();
369 $newContent = $this->content;
370 $this->content = $savedContent;
371 return $newContent;
372 }
373
374 /**
375 * Returns the Language Service
376 * @return LanguageService
377 */
378 protected function getLanguageService()
379 {
380 return $GLOBALS['LANG'];
381 }
382
383 /**
384 * Returns the Backend User
385 * @return BackendUserAuthentication
386 */
387 protected function getBackendUser()
388 {
389 return $GLOBALS['BE_USER'];
390 }
391
392 /**
393 * @return DatabaseConnection
394 * @deprecated since TYPO3 v8, will be removed in TYPO3 v9, use the Doctrine DBAL layer via the ConnectionPool class
395 */
396 protected function getDatabaseConnection()
397 {
398 GeneralUtility::logDeprecatedFunction();
399 return $GLOBALS['TYPO3_DB'];
400 }
401
402 /**
403 * @return PageRenderer
404 */
405 protected function getPageRenderer()
406 {
407 if ($this->pageRenderer === null) {
408 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
409 }
410
411 return $this->pageRenderer;
412 }
413 }