Completed
Push — master ( f66149...a7372c )
by
unknown
130:24 queued 111:56
created

BackendLayoutRenderer   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 76
c 1
b 0
f 0
dl 0
loc 152
rs 10
wmc 13

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getLanguageService() 0 3 1
A drawContent() 0 38 4
A initializeClipboard() 0 27 5
A __construct() 0 14 1
A drawPasteIcon() 0 12 1
A getBackendUser() 0 3 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace TYPO3\CMS\Backend\View\Drawing;
5
6
/*
7
 * This file is part of the TYPO3 CMS project.
8
 *
9
 * It is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License, either version 2
11
 * of the License, or any later version.
12
 *
13
 * For the full copyright and license information, please read the
14
 * LICENSE.txt file that was distributed with this source code.
15
 *
16
 * The TYPO3 project - inspiring people to share!
17
 */
18
19
use Psr\Log\LoggerAwareTrait;
20
use TYPO3\CMS\Backend\Clipboard\Clipboard;
21
use TYPO3\CMS\Backend\Utility\BackendUtility;
22
use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout;
23
use TYPO3\CMS\Backend\View\BackendLayout\Grid\Grid;
24
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumn;
25
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridRow;
26
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
27
use TYPO3\CMS\Core\Imaging\Icon;
28
use TYPO3\CMS\Core\Imaging\IconFactory;
29
use TYPO3\CMS\Core\Localization\LanguageService;
30
use TYPO3\CMS\Core\Messaging\FlashMessage;
31
use TYPO3\CMS\Core\Messaging\FlashMessageService;
32
use TYPO3\CMS\Core\Page\PageRenderer;
33
use TYPO3\CMS\Core\Utility\GeneralUtility;
34
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
35
use TYPO3\CMS\Extbase\Mvc\Request;
36
use TYPO3\CMS\Extbase\Object\ObjectManager;
37
use TYPO3\CMS\Fluid\View\TemplateView;
38
39
/**
40
 * Backend Layout Renderer
41
 *
42
 * Draws a page layout - essentially, behaves as a wrapper for a view
43
 * which renders the Resources/Private/PageLayout/PageLayout template
44
 * with necessary assigned template variables.
45
 *
46
 * - Initializes the clipboard used in the page layout
47
 * - Inserts an encoded paste icon as JS which is made visible when clipboard elements are registered
48
 */
49
class BackendLayoutRenderer
50
{
51
    use LoggerAwareTrait;
52
53
    /**
54
     * @var IconFactory
55
     */
56
    protected $iconFactory;
57
58
    /**
59
     * @var BackendLayout
60
     */
61
    protected $backendLayout;
62
63
    /**
64
     * @var Clipboard
65
     */
66
    protected $clipboard;
67
68
    /**
69
     * @var TemplateView
70
     */
71
    protected $view;
72
73
    public function __construct(BackendLayout $backendLayout)
74
    {
75
        $this->backendLayout = $backendLayout;
76
        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
77
        $this->initializeClipboard();
78
        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
79
        $controllerContext = $objectManager->get(ControllerContext::class);
80
        $request = $objectManager->get(Request::class);
81
        $controllerContext->setRequest($request);
82
        $this->view = GeneralUtility::makeInstance(TemplateView::class);
83
        $this->view->getRenderingContext()->setControllerContext($controllerContext);
84
        $this->view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName('backend');
85
        $this->view->getRenderingContext()->setControllerName('PageLayout');
86
        $this->view->assign('backendLayout', $backendLayout);
87
    }
88
89
    /**
90
     * @param bool $renderUnused If true, renders the bottom column with unused records
91
     * @return string
92
     */
93
    public function drawContent(bool $renderUnused = true): string
94
    {
95
        $this->view->assign('hideRestrictedColumns', (bool)(BackendUtility::getPagesTSconfig($this->backendLayout->getDrawingConfiguration()->getPageId())['mod.']['web_layout.']['hideRestrictedCols'] ?? false));
96
        if (!$this->backendLayout->getDrawingConfiguration()->getLanguageMode()) {
97
            $this->view->assign('grid', $this->backendLayout->getGrid());
98
        }
99
        $this->view->assign('newContentTitle', $this->getLanguageService()->getLL('newContentElement'));
100
        $this->view->assign('newContentTitleShort', $this->getLanguageService()->getLL('content'));
101
102
        $rendered = $this->view->render('PageLayout');
103
        if ($renderUnused) {
104
            $unusedBackendLayout = clone $this->backendLayout;
105
            $unusedBackendLayout->getDrawingConfiguration()->setLanguageColumnsPointer($this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer());
106
            $unusedRecords = $this->backendLayout->getContentFetcher()->getUnusedRecords();
107
108
            if (!empty($unusedRecords)) {
109
                $unusedElementsMessage = GeneralUtility::makeInstance(
110
                    FlashMessage::class,
111
                    $this->getLanguageService()->getLL('staleUnusedElementsWarning'),
0 ignored issues
show
Bug introduced by
$this->getLanguageServic...UnusedElementsWarning') of type string is incompatible with the type array|array<mixed,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

111
                    /** @scrutinizer ignore-type */ $this->getLanguageService()->getLL('staleUnusedElementsWarning'),
Loading history...
112
                    $this->getLanguageService()->getLL('staleUnusedElementsWarningTitle'),
113
                    FlashMessage::WARNING
0 ignored issues
show
Bug introduced by
TYPO3\CMS\Core\Messaging\FlashMessage::WARNING of type integer is incompatible with the type array|array<mixed,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
                    /** @scrutinizer ignore-type */ FlashMessage::WARNING
Loading history...
114
                );
115
                $service = GeneralUtility::makeInstance(FlashMessageService::class);
116
                $queue = $service->getMessageQueueByIdentifier();
117
                $queue->addMessage($unusedElementsMessage);
118
119
                $unusedGrid = GeneralUtility::makeInstance(Grid::class, $unusedBackendLayout);
0 ignored issues
show
Bug introduced by
$unusedBackendLayout of type TYPO3\CMS\Backend\View\BackendLayout\BackendLayout is incompatible with the type array|array<mixed,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
                $unusedGrid = GeneralUtility::makeInstance(Grid::class, /** @scrutinizer ignore-type */ $unusedBackendLayout);
Loading history...
120
                $unusedRow = GeneralUtility::makeInstance(GridRow::class, $unusedBackendLayout);
121
                $unusedColumn = GeneralUtility::makeInstance(GridColumn::class, $unusedBackendLayout, ['colPos' => 99, 'name' => 'unused'], $unusedRecords);
122
123
                $unusedGrid->addRow($unusedRow);
124
                $unusedRow->addColumn($unusedColumn);
125
126
                $this->view->assign('unusedGrid', $unusedGrid);
127
                $rendered .= $this->view->render('UnusedRecords');
128
            }
129
        }
130
        return $rendered;
131
    }
132
133
    /**
134
     * Initializes the clipboard for generating paste links
135
     *
136
     * @see \TYPO3\CMS\Backend\Controller\ContextMenuController::clipboardAction()
137
     * @see \TYPO3\CMS\Filelist\Controller\FileListController::indexAction()
138
     */
139
    protected function initializeClipboard(): void
140
    {
141
        $this->clipboard = GeneralUtility::makeInstance(Clipboard::class);
142
        $this->clipboard->initializeClipboard();
143
        $this->clipboard->lockToNormal();
144
        $this->clipboard->cleanCurrent();
145
        $this->clipboard->endClipboard();
146
147
        $elFromTable = $this->clipboard->elFromTable('tt_content');
148
        if (!empty($elFromTable) && $this->backendLayout->getDrawingConfiguration()->isPageEditable()) {
149
            $pasteItem = (int)substr(key($elFromTable), 11);
150
            $pasteRecord = BackendUtility::getRecord('tt_content', (int)$pasteItem);
151
            $pasteTitle = (string)($pasteRecord['header'] ?: $pasteItem);
152
            $copyMode = $this->clipboard->clipData['normal']['mode'] ? '-' . $this->clipboard->clipData['normal']['mode'] : '';
153
            $addExtOnReadyCode = '
154
                     top.pasteIntoLinkTemplate = '
155
                . $this->drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-into', 'pasteIntoColumn')
156
                . ';
157
                    top.pasteAfterLinkTemplate = '
158
                . $this->drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-after', 'pasteAfterRecord')
159
                . ';';
160
        } else {
161
            $addExtOnReadyCode = '
162
                top.pasteIntoLinkTemplate = \'\';
163
                top.pasteAfterLinkTemplate = \'\';';
164
        }
165
        GeneralUtility::makeInstance(PageRenderer::class)->addJsInlineCode('pasteLinkTemplates', $addExtOnReadyCode);
166
    }
167
168
    /**
169
     * Draw a paste icon either for pasting into a column or for pasting after a record
170
     *
171
     * @param int $pasteItem ID of the item in the clipboard
172
     * @param string $pasteTitle Title for the JS modal
173
     * @param string $copyMode copy or cut
174
     * @param string $cssClass CSS class to determine if pasting is done into column or after record
175
     * @param string $title title attribute of the generated link
176
     *
177
     * @return string Generated HTML code with link and icon
178
     */
179
    private function drawPasteIcon(int $pasteItem, string $pasteTitle, string $copyMode, string $cssClass, string $title): string
180
    {
181
        $pasteIcon = json_encode(
182
            ' <a data-content="' . htmlspecialchars((string)$pasteItem) . '"'
183
            . ' data-title="' . htmlspecialchars($pasteTitle) . '"'
184
            . ' data-severity="warning"'
185
            . ' class="t3js-paste t3js-paste' . htmlspecialchars($copyMode) . ' ' . htmlspecialchars($cssClass) . ' btn btn-default btn-sm"'
186
            . ' title="' . htmlspecialchars($this->getLanguageService()->getLL($title)) . '">'
187
            . $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render()
188
            . '</a>'
189
        );
190
        return $pasteIcon;
191
    }
192
193
    protected function getBackendUser(): BackendUserAuthentication
194
    {
195
        return $GLOBALS['BE_USER'];
196
    }
197
198
    protected function getLanguageService(): LanguageService
199
    {
200
        return $GLOBALS['LANG'];
201
    }
202
}
203