BaseScriptClass.php 13.8 KB
Newer Older
1
2
3
<?php
namespace TYPO3\CMS\Backend\Module;

4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
8
9
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
10
 *
11
12
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
15
 * The TYPO3 project - inspiring people to share!
 */
Christian Kuhn's avatar
Christian Kuhn committed
16

Nicole Cordes's avatar
Nicole Cordes committed
17
use TYPO3\CMS\Backend\Utility\BackendUtility;
18
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
Markus Klein's avatar
Markus Klein committed
19
use TYPO3\CMS\Core\Database\DatabaseConnection;
20
use TYPO3\CMS\Core\Messaging\FlashMessage;
21
use TYPO3\CMS\Core\Page\PageRenderer;
Nicole Cordes's avatar
Nicole Cordes committed
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
use TYPO3\CMS\Lang\LanguageService;
Nicole Cordes's avatar
Nicole Cordes committed
24

25
/**
Christian Kuhn's avatar
Christian Kuhn committed
26
 * Parent class for 'ScriptClasses' in backend modules.
27
28
29
 *
 * EXAMPLE PROTOTYPE
 *
Christian Kuhn's avatar
Christian Kuhn committed
30
 * As for examples there are lots of them if you search for classes which extends \TYPO3\CMS\Backend\Module\BaseScriptClass
31
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.
 * You should consult the documentation and other real-world examples for some actual things to do when building modules.
35
 *
36
37
38
39
40
41
42
43
 * TYPICAL SETUP OF A BACKEND MODULE:
 *
 * PrototypeController EXTENDS THE CLASS \TYPO3\CMS\Backend\Module\BaseScriptClass with a main() and printContent() function:
 *
 * namespace Vendor\Prototype\Controller;
 *
 * class PrototypeController extends \TYPO3\CMS\Backend\Module\BaseScriptClass {
 * 	public function __construct() {
44
45
 * 		$this->getLanguageService()->includeLLFile('EXT:prototype/Resources/Private/Language/locallang.xlf');
 * 		$this->getBackendUser()->modAccess($GLOBALS['MCONF'], TRUE);
46
47
 * 	}
 * }
Christian Kuhn's avatar
Christian Kuhn committed
48
 *
49
 * MAIN FUNCTION - HERE YOU CREATE THE MODULE CONTENT IN $this->content
50
51
 * public function main() {
 * 	TYPICALLY THE INTERNAL VAR, $this->doc is instantiated like this:
52
 * 	$this->doc = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
53
54
55
56
 * 	TYPICALLY THE INTERNAL VAR, $this->backPath is set like this:
 * 	$this->backPath = $this->doc->backPath = $GLOBALS['BACK_PATH'];
 * 	... AND OF COURSE A LOT OF OTHER THINGS GOES ON - LIKE PUTTING CONTENT INTO $this->content
 * 	$this->content='';
57
58
 * }
 * PRINT CONTENT - DONE AS THE LAST THING
59
60
 * public function printContent() {
 * 	echo $this->content;
61
62
63
 * }
 *
 * MAKE INSTANCE OF THE SCRIPT CLASS AND CALL init()
64
65
 * $GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Vendor\Prototype\Controller\PrototypeController::class);
 * $GLOBALS['SOBE']->init();
66
67
68
 *
 *
 * THEN WE WILL CHECK IF THERE IS A 'SUBMODULE' REGISTERED TO BE INITIALIZED AS WELL:
69
 * $GLOBALS['SOBE']->checkExtObj();
70
71
 *
 * THEN WE CALL THE main() METHOD AND THIS SHOULD SPARK THE CREATION OF THE MODULE OUTPUT.
72
 * $GLOBALS['SOBE']->main();
73
 * FINALLY THE printContent() FUNCTION WILL OUTPUT THE ACCUMULATED CONTENT
74
 * $GLOBALS['SOBE']->printContent();
75
76
77
78
79
80
81
 */
class BaseScriptClass {

	/**
	 * Loaded with the global array $MCONF which holds some module configuration from the conf.php file of backend modules.
	 *
	 * @see init()
82
	 * @var array
83
84
85
86
87
88
89
	 */
	public $MCONF = array();

	/**
	 * The integer value of the GET/POST var, 'id'. Used for submodules to the 'Web' module (page id)
	 *
	 * @see init()
90
	 * @var int
91
92
93
94
95
96
97
	 */
	public $id;

	/**
	 * The value of GET/POST var, 'CMD'
	 *
	 * @see init()
98
	 * @var mixed
99
100
101
102
103
104
105
	 */
	public $CMD;

	/**
	 * A WHERE clause for selection records from the pages table based on read-permissions of the current backend user.
	 *
	 * @see init()
106
	 * @var string
107
108
109
110
111
112
113
	 */
	public $perms_clause;

	/**
	 * The module menu items array. Each key represents a key for which values can range between the items in the array of that key.
	 *
	 * @see init()
114
	 * @var array
115
116
117
118
119
120
121
122
123
	 */
	public $MOD_MENU = array(
		'function' => array()
	);

	/**
	 * Current settings for the keys of the MOD_MENU array
	 *
	 * @see $MOD_MENU
124
	 * @var array
125
126
127
128
129
130
131
	 */
	public $MOD_SETTINGS = array();

	/**
	 * Module TSconfig based on PAGE TSconfig / USER TSconfig
	 *
	 * @see menuConfig()
132
	 * @var array
133
134
135
136
137
138
139
	 */
	public $modTSconfig;

	/**
	 * If type is 'ses' then the data is stored as session-lasting data. This means that it'll be wiped out the next time the user logs in.
	 * Can be set from extension classes of this class before the init() function is called.
	 *
140
	 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()
141
	 * @var string
142
143
144
145
146
147
148
	 */
	public $modMenu_type = '';

	/**
	 * dontValidateList can be used to list variables that should not be checked if their value is found in the MOD_MENU array. Used for dynamically generated menus.
	 * Can be set from extension classes of this class before the init() function is called.
	 *
149
	 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()
150
	 * @var string
151
152
153
154
155
156
157
	 */
	public $modMenu_dontValidateList = '';

	/**
	 * List of default values from $MOD_MENU to set in the output array (only if the values from MOD_MENU are not arrays)
	 * Can be set from extension classes of this class before the init() function is called.
	 *
158
	 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()
159
	 * @var string
160
161
162
163
164
165
166
	 */
	public $modMenu_setDefaultList = '';

	/**
	 * Contains module configuration parts from TBE_MODULES_EXT if found
	 *
	 * @see handleExternalFunctionValue()
167
	 * @var array
168
169
170
171
172
173
	 */
	public $extClassConf;

	/**
	 * Generally used for accumulating the output content of backend modules
	 *
174
	 * @var string
175
176
177
178
179
180
181
182
183
184
185
186
	 */
	public $content = '';

	/**
	 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
	 */
	public $doc;

	/**
	 * May contain an instance of a 'Function menu module' which connects to this backend module.
	 *
	 * @see checkExtObj()
187
	 * @var AbstractFunctionModule
188
189
190
	 */
	public $extObj;

191
192
193
194
195
	/**
	 * @var PageRenderer
	 */
	protected $pageRenderer = NULL;

196
197
198
199
200
201
202
203
204
205
206
	/**
	 * Initializes the backend module by setting internal variables, initializing the menu.
	 *
	 * @return void
	 * @see menuConfig()
	 */
	public function init() {
		// Name might be set from outside
		if (!$this->MCONF['name']) {
			$this->MCONF = $GLOBALS['MCONF'];
		}
207
		$this->id = (int)GeneralUtility::_GP('id');
Nicole Cordes's avatar
Nicole Cordes committed
208
		$this->CMD = GeneralUtility::_GP('CMD');
209
		$this->perms_clause = $this->getBackendUser()->getPagePermsClause(1);
210
211
212
213
214
215
		$this->menuConfig();
		$this->handleExternalFunctionValue();
	}

	/**
	 * 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
218
219
	 * Also loads the modTSconfig internal variable.
	 *
	 * @return void
220
	 * @see init(), $MOD_MENU, $MOD_SETTINGS, \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData(), mergeExternalItems()
221
222
223
	 */
	public function menuConfig() {
		// Page/be_user TSconfig settings and blinding of menu-items
Nicole Cordes's avatar
Nicole Cordes committed
224
		$this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->MCONF['name']);
225
		$this->MOD_MENU['function'] = $this->mergeExternalItems($this->MCONF['name'], 'function', $this->MOD_MENU['function']);
Nicole Cordes's avatar
Nicole Cordes committed
226
227
		$this->MOD_MENU['function'] = BackendUtility::unsetMenuItems($this->modTSconfig['properties'], $this->MOD_MENU['function'], 'menu.function');
		$this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->MCONF['name'], $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList);
228
229
230
231
232
233
234
235
236
237
	}

	/**
	 * 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
238
	 * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), menuConfig()
239
240
241
242
243
	 */
	public function mergeExternalItems($modName, $menuKey, $menuArr) {
		$mergeArray = $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey];
		if (is_array($mergeArray)) {
			foreach ($mergeArray as $k => $v) {
244
245
				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']);
246
247
248
249
250
251
252
253
254
255
256
257
				}
			}
		}
		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)
	 * @return void
258
	 * @see getExternalItemConfig(), init()
259
260
	 */
	public function handleExternalFunctionValue($MM_key = 'function', $MS_value = NULL) {
261
262
263
		if ($MS_value === NULL) {
			$MS_value = $this->MOD_SETTINGS[$MM_key];
		}
264
265
266
267
268
269
270
271
272
273
274
275
276
277
		$this->extClassConf = $this->getExternalItemConfig($this->MCONF['name'], $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()
	 */
	public function getExternalItemConfig($modName, $menuKey, $value = '') {
278
279
280
281
		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;
282
283
284
285
	}

	/**
	 * 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...)
286
	 * This value in extClassConf might be set by an extension (in an ext_tables/ext_localconf file) which thus "connects" to a module.
287
288
289
290
	 * 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.
	 *
	 * @return void
291
	 * @see handleExternalFunctionValue(), \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), $extObj
292
293
294
	 */
	public function checkExtObj() {
		if (is_array($this->extClassConf) && $this->extClassConf['name']) {
Nicole Cordes's avatar
Nicole Cordes committed
295
			$this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']);
296
297
			$this->extObj->init($this, $this->extClassConf);
			// Re-write:
Nicole Cordes's avatar
Nicole Cordes committed
298
			$this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->MCONF['name'], $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList);
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
		}
	}

	/**
	 * Calls the checkExtObj function in sub module if present.
	 *
	 * @return void
	 */
	public function checkSubExtObj() {
		if (is_object($this->extObj)) {
			$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.
	 * example call in the header function:
	 * $this->pObj->doc->JScode = $this->pObj->doc->wrapScriptTags(' ...
	 *
	 * @return void
	 */
	public function extObjHeader() {
		if (is_callable(array($this->extObj, 'head'))) {
			$this->extObj->head();
		}
	}

	/**
	 * Calls the 'main' function inside the "Function menu module" if present
	 *
	 * @return void
	 */
	public function extObjContent() {
333
334
335
		if ($this->extObj === NULL) {
			$flashMessage = GeneralUtility::makeInstance(
				FlashMessage::class,
336
				$this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:no_modules_registered'),
337
338
339
340
341
342
343
344
345
				$this->getLanguageService()->getLL('title'),
				FlashMessage::ERROR
			);
			$this->content .= $flashMessage->render();
		} else {
			$this->extObj->pObj = $this;
			if (is_callable(array($this->extObj, 'main'))) {
				$this->content .= $this->extObj->main();
			}
346
347
348
		}
	}

349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	/**
	 * Returns the Language Service
	 * @return LanguageService
	 */
	protected function getLanguageService() {
		return $GLOBALS['LANG'];
	}

	/**
	 * Returns the Backend User
	 * @return BackendUserAuthentication
	 */
	protected function getBackendUser() {
		return $GLOBALS['BE_USER'];
	}

Markus Klein's avatar
Markus Klein committed
365
366
367
368
369
370
371
	/**
	 * @return DatabaseConnection
	 */
	protected function getDatabaseConnection() {
		return $GLOBALS['TYPO3_DB'];
	}

372
373
374
375
376
377
378
379
380
381
382
	/**
	 * @return PageRenderer
	 */
	protected function getPageRenderer() {
		if ($this->pageRenderer === NULL) {
			$this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
		}

		return $this->pageRenderer;
	}

383
}