PermissionController.php 15.7 KB
Newer Older
1
<?php
2

3
/*
4
5
6
7
8
9
10
11
12
13
14
15
 * This file is part of the TYPO3 CMS project.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */

16
17
namespace TYPO3\CMS\Beuser\Controller;

18
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
19
use TYPO3\CMS\Backend\Tree\View\PageTreeView;
20
use TYPO3\CMS\Backend\Utility\BackendUtility;
21
use TYPO3\CMS\Backend\View\BackendTemplateView;
22
use TYPO3\CMS\Core\DataHandling\DataHandler;
23
use TYPO3\CMS\Core\Imaging\Icon;
24
25
26
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
27
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
28
29
30
31
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

/**
 * Backend module page permissions
32
 * @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
33
 */
34
35
36
37
38
39
class PermissionController extends ActionController
{
    /**
     * @var string prefix for session
     */
    const SESSION_PREFIX = 'tx_Beuser_';
40

41
42
43
44
    /**
     * @var int the current page id
     */
    protected $id;
45

46
    /**
47
     * @var string
48
     */
49
    protected $returnUrl = '';
50

51
52
53
54
    /**
     * @var int
     */
    protected $depth;
55

56
57
58
59
60
61
    /**
     * Number of levels to enable recursive settings for
     *
     * @var int
     */
    protected $getLevels = 10;
62

63
64
65
    /**
     * @var array
     */
66
    protected $pageInfo = [];
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
    /**
     * Backend Template Container
     *
     * @var string
     */
    protected $defaultViewObjectName = BackendTemplateView::class;

    /**
     * BackendTemplateContainer
     *
     * @var BackendTemplateView
     */
    protected $view;

82
83
84
85
86
    /**
     * Initialize action
     */
    protected function initializeAction()
    {
87
88
89
90
91
92
93
94
95
        // determine depth parameter
        $this->depth = (int)GeneralUtility::_GP('depth') > 0
            ? (int)GeneralUtility::_GP('depth')
            : (int)$this->getBackendUser()->getSessionData(self::SESSION_PREFIX . 'depth');
        if ($this->request->hasArgument('depth')) {
            $this->depth = (int)$this->request->getArgument('depth');
        }
        $this->getBackendUser()->setAndSaveSessionData(self::SESSION_PREFIX . 'depth', $this->depth);

96
97
98
99
100
        // determine id parameter
        $this->id = (int)GeneralUtility::_GP('id');
        if ($this->request->hasArgument('id')) {
            $this->id = (int)$this->request->getArgument('id');
        }
101

102
103
104
105
        if (!BackendUtility::getRecord('pages', $this->id)) {
            $this->id = 0;
        }

106
107
108
        $this->returnUrl = GeneralUtility::_GP('returnUrl');
        if ($this->request->hasArgument('returnUrl')) {
            $this->returnUrl = $this->request->getArgument('returnUrl');
109
        }
110

111
        $this->setPageInfo();
112
    }
113

114
115
116
117
118
119
120
    /**
     * Initializes view
     *
     * @param ViewInterface $view The view to be initialized
     */
    protected function initializeView(ViewInterface $view)
    {
121
        parent::initializeView($view);
122
        $this->setPageInfo();
123
124
125
126

        // the view of the update action has a different view class
        if ($view instanceof BackendTemplateView) {
            $view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Beuser/Permissions');
127
            $view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
128

129
            $this->registerDocHeaderButtons();
130
            $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($this->pageInfo);
131
            $this->view->getModuleTemplate()->setFlashMessageQueue($this->getFlashMessageQueue());
132
        }
133
134
135
136
137
138
139
    }

    /**
     * Registers the Icons into the docheader
     *
     * @throws \InvalidArgumentException
     */
140
    protected function registerDocHeaderButtons()
141
142
143
144
    {
        /** @var ButtonBar $buttonBar */
        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
        $currentRequest = $this->request;
145
        $lang = $this->getLanguageService();
146

147
148
        if ($currentRequest->getControllerActionName() === 'edit') {
            // CLOSE button:
149
150
151
            if (!empty($this->returnUrl)) {
                $closeButton = $buttonBar->makeLinkButton()
                    ->setHref($this->returnUrl)
152
                    ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
153
154
155
156
157
158
                    ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon(
                        'actions-close',
                        Icon::SIZE_SMALL
                    ));
                $buttonBar->addButton($closeButton);
            }
159
160
161

            // SAVE button:
            $saveButton = $buttonBar->makeInputButton()
162
                ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc'))
163
164
165
166
167
168
169
170
171
172
173
174
                ->setName('tx_beuser_system_beusertxpermission[submit]')
                ->setValue('Save')
                ->setForm('PermissionControllerEdit')
                ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon(
                    'actions-document-save',
                    Icon::SIZE_SMALL
                ))
                ->setShowLabelText(true);

            $buttonBar->addButton($saveButton);
        }

175
        $shortcutButton = $buttonBar->makeShortcutButton()
176
            ->setRouteIdentifier('system_BeuserTxPermission')
177
            ->setDisplayName($this->getShortcutTitle())
178
            ->setArguments(['id' => (int)$this->id]);
179
        $buttonBar->addButton($shortcutButton);
180
    }
181

182
183
184
185
186
187
    /**
     * Index action
     */
    public function indexAction()
    {
        if (!$this->id) {
188
            $this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0];
189
        }
190

191
192
193
        if ($this->getBackendUser()->workspace != 0) {
            // Adding section with the permission setting matrix:
            $this->addFlashMessage(
194
195
                LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser') ?? '',
                LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser') ?? '',
196
197
198
                FlashMessage::WARNING
            );
        }
199

200
        // depth options
201
202
        $depthOptions = [];
        $url = $this->uriBuilder->reset()->setArguments([
203
            'action' => 'index',
204
            'depth' => '${value}',
205
            'id' => $this->id
206
207
        ])->buildBackendUri();
        foreach ([1, 2, 3, 4, 10] as $depthLevel) {
208
209
            $levelLabel = $depthLevel === 1 ? 'level' : 'levels';
            $depthOptions[$depthLevel] = $depthLevel . ' ' . LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:' . $levelLabel, 'beuser');
210
        }
211
        $this->view->assign('currentId', $this->id);
212
213
214
        $this->view->assign('depthBaseUrl', $url);
        $this->view->assign('depth', $this->depth);
        $this->view->assign('depthOptions', $depthOptions);
215

216
217
218
219
        $beUserArray = BackendUtility::getUserNames();
        $this->view->assign('beUsers', $beUserArray);
        $beGroupArray = BackendUtility::getGroupNames();
        $this->view->assign('beGroups', $beGroupArray);
220

221
        /** @var PageTreeView $tree */
222
223
224
225
226
227
228
229
230
231
232
233
        $tree = GeneralUtility::makeInstance(PageTreeView::class);
        $tree->init();
        $tree->addField('perms_user', true);
        $tree->addField('perms_group', true);
        $tree->addField('perms_everybody', true);
        $tree->addField('perms_userid', true);
        $tree->addField('perms_groupid', true);
        $tree->addField('hidden');
        $tree->addField('fe_group');
        $tree->addField('starttime');
        $tree->addField('endtime');
        $tree->addField('editlock');
234

235
236
        // Create the tree from $this->id
        if ($this->id) {
237
            $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getIcon($this->pageInfo)];
238
        } else {
239
            $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getRootIcon($this->pageInfo)];
240
241
242
        }
        $tree->getTree($this->id, $this->depth);
        $this->view->assign('viewTree', $tree->tree);
243

244
        // CSH for permissions setting
245
        $this->view->assign('cshItem', BackendUtility::cshItem('xMOD_csh_corebe', 'perm_module', '', '<span class="btn btn-default btn-sm">|</span>'));
246
    }
247

248
249
250
251
252
253
254
    /**
     * Edit action
     */
    public function editAction()
    {
        $this->view->assign('id', $this->id);
        $this->view->assign('depth', $this->depth);
255

256
        if (!$this->id) {
257
            $this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0];
258
259
260
261
        }
        if ($this->getBackendUser()->workspace != 0) {
            // Adding FlashMessage with the permission setting matrix:
            $this->addFlashMessage(
262
263
                LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser') ?? '',
                LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser') ?? '',
264
265
266
                FlashMessage::WARNING
            );
        }
267
268
        // Get user names and group names
        $beGroupArray = BackendUtility::getGroupNames();
269
        $beUserArray  = BackendUtility::getUserNames();
270

271
        // Owner selector
272
        $beUserDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')];
273
274
275
276
277
278
        foreach ($beUserArray as $uid => &$row) {
            $beUserDataArray[$uid] = $row['username'];
        }
        $beUserDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser');
        $this->view->assign('currentBeUser', $this->pageInfo['perms_userid']);
        $this->view->assign('beUserData', $beUserDataArray);
279

280
        // Group selector
281
        $beGroupDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')];
282
283
284
285
286
287
288
        foreach ($beGroupArray as $uid => $row) {
            $beGroupDataArray[$uid] = $row['title'];
        }
        $beGroupDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser');
        $this->view->assign('currentBeGroup', $this->pageInfo['perms_groupid']);
        $this->view->assign('beGroupData', $beGroupDataArray);
        $this->view->assign('pageInfo', $this->pageInfo);
289
        $this->view->assign('returnUrl', $this->returnUrl);
290
291
        $this->view->assign('recursiveSelectOptions', $this->getRecursiveSelectOptions());
    }
292

293
294
295
296
297
298
299
300
    /**
     * Update action
     *
     * @param array $data
     * @param array $mirror
     */
    protected function updateAction(array $data, array $mirror)
    {
301
302
        $dataHandlerInput = [];
        // Prepare the input data for data handler
303
304
305
306
307
308
309
310
311
        if (!empty($data['pages'])) {
            foreach ($data['pages'] as $pageUid => $properties) {
                // if the owner and group field shouldn't be touched, unset the option
                if ((int)$properties['perms_userid'] === -1) {
                    unset($properties['perms_userid']);
                }
                if ((int)$properties['perms_groupid'] === -1) {
                    unset($properties['perms_groupid']);
                }
312
                $dataHandlerInput[$pageUid] = $properties;
313
                if (!empty($mirror['pages'][$pageUid])) {
314
                    $mirrorPages = GeneralUtility::intExplode(',', $mirror['pages'][$pageUid]);
315
                    foreach ($mirrorPages as $mirrorPageUid) {
316
                        $dataHandlerInput[$mirrorPageUid] = $properties;
317
318
319
320
                    }
                }
            }
        }
321
322
323
324
325
326
327
328
329
330

        $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
        $dataHandler->start(
            [
                'pages' => $dataHandlerInput
            ],
            []
        );
        $dataHandler->process_datamap();

331
        $this->redirectToUri($this->returnUrl);
332
    }
333

334
335
336
337
338
339
340
    /**
     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
     */
    protected function getBackendUser()
    {
        return $GLOBALS['BE_USER'];
    }
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    /**
     * Finding tree and offer setting of values recursively.
     *
     * @return array
     */
    protected function getRecursiveSelectOptions()
    {
        // Initialize tree object:
        $tree = GeneralUtility::makeInstance(PageTreeView::class);
        $tree->init();
        $tree->addField('perms_userid', true);
        $tree->makeHTML = 0;
        $tree->setRecs = 1;
        // Make tree:
        $tree->getTree($this->id, $this->getLevels, '');
357
        $options = [];
358
359
360
361
362
        $options[''] = '';
        // If there are a hierarchy of page ids, then...
        if ($this->getBackendUser()->user['uid'] && !empty($tree->orig_ids_hierarchy)) {
            // Init:
            $labelRecursive = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:recursive', 'beuser');
363
            $labelLevel = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:level', 'beuser');
364
            $labelLevels = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:levels', 'beuser');
365
            $labelPageAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:page_affected', 'beuser');
366
            $labelPagesAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:pages_affected', 'beuser');
367
            $theIdListArr = [];
368
369
370
371
372
373
374
375
            // Traverse the number of levels we want to allow recursive
            // setting of permissions for:
            for ($a = $this->getLevels; $a > 0; $a--) {
                if (is_array($tree->orig_ids_hierarchy[$a])) {
                    foreach ($tree->orig_ids_hierarchy[$a] as $theId) {
                        $theIdListArr[] = $theId;
                    }
                    $lKey = $this->getLevels - $a + 1;
376
377
378
                    $pagesCount = count($theIdListArr);
                    $options[implode(',', $theIdListArr)] = $labelRecursive . ' ' . $lKey . ' ' . ($lKey === 1 ? $labelLevel : $labelLevels) .
                        ' (' . $pagesCount . ' ' . ($pagesCount === 1 ? $labelPageAffected : $labelPagesAffected) . ')';
379
380
381
382
383
                }
            }
        }
        return $options;
    }
384

385
386
387
388
389
390
391
392
    /**
     * Check if page record exists and set pageInfo
     */
    protected function setPageInfo(): void
    {
        $this->pageInfo = BackendUtility::readPageAccess(BackendUtility::getRecord('pages', $this->id) ? $this->id : 0, ' 1=1');
    }

393
394
395
    /**
     * Returns LanguageService
     *
396
     * @return \TYPO3\CMS\Core\Localization\LanguageService
397
398
399
400
401
     */
    protected function getLanguageService()
    {
        return $GLOBALS['LANG'];
    }
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

    /**
     * Returns the shortcut title for the current page
     *
     * @return string
     */
    protected function getShortcutTitle(): string
    {
        return sprintf(
            '%s: %s [%d]',
            $this->getLanguageService()->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab'),
            BackendUtility::getRecordTitle('pages', $this->pageInfo),
            $this->id
        );
    }
417
}