‪TYPO3CMS  10.4
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  {
157  $entry = GeneralUtility::makeInstance(BackendModule::class);
158  if (!empty($module['name']) && is_string($module['name'])) {
159  $entry->setName($module['name']);
160  }
161  if (!empty($module['title']) && is_string($module['title'])) {
162  $entry->setTitle($this->‪getLanguageService()->sL($module['title']));
163  }
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['description']) && is_string($module['description'])) {
173  $entry->setDescription($this->‪getLanguageService()->sL($module['description']));
174  }
175  if (!empty($module['icon'])) {
176  $entry->setIcon($module['icon']);
177  }
178  if (!empty($module['navigationComponentId']) && is_string($module['navigationComponentId'])) {
179  $entry->setNavigationComponentId($module['navigationComponentId']);
180  }
181  if (!empty($module['navigationFrameScript']) && is_string($module['navigationFrameScript'])) {
182  $entry->setNavigationFrameScript($module['navigationFrameScript']);
183  } elseif (!empty($module['parentNavigationFrameScript']) && is_string($module['parentNavigationFrameScript'])) {
184  $entry->setNavigationFrameScript($module['parentNavigationFrameScript']);
185  }
186  if (!empty($module['navigationFrameScriptParam']) && is_string($module['navigationFrameScriptParam'])) {
187  $entry->setNavigationFrameScriptParameters($module['navigationFrameScriptParam']);
188  }
189  if (!empty($module['standalone'])) {
190  $entry->setStandalone((bool)$module['standalone']);
191  }
192  $moduleMenuState = json_decode($this->‪getBackendUser()->uc['modulemenu'] ?? '{}', true);
193  $entry->setCollapsed(isset($moduleMenuState[$module['name']]));
194  return $entry;
195  }
196 
201  protected function ‪createMenuEntriesForTbeModulesExt()
202  {
203  foreach (‪$GLOBALS['TBE_MODULES_EXT'] ?? [] as $mainModule => $tbeModuleExt) {
204  [$main] = explode('_', $mainModule);
205  $mainEntry = $this->‪findByModuleName($main);
206  if ($mainEntry === false) {
207  continue;
208  }
209 
210  $subEntries = $mainEntry->getChildren();
211  if (empty($subEntries)) {
212  continue;
213  }
214  $matchingSubEntry = $this->‪findByModuleName($mainModule);
215  if ($matchingSubEntry !== false) {
216  if (isset($tbeModuleExt['MOD_MENU']) && isset($tbeModuleExt['MOD_MENU']['function'])) {
217  foreach ($tbeModuleExt['MOD_MENU']['function'] as $subModule) {
218  $entry = $this->‪createEntryFromRawData($subModule);
219  $matchingSubEntry->addChild($entry);
220  }
221  }
222  }
223  }
224  }
225 
232  public function ‪getRawModuleMenuData()
233  {
234  // Loads the backend modules available for the logged in user.
236  $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
237  $moduleLoader->observeWorkspaces = true;
238  $moduleLoader->load(‪$GLOBALS['TBE_MODULES']);
239  $loadedModules = $moduleLoader->modules;
240 
241  $modules = [];
242 
243  // Unset modules that are meant to be hidden from the menu.
244  $loadedModules = $this->‪removeHiddenModules($loadedModules);
245  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
246  $dummyScript = (string)$uriBuilder->buildUriFromRoute('dummy');
247  foreach ($loadedModules as $moduleName => $moduleData) {
248  $moduleLink = '';
249  if (!is_array($moduleData['sub'] ?? null)) {
250  $moduleLink = $moduleData['script'];
251  }
252  $moduleLink = GeneralUtility::resolveBackPath($moduleLink);
253  $moduleLabels = $moduleLoader->getLabelsForModule($moduleName);
254  $moduleKey = 'modmenu_' . $moduleName;
255  $modules[$moduleKey] = [
256  'name' => $moduleName,
257  'title' => $moduleLabels['title'],
258  'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName) . ');',
259  'icon' => $this->‪getModuleIcon($moduleKey, $moduleData),
260  'link' => $moduleLink,
261  'description' => $moduleLabels['shortdescription'],
262  'standalone' => (bool)($moduleData['standalone'] ?? false)
263  ];
264  if ((($moduleData['standalone'] ?? false) === false) && !is_array($moduleData['sub']) && $moduleData['script'] !== $dummyScript) {
265  // Work around for modules with own main entry, but being self the only submodule
266  $modules[$moduleKey]['subitems'][$moduleKey] = [
267  'name' => $moduleName,
268  'title' => $moduleLabels['title'],
269  'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName) . ');',
270  'icon' => $this->‪getModuleIcon($moduleKey, $moduleData),
271  'link' => $moduleLink,
272  'originalLink' => $moduleLink,
273  'description' => $moduleLabels['shortdescription'],
274  'navigationFrameScript' => null,
275  'navigationFrameScriptParam' => null,
276  'navigationComponentId' => null
277  ];
278  } elseif (is_array($moduleData['sub'] ?? null)) {
279  foreach ($moduleData['sub'] as $submoduleName => $submoduleData) {
280  if (isset($submoduleData['script'])) {
281  $submoduleLink = GeneralUtility::resolveBackPath($submoduleData['script']);
282  } else {
283  $submoduleLink = (string)$uriBuilder->buildUriFromRoute($submoduleData['name']);
284  }
285  $submoduleKey = $moduleName . '_' . $submoduleName;
286  $submoduleLabels = $moduleLoader->getLabelsForModule($submoduleKey);
287  $submoduleDescription = $submoduleLabels['shortdescription'];
288  $originalLink = $submoduleLink;
289  $navigationFrameScript = $submoduleData['navFrameScript'] ?? null;
290  $modules[$moduleKey]['subitems'][$submoduleKey] = [
291  'name' => $moduleName . '_' . $submoduleName,
292  'title' => $submoduleLabels['title'],
293  'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName . '_' . $submoduleName) . ');',
294  'icon' => $this->‪getModuleIcon($moduleKey, $submoduleData),
295  'link' => $submoduleLink,
296  'originalLink' => $originalLink,
297  'description' => $submoduleDescription,
298  'navigationFrameScript' => $navigationFrameScript,
299  'navigationFrameScriptParam' => $submoduleData['navFrameScriptParam'] ?? null,
300  'navigationComponentId' => $submoduleData['navigationComponentId'] ?? null
301  ];
302  // if the main module has a navframe script, inherit to the submodule,
303  // but only if it is not disabled explicitly (option is set to FALSE)
304  if (($moduleData['navFrameScript'] ?? false) && $submoduleData['inheritNavigationComponentFromMainModule'] !== false) {
305  $modules[$moduleKey]['subitems'][$submoduleKey]['parentNavigationFrameScript'] = $moduleData['navFrameScript'];
306  }
307  }
308  }
309  }
310  return $modules;
311  }
312 
313  public function ‪modulesHaveNavigationComponent(): bool
314  {
316  foreach ($this->moduleStorage->getEntries() as $module) {
317  if ($module->getNavigationComponentId() !== '') {
318  return true;
319  }
320  }
321 
322  return false;
323  }
324 
332  protected function ‪removeHiddenModules($loadedModules)
333  {
334  $userTsConfig = $this->‪getBackendUser()->‪getTSConfig();
335 
336  // Hide modules if set in userTS.
337  $hiddenMainModules = ‪GeneralUtility::trimExplode(',', $userTsConfig['options.']['hideModules'] ?? '', true);
338  foreach ($hiddenMainModules as $hiddenMainModule) {
339  unset($loadedModules[$hiddenMainModule]);
340  }
341 
342  // Hide sub-modules if set in userTS.
343  $hiddenModules = $userTsConfig['options.']['hideModules.'] ?? [];
344  if (is_array($hiddenModules)) {
345  foreach ($hiddenModules as $mainModuleName => $subModules) {
346  $hiddenSubModules = ‪GeneralUtility::trimExplode(',', $subModules, true);
347  foreach ($hiddenSubModules as $hiddenSubModule) {
348  unset($loadedModules[$mainModuleName]['sub'][$hiddenSubModule]);
349  }
350  }
351  }
352 
353  return $loadedModules;
354  }
355 
363  protected function ‪getModuleIcon($moduleKey, $moduleData)
364  {
365  $iconIdentifier = !empty($moduleData['iconIdentifier'])
366  ? $moduleData['iconIdentifier']
367  : 'module-icon-' . $moduleKey;
368  ‪$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
369  if (‪$iconRegistry->isRegistered($iconIdentifier)) {
370  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
371  return $iconFactory->getIcon($iconIdentifier)->render('inline');
372  }
373  return '';
374  }
375 
381  protected function ‪getLanguageService()
382  {
383  return ‪$GLOBALS['LANG'];
384  }
385 
389  protected function ‪getBackendUser(): BackendUserAuthentication
390  {
391  return ‪$GLOBALS['BE_USER'];
392  }
393 }
‪$iconRegistry
‪$iconRegistry
Definition: ext_localconf.php:43
‪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:200
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getLanguageService
‪LanguageService getLanguageService()
Definition: BackendModuleRepository.php:380
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig()
Definition: BackendUserAuthentication.php:1217
‪TYPO3\CMS\Backend\Module\ModuleStorage
Definition: ModuleStorage.php:25
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:33
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getRawModuleMenuData
‪array getRawModuleMenuData()
Definition: BackendModuleRepository.php:231
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getModuleIcon
‪string getModuleIcon($moduleKey, $moduleData)
Definition: BackendModuleRepository.php:362
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\removeHiddenModules
‪array removeHiddenModules($loadedModules)
Definition: BackendModuleRepository.php:331
‪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:38
‪TYPO3\CMS\Backend\Module\ModuleLoader
Definition: ModuleLoader.php:34
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Domain\Model\Module\BackendModule\getChildren
‪SplObjectStorage getChildren()
Definition: BackendModule.php:96
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository
Definition: BackendModuleRepository.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\findByModuleNameInGivenEntries
‪TYPO3 CMS Backend Domain Model Module BackendModule bool findByModuleNameInGivenEntries($name, \SplObjectStorage $entries)
Definition: BackendModuleRepository.php:111
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\findByModuleName
‪TYPO3 CMS Backend Domain Model Module BackendModule bool findByModuleName($name)
Definition: BackendModuleRepository.php:97
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: BackendModuleRepository.php:388
‪TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository\modulesHaveNavigationComponent
‪modulesHaveNavigationComponent()
Definition: BackendModuleRepository.php:312
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪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:46
‪TYPO3\CMS\Backend\Domain\Repository\Module
Definition: BackendModuleRepository.php:16