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