TYPO3 CMS  TYPO3_8-7
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 
21 
33 {
39  public $modules = [];
40 
46  public $modListGroup = [];
47 
53  public $modListUser = [];
54 
60  public $BE_USER;
61 
67  public $observeWorkspaces = false;
68 
74  protected $navigationComponents = [];
75 
80  protected $moduleLabels = [];
81 
90  public function load($modulesArray, BackendUserAuthentication $beUser = null)
91  {
92  // Setting the backend user for use internally
93  $this->BE_USER = $beUser ?: $GLOBALS['BE_USER'];
94 
95  // Unset the array for calling backend modules based on external backend module dispatchers in typo3/index.php
96  unset($modulesArray['_configuration']);
97  $this->navigationComponents = $modulesArray['_navigationComponents'];
98  unset($modulesArray['_navigationComponents']);
99  $mainModules = $this->parseModulesArray($modulesArray);
100 
101  // Traverses the module setup and creates the internal array $this->modules
102  foreach ($mainModules as $mainModuleName => $subModules) {
103  $mainModuleConfiguration = $this->checkMod($mainModuleName);
104  // If $mainModuleConfiguration is not set (FALSE) there is no access to the module !(?)
105  if (is_array($mainModuleConfiguration)) {
106  $this->modules[$mainModuleName] = $mainModuleConfiguration;
107  // Load the submodules
108  if (is_array($subModules)) {
109  foreach ($subModules as $subModuleName) {
110  $subModuleConfiguration = $this->checkMod($mainModuleName . '_' . $subModuleName);
111  if (is_array($subModuleConfiguration)) {
112  $this->modules[$mainModuleName]['sub'][$subModuleName] = $subModuleConfiguration;
113  }
114  }
115  }
116  } elseif ($mainModuleConfiguration !== false) {
117  // Although the configuration was not found, still check if there are submodules
118  // This must be done in order to fill out the select-lists for modules correctly!!
119  if (is_array($subModules)) {
120  foreach ($subModules as $subModuleName) {
121  $this->checkMod($mainModuleName . '_' . $subModuleName);
122  }
123  }
124  }
125  }
126  }
127 
139  public function checkMod($name)
140  {
141  // Check for own way of configuring module
142  if (is_array($GLOBALS['TBE_MODULES']['_configuration'][$name]['configureModuleFunction'] ?? false)) {
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']));
171 
172  // Default script setup
173  if (!empty($setupInformation['configuration']['script']) && $setupInformation['configuration']['script'] === '_DISPATCH' || isset($setupInformation['configuration']['routeTarget'])) {
174  if ($setupInformation['configuration']['extbase']) {
175  $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl('Tx_' . $name);
176  } else {
177  // just go through BackendModuleRequestHandler where the routeTarget is resolved
178  $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl($name);
179  }
180  } else {
181  $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl('dummy');
182  }
183 
184  if (!empty($setupInformation['configuration']['navigationFrameModule'])) {
185  $finalModuleConfiguration['navFrameScript'] = BackendUtility::getModuleUrl(
186  $setupInformation['configuration']['navigationFrameModule'],
187  !empty($setupInformation['configuration']['navigationFrameModuleParameters'])
188  ? $setupInformation['configuration']['navigationFrameModuleParameters']
189  : []
190  );
191  }
192 
193  // Check if this is a submodule
194  $mainModule = '';
195  if (strpos($name, '_') !== false) {
196  list($mainModule, ) = explode('_', $name, 2);
197  }
198 
199  // check if there is a navigation component (like the pagetree)
200  if (is_array($this->navigationComponents[$name] ?? false)) {
201  $finalModuleConfiguration['navigationComponentId'] = $this->navigationComponents[$name]['componentId'];
202  } elseif ($mainModule
203  && is_array($this->navigationComponents[$mainModule] ?? false)
204  && $setupInformation['configuration']['inheritNavigationComponentFromMainModule'] !== false) {
205 
206  // navigation component can be overridden by the main module component
207  $finalModuleConfiguration['navigationComponentId'] = $this->navigationComponents[$mainModule]['componentId'];
208  }
209  return $finalModuleConfiguration;
210  }
211 
219  protected function getModuleSetupInformation($moduleName)
220  {
221  $moduleSetupInformation = [
222  'configuration' => [],
223  'labels' => []
224  ];
225 
226  $moduleConfiguration = !empty($GLOBALS['TBE_MODULES']['_configuration'][$moduleName])
227  ? $GLOBALS['TBE_MODULES']['_configuration'][$moduleName]
228  : null;
229  if ($moduleConfiguration !== null) {
230  // Overlay setup with additional labels
231  if (!empty($moduleConfiguration['labels']) && is_array($moduleConfiguration['labels'])) {
232  if (empty($moduleSetupInformation['labels']['default']) || !is_array($moduleSetupInformation['labels']['default'])) {
233  $moduleSetupInformation['labels']['default'] = $moduleConfiguration['labels'];
234  } else {
235  $moduleSetupInformation['labels']['default'] = array_replace_recursive($moduleSetupInformation['labels']['default'], $moduleConfiguration['labels']);
236  }
237  unset($moduleConfiguration['labels']);
238  }
239  // Overlay setup with additional configuration
240  if (is_array($moduleConfiguration)) {
241  $moduleSetupInformation['configuration'] = array_replace_recursive($moduleSetupInformation['configuration'], $moduleConfiguration);
242  }
243  }
244 
245  // Add some default configuration
246  if (!isset($moduleSetupInformation['configuration']['inheritNavigationComponentFromMainModule'])) {
247  $moduleSetupInformation['configuration']['inheritNavigationComponentFromMainModule'] = true;
248  }
249 
250  return $moduleSetupInformation;
251  }
252 
260  public function checkModAccess($name, $MCONF)
261  {
262  if (empty($MCONF['access'])) {
263  return true;
264  }
265  $access = strtolower($MCONF['access']);
266  // Checking if admin-access is required
267  // If admin-permissions is required then return TRUE if user is admin
268  if (strpos($access, 'admin') !== false && $this->BE_USER->isAdmin()) {
269  return true;
270  }
271  // This will add modules to the select-lists of user and groups
272  if (strpos($access, 'user') !== false) {
273  $this->modListUser[] = $name;
274  }
275  if (strpos($access, 'group') !== false) {
276  $this->modListGroup[] = $name;
277  }
278  // This checks if a user is permitted to access the module
279  if ($this->BE_USER->isAdmin() || $this->BE_USER->check('modules', $name)) {
280  return true;
281  }
282  return false;
283  }
284 
293  public function checkModWorkspace($name, $MCONF)
294  {
295  if (!$this->observeWorkspaces) {
296  return true;
297  }
298  $status = true;
299  if (!empty($MCONF['workspaces'])) {
300  $status = $this->BE_USER->workspace === 0 && GeneralUtility::inList($MCONF['workspaces'], 'online')
301  || $this->BE_USER->workspace === -1 && GeneralUtility::inList($MCONF['workspaces'], 'offline')
302  || $this->BE_USER->workspace > 0 && GeneralUtility::inList($MCONF['workspaces'], 'custom');
303  } elseif ($this->BE_USER->workspace === -99) {
304  $status = false;
305  }
306  return $status;
307  }
308 
316  public function parseModulesArray($arr)
317  {
318  $theMods = [];
319  if (is_array($arr)) {
320  foreach ($arr as $mod => $subs) {
321  // Clean module name to alphanum
322  $mod = $this->cleanName($mod);
323  if ($mod) {
324  if ($subs) {
325  $subsArr = GeneralUtility::trimExplode(',', $subs);
326  foreach ($subsArr as $subMod) {
327  $subMod = $this->cleanName($subMod);
328  if ($subMod) {
329  $theMods[$mod][] = $subMod;
330  }
331  }
332  } else {
333  $theMods[$mod] = 1;
334  }
335  }
336  }
337  }
338  return $theMods;
339  }
340 
348  public function cleanName($str)
349  {
350  return preg_replace('/[^a-z0-9]/i', '', $str);
351  }
352 
366  public function addLabelsForModule($moduleName, $labels)
367  {
368  // If LOCAL_LANG references are used for labels of the module:
369  if (is_string($labels)) {
370  // Extbase-based modules
371  $this->moduleLabels[$moduleName] = [
372  'shortdescription' => $labels . ':mlang_labels_tablabel',
373  'description' => $labels . ':mlang_labels_tabdescr',
374  'title' => $labels . ':mlang_tabs_tab',
375  ];
376  } elseif (isset($labels['title'])) {
377  // New way, where all labels can be LLL references
378  $this->moduleLabels[$moduleName] = $labels;
379  } elseif (isset($labels['ll_ref'])) {
380  // Classic, non-extbase module labels
381  $this->addLabelsForModule($moduleName, $labels['ll_ref']);
382  } else {
383  // Very old obsolete approach, don't use anymore, use one of the ways above.
384  if (is_object($this->getLanguageService())) {
385  $language = $this->getLanguageService()->lang;
386  } else {
387  $language = 'default';
388  }
389 
390  if (empty($labels)) {
391  if (isset($this->getLanguageService()->moduleLabels['labels'][$moduleName . '_tablabel'])) {
392  $labels[$language]['labels']['tablabel'] = $this->getLanguageService()->moduleLabels['labels'][$moduleName . '_tablabel'];
393  }
394  if (isset($this->getLanguageService()->moduleLabels['labels'][$moduleName . '_tabdescr'])) {
395  $labels[$language]['labels']['tabdescr'] = $this->getLanguageService()->moduleLabels['labels'][$moduleName . '_tabdescr'];
396  }
397  if (isset($this->getLanguageService()->moduleLabels['tabs'][$moduleName . '_tab'])) {
398  $labels[$language]['tabs']['tab'] = $this->getLanguageService()->moduleLabels['tabs'][$moduleName . '_tab'];
399  }
400  }
401 
402  if (isset($labels[$language]['ll_ref'])) {
403  $this->addLabelsForModule($moduleName, $labels[$language]['ll_ref']);
404  } elseif (isset($labels['default']['ll_ref'])) {
405  $this->addLabelsForModule($moduleName, $labels['default']['ll_ref']);
406  } else {
407  $this->moduleLabels[$moduleName] = [
408  'shortdescription' => isset($labels[$language]['labels']['tablabel']) ? $labels[$language]['labels']['tablabel'] : $labels['default']['labels']['tablabel'],
409  'description' => isset($labels[$language]['labels']['tabdescr']) ? $labels[$language]['labels']['tabdescr'] : $labels['default']['labels']['tabdescr'],
410  'title' => isset($labels[$language]['tabs']['tab']) ? $labels[$language]['tabs']['tab'] : $labels['default']['tabs']['tab'],
411  ];
412  }
413  }
414  }
415 
422  public function getLabelsForModule($moduleName)
423  {
424  return isset($this->moduleLabels[$moduleName]) ? $this->moduleLabels[$moduleName] : [];
425  }
426 
430  protected function getLanguageService()
431  {
432  return $GLOBALS['LANG'];
433  }
434 }
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
addLabelsForModule($moduleName, $labels)
load($modulesArray, BackendUserAuthentication $beUser=null)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']