795ab9461b3994632adf57ec8ec9a1afeb781832
[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\Utility\IconUtility;
18 use TYPO3\CMS\Core\Database\DatabaseConnection;
19 use TYPO3\CMS\Core\Messaging\FlashMessage;
20 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
23 use TYPO3\CMS\Backend\Utility\BackendUtility;
24 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
25 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
26
27 /**
28 * Backend module page permissions
29 *
30 * @author Frank N├Ągler <typo3@naegler.net>
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 int
46 */
47 protected $returnId;
48
49 /**
50 * @var int
51 */
52 protected $depth;
53
54 /**
55 * @var int
56 */
57 protected $lastEdited;
58
59 /**
60 * @var string
61 */
62 protected $permissionsClause;
63
64 /**
65 * Number of levels to enable recursive settings for
66 *
67 * @var int
68 */
69 protected $getLevels = 10;
70
71 /**
72 * @var array
73 */
74 protected $pageInfo = array();
75
76 /**
77 * Initialize action
78 *
79 * @return void
80 */
81 protected function initializeAction() {
82 // determine id parameter
83 $this->id = (int)GeneralUtility::_GP('id');
84 if ($this->request->hasArgument('id')) {
85 $this->id = (int)$this->request->getArgument('id');
86 }
87
88 // determine depth paramter
89 $this->depth = ((int)GeneralUtility::_GP('depth') > 0) ? (int) GeneralUtility::_GP('depth') :
90 $this->getBackendUser()->getSessionData(self::SESSION_PREFIX . 'depth');
91 if ($this->request->hasArgument('depth')) {
92 $this->depth = (int)$this->request->getArgument('depth');
93 }
94 $this->getBackendUser()->setAndSaveSessionData(self::SESSION_PREFIX . 'depth', $this->depth);
95 $this->lastEdited = GeneralUtility::_GP('lastEdited');
96 $this->returnId = GeneralUtility::_GP('returnId');
97 $this->permissionsClause = $this->getBackendUser()->getPagePermsClause(1);
98 $this->pageInfo = BackendUtility::readPageAccess($this->id, $this->permissionsClause);
99 }
100
101 /**
102 * Initializes view
103 *
104 * @param ViewInterface $view The view to be initialized
105 * @return void
106 */
107 protected function initializeView(ViewInterface $view) {
108 $view->assign(
109 'previewUrl',
110 BackendUtility::viewonclick(
111 $this->pageInfo['uid'], $GLOBALS['BACK_PATH'],
112 BackendUtility::BEgetRootLine($this->pageInfo['uid'])
113 )
114 );
115 }
116
117 /**
118 * Index action
119 *
120 * @return void
121 */
122 public function indexAction() {
123 // Checking access:
124 if ($this->checkAccess()) {
125 if ($this->getBackendUser()->isAdmin() && !$this->id) {
126 $this->pageInfo = array('title' => '[root-level]', 'uid' => 0, 'pid' => 0);
127 }
128
129 $this->view->assign('versionSelector', $this->getVersionSelector($this->id, TRUE));
130 if ($this->getBackendUser()->workspace != 0) {
131 // Adding section with the permission setting matrix:
132 $this->addFlashMessage(
133 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser'),
134 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser'),
135 FlashMessage::WARNING
136 );
137 }
138
139 // depth options
140 $depthOptions = array();
141 $url = $this->uriBuilder->reset()->setArguments(array(
142 'action' => 'index',
143 'depth' => '__DEPTH__',
144 'id' => $this->id
145 ))->buildBackendUri();
146 foreach (array(1, 2, 3, 4, 10) as $depthLevel) {
147 $depthOptions[$depthLevel] = $depthLevel . ' ' . LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:levels', 'beuser');
148 }
149 $this->view->assign('depthBaseUrl', $url);
150 $this->view->assign('depth', $this->depth);
151 $this->view->assign('depthOptions', $depthOptions);
152
153 // Get usernames and groupnames: The arrays we get in return contains only
154 // 1) users which are members of the groups of the current user,
155 // 2) groups that the current user is member of
156 $beGroupKeys = $this->getBackendUser()->userGroupsUID;
157 $beUserArray = BackendUtility::getUserNames();
158 if (!$this->getBackendUser()->isAdmin()) {
159 $beUserArray = BackendUtility::blindUserNames($beUserArray, $beGroupKeys, 0);
160 }
161 $beGroupArray = BackendUtility::getGroupNames();
162 if (!$this->getBackendUser()->isAdmin()) {
163 $beGroupArray = BackendUtility::blindGroupNames($beGroupArray, $beGroupKeys, 0);
164 }
165
166 /** @var \TYPO3\CMS\Backend\Tree\View\PageTreeView */
167 $tree = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\PageTreeView::class);
168 $tree->init('AND ' . $this->permissionsClause);
169 $tree->addField('perms_user', TRUE);
170 $tree->addField('perms_group', TRUE);
171 $tree->addField('perms_everybody', TRUE);
172 $tree->addField('perms_userid', TRUE);
173 $tree->addField('perms_groupid', TRUE);
174 $tree->addField('hidden');
175 $tree->addField('fe_group');
176 $tree->addField('starttime');
177 $tree->addField('endtime');
178 $tree->addField('editlock');
179
180 // Creating top icon; the current page
181 $html = IconUtility::getSpriteIconForRecord('pages', $this->pageInfo);
182 $tree->tree[] = array('row' => $this->pageInfo, 'HTML' => $html);
183
184 // Create the tree from $this->id:
185 $tree->getTree($this->id, $this->depth, '');
186
187 // Traverse tree:
188 $treeData = array();
189 foreach ($tree->tree as $data) {
190 $viewDataRow = array();
191 $pageId = $data['row']['uid'];
192 $viewData['pageId'] = $pageId;
193
194 // User/Group names:
195 if ($beUserArray[$data['row']['perms_userid']]) {
196 $userName = $beUserArray[$data['row']['perms_userid']]['username'];
197 } else {
198 $userName = ($data['row']['perms_userid'] ? $data['row']['perms_userid'] : '');
199 }
200
201 if ($data['row']['perms_userid'] && !$beUserArray[$data['row']['perms_userid']]) {
202 $userName = PermissionAjaxController::renderOwnername(
203 $pageId,
204 $data['row']['perms_userid'],
205 htmlspecialchars(GeneralUtility::fixed_lgd_cs($userName, 20)),
206 FALSE
207 );
208 } else {
209 $userName = PermissionAjaxController::renderOwnername(
210 $pageId,
211 $data['row']['perms_userid'],
212 htmlspecialchars(GeneralUtility::fixed_lgd_cs($userName, 20))
213 );
214 }
215 $viewDataRow['userName'] = $userName;
216
217 if ($beGroupArray[$data['row']['perms_groupid']]) {
218 $groupName = $beGroupArray[$data['row']['perms_groupid']]['title'];
219 } else {
220 $groupName = $data['row']['perms_groupid'] ? $data['row']['perms_groupid'] : '';
221 }
222
223 if ($data['row']['perms_groupid'] && !$beGroupArray[$data['row']['perms_groupid']]) {
224 $groupName = PermissionAjaxController::renderGroupname(
225 $pageId,
226 $data['row']['perms_groupid'],
227 htmlspecialchars(GeneralUtility::fixed_lgd_cs($groupName, 20)),
228 FALSE
229 );
230 } else {
231 $groupName = PermissionAjaxController::renderGroupname(
232 $pageId, $data['row']['perms_groupid'],
233 htmlspecialchars(GeneralUtility::fixed_lgd_cs($groupName, 20))
234 );
235 }
236 $viewDataRow['groupName'] = $groupName;
237
238 // Seeing if editing of permissions are allowed for that page:
239 $viewData['editPermsAllowed'] = ($data['row']['perms_userid'] == $this->getBackendUser()->user['uid']
240 || $this->getBackendUser()->isAdmin());
241
242 $viewData['html'] = $data['HTML'] . htmlspecialchars(GeneralUtility::fixed_lgd_cs($data['row']['title'], 20));
243 $viewData['id'] = $data['row']['_ORIG_uid'] ? $data['row']['_ORIG_uid'] : $pageId;
244
245 $viewData['userPermissions'] = ($pageId ?
246 PermissionAjaxController::renderPermissions($data['row']['perms_user'], $pageId, 'user') .
247 ' ' . $userName : '');
248 $viewData['groupPermissions'] = ($pageId ?
249 PermissionAjaxController::renderPermissions($data['row']['perms_group'], $pageId, 'group') .
250 ' ' . $groupName : '');
251 $viewData['otherPermissions'] = ($pageId ? ' ' .
252 PermissionAjaxController::renderPermissions($data['row']['perms_everybody'], $pageId, 'everybody') : '');
253
254 $viewData['editLock'] = ($data['row']['editlock']) ? TRUE : FALSE;
255
256 $treeData[] = $viewData;
257 }
258 $this->view->assign('viewTree', $treeData);
259
260 // CSH for permissions setting
261 $this->view->assign('cshItem', BackendUtility::cshItem('xMOD_csh_corebe', 'perm_module', $GLOBALS['BACK_PATH']));
262 }
263 }
264
265 /**
266 * Edit action
267 *
268 * @return void
269 */
270 public function editAction() {
271 $this->view->assign('id', $this->id);
272 $this->view->assign('depth', $this->depth);
273
274 // Checking access:
275 if ($this->checkAccess()) {
276 if ($this->getBackendUser()->isAdmin() && !$this->id) {
277 $this->pageInfo = array('title' => '[root-level]', 'uid' => 0, 'pid' => 0);
278 }
279 if ($this->getBackendUser()->workspace != 0) {
280 // Adding FlashMessage with the permission setting matrix:
281 $this->addFlashMessage(
282 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser'),
283 LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser'),
284 FlashMessage::WARNING
285 );
286 }
287 // Get usernames and groupnames
288 $beGroupArray = BackendUtility::getListGroupNames('title,uid');
289 $beGroupKeys = array_keys($beGroupArray);
290 $beUserArray = BackendUtility::getUserNames();
291 if (!$this->getBackendUser()->isAdmin()) {
292 $beUserArray = BackendUtility::blindUserNames($beUserArray, $beGroupKeys, 1);
293 }
294 $beGroupArrayO = ($beGroupArray = BackendUtility::getGroupNames());
295 if (!$this->getBackendUser()->isAdmin()) {
296 $beGroupArray = BackendUtility::blindGroupNames($beGroupArrayO, $beGroupKeys, 1);
297 }
298
299 // Owner selector:
300 $beUserDataArray = array();
301 $beUserDataArray[0] = '';
302 foreach ($beUserArray as $uid => &$row) {
303 $beUserDataArray[$uid] = $row['username'];
304 }
305 $this->view->assign('currentBeUser', $this->pageInfo['perms_userid']);
306 $this->view->assign('beUserData', $beUserDataArray);
307
308 // Group selector:
309 $beGroupDataArray = array();
310 $beGroupDataArray[0] = '';
311 foreach ($beGroupArray as $uid => $row) {
312 $beGroupDataArray[$uid] = $row['title'];
313 }
314 $this->view->assign('currentBeGroup', $this->pageInfo['perms_groupid']);
315 $this->view->assign('beGroupData', $beGroupDataArray);
316 $this->view->assign('pageInfo', $this->pageInfo);
317 $this->view->assign('returnId', $this->returnId);
318 $this->view->assign('recursiveSelectOptions', $this->getRecursiveSelectOptions());
319 // Adding help text:
320 if ($this->getBackendUser()->uc['helpText']) {
321 $this->view->assign('showHelp', TRUE);
322 }
323 }
324 }
325
326 /**
327 * Update action
328 *
329 * @param array $data
330 * @param array $mirror
331 * @return void
332 */
333 protected function updateAction(array $data, array $mirror) {
334 // Checking access:
335 if ($this->checkAccess()) {
336 if (!empty($data['pages'])) {
337 foreach ($data['pages'] as $pageUid => $properties) {
338 $this->getDatabaseConnection()->exec_UPDATEquery(
339 'pages',
340 'uid = ' . (int)$pageUid,
341 $properties
342 );
343 if (!empty($mirror['pages'][$pageUid])) {
344 $mirrorPages = GeneralUtility::trimExplode(',', $mirror['pages'][$pageUid]);
345 foreach ($mirrorPages as $mirrorPageUid) {
346 $this->getDatabaseConnection()->exec_UPDATEquery(
347 'pages',
348 'uid = ' . (int)$mirrorPageUid,
349 $properties
350 );
351 }
352 }
353 }
354 }
355 }
356 $this->redirect('index', NULL, NULL, array('id' => $this->returnId, 'depth' => $this->depth));
357 }
358
359 /**
360 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
361 */
362 protected function getBackendUser() {
363 return $GLOBALS['BE_USER'];
364 }
365
366 /**
367 * @return DatabaseConnection
368 */
369 protected function getDatabaseConnection() {
370 return $GLOBALS['TYPO3_DB'];
371 }
372
373 /**
374 * Finding tree and offer setting of values recursively.
375 *
376 * @return array
377 */
378 protected function getRecursiveSelectOptions() {
379 // Initialize tree object:
380 $tree = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\PageTreeView::class);
381 $tree->init('AND ' . $this->permissionsClause);
382 $tree->addField('perms_userid', TRUE);
383 $tree->makeHTML = 0;
384 $tree->setRecs = 1;
385 // Make tree:
386 $tree->getTree($this->id, $this->getLevels, '');
387 $options = array();
388 $options[''] = '';
389 // If there are a hierarchy of page ids, then...
390 if ($this->getBackendUser()->user['uid'] && count($tree->orig_ids_hierarchy)) {
391 // Init:
392 $labelRecursive = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:recursive', 'beuser');
393 $labelLevels = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:levels', 'beuser');
394 $labelPagesAffected = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:pages_affected', 'beuser');
395 $theIdListArr = array();
396 // Traverse the number of levels we want to allow recursive
397 // setting of permissions for:
398 for ($a = $this->getLevels; $a > 0; $a--) {
399 if (is_array($tree->orig_ids_hierarchy[$a])) {
400 foreach ($tree->orig_ids_hierarchy[$a] as $theId) {
401 if ($this->getBackendUser()->isAdmin() || $this->getBackendUser()->user['uid'] == $tree->recs[$theId]['perms_userid']) {
402 $theIdListArr[] = $theId;
403 }
404 }
405 $lKey = $this->getLevels - $a + 1;
406 $options[implode(',', $theIdListArr)] = $labelRecursive . ' ' . $lKey . ' ' . $labelLevels .
407 ' (' . count($theIdListArr) . ' ' . $labelPagesAffected . ')';
408 }
409 }
410 }
411 return $options;
412 }
413
414 /**
415 * Creates the version selector for the page id inputted.
416 * Requires the core version management extension, "version" to be loaded.
417 *
418 * @param int $id Page id to create selector for.
419 * @param bool $noAction If set, there will be no button for swapping page.
420 * @return string
421 */
422 protected function getVersionSelector($id, $noAction = FALSE) {
423 if (
424 ExtensionManagementUtility::isLoaded('version') &&
425 !ExtensionManagementUtility::isLoaded('workspaces')
426 ) {
427 $versionView = GeneralUtility::makeInstance(\TYPO3\CMS\Version\View\VersionView::class);
428 return $versionView->getVersionSelector($id, $noAction);
429 }
430 return '';
431 }
432
433 /**
434 * Check access
435 *
436 * @return bool check access
437 */
438 protected function checkAccess() {
439 $access = is_array($this->pageInfo);
440 // Checking access:
441 if ($this->id && $access || $this->getBackendUser()->isAdmin() && !$this->id) {
442 return TRUE;
443 }
444 return FALSE;
445 }
446 }