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