Completed
Push — master ( cb9863...be434f )
by
unknown
40:07 queued 25:06
created

GridColumnItem   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 125
dl 0
loc 271
rs 4.5599
c 4
b 0
f 0
wmc 58

27 Methods

Rating   Name   Duplication   Size   Complexity  
B isDisabled() 0 8 7
A getRecord() 0 3 1
A setRecord() 0 3 1
A getColumn() 0 3 1
A isDeletePlaceholder() 0 3 1
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 getDeleteCancelText() 0 3 1
A getVisibilityToggleTitle() 0 4 2
A getDeleteUrl() 0 4 1
A getWrapperClassName() 0 10 3
A getDeleteTitle() 0 3 1
A isEditable() 0 10 5
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 29 6
A getFooterInfo() 0 10 1
A getNewContentAfterUrl() 0 14 1
A isVisibilityToggling() 0 7 4
A isVersioned() 0 3 1

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
use TYPO3\CMS\Core\Versioning\VersionState;
29
30
/**
31
 * Grid Column Item
32
 *
33
 * Model/proxy around a single record which appears in a grid column
34
 * in the page layout. Returns titles, urls etc. and performs basic
35
 * assertions on the contained content element record such as
36
 * is-versioned, is-editable, is-delible and so on.
37
 *
38
 * Accessed from Fluid templates.
39
 */
40
class GridColumnItem extends AbstractGridObject
41
{
42
    /**
43
     * @var mixed[]
44
     */
45
    protected $record = [];
46
47
    /**
48
     * @var GridColumn
49
     */
50
    protected $column;
51
52
    public function __construct(PageLayoutContext $context, GridColumn $column, array $record)
53
    {
54
        parent::__construct($context);
55
        $this->column = $column;
56
        $this->record = $record;
57
    }
58
59
    public function isVersioned(): bool
60
    {
61
        return $this->record['_ORIG_uid'] > 0;
62
    }
63
64
    public function getPreview(): string
65
    {
66
        $record = $this->getRecord();
67
        $previewRenderer = GeneralUtility::makeInstance(StandardPreviewRendererResolver::class)
68
            ->resolveRendererFor(
69
                'tt_content',
70
                $record,
71
                $this->context->getPageId()
72
            );
73
        $previewHeader = $previewRenderer->renderPageModulePreviewHeader($this);
74
        $previewContent = $previewRenderer->renderPageModulePreviewContent($this);
75
        return $previewRenderer->wrapPageModulePreview($previewHeader, $previewContent, $this);
76
    }
77
78
    public function getWrapperClassName(): string
79
    {
80
        $wrapperClassNames = [];
81
        if ($this->isDisabled()) {
82
            $wrapperClassNames[] = 't3-page-ce-hidden t3js-hidden-record';
83
        } elseif (!in_array($this->record['colPos'], $this->context->getBackendLayout()->getColumnPositionNumbers())) {
84
            $wrapperClassNames[] = 't3-page-ce-warning';
85
        }
86
87
        return implode(' ', $wrapperClassNames);
88
    }
89
90
    public function isDelible(): bool
91
    {
92
        $backendUser = $this->getBackendUser();
93
        if (!$backendUser->doesUserHaveAccess($this->context->getPageRecord(), Permission::CONTENT_EDIT)) {
94
            return false;
95
        }
96
        return !(bool)($backendUser->getTSConfig()['options.']['disableDelete.']['tt_content'] ?? $backendUser->getTSConfig()['options.']['disableDelete'] ?? false);
97
    }
98
99
    public function getDeleteUrl(): string
100
    {
101
        $params = '&cmd[tt_content][' . $this->record['uid'] . '][delete]=1';
102
        return BackendUtility::getLinkToDataHandlerAction($params);
103
    }
104
105
    public function getDeleteTitle(): string
106
    {
107
        return $this->getLanguageService()->getLL('deleteItem');
108
    }
109
110
    public function getDeleteConfirmText(): string
111
    {
112
        return $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:label.confirm.delete_record.title');
113
    }
114
115
    public function getDeleteCancelText(): string
116
    {
117
        return $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel');
118
    }
119
120
    public function getFooterInfo(): string
121
    {
122
        $record = $this->getRecord();
123
        $previewRenderer = GeneralUtility::makeInstance(StandardPreviewRendererResolver::class)
124
            ->resolveRendererFor(
125
                'tt_content',
126
                $record,
127
                $this->context->getPageId()
128
            );
129
        return $previewRenderer->renderPageModulePreviewFooter($this);
130
    }
131
132
    /**
133
     * Renders the language flag and language title, but only if an icon is given, otherwise just the language
134
     *
135
     * @param SiteLanguage $language
136
     * @return string
137
     */
138
    protected function renderLanguageFlag(SiteLanguage $language)
139
    {
140
        $title = htmlspecialchars($language->getTitle());
141
        if ($language->getFlagIdentifier()) {
142
            $icon = $this->iconFactory->getIcon(
143
                $language->getFlagIdentifier(),
144
                Icon::SIZE_SMALL
145
            )->render();
146
            return '<span title="' . $title . '" class="t3js-flag">' . $icon . '</span>&nbsp;<span class="t3js-language-title">' . $title . '</span>';
147
        }
148
        return $title;
149
    }
150
151
    public function getIcons(): string
152
    {
153
        $table = 'tt_content';
154
        $row = $this->record;
155
        $icons = [];
156
157
        $toolTip = BackendUtility::getRecordToolTip($row, $table);
158
        $icon = '<span ' . $toolTip . '>' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
159
        if ($this->getBackendUser()->recordEditAccessInternals($table, $row)) {
160
            $icon = BackendUtility::wrapClickMenuOnIcon($icon, $table, $row['uid']);
161
        }
162
        $icons[] = $icon;
163
        if ($row['sys_language_uid'] >= 0) {
164
            $siteLanguage = $this->context->getSiteLanguage();
165
            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...
166
                $icons[] = $this->renderLanguageFlag($siteLanguage);
167
            }
168
        }
169
170
        if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) {
171
            $icons[] = '<a href="#" data-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">'
172
                . $this->iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</a>';
173
        }
174
175
        $_params = ['tt_content', $row['uid'], &$row];
176
        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] ?? [] as $_funcRef) {
177
            $icons[] = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
178
        }
179
        return implode(' ', $icons);
180
    }
181
182
    public function getRecord(): array
183
    {
184
        return $this->record;
185
    }
186
187
    public function setRecord(array $record): void
188
    {
189
        $this->record = $record;
190
    }
191
192
    public function getColumn(): GridColumn
193
    {
194
        return $this->column;
195
    }
196
197
    public function isDisabled(): bool
198
    {
199
        $table = 'tt_content';
200
        $row = $this->getRecord();
201
        $enableCols = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
202
        return $enableCols['disabled'] && $row[$enableCols['disabled']]
203
            || $enableCols['starttime'] && $row[$enableCols['starttime']] > $GLOBALS['EXEC_TIME']
204
            || $enableCols['endtime'] && $row[$enableCols['endtime']] && $row[$enableCols['endtime']] < $GLOBALS['EXEC_TIME'];
205
    }
206
207
    public function isDeletePlaceholder(): bool
208
    {
209
        return VersionState::cast($this->record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER);
210
    }
211
212
    public function isEditable(): bool
213
    {
214
        $languageId = $this->context->getSiteLanguage()->getLanguageId();
215
        if ($this->getBackendUser()->isAdmin()) {
216
            return true;
217
        }
218
        $pageRecord = $this->context->getPageRecord();
219
        return !$pageRecord['editlock']
220
            && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT)
221
            && ($languageId === null || $this->getBackendUser()->checkLanguageAccess($languageId));
222
    }
223
224
    public function isDragAndDropAllowed(): bool
225
    {
226
        $pageRecord = $this->context->getPageRecord();
227
        return (int)$this->record['l18n_parent'] === 0 &&
228
            (
229
                $this->getBackendUser()->isAdmin()
230
                || ((int)$this->record['editlock'] === 0 && (int)$pageRecord['editlock'] === 0)
231
                && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT)
232
                && $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $this->record['CType'], $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
233
            )
234
        ;
0 ignored issues
show
Coding Style introduced by
Space found before semicolon; expected ");" but found ")
;"
Loading history...
235
    }
236
237
    public function getNewContentAfterLinkTitle(): string
238
    {
239
        return $this->getLanguageService()->getLL('newContentElement');
240
    }
241
242
    public function getNewContentAfterTitle(): string
243
    {
244
        return $this->getLanguageService()->getLL('content');
245
    }
246
247
    public function getNewContentAfterUrl(): string
248
    {
249
        $pageId = $this->context->getPageId();
250
        $urlParameters = [
251
            'id' => $pageId,
252
            'sys_language_uid' => $this->context->getSiteLanguage()->getLanguageId(),
253
            'colPos' => $this->column->getColumnNumber(),
254
            'uid_pid' => -$this->record['uid'],
255
            'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
256
        ];
257
        $routeName = BackendUtility::getPagesTSconfig($pageId)['mod.']['newContentElementWizard.']['override']
258
            ?? 'new_content_element_wizard';
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "??"; newline found
Loading history...
259
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
260
        return (string)$uriBuilder->buildUriFromRoute($routeName, $urlParameters);
261
    }
262
263
    public function getVisibilityToggleUrl(): string
264
    {
265
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
266
        if ($this->record[$hiddenField]) {
267
            $value = 0;
268
        } else {
269
            $value = 1;
270
        }
271
        $params = '&data[tt_content][' . ($this->record['_ORIG_uid'] ?: $this->record['uid'])
272
            . '][' . $hiddenField . ']=' . $value;
273
        return BackendUtility::getLinkToDataHandlerAction($params) . '#element-tt_content-' . $this->record['uid'];
274
    }
275
276
    public function getVisibilityToggleTitle(): string
277
    {
278
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
279
        return $this->getLanguageService()->getLL($this->record[$hiddenField] ? 'unhide' : 'hide');
280
    }
281
282
    public function getVisibilityToggleIconName(): string
283
    {
284
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
285
        return $this->record[$hiddenField] ? 'unhide' : 'hide';
286
    }
287
288
    public function isVisibilityToggling(): bool
289
    {
290
        $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
291
        return $hiddenField && $GLOBALS['TCA']['tt_content']['columns'][$hiddenField]
292
            && (
293
                !$GLOBALS['TCA']['tt_content']['columns'][$hiddenField]['exclude']
294
                || $this->getBackendUser()->check('non_exclude_fields', 'tt_content:' . $hiddenField)
295
            )
296
        ;
0 ignored issues
show
Coding Style introduced by
Space found before semicolon; expected ");" but found ")
;"
Loading history...
297
    }
298
299
    public function getEditUrl(): string
300
    {
301
        $urlParameters = [
302
            'edit' => [
303
                'tt_content' => [
304
                    $this->record['uid'] => 'edit',
305
                ]
306
            ],
307
            'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $this->record['uid'],
308
        ];
309
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
310
        return (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters) . '#element-tt_content-' . $this->record['uid'];
311
    }
312
}
313