'; private string $formTag = ''; private FlashMessageQueue $flashMessageQueue; private DocHeaderComponent $docHeaderComponent; /** * Init PageRenderer and properties. */ public function __construct( protected readonly PageRenderer $pageRenderer, protected readonly IconFactory $iconFactory, protected readonly UriBuilder $uriBuilder, protected readonly ModuleProvider $moduleProvider, protected readonly FlashMessageService $flashMessageService, protected readonly ExtensionConfiguration $extensionConfiguration, protected readonly ViewInterface $view, protected readonly ComponentFactory $componentFactory, protected readonly ServerRequestInterface $request, ) { $module = $request->getAttribute('module'); if ($module instanceof ModuleInterface) { // third level, needs the second level in order to keep highlighting in the module menu if ($module->getParentModule()?->getParentModule()) { $this->setModuleName($module->getParentModule()->getIdentifier()); } else { $this->setModuleName($module->getIdentifier()); } $this->setModuleName($module->getIdentifier()); } else { $this->setModuleName($request->getAttribute('route')?->getOption('_identifier') ?? ''); } $this->flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class); $this->setUpBasicPageRendererForBackend($pageRenderer, $extensionConfiguration, $request, $this->getLanguageService()); } /** * Add a variable to the view data collection. */ public function assign(string $key, mixed $value): self { $this->view->assign($key, $value); return $this; } /** * Add multiple variables to the view data collection. */ public function assignMultiple(array $values): self { $this->view->assignMultiple($values); return $this; } /** * Render the module. */ public function render(string $templateFileName = ''): string { $this->prepareRender($templateFileName); return $this->pageRenderer->render($this->request); } /** * Render the module and create an HTML 200 response from it. This is a * lazy shortcut so controllers don't need to take care of this in the backend. */ public function renderResponse(string $templateFileName = ''): ResponseInterface { $this->prepareRender($templateFileName); return $this->pageRenderer->renderResponse($this->request); } private function prepareRender(string $templateFileName): void { if ($templateFileName === '') { $extbaseRequestMessage = ''; /** @var ExtbaseRequestParameters|null $extbaseRequestParameters */ $extbaseRequestParameters = $this->request->getAttribute('extbase'); if ($extbaseRequestParameters) { // This extbase specific code is a helper for a more detailed exception // message, and a tribute to extbase backend extensions being upgraded. // Introduced with v13, it could potentially vanish at some point again. $templateFileName = $extbaseRequestParameters->getControllerName() . '/' . ucfirst($extbaseRequestParameters->getControllerActionName()); $extbaseRequestMessage = ' Expected template filename is "' . $templateFileName . '".'; } throw new \InvalidArgumentException('A template filename must be provided.' . $extbaseRequestMessage, 1732184506); } $this->assignMultiple([ 'docHeader' => $this->docHeaderComponent->docHeaderContent($this->request), 'moduleId' => $this->moduleId, 'moduleName' => $this->moduleName, 'moduleClass' => $this->moduleClass, 'moduleLayout' => $this->moduleLayout->value, 'uiBlock' => $this->uiBlock, 'flashMessageQueueIdentifier' => $this->flashMessageQueue->getIdentifier(), 'formTag' => $this->formTag, ]); $this->pageRenderer->getJavaScriptRenderer()->includeAllImports(); $this->pageRenderer->loadJavaScriptModule('bootstrap'); $this->pageRenderer->loadJavaScriptModule('@typo3/backend/dropdown.js'); $this->pageRenderer->loadJavaScriptModule('@typo3/backend/context-help.js'); $this->pageRenderer->loadJavaScriptModule('@typo3/backend/global-event-handler.js'); $this->pageRenderer->loadJavaScriptModule('@typo3/backend/action-dispatcher.js'); $this->pageRenderer->loadJavaScriptModule('@typo3/backend/element/immediate-action-element.js'); $this->pageRenderer->loadJavaScriptModule('@typo3/backend/hotkeys.js'); $this->pageRenderer->addBodyContent($this->bodyTag . $this->view->render($templateFileName)); $this->pageRenderer->setTitle($this->title); $updateSignalDetails = BackendUtility::getUpdateSignalDetails(); if (!empty($updateSignalDetails['html'])) { $this->pageRenderer->addHeaderData(implode("\n", $updateSignalDetails['html'])); } $this->dispatchNotificationMessages(); } /** * @internal */ public function setLayout(ModuleLayout $moduleLayout): self { $this->moduleLayout = $moduleLayout; return $this; } /** * Set to something like '
' when a special body tag is needed. */ public function setBodyTag(string $bodyTag): self { $this->bodyTag = $bodyTag; return $this; } /** * Title string of the module: "My module · Edit view" */ public function setTitle(string $title, string $context = ''): self { $titleComponents = [$title]; if ($context !== '') { $titleComponents[] = $context; } $this->title = implode(' · ', $titleComponents); return $this; } /** * Get the DocHeader. Can be used in controllers to add custom * buttons / menus / ... to the doc header. */ public function getDocHeaderComponent(): DocHeaderComponent { return $this->docHeaderComponent; } /** * A "