[TASK] Create own response instance in controller actions
[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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Core\DataHandling\DataHandler;
21 use TYPO3\CMS\Core\Http\HtmlResponse;
22 use TYPO3\CMS\Core\Imaging\Icon;
23 use TYPO3\CMS\Core\Imaging\IconFactory;
24 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Fluid\View\StandaloneView;
27
28 /**
29 * This class extends the permissions module in the TYPO3 Backend to provide
30 * convenient methods of editing of page permissions (including page ownership
31 * (user and group)) via new AjaxRequestHandler facility
32 */
33 class PermissionAjaxController
34 {
35 /**
36 * The local configuration array
37 *
38 * @var array
39 */
40 protected $conf = [];
41
42 /**
43 * @var IconFactory
44 */
45 protected $iconFactory;
46
47 /**
48 * The constructor of this class
49 */
50 public function __construct()
51 {
52 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
53 $this->getLanguageService()->includeLLFile('EXT:lang/Resources/Private/Language/locallang_mod_web_perm.xlf');
54 // Configuration, variable assignment
55 $this->conf['page'] = GeneralUtility::_POST('page');
56 $this->conf['who'] = GeneralUtility::_POST('who');
57 $this->conf['mode'] = GeneralUtility::_POST('mode');
58 $this->conf['bits'] = (int)GeneralUtility::_POST('bits');
59 $this->conf['permissions'] = (int)GeneralUtility::_POST('permissions');
60 $this->conf['action'] = GeneralUtility::_POST('action');
61 $this->conf['ownerUid'] = (int)GeneralUtility::_POST('ownerUid');
62 $this->conf['username'] = GeneralUtility::_POST('username');
63 $this->conf['groupUid'] = (int)GeneralUtility::_POST('groupUid');
64 $this->conf['groupname'] = GeneralUtility::_POST('groupname');
65 $this->conf['editLockState'] = (int)GeneralUtility::_POST('editLockState');
66 $this->conf['new_owner_uid'] = (int)GeneralUtility::_POST('newOwnerUid');
67 $this->conf['new_group_uid'] = (int)GeneralUtility::_POST('newGroupUid');
68 }
69
70 /**
71 * The main dispatcher function. Collect data and prepare HTML output.
72 *
73 * @param ServerRequestInterface $request
74 * @return ResponseInterface
75 */
76 public function dispatch(ServerRequestInterface $request): ResponseInterface
77 {
78 $extPath = ExtensionManagementUtility::extPath('beuser');
79
80 $view = GeneralUtility::makeInstance(StandaloneView::class);
81 $view->setPartialRootPaths(['default' => ExtensionManagementUtility::extPath('beuser') . 'Resources/Private/Partials']);
82 $view->assign('pageId', $this->conf['page']);
83
84 $response = new HtmlResponse('');
85
86 // Basic test for required value
87 if ($this->conf['page'] <= 0) {
88 $response->getBody()->write('This script cannot be called directly');
89 return $response->withStatus(500);
90 }
91
92 $content = '';
93 // Init TCE for execution of update
94 /** @var $tce DataHandler */
95 $tce = GeneralUtility::makeInstance(DataHandler::class);
96 // Determine the scripts to execute
97 switch ($this->conf['action']) {
98 case 'show_change_owner_selector':
99 $content = $this->renderUserSelector($this->conf['page'], $this->conf['ownerUid'], $this->conf['username']);
100 break;
101 case 'change_owner':
102 $userId = $this->conf['new_owner_uid'];
103 if (is_int($userId)) {
104 // Prepare data to change
105 $data = [];
106 $data['pages'][$this->conf['page']]['perms_userid'] = $userId;
107 // Execute TCE Update
108 $tce->start($data, []);
109 $tce->process_datamap();
110
111 $view->setTemplatePathAndFilename($extPath . 'Resources/Private/Templates/PermissionAjax/ChangeOwner.html');
112 $view->assign('userId', $userId);
113 $usernameArray = BackendUtility::getUserNames('username', ' AND uid = ' . $userId);
114 $view->assign('username', $usernameArray[$userId]['username']);
115 $content = $view->render();
116 } else {
117 $response->getBody()->write('An error occurred: No page owner uid specified');
118 $response = $response->withStatus(500);
119 }
120 break;
121 case 'show_change_group_selector':
122 $content = $this->renderGroupSelector($this->conf['page'], $this->conf['groupUid'], $this->conf['groupname']);
123 break;
124 case 'change_group':
125 $groupId = $this->conf['new_group_uid'];
126 if (is_int($groupId)) {
127 // Prepare data to change
128 $data = [];
129 $data['pages'][$this->conf['page']]['perms_groupid'] = $groupId;
130 // Execute TCE Update
131 $tce->start($data, []);
132 $tce->process_datamap();
133
134 $view->setTemplatePathAndFilename($extPath . 'Resources/Private/Templates/PermissionAjax/ChangeGroup.html');
135 $view->assign('groupId', $groupId);
136 $groupnameArray = BackendUtility::getGroupNames('title', ' AND uid = ' . $groupId);
137 $view->assign('groupname', $groupnameArray[$groupId]['title']);
138 $content = $view->render();
139 } else {
140 $response->getBody()->write('An error occurred: No page group uid specified');
141 $response = $response->withStatus(500);
142 }
143 break;
144 case 'toggle_edit_lock':
145 // Prepare data to change
146 $data = [];
147 $data['pages'][$this->conf['page']]['editlock'] = $this->conf['editLockState'] === 1 ? 0 : 1;
148 // Execute TCE Update
149 $tce->start($data, []);
150 $tce->process_datamap();
151 $content = $this->renderToggleEditLock($this->conf['page'], $data['pages'][$this->conf['page']]['editlock']);
152 break;
153 default:
154 if ($this->conf['mode'] === 'delete') {
155 $this->conf['permissions'] = (int)($this->conf['permissions'] - $this->conf['bits']);
156 } else {
157 $this->conf['permissions'] = (int)($this->conf['permissions'] + $this->conf['bits']);
158 }
159 // Prepare data to change
160 $data = [];
161 $data['pages'][$this->conf['page']]['perms_' . $this->conf['who']] = $this->conf['permissions'];
162 // Execute TCE Update
163 $tce->start($data, []);
164 $tce->process_datamap();
165
166 $view->setTemplatePathAndFilename($extPath . 'Resources/Private/Templates/PermissionAjax/ChangePermission.html');
167 $view->assign('permission', $this->conf['permissions']);
168 $view->assign('scope', $this->conf['who']);
169 $content = $view->render();
170 }
171 $response->getBody()->write($content);
172 return $response;
173 }
174
175 /**
176 * Generate the user selector element
177 *
178 * @param int $page The page id to change the user for
179 * @param int $ownerUid The page owner uid
180 * @param string $username The username to display
181 * @return string The html select element
182 */
183 protected function renderUserSelector($page, $ownerUid, $username = '')
184 {
185 $page = (int)$page;
186 $ownerUid = (int)$ownerUid;
187 // Get usernames
188 $beUsers = BackendUtility::getUserNames();
189 // Owner selector:
190 $options = '';
191 // Loop through the users
192 foreach ($beUsers as $uid => $row) {
193 $uid = (int)$uid;
194 $selected = $uid === $ownerUid ? ' selected="selected"' : '';
195 $options .= '<option value="' . $uid . '"' . $selected . '>' . htmlspecialchars($row['username']) . '</option>';
196 }
197 $elementId = 'o_' . $page;
198 $options = '<option value="0"></option>' . $options;
199 $selector = '<select name="new_page_owner" id="new_page_owner">' . $options . '</select>';
200 $saveButton = '<a class="saveowner btn btn-default" data-page="' . $page . '" data-owner="' . $ownerUid
201 . '" data-element-id="' . $elementId . '" title="Change owner">'
202 . $this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL)->render()
203 . '</a>';
204 $cancelButton = '<a class="restoreowner btn btn-default" data-page="' . $page . '" data-owner="' . $ownerUid
205 . '" data-element-id="' . $elementId . '"'
206 . (!empty($username) ? ' data-username="' . htmlspecialchars($username) . '"' : '')
207 . ' title="Cancel">'
208 . $this->iconFactory->getIcon('actions-close', Icon::SIZE_SMALL)->render()
209 . '</a>';
210 return '<span id="' . $elementId . '">'
211 . $selector
212 . '<span class="btn-group">'
213 . $saveButton
214 . $cancelButton
215 . '</span>'
216 . '</span>';
217 }
218
219 /**
220 * Generate the group selector element
221 *
222 * @param int $page The page id to change the user for
223 * @param int $groupUid The page group uid
224 * @param string $groupname The groupname to display
225 * @return string The html select element
226 */
227 protected function renderGroupSelector($page, $groupUid, $groupname = '')
228 {
229 $page = (int)$page;
230 $groupUid = (int)$groupUid;
231
232 // Get group names
233 $beGroupsO = $beGroups = BackendUtility::getGroupNames();
234 // Group selector:
235 $options = '';
236 // flag: is set if the page-groupid equals one from the group-list
237 $userset = 0;
238 // Loop through the groups
239 foreach ($beGroups as $uid => $row) {
240 $uid = (int)$uid;
241 if ($uid === $groupUid) {
242 $userset = 1;
243 $selected = ' selected="selected"';
244 } else {
245 $selected = '';
246 }
247 $options .= '<option value="' . $uid . '"' . $selected . '>' . htmlspecialchars($row['title']) . '</option>';
248 }
249 // If the group was not set AND there is a group for the page
250 if (!$userset && $groupUid) {
251 $options = '<option value="' . $groupUid . '" selected="selected">' .
252 htmlspecialchars($beGroupsO[$groupUid]['title']) . '</option>' . $options;
253 }
254 $elementId = 'g_' . $page;
255 $options = '<option value="0"></option>' . $options;
256 $selector = '<select name="new_page_group" id="new_page_group">' . $options . '</select>';
257 $saveButton = '<a class="savegroup btn btn-default" data-page="' . $page . '" data-group-id="' . $groupUid
258 . '" data-element-id="' . $elementId . '" title="Change group">'
259 . $this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL)->render()
260 . '</a>';
261 $cancelButton = '<a class="restoregroup btn btn-default" data-page="' . $page . '" data-group-id="' . $groupUid
262 . '" data-element-id="' . $elementId . '"'
263 . (!empty($groupname) ? ' data-groupname="' . htmlspecialchars($groupname) . '"' : '')
264 . ' title="Cancel">'
265 . $this->iconFactory->getIcon('actions-close', Icon::SIZE_SMALL)->render()
266 . '</a>';
267 return '<span id="' . $elementId . '">'
268 . $selector
269 . '<span class="btn-group">'
270 . $saveButton
271 . $cancelButton
272 . '</span>'
273 . '</span>';
274 }
275
276 /**
277 * Print the string with the new edit lock state of a page record
278 *
279 * @param int $page The TYPO3 page id
280 * @param string $editLockState The state of the TYPO3 page (locked, unlocked)
281 * @return string The new edit lock string wrapped in HTML
282 */
283 protected function renderToggleEditLock($page, $editLockState)
284 {
285 $page = (int)$page;
286 if ($editLockState === 1) {
287 $ret = '<span id="el_' . $page . '"><a class="editlock btn btn-default" data-page="' . $page
288 . '" data-lockstate="1" title="The page and all content is locked for editing by all non-Admin users.">'
289 . $this->iconFactory->getIcon('actions-lock', Icon::SIZE_SMALL)->render() . '</a></span>';
290 } else {
291 $ret = '<span id="el_' . $page . '"><a class="editlock btn btn-default" data-page="' . $page .
292 '" data-lockstate="0" title="Enable the &raquo;Admin-only&laquo; edit lock for this page">'
293 . $this->iconFactory->getIcon('actions-unlock', Icon::SIZE_SMALL)->render() . '</a></span>';
294 }
295 return $ret;
296 }
297
298 /**
299 * @return \TYPO3\CMS\Core\Localization\LanguageService
300 */
301 protected function getLanguageService()
302 {
303 return $GLOBALS['LANG'];
304 }
305
306 /**
307 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
308 */
309 protected function getBackendUser()
310 {
311 return $GLOBALS['BE_USER'];
312 }
313 }