TYPO3 CMS  TYPO3_6-2
StagesService.php
Go to the documentation of this file.
1 <?php
3 
18 
25 
26  const TABLE_STAGE = 'sys_workspace_stage';
27  // if a record is in the "ready to publish" stage STAGE_PUBLISH_ID the nextStage is STAGE_PUBLISH_EXECUTE_ID, this id wont be saved at any time in db
29  // ready to publish stage
30  const STAGE_PUBLISH_ID = -10;
31  const STAGE_EDIT_ID = 0;
33  const MODE_NOTIFY_ALL = 1;
35 
41  private $pathToLocallang = 'LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf';
42 
48  protected $workspaceStageCache = array();
49 
53  protected $workspaceStageAllowedCache = array();
54 
58  protected $fetchGroupsCache = array();
59 
63  protected $userGroups = array();
64 
70  public function getWorkspaceId() {
71  return $this->getBackendUser()->workspace;
72  }
73 
83  $workspaceItems,
84  array $byTableName = array('tt_content', 'pages', 'pages_language_overlay')
85  ) {
86  $currentStage = array();
87  $previousStage = array();
88  $usedStages = array();
89  $found = FALSE;
90  $availableStagesForWS = array_reverse($this->getStagesForWS());
91  $availableStagesForWSUser = $this->getStagesForWSUser();
92  $byTableName = array_flip($byTableName);
93  foreach ($workspaceItems as $tableName => $items) {
94  if (!array_key_exists($tableName, $byTableName)) {
95  continue;
96  }
97  foreach ($items as $item) {
98  $usedStages[$item['t3ver_stage']] = TRUE;
99  }
100  }
101  foreach ($availableStagesForWS as $stage) {
102  if (isset($usedStages[$stage['uid']])) {
103  $currentStage = $stage;
104  $previousStage = $this->getPrevStage($stage['uid']);
105  break;
106  }
107  }
108  foreach ($availableStagesForWSUser as $userWS) {
109  if ($previousStage['uid'] == $userWS['uid']) {
110  $found = TRUE;
111  break;
112  }
113  }
114  if ($found === FALSE || !$this->isStageAllowedForUser($currentStage['uid'])) {
115  $previousStage = array();
116  }
117  return array(
118  $currentStage,
119  $previousStage
120  );
121  }
122 
132  $workspaceItems,
133  array $byTableName = array('tt_content', 'pages', 'pages_language_overlay')
134  ) {
135  $currentStage = array();
136  $usedStages = array();
137  $nextStage = array();
138  $availableStagesForWS = $this->getStagesForWS();
139  $availableStagesForWSUser = $this->getStagesForWSUser();
140  $byTableName = array_flip($byTableName);
141  $found = FALSE;
142  foreach ($workspaceItems as $tableName => $items) {
143  if (!array_key_exists($tableName, $byTableName)) {
144  continue;
145  }
146  foreach ($items as $item) {
147  $usedStages[$item['t3ver_stage']] = TRUE;
148  }
149  }
150  foreach ($availableStagesForWS as $stage) {
151  if (isset($usedStages[$stage['uid']])) {
152  $currentStage = $stage;
153  $nextStage = $this->getNextStage($stage['uid']);
154  break;
155  }
156  }
157  foreach ($availableStagesForWSUser as $userWS) {
158  if ($nextStage['uid'] == $userWS['uid']) {
159  $found = TRUE;
160  break;
161  }
162  }
163  if ($found === FALSE || !$this->isStageAllowedForUser($currentStage['uid'])) {
164  $nextStage = array();
165  }
166  return array(
167  $currentStage,
168  $nextStage
169  );
170  }
171 
177  public function getStagesForWS() {
178  $stages = array();
179  if (isset($this->workspaceStageCache[$this->getWorkspaceId()])) {
180  $stages = $this->workspaceStageCache[$this->getWorkspaceId()];
181  } else {
182  $stages[] = array(
183  'uid' => self::STAGE_EDIT_ID,
184  'title' => $GLOBALS['LANG']->sL(($this->pathToLocallang . ':actionSendToStage')) . ' "'
185  . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xlf:stage_editing') . '"'
186  );
187  $workspaceRec = BackendUtility::getRecord('sys_workspace', $this->getWorkspaceId());
188  if ($workspaceRec['custom_stages'] > 0) {
189  // Get all stage records for this workspace
190  $where = 'parentid=' . $this->getWorkspaceId() . ' AND parenttable='
191  . $GLOBALS['TYPO3_DB']->fullQuoteStr('sys_workspace', self::TABLE_STAGE) . ' AND deleted=0';
192  $workspaceStageRecs = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', self::TABLE_STAGE, $where, '', 'sorting', '', 'uid');
193  foreach ($workspaceStageRecs as $stage) {
194  $stage['title'] = $GLOBALS['LANG']->sL(($this->pathToLocallang . ':actionSendToStage')) . ' "' . $stage['title'] . '"';
195  $stages[] = $stage;
196  }
197  }
198  $stages[] = array(
199  'uid' => self::STAGE_PUBLISH_ID,
200  'title' => $GLOBALS['LANG']->sL(($this->pathToLocallang . ':actionSendToStage')) . ' "'
201  . $GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang_mod.xlf:stage_ready_to_publish') . '"'
202  );
203  $stages[] = array(
204  'uid' => self::STAGE_PUBLISH_EXECUTE_ID,
205  'title' => $GLOBALS['LANG']->sL($this->pathToLocallang . ':publish_execute_action_option')
206  );
207  $this->workspaceStageCache[$this->getWorkspaceId()] = $stages;
208  }
209  return $stages;
210  }
211 
217  public function getStagesForWSUser() {
218  $stagesForWSUserData = array();
219  $allowedStages = array();
220  $orderedAllowedStages = array();
221  $workspaceStageRecs = $this->getStagesForWS();
222  if (is_array($workspaceStageRecs) && !empty($workspaceStageRecs)) {
223  if ($GLOBALS['BE_USER']->isAdmin()) {
224  $orderedAllowedStages = $workspaceStageRecs;
225  } else {
226  foreach ($workspaceStageRecs as $workspaceStageRec) {
227  if ($workspaceStageRec['uid'] === self::STAGE_EDIT_ID) {
228  $allowedStages[self::STAGE_EDIT_ID] = $workspaceStageRec;
229  $stagesForWSUserData[$workspaceStageRec['uid']] = $workspaceStageRec;
230  } elseif ($this->isStageAllowedForUser($workspaceStageRec['uid'])) {
231  $stagesForWSUserData[$workspaceStageRec['uid']] = $workspaceStageRec;
232  } elseif ($workspaceStageRec['uid'] == self::STAGE_PUBLISH_EXECUTE_ID && $GLOBALS['BE_USER']->workspacePublishAccess($this->getWorkspaceId())) {
233  $allowedStages[] = $workspaceStageRec;
234  $stagesForWSUserData[$workspaceStageRec['uid']] = $workspaceStageRec;
235  }
236  }
237  foreach ($stagesForWSUserData as $allowedStage) {
238  $nextStage = $this->getNextStage($allowedStage['uid']);
239  $prevStage = $this->getPrevStage($allowedStage['uid']);
240  if (isset($prevStage['uid'])) {
241  $allowedStages[$prevStage['uid']] = $prevStage;
242  }
243  if (isset($nextStage['uid'])) {
244  $allowedStages[$nextStage['uid']] = $nextStage;
245  }
246  }
247  $orderedAllowedStages = array_values($allowedStages);
248  }
249  }
250  return $orderedAllowedStages;
251  }
252 
260  public function checkCustomStagingForWS() {
261  $workspaceRec = BackendUtility::getRecord('sys_workspace', $this->getWorkspaceId());
262  return $workspaceRec['custom_stages'] > 0;
263  }
264 
271  public function getStageTitle($ver_stage) {
272  global $LANG;
273  $stageTitle = '';
274  switch ($ver_stage) {
275  case self::STAGE_PUBLISH_EXECUTE_ID:
276  $stageTitle = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xlf:stage_publish');
277  break;
278  case self::STAGE_PUBLISH_ID:
279  $stageTitle = $GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang_mod.xlf:stage_ready_to_publish');
280  break;
281  case self::STAGE_EDIT_ID:
282  $stageTitle = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xlf:stage_editing');
283  break;
284  default:
285  $stageTitle = $this->getPropertyOfCurrentWorkspaceStage($ver_stage, 'title');
286  if ($stageTitle == NULL) {
287  $stageTitle = $GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:error.getStageTitle.stageNotFound');
288  }
289  }
290  return $stageTitle;
291  }
292 
299  public function getStageRecord($stageid) {
300  return BackendUtility::getRecord('sys_workspace_stage', $stageid);
301  }
302 
310  public function getNextStage($stageId) {
311  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($stageId)) {
312  throw new \InvalidArgumentException($GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:error.stageId.integer'), 1291109987);
313  }
314  $nextStage = FALSE;
315  $workspaceStageRecs = $this->getStagesForWS();
316  if (is_array($workspaceStageRecs) && !empty($workspaceStageRecs)) {
317  reset($workspaceStageRecs);
318  while (!is_null(($workspaceStageRecKey = key($workspaceStageRecs)))) {
319  $workspaceStageRec = current($workspaceStageRecs);
320  if ($workspaceStageRec['uid'] == $stageId) {
321  $nextStage = next($workspaceStageRecs);
322  break;
323  }
324  next($workspaceStageRecs);
325  }
326  } else {
327 
328  }
329  if ($nextStage === FALSE) {
330  $nextStage[] = array(
331  'uid' => self::STAGE_EDIT_ID,
332  'title' => $GLOBALS['LANG']->sL(($this->pathToLocallang . ':actionSendToStage')) . ' "'
333  . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_user_ws.xlf:stage_editing') . '"'
334  );
335  }
336  return $nextStage;
337  }
338 
346  public function getNextStages(array &$nextStageArray, $stageId) {
347  // Current stage is "Ready to publish" - there is no next stage
348  if ($stageId == self::STAGE_PUBLISH_ID) {
349  return $nextStageArray;
350  } else {
351  $nextStageRecord = $this->getNextStage($stageId);
352  if (empty($nextStageRecord) || !is_array($nextStageRecord)) {
353  // There is no next stage
354  return $nextStageArray;
355  } else {
356  // Check if the user has the permission to for the current stage
357  // If this next stage record is the first next stage after the current the user
358  // has always the needed permission
359  if ($this->isStageAllowedForUser($stageId)) {
360  $nextStageArray[] = $nextStageRecord;
361  return $this->getNextStages($nextStageArray, $nextStageRecord['uid']);
362  } else {
363  // He hasn't - return given next stage array
364  return $nextStageArray;
365  }
366  }
367  }
368  }
369 
377  public function getPrevStage($stageId) {
378  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($stageId)) {
379  throw new \InvalidArgumentException($GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:error.stageId.integer'));
380  }
381  $prevStage = FALSE;
382  $workspaceStageRecs = $this->getStagesForWS();
383  if (is_array($workspaceStageRecs) && !empty($workspaceStageRecs)) {
384  end($workspaceStageRecs);
385  while (!is_null(($workspaceStageRecKey = key($workspaceStageRecs)))) {
386  $workspaceStageRec = current($workspaceStageRecs);
387  if ($workspaceStageRec['uid'] == $stageId) {
388  $prevStage = prev($workspaceStageRecs);
389  break;
390  }
391  prev($workspaceStageRecs);
392  }
393  } else {
394 
395  }
396  return $prevStage;
397  }
398 
406  public function getPrevStages(array &$prevStageArray, $stageId) {
407  // Current stage is "Editing" - there is no prev stage
408  if ($stageId != self::STAGE_EDIT_ID) {
409  $prevStageRecord = $this->getPrevStage($stageId);
410  if (!empty($prevStageRecord) && is_array($prevStageRecord)) {
411  // Check if the user has the permission to switch to that stage
412  // If this prev stage record is the first previous stage before the current
413  // the user has always the needed permission
414  if ($this->isStageAllowedForUser($stageId)) {
415  $prevStageArray[] = $prevStageRecord;
416  $prevStageArray = $this->getPrevStages($prevStageArray, $prevStageRecord['uid']);
417  }
418  }
419  }
420  return $prevStageArray;
421  }
422 
430  public function getResponsibleBeUser($stageId, $selectDefaultUserField = FALSE) {
431  $workspaceRec = BackendUtility::getRecord('sys_workspace', $this->getWorkspaceId());
432  $recipientArray = array();
433  switch ($stageId) {
434  case self::STAGE_PUBLISH_EXECUTE_ID:
435 
436  case self::STAGE_PUBLISH_ID:
437  if (!$selectDefaultUserField) {
438  $userList = $this->getResponsibleUser($workspaceRec['adminusers'] . ',' . $workspaceRec['members']);
439  } else {
440  $notification_default_user = $workspaceRec['publish_notification_defaults'];
441  $userList = $this->getResponsibleUser($notification_default_user);
442  }
443  break;
444  case self::STAGE_EDIT_ID:
445  if (!$selectDefaultUserField) {
446  $userList = $this->getResponsibleUser($workspaceRec['adminusers'] . ',' . $workspaceRec['members']);
447  } else {
448  $notification_default_user = $workspaceRec['edit_notification_defaults'];
449  $userList = $this->getResponsibleUser($notification_default_user);
450  }
451  break;
452  default:
453  if (!$selectDefaultUserField) {
454  $responsible_persons = $this->getPropertyOfCurrentWorkspaceStage($stageId, 'responsible_persons');
455  $userList = $this->getResponsibleUser($responsible_persons);
456  } else {
457  $notification_default_user = $this->getPropertyOfCurrentWorkspaceStage($stageId, 'notification_defaults');
458  $userList = $this->getResponsibleUser($notification_default_user);
459  }
460  }
461  if (!empty($userList)) {
462  $userRecords = BackendUtility::getUserNames(
463  'username, uid, email, realName',
464  'AND uid IN (' . $userList . ')' . BackendUtility::BEenableFields('be_users')
465  );
466  }
467  if (!empty($userRecords) && is_array($userRecords)) {
468  foreach ($userRecords as $userUid => $userRecord) {
469  $recipientArray[$userUid] = $userRecord;
470  }
471  }
472  return $recipientArray;
473  }
474 
481  public function getResponsibleUser($stageRespValue) {
482  $stageValuesArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $stageRespValue, TRUE);
483  $beuserUidArray = array();
484  $begroupUidArray = array();
485 
486  foreach ($stageValuesArray as $uidvalue) {
487  if (strstr($uidvalue, 'be_users') !== FALSE) {
488  // Current value is a uid of a be_user record
489  $beuserUidArray[] = str_replace('be_users_', '', $uidvalue);
490  } elseif (strstr($uidvalue, 'be_groups') !== FALSE) {
491  $begroupUidArray[] = str_replace('be_groups_', '', $uidvalue);
492  } elseif ((int)$uidvalue) {
493  $beuserUidArray[] = (int)$uidvalue;
494  }
495  }
496 
497  if (!empty($begroupUidArray)) {
498  $allBeUserArray = BackendUtility::getUserNames();
499  $begroupUidList = implode(',', $begroupUidArray);
500  $this->userGroups = array();
501  $begroupUidArray = $this->fetchGroups($begroupUidList);
502  foreach ($begroupUidArray as $groupkey => $groupData) {
503  foreach ($allBeUserArray as $useruid => $userdata) {
504  if (\TYPO3\CMS\Core\Utility\GeneralUtility::inList($userdata['usergroup_cached_list'], $groupData['uid'])) {
505  $beuserUidArray[] = $useruid;
506  }
507  }
508  }
509  }
510 
511  array_unique($beuserUidArray);
512  return implode(',', $beuserUidArray);
513  }
514 
520  private function fetchGroups($grList, $idList = '') {
521  $cacheKey = md5($grList . $idList);
522  $groupList = array();
523  if (isset($this->fetchGroupsCache[$cacheKey])) {
524  $groupList = $this->fetchGroupsCache[$cacheKey];
525  } else {
526  if ($idList === '') {
527  // we're at the beginning of the recursion and therefore we need to reset the userGroups member
528  $this->userGroups = array();
529  }
530  $groupList = $this->fetchGroupsRecursive($grList);
531  $this->fetchGroupsCache[$cacheKey] = $groupList;
532  }
533  return $groupList;
534  }
535 
540  private function fetchGroupsFromDB(array $groups) {
541  $whereSQL = 'deleted=0 AND hidden=0 AND pid=0 AND uid IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($groups)) . ') ';
542  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'be_groups', $whereSQL);
543  // The userGroups array is filled
544  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
545  $this->userGroups[$row['uid']] = $row;
546  }
547  }
548 
556  private function fetchGroupsRecursive($grList, $idList = '') {
557  $requiredGroups = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $grList, TRUE);
558  $existingGroups = array_keys($this->userGroups);
559  $missingGroups = array_diff($requiredGroups, $existingGroups);
560  if (count($missingGroups) > 0) {
561  $this->fetchGroupsFromDB($missingGroups);
562  }
563  // Traversing records in the correct order
564  foreach ($requiredGroups as $uid) {
565  // traversing list
566  // Get row:
567  $row = $this->userGroups[$uid];
568  if (is_array($row) && !\TYPO3\CMS\Core\Utility\GeneralUtility::inList($idList, $uid)) {
569  // Must be an array and $uid should not be in the idList, because then it is somewhere previously in the grouplist
570  // If the localconf.php option isset the user of the sub- sub- groups will also be used
571  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['customStageShowRecipientRecursive'] == 1) {
572  // Include sub groups
573  if (trim($row['subgroup'])) {
574  // Make integer list
575  $theList = implode(',', \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $row['subgroup']));
576  // Get the subarray
577  $subbarray = $this->fetchGroups($theList, $idList . ',' . $uid);
578  list($subUid, $subArray) = each($subbarray);
579  // Merge the subarray to the already existing userGroups array
580  $this->userGroups[$subUid] = $subArray;
581  }
582  }
583  }
584  }
585  return $this->userGroups;
586  }
587 
596  public function getPropertyOfCurrentWorkspaceStage($stageId, $property) {
597  $result = NULL;
598  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($stageId)) {
599  throw new \InvalidArgumentException($GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:error.stageId.integer'));
600  }
601  $workspaceStage = BackendUtility::getRecord(self::TABLE_STAGE, $stageId);
602  if (is_array($workspaceStage) && isset($workspaceStage[$property])) {
603  $result = $workspaceStage[$property];
604  }
605  return $result;
606  }
607 
615  public function getPositionOfCurrentStage($stageId) {
616  $stagesOfWS = $this->getStagesForWS();
617  $countOfStages = count($stagesOfWS);
618  switch ($stageId) {
619  case self::STAGE_PUBLISH_ID:
620  $position = $countOfStages;
621  break;
622  case self::STAGE_EDIT_ID:
623  $position = 1;
624  break;
625  default:
626  $position = 1;
627  foreach ($stagesOfWS as $key => $stageInfoArray) {
628  $position++;
629  if ($stageId == $stageInfoArray['uid']) {
630  break;
631  }
632  }
633  }
634  return array('position' => $position, 'count' => $countOfStages);
635  }
636 
643  public function isPrevStageAllowedForUser($stageId) {
644  $isAllowed = FALSE;
645  try {
646  $prevStage = $this->getPrevStage($stageId);
647  // if there's no prev-stage the stageIds match,
648  // otherwise we've to check if the user is permitted to use the stage
649  if (!empty($prevStage) && $prevStage['uid'] != $stageId) {
650  // if the current stage is allowed for the user, the user is also allowed to send to prev
651  $isAllowed = $this->isStageAllowedForUser($stageId);
652  }
653  } catch (\Exception $e) {
654 
655  }
656  return $isAllowed;
657  }
658 
665  public function isNextStageAllowedForUser($stageId) {
666  $isAllowed = FALSE;
667  try {
668  $nextStage = $this->getNextStage($stageId);
669  // if there's no next-stage the stageIds match,
670  // otherwise we've to check if the user is permitted to use the stage
671  if (!empty($nextStage) && $nextStage['uid'] != $stageId) {
672  // if the current stage is allowed for the user, the user is also allowed to send to next
673  $isAllowed = $this->isStageAllowedForUser($stageId);
674  }
675  } catch (\Exception $e) {
676 
677  }
678  return $isAllowed;
679  }
680 
685  protected function isStageAllowedForUser($stageId) {
686  $cacheKey = $this->getWorkspaceId() . '_' . $stageId;
687  $isAllowed = FALSE;
688  if (isset($this->workspaceStageAllowedCache[$cacheKey])) {
689  $isAllowed = $this->workspaceStageAllowedCache[$cacheKey];
690  } else {
691  $isAllowed = $GLOBALS['BE_USER']->workspaceCheckStageForCurrent($stageId);
692  $this->workspaceStageAllowedCache[$cacheKey] = $isAllowed;
693  }
694  return $isAllowed;
695  }
696 
703  public function isValid($stageId) {
704  $isValid = FALSE;
705  $stages = $this->getStagesForWS();
706  foreach ($stages as $stage) {
707  if ($stage['uid'] == $stageId) {
708  $isValid = TRUE;
709  break;
710  }
711  }
712  return $isValid;
713  }
714 
727  public function getNotificationMode($stageId) {
728  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($stageId)) {
729  throw new \InvalidArgumentException($GLOBALS['LANG']->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:error.stageId.integer'));
730  }
731  switch ($stageId) {
732  case self::STAGE_PUBLISH_EXECUTE_ID:
733 
734  case self::STAGE_PUBLISH_ID:
735  $workspaceRecord = BackendUtility::getRecord('sys_workspace', $this->getWorkspaceId());
736  return $workspaceRecord['publish_notification_mode'];
737  break;
738  case self::STAGE_EDIT_ID:
739  $workspaceRecord = BackendUtility::getRecord('sys_workspace', $this->getWorkspaceId());
740  return $workspaceRecord['edit_notification_mode'];
741  break;
742  default:
743  $workspaceStage = BackendUtility::getRecord(self::TABLE_STAGE, $stageId);
744  if (is_array($workspaceStage) && isset($workspaceStage['notification_mode'])) {
745  return $workspaceStage['notification_mode'];
746  }
747  }
748  }
749 
753  protected function getBackendUser() {
754  return $GLOBALS['BE_USER'];
755  }
756 }
getNextStageForElementCollection( $workspaceItems, array $byTableName=array('tt_content', 'pages', 'pages_language_overlay'))
getPreviousStageForElementCollection( $workspaceItems, array $byTableName=array('tt_content', 'pages', 'pages_language_overlay'))
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
$uid
Definition: server.php:36
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
getPropertyOfCurrentWorkspaceStage($stageId, $property)
getPrevStages(array &$prevStageArray, $stageId)
static getUserNames($fields='username, usergroup, usergroup_cached_list, uid', $where='')
getNextStages(array &$nextStageArray, $stageId)
getResponsibleBeUser($stageId, $selectDefaultUserField=FALSE)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]