‪TYPO3CMS  9.5
ModuleLoader.php
Go to the documentation of this file.
1 <?php
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 
20 
32 {
38  public ‪$modules = [];
39 
45  public ‪$modListGroup = [];
46 
52  public ‪$modListUser = [];
53 
59  public ‪$BE_USER;
60 
66  public ‪$observeWorkspaces = false;
67 
73  protected ‪$navigationComponents = [];
74 
79  protected ‪$moduleLabels = [];
80 
89  public function ‪load($modulesArray, ‪BackendUserAuthentication $beUser = null)
90  {
91  // Setting the backend user for use internally
92  $this->BE_USER = $beUser ?: ‪$GLOBALS['BE_USER'];
93 
94  // Unset the array for calling backend modules based on external backend module dispatchers in typo3/index.php
95  unset($modulesArray['_configuration']);
96  $this->navigationComponents = $modulesArray['_navigationComponents'];
97  unset($modulesArray['_navigationComponents']);
98  $mainModules = $this->‪parseModulesArray($modulesArray);
99 
100  // Traverses the module setup and creates the internal array $this->modules
101  foreach ($mainModules as $mainModuleName => $subModules) {
102  $mainModuleConfiguration = $this->‪checkMod($mainModuleName);
103  // If $mainModuleConfiguration is not set (FALSE) there is no access to the module !(?)
104  if (is_array($mainModuleConfiguration)) {
105  $this->modules[$mainModuleName] = $mainModuleConfiguration;
106  // Load the submodules
107  if (is_array($subModules)) {
108  foreach ($subModules as $subModuleName) {
109  $subModuleConfiguration = $this->‪checkMod($mainModuleName . '_' . $subModuleName);
110  if (is_array($subModuleConfiguration)) {
111  $this->modules[$mainModuleName]['sub'][$subModuleName] = $subModuleConfiguration;
112  }
113  }
114  }
115  } elseif ($mainModuleConfiguration !== false) {
116  // Although the configuration was not found, still check if there are submodules
117  // This must be done in order to fill out the select-lists for modules correctly!!
118  if (is_array($subModules)) {
119  foreach ($subModules as $subModuleName) {
120  $this->‪checkMod($mainModuleName . '_' . $subModuleName);
121  }
122  }
123  }
124  }
125  }
126 
138  public function ‪checkMod($name)
139  {
140  // Check for own way of configuring module
141  if (is_array(‪$GLOBALS['TBE_MODULES']['_configuration'][$name]['configureModuleFunction'] ?? false)) {
142  trigger_error('Registering a module using "configureModuleFunction" will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
143  $obj = ‪$GLOBALS['TBE_MODULES']['_configuration'][$name]['configureModuleFunction'];
144  if (is_callable($obj)) {
145  $MCONF = call_user_func($obj, $name);
146  if ($this->‪checkModAccess($name, $MCONF) !== true) {
147  return false;
148  }
149  $this->‪addLabelsForModule($name, $MCONF['labels']);
150  return $MCONF;
151  }
152  }
153 
154  // merge configuration and labels into one array
155  $setupInformation = $this->‪getModuleSetupInformation($name);
156 
157  // clean up the configuration part
158  if (empty($setupInformation['configuration'])) {
159  return 'notFound';
160  }
161  $finalModuleConfiguration = $setupInformation['configuration'];
162  if (!empty($finalModuleConfiguration['shy'])
163  || !$this->‪checkModAccess($name, $setupInformation['configuration'])
164  || !$this->‪checkModWorkspace($name, $setupInformation['configuration'])
165  ) {
166  return false;
167  }
168  $finalModuleConfiguration['name'] = $name;
169  // Language processing. This will add module labels and image reference to the internal ->moduleLabels array of the LANG object.
170  $this->‪addLabelsForModule($name, $finalModuleConfiguration['labels'] ?? $setupInformation['labels']);
172  $uriBuilder = GeneralUtility::makeInstance(\‪TYPO3\CMS\Backend\Routing\UriBuilder::class);
173  if (isset($setupInformation['configuration']['routeTarget'])) {
174  $finalModuleConfiguration['script'] = (string)$uriBuilder->buildUriFromRoute($name);
175  } else {
176  $finalModuleConfiguration['script'] = (string)$uriBuilder->buildUriFromRoute('dummy');
177  }
178 
179  if (!empty($setupInformation['configuration']['navigationFrameModule'])) {
180  $finalModuleConfiguration['navFrameScript'] = (string)$uriBuilder->buildUriFromRoute(
181  $setupInformation['configuration']['navigationFrameModule'],
182  !empty($setupInformation['configuration']['navigationFrameModuleParameters'])
183  ? $setupInformation['configuration']['navigationFrameModuleParameters']
184  : []
185  );
186  }
187 
188  // Check if this is a submodule
189  $mainModule = '';
190  if (strpos($name, '_') !== false) {
191  list($mainModule, ) = explode('_', $name, 2);
192  }
193 
194  // check if there is a navigation component (like the pagetree)
195  if (is_array($this->navigationComponents[$name] ?? false)) {
196  $finalModuleConfiguration['navigationComponentId'] = $this->navigationComponents[$name]['componentId'];
197  } elseif ($mainModule
198  && is_array($this->navigationComponents[$mainModule] ?? false)
199  && $setupInformation['configuration']['inheritNavigationComponentFromMainModule'] !== false) {
200 
201  // navigation component can be overridden by the main module component
202  $finalModuleConfiguration['navigationComponentId'] = $this->navigationComponents[$mainModule]['componentId'];
203  }
204  return $finalModuleConfiguration;
205  }
206 
214  protected function ‪getModuleSetupInformation($moduleName)
215  {
216  $moduleSetupInformation = [
217  'configuration' => [],
218  'labels' => []
219  ];
220 
221  $moduleConfiguration = !empty(‪$GLOBALS['TBE_MODULES']['_configuration'][$moduleName])
222  ? ‪$GLOBALS['TBE_MODULES']['_configuration'][$moduleName]
223  : null;
224  if ($moduleConfiguration !== null) {
225  // Overlay setup with additional labels
226  if (!empty($moduleConfiguration['labels']) && is_array($moduleConfiguration['labels'])) {
227  if (empty($moduleSetupInformation['labels']['default']) || !is_array($moduleSetupInformation['labels']['default'])) {
228  $moduleSetupInformation['labels']['default'] = $moduleConfiguration['labels'];
229  } else {
230  $moduleSetupInformation['labels']['default'] = array_replace_recursive($moduleSetupInformation['labels']['default'], $moduleConfiguration['labels']);
231  }
232  unset($moduleConfiguration['labels']);
233  }
234  // Overlay setup with additional configuration
235  if (is_array($moduleConfiguration)) {
236  $moduleSetupInformation['configuration'] = array_replace_recursive($moduleSetupInformation['configuration'], $moduleConfiguration);
237  }
238  }
239 
240  // Add some default configuration
241  if (!isset($moduleSetupInformation['configuration']['inheritNavigationComponentFromMainModule'])) {
242  $moduleSetupInformation['configuration']['inheritNavigationComponentFromMainModule'] = true;
243  }
244 
245  return $moduleSetupInformation;
246  }
247 
255  public function ‪checkModAccess($name, $MCONF)
256  {
257  if (empty($MCONF['access'])) {
258  return true;
259  }
260  $access = strtolower($MCONF['access']);
261  // Check if this module is only allowed by system maintainers (= admins who are in the list of system maintainers)
262  if (strpos($MCONF['access'], ‪BackendUserAuthentication::ROLE_SYSTEMMAINTAINER) !== false) {
263  return $this->BE_USER->isSystemMaintainer();
264  }
265  // Checking if admin-access is required
266  // If admin-permissions is required then return TRUE if user is admin
267  if (strpos($access, 'admin') !== false && $this->BE_USER->isAdmin()) {
268  return true;
269  }
270  // This will add modules to the select-lists of user and groups
271  if (strpos($access, 'user') !== false) {
272  $this->modListUser[] = $name;
273  }
274  if (strpos($access, 'group') !== false) {
275  $this->modListGroup[] = $name;
276  }
277  // This checks if a user is permitted to access the module
278  if ($this->BE_USER->isAdmin() || $this->BE_USER->check('modules', $name)) {
279  return true;
280  }
281  return false;
282  }
283 
292  public function ‪checkModWorkspace($name, $MCONF)
293  {
294  if (!$this->observeWorkspaces) {
295  return true;
296  }
297  $status = true;
298  if (!empty($MCONF['workspaces'])) {
299  $status = $this->BE_USER->workspace === 0 && GeneralUtility::inList($MCONF['workspaces'], 'online')
300  || $this->BE_USER->workspace === -1 && GeneralUtility::inList($MCONF['workspaces'], 'offline')
301  || $this->BE_USER->workspace > 0 && GeneralUtility::inList($MCONF['workspaces'], 'custom');
302  } elseif ($this->BE_USER->workspace === -99) {
303  $status = false;
304  }
305  return $status;
306  }
307 
315  public function ‪parseModulesArray($arr)
316  {
317  $theMods = [];
318  if (is_array($arr)) {
319  foreach ($arr as $mod => $subs) {
320  // Clean module name to alphanum
321  $mod = $this->‪cleanName($mod);
322  if ($mod) {
323  if ($subs) {
324  $subsArr = GeneralUtility::trimExplode(',', $subs);
325  foreach ($subsArr as $subMod) {
326  $subMod = $this->‪cleanName($subMod);
327  if ($subMod) {
328  $theMods[$mod][] = $subMod;
329  }
330  }
331  } else {
332  $theMods[$mod] = 1;
333  }
334  }
335  }
336  }
337  return $theMods;
338  }
339 
347  public function ‪cleanName($str)
348  {
349  return preg_replace('/[^a-z0-9]/i', '', $str);
350  }
351 
365  public function ‪addLabelsForModule($moduleName, $labels)
366  {
367  // If LOCAL_LANG references are used for labels of the module:
368  if (is_string($labels)) {
369  // Extbase-based modules
370  $this->moduleLabels[$moduleName] = [
371  'shortdescription' => $labels . ':mlang_labels_tablabel',
372  'description' => $labels . ':mlang_labels_tabdescr',
373  'title' => $labels . ':mlang_tabs_tab',
374  ];
375  } elseif (isset($labels['title'])) {
376  // New way, where all labels can be LLL references
377  $this->moduleLabels[$moduleName] = $labels;
378  } elseif (isset($labels['ll_ref'])) {
379  // Classic, non-extbase module labels
380  $this->‪addLabelsForModule($moduleName, $labels['ll_ref']);
381  } else {
382  // Very old obsolete approach, don't use anymore, use one of the ways above.
383  if (is_object($this->‪getLanguageService())) {
384  $language = $this->‪getLanguageService()->lang;
385  } else {
386  $language = 'default';
387  }
388 
389  if (isset($labels[$language]['ll_ref'])) {
390  $this->‪addLabelsForModule($moduleName, $labels[$language]['ll_ref']);
391  } elseif (isset($labels['default']['ll_ref'])) {
392  $this->‪addLabelsForModule($moduleName, $labels['default']['ll_ref']);
393  } else {
394  $this->moduleLabels[$moduleName] = [
395  'shortdescription' => $labels[$language]['labels']['tablabel'] ?? $labels['default']['labels']['tablabel'],
396  'description' => $labels[$language]['labels']['tabdescr'] ?? $labels['default']['labels']['tabdescr'],
397  'title' => $labels[$language]['tabs']['tab'] ?? $labels['default']['tabs']['tab'],
398  ];
399  }
400  }
401  }
402 
409  public function ‪getLabelsForModule($moduleName)
410  {
411  return $this->moduleLabels[$moduleName] ?? [];
412  }
413 
417  protected function ‪getLanguageService()
418  {
419  return ‪$GLOBALS['LANG'];
420  }
421 }
‪TYPO3\CMS\Backend\Module\ModuleLoader\load
‪load($modulesArray, BackendUserAuthentication $beUser=null)
Definition: ModuleLoader.php:82
‪TYPO3\CMS\Backend\Module\ModuleLoader\checkModWorkspace
‪bool checkModWorkspace($name, $MCONF)
Definition: ModuleLoader.php:285
‪TYPO3
‪TYPO3\CMS\Backend\Module\ModuleLoader\cleanName
‪string cleanName($str)
Definition: ModuleLoader.php:340
‪TYPO3\CMS\Backend\Module\ModuleLoader\$observeWorkspaces
‪bool $observeWorkspaces
Definition: ModuleLoader.php:61
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\ROLE_SYSTEMMAINTAINER
‪const ROLE_SYSTEMMAINTAINER
Definition: BackendUserAuthentication.php:47
‪TYPO3\CMS\Backend\Module\ModuleLoader
Definition: ModuleLoader.php:32
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Module\ModuleLoader\getModuleSetupInformation
‪array getModuleSetupInformation($moduleName)
Definition: ModuleLoader.php:207
‪TYPO3\CMS\Backend\Module\ModuleLoader\$modListGroup
‪array $modListGroup
Definition: ModuleLoader.php:43
‪TYPO3\CMS\Backend\Module\ModuleLoader\$moduleLabels
‪array $moduleLabels
Definition: ModuleLoader.php:72
‪TYPO3\CMS\Backend\Module\ModuleLoader\parseModulesArray
‪array parseModulesArray($arr)
Definition: ModuleLoader.php:308
‪TYPO3\CMS\Backend\Module\ModuleLoader\getLanguageService
‪LanguageService getLanguageService()
Definition: ModuleLoader.php:410
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Module\ModuleLoader\$navigationComponents
‪array $navigationComponents
Definition: ModuleLoader.php:67
‪TYPO3\CMS\Backend\Module\ModuleLoader\$modules
‪array $modules
Definition: ModuleLoader.php:37
‪TYPO3\CMS\Backend\Module\ModuleLoader\$BE_USER
‪TYPO3 CMS Core Authentication BackendUserAuthentication $BE_USER
Definition: ModuleLoader.php:55
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Backend\Module\ModuleLoader\addLabelsForModule
‪addLabelsForModule($moduleName, $labels)
Definition: ModuleLoader.php:358
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Module\ModuleLoader\$modListUser
‪array $modListUser
Definition: ModuleLoader.php:49
‪TYPO3\CMS\Backend\Module\ModuleLoader\checkModAccess
‪bool checkModAccess($name, $MCONF)
Definition: ModuleLoader.php:248
‪TYPO3\CMS\Backend\Module
Definition: AbstractFunctionModule.php:2
‪TYPO3\CMS\Backend\Module\ModuleLoader\getLabelsForModule
‪array getLabelsForModule($moduleName)
Definition: ModuleLoader.php:402
‪TYPO3\CMS\Backend\Module\ModuleLoader\checkMod
‪string bool array checkMod($name)
Definition: ModuleLoader.php:131