[FEATURE] Indicate status of permissions by color in EXT:beuser
[Packages/TYPO3.CMS.git] / typo3 / sysext / beuser / Classes / Controller / PermissionAjaxController.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\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Http\AjaxRequestHandler;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * This class extends the permissions module in the TYPO3 Backend to provide
24 * convenient methods of editing of page permissions (including page ownership
25 * (user and group)) via new AjaxRequestHandler facility
26 */
27 class PermissionAjaxController {
28
29 /**
30 * The local configuration array
31 *
32 * @var array
33 */
34 protected $conf = array();
35
36 /**
37 * The constructor of this class
38 */
39 public function __construct() {
40 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_mod_web_perm.xlf');
41 // Configuration, variable assignment
42 $this->conf['page'] = GeneralUtility::_POST('page');
43 $this->conf['who'] = GeneralUtility::_POST('who');
44 $this->conf['mode'] = GeneralUtility::_POST('mode');
45 $this->conf['bits'] = (int)GeneralUtility::_POST('bits');
46 $this->conf['permissions'] = (int)GeneralUtility::_POST('permissions');
47 $this->conf['action'] = GeneralUtility::_POST('action');
48 $this->conf['ownerUid'] = (int)GeneralUtility::_POST('ownerUid');
49 $this->conf['username'] = GeneralUtility::_POST('username');
50 $this->conf['groupUid'] = (int)GeneralUtility::_POST('groupUid');
51 $this->conf['groupname'] = GeneralUtility::_POST('groupname');
52 $this->conf['editLockState'] = (int)GeneralUtility::_POST('editLockState');
53 // User: Replace some parts of the posted values
54 $this->conf['new_owner_uid'] = (int)GeneralUtility::_POST('newOwnerUid');
55 $temp_owner_data = BackendUtility::getUserNames('username, uid', ' AND uid = ' . $this->conf['new_owner_uid']);
56 $this->conf['new_owner_username'] = htmlspecialchars($temp_owner_data[$this->conf['new_owner_uid']]['username']);
57 // Group: Replace some parts of the posted values
58 $this->conf['new_group_uid'] = (int)GeneralUtility::_POST('newGroupUid');
59 $temp_group_data = BackendUtility::getGroupNames('title,uid', ' AND uid = ' . $this->conf['new_group_uid']);
60 $this->conf['new_group_username'] = htmlspecialchars($temp_group_data[$this->conf['new_group_uid']]['title']);
61 }
62
63 /**
64 * The main dispatcher function. Collect data and prepare HTML output.
65 *
66 * @param array $params array of parameters from the AJAX interface, currently unused
67 * @param AjaxRequestHandler $ajaxObj object of type AjaxRequestHandler
68 * @return void
69 */
70 public function dispatch($params = array(), AjaxRequestHandler $ajaxObj = NULL) {
71 $content = '';
72 // Basic test for required value
73 if ($this->conf['page'] > 0) {
74 // Init TCE for execution of update
75 /** @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */
76 $tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
77 $tce->stripslashes_values = 1;
78 // Determine the scripts to execute
79 switch ($this->conf['action']) {
80 case 'show_change_owner_selector':
81 $content = $this->renderUserSelector($this->conf['page'], $this->conf['ownerUid'], $this->conf['username']);
82 break;
83 case 'change_owner':
84 if (is_int($this->conf['new_owner_uid'])) {
85 // Prepare data to change
86 $data = array();
87 $data['pages'][$this->conf['page']]['perms_userid'] = $this->conf['new_owner_uid'];
88 // Execute TCE Update
89 $tce->start($data, array());
90 $tce->process_datamap();
91 $content = self::renderOwnername($this->conf['page'], $this->conf['new_owner_uid'], $this->conf['new_owner_username']);
92 } else {
93 $ajaxObj->setError('An error occurred: No page owner uid specified.');
94 }
95 break;
96 case 'show_change_group_selector':
97 $content = $this->renderGroupSelector($this->conf['page'], $this->conf['groupUid'], $this->conf['groupname']);
98 break;
99 case 'change_group':
100 if (is_int($this->conf['new_group_uid'])) {
101 // Prepare data to change
102 $data = array();
103 $data['pages'][$this->conf['page']]['perms_groupid'] = $this->conf['new_group_uid'];
104 // Execute TCE Update
105 $tce->start($data, array());
106 $tce->process_datamap();
107 $content = self::renderGroupname($this->conf['page'], $this->conf['new_group_uid'], $this->conf['new_group_username']);
108 } else {
109 $ajaxObj->setError('An error occurred: No page group uid specified.');
110 }
111 break;
112 case 'toggle_edit_lock':
113 // Prepare data to change
114 $data = array();
115 $data['pages'][$this->conf['page']]['editlock'] = $this->conf['editLockState'] === 1 ? 0 : 1;
116 // Execute TCE Update
117 $tce->start($data, array());
118 $tce->process_datamap();
119 $content = $this->renderToggleEditLock($this->conf['page'], $data['pages'][$this->conf['page']]['editlock']);
120 break;
121 default:
122 if ($this->conf['mode'] === 'delete') {
123 $this->conf['permissions'] = (int)($this->conf['permissions'] - $this->conf['bits']);
124 } else {
125 $this->conf['permissions'] = (int)($this->conf['permissions'] + $this->conf['bits']);
126 }
127 // Prepare data to change
128 $data = array();
129 $data['pages'][$this->conf['page']]['perms_' . $this->conf['who']] = $this->conf['permissions'];
130 // Execute TCE Update
131 $tce->start($data, array());
132 $tce->process_datamap();
133 $content = self::renderPermissions($this->conf['permissions'], $this->conf['page'], $this->conf['who']);
134 }
135 } else {
136 $ajaxObj->setError('This script cannot be called directly.');
137 }
138 $ajaxObj->addContent($this->conf['page'] . '_' . $this->conf['who'], $content);
139 }
140
141 /**
142 * Generate the user selector element
143 *
144 * @param int $page The page id to change the user for
145 * @param int $ownerUid The page owner uid
146 * @param string $username The username to display
147 * @return string The html select element
148 */
149 protected function renderUserSelector($page, $ownerUid, $username = '') {
150 // Get usernames
151 $beUsers = BackendUtility::getUserNames();
152 // Init groupArray
153 $groups = array();
154 if (!$GLOBALS['BE_USER']->isAdmin()) {
155 $beUsers = BackendUtility::blindUserNames($beUsers, $groups, 1);
156 }
157 // Owner selector:
158 $options = '';
159 // Loop through the users
160 foreach ($beUsers as $uid => $row) {
161 $selected = $uid == $ownerUid ? ' selected="selected"' : '';
162 $options .= '<option value="' . $uid . '"' . $selected . '>' . htmlspecialchars($row['username']) . '</option>';
163 }
164 $elementId = 'o_' . $page;
165 $options = '<option value="0"></option>' . $options;
166 $selector = '<select name="new_page_owner" id="new_page_owner">' . $options . '</select>';
167 $saveButton = '<a class="saveowner" data-page="' . $page . '" data-owner="' . $ownerUid . '" data-element-id="' . $elementId . '" title="Change owner">' . IconUtility::getSpriteIcon('actions-document-save') . '</a>';
168 $cancelButton = '<a class="restoreowner" data-page="' . $page . '" data-owner="' . $ownerUid . '" data-element-id="' . $elementId . '"' . (!empty($username) ? ' data-username="' . htmlspecialchars($username) . '"' : '') . ' title="Cancel">' . IconUtility::getSpriteIcon('actions-document-close') . '</a>';
169 return '<span id="' . $elementId . '">' . $selector . $saveButton . $cancelButton . '</span>';
170 }
171
172 /**
173 * Generate the group selector element
174 *
175 * @param int $page The page id to change the user for
176 * @param int $groupUid The page group uid
177 * @param string $username The username to display
178 * @return string The html select element
179 */
180 protected function renderGroupSelector($page, $groupUid, $groupname = '') {
181 // Get usernames
182 $beGroups = BackendUtility::getListGroupNames('title,uid');
183 $beGroupKeys = array_keys($beGroups);
184 $beGroupsO = ($beGroups = BackendUtility::getGroupNames());
185 if (!$this->getBackendUser()->isAdmin()) {
186 $beGroups = BackendUtility::blindGroupNames($beGroupsO, $beGroupKeys, 1);
187 }
188 // Group selector:
189 $options = '';
190 // flag: is set if the page-groupid equals one from the group-list
191 $userset = 0;
192 // Loop through the groups
193 foreach ($beGroups as $uid => $row) {
194 if ($uid == $groupUid) {
195 $userset = 1;
196 $selected = ' selected="selected"';
197 } else {
198 $selected = '';
199 }
200 $options .= '<option value="' . $uid . '"' . $selected . '>' . htmlspecialchars($row['title']) . '</option>';
201 }
202 // If the group was not set AND there is a group for the page
203 if (!$userset && $groupUid) {
204 $options = '<option value="' . $groupUid . '" selected="selected">' .
205 htmlspecialchars($beGroupsO[$groupUid]['title']) . '</option>' . $options;
206 }
207 $elementId = 'g_' . $page;
208 $options = '<option value="0"></option>' . $options;
209 $selector = '<select name="new_page_group" id="new_page_group">' . $options . '</select>';
210 $saveButton = '<a class="savegroup" data-page="' . $page . '" data-group="' . $groupUid . '" data-element-id="' . $elementId . '" title="Change group">' . IconUtility::getSpriteIcon('actions-document-save') . '</a>';
211 $cancelButton = '<a class="restoregroup" data-page="' . $page . '" data-group="' . $groupUid . '" data-element-id="' . $elementId . '"' . (!empty($groupname) ? ' data-groupname="' . htmlspecialchars($groupname) . '"' : '') . ' title="Cancel">' . IconUtility::getSpriteIcon('actions-document-close') . '</a>';
212 return '<span id="' . $elementId . '">' . $selector . $saveButton . $cancelButton . '</span>';
213 }
214
215 /**
216 * Print the string with the new owner of a page record
217 *
218 * @param int $page The TYPO3 page id
219 * @param int $ownerUid The new page user uid
220 * @param string $username The TYPO3 BE username (used to display in the element)
221 * @param bool $validUser Must be set to FALSE, if the user has no name or is deleted
222 * @return string The new group wrapped in HTML
223 */
224 static public function renderOwnername($page, $ownerUid, $username, $validUser = TRUE) {
225 $elementId = 'o_' . $page;
226 return '<span id="' . $elementId . '"><a class="ug_selector changeowner" data-page="' . $page . '" data-owner="' . $ownerUid . '" data-username="' . htmlspecialchars($username) . '">' . ($validUser ? ($username == '' ? '<span class=not_set>[' . $GLOBALS['LANG']->getLL('notSet') . ']</span>' : htmlspecialchars(GeneralUtility::fixed_lgd_cs($username, 20))) : '<span class=not_set title="' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($username, 20)) . '">[' . $GLOBALS['LANG']->getLL('deleted') . ']</span>') . '</a></span>';
227 }
228
229 /**
230 * Print the string with the new group of a page record
231 *
232 * @param int $page The TYPO3 page id
233 * @param int $groupUid The new page group uid
234 * @param string $groupname The TYPO3 BE groupname (used to display in the element)
235 * @param bool $validGroup Must be set to FALSE, if the group has no name or is deleted
236 * @return string The new group wrapped in HTML
237 */
238 static public function renderGroupname($page, $groupUid, $groupname, $validGroup = TRUE) {
239 $elementId = 'g_' . $page;
240 return '<span id="' . $elementId . '"><a class="ug_selector changegroup" data-page="' . $page . '" data-group="' . $groupUid . '" data-groupname="' . htmlspecialchars($groupname) . '">' . ($validGroup ? ($groupname == '' ? '<span class=not_set>[' . $GLOBALS['LANG']->getLL('notSet') . ']</span>' : htmlspecialchars(GeneralUtility::fixed_lgd_cs($groupname, 20))) : '<span class=not_set title="' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($groupname, 20)) . '">[' . $GLOBALS['LANG']->getLL('deleted') . ']</span>') . '</a></span>';
241 }
242
243 /**
244 * Print the string with the new edit lock state of a page record
245 *
246 * @param int $page The TYPO3 page id
247 * @param string $editlockstate The state of the TYPO3 page (locked, unlocked)
248 * @return string The new edit lock string wrapped in HTML
249 */
250 protected function renderToggleEditLock($page, $editLockState) {
251 if ($editLockState === 1) {
252 $ret = '<span id="el_' . $page . '"><a class="editlock" data-page="' . (int)$page . '" data-lockstate="1" title="The page and all content is locked for editing by all non-Admin users.">' . IconUtility::getSpriteIcon('status-warning-lock') . '</a></span>';
253 } else {
254 $ret = '<span id="el_' . $page . '"><a class="editlock" data-page="' . (int)$page . '" data-lockstate="0" title="Enable the &raquo;Admin-only&laquo; edit lock for this page">[+]</a></span>';
255 }
256 return $ret;
257 }
258
259 /**
260 * Print a set of permissions. Also used in index.php
261 *
262 * @param int $int Permission integer (bits)
263 * @param int $page The TYPO3 page id
264 * @param string $who The scope (user, group or everybody)
265 * @return string HTML marked up x/* indications.
266 */
267 static public function renderPermissions($int, $pageId = 0, $who = 'user') {
268 $str = '';
269 $permissions = array(1, 16, 2, 4, 8);
270 foreach ($permissions as $permission) {
271 if ($int & $permission) {
272 $str .= IconUtility::getSpriteIcon('status-status-permission-granted', array(
273 'title' => $GLOBALS['LANG']->getLL($permission, TRUE),
274 'class' => 'change-permission text-success',
275 'data-page' => $pageId,
276 'data-permissions' => $int,
277 'data-mode' => 'delete',
278 'data-who' => $who,
279 'data-bits' => $permission,
280 'style' => 'cursor:pointer'
281 ));
282 } else {
283 $str .= IconUtility::getSpriteIcon('status-status-permission-denied', array(
284 'title' => $GLOBALS['LANG']->getLL($permission, TRUE),
285 'class' => 'change-permission text-danger',
286 'data-page' => $pageId,
287 'data-permissions' => $int,
288 'data-mode' => 'add',
289 'data-who' => $who,
290 'data-bits' => $permission,
291 'style' => 'cursor:pointer'
292 ));
293 }
294 }
295 return '<span id="' . $pageId . '_' . $who . '">' . $str . '</span>';
296 }
297
298 /**
299 * @return \TYPO3\CMS\Lang\LanguageService
300 */
301 protected function getLanguageService() {
302 return $GLOBALS['LANG'];
303 }
304
305 /**
306 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
307 */
308 protected function getBackendUser() {
309 return $GLOBALS['BE_USER'];
310 }
311
312 }