‪TYPO3CMS  11.5
BackendModuleRepository.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
28 
34 {
38  protected ‪$moduleStorage;
39 
43  public function ‪__construct()
44  {
45  $this->moduleStorage = GeneralUtility::makeInstance(ModuleStorage::class);
46 
47  $rawData = $this->‪getRawModuleMenuData();
48 
51  }
52 
59  public function ‪loadAllowedModules(array $excludeGroupNames = [])
60  {
61  if (empty($excludeGroupNames)) {
62  return $this->moduleStorage->getEntries();
63  }
64 
65  $modules = new \SplObjectStorage();
66  foreach ($this->moduleStorage->getEntries() as $moduleGroup) {
67  if (!in_array($moduleGroup->getName(), $excludeGroupNames, true)) {
68  if ($moduleGroup->getChildren()->count() > 0 || $moduleGroup->isStandalone()) {
69  $modules->attach($moduleGroup);
70  }
71  }
72  }
73 
74  return $modules;
75  }
76 
81  public function ‪findByGroupName($groupName = '')
82  {
83  foreach ($this->moduleStorage->getEntries() as $moduleGroup) {
84  if ($moduleGroup->getName() === $groupName) {
85  return $moduleGroup;
86  }
87  }
88 
89  return false;
90  }
91 
98  public function ‪findByModuleName($name)
99  {
100  $entries = $this->moduleStorage->getEntries();
101  $entry = $this->‪findByModuleNameInGivenEntries($name, $entries);
102  return $entry;
103  }
104 
112  public function ‪findByModuleNameInGivenEntries($name, \SplObjectStorage $entries)
113  {
114  foreach ($entries as $entry) {
115  if ($entry->getName() === $name) {
116  return $entry;
117  }
118  $children = $entry->‪getChildren();
119  if (!empty($children)) {
120  $childRecord = $this->‪findByModuleNameInGivenEntries($name, $children);
121  if ($childRecord !== false) {
122  return $childRecord;
123  }
124  }
125  }
126  return false;
127  }
128 
134  protected function ‪convertRawModuleDataToModuleMenuObject(array $rawModuleData)
135  {
136  foreach ($rawModuleData as $module) {
137  $entry = $this->‪createEntryFromRawData($module);
138  if (isset($module['subitems']) && !empty($module['subitems'])) {
139  foreach ($module['subitems'] as $subitem) {
140  $subEntry = $this->‪createEntryFromRawData($subitem);
141  $entry->addChild($subEntry);
142  }
143  }
144  $this->moduleStorage->attachEntry($entry);
145  }
146  }
147 
154  protected function ‪createEntryFromRawData(array $module)
155  {
156  $entry = GeneralUtility::makeInstance(BackendModule::class);
157  if (!empty($module['name']) && is_string($module['name'])) {
158  $entry->setName($module['name']);
159  }
160  if (!empty($module['title']) && is_string($module['title'])) {
161  $entry->setTitle($this->‪getLanguageService()->sL($module['title']));
162  }
163  // @deprecated using inline JavaScript is deprecated, will be removed in TYPO3 v12.0
164  if (!empty($module['onclick']) && is_string($module['onclick'])) {
165  $entry->setOnClick($module['onclick']);
166  }
167  if (!empty($module['link']) && is_string($module['link'])) {
168  $entry->setLink($module['link']);
169  } elseif (empty($module['link']) && !empty($module['path']) && is_string($module['path'])) {
170  $entry->setLink($module['path']);
171  }
172  if (!empty($module['component']) && is_string($module['component'])) {
173  $entry->setComponent($module['component']);
174  }
175  if (!empty($module['description']) && is_string($module['description'])) {
176  $entry->setDescription($this->‪getLanguageService()->sL($module['description']));
177  }
178  if (!empty($module['icon'])) {
179  $entry->setIcon($module['icon']);
180  }
181  if (!empty($module['navigationComponentId']) && is_string($module['navigationComponentId'])) {
182  $entry->setNavigationComponentId($module['navigationComponentId']);
183  }
184  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
185  if (!empty($module['navigationFrameScript']) && is_string($module['navigationFrameScript'])) {
186  $entry->setNavigationFrameScript($module['navigationFrameScript']);
187  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
188  } elseif (!empty($module['parentNavigationFrameScript']) && is_string($module['parentNavigationFrameScript'])) {
189  $entry->setNavigationFrameScript($module['parentNavigationFrameScript']);
190  }
191  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
192  if (!empty($module['navigationFrameScriptParam']) && is_string($module['navigationFrameScriptParam'])) {
193  $entry->setNavigationFrameScriptParameters($module['navigationFrameScriptParam']);
194  }
195  if (!empty($module['standalone'])) {
196  $entry->setStandalone((bool)$module['standalone']);
197  }
198  $moduleMenuState = json_decode($this->‪getBackendUser()->uc['modulemenu'] ?? '{}', true);
199  $entry->setCollapsed(isset($moduleMenuState[$module['name']]));
200  return $entry;
201  }
202 
207  protected function ‪createMenuEntriesForTbeModulesExt()
208  {
209  foreach (‪$GLOBALS['TBE_MODULES_EXT'] ?? [] as $mainModule => $tbeModuleExt) {
210  [$main] = explode('_', $mainModule);
211  $mainEntry = $this->‪findByModuleName($main);
212  if ($mainEntry === false) {
213  continue;
214  }
215 
216  $subEntries = $mainEntry->getChildren();
217  if (empty($subEntries)) {
218  continue;
219  }
220  $matchingSubEntry = $this->‪findByModuleName($mainModule);
221  if ($matchingSubEntry !== false) {
222  if (isset($tbeModuleExt['MOD_MENU']) && isset($tbeModuleExt['MOD_MENU']['function'])) {
223  foreach ($tbeModuleExt['MOD_MENU']['function'] as $subModule) {
224  $entry = $this->‪createEntryFromRawData($subModule);
225  $matchingSubEntry->addChild($entry);
226  }
227  }
228  }
229  }
230  }
231 
238  public function ‪getRawModuleMenuData()
239  {
240  // Loads the backend modules available for the logged in user.
241  $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
242  $moduleLoader->observeWorkspaces = true;
243  $moduleLoader->load(‪$GLOBALS['TBE_MODULES']);
244  $loadedModules = $moduleLoader->getModules();
245 
246  $modules = [];
247 
248  // Unset modules that are meant to be hidden from the menu.
249  $loadedModules = $this->‪removeHiddenModules($loadedModules);
250  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
251  $dummyScript = (string)$uriBuilder->buildUriFromRoute('dummy');
252  foreach ($loadedModules as $moduleName => $moduleData) {
253  $moduleLink = '';
254  $moduleComponent = '';
255  if (!is_array($moduleData['sub'] ?? null)) {
256  $moduleLink = $moduleData['script'];
257  $moduleComponent = $moduleData['component'] ?? '';
258  }
259  $moduleLink = GeneralUtility::resolveBackPath($moduleLink);
260  $moduleLabels = $moduleLoader->getLabelsForModule($moduleName);
261  $moduleKey = 'modmenu_' . $moduleName;
262  $modules[$moduleKey] = [
263  'name' => $moduleName,
264  'title' => $moduleLabels['title'],
265  'icon' => $this->‪getModuleIcon($moduleKey, $moduleData),
266  'link' => $moduleLink,
267  'component' => $moduleComponent,
268  'description' => $moduleLabels['shortdescription'],
269  'standalone' => (bool)($moduleData['standalone'] ?? false),
270  ];
271  if ((($moduleData['standalone'] ?? false) === false) && !is_array($moduleData['sub'] ?? null) && ($moduleData['script'] ?? null) !== $dummyScript) {
272  // Work around for modules with own main entry, but being self the only submodule
273  $modules[$moduleKey]['subitems'][$moduleKey] = [
274  'name' => $moduleName,
275  'title' => $moduleLabels['title'] ?? '',
276  'icon' => $this->‪getModuleIcon($moduleKey, $moduleData),
277  'link' => $moduleLink,
278  'component' => $moduleComponent,
279  'originalLink' => $moduleLink,
280  'description' => $moduleLabels['shortdescription'] ?? '',
281  'navigationFrameScript' => null,
282  'navigationFrameScriptParam' => null,
283  'navigationComponentId' => null,
284  ];
285  } elseif (is_array($moduleData['sub'] ?? null)) {
286  foreach ($moduleData['sub'] as $submoduleName => $submoduleData) {
287  $submoduleComponent = $submoduleData['component'] ?? '';
288  if (isset($submoduleData['script'])) {
289  $submoduleLink = GeneralUtility::resolveBackPath($submoduleData['script']);
290  } else {
291  $submoduleLink = (string)$uriBuilder->buildUriFromRoute($submoduleData['name']);
292  }
293  $submoduleKey = $moduleName . '_' . $submoduleName;
294  $submoduleLabels = $moduleLoader->getLabelsForModule($submoduleKey);
295  $submoduleDescription = $submoduleLabels['shortdescription'];
296  $originalLink = $submoduleLink;
297  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
298  $navigationFrameScript = $submoduleData['navFrameScript'] ?? null;
299  $modules[$moduleKey]['subitems'][$submoduleKey] = [
300  'name' => $moduleName . '_' . $submoduleName,
301  'title' => $submoduleLabels['title'],
302  'icon' => $this->‪getModuleIcon($moduleKey, $submoduleData),
303  'link' => $submoduleLink,
304  'component' => $submoduleComponent,
305  'originalLink' => $originalLink,
306  'description' => $submoduleDescription,
307  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
308  'navigationFrameScript' => $navigationFrameScript,
309  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
310  'navigationFrameScriptParam' => $submoduleData['navFrameScriptParam'] ?? null,
311  'navigationComponentId' => $submoduleData['navigationComponentId'] ?? null,
312  ];
313  // if the main module has a navframe script, inherit to the submodule,
314  // but only if it is not disabled explicitly (option is set to FALSE)
315  // @deprecated since TYPO3 v11, will be removed in TYPO3 v12.0
316  if (($moduleData['navFrameScript'] ?? false) && $submoduleData['inheritNavigationComponentFromMainModule'] !== false) {
317  $modules[$moduleKey]['subitems'][$submoduleKey]['parentNavigationFrameScript'] = $moduleData['navFrameScript'];
318  }
319  }
320  }
321  }
322  return $modules;
323  }
324 
329  public function ‪modulesHaveNavigationComponent(): bool
330  {
332  foreach ($this->moduleStorage->getEntries() as $module) {
333  if ($module->getNavigationComponentId() !== '') {
334  return true;
335  }
336  }
337 
338  return false;
339  }
340 
348  protected function ‪removeHiddenModules($loadedModules)
349  {
350  $userTsConfig = $this->‪getBackendUser()->‪getTSConfig();
351 
352  // Hide modules if set in userTS.
353  $hiddenMainModules = ‪GeneralUtility::trimExplode(',', $userTsConfig['options.']['hideModules'] ?? '', true);
354  foreach ($hiddenMainModules as $hiddenMainModule) {
355  unset($loadedModules[$hiddenMainModule]);
356  }
357 
358  // Hide sub-modules if set in userTS.
359  $hiddenModules = $userTsConfig['options.']['hideModules.'] ?? [];
360  if (is_array($hiddenModules)) {
361  foreach ($hiddenModules as $mainModuleName => $subModules) {
362  $hiddenSubModules = ‪GeneralUtility::trimExplode(',', $subModules, true);
363  foreach ($hiddenSubModules as $hiddenSubModule) {
364  unset($loadedModules[$mainModuleName]['sub'][$hiddenSubModule]);
365  }
366  }
367  }
368 
369  return $loadedModules;
370  }
371 
379  protected function ‪getModuleIcon($moduleKey, $moduleData)
380  {
381  $iconIdentifier = !empty($moduleData['iconIdentifier'])
382  ? $moduleData['iconIdentifier']
383  : 'module-icon-' . $moduleKey;
384  $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
385  if ($iconRegistry->isRegistered($iconIdentifier)) {
386  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
387  return $iconFactory->getIcon($iconIdentifier)->render('inline');
388  }
389  return '';
390  }
391 
397  protected function ‪getLanguageService()
398  {
399  return ‪$GLOBALS['LANG'];
400  }
401 
405  protected function ‪getBackendUser(): ‪BackendUserAuthentication
406  {
407  return ‪$GLOBALS['BE_USER'];
408  }
409 }
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\findByModuleName
‪TYPO3 CMS Backend Domain Model Module BackendModule false findByModuleName($name)
Definition: BackendModuleRepository.php:97
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:999
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\findByModuleNameInGivenEntries
‪TYPO3 CMS Backend Domain Model Module BackendModule false findByModuleNameInGivenEntries($name, \SplObjectStorage $entries)
Definition: BackendModuleRepository.php:111
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\convertRawModuleDataToModuleMenuObject
‪convertRawModuleDataToModuleMenuObject(array $rawModuleData)
Definition: BackendModuleRepository.php:133
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\createMenuEntriesForTbeModulesExt
‪createMenuEntriesForTbeModulesExt()
Definition: BackendModuleRepository.php:206
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getLanguageService
‪LanguageService getLanguageService()
Definition: BackendModuleRepository.php:396
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig()
Definition: BackendUserAuthentication.php:1000
‪TYPO3\CMS\Backend\Module\ModuleStorage
Definition: ModuleStorage.php:25
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getRawModuleMenuData
‪array getRawModuleMenuData()
Definition: BackendModuleRepository.php:237
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getModuleIcon
‪string getModuleIcon($moduleKey, $moduleData)
Definition: BackendModuleRepository.php:378
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\removeHiddenModules
‪array removeHiddenModules($loadedModules)
Definition: BackendModuleRepository.php:347
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\__construct
‪__construct()
Definition: BackendModuleRepository.php:42
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\$moduleStorage
‪TYPO3 CMS Backend Module ModuleStorage $moduleStorage
Definition: BackendModuleRepository.php:37
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\findByGroupName
‪SplObjectStorage false findByGroupName($groupName='')
Definition: BackendModuleRepository.php:80
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\createEntryFromRawData
‪TYPO3 CMS Backend Domain Model Module BackendModule createEntryFromRawData(array $module)
Definition: BackendModuleRepository.php:153
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:40
‪TYPO3\CMS\Backend\Module\ModuleLoader
Definition: ModuleLoader.php:34
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:32
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Domain\Model\Module\BackendModule\getChildren
‪SplObjectStorage getChildren()
Definition: BackendModule.php:103
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository
Definition: BackendModuleRepository.php:34
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: BackendModuleRepository.php:404
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Domain\Model\Module\BackendModule
Definition: BackendModule.php:22
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\loadAllowedModules
‪SplObjectStorage loadAllowedModules(array $excludeGroupNames=[])
Definition: BackendModuleRepository.php:58
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Backend\Domain\Repository\Module
Definition: BackendModuleRepository.php:16
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\modulesHaveNavigationComponent
‪bool modulesHaveNavigationComponent()
Definition: BackendModuleRepository.php:328