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