[TASK] Replace sprite icon "actions-document-new" with the new IconFactory
[Packages/TYPO3.CMS.git] / typo3 / sysext / sys_action / Classes / ActionTask.php
1 <?php
2 namespace TYPO3\CMS\SysAction;
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\Core\Imaging\Icon;
18 use TYPO3\CMS\Core\Imaging\IconFactory;
19 use TYPO3\CMS\Core\Page\PageRenderer;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Backend\Utility\BackendUtility;
22
23 /**
24 * This class provides a task for the taskcenter
25 */
26 class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
27
28 /**
29 * @var \TYPO3\CMS\Taskcenter\Controller\TaskModuleController
30 */
31 protected $taskObject;
32
33 /**
34 * All hook objects get registered here for later use
35 *
36 * @var array
37 */
38 protected $hookObjects = array();
39
40 /**
41 * URL to task module
42 *
43 * @var string
44 */
45 protected $moduleUrl;
46
47 /**
48 * @var IconFactory
49 */
50 protected $iconFactory;
51
52 /**
53 * Constructor
54 */
55 public function __construct(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController $taskObject) {
56 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
57 $this->moduleUrl = BackendUtility::getModuleUrl('user_task');
58 $this->taskObject = $taskObject;
59 $this->getLanguageService()->includeLLFile('EXT:sys_action/Resources/Private/Language/locallang.xlf');
60 if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['sys_action']['tx_sysaction_task'])) {
61 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['sys_action']['tx_sysaction_task'] as $classRef) {
62 $this->hookObjects[] = GeneralUtility::getUserObj($classRef);
63 }
64 }
65 }
66
67 /**
68 * This method renders the task
69 *
70 * @return string The task as HTML
71 */
72 public function getTask() {
73 $content = '';
74 $show = (int)GeneralUtility::_GP('show');
75 foreach ($this->hookObjects as $hookObject) {
76 if (method_exists($hookObject, 'getTask')) {
77 $show = $hookObject->getTask($show, $this);
78 }
79 }
80 // If no task selected, render the menu
81 if ($show == 0) {
82 $content .= $this->taskObject->description($this->getLanguageService()->getLL('sys_action'), $this->getLanguageService()->getLL('description'));
83 $content .= $this->renderActionList();
84 } else {
85 $record = BackendUtility::getRecord('sys_action', $show);
86 // If the action is not found
87 if (empty($record)) {
88 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_error-not-found', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
89 $content .= $flashMessage->render();
90 } else {
91 // Render the task
92 $content .= $this->taskObject->description($record['title'], $record['description']);
93 // Output depends on the type
94 switch ($record['type']) {
95 case 1:
96 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
97 $pageRenderer->loadRequireJsModule('TYPO3/CMS/SysAction/ActionTask');
98 $content .= $this->viewNewBackendUser($record);
99 break;
100 case 2:
101 $content .= $this->viewSqlQuery($record);
102 break;
103 case 3:
104 $content .= $this->viewRecordList($record);
105 break;
106 case 4:
107 $content .= $this->viewEditRecord($record);
108 break;
109 case 5:
110 $content .= $this->viewNewRecord($record);
111 break;
112 default:
113 $flashMessage = GeneralUtility::makeInstance(
114 \TYPO3\CMS\Core\Messaging\FlashMessage::class,
115 $this->getLanguageService()->getLL('action_noType', TRUE),
116 $this->getLanguageService()->getLL('action_error'),
117 \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
118 );
119 $content .= '<br />' . $flashMessage->render();
120 }
121 }
122 }
123 return $content;
124 }
125
126 /**
127 * General overview over the task in the taskcenter menu
128 *
129 * @return string Overview as HTML
130 */
131 public function getOverview() {
132 $content = '<p>' . $this->getLanguageService()->getLL('description') . '</p>';
133 // Get the actions
134 $actionList = $this->getActions();
135 if (!empty($actionList)) {
136 $items = '';
137 // Render a single action menu item
138 foreach ($actionList as $action) {
139 $active = GeneralUtility::_GP('show') === $action['uid'] ? ' class="active" ' : '';
140 $items .= '<li' . $active . '>
141 <a href="' . $action['link'] . '" title="' . htmlspecialchars($action['description']) . '">' . htmlspecialchars($action['title']) . '</a>
142 </li>';
143 }
144 $content .= '<ul>' . $items . '</ul>';
145 }
146 return $content;
147 }
148
149 /**
150 * Get all actions of an user. Admins can see any action, all others only those
151 * which are allowed in sys_action record itself.
152 *
153 * @return array Array holding every needed information of a sys_action
154 */
155 protected function getActions() {
156 $actionList = array();
157 // admins can see any record
158 if ($this->getBackendUser()->isAdmin()) {
159 $res = $this->getDatabaseConnection()->exec_SELECTquery('*', 'sys_action', '', '', 'sys_action.sorting');
160 } else {
161 // Editors can only see the actions which are assigned to a usergroup they belong to
162 $additionalWhere = 'be_groups.uid IN (' . ($this->getBackendUser()->groupList ?: 0) . ')';
163 $res = $this->getDatabaseConnection()->exec_SELECT_mm_query('sys_action.*', 'sys_action', 'sys_action_asgr_mm', 'be_groups', ' AND sys_action.hidden=0 AND ' . $additionalWhere, 'sys_action.uid', 'sys_action.sorting');
164 }
165 while ($actionRow = $this->getDatabaseConnection()->sql_fetch_assoc($res)) {
166 $editActionLink = '';
167 // Admins are allowed to edit sys_action records
168 if ($this->getBackendUser()->isAdmin()) {
169 $link = BackendUtility::getModuleUrl(
170 'record_edit',
171 array(
172 'edit[sys_action][' . $actionRow['uid'] . ']' => 'edit',
173 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
174 ),
175 FALSE,
176 TRUE
177 );
178 $editActionLink = '<a class="edit" href="' . $link . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-info', array('title' => $this->getLanguageService()->getLL('edit-sys_action'))) . $this->getLanguageService()->getLL('edit-sys_action') . '</a>';
179 }
180 $actionList[] = array(
181 'uid' => $actionRow['uid'],
182 'title' => $actionRow['title'],
183 'description' => $actionRow['description'],
184 'descriptionHtml' => nl2br(htmlspecialchars($actionRow['description'])) . $editActionLink,
185 'link' => $this->moduleUrl . '&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . $actionRow['uid']
186 );
187 }
188 $this->getDatabaseConnection()->sql_free_result($res);
189 return $actionList;
190 }
191
192 /**
193 * Render the menu of sys_actions
194 *
195 * @return string List of sys_actions as HTML
196 */
197 protected function renderActionList() {
198 $content = '';
199 // Get the sys_action records
200 $actionList = $this->getActions();
201 // If any actions are found for the current users
202 if (!empty($actionList)) {
203 $content .= $this->taskObject->renderListMenu($actionList);
204 } else {
205 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_not-found-description', TRUE), $this->getLanguageService()->getLL('action_not-found'), \TYPO3\CMS\Core\Messaging\FlashMessage::INFO);
206 $content .= $flashMessage->render();
207 }
208 // Admin users can create a new action
209 if ($this->getBackendUser()->isAdmin()) {
210 $link = BackendUtility::getModuleUrl(
211 'record_edit',
212 array(
213 'edit[sys_action][0]' => 'new',
214 'returnUrl' => $this->moduleUrl
215 ),
216 FALSE,
217 TRUE
218 );
219 $content .= '<p>' .
220 '<a href="' . $link . '" title="' . $this->getLanguageService()->getLL('new-sys_action') . '">' .
221 $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL) .
222 $this->getLanguageService()->getLL('new-sys_action') .
223 '</a></p>';
224 }
225 return $content;
226 }
227
228 /**
229 * Action to create a new BE user
230 *
231 * @param array $record sys_action record
232 * @return string form to create a new user
233 */
234 protected function viewNewBackendUser($record) {
235 $content = '';
236 $beRec = BackendUtility::getRecord('be_users', (int)$record['t1_copy_of_user']);
237 // A record is need which is used as copy for the new user
238 if (!is_array($beRec)) {
239 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_notReady', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
240 $content .= $flashMessage->render();
241 return $content;
242 }
243 $vars = GeneralUtility::_POST('data');
244 $key = 'NEW';
245 if ($vars['sent'] == 1) {
246 $errors = array();
247 // Basic error checks
248 if (!empty($vars['email']) && !GeneralUtility::validEmail($vars['email'])) {
249 $errors[] = $this->getLanguageService()->getLL('error-wrong-email');
250 }
251 if (empty($vars['username'])) {
252 $errors[] = $this->getLanguageService()->getLL('error-username-empty');
253 }
254 if ($vars['key'] === 'NEW' && empty($vars['password'])) {
255 $errors[] = $this->getLanguageService()->getLL('error-password-empty');
256 }
257 if ($vars['key'] !== 'NEW' && !$this->isCreatedByUser($vars['key'], $record)) {
258 $errors[] = $this->getLanguageService()->getLL('error-wrong-user');
259 }
260 foreach ($this->hookObjects as $hookObject) {
261 if (method_exists($hookObject, 'viewNewBackendUser_Error')) {
262 $errors = $hookObject->viewNewBackendUser_Error($vars, $errors, $this);
263 }
264 }
265 // Show errors if there are any
266 if (!empty($errors)) {
267 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, implode('<br />', $errors), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
268 $content .= $flashMessage->render() . '<br />';
269 } else {
270 // Save user
271 $key = $this->saveNewBackendUser($record, $vars);
272 // Success message
273 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $vars['key'] === 'NEW' ? $this->getLanguageService()->getLL('success-user-created') : $this->getLanguageService()->getLL('success-user-updated'), $this->getLanguageService()->getLL('success'), \TYPO3\CMS\Core\Messaging\FlashMessage::OK);
274 $content .= $flashMessage->render() . '<br />';
275 }
276 }
277 // Load BE user to edit
278 if ((int)GeneralUtility::_GP('be_users_uid') > 0) {
279 $tmpUserId = (int)GeneralUtility::_GP('be_users_uid');
280 // Check if the selected user is created by the current user
281 $rawRecord = $this->isCreatedByUser($tmpUserId, $record);
282 if ($rawRecord) {
283 // Delete user
284 if (GeneralUtility::_GP('delete') == 1) {
285 $this->deleteUser($tmpUserId, $record['uid']);
286 }
287 $key = $tmpUserId;
288 $vars = $rawRecord;
289 }
290 }
291 $content .= '<form action="" method="post" enctype="multipart/form-data">
292 <fieldset class="fields">
293 <legend>' . $this->getLanguageService()->getLL('action_t1_legend_generalFields') . '</legend>
294 <div class="row">
295 <label for="field_disable">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_general.xlf:LGL.disable') . '</label>
296 <input type="checkbox" id="field_disable" name="data[disable]" value="1" class="checkbox" ' . ($vars['disable'] == 1 ? ' checked="checked" ' : '') . ' />
297 </div>
298 <div class="row">
299 <label for="field_realname">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_general.xlf:LGL.name') . '</label>
300 <input type="text" id="field_realname" name="data[realName]" value="' . htmlspecialchars($vars['realName']) . '" />
301 </div>
302 <div class="row">
303 <label for="field_username">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_tca.xlf:be_users.username') . '</label>
304 <input type="text" id="field_username" name="data[username]" value="' . htmlspecialchars($vars['username']) . '" />
305 </div>
306 <div class="row">
307 <label for="field_password">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_tca.xlf:be_users.password') . '</label>
308 <input type="password" id="field_password" name="data[password]" value="" />
309 </div>
310 <div class="row">
311 <label for="field_email">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_general.xlf:LGL.email') . '</label>
312 <input type="text" id="field_email" name="data[email]" value="' . htmlspecialchars($vars['email']) . '" />
313 </div>
314 </fieldset>
315 <fieldset class="fields">
316 <legend>' . $this->getLanguageService()->getLL('action_t1_legend_configuration') . '</legend>
317
318 <div class="row">
319 <label for="field_usergroup">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_tca.xlf:be_users.usergroup') . '</label>
320 <select id="field_usergroup" name="data[usergroup][]" multiple="multiple">
321 ' . $this->getUsergroups($record, $vars) . '
322 </select>
323 </div>
324 <div class="row">
325 <input type="hidden" name="data[key]" value="' . $key . '" />
326 <input type="hidden" name="data[sent]" value="1" />
327 <input class="btn btn-default" type="submit" value="' . ($key === 'NEW' ? $this->getLanguageService()->getLL('action_Create') : $this->getLanguageService()->getLL('action_Update')) . '" />
328 </div>
329 </fieldset>
330 </form>';
331 $content .= $this->getCreatedUsers($record, $key);
332 return $content;
333 }
334
335 /**
336 * Delete a BE user and redirect to the action by its id
337 *
338 * @param int $userId Id of the BE user
339 * @param int $actionId Id of the action
340 * @return void
341 */
342 protected function deleteUser($userId, $actionId) {
343 $this->getDatabaseConnection()->exec_UPDATEquery('be_users', 'uid=' . $userId, array(
344 'deleted' => 1,
345 'tstamp' => $GLOBALS['ACCESS_TIME']
346 ));
347 // redirect to the original task
348 $redirectUrl = $this->moduleUrl . '&show=' . $actionId;
349 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($redirectUrl);
350 }
351
352 /**
353 * Check if a BE user is created by the current user
354 *
355 * @param int $id Id of the BE user
356 * @param array $action sys_action record.
357 * @return mixed The record of the BE user if found, otherwise FALSE
358 */
359 protected function isCreatedByUser($id, $action) {
360 $record = BackendUtility::getRecord('be_users', $id, '*', ' AND cruser_id=' . $this->getBackendUser()->user['uid'] . ' AND createdByAction=' . $action['uid']);
361 if (is_array($record)) {
362 return $record;
363 } else {
364 return FALSE;
365 }
366 }
367
368 /**
369 * Render all users who are created by the current BE user including a link to edit the record
370 *
371 * @param array $action sys_action record.
372 * @param int $selectedUser Id of a selected user
373 * @return string html list of users
374 */
375 protected function getCreatedUsers($action, $selectedUser) {
376 $content = '';
377 $userList = array();
378 // List of users
379 $res = $this->getDatabaseConnection()->exec_SELECTquery('*', 'be_users', 'cruser_id=' . $this->getBackendUser()->user['uid'] . ' AND createdByAction=' . (int)$action['uid'] . BackendUtility::deleteClause('be_users'), '', 'username');
380 // Render the user records
381 while ($row = $this->getDatabaseConnection()->sql_fetch_assoc($res)) {
382 $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord('be_users', $row, array('title' => 'uid=' . $row['uid']));
383 $line = $icon . $this->action_linkUserName($row['username'], $row['realName'], $action['uid'], $row['uid']);
384 // Selected user
385 if ($row['uid'] == $selectedUser) {
386 $line = '<strong>' . $line . '</strong>';
387 }
388 $userList[] = $line;
389 }
390 $this->getDatabaseConnection()->sql_free_result($res);
391 // If any records found
392 if (!empty($userList)) {
393 $content .= '<br />' . $this->taskObject->doc->section($this->getLanguageService()->getLL('action_t1_listOfUsers'), implode('<br />', $userList));
394 }
395 return $content;
396 }
397
398 /**
399 * Create a link to edit a user
400 *
401 * @param string $username Username
402 * @param string $realName Real name of the user
403 * @param int $sysActionUid Id of the sys_action record
404 * @param int $userId Id of the user
405 * @return string html link
406 */
407 protected function action_linkUserName($username, $realName, $sysActionUid, $userId) {
408 if (!empty($realName)) {
409 $username .= ' (' . $realName . ')';
410 }
411 // Link to update the user record
412 $href = $this->moduleUrl . '&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . (int)$sysActionUid . '&be_users_uid=' . (int)$userId;
413 $link = '<a href="' . htmlspecialchars($href) . '">' . htmlspecialchars($username) . '</a>';
414 // Link to delete the user record
415 $link .= '
416 <a href="' . htmlspecialchars(($href . '&delete=1')) . '" class="t3js-confirm-trigger" data-title="' . $this->getLanguageService()->getLL('lDelete_warning_title', TRUE) . '" data-message="' . $this->getLanguageService()->getLL('lDelete_warning', TRUE) . '">'
417 . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-delete') .
418 '</a>';
419 return $link;
420 }
421
422 /**
423 * Save/Update a BE user
424 *
425 * @param array $record Current action record
426 * @param array $vars POST vars
427 * @return int Id of the new/updated user
428 */
429 protected function saveNewBackendUser($record, $vars) {
430 // Check if the db mount is a page the current user is allowed to.);
431 $vars['db_mountpoints'] = $this->fixDbMount($vars['db_mountpoints']);
432 // Check if the usergroup is allowed
433 $vars['usergroup'] = $this->fixUserGroup($vars['usergroup'], $record);
434 $key = $vars['key'];
435 $vars['password'] = trim($vars['password']);
436 // Check if md5 is used as password encryption
437 if ($vars['password'] !== '' && strpos($GLOBALS['TCA']['be_users']['columns']['password']['config']['eval'], 'md5') !== FALSE) {
438 $vars['password'] = md5($vars['password']);
439 }
440 $data = '';
441 $newUserId = 0;
442 if ($key === 'NEW') {
443 $beRec = BackendUtility::getRecord('be_users', (int)$record['t1_copy_of_user']);
444 if (is_array($beRec)) {
445 $data = array();
446 $data['be_users'][$key] = $beRec;
447 $data['be_users'][$key]['username'] = $this->fixUsername($vars['username'], $record['t1_userprefix']);
448 $data['be_users'][$key]['password'] = $vars['password'];
449 $data['be_users'][$key]['realName'] = $vars['realName'];
450 $data['be_users'][$key]['email'] = $vars['email'];
451 $data['be_users'][$key]['disable'] = (int)$vars['disable'];
452 $data['be_users'][$key]['admin'] = 0;
453 $data['be_users'][$key]['usergroup'] = $vars['usergroup'];
454 $data['be_users'][$key]['db_mountpoints'] = $vars['db_mountpoints'];
455 $data['be_users'][$key]['createdByAction'] = $record['uid'];
456 }
457 } else {
458 // Check ownership
459 $beRec = BackendUtility::getRecord('be_users', (int)$key);
460 if (is_array($beRec) && $beRec['cruser_id'] == $this->getBackendUser()->user['uid']) {
461 $data = array();
462 $data['be_users'][$key]['username'] = $this->fixUsername($vars['username'], $record['t1_userprefix']);
463 if ($vars['password'] !== '') {
464 $data['be_users'][$key]['password'] = $vars['password'];
465 }
466 $data['be_users'][$key]['realName'] = $vars['realName'];
467 $data['be_users'][$key]['email'] = $vars['email'];
468 $data['be_users'][$key]['disable'] = (int)$vars['disable'];
469 $data['be_users'][$key]['admin'] = 0;
470 $data['be_users'][$key]['usergroup'] = $vars['usergroup'];
471 $data['be_users'][$key]['db_mountpoints'] = $vars['db_mountpoints'];
472 $newUserId = $key;
473 }
474 }
475 // Save/update user by using TCEmain
476 if (is_array($data)) {
477 $tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
478 $tce->stripslashes_values = 0;
479 $tce->start($data, array(), $this->getBackendUser());
480 $tce->admin = 1;
481 $tce->process_datamap();
482 $newUserId = (int)$tce->substNEWwithIDs['NEW'];
483 if ($newUserId) {
484 // Create
485 $this->action_createDir($newUserId);
486 } else {
487 // Update
488 $newUserId = (int)$key;
489 }
490 unset($tce);
491 }
492 return $newUserId;
493 }
494
495 /**
496 * Create the username based on the given username and the prefix
497 *
498 * @param string $username Username
499 * @param string $prefix Prefix
500 * @return string Combined username
501 */
502 protected function fixUsername($username, $prefix) {
503 $prefix = trim($prefix);
504 if (substr($username, 0, strlen($prefix)) === $prefix) {
505 $username = substr($username, strlen($prefix));
506 }
507 return $prefix . $username;
508 }
509
510 /**
511 * Clean the to be applied usergroups from not allowed ones
512 *
513 * @param array $appliedUsergroups Array of to be applied user groups
514 * @param array $actionRecord The action record
515 * @return array Cleaned array
516 */
517 protected function fixUserGroup($appliedUsergroups, $actionRecord) {
518 if (is_array($appliedUsergroups)) {
519 $cleanGroupList = array();
520 // Create an array from the allowed usergroups using the uid as key
521 $allowedUsergroups = array_flip(explode(',', $actionRecord['t1_allowed_groups']));
522 // Walk through the array and check every uid if it is under the allowed ines
523 foreach ($appliedUsergroups as $group) {
524 if (isset($allowedUsergroups[$group])) {
525 $cleanGroupList[] = $group;
526 }
527 }
528 $appliedUsergroups = $cleanGroupList;
529 }
530 return $appliedUsergroups;
531 }
532
533 /**
534 * Clean the to be applied DB-Mounts from not allowed ones
535 *
536 * @param string $appliedDbMounts List of pages like pages_123,pages456
537 * @return string Cleaned list
538 */
539 protected function fixDbMount($appliedDbMounts) {
540 // Admins can see any page, no need to check there
541 if (!empty($appliedDbMounts) && !$this->getBackendUser()->isAdmin()) {
542 $cleanDbMountList = array();
543 $dbMounts = GeneralUtility::trimExplode(',', $appliedDbMounts, TRUE);
544 // Walk through every wanted DB-Mount and check if it allowed for the current user
545 foreach ($dbMounts as $dbMount) {
546 $uid = (int)substr($dbMount, strrpos($dbMount, '_') + 1);
547 $page = BackendUtility::getRecord('pages', $uid);
548 // Check rootline and access rights
549 if ($this->checkRootline($uid) && $this->getBackendUser()->calcPerms($page)) {
550 $cleanDbMountList[] = 'pages_' . $uid;
551 }
552 }
553 // Build the clean list
554 $appliedDbMounts = implode(',', $cleanDbMountList);
555 }
556 return $appliedDbMounts;
557 }
558
559 /**
560 * Check if a page is inside the rootline the current user can see
561 *
562 * @param int $pageId Id of the the page to be checked
563 * @return bool Access to the page
564 */
565 protected function checkRootline($pageId) {
566 $access = FALSE;
567 $dbMounts = array_flip(explode(',', trim($this->getBackendUser()->dataLists['webmount_list'], ',')));
568 $rootline = BackendUtility::BEgetRootLine($pageId);
569 foreach ($rootline as $page) {
570 if (isset($dbMounts[$page['uid']]) && !$access) {
571 $access = TRUE;
572 }
573 }
574 return $access;
575 }
576
577 /**
578 * Create a user directory if defined
579 *
580 * @param int $uid Id of the user record
581 * @return void
582 */
583 protected function action_createDir($uid) {
584 $path = $this->action_getUserMainDir();
585 if ($path) {
586 GeneralUtility::mkdir($path . $uid);
587 GeneralUtility::mkdir($path . $uid . '/_temp_/');
588 }
589 }
590
591 /**
592 * Get the path to the user home directory which is set in the localconf.php
593 *
594 * @return string Path
595 */
596 protected function action_getUserMainDir() {
597 $path = $GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'];
598 // If path is set and a valid directory
599 if ($path && @is_dir($path) && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] && GeneralUtility::isFirstPartOfStr($path, $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath']) && substr($path, -1) == '/') {
600 return $path;
601 }
602 }
603
604 /**
605 * Get all allowed usergroups which can be applied to a user record
606 *
607 * @param array $record sys_action record
608 * @param array $vars Selected be_user record
609 * @return string Rendered user groups
610 */
611 protected function getUsergroups($record, $vars) {
612 $content = '';
613 // Do nothing if no groups are allowed
614 if (empty($record['t1_allowed_groups'])) {
615 return $content;
616 }
617 $content .= '<option value=""></option>';
618 $grList = GeneralUtility::trimExplode(',', $record['t1_allowed_groups'], TRUE);
619 foreach ($grList as $group) {
620 $checkGroup = BackendUtility::getRecord('be_groups', $group);
621 if (is_array($checkGroup)) {
622 $selected = GeneralUtility::inList($vars['usergroup'], $checkGroup['uid']) ? ' selected="selected" ' : '';
623 $content .= '<option ' . $selected . 'value="' . $checkGroup['uid'] . '">' . htmlspecialchars($checkGroup['title']) . '</option>';
624 }
625 }
626 return $content;
627 }
628
629 /**
630 * Action to create a new record
631 *
632 * @param array $record sys_action record
633 * @return void Redirect to form to create a record
634 */
635 protected function viewNewRecord($record) {
636 $link = BackendUtility::getModuleUrl(
637 'record_edit',
638 array(
639 'edit[' . $record['t3_tables'] . '][' . (int)$record['t3_listPid'] . ']' => 'new',
640 'returnUrl' => $this->moduleUrl
641 ),
642 FALSE,
643 TRUE
644 );
645 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($link);
646 }
647
648 /**
649 * Action to edit records
650 *
651 * @param array $record sys_action record
652 * @return string list of records
653 */
654 protected function viewEditRecord($record) {
655 $content = '';
656 $actionList = array();
657 $dbAnalysis = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\RelationHandler::class);
658 $dbAnalysis->setFetchAllFields(TRUE);
659 $dbAnalysis->start($record['t4_recordsToEdit'], '*');
660 $dbAnalysis->getFromDB();
661 // collect the records
662 foreach ($dbAnalysis->itemArray as $el) {
663 $path = BackendUtility::getRecordPath($el['id'], $this->taskObject->perms_clause, $this->getBackendUser()->uc['titleLen']);
664 $record = BackendUtility::getRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']]);
665 $title = BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]);
666 $description = $this->getLanguageService()->sL($GLOBALS['TCA'][$el['table']]['ctrl']['title'], TRUE);
667 // @todo: which information could be needful
668 if (isset($record['crdate'])) {
669 $description .= ' - ' . BackendUtility::dateTimeAge($record['crdate']);
670 }
671 $link = BackendUtility::getModuleUrl(
672 'record_edit',
673 array(
674 'edit[' . $el['table'] . '][' . $el['id'] . ']' => 'edit',
675 'returnUrl' => $this->moduleUrl
676 ),
677 FALSE,
678 TRUE
679 );
680 $actionList[$el['id']] = array(
681 'title' => $title,
682 'description' => BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]),
683 'descriptionHtml' => $description,
684 'link' => $link,
685 'icon' => \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']], array('title' => htmlspecialchars($path)))
686 );
687 }
688 // Render the record list
689 $content .= $this->taskObject->renderListMenu($actionList);
690 return $content;
691 }
692
693 /**
694 * Action to view the result of a SQL query
695 *
696 * @param array $record sys_action record
697 * @return string Result of the query
698 */
699 protected function viewSqlQuery($record) {
700 $content = '';
701 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('lowlevel')) {
702 $sql_query = unserialize($record['t2_data']);
703 if (!is_array($sql_query) || is_array($sql_query) && strtoupper(substr(trim($sql_query['qSelect']), 0, 6)) === 'SELECT') {
704 $actionContent = '';
705 $fullsearch = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\QueryView::class);
706 $fullsearch->formW = 40;
707 $fullsearch->noDownloadB = 1;
708 $type = $sql_query['qC']['search_query_makeQuery'];
709 if ($sql_query['qC']['labels_noprefix'] === 'on') {
710 $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] = 'on';
711 }
712 $sqlQuery = $sql_query['qSelect'];
713 $queryIsEmpty = FALSE;
714 if ($sqlQuery) {
715 $res = $this->getDatabaseConnection()->sql_query($sqlQuery);
716 if (!$this->getDatabaseConnection()->sql_error()) {
717 $fullsearch->formW = 48;
718 // Additional configuration
719 $GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels'] = 1;
720 $GLOBALS['SOBE']->MOD_SETTINGS['queryFields'] = $sql_query['qC']['queryFields'];
721 $cP = $fullsearch->getQueryResultCode($type, $res, $sql_query['qC']['queryTable']);
722 $actionContent = $cP['content'];
723 // If the result is rendered as csv or xml, show a download link
724 if ($type === 'csv' || $type === 'xml') {
725 $actionContent .= '<br /><br /><a href="' . GeneralUtility::getIndpEnv('REQUEST_URI') . '&download_file=1"><strong>' . $this->getLanguageService()->getLL('action_download_file') . '</strong></a>';
726 }
727 } else {
728 $actionContent .= $this->getDatabaseConnection()->sql_error();
729 }
730 } else {
731 // Query is empty (not built)
732 $queryIsEmpty = TRUE;
733 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_emptyQuery', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
734 $content .= '<br />' . $flashMessage->render();
735 }
736 // Admin users are allowed to see and edit the query
737 if ($this->getBackendUser()->isAdmin()) {
738 if (!$queryIsEmpty) {
739 $actionContent .= '<hr /> ' . $fullsearch->tableWrap($sql_query['qSelect']);
740 }
741 $actionContent .= '<br /><a title="' . $this->getLanguageService()->getLL('action_editQuery') . '" href="'
742 . htmlspecialchars(BackendUtility::getModuleUrl('system_dbint')
743 . '&id=' . '&SET[function]=search' . '&SET[search]=query'
744 . '&storeControl[STORE]=-' . $record['uid'] . '&storeControl[LOAD]=1')
745 . '">'
746 . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-info')
747 . $this->getLanguageService()->getLL(($queryIsEmpty ? 'action_createQuery'
748 : 'action_editQuery')) . '</a><br /><br />';
749 }
750 $content .= $this->taskObject->doc->section($this->getLanguageService()->getLL('action_t2_result'), $actionContent, 0, 1);
751 } else {
752 // Query is not configured
753 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_notReady', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
754 $content .= '<br />' . $flashMessage->render();
755 }
756 } else {
757 // Required sysext lowlevel is not installed
758 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_lowlevelMissing', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
759 $content .= '<br />' . $flashMessage->render();
760 }
761 return $content;
762 }
763
764 /**
765 * Action to create a list of records of a specific table and pid
766 *
767 * @param array $record sys_action record
768 * @return string list of records
769 */
770 protected function viewRecordList($record) {
771 $content = '';
772 $this->id = (int)$record['t3_listPid'];
773 $this->table = $record['t3_tables'];
774 if ($this->id == 0 || $this->table == '') {
775 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_notReady', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
776 $content .= '<br />' . $flashMessage->render();
777 return $content;
778 }
779 // Loading current page record and checking access:
780 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->taskObject->perms_clause);
781 $access = is_array($this->pageinfo) ? 1 : 0;
782 // If there is access to the page, then render the list contents and set up the document template object:
783 if ($access) {
784 // Initialize the dblist object:
785 $dblist = GeneralUtility::makeInstance(\TYPO3\CMS\SysAction\ActionList::class);
786 $dblist->script = GeneralUtility::getIndpEnv('REQUEST_URI');
787 $dblist->backPath = $GLOBALS['BACK_PATH'];
788 $dblist->calcPerms = $this->getBackendUser()->calcPerms($this->pageinfo);
789 $dblist->thumbs = $this->getBackendUser()->uc['thumbnailsByDefault'];
790 $dblist->returnUrl = $this->taskObject->returnUrl;
791 $dblist->allFields = 1;
792 $dblist->localizationView = 1;
793 $dblist->showClipboard = 0;
794 $dblist->disableSingleTableView = 1;
795 $dblist->pageRow = $this->pageinfo;
796 $dblist->counter++;
797 $dblist->MOD_MENU = array('bigControlPanel' => '', 'clipBoard' => '', 'localization' => '');
798 $dblist->modTSconfig = $this->taskObject->modTSconfig;
799 $dblist->dontShowClipControlPanels = (!$this->taskObject->MOD_SETTINGS['bigControlPanel'] && $dblist->clipObj->current == 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']);
800 // Initialize the listing object, dblist, for rendering the list:
801 $this->pointer = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(GeneralUtility::_GP('pointer'), 0, 100000);
802 $dblist->start($this->id, $this->table, $this->pointer, $this->taskObject->search_field, $this->taskObject->search_levels, $this->taskObject->showLimit);
803 $dblist->setDispFields();
804 // Render the list of tables:
805 $dblist->generateList();
806 // Add JavaScript functions to the page:
807 $this->taskObject->doc->JScode = $this->taskObject->doc->wrapScriptTags('
808
809 function jumpExt(URL,anchor) {
810 var anc = anchor?anchor:"";
811 window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
812 return false;
813 }
814 function jumpSelf(URL) {
815 window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
816 return false;
817 }
818
819 function setHighlight(id) {
820 top.fsMod.recentIds["web"]=id;
821 top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting
822
823 if (top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
824 top.content.nav_frame.refresh_nav();
825 }
826 }
827
828 ' . $dblist->CBfunctions() . '
829 function editRecords(table,idList,addParams,CBflag) {
830 window.location.href="' . BackendUtility::getModuleUrl('record_edit', array('returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'))) . '&edit["+table+"]["+idList+"]=edit"+addParams;
831 }
832 function editList(table,idList) {
833 var list="";
834
835 // Checking how many is checked, how many is not
836 var pointer=0;
837 var pos = idList.indexOf(",");
838 while (pos!=-1) {
839 if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
840 list+=idList.substr(pointer,pos-pointer)+",";
841 }
842 pointer=pos+1;
843 pos = idList.indexOf(",",pointer);
844 }
845 if (cbValue(table+"|"+idList.substr(pointer))) {
846 list+=idList.substr(pointer)+",";
847 }
848
849 return list ? list : idList;
850 }
851 T3_THIS_LOCATION = ' . GeneralUtility::quoteJSvalue(rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';
852
853 if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
854 ');
855 // Setting up the context sensitive menu:
856 $this->taskObject->doc->getContextMenuCode();
857 // Begin to compile the whole page
858 $content .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">' . $dblist->HTMLcode . '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" />
859 </form>';
860 // If a listing was produced, create the page footer with search form etc:
861 if ($dblist->HTMLcode) {
862 // Making field select box (when extended view for a single table is enabled):
863 if ($dblist->table) {
864 $tmpBackpath = $GLOBALS['BACK_PATH'];
865 $GLOBALS['BACK_PATH'] = '';
866 $content .= $dblist->fieldSelectBox($dblist->table);
867 $GLOBALS['BACK_PATH'] = $tmpBackpath;
868 }
869 }
870 } else {
871 // Not enough rights to access the list view or the page
872 $flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('action_error-access', TRUE), $this->getLanguageService()->getLL('action_error'), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
873 $content .= $flashMessage->render();
874 }
875 return $content;
876 }
877
878 /**
879 * Returns LanguageService
880 *
881 * @return \TYPO3\CMS\Lang\LanguageService
882 */
883 protected function getLanguageService() {
884 return $GLOBALS['LANG'];
885 }
886
887 /**
888 * Returns the current BE user.
889 *
890 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
891 */
892 protected function getBackendUser() {
893 return $GLOBALS['BE_USER'];
894 }
895
896 /**
897 * Returns the database connection
898 *
899 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
900 */
901 protected function getDatabaseConnection() {
902 return $GLOBALS['TYPO3_DB'];
903 }
904
905 }