[BUGFIX] Fix thrown \InvalidArgumentException in access module
[Packages/TYPO3.CMS.git] / typo3 / sysext / beuser / Classes / Controller / PermissionController.php
1 <?php
2 namespace TYPO3\CMS\Beuser\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
18 use TYPO3\CMS\Backend\Tree\View\PageTreeView;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Backend\View\BackendTemplateView;
21 use TYPO3\CMS\Core\Database\ConnectionPool;
22 use TYPO3\CMS\Core\Imaging\Icon;
23 use TYPO3\CMS\Core\Messaging\FlashMessage;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
26 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
27 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
28
29 /**
30 * Backend module page permissions
31 */
32 class PermissionController extends ActionController
33 {
34 /**
35 * @var string prefix for session
36 */
37 const SESSION_PREFIX = 'tx_Beuser_';
38
39 /**
40 * @var int the current page id
41 */
42 protected $id;
43
44 /**
45 * @var string
46 */
47 protected $returnUrl = '';
48
49 /**
50 * @var int
51 */
52 protected $depth;
53
54 /**
55 * Number of levels to enable recursive settings for
56 *
57 * @var int
58 */
59 protected $getLevels = 10;
60
61 /**
62 * @var array
63 */
64 protected $pageInfo = [];
65
66 /**
67 * Backend Template Container
68 *
69 * @var string
70 */
71 protected $defaultViewObjectName = BackendTemplateView::class;
72
73 /**
74 * BackendTemplateContainer
75 *
76 * @var BackendTemplateView
77 */
78 protected $view;
79
80 /**
81 * Initialize action
82 */
83 protected function initializeAction()
84 {
85 // determine depth parameter
86 $this->depth = (int)GeneralUtility::_GP('depth') > 0
87 ? (int)GeneralUtility::_GP('depth')
88 : (int)$this->getBackendUser()->getSessionData(self::SESSION_PREFIX . 'depth');
89 if ($this->request->hasArgument('depth')) {
90 $this->depth = (int)$this->request->getArgument('depth');
91 }
92 $this->getBackendUser()->setAndSaveSessionData(self::SESSION_PREFIX . 'depth', $this->depth);
93
94 // determine id parameter
95 $this->id = (int)GeneralUtility::_GP('id');
96 if ($this->request->hasArgument('id')) {
97 $this->id = (int)$this->request->getArgument('id');
98 }
99
100 $this->returnUrl = GeneralUtility::_GP('returnUrl');
101 if ($this->request->hasArgument('returnUrl')) {
102 $this->returnUrl = $this->request->getArgument('returnUrl');
103 }
104
105 $this->pageInfo = BackendUtility::readPageAccess($this->id, ' 1=1');
106 }
107
108 /**
109 * Initializes view
110 *
111 * @param ViewInterface $view The view to be initialized
112 */
113 protected function initializeView(ViewInterface $view)
114 {
115 parent::initializeView($view);
116 $view->assign(
117 'previewUrl',
118 BackendUtility::viewOnClick(
119 (int)$this->pageInfo['uid'],
120 '',
121 BackendUtility::BEgetRootLine((int)$this->pageInfo['uid'])
122 )
123 );
124
125 // the view of the update action has a different view class
126 if ($view instanceof BackendTemplateView) {
127 $view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Beuser/Permissions');
128 $view->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
129 $view->getModuleTemplate()->addJavaScriptCode(
130 'jumpToUrl',
131 '
132 function jumpToUrl(URL) {
133 window.location.href = URL;
134 return false;
135 }
136 '
137 );
138 $this->registerDocHeaderButtons();
139 $this->view->getModuleTemplate()->getDocHeaderComponent()->setMetaInformation($this->pageInfo);
140 $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
141 }
142 }
143
144 /**
145 * Registers the Icons into the docheader
146 *
147 * @throws \InvalidArgumentException
148 */
149 protected function registerDocHeaderButtons()
150 {
151 /** @var ButtonBar $buttonBar */
152 $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
153 $currentRequest = $this->request;
154 $moduleName = $currentRequest->getPluginName();
155 $getVars = $this->request->getArguments();
156 $lang = $this->getLanguageService();
157
158 $extensionName = $currentRequest->getControllerExtensionName();
159 if (empty($getVars)) {
160 $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName);
161 $getVars = ['id', 'route', $modulePrefix];
162 }
163
164 if ($currentRequest->getControllerActionName() === 'edit') {
165 // CLOSE button:
166 if (!empty($this->returnUrl)) {
167 $closeButton = $buttonBar->makeLinkButton()
168 ->setHref($this->returnUrl)
169 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
170 ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon(
171 'actions-close',
172 Icon::SIZE_SMALL
173 ));
174 $buttonBar->addButton($closeButton);
175 }
176
177 // SAVE button:
178 $saveButton = $buttonBar->makeInputButton()
179 ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc'))
180 ->setName('tx_beuser_system_beusertxpermission[submit]')
181 ->setValue('Save')
182 ->setForm('PermissionControllerEdit')
183 ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon(
184 'actions-document-save',
185 Icon::SIZE_SMALL
186 ))
187 ->setShowLabelText(true);
188
189 $buttonBar->addButton($saveButton);
190 }
191
192 // SHORTCUT botton:
193 $shortcutButton = $buttonBar->makeShortcutButton()
194 ->setModuleName($moduleName)
195 ->setGetVariables($getVars);
196 $buttonBar->addButton($shortcutButton);
197 }
198
199 /**
200 * Index action
201 */
202 public function indexAction()
203 {
204 if (!$this->id) {
205 $this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0];
206 }
207
208 if ($this->getBackendUser()->workspace != 0) {
209 // Adding section with the permission setting matrix:
210 $this->addFlashMessage(
211 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser'),
212 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser'),
213 FlashMessage::WARNING
214 );
215 }
216
217 // depth options
218 $depthOptions = [];
219 $url = $this->uriBuilder->reset()->setArguments([
220 'action' => 'index',
221 'depth' => '__DEPTH__',
222 'id' => $this->id
223 ])->buildBackendUri();
224 foreach ([1, 2, 3, 4, 10] as $depthLevel) {
225 $levelLabel = $depthLevel === 1 ? 'level' : 'levels';
226 $depthOptions[$depthLevel] = $depthLevel . ' ' . LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:' . $levelLabel, 'beuser');
227 }
228 $this->view->assign('currentId', $this->id);
229 $this->view->assign('depthBaseUrl', $url);
230 $this->view->assign('depth', $this->depth);
231 $this->view->assign('depthOptions', $depthOptions);
232
233 $beUserArray = BackendUtility::getUserNames();
234 $this->view->assign('beUsers', $beUserArray);
235 $beGroupArray = BackendUtility::getGroupNames();
236 $this->view->assign('beGroups', $beGroupArray);
237
238 /** @var $tree PageTreeView */
239 $tree = GeneralUtility::makeInstance(PageTreeView::class);
240 $tree->init();
241 $tree->addField('perms_user', true);
242 $tree->addField('perms_group', true);
243 $tree->addField('perms_everybody', true);
244 $tree->addField('perms_userid', true);
245 $tree->addField('perms_groupid', true);
246 $tree->addField('hidden');
247 $tree->addField('fe_group');
248 $tree->addField('starttime');
249 $tree->addField('endtime');
250 $tree->addField('editlock');
251
252 // Create the tree from $this->id
253 if ($this->id) {
254 $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getIcon($this->id)];
255 } else {
256 $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getRootIcon($this->pageInfo)];
257 }
258 $tree->getTree($this->id, $this->depth);
259 $this->view->assign('viewTree', $tree->tree);
260
261 // CSH for permissions setting
262 $this->view->assign('cshItem', BackendUtility::cshItem('xMOD_csh_corebe', 'perm_module', null, '<span class="btn btn-default btn-sm">|</span>'));
263 }
264
265 /**
266 * Edit action
267 */
268 public function editAction()
269 {
270 $this->view->assign('id', $this->id);
271 $this->view->assign('depth', $this->depth);
272
273 if (!$this->id) {
274 $this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0];
275 }
276 if ($this->getBackendUser()->workspace != 0) {
277 // Adding FlashMessage with the permission setting matrix:
278 $this->addFlashMessage(
279 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser'),
280 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser'),
281 FlashMessage::WARNING
282 );
283 }
284 // Get user names and group names
285 $beGroupArray = BackendUtility::getGroupNames();
286 $beUserArray = BackendUtility::getUserNames();
287
288 // Owner selector
289 $beUserDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')];
290 foreach ($beUserArray as $uid => &$row) {
291 $beUserDataArray[$uid] = $row['username'];
292 }
293 $beUserDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser');
294 $this->view->assign('currentBeUser', $this->pageInfo['perms_userid']);
295 $this->view->assign('beUserData', $beUserDataArray);
296
297 // Group selector
298 $beGroupDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')];
299 foreach ($beGroupArray as $uid => $row) {
300 $beGroupDataArray[$uid] = $row['title'];
301 }
302 $beGroupDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser');
303 $this->view->assign('currentBeGroup', $this->pageInfo['perms_groupid']);
304 $this->view->assign('beGroupData', $beGroupDataArray);
305 $this->view->assign('pageInfo', $this->pageInfo);
306 $this->view->assign('returnUrl', $this->returnUrl);
307 $this->view->assign('recursiveSelectOptions', $this->getRecursiveSelectOptions());
308 }
309
310 /**
311 * Update action
312 *
313 * @param array $data
314 * @param array $mirror
315 */
316 protected function updateAction(array $data, array $mirror)
317 {
318 if (!empty($data['pages'])) {
319 foreach ($data['pages'] as $pageUid => $properties) {
320 // if the owner and group field shouldn't be touched, unset the option
321 if ((int)$properties['perms_userid'] === -1) {
322 unset($properties['perms_userid']);
323 }
324 if ((int)$properties['perms_groupid'] === -1) {
325 unset($properties['perms_groupid']);
326 }
327 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');
328 $connection->update(
329 'pages',
330 $properties,
331 ['uid' => (int)$pageUid]
332 );
333
334 if (!empty($mirror['pages'][$pageUid])) {
335 $mirrorPages = GeneralUtility::trimExplode(',', $mirror['pages'][$pageUid]);
336 foreach ($mirrorPages as $mirrorPageUid) {
337 $connection->update(
338 'pages',
339 $properties,
340 ['uid' => (int)$mirrorPageUid]
341 );
342 }
343 }
344 }
345 }
346 $this->redirectToUri($this->returnUrl);
347 }
348
349 /**
350 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
351 */
352 protected function getBackendUser()
353 {
354 return $GLOBALS['BE_USER'];
355 }
356
357 /**
358 * Finding tree and offer setting of values recursively.
359 *
360 * @return array
361 */
362 protected function getRecursiveSelectOptions()
363 {
364 // Initialize tree object:
365 $tree = GeneralUtility::makeInstance(PageTreeView::class);
366 $tree->init();
367 $tree->addField('perms_userid', true);
368 $tree->makeHTML = 0;
369 $tree->setRecs = 1;
370 // Make tree:
371 $tree->getTree($this->id, $this->getLevels, '');
372 $options = [];
373 $options[''] = '';
374 // If there are a hierarchy of page ids, then...
375 if ($this->getBackendUser()->user['uid'] && !empty($tree->orig_ids_hierarchy)) {
376 // Init:
377 $labelRecursive = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:recursive', 'beuser');
378 $labelLevel = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:level', 'beuser');
379 $labelLevels = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:levels', 'beuser');
380 $labelPageAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:page_affected', 'beuser');
381 $labelPagesAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:pages_affected', 'beuser');
382 $theIdListArr = [];
383 // Traverse the number of levels we want to allow recursive
384 // setting of permissions for:
385 for ($a = $this->getLevels; $a > 0; $a--) {
386 if (is_array($tree->orig_ids_hierarchy[$a])) {
387 foreach ($tree->orig_ids_hierarchy[$a] as $theId) {
388 $theIdListArr[] = $theId;
389 }
390 $lKey = $this->getLevels - $a + 1;
391 $pagesCount = count($theIdListArr);
392 $options[implode(',', $theIdListArr)] = $labelRecursive . ' ' . $lKey . ' ' . ($lKey === 1 ? $labelLevel : $labelLevels) .
393 ' (' . $pagesCount . ' ' . ($pagesCount === 1 ? $labelPageAffected : $labelPagesAffected) . ')';
394 }
395 }
396 }
397 return $options;
398 }
399
400 /**
401 * Returns LanguageService
402 *
403 * @return \TYPO3\CMS\Core\Localization\LanguageService
404 */
405 protected function getLanguageService()
406 {
407 return $GLOBALS['LANG'];
408 }
409 }