Passed
Push — master ( 202801...6ecbcd )
by
unknown
31:41 queued 13:20
created

GridColumnItem   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 294
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 59
eloc 135
dl 0
loc 294
rs 4.08
c 1
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
B isDisabled() 0 8 7
A getVisibilityToggleUrl() 0 11 3
A getNewContentAfterTitle() 0 3 1
A getVisibilityToggleIconName() 0 4 2
A getNewContentAfterLinkTitle() 0 3 1
A getEditUrl() 0 12 1
A getPreview() 0 12 1
A addTranslation() 0 4 1
A getRecord() 0 3 1
A getDeleteCancelText() 0 3 1
A getVisibilityToggleTitle() 0 4 2
A getDeleteUrl() 0 4 1
A getWrapperClassName() 0 10 3
A getTranslations() 0 3 1
A getDeleteTitle() 0 3 1
A setRecord() 0 3 1
A isEditable() 0 10 4
A getColumn() 0 3 1
A isDragAndDropAllowed() 0 9 6
A getDeleteConfirmText() 0 3 1
A isDelible() 0 7 2
A __construct() 0 5 1
A renderLanguageFlag() 0 11 2
A getIcons() 0 27 5
A getFooterInfo() 0 10 1
A getNewContentAfterUrl() 0 28 2
A isVisibilityToggling() 0 7 4
A isVersioned() 0 3 2

How to fix   Complexity   

Complex Class

Complex classes like GridColumnItem often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GridColumnItem, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace TYPO3\CMS\Backend\View\BackendLayout\Grid;
19
20
use TYPO3\CMS\Backend\Preview\StandardPreviewRendererResolver;
21
use TYPO3\CMS\Backend\Routing\UriBuilder;
22
use TYPO3\CMS\Backend\Utility\BackendUtility;
23
use TYPO3\CMS\Backend\View\PageLayoutContext;
24
use TYPO3\CMS\Core\Imaging\Icon;
25
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
26
use TYPO3\CMS\Core\Type\Bitmask\Permission;
27
use TYPO3\CMS\Core\Utility\GeneralUtility;
28
29
/**
30
 * Grid Column Item
31
 *
32
 * Model/proxy around a single record which appears in a grid column
33
 * in the page layout. Returns titles, urls etc. and performs basic
34
 * assertions on the contained content element record such as
35
 * is-versioned, is-editable, is-delible and so on.
36
 *
37
 * Accessed from Fluid templates.
38
 *
39
 * @internal this is experimental and subject to change in TYPO3 v10 / v11
40
 */
41
class GridColumnItem extends AbstractGridObject
42
{
43
    /**
44
     * @var mixed[]
45
     */
46
    protected $record = [];
47
48
    /**
49
     * @var GridColumn
50
     */
51
    protected $column;
52
53
    /**
54
     * @var GridColumnItem[]
55
     */
56
    protected $translations = [];
57
58
    public function __construct(PageLayoutContext $context, GridColumn $column, array $record)
59
    {
60
        parent::__construct($context);
61
        $this->column = $column;
62
        $this->record = $record;
63
    }
64
65
    public function isVersioned(): bool
66
    {
67
        return $this->record['_ORIG_uid'] > 0 || (int)$this->record['t3ver_state'] !== 0;
68
    }
69
70
    public function getPreview(): string
71
    {
72
        $record = $this->getRecord();
73
        $previewRenderer = GeneralUtility::makeInstance(StandardPreviewRendererResolver::class)
74
            ->resolveRendererFor(
75
                'tt_content',
76
                $record,
77
                $this->context->getPageId()
78
            );
79
        $previewHeader = $previewRenderer->renderPageModulePreviewHeader($this);
80
        $previewContent = $previewRenderer->renderPageModulePreviewContent($this);
81
        return $previewRenderer->wrapPageModulePreview($previewHeader, $previewContent, $this);
82
    }
83
84
    public function getWrapperClassName(): string
85
    {
86
        $wrapperClassNames = [];
87
        if ($this->isDisabled()) {
88
            $wrapperClassNames[] = 't3-page-ce-hidden t3js-hidden-record';
89
        } elseif (!in_array($this->record['colPos'], $this->context->getBackendLayout()->getColumnPositionNumbers())) {
90
            $wrapperClassNames[] = 't3-page-ce-warning';
91
        }
92
93
        return implode(' ', $wrapperClassNames);
94
    }
95
96
    public function isDelible(): bool
97
    {
98
        $backendUser = $this->getBackendUser();
99
        if (!$backendUser->doesUserHaveAccess($this->context->getPageRecord(), Permission::CONTENT_EDIT)) {
100
            return false;
101
        }
102
        return !(bool)($backendUser->getTSConfig()['options.']['disableDelete.']['tt_content'] ?? $backendUser->getTSConfig()['options.']['disableDelete'] ?? false);
103
    }
104
105
    public function getDeleteUrl(): string
106
    {
107
        $params = '&cmd[tt_content][' . $this->record['uid'] . '][delete]=1';
108
        return BackendUtility::getLinkToDataHandlerAction($params);
109
    }
110
111
    public function getDeleteTitle(): string
112
    {
113
        return $this->getLanguageService()->getLL('deleteItem');
114
    }
115
116
    public function getDeleteConfirmText(): string
117
    {
118
        return $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:label.confirm.delete_record.title');
119
    }
120
121
    public function getDeleteCancelText(): string
122
    {
123
        return $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel');
124
    }
125
126
    public function getFooterInfo(): string
127
    {
128
        $record = $this->getRecord();
129
        $previewRenderer = GeneralUtility::makeInstance(StandardPreviewRendererResolver::class)
130
            ->resolveRendererFor(
131
                'tt_content',
132
                $record,
133
                $this->context->getPageId()
134
            );
135
        return $previewRenderer->renderPageModulePreviewFooter($this);
136
    }
137
138
    /**
139
     * Renders the language flag and language title, but only if an icon is given, otherwise just the language
140
     *
141
     * @param SiteLanguage $language
142
     * @return string
143
     */
144
    protected function renderLanguageFlag(SiteLanguage $language)
145
    {
146
        $title = htmlspecialchars($language->getTitle());
147
        if ($language->getFlagIdentifier()) {
148
            $icon = $this->iconFactory->getIcon(
149
                $language->getFlagIdentifier(),
150
                Icon::SIZE_SMALL
151
            )->render();
152
            return '<span title="' . $title . '" class="t3js-flag">' . $icon . '</span>&nbsp;<span class="t3js-language-title">' . $title . '</span>';
153
        }
154
        return $title;
155
    }
156
157
    public function getIcons(): string
158
    {
159
        $table = 'tt_content';
160
        $row = $this->record;
161
        $icons = [];
162
163
        $toolTip = BackendUtility::getRecordToolTip($row, $table);
164
        $icon = '<span ' . $toolTip . '>' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
165
        if ($this->getBackendUser()->recordEditAccessInternals($table, $row)) {
166
            $icon = BackendUtility::wrapClickMenuOnIcon($icon, $table, $row['uid']);
167
        }
168
        $icons[] = $icon;
169
        $siteLanguage = $this->context->getSiteLanguage((int)$row['sys_language_uid']);
170
        if ($siteLanguage instanceof SiteLanguage) {
0 ignored issues
show
introduced by
$siteLanguage is always a sub-type of TYPO3\CMS\Core\Site\Entity\SiteLanguage.
Loading history...
171
            $icons[] = $this->renderLanguageFlag($siteLanguage);
172
        }
173
174
        if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) {
175
            $icons[] = '<a href="#" data-bs-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">'
176
                . $this->iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</a>';
177
        }
178
179
        $_params = ['tt_content', $row['uid'], &$row];
180
        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] ?? [] as $_funcRef) {
181
            $icons[] = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
182
        }
183
        return implode(' ', $icons);
184
    }
185
186
    public function getRecord(): array
187
    {
188
        return $this->record;
189
    }
190
191
    public function setRecord(array $record): void
192
    {
193
        $this->record = $record;
194
    }
195
196
    public function getColumn(): GridColumn
197
    {
198
        return $this->column;
199
    }
200
201
    public function getTranslations(): array
202
    {
203
        return $this->translations;
204
    }
205
206
    public function addTranslation(int $languageId, GridColumnItem $translation): GridColumnItem
207
    {
208
        $this->translations[$languageId] = $translation;
209
        return $this;
210
    }
211
212
    public function isDisabled(): bool
213
    {
214
        $table = 'tt_content';
215
        $row = $this->getRecord();
216
        $enableCols = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
217
        return $enableCols['disabled'] && $row[$enableCols['disabled']]
218
            || $enableCols['starttime'] && $row[$enableCols['starttime']] > $GLOBALS['EXEC_TIME']
219
            || $enableCols['endtime'] && $row[$enableCols['endtime']] && $row[$enableCols['endtime']] < $GLOBALS['EXEC_TIME'];
220
    }
221
222
    public function isEditable(): bool
223
    {
224
        $backendUser = $this->getBackendUser();
225
        if ($backendUser->isAdmin()) {
226
            return true;
227
        }
228
        $pageRecord = $this->context->getPageRecord();
229
        return !(bool)($pageRecord['editlock'] ?? false)
230
            && $backendUser->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT)
231
            && $backendUser->recordEditAccessInternals('tt_content', $this->record);
232
    }
233
234
    public function isDragAndDropAllowed(): bool
235
    {
236
        $pageRecord = $this->context->getPageRecord();
237
        return (int)$this->record['l18n_parent'] === 0 &&
238
            (
239
                $this->getBackendUser()->isAdmin()
240
                || ((int)$this->record['editlock'] === 0 && (int)$pageRecord['editlock'] === 0)
241
                && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT)
242
                && $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $this->record['CType'], $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
243
            )
244
        ;
245
    }
246
247
    public function getNewContentAfterLinkTitle(): string
248
    {
249
        return $this->getLanguageService()->getLL('newContentElement');
250
    }
251
252
    public function getNewContentAfterTitle(): string
253
    {
254
        return $this->getLanguageService()->getLL('content');
255
    }
256
257
    public function getNewContentAfterUrl(): string
258
    {
259
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
260
        $pageId = $this->context->getPageId();
261
262
        if ($this->context->getDrawingConfiguration()->getShowNewContentWizard()) {
263
            $urlParameters = [
264
                'id' => $pageId,
265
                'sys_language_uid' => $this->context->getSiteLanguage()->getLanguageId(),
266
                'colPos' => $this->column->getColumnNumber(),
267
                'uid_pid' => -$this->record['uid'],
268
                'returnUrl' => $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams')->getRequestUri()
269
            ];
270
            $routeName = BackendUtility::getPagesTSconfig($pageId)['mod.']['newContentElementWizard.']['override']
271
                ?? 'new_content_element_wizard';
272
        } else {
273
            $urlParameters = [
274
                'edit' => [
275
                    'tt_content' => [
276
                        -$this->record['uid'] => 'new'
277
                    ]
278
                ],
279
                'returnUrl' => $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams')->getRequestUri()
280
            ];
281
            $routeName = 'record_edit';
282
        }
283
284
        return (string)$uriBuilder->buildUriFromRoute($routeName, $urlParameters);
285
    }
286
287
    public function getVisibilityToggleUrl(): string
288
    {
289
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
290
        if ($this->record[$hiddenField]) {
291
            $value = 0;
292
        } else {
293
            $value = 1;
294
        }
295
        $params = '&data[tt_content][' . ($this->record['_ORIG_uid'] ?: $this->record['uid'])
296
            . '][' . $hiddenField . ']=' . $value;
297
        return BackendUtility::getLinkToDataHandlerAction($params) . '#element-tt_content-' . $this->record['uid'];
298
    }
299
300
    public function getVisibilityToggleTitle(): string
301
    {
302
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
303
        return $this->getLanguageService()->getLL($this->record[$hiddenField] ? 'unhide' : 'hide');
304
    }
305
306
    public function getVisibilityToggleIconName(): string
307
    {
308
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
309
        return $this->record[$hiddenField] ? 'unhide' : 'hide';
310
    }
311
312
    public function isVisibilityToggling(): bool
313
    {
314
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
315
        return $hiddenField && $GLOBALS['TCA']['tt_content']['columns'][$hiddenField]
316
            && (
317
                !$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]['exclude']
318
                || $this->getBackendUser()->check('non_exclude_fields', 'tt_content:' . $hiddenField)
319
            )
320
        ;
321
    }
322
323
    public function getEditUrl(): string
324
    {
325
        $urlParameters = [
326
            'edit' => [
327
                'tt_content' => [
328
                    $this->record['uid'] => 'edit',
329
                ]
330
            ],
331
            'returnUrl' => $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams')->getRequestUri() . '#element-tt_content-' . $this->record['uid'],
332
        ];
333
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
334
        return (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters) . '#element-tt_content-' . $this->record['uid'];
335
    }
336
}
337