TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ActionTask.php
Go to the documentation of this file.
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 Doctrine\DBAL\DBALException;
31 
36 {
40  protected $taskObject;
41 
47  protected $hookObjects = [];
48 
54  protected $moduleUrl;
55 
59  protected $iconFactory;
60 
64  public function __construct(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController $taskObject)
65  {
66  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
67  $this->moduleUrl = BackendUtility::getModuleUrl('user_task');
68  $this->taskObject = $taskObject;
69  $this->getLanguageService()->includeLLFile('EXT:sys_action/Resources/Private/Language/locallang.xlf');
70  if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['sys_action']['tx_sysaction_task'])) {
71  foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['sys_action']['tx_sysaction_task'] as $classRef) {
72  $this->hookObjects[] = GeneralUtility::getUserObj($classRef);
73  }
74  }
75  }
76 
82  public function getTask()
83  {
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($this->getLanguageService()->getLL('sys_action'), $this->getLanguageService()->getLL('description'));
94  $content .= $this->renderActionList();
95  } else {
96  $record = BackendUtility::getRecord('sys_action', $show);
97  // If the action is not found
98  if (empty($record)) {
99  $this->addMessage(
100  $this->getLanguageService()->getLL('action_error-not-found'),
101  $this->getLanguageService()->getLL('action_error'),
103  );
104  } else {
105  // Render the task
106  $content .= $this->taskObject->description($record['title'], $record['description']);
107  // Output depends on the type
108  switch ($record['type']) {
109  case 1:
110  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
111  $pageRenderer->loadRequireJsModule('TYPO3/CMS/SysAction/ActionTask');
112  $content .= $this->viewNewBackendUser($record);
113  break;
114  case 2:
115  $content .= $this->viewSqlQuery($record);
116  break;
117  case 3:
118  $content .= $this->viewRecordList($record);
119  break;
120  case 4:
121  $content .= $this->viewEditRecord($record);
122  break;
123  case 5:
124  $content .= $this->viewNewRecord($record);
125  break;
126  default:
127  $this->addMessage(
128  $this->getLanguageService()->getLL('action_noType'),
129  $this->getLanguageService()->getLL('action_error'),
131  );
132  $content .= $this->renderFlashMessages();
133  }
134  }
135  }
136  return $content;
137  }
138 
144  public function getOverview()
145  {
146  $content = '<p>' . $this->getLanguageService()->getLL('description') . '</p>';
147  // Get the actions
148  $actionList = $this->getActions();
149  if (!empty($actionList)) {
150  $items = '';
151  // Render a single action menu item
152  foreach ($actionList as $action) {
153  $active = GeneralUtility::_GP('show') === $action['uid'] ? 'active' : '';
154  $items .= '<a class="list-group-item ' . $active . '" href="' . $action['link'] . '" title="' . htmlspecialchars($action['description']) . '">' . htmlspecialchars($action['title']) . '</a>';
155  }
156  $content .= '<div class="list-group">' . $items . '</div>';
157  }
158  return $content;
159  }
160 
167  protected function getActions()
168  {
169  $backendUser = $this->getBackendUser();
170  $actionList = [];
171 
172  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_action');
173  $queryBuilder->select('sys_action.*')
174  ->from('sys_action');
175 
176  if (!empty($GLOBALS['TCA']['sys_action']['ctrl']['sortby'])) {
177  $queryBuilder->orderBy('sys_action.' . $GLOBALS['TCA']['sys_action']['ctrl']['sortby']);
178  }
179 
180  $queryBuilder->getRestrictions()
181  ->removeAll()
182  ->add(GeneralUtility::makeInstance(RootLevelRestriction::class, ['sys_action']));
183 
184  // Editors can only see the actions which are assigned to a usergroup they belong to
185  if (!$backendUser->isAdmin()) {
186  $groupList = $backendUser->groupList ?: '0';
187 
188  $queryBuilder->getRestrictions()
189  ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
190 
191  $queryBuilder
192  ->join(
193  'sys_action',
194  'sys_action_asgr_mm',
195  'sys_action_asgr_mm',
196  $queryBuilder->expr()->eq(
197  'sys_action_asgr_mm.uid_local',
198  $queryBuilder->quoteIdentifier('sys_action.uid')
199  )
200  )
201  ->join(
202  'sys_action_asgr_mm',
203  'be_groups',
204  'be_groups',
205  $queryBuilder->expr()->eq(
206  'sys_action_asgr_mm.uid_foreign',
207  $queryBuilder->quoteIdentifier('be_groups.uid')
208  )
209  )
210  ->where(
211  $queryBuilder->expr()->in(
212  'be_groups.uid',
213  $queryBuilder->createNamedParameter(
214  GeneralUtility::intExplode(',', $groupList, true),
215  Connection::PARAM_INT_ARRAY
216  )
217  )
218  )
219  ->groupBy('sys_action.uid');
220  }
221 
222  $queryResult = $queryBuilder->execute();
223  while ($actionRow = $queryResult->fetch()) {
224  $editActionLink = '';
225 
226  // Admins are allowed to edit sys_action records
227  if ($this->getBackendUser()->isAdmin()) {
228  $uidEditArgument = 'edit[sys_action][' . (int)$actionRow['uid'] . ']';
229 
230  $link = BackendUtility::getModuleUrl(
231  'record_edit',
232  [
233  $uidEditArgument => 'edit',
234  'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
235  ]
236  );
237 
238  $title = 'title="' . $this->getLanguageService()->getLL('edit-sys_action') . '"';
239  $icon = $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render();
240  $editActionLink = '<a class="btn btn-default btn-sm" href="' . $link . '"' . $title . '>';
241  $editActionLink .= $icon . ' ' . $this->getLanguageService()->getLL('edit-sys_action') . '</a>';
242  }
243 
244  $actionList[] = [
245  'uid' => 'actiontask' . $actionRow['uid'],
246  'title' => $actionRow['title'],
247  'description' => $actionRow['description'],
248  'descriptionHtml' => (
249  $actionRow['description']
250  ? '<p>' . nl2br(htmlspecialchars($actionRow['description'])) . '</p>'
251  : ''
252  ) . $editActionLink,
253  'link' => $this->moduleUrl
254  . '&SET[function]=sys_action.'
255  . self::class
256  . '&show='
257  . (int)$actionRow['uid']
258  ];
259  }
260 
261  return $actionList;
262  }
263 
269  protected function renderActionList()
270  {
271  $content = '';
272  // Get the sys_action records
273  $actionList = $this->getActions();
274  // If any actions are found for the current users
275  if (!empty($actionList)) {
276  $content .= $this->taskObject->renderListMenu($actionList);
277  } else {
278  $this->addMessage(
279  $this->getLanguageService()->getLL('action_not-found-description'),
280  $this->getLanguageService()->getLL('action_not-found'),
282  );
283  }
284  // Admin users can create a new action
285  if ($this->getBackendUser()->isAdmin()) {
286  $link = BackendUtility::getModuleUrl(
287  'record_edit',
288  [
289  'edit[sys_action][0]' => 'new',
290  'returnUrl' => $this->moduleUrl
291  ]
292  );
293 
294  $content .= '<p>' .
295  '<a class="btn btn-default" href="' . $link . '" title="' . $this->getLanguageService()->getLL('new-sys_action') . '">' .
296  $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . ' ' .
297  $this->getLanguageService()->getLL('new-sys_action') .
298  '</a></p>';
299  }
300  return $content;
301  }
302 
309  protected function viewNewBackendUser($record)
310  {
311  $content = '';
312  $beRec = BackendUtility::getRecord('be_users', (int)$record['t1_copy_of_user']);
313  // A record is need which is used as copy for the new user
314  if (!is_array($beRec)) {
315  $this->addMessage(
316  $this->getLanguageService()->getLL('action_notReady'),
317  $this->getLanguageService()->getLL('action_error'),
319  );
320  $content .= $this->renderFlashMessages();
321  return $content;
322  }
323  $vars = GeneralUtility::_POST('data');
324  $key = 'NEW';
325  if ($vars['sent'] == 1) {
326  $errors = [];
327  // Basic error checks
328  if (!empty($vars['email']) && !GeneralUtility::validEmail($vars['email'])) {
329  $errors[] = $this->getLanguageService()->getLL('error-wrong-email');
330  }
331  if (empty($vars['username'])) {
332  $errors[] = $this->getLanguageService()->getLL('error-username-empty');
333  }
334  if ($vars['key'] === 'NEW' && empty($vars['password'])) {
335  $errors[] = $this->getLanguageService()->getLL('error-password-empty');
336  }
337  if ($vars['key'] !== 'NEW' && !$this->isCreatedByUser($vars['key'], $record)) {
338  $errors[] = $this->getLanguageService()->getLL('error-wrong-user');
339  }
340  foreach ($this->hookObjects as $hookObject) {
341  if (method_exists($hookObject, 'viewNewBackendUser_Error')) {
342  $errors = $hookObject->viewNewBackendUser_Error($vars, $errors, $this);
343  }
344  }
345  // Show errors if there are any
346  if (!empty($errors)) {
347  $this->addMessage(
348  implode(LF, $errors),
349  $this->getLanguageService()->getLL('action_error'),
351  );
352  } else {
353  // Save user
354  $key = $this->saveNewBackendUser($record, $vars);
355  // Success message
356  $message = $vars['key'] === 'NEW'
357  ? $this->getLanguageService()->getLL('success-user-created')
358  : $this->getLanguageService()->getLL('success-user-updated');
359  $this->addMessage(
360  $message,
361  $this->getLanguageService()->getLL('success')
362  );
363  }
364  $content .= $this->renderFlashMessages();
365  }
366  // Load BE user to edit
367  if ((int)GeneralUtility::_GP('be_users_uid') > 0) {
368  $tmpUserId = (int)GeneralUtility::_GP('be_users_uid');
369  // Check if the selected user is created by the current user
370  $rawRecord = $this->isCreatedByUser($tmpUserId, $record);
371  if ($rawRecord) {
372  // Delete user
373  if (GeneralUtility::_GP('delete') == 1) {
374  $this->deleteUser($tmpUserId, $record['uid']);
375  }
376  $key = $tmpUserId;
377  $vars = $rawRecord;
378  }
379  }
380  $content .= '<form action="" class="panel panel-default" method="post" enctype="multipart/form-data">
381  <fieldset class="form-section">
382  <h4 class="form-section-headline">' . $this->getLanguageService()->getLL('action_t1_legend_generalFields') . '</h4>
383  <div class="form-group">
384  <label for="field_disable">' . $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.disable') . '</label>
385  <input type="checkbox" id="field_disable" name="data[disable]" value="1" class="checkbox" ' . ($vars['disable'] == 1 ? ' checked="checked" ' : '') . ' />
386  </div>
387  <div class="form-group">
388  <label for="field_realname">' . $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.name') . '</label>
389  <input type="text" id="field_realname" class="form-control" name="data[realName]" value="' . htmlspecialchars($vars['realName']) . '" />
390  </div>
391  <div class="form-group">
392  <label for="field_username">' . $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:be_users.username') . '</label>
393  <input type="text" id="field_username" class="form-control" name="data[username]" value="' . htmlspecialchars($vars['username']) . '" />
394  </div>
395  <div class="form-group">
396  <label for="field_password">' . $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:be_users.password') . '</label>
397  <input type="password" id="field_password" class="form-control" name="data[password]" value="" />
398  </div>
399  <div class="form-group">
400  <label for="field_email">' . $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.email') . '</label>
401  <input type="text" id="field_email" class="form-control" name="data[email]" value="' . htmlspecialchars($vars['email']) . '" />
402  </div>
403  </fieldset>
404  <fieldset class="form-section">
405  <h4 class="form-section-headline">' . $this->getLanguageService()->getLL('action_t1_legend_configuration') . '</h4>
406  <div class="form-group">
407  <label for="field_usergroup">' . $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:be_users.usergroup') . '</label>
408  <select id="field_usergroup" class="form-control" name="data[usergroup][]" multiple="multiple">
409  ' . $this->getUsergroups($record, $vars) . '
410  </select>
411  </div>
412  <div class="form-group">
413  <input type="hidden" name="data[key]" value="' . $key . '" />
414  <input type="hidden" name="data[sent]" value="1" />
415  <input class="btn btn-default" type="submit" value="' . ($key === 'NEW' ? $this->getLanguageService()->getLL('action_Create') : $this->getLanguageService()->getLL('action_Update')) . '" />
416  </div>
417  </fieldset>
418  </form>';
419  $content .= $this->getCreatedUsers($record, $key);
420  return $content;
421  }
422 
430  protected function deleteUser($userId, $actionId)
431  {
432  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('be_users')->update(
433  'be_users',
434  ['deleted' => 1, 'tstamp' => (int)$GLOBALS['ACCESS_TIME']],
435  ['uid' => (int)$userId]
436  );
437 
438  // redirect to the original task
439  HttpUtility::redirect($this->moduleUrl . '&show=' . (int)$actionId);
440  }
441 
449  protected function isCreatedByUser($id, $action)
450  {
451  $record = BackendUtility::getRecord('be_users', $id, '*', ' AND cruser_id=' . $this->getBackendUser()->user['uid'] . ' AND createdByAction=' . $action['uid']);
452  if (is_array($record)) {
453  return $record;
454  } else {
455  return false;
456  }
457  }
458 
466  protected function getCreatedUsers($action, $selectedUser)
467  {
468  $content = '';
469  $userList = [];
470 
471  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
472  ->getQueryBuilderForTable('be_users');
473 
474  $queryBuilder->getRestrictions()
475  ->removeAll()
476  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
477 
478  $res = $queryBuilder
479  ->select('*')
480  ->from('be_users')
481  ->where(
482  $queryBuilder->expr()->eq(
483  'cruser_id',
484  $queryBuilder->createNamedParameter($this->getBackendUser()->user['uid'], \PDO::PARAM_INT)
485  ),
486  $queryBuilder->expr()->eq(
487  'createdByAction',
488  $queryBuilder->createNamedParameter($action['uid'], \PDO::PARAM_INT)
489  )
490  )
491  ->orderBy('username')
492  ->execute();
493 
494  // Render the user records
495  while ($row = $res->fetch()) {
496  $icon = '<span title="' . htmlspecialchars('uid=' . $row['uid']) . '">' . $this->iconFactory->getIconForRecord('be_users', $row, Icon::SIZE_SMALL)->render() . '</span>';
497  $line = $icon . $this->action_linkUserName($row['username'], $row['realName'], $action['uid'], $row['uid']);
498  // Selected user
499  if ($row['uid'] == $selectedUser) {
500  $line = '<strong>' . $line . '</strong>';
501  }
502  $userList[] = '<li class="list-group-item">' . $line . '</li>';
503  }
504 
505  // If any records found
506  if (!empty($userList)) {
507  $content .= '<div class="panel panel-default">';
508  $content .= '<div class="panel-heading">';
509  $content .= '<h3 class="panel-title">' . htmlspecialchars($this->getLanguageService()->getLL('action_t1_listOfUsers')) . '</h3>';
510  $content .= '</div>';
511  $content .= '<ul class="list-group">' . implode($userList) . '</ul>';
512  $content .= '</div>';
513  }
514  return $content;
515  }
516 
526  protected function action_linkUserName($username, $realName, $sysActionUid, $userId)
527  {
528  if (!empty($realName)) {
529  $username .= ' (' . $realName . ')';
530  }
531  // Link to update the user record
532  $href = $this->moduleUrl . '&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . (int)$sysActionUid . '&be_users_uid=' . (int)$userId;
533  $link = '<a href="' . htmlspecialchars($href) . '">' . htmlspecialchars($username) . '</a>';
534  // Link to delete the user record
535  $link .= '
536  <a href="' . htmlspecialchars(($href . '&delete=1')) . '" class="t3js-confirm-trigger" data-title="' . htmlspecialchars($this->getLanguageService()->getLL('lDelete_warning_title')) . '" data-message="' . htmlspecialchars($this->getLanguageService()->getLL('lDelete_warning')) . '">'
537  . $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() .
538  '</a>';
539  return $link;
540  }
541 
549  protected function saveNewBackendUser($record, $vars)
550  {
551  // Check if the db mount is a page the current user is allowed to.);
552  $vars['db_mountpoints'] = $this->fixDbMount($vars['db_mountpoints']);
553  // Check if the usergroup is allowed
554  $vars['usergroup'] = $this->fixUserGroup($vars['usergroup'], $record);
555  $key = $vars['key'];
556  $vars['password'] = trim($vars['password']);
557  // Check if md5 is used as password encryption
558  if ($vars['password'] !== '' && strpos($GLOBALS['TCA']['be_users']['columns']['password']['config']['eval'], 'md5') !== false) {
559  $vars['password'] = md5($vars['password']);
560  }
561  $data = '';
562  $newUserId = 0;
563  if ($key === 'NEW') {
564  $beRec = BackendUtility::getRecord('be_users', (int)$record['t1_copy_of_user']);
565  if (is_array($beRec)) {
566  $data = [];
567  $data['be_users'][$key] = $beRec;
568  $data['be_users'][$key]['username'] = $this->fixUsername($vars['username'], $record['t1_userprefix']);
569  $data['be_users'][$key]['password'] = $vars['password'];
570  $data['be_users'][$key]['realName'] = $vars['realName'];
571  $data['be_users'][$key]['email'] = $vars['email'];
572  $data['be_users'][$key]['disable'] = (int)$vars['disable'];
573  $data['be_users'][$key]['admin'] = 0;
574  $data['be_users'][$key]['usergroup'] = $vars['usergroup'];
575  $data['be_users'][$key]['db_mountpoints'] = $vars['db_mountpoints'];
576  $data['be_users'][$key]['createdByAction'] = $record['uid'];
577  }
578  } else {
579  // Check ownership
580  $beRec = BackendUtility::getRecord('be_users', (int)$key);
581  if (is_array($beRec) && $beRec['cruser_id'] == $this->getBackendUser()->user['uid']) {
582  $data = [];
583  $data['be_users'][$key]['username'] = $this->fixUsername($vars['username'], $record['t1_userprefix']);
584  if ($vars['password'] !== '') {
585  $data['be_users'][$key]['password'] = $vars['password'];
586  }
587  $data['be_users'][$key]['realName'] = $vars['realName'];
588  $data['be_users'][$key]['email'] = $vars['email'];
589  $data['be_users'][$key]['disable'] = (int)$vars['disable'];
590  $data['be_users'][$key]['admin'] = 0;
591  $data['be_users'][$key]['usergroup'] = $vars['usergroup'];
592  $data['be_users'][$key]['db_mountpoints'] = $vars['db_mountpoints'];
593  $newUserId = $key;
594  }
595  }
596  // Save/update user by using DataHandler
597  if (is_array($data)) {
598  $dataHandler = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
599  $dataHandler->start($data, [], $this->getBackendUser());
600  $dataHandler->admin = 1;
601  $dataHandler->process_datamap();
602  $newUserId = (int)$dataHandler->substNEWwithIDs['NEW'];
603  if ($newUserId) {
604  // Create
605  $this->action_createDir($newUserId);
606  } else {
607  // Update
608  $newUserId = (int)$key;
609  }
610  unset($tce);
611  }
612  return $newUserId;
613  }
614 
622  protected function fixUsername($username, $prefix)
623  {
624  $prefix = trim($prefix);
625  if (substr($username, 0, strlen($prefix)) === $prefix) {
626  $username = substr($username, strlen($prefix));
627  }
628  return $prefix . $username;
629  }
630 
638  protected function fixUserGroup($appliedUsergroups, $actionRecord)
639  {
640  if (is_array($appliedUsergroups)) {
641  $cleanGroupList = [];
642  // Create an array from the allowed usergroups using the uid as key
643  $allowedUsergroups = array_flip(explode(',', $actionRecord['t1_allowed_groups']));
644  // Walk through the array and check every uid if it is under the allowed ines
645  foreach ($appliedUsergroups as $group) {
646  if (isset($allowedUsergroups[$group])) {
647  $cleanGroupList[] = $group;
648  }
649  }
650  $appliedUsergroups = $cleanGroupList;
651  }
652  return $appliedUsergroups;
653  }
654 
661  protected function fixDbMount($appliedDbMounts)
662  {
663  // Admins can see any page, no need to check there
664  if (!empty($appliedDbMounts) && !$this->getBackendUser()->isAdmin()) {
665  $cleanDbMountList = [];
666  $dbMounts = GeneralUtility::trimExplode(',', $appliedDbMounts, true);
667  // Walk through every wanted DB-Mount and check if it allowed for the current user
668  foreach ($dbMounts as $dbMount) {
669  $uid = (int)substr($dbMount, strrpos($dbMount, '_') + 1);
670  $page = BackendUtility::getRecord('pages', $uid);
671  // Check rootline and access rights
672  if ($this->checkRootline($uid) && $this->getBackendUser()->calcPerms($page)) {
673  $cleanDbMountList[] = 'pages_' . $uid;
674  }
675  }
676  // Build the clean list
677  $appliedDbMounts = implode(',', $cleanDbMountList);
678  }
679  return $appliedDbMounts;
680  }
681 
688  protected function checkRootline($pageId)
689  {
690  $access = false;
691  $dbMounts = array_flip(explode(',', trim($this->getBackendUser()->dataLists['webmount_list'], ',')));
692  $rootline = BackendUtility::BEgetRootLine($pageId);
693  foreach ($rootline as $page) {
694  if (isset($dbMounts[$page['uid']]) && !$access) {
695  $access = true;
696  }
697  }
698  return $access;
699  }
700 
707  protected function action_createDir($uid)
708  {
709  $path = $this->action_getUserMainDir();
710  if ($path) {
711  GeneralUtility::mkdir($path . $uid);
712  GeneralUtility::mkdir($path . $uid . '/_temp_/');
713  }
714  }
715 
721  protected function action_getUserMainDir()
722  {
723  $path = $GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'];
724  // If path is set and a valid directory
725  if ($path && @is_dir($path) && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] && GeneralUtility::isFirstPartOfStr($path, $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath']) && substr($path, -1) == '/') {
726  return $path;
727  }
728  }
729 
737  protected function getUsergroups($record, $vars)
738  {
739  $content = '';
740  // Do nothing if no groups are allowed
741  if (empty($record['t1_allowed_groups'])) {
742  return $content;
743  }
744  $content .= '<option value=""></option>';
745  $grList = GeneralUtility::trimExplode(',', $record['t1_allowed_groups'], true);
746  foreach ($grList as $group) {
747  $checkGroup = BackendUtility::getRecord('be_groups', $group);
748  if (is_array($checkGroup)) {
749  $selected = GeneralUtility::inList($vars['usergroup'], $checkGroup['uid']) ? ' selected="selected" ' : '';
750  $content .= '<option ' . $selected . 'value="' . $checkGroup['uid'] . '">' . htmlspecialchars($checkGroup['title']) . '</option>';
751  }
752  }
753  return $content;
754  }
755 
762  protected function viewNewRecord($record)
763  {
764  $link = BackendUtility::getModuleUrl(
765  'record_edit',
766  [
767  'edit[' . $record['t3_tables'] . '][' . (int)$record['t3_listPid'] . ']' => 'new',
768  'returnUrl' => $this->moduleUrl
769  ]
770  );
771  HttpUtility::redirect($link);
772  }
773 
780  protected function viewEditRecord($record)
781  {
782  $content = '';
783  $actionList = [];
784  $dbAnalysis = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\RelationHandler::class);
785  $dbAnalysis->setFetchAllFields(true);
786  $dbAnalysis->start($record['t4_recordsToEdit'], '*');
787  $dbAnalysis->getFromDB();
788  // collect the records
789  foreach ($dbAnalysis->itemArray as $el) {
790  $path = BackendUtility::getRecordPath($el['id'], $this->taskObject->perms_clause, $this->getBackendUser()->uc['titleLen']);
791  $record = BackendUtility::getRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']]);
792  $title = BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]);
793  $description = htmlspecialchars($this->getLanguageService()->sL($GLOBALS['TCA'][$el['table']]['ctrl']['title']));
794  // @todo: which information could be needful
795  if (isset($record['crdate'])) {
796  $description .= ' - ' . BackendUtility::dateTimeAge($record['crdate']);
797  }
798  $link = BackendUtility::getModuleUrl(
799  'record_edit',
800  [
801  'edit[' . $el['table'] . '][' . $el['id'] . ']' => 'edit',
802  'returnUrl' => $this->moduleUrl
803  ]
804  );
805  $actionList[$el['id']] = [
806  'uid' => 'record-' . $el['table'] . '-' . $el['id'],
807  'title' => $title,
808  'description' => BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]),
809  'descriptionHtml' => $description,
810  'link' => $link,
811  'icon' => '<span title="' . htmlspecialchars($path) . '">' . $this->iconFactory->getIconForRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']], Icon::SIZE_SMALL)->render() . '</span>'
812  ];
813  }
814  // Render the record list
815  $content .= $this->taskObject->renderListMenu($actionList);
816  return $content;
817  }
818 
825  protected function viewSqlQuery($record)
826  {
827  $content = '';
828  if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('lowlevel')) {
829  $sql_query = unserialize($record['t2_data']);
830  if (!is_array($sql_query) || is_array($sql_query) && strtoupper(substr(trim($sql_query['qSelect']), 0, 6)) === 'SELECT') {
831  $actionContent = '';
832  $fullsearch = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\QueryView::class);
833  $fullsearch->formW = 40;
834  $fullsearch->noDownloadB = 1;
835  $type = $sql_query['qC']['search_query_makeQuery'];
836  if ($sql_query['qC']['labels_noprefix'] === 'on') {
837  $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] = 'on';
838  }
839  $sqlQuery = $sql_query['qSelect'];
840  $queryIsEmpty = false;
841  if ($sqlQuery) {
842  try {
843  $dataRows = GeneralUtility::makeInstance(ConnectionPool::class)
844  ->getConnectionForTable($sql_query['qC']['queryTable'])
845  ->executeQuery($sqlQuery)->fetchAll();
846  $fullsearch->formW = 48;
847  // Additional configuration
848  $GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels'] = 1;
849  $GLOBALS['SOBE']->MOD_SETTINGS['queryFields'] = $sql_query['qC']['queryFields'];
850  $cP = $fullsearch->getQueryResultCode($type, $dataRows, $sql_query['qC']['queryTable']);
851  $actionContent = $cP['content'];
852  // If the result is rendered as csv or xml, show a download link
853  if ($type === 'csv' || $type === 'xml') {
854  $actionContent .= '<a href="' . GeneralUtility::getIndpEnv('REQUEST_URI') . '&download_file=1"><strong>' . $this->getLanguageService()->getLL('action_download_file') . '</strong></a>';
855  }
856  } catch (DBALException $e) {
857  $actionContent .= $e->getMessage();
858  }
859  } else {
860  // Query is empty (not built)
861  $queryIsEmpty = true;
862  $this->addMessage(
863  $this->getLanguageService()->getLL('action_emptyQuery'),
864  $this->getLanguageService()->getLL('action_error'),
866  );
867  $content .= $this->renderFlashMessages();
868  }
869  // Admin users are allowed to see and edit the query
870  if ($this->getBackendUser()->isAdmin()) {
871  if (!$queryIsEmpty) {
872  $actionContent .= '<div class="panel panel-default"><div class="panel-body"><pre>' . $sql_query['qSelect'] . '</pre></div></div>';
873  }
874  $actionContent .= '<a title="' . $this->getLanguageService()->getLL('action_editQuery') . '" class="btn btn-default" href="'
875  . htmlspecialchars(BackendUtility::getModuleUrl('system_dbint')
876  . '&id=' . '&SET[function]=search' . '&SET[search]=query'
877  . '&storeControl[STORE]=-' . $record['uid'] . '&storeControl[LOAD]=1')
878  . '">'
879  . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render() . ' '
880  . $this->getLanguageService()->getLL(($queryIsEmpty ? 'action_createQuery'
881  : 'action_editQuery')) . '</a>';
882  }
883  $content .= '<h2>' . htmlspecialchars($this->getLanguageService()->getLL('action_t2_result')) . '</h2>' . $actionContent;
884  } else {
885  // Query is not configured
886  $this->addMessage(
887  $this->getLanguageService()->getLL('action_notReady'),
888  $this->getLanguageService()->getLL('action_error'),
890  );
891  $content .= $this->renderFlashMessages();
892  }
893  } else {
894  // Required sysext lowlevel is not installed
895  $this->addMessage(
896  $this->getLanguageService()->getLL('action_lowlevelMissing'),
897  $this->getLanguageService()->getLL('action_error'),
899  );
900  $content .= $this->renderFlashMessages();
901  }
902  return $content;
903  }
904 
911  protected function viewRecordList($record)
912  {
913  $content = '';
914  $this->id = (int)$record['t3_listPid'];
915  $this->table = $record['t3_tables'];
916  if ($this->id == 0) {
917  $this->addMessage(
918  $this->getLanguageService()->getLL('action_notReady'),
919  $this->getLanguageService()->getLL('action_error'),
921  );
922  $content .= $this->renderFlashMessages();
923  return $content;
924  }
925  // Loading current page record and checking access:
926  $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->taskObject->perms_clause);
927  $access = is_array($this->pageinfo) ? 1 : 0;
928  // If there is access to the page, then render the list contents and set up the document template object:
929  if ($access) {
930  // Initialize the dblist object:
931  $dblist = GeneralUtility::makeInstance(\TYPO3\CMS\SysAction\ActionList::class);
932  $dblist->script = GeneralUtility::getIndpEnv('REQUEST_URI');
933  $dblist->calcPerms = $this->getBackendUser()->calcPerms($this->pageinfo);
934  $dblist->thumbs = $this->getBackendUser()->uc['thumbnailsByDefault'];
935  $dblist->returnUrl = $this->taskObject->returnUrl;
936  $dblist->allFields = 1;
937  $dblist->localizationView = 1;
938  $dblist->showClipboard = 0;
939  $dblist->disableSingleTableView = 1;
940  $dblist->pageRow = $this->pageinfo;
941  $dblist->counter++;
942  $dblist->MOD_MENU = ['bigControlPanel' => '', 'clipBoard' => '', 'localization' => ''];
943  $dblist->modTSconfig = $this->taskObject->modTSconfig;
944  $dblist->dontShowClipControlPanels = (!$this->taskObject->MOD_SETTINGS['bigControlPanel'] && $dblist->clipObj->current == 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']);
945  // Initialize the listing object, dblist, for rendering the list:
947  $dblist->start($this->id, $this->table, $this->pointer, $this->taskObject->search_field, $this->taskObject->search_levels, $this->taskObject->showLimit);
948  $dblist->setDispFields();
949  // Render the list of tables:
950  $dblist->generateList();
951  // Add JavaScript functions to the page:
952  $this->taskObject->getModuleTemplate()->addJavaScriptCode(
953  'ActionTaskInlineJavascript',
954  '
955 
956  function jumpExt(URL,anchor) {
957  var anc = anchor?anchor:"";
958  window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
959  return false;
960  }
961  function jumpSelf(URL) {
962  window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
963  return false;
964  }
965 
966  function setHighlight(id) {
967  top.fsMod.recentIds["web"]=id;
968  top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting
969 
970  if (top.nav_frame && top.nav_frame.refresh_nav) {
971  top.nav_frame.refresh_nav();
972  }
973  }
974 
975  ' . $dblist->CBfunctions() . '
976  function editRecords(table,idList,addParams,CBflag) {
977  window.location.href="' . BackendUtility::getModuleUrl('record_edit', ['returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]) . '&edit["+table+"]["+idList+"]=edit"+addParams;
978  }
979  function editList(table,idList) {
980  var list="";
981 
982  // Checking how many is checked, how many is not
983  var pointer=0;
984  var pos = idList.indexOf(",");
985  while (pos!=-1) {
986  if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
987  list+=idList.substr(pointer,pos-pointer)+",";
988  }
989  pointer=pos+1;
990  pos = idList.indexOf(",",pointer);
991  }
992  if (cbValue(table+"|"+idList.substr(pointer))) {
993  list+=idList.substr(pointer)+",";
994  }
995 
996  return list ? list : idList;
997  }
998  T3_THIS_LOCATION = ' . GeneralUtility::quoteJSvalue(rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';
999 
1000  if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
1001  '
1002  );
1003  // Setting up the context sensitive menu:
1004  $this->taskObject->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
1005  // Begin to compile the whole page
1006  $content .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">' . $dblist->HTMLcode . '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" />
1007  </form>';
1008  // If a listing was produced, create the page footer with search form etc:
1009  // Making field select box (when extended view for a single table is enabled):
1010  if ($dblist->HTMLcode && $dblist->table) {
1011  $content .= $dblist->fieldSelectBox($dblist->table);
1012  }
1013  } else {
1014  // Not enough rights to access the list view or the page
1015  $this->addMessage(
1016  $this->getLanguageService()->getLL('action_error-access'),
1017  $this->getLanguageService()->getLL('action_error'),
1019  );
1020  $content .= $this->renderFlashMessages();
1021  }
1022  return $content;
1023  }
1024 
1032  protected function addMessage($message, $title = '', $severity = FlashMessage::OK)
1033  {
1034  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $title, $severity);
1035  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1036  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1037  $defaultFlashMessageQueue->enqueue($flashMessage);
1038  }
1039 
1045  protected function renderFlashMessages()
1046  {
1047  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1048  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1049  return $defaultFlashMessageQueue->renderFlashMessages();
1050  }
1051 
1057  protected function getLanguageService()
1058  {
1059  return $GLOBALS['LANG'];
1060  }
1061 
1067  protected function getBackendUser()
1068  {
1069  return $GLOBALS['BE_USER'];
1070  }
1071 }
static getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:76
getCreatedUsers($action, $selectedUser)
Definition: ActionTask.php:466
__construct(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController $taskObject)
Definition: ActionTask.php:64
static isFirstPartOfStr($str, $partStr)
action_linkUserName($username, $realName, $sysActionUid, $userId)
Definition: ActionTask.php:526
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
fixUserGroup($appliedUsergroups, $actionRecord)
Definition: ActionTask.php:638
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
saveNewBackendUser($record, $vars)
Definition: ActionTask.php:549
deleteUser($userId, $actionId)
Definition: ActionTask.php:430
static BEgetRootLine($uid, $clause= '', $workspaceOL=false)
static getRecord($table, $uid, $fields= '*', $where= '', $useDeleteClause=true)
fixUsername($username, $prefix)
Definition: ActionTask.php:622
fixDbMount($appliedDbMounts)
Definition: ActionTask.php:661
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
addMessage($message, $title= '', $severity=FlashMessage::OK)
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)