Passed
Push — master ( 0de5ac...6d956e )
by
unknown
27:41 queued 14:26
created

PermissionController::addFlashMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 3
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\Beuser\Controller;
19
20
use Psr\Http\Message\ResponseFactoryInterface;
21
use Psr\Http\Message\ResponseInterface;
22
use Psr\Http\Message\ServerRequestInterface;
23
use TYPO3\CMS\Backend\Routing\UriBuilder;
24
use TYPO3\CMS\Backend\Template\ModuleTemplate;
25
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
26
use TYPO3\CMS\Backend\Tree\View\PageTreeView;
27
use TYPO3\CMS\Backend\Utility\BackendUtility;
28
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
29
use TYPO3\CMS\Core\DataHandling\DataHandler;
30
use TYPO3\CMS\Core\Imaging\Icon;
31
use TYPO3\CMS\Core\Imaging\IconFactory;
32
use TYPO3\CMS\Core\Localization\LanguageService;
33
use TYPO3\CMS\Core\Messaging\FlashMessage;
34
use TYPO3\CMS\Core\Messaging\FlashMessageService;
35
use TYPO3\CMS\Core\Page\PageRenderer;
36
use TYPO3\CMS\Core\Utility\GeneralUtility;
37
use TYPO3\CMS\Fluid\View\StandaloneView;
38
use TYPO3Fluid\Fluid\View\ViewInterface;
39
40
/**
41
 * Backend module page permissions.
42
 * Also includes the ajax endpoint for convenient methods for editing
43
 * of page permissions (including page ownership (user and group)).
44
 *
45
 * @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
46
 */
47
class PermissionController
48
{
49
    private const SESSION_PREFIX = 'tx_Beuser_';
50
    private const ALLOWED_ACTIONS = ['index', 'edit', 'update'];
51
    private const DEPTH_LEVELS = [1, 2, 3, 4, 10];
52
    private const RECURSIVE_LEVELS = 10;
53
54
    protected int $id = 0;
55
    protected string $returnUrl = '';
56
    protected int $depth;
57
    protected array $pageInfo = [];
58
59
    protected ModuleTemplateFactory $moduleTemplateFactory;
60
    protected PageRenderer $pageRenderer;
61
    protected IconFactory $iconFactory;
62
    protected UriBuilder $uriBuilder;
63
    protected ResponseFactoryInterface $responseFactory;
64
65
    protected ?ModuleTemplate $moduleTemplate = null;
66
    protected ?ViewInterface $view = null;
67
68
    public function __construct(
69
        ModuleTemplateFactory $moduleTemplateFactory,
70
        PageRenderer $pageRenderer,
71
        IconFactory $iconFactory,
72
        UriBuilder $uriBuilder,
73
        ResponseFactoryInterface $responseFactory
74
    ) {
75
        $this->moduleTemplateFactory = $moduleTemplateFactory;
76
        $this->pageRenderer = $pageRenderer;
77
        $this->iconFactory = $iconFactory;
78
        $this->uriBuilder = $uriBuilder;
79
        $this->responseFactory = $responseFactory;
80
    }
81
82
    public function handleRequest(ServerRequestInterface $request): ResponseInterface
83
    {
84
        $parsedBody = $request->getParsedBody();
85
        $queryParams = $request->getQueryParams();
86
        $backendUser = $this->getBackendUser();
87
        $lang = $this->getLanguageService();
88
89
        $this->moduleTemplate = $this->moduleTemplateFactory->create($request);
90
91
        // determine depth parameter
92
        $this->depth = (int)($parsedBody['depth'] ?? $queryParams['depth'] ?? 0);
93
        if (!$this->depth) {
94
            $this->depth = (int)$backendUser->getSessionData(self::SESSION_PREFIX . 'depth');
95
        } else {
96
            $backendUser->setAndSaveSessionData(self::SESSION_PREFIX . 'depth', $this->depth);
97
        }
98
99
        // determine id parameter
100
        $this->id = (int)($parsedBody['id'] ?? $queryParams['id'] ?? 0);
101
        $pageRecord = BackendUtility::getRecord('pages', $this->id);
102
        // Check if a page with the given id exists, otherwise fall back
103
        if ($pageRecord === null) {
104
            $this->id = 0;
105
        }
106
107
        $this->returnUrl = GeneralUtility::sanitizeLocalUrl((string)($parsedBody['returnUrl'] ?? $queryParams['returnUrl'] ?? ''));
108
        $this->pageInfo = BackendUtility::readPageAccess($this->id, ' 1=1') ?: [
109
            'title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'],
110
            'uid' => 0,
111
            'pid' => 0
112
        ];
113
114
        $action = (string)($parsedBody['action'] ?? $queryParams['action'] ?? 'index');
115
        if (!in_array($action, self::ALLOWED_ACTIONS, true)) {
116
            return $this->htmlResponse('Action not allowed', 400);
117
        }
118
119
        if ($action !== 'update') {
120
            $template = ucfirst($action);
121
            if ($backendUser->workspace !== 0) {
122
                $this->addFlashMessage(
123
                    $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText'),
124
                    $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning'),
125
                    FlashMessage::WARNING
126
                );
127
            }
128
            $this->initializeView($template);
129
            $this->registerDocHeaderButtons($action);
130
            $this->moduleTemplate->setTitle(
131
                $this->getLanguageService()->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:mlang_tabs_tab'),
132
                $this->id !== 0 && !empty($this->pageInfo['title']) ? $this->pageInfo['title'] : ''
133
            );
134
            $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageInfo);
135
        }
136
137
        return $this->{$action . 'Action'}($request);
138
    }
139
140
    public function handleAjaxRequest(ServerRequestInterface $request): ResponseInterface
141
    {
142
        $parsedBody = $request->getParsedBody();
143
        $conf = [
144
            'page' => $parsedBody['page'] ?? null,
145
            'who' => $parsedBody['who'] ?? null,
146
            'mode' => $parsedBody['mode'] ?? null,
147
            'bits' => (int)($parsedBody['bits'] ?? 0),
148
            'permissions' => (int)($parsedBody['permissions'] ?? 0),
149
            'action' => $parsedBody['action'] ?? null,
150
            'ownerUid' => (int)($parsedBody['ownerUid'] ?? 0),
151
            'username' => $parsedBody['username'] ?? null,
152
            'groupUid' => (int)($parsedBody['groupUid'] ?? 0),
153
            'groupname' => $parsedBody['groupname'] ?? '',
154
            'editLockState' => (int)($parsedBody['editLockState'] ?? 0),
155
            'new_owner_uid' => (int)($parsedBody['newOwnerUid'] ?? 0),
156
            'new_group_uid' => (int)($parsedBody['newGroupUid'] ?? 0),
157
        ];
158
159
        // Basic test for required value
160
        if ($conf['page'] <= 0) {
161
            return $this->htmlResponse('This script cannot be called directly', 500);
162
        }
163
164
        // Initialize view and always assign current page id
165
        $this->initializeView();
166
        $this->view->assign('pageId', $conf['page']);
0 ignored issues
show
Bug introduced by
The method assign() does not exist on null. ( Ignorable by Annotation )

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

166
        $this->view->/** @scrutinizer ignore-call */ 
167
                     assign('pageId', $conf['page']);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
167
168
        // Initialize TCE for execution of updates
169
        $tce = GeneralUtility::makeInstance(DataHandler::class);
170
171
        // Determine the action to execute
172
        switch ($conf['action'] ?? '') {
173
            case 'show_change_owner_selector':
174
                $this->view->setTemplatePathAndFilename(
0 ignored issues
show
Bug introduced by
The method setTemplatePathAndFilename() does not exist on TYPO3Fluid\Fluid\View\ViewInterface. It seems like you code against a sub-type of TYPO3Fluid\Fluid\View\ViewInterface such as TYPO3\CMS\Fluid\View\AbstractTemplateView. ( Ignorable by Annotation )

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

174
                $this->view->/** @scrutinizer ignore-call */ 
175
                             setTemplatePathAndFilename(
Loading history...
175
                    GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/ChangeOwnerSelector.html')
176
                );
177
                $users = BackendUtility::getUserNames();
178
                $this->view->assignMultiple([
179
                    'elementId' => 'o_' . $conf['page'],
180
                    'ownerUid' => $conf['ownerUid'],
181
                    'username' => $conf['username'],
182
                    'users' => $users,
183
                    'addCurrentUser' => !isset($users[$conf['ownerUid']])
184
                ]);
185
                break;
186
            case 'show_change_group_selector':
187
                $this->view->setTemplatePathAndFilename(
188
                    GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/ChangeGroupSelector.html')
189
                );
190
                $groups = BackendUtility::getGroupNames();
191
                $this->view->assignMultiple([
192
                    'elementId' => 'g_' . $conf['page'],
193
                    'groupUid' => $conf['groupUid'],
194
                    'groupname' => $conf['groupname'],
195
                    'groups' => $groups,
196
                    'addCurrentGroup' => !isset($groups[$conf['groupUid']])
197
                ]);
198
                break;
199
            case 'toggle_edit_lock':
200
                // Initialize requested lock state
201
                $editLockState = !$conf['editLockState'];
202
203
                // Execute TCE Update
204
                $tce->start([
205
                    'pages' => [
206
                        $conf['page'] => [
207
                            'editlock' => $editLockState
208
                        ]
209
                    ]
210
                ], []);
211
                $tce->process_datamap();
212
213
                // Setup view
214
                $this->view->setTemplatePathAndFilename(
215
                    GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/ToggleEditLock.html')
216
                );
217
                $this->view->assignMultiple([
218
                    'elementId' => 'el_' . $conf['page'],
219
                    'editLockState' => $editLockState
220
                ]);
221
                break;
222
            case 'change_owner':
223
                // Check if new owner uid is given (also accept 0 => [not set])
224
                if ($conf['new_owner_uid'] < 0) {
225
                    return $this->htmlResponse('An error occurred: No page owner uid specified', 500);
226
                }
227
228
                // Execute TCE Update
229
                $tce->start([
230
                    'pages' => [
231
                        $conf['page'] => [
232
                            'perms_userid' => $conf['new_owner_uid']
233
                        ]
234
                    ]
235
                ], []);
236
                $tce->process_datamap();
237
238
                // Setup and render view
239
                $this->view->setTemplatePathAndFilename(
240
                    GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/ChangeOwner.html')
241
                );
242
                $this->view->assignMultiple([
243
                    'userId' => $conf['new_owner_uid'],
244
                    'username' => BackendUtility::getUserNames(
245
                        'username',
246
                        ' AND uid = ' . $conf['new_owner_uid']
247
                    )[$conf['new_owner_uid']]['username'] ?? ''
248
                ]);
249
                break;
250
            case 'change_group':
251
                // Check if new group uid is given (also accept 0 => [not set])
252
                if ($conf['new_group_uid'] < 0) {
253
                    return $this->htmlResponse('An error occurred: No page group uid specified', 500);
254
                }
255
256
                // Execute TCE Update
257
                $tce->start([
258
                    'pages' => [
259
                        $conf['page'] => [
260
                            'perms_groupid' => $conf['new_group_uid']
261
                        ]
262
                    ]
263
                ], []);
264
                $tce->process_datamap();
265
266
                // Setup and render view
267
                $this->view->setTemplatePathAndFilename(
268
                    GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/ChangeGroup.html')
269
                );
270
                $this->view->assignMultiple([
271
                    'groupId' => $conf['new_group_uid'],
272
                    'groupname' => BackendUtility::getGroupNames(
273
                        'title',
274
                        ' AND uid = ' . $conf['new_group_uid']
275
                    )[$conf['new_group_uid']]['title'] ?? ''
276
                ]);
277
                break;
278
            default:
279
                // Initialize permissions state
280
                if ($conf['mode'] === 'delete') {
281
                    $conf['permissions'] -= $conf['bits'];
282
                } else {
283
                    $conf['permissions'] += $conf['bits'];
284
                }
285
286
                // Execute TCE Update
287
                $tce->start([
288
                    'pages' => [
289
                        $conf['page'] => [
290
                            'perms_' . $conf['who'] => $conf['permissions']
291
                        ]
292
                    ]
293
                ], []);
294
                $tce->process_datamap();
295
296
                // Setup and render view
297
                $this->view->setTemplatePathAndFilename(
298
                    GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/ChangePermission.html')
299
                );
300
                $this->view->assignMultiple([
301
                    'permission' => $conf['permissions'],
302
                    'scope' => $conf['who']
303
                ]);
304
        }
305
306
        return $this->htmlResponse($this->view->render());
307
    }
308
309
    public function indexAction(ServerRequestInterface $request): ResponseInterface
310
    {
311
        $this->view->assignMultiple([
312
            'currentId' => $this->id,
313
            'viewTree' => $this->getTree(),
314
            'beUsers' => BackendUtility::getUserNames(),
315
            'beGroups' => BackendUtility::getGroupNames(),
316
            'depth' => $this->depth,
317
            'depthOptions' => $this->getDepthOptions(),
318
            'depthBaseUrl' => $this->uriBuilder->buildUriFromRoute('system_BeuserTxPermission', [
319
                'id' => $this->id,
320
                'depth' => '${value}',
321
                'action' => 'index',
322
            ]),
323
            'returnUrl' => (string)$this->uriBuilder->buildUriFromRoute('system_BeuserTxPermission', [
324
                'id' => $this->id,
325
                'depth' => $this->depth,
326
                'action' => 'index'
327
            ])
328
        ]);
329
330
        return $this->htmlResponse($this->moduleTemplate->setContent($this->view->render())->renderContent());
0 ignored issues
show
Bug introduced by
The method setContent() does not exist on null. ( Ignorable by Annotation )

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

330
        return $this->htmlResponse($this->moduleTemplate->/** @scrutinizer ignore-call */ setContent($this->view->render())->renderContent());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
331
    }
332
333
    public function editAction(ServerRequestInterface $request): ResponseInterface
334
    {
335
        $lang = $this->getLanguageService();
336
        $selectNone = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone');
337
        $selectUnchanged = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged');
338
339
        // Owner selector
340
        $beUserDataArray = [0 => $selectNone];
341
        foreach (BackendUtility::getUserNames() as $uid => $row) {
342
            $beUserDataArray[$uid] = $row['username'] ?? '';
343
        }
344
        $beUserDataArray[-1] = $selectUnchanged;
345
346
        // Group selector
347
        $beGroupDataArray = [0 => $selectNone];
348
        foreach (BackendUtility::getGroupNames() as $uid => $row) {
349
            $beGroupDataArray[$uid] = $row['title'] ?? '';
350
        }
351
        $beGroupDataArray[-1] = $selectUnchanged;
352
353
        $this->view->assignMultiple([
354
            'id' => $this->id,
355
            'depth' => $this->depth,
356
            'currentBeUser' => $this->pageInfo['perms_userid'] ?? 0,
357
            'beUserData' => $beUserDataArray,
358
            'currentBeGroup' => $this->pageInfo['perms_groupid'] ?? 0,
359
            'beGroupData' => $beGroupDataArray,
360
            'pageInfo' => $this->pageInfo,
361
            'returnUrl' => $this->returnUrl,
362
            'recursiveSelectOptions' => $this->getRecursiveSelectOptions(),
363
            'formAction' => (string)$this->uriBuilder->buildUriFromRoute('system_BeuserTxPermission', [
364
                'action' => 'update',
365
                'id' => $this->id,
366
                'depth' => $this->depth,
367
                'returnUrl' => $this->returnUrl
368
            ])
369
        ]);
370
371
        return $this->htmlResponse($this->moduleTemplate->setContent($this->view->render())->renderContent());
372
    }
373
374
    protected function updateAction(ServerRequestInterface $request): ResponseInterface
375
    {
376
        $data = (array)($request->getParsedBody()['data'] ?? []);
377
        $mirror = (array)($request->getParsedBody()['mirror'] ?? []);
378
379
        $dataHandlerInput = [];
380
        // Prepare the input data for data handler
381
        if (is_array($data['pages'] ?? false) && $data['pages'] !== []) {
382
            foreach ($data['pages'] as $pageUid => $properties) {
383
                // if the owner and group field shouldn't be touched, unset the option
384
                if ((int)$properties['perms_userid'] === -1) {
385
                    unset($properties['perms_userid']);
386
                }
387
                if ((int)$properties['perms_groupid'] === -1) {
388
                    unset($properties['perms_groupid']);
389
                }
390
                $dataHandlerInput[$pageUid] = $properties;
391
                if (!empty($mirror['pages'][$pageUid])) {
392
                    $mirrorPages = GeneralUtility::intExplode(',', $mirror['pages'][$pageUid]);
393
                    foreach ($mirrorPages as $mirrorPageUid) {
394
                        $dataHandlerInput[$mirrorPageUid] = $properties;
395
                    }
396
                }
397
            }
398
        }
399
400
        $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
401
        $dataHandler->start(
402
            [
403
                'pages' => $dataHandlerInput
404
            ],
405
            []
406
        );
407
        $dataHandler->process_datamap();
408
409
        return $this->responseFactory->createResponse(303)
410
            ->withHeader('location', $this->returnUrl);
411
    }
412
413
    protected function initializeView(string $template = ''): void
414
    {
415
        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
416
        $this->view->setTemplateRootPaths(['EXT:beuser/Resources/Private/Templates/Permission']);
0 ignored issues
show
Bug introduced by
The method setTemplateRootPaths() does not exist on TYPO3Fluid\Fluid\View\ViewInterface. It seems like you code against a sub-type of TYPO3Fluid\Fluid\View\ViewInterface such as TYPO3\CMS\Fluid\View\AbstractTemplateView. ( Ignorable by Annotation )

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

416
        $this->view->/** @scrutinizer ignore-call */ 
417
                     setTemplateRootPaths(['EXT:beuser/Resources/Private/Templates/Permission']);
Loading history...
417
        $this->view->setPartialRootPaths(['EXT:beuser/Resources/Private/Partials/Permission']);
0 ignored issues
show
Bug introduced by
The method setPartialRootPaths() does not exist on TYPO3Fluid\Fluid\View\ViewInterface. It seems like you code against a sub-type of TYPO3Fluid\Fluid\View\ViewInterface such as TYPO3\CMS\Fluid\View\AbstractTemplateView. ( Ignorable by Annotation )

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

417
        $this->view->/** @scrutinizer ignore-call */ 
418
                     setPartialRootPaths(['EXT:beuser/Resources/Private/Partials/Permission']);
Loading history...
418
        $this->view->setLayoutRootPaths(['EXT:beuser/Resources/Private/Layouts']);
0 ignored issues
show
Bug introduced by
The method setLayoutRootPaths() does not exist on TYPO3Fluid\Fluid\View\ViewInterface. It seems like you code against a sub-type of TYPO3Fluid\Fluid\View\ViewInterface such as TYPO3\CMS\Fluid\View\AbstractTemplateView. ( Ignorable by Annotation )

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

418
        $this->view->/** @scrutinizer ignore-call */ 
419
                     setLayoutRootPaths(['EXT:beuser/Resources/Private/Layouts']);
Loading history...
419
        if ($template !== '') {
420
            $this->view->setTemplatePathAndFilename(
421
                GeneralUtility::getFileAbsFileName('EXT:beuser/Resources/Private/Templates/Permission/' . $template . '.html')
422
            );
423
            // Only add JS modules in case a template is given, as otherwise this may be a ajax request
424
            $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Beuser/Permissions');
425
            $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
426
        }
427
    }
428
429
    protected function registerDocHeaderButtons(string $action): void
430
    {
431
        $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
432
        $lang = $this->getLanguageService();
433
434
        if ($action === 'edit') {
435
            // CLOSE button:
436
            if ($this->returnUrl !== '') {
437
                $closeButton = $buttonBar->makeLinkButton()
438
                    ->setHref($this->returnUrl)
439
                    ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
440
                    ->setShowLabelText(true)
441
                    ->setIcon($this->iconFactory->getIcon('actions-close', Icon::SIZE_SMALL));
442
                $buttonBar->addButton($closeButton);
443
            }
444
445
            // SAVE button:
446
            $saveButton = $buttonBar->makeInputButton()
447
                ->setName('_save')
448
                ->setValue('1')
449
                ->setForm('PermissionControllerEdit')
450
                ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc'))
451
                ->setShowLabelText(true)
452
                ->setIcon($this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL));
453
            $buttonBar->addButton($saveButton);
454
        }
455
456
        $shortcutButton = $buttonBar->makeShortcutButton()
457
            ->setRouteIdentifier('system_BeuserTxPermission')
458
            ->setDisplayName($this->getShortcutTitle())
459
            ->setArguments(['id' => $this->id, 'action' => $action]);
460
        $buttonBar->addButton($shortcutButton);
461
462
        $helpButton = $buttonBar->makeHelpButton()
463
            ->setModuleName('xMOD_csh_corebe')
464
            ->setFieldName('perm_module');
465
466
        $buttonBar->addButton($helpButton);
467
    }
468
469
    protected function getTree(): array
470
    {
471
        $tree = GeneralUtility::makeInstance(PageTreeView::class);
472
        $tree->init();
473
        $tree->addField('perms_user', true);
474
        $tree->addField('perms_group', true);
475
        $tree->addField('perms_everybody', true);
476
        $tree->addField('perms_userid', true);
477
        $tree->addField('perms_groupid', true);
478
        $tree->addField('hidden');
479
        $tree->addField('fe_group');
480
        $tree->addField('starttime');
481
        $tree->addField('endtime');
482
        $tree->addField('editlock');
483
484
        // Create the tree from $this->id
485
        if ($this->id) {
486
            $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getIcon($this->pageInfo)];
487
        } else {
488
            $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getRootIcon($this->pageInfo)];
489
        }
490
        $tree->getTree($this->id, $this->depth);
491
492
        return $tree->tree;
493
    }
494
495
    protected function getDepthOptions(): array
496
    {
497
        $depthOptions = [];
498
        foreach (self::DEPTH_LEVELS as $depthLevel) {
499
            $levelLabel = $depthLevel === 1 ? 'level' : 'levels';
500
            $depthOptions[$depthLevel] = $depthLevel . ' ' . $this->getLanguageService()->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:' . $levelLabel);
501
        }
502
        return $depthOptions;
503
    }
504
505
    /**
506
     * Finding tree and offer setting of values recursively.
507
     *
508
     * @return array
509
     */
510
    protected function getRecursiveSelectOptions(): array
511
    {
512
        $lang = $this->getLanguageService();
513
        // Initialize tree object:
514
        $tree = GeneralUtility::makeInstance(PageTreeView::class);
515
        $tree->init();
516
        $tree->addField('perms_userid', true);
517
        $tree->makeHTML = 0;
518
        // Make tree:
519
        $tree->getTree($this->id, self::RECURSIVE_LEVELS);
520
        $options = [
521
            '' => $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone')
522
        ];
523
        // If there are a hierarchy of page ids, then...
524
        if (!empty($tree->orig_ids_hierarchy) && ($this->getBackendUser()->user['uid'] ?? false)) {
525
            // Init:
526
            $labelRecursive = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:recursive');
527
            $labelLevel = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:level');
528
            $labelLevels = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:levels');
529
            $labelPageAffected = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:page_affected');
530
            $labelPagesAffected = $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:pages_affected');
531
            $theIdListArr = [];
532
            // Traverse the number of levels we want to allow recursive
533
            // setting of permissions for:
534
            for ($a = self::RECURSIVE_LEVELS; $a > 0; $a--) {
535
                if (is_array($tree->orig_ids_hierarchy[$a] ?? false)) {
536
                    foreach ($tree->orig_ids_hierarchy[$a] as $theId) {
537
                        $theIdListArr[] = $theId;
538
                    }
539
                    $lKey = self::RECURSIVE_LEVELS - $a + 1;
540
                    $pagesCount = count($theIdListArr);
541
                    $options[implode(',', $theIdListArr)] = $labelRecursive . ' ' . $lKey . ' ' . ($lKey === 1 ? $labelLevel : $labelLevels) .
542
                        ' (' . $pagesCount . ' ' . ($pagesCount === 1 ? $labelPageAffected : $labelPagesAffected) . ')';
543
                }
544
            }
545
        }
546
        return $options;
547
    }
548
549
    /**
550
     * Adds a flash message to the default flash message queue
551
     *
552
     * @param string $message
553
     * @param string $title
554
     * @param int $severity
555
     */
556
    protected function addFlashMessage(string $message, string $title = '', int $severity = FlashMessage::INFO): void
557
    {
558
        $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $title, $severity, true);
559
        $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
560
        $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
561
        $defaultFlashMessageQueue->enqueue($flashMessage);
562
    }
563
564
    /**
565
     * Returns the shortcut title for the current page
566
     *
567
     * @return string
568
     */
569
    protected function getShortcutTitle(): string
570
    {
571
        return sprintf(
572
            '%s: %s [%d]',
573
            $this->getLanguageService()->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'),
574
            BackendUtility::getRecordTitle('pages', $this->pageInfo),
575
            $this->id
576
        );
577
    }
578
579
    protected function htmlResponse(string $html, int $code = 200): ResponseInterface
580
    {
581
        $response = $this->responseFactory->createResponse($code)
582
            ->withHeader('Content-Type', 'text/html; charset=utf-8');
583
        $response->getBody()->write($html);
584
        return $response;
585
    }
586
587
    protected function getBackendUser(): BackendUserAuthentication
588
    {
589
        return $GLOBALS['BE_USER'];
590
    }
591
592
    protected function getLanguageService(): LanguageService
593
    {
594
        return $GLOBALS['LANG'];
595
    }
596
}
597