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