[FEATURE] Add FlashMessage support to ModuleTemplate API
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Template / ModuleTemplate.php
1 <?php
2 namespace TYPO3\CMS\Backend\Template;
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
17 use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
20 use TYPO3\CMS\Core\Imaging\Icon;
21 use TYPO3\CMS\Core\Imaging\IconFactory;
22 use TYPO3\CMS\Core\Messaging\AbstractMessage;
23 use TYPO3\CMS\Core\Messaging\FlashMessageService;
24 use TYPO3\CMS\Core\Page\PageRenderer;
25 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Fluid\View\Exception\InvalidTemplateResourceException;
28 use TYPO3\CMS\Fluid\View\StandaloneView;
29 use TYPO3\CMS\Lang\LanguageService;
30 use TYPO3\CMS\Version\View\VersionView;
31
32 /**
33 * A class taking care of the "outer" HTML of a module, especially
34 * the doc header and other related parts.
35 *
36 * @internal This API is not yet carved in stone and may be adapted later.
37 */
38 class ModuleTemplate
39 {
40 /**
41 * Error Icon Constant
42 *
43 * @internal
44 */
45 const STATUS_ICON_ERROR = 3;
46
47 /**
48 * Warning Icon Constant
49 *
50 * @internal
51 */
52 const STATUS_ICON_WARNING = 2;
53
54 /**
55 * Notification Icon Constant
56 *
57 * @internal
58 */
59 const STATUS_ICON_NOTIFICATION = 1;
60
61 /**
62 * OK Icon Constant
63 *
64 * @internal
65 */
66 const STATUS_ICON_OK = -1;
67
68 /**
69 * DocHeaderComponent
70 *
71 * @var DocHeaderComponent
72 */
73 protected $docHeaderComponent;
74
75 /**
76 * Javascript Code Array
77 * Used for inline JS
78 *
79 * @var array
80 */
81 protected $javascriptCodeArray = [];
82
83 /**
84 * Expose the pageRenderer
85 *
86 * @var PageRenderer
87 */
88 protected $pageRenderer;
89
90 /**
91 * TemplateRootPath
92 *
93 * @var string[]
94 */
95 protected $templateRootPaths = ['EXT:backend/Resources/Private/Templates'];
96
97 /**
98 * PartialRootPath
99 *
100 * @var string[]
101 */
102 protected $partialRootPaths = ['EXT:backend/Resources/Private/Partials'];
103
104 /**
105 * LayoutRootPath
106 *
107 * @var string[]
108 */
109 protected $layoutRootPaths = ['EXT:backend/Resources/Private/Layouts'];
110
111 /**
112 * Template name
113 *
114 * @var string
115 */
116 protected $templateFile = 'Module.html';
117
118 /**
119 * Fluid Standalone View
120 *
121 * @var StandaloneView
122 */
123 protected $view;
124
125 /**
126 * Content String
127 *
128 * @var string
129 */
130 protected $content = '';
131
132 /**
133 * Defines whether a section has been opened before
134 *
135 * @var int
136 */
137 protected $sectionFlag = 0;
138
139 /**
140 * IconFactory Member
141 *
142 * @var IconFactory
143 */
144 protected $iconFactory;
145
146 /**
147 * Module ID
148 *
149 * @var string
150 */
151 protected $moduleId = '';
152
153 /**
154 * Module Name
155 *
156 * @var string
157 */
158 protected $moduleName = '';
159
160 /**
161 * Title Tag
162 *
163 * @var string
164 */
165 protected $title = '';
166
167 /**
168 * Flash message queue
169 *
170 * @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue
171 */
172 protected $flashMessageQueue;
173
174 /**
175 * Gets the standalone view.
176 *
177 * @return StandaloneView
178 */
179 public function getView()
180 {
181 return $this->view;
182 }
183
184 /**
185 * Set content
186 *
187 * @param string $content Content of the module
188 * @return void
189 */
190 public function setContent($content)
191 {
192 $this->view->assign('content', $content);
193 }
194
195 /**
196 * Set title tag
197 *
198 * @param string $title
199 */
200 public function setTitle($title)
201 {
202 $this->title = $title;
203 }
204
205 /**
206 * Returns the IconFactory
207 *
208 * @return IconFactory
209 */
210 public function getIconFactory()
211 {
212 return $this->iconFactory;
213 }
214
215 /**
216 * Class constructor
217 * Sets up view and property objects
218 *
219 * @throws InvalidTemplateResourceException In case a template is invalid
220 */
221 public function __construct()
222 {
223 $this->view = GeneralUtility::makeInstance(StandaloneView::class);
224 $this->view->setPartialRootPaths($this->partialRootPaths);
225 $this->view->setTemplateRootPaths($this->templateRootPaths);
226 $this->view->setLayoutRootPaths($this->layoutRootPaths);
227 $this->view->setTemplate($this->templateFile);
228 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
229 $this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class);
230 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
231 }
232
233 /**
234 * Loads all necessary Javascript Files
235 *
236 * @return void
237 */
238 protected function loadJavaScripts()
239 {
240 $this->pageRenderer->loadJquery();
241 $this->pageRenderer->loadRequireJsModule('bootstrap');
242 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
243 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DocumentHeader');
244 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/SplitButtons');
245 }
246
247 /**
248 * Loads all necessary stylesheets
249 *
250 * @return void
251 */
252 protected function loadStylesheets()
253 {
254 if ($GLOBALS['TBE_STYLES']['stylesheet']) {
255 $this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheet']);
256 }
257 if ($GLOBALS['TBE_STYLES']['stylesheet2']) {
258 $this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheet2']);
259 }
260 }
261
262 /**
263 * Sets mandatory parameters for the view (pageRenderer)
264 *
265 * @return void
266 */
267 protected function setupPage()
268 {
269 // Yes, hardcoded on purpose
270 $this->pageRenderer->setXmlPrologAndDocType('<!DOCTYPE html>');
271 $this->pageRenderer->setCharSet('utf-8');
272 $this->pageRenderer->setLanguage('default');
273 $this->pageRenderer->addMetaTag('<meta name="viewport" content="width=device-width, initial-scale=1">');
274 }
275
276 /**
277 * Wrapper function for adding JS inline blocks
278 *
279 * @return void
280 */
281 protected function setJavaScriptCodeArray()
282 {
283 foreach ($this->javascriptCodeArray as $name => $code) {
284 $this->pageRenderer->addJsInlineCode($name, $code, false);
285 }
286 }
287
288 /**
289 * Adds JS inline blocks of code to the internal registry
290 *
291 * @param string $name Javascript code block name
292 * @param string $code Inline Javascript
293 *
294 * @return void
295 */
296 public function addJavaScriptCode($name = '', $code = '')
297 {
298 $this->javascriptCodeArray[$name] = $code;
299 }
300
301 /**
302 * Get the DocHeader
303 *
304 * @return DocHeaderComponent
305 */
306 public function getDocHeaderComponent()
307 {
308 return $this->docHeaderComponent;
309 }
310
311 /**
312 * Returns the fully rendered view
313 *
314 * @return string
315 */
316 public function renderContent()
317 {
318 $this->setupPage();
319 $this->pageRenderer->setTitle($this->title);
320 $this->loadJavaScripts();
321 $this->setJavaScriptCodeArray();
322 $this->loadStylesheets();
323
324 $this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent());
325 if ($this->moduleId) {
326 $this->view->assign('moduleId', $this->moduleId);
327 }
328 if ($this->moduleName) {
329 $this->view->assign('moduleName', $this->moduleName);
330 }
331
332 $renderedPage = $this->pageRenderer->render(PageRenderer::PART_HEADER);
333 $renderedPage .= $this->view->render();
334 $this->pageRenderer->addJsFooterInlineCode('updateSignals', BackendUtility::getUpdateSignalCode());
335 $renderedPage .= $this->pageRenderer->render(PageRenderer::PART_FOOTER);
336
337 return $renderedPage;
338 }
339
340 /**
341 * Get PageRenderer
342 *
343 * @return PageRenderer
344 */
345 public function getPageRenderer()
346 {
347 return $this->pageRenderer;
348 }
349
350 /**
351 * Set form tag
352 *
353 * @param string $formTag Form tag to add
354 *
355 * @return void
356 */
357 public function setForm($formTag = '')
358 {
359 $this->view->assign('formTag', $formTag);
360 }
361
362 /**
363 * Sets the ModuleId
364 *
365 * @param string $moduleId ID of the module
366 *
367 * @return void
368 */
369 public function setModuleId($moduleId)
370 {
371 $this->moduleId = $moduleId;
372 $this->registerModuleMenu($moduleId);
373 }
374
375 /**
376 * Sets the ModuleName
377 *
378 * @param string $moduleName Name of the module
379 *
380 * @return void
381 */
382 public function setModuleName($moduleName)
383 {
384 $this->moduleName = $moduleName;
385 }
386
387 /**
388 * Generates the Menu for things like Web->Info
389 *
390 * @param $moduleMenuIdentifier
391 */
392 public function registerModuleMenu($moduleMenuIdentifier)
393 {
394 if (isset($GLOBALS['TBE_MODULES_EXT'][$moduleMenuIdentifier])) {
395 $menuEntries =
396 $GLOBALS['TBE_MODULES_EXT'][$moduleMenuIdentifier]['MOD_MENU']['function'];
397 $menu = $this->getDocHeaderComponent()->getMenuRegistry()->makeMenu()->setIdentifier('MOD_FUNC');
398 foreach ($menuEntries as $menuEntry) {
399 $menuItem = $menu->makeMenuItem()
400 ->setTitle($menuEntry['title'])
401 ->setHref('#');
402 $menu->addMenuItem($menuItem);
403 }
404 $this->docHeaderComponent->getMenuRegistry()->addMenu($menu);
405 }
406 }
407
408 /**
409 * Creates a tab menu where the tabs or collapsible are rendered with bootstrap markup
410 *
411 * @param array $menuItems Tab elements, each element is an array with "label" and "content"
412 * @param string $domId DOM id attribute, will be appended with an iteration number per tab.
413 * @param int $defaultTabIndex Default tab to open (for toggle <=0). Value corresponds to integer-array index + 1
414 * (index zero is "1", index "1" is 2 etc.). A value of zero (or something non-existing
415 * will result in no default tab open.
416 * @param bool $collapsible If set, the tabs are rendered as headers instead over each sheet. Effectively this means
417 * there is no tab menu, but rather a foldout/fold-in menu.
418 * @param bool $wrapContent If set, the content is wrapped in div structure which provides a padding and border
419 * style. Set this FALSE to get unstyled content pane with fullsize content area.
420 * @param bool $storeLastActiveTab If set, the last open tab is stored in local storage and will be re-open again.
421 * If you don't need this feature, e.g. for wizards like import/export you can
422 * disable this behaviour.
423 * @return string
424 */
425 public function getDynamicTabMenu(array $menuItems, $domId, $defaultTabIndex = 1, $collapsible = false, $wrapContent = true, $storeLastActiveTab = true)
426 {
427 $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tabs');
428 $templatePathAndFileName = 'EXT:backend/Resources/Private/Templates/DocumentTemplate/' . ($collapsible ? 'Collapse.html' : 'Tabs.html');
429 $view = GeneralUtility::makeInstance(StandaloneView::class);
430 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFileName));
431 $view->assignMultiple(array(
432 'id' => 'DTM-' . GeneralUtility::shortMD5($domId),
433 'items' => $menuItems,
434 'defaultTabIndex' => $defaultTabIndex,
435 'wrapContent' => $wrapContent,
436 'storeLastActiveTab' => $storeLastActiveTab,
437 ));
438 return $view->render();
439 }
440
441 /*******************************************
442 * THE FOLLOWING METHODS ARE SUBJECT TO BE DEPRECATED / DROPPED!
443 *
444 * These methods have been copied over from DocumentTemplate and enables
445 * core modules to drop the dependency to DocumentTemplate altogether without
446 * rewriting these modules now.
447 * The methods below are marked as internal and will be removed
448 * one-by-one with further refactoring of modules.
449 *
450 * Do not use these methods within own extensions if possible or
451 * be prepared to change this later again.
452 *******************************************/
453
454 /**
455 * Includes a javascript library that exists in the core /typo3/ directory
456 *
457 * @param string $lib Library name. Call it with the full path like
458 * "sysext/core/Resources/Public/JavaScript/QueryGenerator.js" to load it
459 *
460 * @return void
461 * @internal
462 */
463 public function loadJavascriptLib($lib)
464 {
465 // @todo: maybe we can remove this one as well
466 $this->pageRenderer->addJsFile($lib);
467 }
468
469 /**
470 * Returns a linked shortcut-icon which will call the shortcut frame and set a
471 * shortcut there back to the calling page/module
472 *
473 * @param string $gvList Is the list of GET variables to store (if any)
474 * @param string $setList Is the list of SET[] variables to store
475 * (if any) - SET[] variables a stored in $GLOBALS["SOBE"]->MOD_SETTINGS
476 * for backend modules
477 * @param string $modName Module name string
478 * @param string|int $motherModName Is used to enter the "parent module
479 * name" if the module is a submodule under eg. Web>* or File>*. You
480 * can also set this value to 1 in which case the currentLoadedModule
481 * is sent to the shortcut script (so - not a fixed value!) - that is used
482 * in file_edit and wizard_rte modules where those are really running as
483 * a part of another module.
484 * @param string $displayName When given this name is used instead of the
485 * module name.
486 * @param string $classes Additional CSS classes for the link around the icon
487 *
488 * @return string HTML content
489 * @todo Make this thing return a button object
490 * @internal
491 */
492 public function makeShortcutIcon($gvList, $setList, $modName, $motherModName = '', $displayName = '', $classes = 'btn btn-default btn-sm')
493 {
494 $gvList = 'route,' . $gvList;
495 $storeUrl = $this->makeShortcutUrl($gvList, $setList);
496 $pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
497 // Fallback for alt_mod. We still pass in the old xMOD... stuff,
498 // but TBE_MODULES only knows about "record_edit".
499 // We still need to pass the xMOD name to createShortcut below,
500 // since this is used for icons.
501 $moduleName = $modName === 'xMOD_alt_doc.php' ? 'record_edit' : $modName;
502 // Add the module identifier automatically if typo3/index.php is used:
503 if (GeneralUtility::_GET('M') !== null && isset($GLOBALS['TBE_MODULES']['_PATHS'][$moduleName])) {
504 $storeUrl = '&M=' . $moduleName . $storeUrl;
505 }
506 if ((int)$motherModName === 1) {
507 $motherModule = 'top.currentModuleLoaded';
508 } elseif ($motherModName) {
509 $motherModule = GeneralUtility::quoteJSvalue($motherModName);
510 } else {
511 $motherModule = '\'\'';
512 }
513 $confirmationText = GeneralUtility::quoteJSvalue(
514 $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark')
515 );
516
517 $shortcutUrl = $pathInfo['path'] . '?' . $storeUrl;
518 $shortcutExist = BackendUtility::shortcutExists($shortcutUrl);
519
520 if ($shortcutExist) {
521 return '<a class="active ' . htmlspecialchars($classes) . '" title="">' .
522 $this->iconFactory->getIcon('actions-system-shortcut-active', Icon::SIZE_SMALL)->render() . '</a>';
523 }
524
525 $url = GeneralUtility::quoteJSvalue(rawurlencode($shortcutUrl));
526 $onClick = 'top.TYPO3.ShortcutMenu.createShortcut(' . GeneralUtility::quoteJSvalue(rawurlencode($modName)) .
527 ', ' . $url . ', ' . $confirmationText . ', ' . $motherModule . ', this, ' . GeneralUtility::quoteJSvalue($displayName) . ');return false;';
528
529 return '<a href="#" class="' . htmlspecialchars($classes) . '" onclick="' . htmlspecialchars($onClick) . '" title="' .
530 $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark', true) . '">' .
531 $this->iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render() . '</a>';
532 }
533
534 /**
535 * MAKE url for storing
536 * Internal func
537 *
538 * @param string $gvList Is the list of GET variables to store (if any)
539 * @param string $setList Is the list of SET[] variables to store (if any)
540 * - SET[] variables a stored in $GLOBALS["SOBE"]->MOD_SETTINGS for backend
541 * modules
542 *
543 * @return string
544 * @internal
545 */
546 public function makeShortcutUrl($gvList, $setList)
547 {
548 $getParams = GeneralUtility::_GET();
549 $storeArray = array_merge(
550 GeneralUtility::compileSelectedGetVarsFromArray($gvList, $getParams),
551 array('SET' => GeneralUtility::compileSelectedGetVarsFromArray($setList, (array)$GLOBALS['SOBE']->MOD_SETTINGS))
552 );
553 return GeneralUtility::implodeArrayForUrl('', $storeArray);
554 }
555
556 /**
557 * Creates the version selector for the page id inputted.
558 * Requires the core version management extension, "version" to be loaded.
559 *
560 * @param int $id Page id to create selector for.
561 * @param bool $noAction If set, there will be no button for swapping page.
562 *
563 * @return string
564 * @internal
565 */
566 public function getVersionSelector($id, $noAction = false)
567 {
568 if (ExtensionManagementUtility::isLoaded('version')
569 && !ExtensionManagementUtility::isLoaded('workspaces')
570 ) {
571 /**
572 * For Code Completion
573 *
574 * @var $versionGuiObj VersionView
575 */
576 $versionGuiObj = GeneralUtility::makeInstance(VersionView::class);
577 return $versionGuiObj->getVersionSelector($id, $noAction);
578 }
579 return '';
580 }
581
582 /**
583 * Begins an output section and sets header and content
584 *
585 * @param string $label The header
586 * @param string $text The HTML-content
587 * @param bool $noStrToUpper A flag that will prevent the header from
588 * being converted to uppercase
589 * @param bool $sH Defines the type of header (if set, "<h3>" rather
590 * than the default "h4")
591 * @param int $type The number of an icon to show with the header
592 * (see the icon-function). -1,1,2,3
593 * @param bool $allowHtmlInHeader If set, HTML tags are allowed in
594 * $label (otherwise this value is by default htmlspecialchars()'ed)
595 *
596 * @return string HTML content
597 * @internal
598 */
599 public function section($label, $text, $noStrToUpper = false, $sH = false, $type = 0, $allowHtmlInHeader = false)
600 {
601 $str = '';
602 // Setting header
603 if ($label) {
604 if (!$allowHtmlInHeader) {
605 $label = htmlspecialchars($label);
606 }
607 $str .= $this->sectionHeader($this->icons($type) . $label, $sH, $noStrToUpper ? '' : ' class="uppercase"');
608 }
609 // Setting content
610 $str .= '
611
612 <!-- Section content -->
613 ' . $text;
614 return $this->sectionBegin() . $str;
615 }
616
617 /**
618 * Inserts a divider image
619 * Ends a section (if open) before inserting the image
620 *
621 * @param int $dist The margin-top/-bottom of the <hr> ruler.
622 *
623 * @return string HTML content
624 * @internal
625 */
626 public function divider($dist)
627 {
628 $dist = (int)$dist;
629 $str = '
630
631 <!-- DIVIDER -->
632 <hr style="margin-top: ' . $dist . 'px; margin-bottom: ' . $dist . 'px;" />
633 ';
634 return $this->sectionEnd() . $str;
635 }
636
637 /**
638 * Make a section header.
639 * Begins a section if not already open.
640 *
641 * @param string $label The label between the <h3> or <h4> tags. (Allows HTML)
642 * @param bool $sH If set, <h3> is used, otherwise <h4>
643 * @param string $addAttribute Additional attributes to h-tag, eg. ' class=""'
644 *
645 * @return string HTML content
646 * @internal
647 */
648 public function sectionHeader($label, $sH = false, $addAttribute = '')
649 {
650 $tag = $sH ? 'h2' : 'h3';
651 if ($addAttribute && $addAttribute[0] !== ' ') {
652 $addAttribute = ' ' . $addAttribute;
653 }
654 $str = '
655
656 <!-- Section header -->
657 <' . $tag . $addAttribute . '>' . $label . '</' . $tag . '>
658 ';
659 return $this->sectionBegin() . $str;
660 }
661
662 /**
663 * Begins an output section.
664 * Returns the <div>-begin tag AND sets the ->sectionFlag TRUE
665 * (if the ->sectionFlag is not already set!)
666 * You can call this function even if a section is already begun
667 * since the function will only return something if the sectionFlag
668 * is not already set!
669 *
670 * @return string HTML content
671 * @internal
672 */
673 public function sectionBegin()
674 {
675 if (!$this->sectionFlag) {
676 $this->sectionFlag = 1;
677 $str = '
678
679 <!-- ***********************
680 Begin output section.
681 *********************** -->
682 <div>
683 ';
684 return $str;
685 }
686 return '';
687 }
688
689 /**
690 * Ends and output section
691 * Returns the </div>-end tag AND clears the ->sectionFlag
692 * (but does so only IF the sectionFlag is set - that is a section is 'open')
693 * See sectionBegin() also.
694 *
695 * @return string HTML content
696 * @internal
697 */
698 public function sectionEnd()
699 {
700 if ($this->sectionFlag) {
701 $this->sectionFlag = 0;
702 return '
703 </div>
704 <!-- *********************
705 End output section.
706 ********************* -->
707 ';
708 }
709 return '';
710 }
711
712
713
714 /**
715 * Returns the BE USER Object
716 *
717 * @return BackendUserAuthentication
718 */
719 protected function getBackendUserAuthentication()
720 {
721 return $GLOBALS['BE_USER'];
722 }
723
724 /**
725 * Returns the LanguageService
726 *
727 * @return LanguageService
728 */
729 protected function getLanguageService()
730 {
731 return $GLOBALS['LANG'];
732 }
733
734 /**
735 * Returns an image-tag with an 18x16 icon of the following types:
736 *
737 * $type:
738 * -1:» OK icon (Check-mark)
739 * 1:» Notice (Speach-bubble)
740 * 2:» Warning (Yellow triangle)
741 * 3:» Fatal error (Red stop sign)
742 *
743 * @param int $type See description
744 *
745 * @return string HTML image tag (if applicable)
746 * @internal
747 */
748 public function icons($type)
749 {
750 $icon = '';
751 switch ($type) {
752 case self::STATUS_ICON_ERROR:
753 $icon = 'status-dialog-error';
754 break;
755 case self::STATUS_ICON_WARNING:
756 $icon = 'status-dialog-warning';
757 break;
758 case self::STATUS_ICON_NOTIFICATION:
759 $icon = 'status-dialog-notification';
760 break;
761 case self::STATUS_ICON_OK:
762 $icon = 'status-dialog-ok';
763 break;
764 default:
765 // Do nothing
766 }
767 if ($icon != '') {
768 return $this->iconFactory->getIcon($icon, Icon::SIZE_SMALL)->render();
769 }
770 return '';
771 }
772
773 /**
774 * Returns JavaScript variables setting the returnUrl and thisScript location for use by JavaScript on the page.
775 * Used in fx. db_list.php (Web>List)
776 *
777 * @param string $thisLocation URL to "this location" / current script
778 * @return string Urls are returned as JavaScript variables T3_RETURN_URL and T3_THIS_LOCATION
779 * @see typo3/db_list.php
780 * @internal
781 */
782 public function redirectUrls($thisLocation = '')
783 {
784 $thisLocation = $thisLocation ? $thisLocation : GeneralUtility::linkThisScript(array(
785 'CB' => '',
786 'SET' => '',
787 'cmd' => '',
788 'popViewId' => ''
789 ));
790 $out = '
791 var T3_RETURN_URL = ' . GeneralUtility::quoteJSvalue(str_replace('%20', '', rawurlencode(GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'))))) . ';
792 var T3_THIS_LOCATION = ' . GeneralUtility::quoteJSvalue(str_replace('%20', '', rawurlencode($thisLocation))) . '
793 ';
794 return $out;
795 }
796
797 /**
798 * Returns the header-bar in the top of most backend modules
799 * Closes section if open.
800 *
801 * @param string $text The text string for the header
802 * @return string HTML content
803 * @internal
804 */
805 public function header($text)
806 {
807 $str = '
808
809 <!-- MAIN Header in page top -->
810 <h1 class="t3js-title-inlineedit">' . htmlspecialchars($text) . '</h1>
811 ';
812 return $this->sectionEnd() . $str;
813 }
814
815 /**
816 * Creates a Message object and adds it to the FlashMessageQueue.
817 *
818 * @param string $messageBody The message
819 * @param string $messageTitle Optional message title
820 * @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\FlashMessage constants
821 * @param bool $storeInSession Optional, defines whether the message should be stored in the session (default)
822 * @return void
823 * @throws \InvalidArgumentException if the message body is no string
824 */
825 public function addFlashMessage($messageBody, $messageTitle = '', $severity = AbstractMessage::OK, $storeInSession = true)
826 {
827 if (!is_string($messageBody)) {
828 throw new \InvalidArgumentException('The message body must be of type string, "' . gettype($messageBody) . '" given.', 1446483133);
829 }
830 /* @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
831 $flashMessage = GeneralUtility::makeInstance(
832 \TYPO3\CMS\Core\Messaging\FlashMessage::class,
833 $messageBody,
834 $messageTitle,
835 $severity,
836 $storeInSession
837 );
838 $this->getFlashMessageQueue()->enqueue($flashMessage);
839 }
840
841 /**
842 * @return \TYPO3\CMS\Core\Messaging\FlashMessageQueue
843 */
844 protected function getFlashMessageQueue()
845 {
846 if (!isset($this->flashMessageQueue)) {
847 /** @var FlashMessageService $service */
848 $service = GeneralUtility::makeInstance(FlashMessageService::class);
849 $this->flashMessageQueue = $service->getMessageQueueByIdentifier('module.template.flashmessages');
850 }
851 return $this->flashMessageQueue;
852 }
853 }