Passed
Push — master ( d5a28b...d12ca0 )
by
unknown
17:01
created

RecyclerModuleController   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 19
eloc 80
dl 0
loc 221
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getLanguageService() 0 3 1
A getShortcutTitle() 0 7 1
A initializeView() 0 8 1
A getDataFromSession() 0 9 3
A getJavaScriptConfiguration() 0 11 1
A registerDocheaderButtons() 0 16 1
A __construct() 0 8 1
A indexAction() 0 9 2
A getBackendUser() 0 3 1
B handleRequest() 0 37 7
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Recycler\Controller;
17
18
use Psr\Http\Message\ResponseInterface;
19
use Psr\Http\Message\ServerRequestInterface;
20
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
21
use TYPO3\CMS\Backend\Template\ModuleTemplate;
22
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
23
use TYPO3\CMS\Backend\Utility\BackendUtility;
24
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
25
use TYPO3\CMS\Core\Http\HtmlResponse;
26
use TYPO3\CMS\Core\Http\NormalizedParams;
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\Page\PageRenderer;
31
use TYPO3\CMS\Core\Type\Bitmask\Permission;
32
use TYPO3\CMS\Core\Utility\GeneralUtility;
33
use TYPO3\CMS\Core\Utility\MathUtility;
34
use TYPO3\CMS\Fluid\View\StandaloneView;
35
36
/**
37
 * Backend Module for the 'recycler' extension.
38
 * @internal This class is a specific Backend controller implementation and is not considered part of the Public TYPO3 API.
39
 */
40
class RecyclerModuleController
41
{
42
43
    /**
44
     * @var array
45
     */
46
    protected $pageRecord = [];
47
48
    /**
49
     * @var bool
50
     */
51
    protected $isAccessibleForCurrentUser = false;
52
53
    /**
54
     * @var bool
55
     */
56
    protected $allowDelete = false;
57
58
    /**
59
     * @var int
60
     */
61
    protected $recordsPageLimit = 50;
62
63
    /**
64
     * @var int
65
     */
66
    protected $id;
67
68
    /**
69
     * @var StandaloneView
70
     */
71
    protected $view;
72
73
    /**
74
     * @var ModuleTemplate
75
     */
76
    protected $moduleTemplate;
77
78
    protected IconFactory $iconFactory;
79
    protected PageRenderer $pageRenderer;
80
    protected ModuleTemplateFactory $moduleTemplateFactory;
81
82
    public function __construct(
83
        IconFactory $iconFactory,
84
        PageRenderer $pageRenderer,
85
        ModuleTemplateFactory $moduleTemplateFactory
86
    ) {
87
        $this->iconFactory = $iconFactory;
88
        $this->pageRenderer = $pageRenderer;
89
        $this->moduleTemplateFactory = $moduleTemplateFactory;
90
    }
91
92
    /**
93
     * Injects the request object for the current request, and renders correct action
94
     *
95
     * @param ServerRequestInterface $request the current request
96
     * @return ResponseInterface the response with the content
97
     */
98
    public function handleRequest(ServerRequestInterface $request): ResponseInterface
99
    {
100
        $this->id = (int)($request->getQueryParams()['id'] ?? $request->getParsedBody()['id'] ?? 0);
101
        $backendUser = $this->getBackendUser();
102
        $this->pageRecord = BackendUtility::readPageAccess($this->id, $backendUser->getPagePermsClause(Permission::PAGE_SHOW));
0 ignored issues
show
Documentation Bug introduced by
It seems like TYPO3\CMS\Backend\Utilit...Permission::PAGE_SHOW)) can also be of type false. However, the property $pageRecord is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
103
        $this->isAccessibleForCurrentUser = $this->id && is_array($this->pageRecord) || !$this->id && $this->getBackendUser()->isAdmin();
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: $this->isAccessibleForCu...ckendUser()->isAdmin()), Probably Intended Meaning: $this->isAccessibleForCu...ckendUser()->isAdmin())
Loading history...
104
        $this->moduleTemplate = $this->moduleTemplateFactory->create($request);
105
106
        // don't access in workspace
107
        if ($backendUser->workspace !== 0) {
108
            $this->isAccessibleForCurrentUser = false;
109
        }
110
111
        // read configuration
112
        if ($backendUser->isAdmin()) {
113
            $this->allowDelete = true;
114
        } else {
115
            $this->allowDelete = (bool)($backendUser->getTSConfig()['mod.']['recycler.']['allowDelete'] ?? false);
116
        }
117
118
        $this->recordsPageLimit = MathUtility::forceIntegerInRange(
119
            (int)($backendUser->getTSConfig()['mod.']['recycler.']['recordsPageLimit'] ?? 25),
120
            1
121
        );
122
123
        $action = 'index';
124
        $this->initializeView($action);
125
126
        $result = call_user_func_array([$this, $action . 'Action'], [$request]);
127
        if ($result instanceof ResponseInterface) {
128
            return $result;
129
        }
130
131
        $this->registerDocheaderButtons($request->getQueryParams()['route']);
132
133
        $this->moduleTemplate->setContent($this->view->render());
134
        return new HtmlResponse($this->moduleTemplate->renderContent());
135
    }
136
137
    /**
138
     * @param string $templateName
139
     */
140
    protected function initializeView(string $templateName)
141
    {
142
        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
143
        $this->view->setTemplate($templateName);
144
        $this->view->setTemplateRootPaths(['EXT:recycler/Resources/Private/Templates/RecyclerModule']);
145
        $this->view->setPartialRootPaths(['EXT:recycler/Resources/Private/Partials']);
146
        $this->view->setLayoutRootPaths(['EXT:recycler/Resources/Private/Layouts']);
147
        $this->view->getRequest()->setControllerExtensionName('Recycler');
148
    }
149
150
    /**
151
     * Renders the content of the module.
152
     *
153
     * @param ServerRequestInterface $request
154
     */
155
    public function indexAction(ServerRequestInterface $request)
156
    {
157
        $this->pageRenderer->addInlineSettingArray('Recycler', $this->getJavaScriptConfiguration($request->getAttribute('normalizedParams')));
158
        $this->pageRenderer->addInlineLanguageLabelFile('EXT:recycler/Resources/Private/Language/locallang.xlf');
159
        if ($this->isAccessibleForCurrentUser) {
160
            $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageRecord);
161
        }
162
163
        $this->view->assign('allowDelete', $this->allowDelete);
164
    }
165
166
    /**
167
     * Registers the Icons into the docheader
168
     *
169
     * @param string $route
170
     * @throws \InvalidArgumentException
171
     */
172
    protected function registerDocheaderButtons(string $route)
173
    {
174
        $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
175
176
        $shortcutButton = $buttonBar->makeShortcutButton()
177
            ->setRouteIdentifier('web_RecyclerRecycler')
178
            ->setDisplayName($this->getShortcutTitle())
179
            ->setArguments(['id' => (int)$this->id]);
180
        $buttonBar->addButton($shortcutButton);
181
182
        $reloadButton = $buttonBar->makeLinkButton()
183
            ->setHref('#')
184
            ->setDataAttributes(['action' => 'reload'])
185
            ->setTitle($this->getLanguageService()->sL('LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:button.reload'))
186
            ->setIcon($this->iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
187
        $buttonBar->addButton($reloadButton, ButtonBar::BUTTON_POSITION_RIGHT);
188
    }
189
190
    /**
191
     * Gets the JavaScript configuration.
192
     *
193
     * @param NormalizedParams $normalizedParams
194
     * @return array The JavaScript configuration
195
     */
196
    protected function getJavaScriptConfiguration(NormalizedParams $normalizedParams): array
197
    {
198
        return [
199
            'pagingSize' => $this->recordsPageLimit,
200
            'showDepthMenu' => true,
201
            'startUid' => $this->id,
202
            'isSSL' => $normalizedParams->isHttps(),
203
            'deleteDisable' => !$this->allowDelete,
204
            'depthSelection' => $this->getDataFromSession('depthSelection', '0'),
205
            'tableSelection' => $this->getDataFromSession('tableSelection', ''),
206
            'States' => $this->getBackendUser()->uc['moduleData']['web_recycler']['States']
207
        ];
208
    }
209
210
    /**
211
     * Gets data from the session of the current backend user.
212
     *
213
     * @param string $identifier The identifier to be used to get the data
214
     * @param string $default The default date to be used if nothing was found in the session
215
     * @return string The accordant data in the session of the current backend user
216
     */
217
    protected function getDataFromSession($identifier, $default = null)
218
    {
219
        $sessionData = &$this->getBackendUser()->uc['tx_recycler'];
220
        if (isset($sessionData[$identifier]) && $sessionData[$identifier]) {
221
            $data = $sessionData[$identifier];
222
        } else {
223
            $data = $default;
224
        }
225
        return $data;
226
    }
227
228
    /**
229
     * Returns the shortcut title for the current page
230
     *
231
     * @return string
232
     */
233
    protected function getShortcutTitle(): string
234
    {
235
        return sprintf(
236
            '%s: %s [%d]',
237
            $this->getLanguageService()->sL('LLL:EXT:recycler/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'),
238
            BackendUtility::getRecordTitle('pages', $this->pageRecord),
239
            $this->id
240
        );
241
    }
242
243
    /**
244
     * Returns the current BE user.
245
     *
246
     * @return BackendUserAuthentication
247
     */
248
    protected function getBackendUser(): BackendUserAuthentication
249
    {
250
        return $GLOBALS['BE_USER'];
251
    }
252
253
    /**
254
     * Returns an instance of LanguageService
255
     *
256
     * @return LanguageService
257
     */
258
    protected function getLanguageService(): LanguageService
259
    {
260
        return $GLOBALS['LANG'];
261
    }
262
}
263