TYPO3 CMS  TYPO3_8-7
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 
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>' . htmlspecialchars($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 = $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="' . htmlspecialchars($link) . '" title="' . htmlspecialchars($title) . '">';
241  $editActionLink .= $icon . ' ' . htmlspecialchars($title) . '</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  $title = $this->getLanguageService()->getLL('new-sys_action');
295  $content .= '<p>' .
296  '<a class="btn btn-default" href="' . htmlspecialchars($link) . '" title="' . htmlspecialchars($title) . '">' .
297  $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . ' ' .
298  htmlspecialchars($title) .
299  '</a></p>';
300  }
301  return $content;
302  }
303 
310  protected function viewNewBackendUser($record)
311  {
312  $content = '';
313  $beRec = BackendUtility::getRecord('be_users', (int)$record['t1_copy_of_user']);
314  // A record is need which is used as copy for the new user
315  if (!is_array($beRec)) {
316  $this->addMessage(
317  $this->getLanguageService()->getLL('action_notReady'),
318  $this->getLanguageService()->getLL('action_error'),
320  );
321  $content .= $this->renderFlashMessages();
322  return $content;
323  }
324  $vars = GeneralUtility::_POST('data');
325  $key = 'NEW';
326  if ($vars['sent'] == 1) {
327  $errors = [];
328  // Basic error checks
329  if (!empty($vars['email']) && !GeneralUtility::validEmail($vars['email'])) {
330  $errors[] = $this->getLanguageService()->getLL('error-wrong-email');
331  }
332  if (empty($vars['username'])) {
333  $errors[] = $this->getLanguageService()->getLL('error-username-empty');
334  }
335  if ($vars['key'] === 'NEW' && empty($vars['password'])) {
336  $errors[] = $this->getLanguageService()->getLL('error-password-empty');
337  }
338  if ($vars['key'] !== 'NEW' && !$this->isCreatedByUser($vars['key'], $record)) {
339  $errors[] = $this->getLanguageService()->getLL('error-wrong-user');
340  }
341  foreach ($this->hookObjects as $hookObject) {
342  if (method_exists($hookObject, 'viewNewBackendUser_Error')) {
343  $errors = $hookObject->viewNewBackendUser_Error($vars, $errors, $this);
344  }
345  }
346  // Show errors if there are any
347  if (!empty($errors)) {
348  $this->addMessage(
349  implode(LF, $errors),
350  $this->getLanguageService()->getLL('action_error'),
352  );
353  } else {
354  // Save user
355  $key = $this->saveNewBackendUser($record, $vars);
356  // Success message
357  $message = $vars['key'] === 'NEW'
358  ? $this->getLanguageService()->getLL('success-user-created')
359  : $this->getLanguageService()->getLL('success-user-updated');
360  $this->addMessage(
361  $message,
362  $this->getLanguageService()->getLL('success')
363  );
364  }
365  $content .= $this->renderFlashMessages();
366  }
367  // Load BE user to edit
368  if ((int)GeneralUtility::_GP('be_users_uid') > 0) {
369  $tmpUserId = (int)GeneralUtility::_GP('be_users_uid');
370  // Check if the selected user is created by the current user
371  $rawRecord = $this->isCreatedByUser($tmpUserId, $record);
372  if ($rawRecord) {
373  // Delete user
374  if (GeneralUtility::_GP('delete') == 1) {
375  $this->deleteUser($tmpUserId, $record['uid']);
376  }
377  $key = $tmpUserId;
378  $vars = $rawRecord;
379  }
380  }
381  $content .= '<form action="" class="panel panel-default" method="post" enctype="multipart/form-data">
382  <fieldset class="form-section">
383  <h4 class="form-section-headline">' . htmlspecialchars($this->getLanguageService()->getLL('action_t1_legend_generalFields')) . '</h4>
384  <div class="form-group">
385  <label for="field_disable">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.disable')) . '</label>
386  <input type="checkbox" id="field_disable" name="data[disable]" value="1" class="checkbox" ' . ($vars['disable'] == 1 ? ' checked="checked" ' : '') . ' />
387  </div>
388  <div class="form-group">
389  <label for="field_realname">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.name')) . '</label>
390  <input type="text" id="field_realname" class="form-control" name="data[realName]" value="' . htmlspecialchars($vars['realName']) . '" />
391  </div>
392  <div class="form-group">
393  <label for="field_username">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:be_users.username')) . '</label>
394  <input type="text" id="field_username" class="form-control" name="data[username]" value="' . htmlspecialchars($vars['username']) . '" />
395  </div>
396  <div class="form-group">
397  <label for="field_password">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:be_users.password')) . '</label>
398  <input type="password" id="field_password" class="form-control" name="data[password]" value="" />
399  </div>
400  <div class="form-group">
401  <label for="field_email">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.email')) . '</label>
402  <input type="text" id="field_email" class="form-control" name="data[email]" value="' . htmlspecialchars($vars['email']) . '" />
403  </div>
404  </fieldset>
405  <fieldset class="form-section">
406  <h4 class="form-section-headline">' . htmlspecialchars($this->getLanguageService()->getLL('action_t1_legend_configuration')) . '</h4>
407  <div class="form-group">
408  <label for="field_usergroup">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:be_users.usergroup')) . '</label>
409  <select id="field_usergroup" class="form-control" name="data[usergroup][]" multiple="multiple">
410  ' . $this->getUsergroups($record, $vars) . '
411  </select>
412  </div>
413  <div class="form-group">
414  <input type="hidden" name="data[key]" value="' . $key . '" />
415  <input type="hidden" name="data[sent]" value="1" />
416  <input class="btn btn-default" type="submit" value="' . htmlspecialchars($this->getLanguageService()->getLL($key === 'NEW' ? 'action_Create' : 'action_Update')) . '" />
417  </div>
418  </fieldset>
419  </form>';
420  $content .= $this->getCreatedUsers($record, $key);
421  return $content;
422  }
423 
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  }
455  return false;
456  }
457 
465  protected function getCreatedUsers($action, $selectedUser)
466  {
467  $content = '';
468  $userList = [];
469 
470  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
471  ->getQueryBuilderForTable('be_users');
472 
473  $queryBuilder->getRestrictions()
474  ->removeAll()
475  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
476 
477  $res = $queryBuilder
478  ->select('*')
479  ->from('be_users')
480  ->where(
481  $queryBuilder->expr()->eq(
482  'cruser_id',
483  $queryBuilder->createNamedParameter($this->getBackendUser()->user['uid'], \PDO::PARAM_INT)
484  ),
485  $queryBuilder->expr()->eq(
486  'createdByAction',
487  $queryBuilder->createNamedParameter($action['uid'], \PDO::PARAM_INT)
488  )
489  )
490  ->orderBy('username')
491  ->execute();
492 
493  // Render the user records
494  while ($row = $res->fetch()) {
495  $icon = '<span title="' . htmlspecialchars('uid=' . $row['uid']) . '">' . $this->iconFactory->getIconForRecord('be_users', $row, Icon::SIZE_SMALL)->render() . '</span>';
496  $line = $icon . $this->action_linkUserName($row['username'], $row['realName'], $action['uid'], $row['uid']);
497  // Selected user
498  if ($row['uid'] == $selectedUser) {
499  $line = '<strong>' . $line . '</strong>';
500  }
501  $userList[] = '<li class="list-group-item">' . $line . '</li>';
502  }
503 
504  // If any records found
505  if (!empty($userList)) {
506  $content .= '<div class="panel panel-default">';
507  $content .= '<div class="panel-heading">';
508  $content .= '<h3 class="panel-title">' . htmlspecialchars($this->getLanguageService()->getLL('action_t1_listOfUsers')) . '</h3>';
509  $content .= '</div>';
510  $content .= '<ul class="list-group">' . implode($userList) . '</ul>';
511  $content .= '</div>';
512  }
513  return $content;
514  }
515 
525  protected function action_linkUserName($username, $realName, $sysActionUid, $userId)
526  {
527  if (!empty($realName)) {
528  $username .= ' (' . $realName . ')';
529  }
530  // Link to update the user record
531  $href = $this->moduleUrl . '&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . (int)$sysActionUid . '&be_users_uid=' . (int)$userId;
532  $link = '<a href="' . htmlspecialchars($href) . '">' . htmlspecialchars($username) . '</a>';
533  // Link to delete the user record
534  $link .= '
535  <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')) . '">'
536  . $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() .
537  '</a>';
538  return $link;
539  }
540 
548  protected function saveNewBackendUser($record, $vars)
549  {
550  // Check if the usergroup is allowed
551  $vars['usergroup'] = $this->fixUserGroup($vars['usergroup'], $record);
552  $key = $vars['key'];
553  $vars['password'] = trim($vars['password']);
554  // Check if md5 is used as password encryption
555  if ($vars['password'] !== '' && strpos($GLOBALS['TCA']['be_users']['columns']['password']['config']['eval'], 'md5') !== false) {
556  $vars['password'] = md5($vars['password']);
557  }
558  $data = '';
559  $newUserId = 0;
560  if ($key === 'NEW') {
561  $beRec = BackendUtility::getRecord('be_users', (int)$record['t1_copy_of_user']);
562  if (is_array($beRec)) {
563  $data = [];
564  $data['be_users'][$key] = $beRec;
565  $data['be_users'][$key]['username'] = $this->fixUsername($vars['username'], $record['t1_userprefix']);
566  $data['be_users'][$key]['password'] = $vars['password'];
567  $data['be_users'][$key]['realName'] = $vars['realName'];
568  $data['be_users'][$key]['email'] = $vars['email'];
569  $data['be_users'][$key]['disable'] = (int)$vars['disable'];
570  $data['be_users'][$key]['admin'] = 0;
571  $data['be_users'][$key]['usergroup'] = $vars['usergroup'];
572  $data['be_users'][$key]['createdByAction'] = $record['uid'];
573  }
574  } else {
575  // Check ownership
576  $beRec = BackendUtility::getRecord('be_users', (int)$key);
577  if (is_array($beRec) && $beRec['cruser_id'] == $this->getBackendUser()->user['uid']) {
578  $data = [];
579  $data['be_users'][$key]['username'] = $this->fixUsername($vars['username'], $record['t1_userprefix']);
580  if ($vars['password'] !== '') {
581  $data['be_users'][$key]['password'] = $vars['password'];
582  }
583  $data['be_users'][$key]['realName'] = $vars['realName'];
584  $data['be_users'][$key]['email'] = $vars['email'];
585  $data['be_users'][$key]['disable'] = (int)$vars['disable'];
586  $data['be_users'][$key]['admin'] = 0;
587  $data['be_users'][$key]['usergroup'] = $vars['usergroup'];
588  $newUserId = $key;
589  }
590  }
591  // Save/update user by using DataHandler
592  if (is_array($data)) {
593  $dataHandler = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
594  $dataHandler->start($data, [], $this->getBackendUser());
595  $dataHandler->admin = 1;
596  $dataHandler->process_datamap();
597  $newUserId = (int)$dataHandler->substNEWwithIDs['NEW'];
598  if ($newUserId) {
599  // Create
600  $this->action_createDir($newUserId);
601  } else {
602  // Update
603  $newUserId = (int)$key;
604  }
605  unset($tce);
606  }
607  return $newUserId;
608  }
609 
617  protected function fixUsername($username, $prefix)
618  {
619  $prefix = trim($prefix);
620  if (substr($username, 0, strlen($prefix)) === $prefix) {
621  $username = substr($username, strlen($prefix));
622  }
623  return $prefix . $username;
624  }
625 
633  protected function fixUserGroup($appliedUsergroups, $actionRecord)
634  {
635  if (is_array($appliedUsergroups)) {
636  $cleanGroupList = [];
637  // Create an array from the allowed usergroups using the uid as key
638  $allowedUsergroups = array_flip(explode(',', $actionRecord['t1_allowed_groups']));
639  // Walk through the array and check every uid if it is under the allowed ines
640  foreach ($appliedUsergroups as $group) {
641  if (isset($allowedUsergroups[$group])) {
642  $cleanGroupList[] = $group;
643  }
644  }
645  $appliedUsergroups = $cleanGroupList;
646  }
647  return $appliedUsergroups;
648  }
649 
656  protected function checkRootline($pageId)
657  {
658  $access = false;
659  $dbMounts = array_flip(explode(',', trim($this->getBackendUser()->dataLists['webmount_list'], ',')));
660  $rootline = BackendUtility::BEgetRootLine($pageId);
661  foreach ($rootline as $page) {
662  if (isset($dbMounts[$page['uid']]) && !$access) {
663  $access = true;
664  }
665  }
666  return $access;
667  }
668 
674  protected function action_createDir($uid)
675  {
676  $path = $this->action_getUserMainDir();
677  if ($path) {
678  GeneralUtility::mkdir($path . $uid);
679  GeneralUtility::mkdir($path . $uid . '/_temp_/');
680  }
681  }
682 
688  protected function action_getUserMainDir()
689  {
690  $path = $GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'];
691  // If path is set and a valid directory
692  if ($path && @is_dir($path) && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] && GeneralUtility::isFirstPartOfStr($path, $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath']) && substr($path, -1) === '/') {
693  return $path;
694  }
695  }
696 
704  protected function getUsergroups($record, $vars)
705  {
706  $content = '';
707  // Do nothing if no groups are allowed
708  if (empty($record['t1_allowed_groups'])) {
709  return $content;
710  }
711  $content .= '<option value=""></option>';
712  $grList = GeneralUtility::trimExplode(',', $record['t1_allowed_groups'], true);
713  foreach ($grList as $group) {
714  $checkGroup = BackendUtility::getRecord('be_groups', $group);
715  if (is_array($checkGroup)) {
716  $selected = GeneralUtility::inList($vars['usergroup'], $checkGroup['uid']) ? ' selected="selected" ' : '';
717  $content .= '<option ' . $selected . 'value="' . (int)$checkGroup['uid'] . '">' . htmlspecialchars($checkGroup['title']) . '</option>';
718  }
719  }
720  return $content;
721  }
722 
728  protected function viewNewRecord($record)
729  {
730  $link = BackendUtility::getModuleUrl(
731  'record_edit',
732  [
733  'edit[' . $record['t3_tables'] . '][' . (int)$record['t3_listPid'] . ']' => 'new',
734  'returnUrl' => $this->moduleUrl
735  ]
736  );
737  HttpUtility::redirect($link);
738  }
739 
746  protected function viewEditRecord($record)
747  {
748  $content = '';
749  $actionList = [];
750  $dbAnalysis = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\RelationHandler::class);
751  $dbAnalysis->setFetchAllFields(true);
752  $dbAnalysis->start($record['t4_recordsToEdit'], '*');
753  $dbAnalysis->getFromDB();
754  // collect the records
755  foreach ($dbAnalysis->itemArray as $el) {
756  $path = BackendUtility::getRecordPath($el['id'], $this->taskObject->perms_clause, $this->getBackendUser()->uc['titleLen']);
757  $record = BackendUtility::getRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']]);
758  $title = BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]);
759  $description = htmlspecialchars($this->getLanguageService()->sL($GLOBALS['TCA'][$el['table']]['ctrl']['title']));
760  // @todo: which information could be needful
761  if (isset($record['crdate'])) {
762  $description .= ' - ' . htmlspecialchars(BackendUtility::dateTimeAge($record['crdate']));
763  }
764  $link = BackendUtility::getModuleUrl(
765  'record_edit',
766  [
767  'edit[' . $el['table'] . '][' . $el['id'] . ']' => 'edit',
768  'returnUrl' => $this->moduleUrl
769  ]
770  );
771  $actionList[$el['id']] = [
772  'uid' => 'record-' . $el['table'] . '-' . $el['id'],
773  'title' => $title,
774  'description' => BackendUtility::getRecordTitle($el['table'], $dbAnalysis->results[$el['table']][$el['id']]),
775  'descriptionHtml' => $description,
776  'link' => $link,
777  'icon' => '<span title="' . htmlspecialchars($path) . '">' . $this->iconFactory->getIconForRecord($el['table'], $dbAnalysis->results[$el['table']][$el['id']], Icon::SIZE_SMALL)->render() . '</span>'
778  ];
779  }
780  // Render the record list
781  $content .= $this->taskObject->renderListMenu($actionList);
782  return $content;
783  }
784 
791  protected function viewSqlQuery($record)
792  {
793  $content = '';
794  if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('lowlevel')) {
795  $sql_query = unserialize($record['t2_data']);
796  if (!is_array($sql_query) || is_array($sql_query) && strtoupper(substr(trim($sql_query['qSelect']), 0, 6)) === 'SELECT') {
797  $actionContent = '';
798  $type = $sql_query['qC']['search_query_makeQuery'];
799  if ($sql_query['qC']['labels_noprefix'] === 'on') {
800  $GLOBALS['SOBE']->MOD_SETTINGS['labels_noprefix'] = 'on';
801  }
802  $sqlQuery = $sql_query['qSelect'];
803  $queryIsEmpty = false;
804  if ($sqlQuery) {
805  try {
806  $dataRows = GeneralUtility::makeInstance(ConnectionPool::class)
807  ->getConnectionForTable($sql_query['qC']['queryTable'])
808  ->executeQuery($sqlQuery)->fetchAll();
809  // Additional configuration
810  $GLOBALS['SOBE']->MOD_SETTINGS['search_result_labels'] = $sql_query['qC']['search_result_labels'];
811  $GLOBALS['SOBE']->MOD_SETTINGS['queryFields'] = $sql_query['qC']['queryFields'];
812 
813  $fullsearch = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\QueryView::class, $GLOBALS['SOBE']->MOD_SETTINGS);
814  $fullsearch->noDownloadB = 1;
815  $fullsearch->formW = 48;
816  $cP = $fullsearch->getQueryResultCode($type, $dataRows, $sql_query['qC']['queryTable']);
817  $actionContent = $cP['content'];
818  // If the result is rendered as csv or xml, show a download link
819  if ($type === 'csv' || $type === 'xml') {
820  $actionContent .= '<a href="' . htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI') . '&download_file=1') . '">'
821  . '<strong>' . htmlspecialchars($this->getLanguageService()->getLL('action_download_file')) . '</strong></a>';
822  }
823  } catch (DBALException $e) {
824  $actionContent .= $e->getMessage();
825  }
826  } else {
827  // Query is empty (not built)
828  $queryIsEmpty = true;
829  $this->addMessage(
830  $this->getLanguageService()->getLL('action_emptyQuery'),
831  $this->getLanguageService()->getLL('action_error'),
833  );
834  $content .= $this->renderFlashMessages();
835  }
836  // Admin users are allowed to see and edit the query
837  if ($this->getBackendUser()->isAdmin()) {
838  if (!$queryIsEmpty) {
839  $actionContent .= '<div class="panel panel-default"><div class="panel-body"><pre>' . htmlspecialchars($sql_query['qSelect']) . '</pre></div></div>';
840  }
841  $actionContent .= '<a title="' . htmlspecialchars($this->getLanguageService()->getLL('action_editQuery')) . '" class="btn btn-default" href="'
842  . htmlspecialchars(BackendUtility::getModuleUrl('system_dbint')
843  . '&id=' . '&SET[function]=search' . '&SET[search]=query'
844  . '&storeControl[STORE]=-' . $record['uid'] . '&storeControl[LOAD]=1')
845  . '">'
846  . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . ' '
847  . $this->getLanguageService()->getLL(($queryIsEmpty ? 'action_createQuery'
848  : 'action_editQuery')) . '</a>';
849  }
850  $content .= '<h2>' . htmlspecialchars($this->getLanguageService()->getLL('action_t2_result')) . '</h2>' . $actionContent;
851  } else {
852  // Query is not configured
853  $this->addMessage(
854  $this->getLanguageService()->getLL('action_notReady'),
855  $this->getLanguageService()->getLL('action_error'),
857  );
858  $content .= $this->renderFlashMessages();
859  }
860  } else {
861  // Required sysext lowlevel is not installed
862  $this->addMessage(
863  $this->getLanguageService()->getLL('action_lowlevelMissing'),
864  $this->getLanguageService()->getLL('action_error'),
866  );
867  $content .= $this->renderFlashMessages();
868  }
869  return $content;
870  }
871 
878  protected function viewRecordList($record)
879  {
880  $content = '';
881  $this->id = (int)$record['t3_listPid'];
882  $this->table = $record['t3_tables'];
883  if ($this->id == 0) {
884  $this->addMessage(
885  $this->getLanguageService()->getLL('action_notReady'),
886  $this->getLanguageService()->getLL('action_error'),
888  );
889  $content .= $this->renderFlashMessages();
890  return $content;
891  }
892  // Loading current page record and checking access:
893  $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->taskObject->perms_clause);
894  $access = is_array($this->pageinfo) ? 1 : 0;
895  // If there is access to the page, then render the list contents and set up the document template object:
896  if ($access) {
897  // Initialize the dblist object:
898  $dblist = GeneralUtility::makeInstance(\TYPO3\CMS\SysAction\ActionList::class);
899  $dblist->script = GeneralUtility::getIndpEnv('REQUEST_URI');
900  $dblist->calcPerms = $this->getBackendUser()->calcPerms($this->pageinfo);
901  $dblist->thumbs = $this->getBackendUser()->uc['thumbnailsByDefault'];
902  $dblist->returnUrl = $this->taskObject->returnUrl;
903  $dblist->allFields = 1;
904  $dblist->localizationView = 1;
905  $dblist->showClipboard = 0;
906  $dblist->disableSingleTableView = 1;
907  $dblist->pageRow = $this->pageinfo;
908  $dblist->counter++;
909  $dblist->MOD_MENU = ['bigControlPanel' => '', 'clipBoard' => '', 'localization' => ''];
910  $dblist->modTSconfig = $this->taskObject->modTSconfig;
911  $dblist->dontShowClipControlPanels = (!$this->taskObject->MOD_SETTINGS['bigControlPanel'] && $dblist->clipObj->current === 'normal' && !$this->modTSconfig['properties']['showClipControlPanelsDespiteOfCMlayers']);
912  // Initialize the listing object, dblist, for rendering the list:
914  $dblist->start($this->id, $this->table, $this->pointer, $this->taskObject->search_field, $this->taskObject->search_levels, $this->taskObject->showLimit);
915  $dblist->setDispFields();
916  // Render the list of tables:
917  $dblist->generateList();
918  // Add JavaScript functions to the page:
919  $this->taskObject->getModuleTemplate()->addJavaScriptCode(
920  'ActionTaskInlineJavascript',
921  '
922 
923  function jumpExt(URL,anchor) {
924  var anc = anchor?anchor:"";
925  window.location.href = URL+(T3_THIS_LOCATION?"&returnUrl="+T3_THIS_LOCATION:"")+anc;
926  return false;
927  }
928  function jumpSelf(URL) {
929  window.location.href = URL+(T3_RETURN_URL?"&returnUrl="+T3_RETURN_URL:"");
930  return false;
931  }
932 
933  function setHighlight(id) {
934  top.fsMod.recentIds["web"]=id;
935  top.fsMod.navFrameHighlightedID["web"]="pages"+id+"_"+top.fsMod.currentBank; // For highlighting
936 
937  if (top.nav_frame && top.nav_frame.refresh_nav) {
938  top.nav_frame.refresh_nav();
939  }
940  }
941 
942  ' . $dblist->CBfunctions() . '
943  function editRecords(table,idList,addParams,CBflag) {
944  var recordEditUrl = ' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('record_edit', ['returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')])) . ';
945  window.location.href = recordEditUrl + "&edit[" + table + "][" + idList + "]=edit" + addParams;
946  }
947  function editList(table,idList) {
948  var list="";
949 
950  // Checking how many is checked, how many is not
951  var pointer=0;
952  var pos = idList.indexOf(",");
953  while (pos!=-1) {
954  if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
955  list+=idList.substr(pointer,pos-pointer)+",";
956  }
957  pointer=pos+1;
958  pos = idList.indexOf(",",pointer);
959  }
960  if (cbValue(table+"|"+idList.substr(pointer))) {
961  list+=idList.substr(pointer)+",";
962  }
963 
964  return list ? list : idList;
965  }
966  T3_THIS_LOCATION = ' . GeneralUtility::quoteJSvalue(rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';
967 
968  if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
969  '
970  );
971  // Setting up the context sensitive menu:
972  $this->taskObject->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
973  $this->taskObject->getModuleTemplate()->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
974  // Begin to compile the whole page
975  $content .= '<form action="' . htmlspecialchars($dblist->listURL()) . '" method="post" name="dblistForm">' . $dblist->HTMLcode . '<input type="hidden" name="cmd_table" /><input type="hidden" name="cmd" /></form>';
976  // If a listing was produced, create the page footer with search form etc:
977  // Making field select box (when extended view for a single table is enabled):
978  if ($dblist->HTMLcode && $dblist->table) {
979  $content .= $dblist->fieldSelectBox($dblist->table);
980  }
981  } else {
982  // Not enough rights to access the list view or the page
983  $this->addMessage(
984  $this->getLanguageService()->getLL('action_error-access'),
985  $this->getLanguageService()->getLL('action_error'),
987  );
988  $content .= $this->renderFlashMessages();
989  }
990  return $content;
991  }
992 
1000  protected function addMessage($message, $title = '', $severity = FlashMessage::OK)
1001  {
1002  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $title, $severity);
1003  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1004  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1005  $defaultFlashMessageQueue->enqueue($flashMessage);
1006  }
1007 
1013  protected function renderFlashMessages()
1014  {
1015  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1016  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1017  return $defaultFlashMessageQueue->renderFlashMessages();
1018  }
1019 
1025  protected function getLanguageService()
1026  {
1027  return $GLOBALS['LANG'];
1028  }
1029 
1035  protected function getBackendUser()
1036  {
1037  return $GLOBALS['BE_USER'];
1038  }
1039 }
deleteUser($userId, $actionId)
Definition: ActionTask.php:430
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
static readPageAccess($id, $perms_clause)
fixUserGroup($appliedUsergroups, $actionRecord)
Definition: ActionTask.php:633
fixUsername($username, $prefix)
Definition: ActionTask.php:617
action_linkUserName($username, $realName, $sysActionUid, $userId)
Definition: ActionTask.php:525
static isFirstPartOfStr($str, $partStr)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
static BEgetRootLine($uid, $clause='', $workspaceOL=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
saveNewBackendUser($record, $vars)
Definition: ActionTask.php:548
static makeInstance($className,... $constructorArguments)
addMessage($message, $title='', $severity=FlashMessage::OK)
getCreatedUsers($action, $selectedUser)
Definition: ActionTask.php:465
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
static redirect($url, $httpStatus=self::HTTP_STATUS_303)
static getRecordPath($uid, $clause, $titleLimit, $fullTitleLimit=0)
static getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
__construct(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController $taskObject)
Definition: ActionTask.php:64
static dateTimeAge($tstamp, $prefix=1, $date='')