1<?php 2namespace TYPO3\CMS\Taskcenter\Controller; 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 17use Psr\Http\Message\ResponseInterface; 18use Psr\Http\Message\ServerRequestInterface; 19use TYPO3\CMS\Backend\Template\ModuleTemplate; 20use TYPO3\CMS\Backend\Utility\BackendUtility; 21use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; 22use TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait; 23use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait; 24use TYPO3\CMS\Core\Http\HtmlResponse; 25use TYPO3\CMS\Core\Localization\LanguageService; 26use TYPO3\CMS\Core\Messaging\FlashMessage; 27use TYPO3\CMS\Core\Messaging\FlashMessageService; 28use TYPO3\CMS\Core\Page\PageRenderer; 29use TYPO3\CMS\Core\Type\Bitmask\Permission; 30use TYPO3\CMS\Core\Utility\GeneralUtility; 31use TYPO3\CMS\Core\Utility\PathUtility; 32use TYPO3\CMS\Fluid\View\StandaloneView; 33use TYPO3\CMS\Taskcenter\TaskInterface; 34 35/** 36 * This class provides a task center for BE users 37 * @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API. 38 */ 39class TaskModuleController 40{ 41 use PublicPropertyDeprecationTrait; 42 use PublicMethodDeprecationTrait; 43 44 /** 45 * @var array 46 */ 47 private $deprecatedPublicProperties = [ 48 'MCONF' => 'Using TaskModuleController::$MCONF is deprecated and will not be possible anymore in TYPO3 v10.0.', 49 'id' => 'Using TaskModuleController::$id is deprecated and will not be possible anymore in TYPO3 v10.0.', 50 'MOD_MENU' => 'Using TaskModuleController::$MOD_MENU is deprecated and will not be possible anymore in TYPO3 v10.0.', 51 'modMenu_type' => 'Using TaskModuleController::$modMenu_type is deprecated and will not be possible anymore in TYPO3 v10.0.', 52 'modMenu_setDefaultList' => 'Using TaskModuleController::$$modMenu_setDefaultList is deprecated and will not be possible anymore in TYPO3 v10.0.', 53 'modMenu_dontValidateList' => 'Using TaskModuleController::$modMenu_dontValidateList is deprecated and will not be possible anymore in TYPO3 v10.0.', 54 'content' => 'Using TaskModuleController::$content is deprecated and will not be possible anymore in TYPO3 v10.0.', 55 'perms_clause' => 'Using TaskModuleController::$perms_clause is deprecated, the property will be removed in TYPO3 v10.0.', 56 'CMD' => 'Using TaskModuleController::$CMD is deprecated, the property will be removed in TYPO3 v10.0.', 57 'extClassConf' => 'Using TaskModuleController::$extClassConf is deprecated, the property will be removed in TYPO3 v10.0.', 58 'extObj' => 'Using TaskModuleController::$extObj is deprecated, the property will be removed in TYPO3 v10.0.', 59 ]; 60 61 /** 62 * @var array 63 */ 64 private $deprecatedPublicMethods = [ 65 'menuConfig' => 'Using TaskModuleController::menuConfig() is deprecated and will not be possible anymore in TYPO3 v10.0.', 66 'mergeExternalItems' => 'Using TaskModuleController::mergeExternalItems() is deprecated and will not be possible anymore in TYPO3 v10.0.', 67 'handleExternalFunctionValue' => 'Using TaskModuleController::handleExternalFunctionValue() is deprecated and will not be possible anymore in TYPO3 v10.0.', 68 'getExternalItemConfig' => 'Using TaskModuleController::getExternalItemConfig() is deprecated and will not be possible anymore in TYPO3 v10.0.', 69 'main' => 'Using TaskModuleController::main() is deprecated and will not be possible anymore in TYPO3 v10.0.', 70 'urlInIframe' => 'Using TaskModuleController::urlInIframe() is deprecated. The method will be removed in TYPO3 v10.0.', 71 'extObjHeader' => 'Using TaskModuleController::extObjHeader() is deprecated. The method will be removed in TYPO3 v10.0.', 72 'checkSubExtObj' => 'Using TaskModuleController::checkSubExtObj() is deprecated. The method will be removed in TYPO3 v10.0.', 73 'checkExtObj' => 'Using TaskModuleController::checkExtObj() is deprecated. The method will be removed in TYPO3 v10.0.', 74 'extObjContent' => 'Using TaskModuleController::extObjContent() is deprecated. The method will be removed in TYPO3 v10.0.', 75 'getExtObjContent' => 'Using TaskModuleController::getExtObjContent() is deprecated. The method will be removed in TYPO3 v10.0.', 76 ]; 77 78 /** 79 * Loaded with the global array $MCONF which holds some module configuration from the conf.php file of backend modules. 80 * 81 * @see init() 82 * @var array 83 */ 84 protected $MCONF = []; 85 86 /** 87 * The integer value of the GET/POST var, 'id'. Used for submodules to the 'Web' module (page id) 88 * 89 * @see init() 90 * @var int 91 */ 92 protected $id; 93 94 /** 95 * The value of GET/POST var, 'CMD' 96 * 97 * @see init() 98 * @var mixed 99 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 100 */ 101 protected $CMD; 102 103 /** 104 * A WHERE clause for selection records from the pages table based on read-permissions of the current backend user. 105 * 106 * @see init() 107 * @var string 108 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 109 */ 110 protected $perms_clause; 111 112 /** 113 * The module menu items array. Each key represents a key for which values can range between the items in the array of that key. 114 * 115 * @see init() 116 * @var array 117 */ 118 protected $MOD_MENU = [ 119 'function' => [] 120 ]; 121 122 /** 123 * Current settings for the keys of the MOD_MENU array 124 * Public since task objects use this. 125 * 126 * @see $MOD_MENU 127 * @var array 128 */ 129 public $MOD_SETTINGS = []; 130 131 /** 132 * Module TSconfig based on PAGE TSconfig / USER TSconfig 133 * Public since task objects use this. 134 * 135 * @see menuConfig() 136 * @var array 137 */ 138 public $modTSconfig; 139 140 /** 141 * 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. 142 * Can be set from extension classes of this class before the init() function is called. 143 * 144 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData() 145 * @var string 146 */ 147 protected $modMenu_type = ''; 148 149 /** 150 * 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. 151 * Can be set from extension classes of this class before the init() function is called. 152 * 153 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData() 154 * @var string 155 */ 156 protected $modMenu_dontValidateList = ''; 157 158 /** 159 * List of default values from $MOD_MENU to set in the output array (only if the values from MOD_MENU are not arrays) 160 * Can be set from extension classes of this class before the init() function is called. 161 * 162 * @see menuConfig(), \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData() 163 * @var string 164 */ 165 protected $modMenu_setDefaultList = ''; 166 167 /** 168 * Contains module configuration parts from TBE_MODULES_EXT if found 169 * 170 * @see handleExternalFunctionValue() 171 * @var array 172 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 173 */ 174 protected $extClassConf; 175 176 /** 177 * Generally used for accumulating the output content of backend modules 178 * 179 * @var string 180 */ 181 protected $content = ''; 182 183 /** 184 * May contain an instance of a 'Function menu module' which connects to this backend module. 185 * 186 * @see checkExtObj() 187 * @var \object 188 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 189 */ 190 protected $extObj; 191 192 /** 193 * @var array 194 */ 195 protected $pageinfo; 196 197 /** 198 * ModuleTemplate Container 199 * 200 * @var ModuleTemplate 201 */ 202 protected $moduleTemplate; 203 204 /** 205 * The name of the module 206 * 207 * @var string 208 */ 209 protected $moduleName = 'user_task'; 210 211 /** 212 * Initializes the Module 213 */ 214 public function __construct() 215 { 216 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class); 217 $this->getLanguageService()->includeLLFile('EXT:taskcenter/Resources/Private/Language/locallang_task.xlf'); 218 $this->MCONF = [ 219 'name' => $this->moduleName 220 ]; 221 // Name might be set from outside 222 if (!$this->MCONF['name']) { 223 $this->MCONF = $GLOBALS['MCONF']; 224 } 225 $this->id = (int)GeneralUtility::_GP('id'); 226 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 227 $this->CMD = GeneralUtility::_GP('CMD'); 228 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 229 $this->perms_clause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW); 230 $this->menuConfig(); 231 $this->handleExternalFunctionValue(); 232 } 233 234 /** 235 * Adds items to the ->MOD_MENU array. Used for the function menu selector. 236 */ 237 protected function menuConfig() 238 { 239 $this->MOD_MENU = ['mode' => []]; 240 $languageService = $this->getLanguageService(); 241 $this->MOD_MENU['mode']['information'] = $languageService->sL('LLL:EXT:taskcenter/Resources/Private/Language/locallang.xlf:task_overview'); 242 $this->MOD_MENU['mode']['tasks'] = $languageService->sL('LLL:EXT:taskcenter/Resources/Private/Language/locallang.xlf:task_tasks'); 243 // Copied from parent::menuConfig, because parent is hardcoded to menu.function, 244 // however menu.function is already used for the individual tasks. Therefore we use menu.mode here. 245 // Page/be_user TSconfig settings and blinding of menu-items 246 $this->modTSconfig['properties'] = BackendUtility::getPagesTSconfig($this->id)['mod.'][$this->moduleName . '.'] ?? []; 247 $this->MOD_MENU['mode'] = $this->mergeExternalItems($this->MCONF['name'], 'mode', $this->MOD_MENU['mode']); 248 $blindActions = $this->modTSconfig['properties']['menu.']['mode.'] ?? []; 249 foreach ($blindActions as $key => $value) { 250 if (!$value && array_key_exists($key, $this->MOD_MENU['mode'])) { 251 unset($this->MOD_MENU['mode'][$key]); 252 } 253 } 254 // Page / user TSconfig settings and blinding of menu-items 255 // Now overwrite the stuff again for unknown reasons 256 $this->modTSconfig['properties'] = BackendUtility::getPagesTSconfig($this->id)['mod.'][$this->MCONF['name'] . '.'] ?? []; 257 $this->MOD_MENU['function'] = $this->mergeExternalItems($this->MCONF['name'], 'function', $this->MOD_MENU['function']); 258 $blindActions = $this->modTSconfig['properties']['menu.']['function.'] ?? []; 259 foreach ($blindActions as $key => $value) { 260 if (!$value && array_key_exists($key, $this->MOD_MENU['function'])) { 261 unset($this->MOD_MENU['function'][$key]); 262 } 263 } 264 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->MCONF['name'], $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList); 265 } 266 267 /** 268 * Generates the menu based on $this->MOD_MENU 269 * 270 * @throws \InvalidArgumentException 271 */ 272 protected function generateMenu() 273 { 274 $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); 275 $menu->setIdentifier('WebFuncJumpMenu'); 276 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */ 277 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); 278 foreach ($this->MOD_MENU['mode'] as $controller => $title) { 279 $item = $menu 280 ->makeMenuItem() 281 ->setHref( 282 (string)$uriBuilder->buildUriFromRoute( 283 $this->moduleName, 284 [ 285 'id' => $this->id, 286 'SET' => [ 287 'mode' => $controller 288 ] 289 ] 290 ) 291 ) 292 ->setTitle($title); 293 if ($controller === $this->MOD_SETTINGS['mode']) { 294 $item->setActive(true); 295 } 296 $menu->addMenuItem($item); 297 } 298 $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu); 299 } 300 301 /** 302 * Injects the request object for the current request or subrequest 303 * Simply calls main() and writes the content to the response 304 * 305 * @param ServerRequestInterface $request the current request 306 * @return ResponseInterface the response with the content 307 */ 308 public function mainAction(ServerRequestInterface $request): ResponseInterface 309 { 310 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 311 $GLOBALS['SOBE'] = $this; 312 313 $this->main(); 314 $this->moduleTemplate->setContent($this->content); 315 return new HtmlResponse($this->moduleTemplate->renderContent()); 316 } 317 318 /** 319 * Creates the module's content. In this case it rather acts as a kind of # 320 * dispatcher redirecting requests to specific tasks. 321 */ 322 protected function main() 323 { 324 $this->getButtons(); 325 $this->generateMenu(); 326 $this->moduleTemplate->addJavaScriptCode( 327 'TaskCenterInlineJavascript', 328 'if (top.fsMod) { top.fsMod.recentIds["web"] = 0; }' 329 ); 330 331 // Render content depending on the mode 332 $mode = (string)$this->MOD_SETTINGS['mode']; 333 if ($mode === 'information') { 334 $this->renderInformationContent(); 335 } else { 336 $this->renderModuleContent(); 337 } 338 // Renders the module page 339 $this->moduleTemplate->setTitle($this->getLanguageService()->getLL('title')); 340 } 341 342 /** 343 * Generates the module content by calling the selected task 344 */ 345 protected function renderModuleContent() 346 { 347 $languageService = $this->getLanguageService(); 348 $chosenTask = (string)$this->MOD_SETTINGS['function']; 349 // Render the taskcenter task as default 350 if (empty($chosenTask) || $chosenTask === 'index') { 351 $chosenTask = 'taskcenter.tasks'; 352 } 353 // Render the task 354 $actionContent = ''; 355 $flashMessage = null; 356 list($extKey, $taskClass) = explode('.', $chosenTask, 2); 357 if (class_exists($taskClass)) { 358 $taskInstance = GeneralUtility::makeInstance($taskClass, $this); 359 if ($taskInstance instanceof TaskInterface) { 360 // Check if the task is restricted to admins only 361 if ($this->checkAccess($extKey, $taskClass)) { 362 $actionContent .= $taskInstance->getTask(); 363 } else { 364 $flashMessage = GeneralUtility::makeInstance( 365 FlashMessage::class, 366 $languageService->getLL('error-access'), 367 $languageService->getLL('error_header'), 368 FlashMessage::ERROR 369 ); 370 } 371 } else { 372 // Error if the task is not an instance of \TYPO3\CMS\Taskcenter\TaskInterface 373 $flashMessage = GeneralUtility::makeInstance( 374 FlashMessage::class, 375 sprintf($languageService->getLL('error_no-instance'), $taskClass, TaskInterface::class), 376 $languageService->getLL('error_header'), 377 FlashMessage::ERROR 378 ); 379 } 380 } else { 381 $flashMessage = GeneralUtility::makeInstance( 382 FlashMessage::class, 383 $languageService->sL('LLL:EXT:taskcenter/Resources/Private/Language/locallang_mod.xlf:mlang_labels_tabdescr'), 384 $languageService->sL('LLL:EXT:taskcenter/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'), 385 FlashMessage::INFO 386 ); 387 } 388 389 if ($flashMessage) { 390 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */ 391 $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class); 392 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */ 393 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); 394 $defaultFlashMessageQueue->enqueue($flashMessage); 395 } 396 397 $assigns = []; 398 $assigns['reports'] = $this->indexAction(); 399 $assigns['taskClass'] = strtolower(str_replace('\\', '-', htmlspecialchars($extKey . '-' . $taskClass))); 400 $assigns['actionContent'] = $actionContent; 401 402 // Rendering of the output via fluid 403 $view = GeneralUtility::makeInstance(StandaloneView::class); 404 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName( 405 'EXT:taskcenter/Resources/Private/Templates/ModuleContent.html' 406 )); 407 $view->assignMultiple($assigns); 408 $this->content .= $view->render(); 409 } 410 411 /** 412 * Generates the information content 413 */ 414 protected function renderInformationContent() 415 { 416 $assigns = []; 417 $assigns['LLPrefix'] = 'LLL:EXT:taskcenter/Resources/Private/Language/locallang.xlf:'; 418 $assigns['LLPrefixMod'] = 'LLL:EXT:taskcenter/Resources/Private/Language/locallang_mod.xlf:'; 419 $assigns['LLPrefixTask'] = 'LLL:EXT:taskcenter/Resources/Private/Language/locallang_task.xlf:'; 420 $assigns['admin'] = $this->getBackendUser()->isAdmin(); 421 422 // Rendering of the output via fluid 423 $view = GeneralUtility::makeInstance(StandaloneView::class); 424 $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:taskcenter/Resources/Private/Templates')]); 425 $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:taskcenter/Resources/Private/Partials')]); 426 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName( 427 'EXT:taskcenter/Resources/Private/Templates/InformationContent.html' 428 )); 429 $view->assignMultiple($assigns); 430 $this->content .= $view->render(); 431 } 432 433 /** 434 * Render the headline of a task including a title and an optional description. 435 * Public since task objects use this. 436 * 437 * @param string $title Title 438 * @param string $description Description 439 * @return string formatted title and description 440 */ 441 public function description($title, $description = '') 442 { 443 $descriptionView = GeneralUtility::makeInstance(StandaloneView::class); 444 $descriptionView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName( 445 'EXT:taskcenter/Resources/Private/Partials/Description.html' 446 )); 447 $descriptionView->assign('title', $title); 448 $descriptionView->assign('description', $description); 449 return $descriptionView->render(); 450 } 451 452 /** 453 * Render a list of items as a nicely formatted definition list including a link, icon, title and description. 454 * The keys of a single item are: 455 * - title: Title of the item 456 * - link: Link to the task 457 * - icon: Path to the icon or Icon as HTML if it begins with <img 458 * - description: Description of the task, using htmlspecialchars() 459 * - descriptionHtml: Description allowing HTML tags which will override the description 460 * Public since task objects use this. 461 * 462 * @param array $items List of items to be displayed in the definition list. 463 * @param bool $mainMenu Set it to TRUE to render the main menu 464 * @return string Formatted definition list 465 */ 466 public function renderListMenu($items, $mainMenu = false) 467 { 468 $assigns = []; 469 $assigns['mainMenu'] = $mainMenu; 470 471 // Change the sorting of items to the user's one 472 if ($mainMenu) { 473 $userSorting = unserialize($this->getBackendUser()->uc['taskcenter']['sorting'], ['allowed_classes' => false]); 474 if (is_array($userSorting)) { 475 $newSorting = []; 476 foreach ($userSorting as $item) { 477 if (isset($items[$item])) { 478 $newSorting[] = $items[$item]; 479 unset($items[$item]); 480 } 481 } 482 $items = $newSorting + $items; 483 } 484 } 485 if (is_array($items) && !empty($items)) { 486 foreach ($items as $itemKey => &$item) { 487 // Check for custom icon 488 if (!empty($item['icon'])) { 489 if (strpos($item['icon'], '<img ') === false) { 490 $iconFile = GeneralUtility::getFileAbsFileName($item['icon']); 491 if (@is_file($iconFile)) { 492 $item['iconFile'] = PathUtility::getAbsoluteWebPath($iconFile); 493 } 494 } 495 } 496 $id = $this->getUniqueKey($item['uid']); 497 $contentId = strtolower(str_replace('\\', '-', $id)); 498 $item['uniqueKey'] = $id; 499 $item['contentId'] = $contentId; 500 // Collapsed & expanded menu items 501 if (isset($this->getBackendUser()->uc['taskcenter']['states'][$id]) && $this->getBackendUser()->uc['taskcenter']['states'][$id]) { 502 $item['ariaExpanded'] = 'true'; 503 $item['collapseIcon'] = 'actions-view-list-expand'; 504 $item['collapsed'] = ''; 505 } else { 506 $item['ariaExpanded'] = 'false'; 507 $item['collapseIcon'] = 'actions-view-list-collapse'; 508 $item['collapsed'] = 'in'; 509 } 510 // Active menu item 511 $panelState = (string)$this->MOD_SETTINGS['function'] == $item['uid'] ? 'panel-active' : 'panel-default'; 512 $item['panelState'] = $panelState; 513 } 514 } 515 $assigns['items'] = $items; 516 517 // Rendering of the output via fluid 518 $view = GeneralUtility::makeInstance(StandaloneView::class); 519 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName( 520 'EXT:taskcenter/Resources/Private/Templates/ListMenu.html' 521 )); 522 $view->assignMultiple($assigns); 523 return $view->render(); 524 } 525 526 /** 527 * Shows an overview list of available reports. 528 * 529 * @return string List of available reports 530 */ 531 protected function indexAction() 532 { 533 $languageService = $this->getLanguageService(); 534 $content = ''; 535 $tasks = []; 536 $defaultIcon = 'EXT:taskcenter/Resources/Public/Icons/module-taskcenter.svg'; 537 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */ 538 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); 539 // Render the tasks only if there are any available 540 if (count($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'] ?? [])) { 541 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'] as $extKey => $extensionReports) { 542 foreach ($extensionReports as $taskClass => $task) { 543 if (!$this->checkAccess($extKey, $taskClass)) { 544 continue; 545 } 546 $link = (string)$uriBuilder->buildUriFromRoute('user_task') . '&SET[function]=' . $extKey . '.' . $taskClass; 547 $taskTitle = $languageService->sL($task['title']); 548 $taskDescriptionHtml = ''; 549 550 if (class_exists($taskClass)) { 551 $taskInstance = GeneralUtility::makeInstance($taskClass, $this); 552 if ($taskInstance instanceof TaskInterface) { 553 $taskDescriptionHtml = $taskInstance->getOverview(); 554 } 555 } 556 // Generate an array of all tasks 557 $uniqueKey = $this->getUniqueKey($extKey . '.' . $taskClass); 558 $tasks[$uniqueKey] = [ 559 'title' => $taskTitle, 560 'descriptionHtml' => $taskDescriptionHtml, 561 'description' => $languageService->sL($task['description']), 562 'icon' => !empty($task['icon']) ? $task['icon'] : $defaultIcon, 563 'link' => $link, 564 'uid' => $extKey . '.' . $taskClass 565 ]; 566 } 567 } 568 $content .= $this->renderListMenu($tasks, true); 569 } else { 570 $flashMessage = GeneralUtility::makeInstance( 571 FlashMessage::class, 572 $languageService->getLL('no-tasks'), 573 '', 574 FlashMessage::INFO 575 ); 576 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */ 577 $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class); 578 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */ 579 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); 580 $defaultFlashMessageQueue->enqueue($flashMessage); 581 } 582 return $content; 583 } 584 585 /** 586 * Create the panel of buttons for submitting the form or otherwise 587 * perform operations. 588 */ 589 protected function getButtons() 590 { 591 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); 592 593 // Shortcut 594 $shortcutButton = $buttonBar->makeShortcutButton() 595 ->setModuleName($this->moduleName) 596 ->setSetVariables(['function']); 597 $buttonBar->addButton($shortcutButton); 598 } 599 600 /** 601 * Check the access to a task. Considered are: 602 * - Admins are always allowed 603 * - Tasks can be restriced to admins only 604 * - Tasks can be blinded for Users with TsConfig taskcenter.<extensionkey>.<taskName> = 0 605 * 606 * @param string $extKey Extension key 607 * @param string $taskClass Name of the task 608 * @return bool Access to the task allowed or not 609 */ 610 protected function checkAccess($extKey, $taskClass): bool 611 { 612 $backendUser = $this->getBackendUser(); 613 // Admins are always allowed 614 if ($backendUser->isAdmin()) { 615 return true; 616 } 617 // Check if task is restricted to admins 618 if ((int)$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['taskcenter'][$extKey][$taskClass]['admin'] === 1) { 619 return false; 620 } 621 // Check if task is blinded with TsConfig (taskcenter.<extkey>.<taskName> 622 return (bool)($backendUser->getTSConfig()['taskcenter.'][$extKey . '.'][$taskClass] ?? true); 623 } 624 625 /** 626 * Returns HTML code to dislay an url in an iframe at the right side of the taskcenter 627 * 628 * @param string $url Url to display 629 * @return string Code that inserts the iframe (HTML) 630 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. Remember to remove the fluid template, too. 631 */ 632 protected function urlInIframe($url) 633 { 634 $urlView = GeneralUtility::makeInstance(StandaloneView::class); 635 $urlView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName( 636 'EXT:taskcenter/Resources/Private/Partials/UrlInIframe.html' 637 )); 638 $urlView->assign('url', $url); 639 return $urlView->render(); 640 } 641 642 /** 643 * Create a unique key from a string which can be used in JS for sorting 644 * Therefore '_' are replaced 645 * 646 * @param string $string string which is used to generate the identifier 647 * @return string Modified string 648 */ 649 protected function getUniqueKey($string) 650 { 651 $search = ['.', '_']; 652 $replace = ['-', '']; 653 return str_replace($search, $replace, $string); 654 } 655 656 /** 657 * Returns the current BE user. 658 * 659 * @return BackendUserAuthentication 660 */ 661 protected function getBackendUser(): BackendUserAuthentication 662 { 663 return $GLOBALS['BE_USER']; 664 } 665 666 /** 667 * Returns LanguageService 668 * 669 * @return LanguageService 670 */ 671 protected function getLanguageService(): LanguageService 672 { 673 return $GLOBALS['LANG']; 674 } 675 676 /** 677 * Public since task objects use this. 678 * 679 * @return ModuleTemplate 680 */ 681 public function getModuleTemplate(): ModuleTemplate 682 { 683 return $this->moduleTemplate; 684 } 685 686 /** 687 * Merges menu items from global array $TBE_MODULES_EXT 688 * 689 * @param string $modName Module name for which to find value 690 * @param string $menuKey Menu key, eg. 'function' for the function menu. 691 * @param array $menuArr The part of a MOD_MENU array to work on. 692 * @return array Modified array part. 693 * @internal 694 * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), menuConfig() 695 */ 696 protected function mergeExternalItems($modName, $menuKey, $menuArr) 697 { 698 $mergeArray = $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey]; 699 if (is_array($mergeArray)) { 700 foreach ($mergeArray as $k => $v) { 701 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')) { 702 $menuArr[$k] = $this->getLanguageService()->sL($v['title']); 703 } 704 } 705 } 706 return $menuArr; 707 } 708 709 /** 710 * Loads $this->extClassConf with the configuration for the CURRENT function of the menu. 711 * 712 * @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) 713 * @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) 714 * @see getExternalItemConfig(), init() 715 */ 716 protected function handleExternalFunctionValue($MM_key = 'function', $MS_value = null) 717 { 718 if ($MS_value === null) { 719 $MS_value = $this->MOD_SETTINGS[$MM_key]; 720 } 721 $this->extClassConf = $this->getExternalItemConfig($this->MCONF['name'], $MM_key, $MS_value); 722 } 723 724 /** 725 * Returns configuration values from the global variable $TBE_MODULES_EXT for the module given. 726 * 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. 727 * 728 * @param string $modName Module name 729 * @param string $menuKey Menu key, eg. "function" for the function menu. See $this->MOD_MENU 730 * @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... 731 * @return mixed The value from the TBE_MODULES_EXT array. 732 * @see handleExternalFunctionValue() 733 */ 734 protected function getExternalItemConfig($modName, $menuKey, $value = '') 735 { 736 if (isset($GLOBALS['TBE_MODULES_EXT'][$modName])) { 737 return (string)$value !== '' ? $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey][$value] : $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey]; 738 } 739 return null; 740 } 741 742 /** 743 * 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...) 744 * This value in extClassConf might be set by an extension (in an ext_tables/ext_localconf file) which thus "connects" to a module. 745 * The array $this->extClassConf is set in handleExternalFunctionValue() based on the value of MOD_SETTINGS[function] 746 * 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. 747 * 748 * @see handleExternalFunctionValue(), \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(), $extObj 749 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 750 */ 751 protected function checkExtObj() 752 { 753 if (is_array($this->extClassConf) && $this->extClassConf['name']) { 754 $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']); 755 $this->extObj->init($this, $this->extClassConf); 756 // Re-write: 757 $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->MCONF['name'], $this->modMenu_type, $this->modMenu_dontValidateList, $this->modMenu_setDefaultList); 758 } 759 } 760 761 /** 762 * Calls the checkExtObj function in sub module if present. 763 * 764 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 765 */ 766 protected function checkSubExtObj() 767 { 768 if (is_object($this->extObj)) { 769 $this->extObj->checkExtObj(); 770 } 771 } 772 773 /** 774 * Calls the 'header' function inside the "Function menu module" if present. 775 * 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. 776 * 777 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 778 */ 779 protected function extObjHeader() 780 { 781 if (is_callable([$this->extObj, 'head'])) { 782 $this->extObj->head(); 783 } 784 } 785 786 /** 787 * Calls the 'main' function inside the "Function menu module" if present 788 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 789 */ 790 protected function extObjContent() 791 { 792 if ($this->extObj === null) { 793 $flashMessage = GeneralUtility::makeInstance( 794 FlashMessage::class, 795 $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:no_modules_registered'), 796 $this->getLanguageService()->getLL('title'), 797 FlashMessage::ERROR 798 ); 799 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */ 800 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); 801 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */ 802 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); 803 $defaultFlashMessageQueue->enqueue($flashMessage); 804 } else { 805 $this->extObj->pObj = $this; 806 if (is_callable([$this->extObj, 'main'])) { 807 $this->content .= $this->extObj->main(); 808 } 809 } 810 } 811 812 /** 813 * Return the content of the 'main' function inside the "Function menu module" if present 814 * 815 * @return string 816 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 817 */ 818 protected function getExtObjContent() 819 { 820 $savedContent = $this->content; 821 $this->content = ''; 822 $this->extObjContent(); 823 $newContent = $this->content; 824 $this->content = $savedContent; 825 return $newContent; 826 } 827 828 /** 829 * @return PageRenderer 830 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0. 831 */ 832 protected function getPageRenderer(): PageRenderer 833 { 834 return GeneralUtility::makeInstance(PageRenderer::class); 835 } 836} 837