TYPO3 CMS  TYPO3_6-2
WorkspaceService.php
Go to the documentation of this file.
1 <?php
3 
22 
29 
33  protected $pageCache = array();
34 
38  protected $versionsOnPageCache = array();
39 
40  const TABLE_WORKSPACE = 'sys_workspace';
41  const SELECT_ALL_WORKSPACES = -98;
42  const LIVE_WORKSPACE_ID = 0;
49  public function getAvailableWorkspaces() {
50  $availableWorkspaces = array();
51  // add default workspaces
52  if ($GLOBALS['BE_USER']->checkWorkspace(array('uid' => (string) self::LIVE_WORKSPACE_ID))) {
53  $availableWorkspaces[self::LIVE_WORKSPACE_ID] = self::getWorkspaceTitle(self::LIVE_WORKSPACE_ID);
54  }
55  // add custom workspaces (selecting all, filtering by BE_USER check):
56  $customWorkspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid, title, adminusers, members', 'sys_workspace', 'pid = 0' . BackendUtility::deleteClause('sys_workspace'), '', 'title');
57  if (count($customWorkspaces)) {
58  foreach ($customWorkspaces as $workspace) {
59  if ($GLOBALS['BE_USER']->checkWorkspace($workspace)) {
60  $availableWorkspaces[$workspace['uid']] = $workspace['title'];
61  }
62  }
63  }
64  return $availableWorkspaces;
65  }
66 
72  public function getCurrentWorkspace() {
73  $workspaceId = $GLOBALS['BE_USER']->workspace;
74  $activeId = $GLOBALS['BE_USER']->getSessionData('tx_workspace_activeWorkspace');
75 
76  // Avoid invalid workspace settings
77  if ($activeId !== NULL && $activeId !== self::SELECT_ALL_WORKSPACES) {
78  $availableWorkspaces = $this->getAvailableWorkspaces();
79  if (!isset($availableWorkspaces[$activeId])) {
80  $activeId = NULL;
81  }
82  }
83 
84  if ($activeId !== NULL) {
85  $workspaceId = $activeId;
86  }
87 
88  return $workspaceId;
89  }
90 
97  static public function getWorkspaceTitle($wsId) {
98  $title = FALSE;
99  switch ($wsId) {
100  case self::LIVE_WORKSPACE_ID:
101  $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:shortcut_onlineWS');
102  break;
103  default:
104  $labelField = $GLOBALS['TCA']['sys_workspace']['ctrl']['label'];
105  $wsRecord = BackendUtility::getRecord('sys_workspace', $wsId, 'uid,' . $labelField);
106  if (is_array($wsRecord)) {
107  $title = $wsRecord[$labelField];
108  }
109  }
110  if ($title === FALSE) {
111  throw new \InvalidArgumentException('No such workspace defined');
112  }
113  return $title;
114  }
115 
125  public function getCmdArrayForPublishWS($wsid, $doSwap, $pageId = 0, $language = NULL) {
126  $wsid = (int)$wsid;
127  $cmd = array();
128  if ($wsid >= -1 && $wsid !== 0) {
129  // Define stage to select:
130  $stage = -99;
131  if ($wsid > 0) {
132  $workspaceRec = BackendUtility::getRecord('sys_workspace', $wsid);
133  if ($workspaceRec['publish_access'] & 1) {
135  }
136  }
137  // Select all versions to swap:
138  $versions = $this->selectVersionsInWorkspace($wsid, 0, $stage, $pageId ?: -1, 999, 'tables_modify', $language);
139  // Traverse the selection to build CMD array:
140  foreach ($versions as $table => $records) {
141  foreach ($records as $rec) {
142  // Build the cmd Array:
143  $cmd[$table][$rec['t3ver_oid']]['version'] = array('action' => 'swap', 'swapWith' => $rec['uid'], 'swapIntoWS' => $doSwap ? 1 : 0);
144  }
145  }
146  }
147  return $cmd;
148  }
149 
159  public function getCmdArrayForFlushWS($wsid, $flush = TRUE, $pageId = 0, $language = NULL) {
160  $wsid = (int)$wsid;
161  $cmd = array();
162  if ($wsid >= -1 && $wsid !== 0) {
163  // Define stage to select:
164  $stage = -99;
165  // Select all versions to swap:
166  $versions = $this->selectVersionsInWorkspace($wsid, 0, $stage, $pageId ?: -1, 999, 'tables_modify', $language);
167  // Traverse the selection to build CMD array:
168  foreach ($versions as $table => $records) {
169  foreach ($records as $rec) {
170  // Build the cmd Array:
171  $cmd[$table][$rec['uid']]['version'] = array('action' => $flush ? 'flush' : 'clearWSID');
172  }
173  }
174  }
175  return $cmd;
176  }
177 
192  public function selectVersionsInWorkspace($wsid, $filter = 0, $stage = -99, $pageId = -1, $recursionLevel = 0, $selectionType = 'tables_select', $language = NULL) {
193  $wsid = (int)$wsid;
194  $filter = (int)$filter;
195  $output = array();
196  // Contains either nothing or a list with live-uids
197  if ($pageId != -1 && $recursionLevel > 0) {
198  $pageList = $this->getTreeUids($pageId, $wsid, $recursionLevel);
199  } elseif ($pageId != -1) {
200  $pageList = $pageId;
201  } else {
202  $pageList = '';
203  // check if person may only see a "virtual" page-root
204  $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
205  $mountPoints = array_unique($mountPoints);
206  if (!in_array(0, $mountPoints)) {
207  $tempPageIds = array();
208  foreach ($mountPoints as $mountPoint) {
209  $tempPageIds[] = $this->getTreeUids($mountPoint, $wsid, $recursionLevel);
210  }
211  $pageList = implode(',', $tempPageIds);
212  $pageList = implode(',', array_unique(explode(',', $pageList)));
213  }
214  }
215  // Traversing all tables supporting versioning:
216  foreach ($GLOBALS['TCA'] as $table => $cfg) {
217  // we do not collect records from tables without permissions on them.
218  if (!$GLOBALS['BE_USER']->check($selectionType, $table)) {
219  continue;
220  }
221  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
222  $recs = $this->selectAllVersionsFromPages($table, $pageList, $wsid, $filter, $stage, $language);
223  if ((int)$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] === 2) {
224  $moveRecs = $this->getMoveToPlaceHolderFromPages($table, $pageList, $wsid, $filter, $stage);
225  $recs = array_merge($recs, $moveRecs);
226  }
227  $recs = $this->filterPermittedElements($recs, $table);
228  if (count($recs)) {
229  $output[$table] = $recs;
230  }
231  }
232  }
233  return $output;
234  }
235 
247  protected function selectAllVersionsFromPages($table, $pageList, $wsid, $filter, $stage, $language = NULL) {
248  // Include root level page as there might be some records with where root level restriction is ignored (e.g. FAL records)
249  if ($pageList !== '' && BackendUtility::isRootLevelRestrictionIgnored($table)) {
250  $pageList .= ',0';
251  }
252  $isTableLocalizable = BackendUtility::isTableLocalizable($table);
253  $languageParentField = '';
254  // If table is not localizable, but localized reocrds shall
255  // be collected, an empty result array needs to be returned:
256  if ($isTableLocalizable === FALSE && $language > 0) {
257  return array();
258  } elseif ($isTableLocalizable) {
259  $languageParentField = 'A.' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ', ';
260  }
261  $fields = 'A.uid, A.t3ver_oid, A.t3ver_stage, ' . $languageParentField . 'B.pid AS wspid, B.pid AS livepid';
262  if ($isTableLocalizable) {
263  $fields .= ', A.' . $GLOBALS['TCA'][$table]['ctrl']['languageField'];
264  }
265  $from = $table . ' A,' . $table . ' B';
266  // Table A is the offline version and pid=-1 defines offline
267  $where = 'A.pid=-1 AND A.t3ver_state!=' . new VersionState(VersionState::MOVE_POINTER);
268  if ($pageList) {
269  $pidField = $table === 'pages' ? 'uid' : 'pid';
270  $pidConstraint = strstr($pageList, ',') ? ' IN (' . $pageList . ')' : '=' . $pageList;
271  $where .= ' AND B.' . $pidField . $pidConstraint;
272  }
273  if ($isTableLocalizable && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($language)) {
274  $where .= ' AND A.' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '=' . $language;
275  }
276  // For "real" workspace numbers, select by that.
277  // If = -98, select all that are NOT online (zero).
278  // Anything else below -1 will not select on the wsid and therefore select all!
279  if ($wsid > self::SELECT_ALL_WORKSPACES) {
280  $where .= ' AND A.t3ver_wsid=' . $wsid;
281  } elseif ($wsid === self::SELECT_ALL_WORKSPACES) {
282  $where .= ' AND A.t3ver_wsid!=0';
283  }
284  // lifecycle filter:
285  // 1 = select all drafts (never-published),
286  // 2 = select all published one or more times (archive/multiple)
287  if ($filter === 1 || $filter === 2) {
288  $where .= ' AND A.t3ver_count ' . ($filter === 1 ? '= 0' : '> 0');
289  }
290  if ($stage != -99) {
291  $where .= ' AND A.t3ver_stage=' . (int)$stage;
292  }
293  // Table B (online) must have PID >= 0 to signify being online.
294  $where .= ' AND B.pid>=0';
295  // ... and finally the join between the two tables.
296  $where .= ' AND A.t3ver_oid=B.uid';
297  $where .= BackendUtility::deleteClause($table, 'A');
298  $where .= BackendUtility::deleteClause($table, 'B');
299  // Select all records from this table in the database from the workspace
300  // This joins the online version with the offline version as tables A and B
301  // Order by UID, mostly to have a sorting in the backend overview module which doesn't "jump around" when swapping.
302  $res = $this->getDatabaseConnection()->exec_SELECTgetRows($fields, $from, $where, '', 'B.uid');
303  return is_array($res) ? $res : array();
304  }
305 
316  protected function getMoveToPlaceHolderFromPages($table, $pageList, $wsid, $filter, $stage) {
317  // Aliases:
318  // A - moveTo placeholder
319  // B - online record
320  // C - moveFrom placeholder
321  $fields = 'A.pid AS wspid, B.uid AS t3ver_oid, C.uid AS uid, B.pid AS livepid';
322  $from = $table . ' A, ' . $table . ' B,' . $table . ' C';
323  $where = 'A.t3ver_state=' . new VersionState(VersionState::MOVE_PLACEHOLDER) . ' AND B.pid>0 AND B.t3ver_state='
324  . new VersionState(VersionState::DEFAULT_STATE) . ' AND B.t3ver_wsid=0 AND C.pid=-1 AND C.t3ver_state='
326  if ($wsid > self::SELECT_ALL_WORKSPACES) {
327  $where .= ' AND A.t3ver_wsid=' . $wsid . ' AND C.t3ver_wsid=' . $wsid;
328  } elseif ($wsid === self::SELECT_ALL_WORKSPACES) {
329  $where .= ' AND A.t3ver_wsid!=0 AND C.t3ver_wsid!=0 ';
330  }
331  // lifecycle filter:
332  // 1 = select all drafts (never-published),
333  // 2 = select all published one or more times (archive/multiple)
334  if ($filter === 1 || $filter === 2) {
335  $where .= ' AND C.t3ver_count ' . ($filter === 1 ? '= 0' : '> 0');
336  }
337  if ($stage != -99) {
338  $where .= ' AND C.t3ver_stage=' . (int)$stage;
339  }
340  if ($pageList) {
341  $pidField = $table === 'pages' ? 'B.uid' : 'A.pid';
342  $pidConstraint = strstr($pageList, ',') ? ' IN (' . $pageList . ')' : '=' . $pageList;
343  $where .= ' AND ' . $pidField . $pidConstraint;
344  }
345  $where .= ' AND A.t3ver_move_id = B.uid AND B.uid = C.t3ver_oid';
346  $where .= BackendUtility::deleteClause($table, 'A');
347  $where .= BackendUtility::deleteClause($table, 'B');
348  $where .= BackendUtility::deleteClause($table, 'C');
349  $res = $this->getDatabaseConnection()->exec_SELECTgetRows($fields, $from, $where, '', 'A.uid');
350  return is_array($res) ? $res : array();
351  }
352 
361  protected function getTreeUids($pageId, $wsid, $recursionLevel) {
362  // Reusing existing functionality with the drawback that
363  // mount points are not covered yet
364  $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
366  $searchObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\QueryView');
367  if ($pageId > 0) {
368  $pageList = $searchObj->getTreeList($pageId, $recursionLevel, 0, $perms_clause);
369  } else {
370  $mountPoints = $GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint'];
371  if (!is_array($mountPoints) || empty($mountPoints)) {
372  $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
373  $mountPoints = array_unique($mountPoints);
374  }
375  $newList = array();
376  foreach ($mountPoints as $mountPoint) {
377  $newList[] = $searchObj->getTreeList($mountPoint, $recursionLevel, 0, $perms_clause);
378  }
379  $pageList = implode(',', $newList);
380  }
381  unset($searchObj);
382  if ((int)$GLOBALS['TCA']['pages']['ctrl']['versioningWS'] === 2 && $pageList) {
383  // Remove the "subbranch" if a page was moved away
384  $movedAwayPages = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid, pid, t3ver_move_id', 'pages', 't3ver_move_id IN (' . $pageList . ') AND t3ver_wsid=' . (int)$wsid . BackendUtility::deleteClause('pages'), '', 'uid', '', 't3ver_move_id');
385  $pageIds = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $pageList, TRUE);
386  // move all pages away
387  $newList = array_diff($pageIds, array_keys($movedAwayPages));
388  // keep current page in the list
389  $newList[] = $pageId;
390  // move back in if still connected to the "remaining" pages
391  do {
392  $changed = FALSE;
393  foreach ($movedAwayPages as $uid => $rec) {
394  if (in_array($rec['pid'], $newList) && !in_array($uid, $newList)) {
395  $newList[] = $uid;
396  $changed = TRUE;
397  }
398  }
399  } while ($changed);
400  $pageList = implode(',', $newList);
401  // In case moving pages is enabled we need to replace all move-to pointer with their origin
402  $pages = $this->getDatabaseConnection()->exec_SELECTgetRows('uid, t3ver_move_id', 'pages', 'uid IN (' . $pageList . ')' . BackendUtility::deleteClause('pages'), '', 'uid', '', 'uid');
403  $newList = array();
404  $pageIds = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $pageList, TRUE);
405  if (!in_array($pageId, $pageIds)) {
406  $pageIds[] = $pageId;
407  }
408  foreach ($pageIds as $pageId) {
409  if ((int)$pages[$pageId]['t3ver_move_id'] > 0) {
410  $newList[] = (int)$pages[$pageId]['t3ver_move_id'];
411  } else {
412  $newList[] = $pageId;
413  }
414  }
415  $pageList = implode(',', $newList);
416  }
417  return $pageList;
418  }
419 
427  protected function filterPermittedElements($recs, $table) {
428  $permittedElements = array();
429  if (is_array($recs)) {
430  foreach ($recs as $rec) {
431  if ($this->isPageAccessibleForCurrentUser($table, $rec) && $this->isLanguageAccessibleForCurrentUser($table, $rec)) {
432  $permittedElements[] = $rec;
433  }
434  }
435  }
436  return $permittedElements;
437  }
438 
446  protected function isPageAccessibleForCurrentUser($table, array $record) {
447  $pageIdField = $table === 'pages' ? 'uid' : 'wspid';
448  $pageId = isset($record[$pageIdField]) ? (int)$record[$pageIdField] : NULL;
449  if ($pageId === NULL) {
450  return FALSE;
451  }
452  if ($pageId === 0 && BackendUtility::isRootLevelRestrictionIgnored($table)) {
453  return TRUE;
454  }
455  $page = BackendUtility::getRecord('pages', $pageId, 'uid,pid,perms_userid,perms_user,perms_groupid,perms_group,perms_everybody');
456 
457  return $GLOBALS['BE_USER']->doesUserHaveAccess($page, 1);
458  }
459 
467  protected function isLanguageAccessibleForCurrentUser($table, array $record) {
469  $languageUid = $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
470  } else {
471  return TRUE;
472  }
473  return $GLOBALS['BE_USER']->checkLanguageAccess($languageUid);
474  }
475 
482  static public function isOldStyleWorkspaceUsed() {
483  $cacheKey = 'workspace-oldstyleworkspace-notused';
484  $cacheResult = $GLOBALS['BE_USER']->getSessionData($cacheKey);
485  if (!$cacheResult) {
486  $where = 'adminusers != \'\' AND adminusers NOT LIKE \'%be_users%\' AND adminusers NOT LIKE \'%be_groups%\' AND deleted=0';
487  $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'sys_workspace', $where);
488  $oldStyleWorkspaceIsUsed = $count > 0;
489  $GLOBALS['BE_USER']->setAndSaveSessionData($cacheKey, !$oldStyleWorkspaceIsUsed);
490  } else {
491  $oldStyleWorkspaceIsUsed = !$cacheResult;
492  }
493  return $oldStyleWorkspaceIsUsed;
494  }
495 
504  static public function isNewPage($id, $language = 0) {
505  $isNewPage = FALSE;
506  // If the language is not default, check state of overlay
507  if ($language > 0) {
508  $whereClause = 'pid = ' . (int)$id;
509  $whereClause .= ' AND ' . $GLOBALS['TCA']['pages_language_overlay']['ctrl']['languageField'] . ' = ' . (int)$language;
510  $whereClause .= ' AND t3ver_wsid = ' . (int)$GLOBALS['BE_USER']->workspace;
511  $whereClause .= BackendUtility::deleteClause('pages_language_overlay');
512  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('t3ver_state', 'pages_language_overlay', $whereClause);
513  if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
514  $isNewPage = VersionState::cast($row['t3ver_state'])->equals(VersionState::NEW_PLACEHOLDER);
515  }
516  } else {
517  $rec = BackendUtility::getRecord('pages', $id, 't3ver_state');
518  if (is_array($rec)) {
519  $isNewPage = VersionState::cast($rec['t3ver_state'])->equals(VersionState::NEW_PLACEHOLDER);
520  }
521  }
522  return $isNewPage;
523  }
524 
535  static public function viewSingleRecord($table, $uid, array $liveRecord = NULL, array $versionRecord = NULL) {
536  $viewUrl = '';
537 
538  if ($table == 'pages') {
540  } elseif ($table === 'pages_language_overlay' || $table === 'tt_content') {
541  if ($liveRecord === NULL) {
542  $liveRecord = BackendUtility::getLiveVersionOfRecord($table, $uid);
543  }
544  if ($versionRecord === NULL) {
545  $versionRecord = BackendUtility::getRecord($table, $uid);
546  }
547  if (VersionState::cast($versionRecord['t3ver_state'])->equals(VersionState::MOVE_POINTER)) {
548  $movePlaceholder = BackendUtility::getMovePlaceholder($table, $liveRecord['uid'], 'pid');
549  }
550 
551  $previewPageId = (empty($movePlaceholder['pid']) ? $liveRecord['pid'] : $movePlaceholder['pid']);
552  $additionalParameters = '&tx_workspaces_web_workspacesworkspaces[previewWS]=' . $versionRecord['t3ver_wsid'];
553 
554  $languageField = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
555  if ($versionRecord[$languageField] > 0) {
556  $additionalParameters .= '&L=' . $versionRecord[$languageField];
557  }
558 
559  $viewUrl = BackendUtility::viewOnClick($previewPageId, '', '', '', '', $additionalParameters);
560  } else {
561  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['viewSingleRecord'])) {
562  $_params = array(
563  'table' => $table,
564  'uid' => $uid,
565  'record' => $liveRecord,
566  'liveRecord' => $liveRecord,
567  'versionRecord' => $versionRecord,
568  );
569  $_funcRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['viewSingleRecord'];
570  $null = NULL;
571  $viewUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($_funcRef, $_params, $null);
572  }
573  }
574 
575  return $viewUrl;
576  }
577 
585  public function canCreatePreviewLink($pageUid, $workspaceUid) {
586  $result = TRUE;
587  if ($pageUid > 0 && $workspaceUid > 0) {
588  $pageRecord = BackendUtility::getRecord('pages', $pageUid);
589  BackendUtility::workspaceOL('pages', $pageRecord, $workspaceUid);
590  if (
591  !GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'], $pageRecord['doktype'])
592  || VersionState::cast($pageRecord['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)
593  ) {
594  $result = FALSE;
595  }
596  } else {
597  $result = FALSE;
598  }
599  return $result;
600  }
601 
609  $previewObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Version\\Hook\\PreviewHook');
610  $timeToLiveHours = $previewObject->getPreviewLinkLifetime();
611  $previewKeyword = $previewObject->compilePreviewKeyword('', $GLOBALS['BE_USER']->user['uid'], $timeToLiveHours * 3600, $this->getCurrentWorkspace());
612  $linkParams = array(
613  'ADMCMD_prev' => $previewKeyword,
614  'id' => $uid
615  );
616  return BackendUtility::getViewDomain($uid) . '/index.php?' . \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('', $linkParams);
617  }
618 
626  public function generateWorkspaceSplittedPreviewLink($uid, $addDomain = FALSE) {
627  // In case a $pageUid is submitted we need to make sure it points to a live-page
628  if ($uid > 0) {
629  $uid = $this->getLivePageUid($uid);
630  }
632  $uriBuilder = $this->getObjectManager()->get('TYPO3\\CMS\\Extbase\\Mvc\\Web\\Routing\\UriBuilder');
633  // This seems to be very harsh to set this directly to "/typo3 but the viewOnClick also
634  // has /index.php as fixed value here and dealing with the backPath is very error-prone
635  // @todo make sure this would work in local extension installation too
636  $backPath = '/' . TYPO3_mainDir;
637  $redirect = $backPath . 'index.php?redirect_url=';
638  // @todo this should maybe be changed so that the extbase URI Builder can deal with module names directly
639  $originalM = GeneralUtility::_GET('M');
640  GeneralUtility::_GETset('web_WorkspacesWorkspaces', 'M');
641  $viewScript = $backPath . $uriBuilder->uriFor('index', array(), 'Preview', 'workspaces', 'web_workspacesworkspaces') . '&id=';
642  GeneralUtility::_GETset($originalM, 'M');
643  if ($addDomain === TRUE) {
644  return BackendUtility::getViewDomain($uid) . $redirect . urlencode($viewScript) . $uid;
645  } else {
646  return $viewScript;
647  }
648  }
649 
657  $previewUrl = $this->generateWorkspacePreviewLink($uid);
658  $previewLanguages = $this->getAvailableLanguages($uid);
659  $previewLinks = array();
660 
661  foreach ($previewLanguages as $languageUid => $language) {
662  $previewLinks[$language] = $previewUrl . '&L=' . $languageUid;
663  }
664 
665  return $previewLinks;
666  }
667 
676  public function getLivePageUid($uid) {
677  if (!isset($this->pageCache[$uid])) {
678  $pageRecord = BackendUtility::getRecord('pages', $uid);
679  if (is_array($pageRecord)) {
680  $this->pageCache[$uid] = $pageRecord['t3ver_oid'] ? $pageRecord['t3ver_oid'] : $uid;
681  } else {
682  throw new \InvalidArgumentException('uid is supposed to point to an existing page - given value was:' . $uid, 1290628113);
683  }
684  }
685  return $this->pageCache[$uid];
686  }
687 
695  public function hasPageRecordVersions($workspace, $pageId) {
696  $workspace = (int)$workspace;
697  $pageId = (int)$pageId;
698  if ($workspace === 0) {
699  return FALSE;
700  }
701 
702  if (isset($this->versionsOnPageCache[$pageId][$workspace])) {
703  return $this->versionsOnPageCache[$pageId][$workspace];
704  }
705 
706  if (!empty($this->versionsOnPageCache)) {
707  return FALSE;
708  }
709 
710  $this->versionsOnPageCache[$pageId][$workspace] = FALSE;
711  foreach ($GLOBALS['TCA'] as $tableName => $tableConfiguration) {
712  if ($tableName === 'pages' || empty($tableConfiguration['ctrl']['versioningWS'])) {
713  continue;
714  }
715  $joinStatement = 'A.t3ver_oid=B.uid';
716  // Consider records that are moved to a different page
718  $movePointer = new VersionState(VersionState::MOVE_POINTER);
719  $joinStatement = '(A.t3ver_oid=B.uid AND A.t3ver_state<>' . $movePointer
720  . ' OR A.t3ver_oid=B.t3ver_move_id AND A.t3ver_state=' . $movePointer . ')';
721  }
722  // Select all records from this table in the database from the workspace
723  // This joins the online version with the offline version as tables A and B
724  $records = $this->getDatabaseConnection()->exec_SELECTgetRows(
725  'B.uid as live_uid, B.pid as live_pid, A.uid as offline_uid',
726  $tableName . ' A,' . $tableName . ' B',
727  'A.pid=-1 AND A.t3ver_wsid=' . $workspace . ' AND ' . $joinStatement .
728  BackendUtility::deleteClause($tableName, 'A') . BackendUtility::deleteClause($tableName, 'B'),
729  'live_pid'
730  );
731 
732  if (!empty($records)) {
733  foreach ($records as $record) {
734  $this->versionsOnPageCache[$record['live_pid']][$workspace] = TRUE;
735  }
736  }
737  }
738 
739  return $this->versionsOnPageCache[$pageId][$workspace];
740  }
741 
745  protected function getDatabaseConnection() {
746  return $GLOBALS['TYPO3_DB'];
747  }
748 
752  protected function getObjectManager() {
753  return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
754  }
755 
762  public function getAvailableLanguages($pageId) {
763  $languageOptions = array();
765  $translationConfigurationProvider = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Configuration\\TranslationConfigurationProvider');
766  $systemLanguages = $translationConfigurationProvider->getSystemLanguages($pageId);
767 
768  if ($GLOBALS['BE_USER']->checkLanguageAccess(0)) {
769  // Use configured label for default language
770  $languageOptions[0] = $systemLanguages[0]['title'];
771  }
772  $pages = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $pageId);
773 
774  if (!is_array($pages)) {
775  return $languageOptions;
776  }
777 
778  foreach ($pages as $page) {
779  $languageId = (int)$page['sys_language_uid'];
780  // Only add links to active languages the user has access to
781  if (isset($systemLanguages[$languageId]) && $GLOBALS['BE_USER']->checkLanguageAccess($languageId)) {
782  $languageOptions[$page['sys_language_uid']] = $systemLanguages[$languageId]['title'];
783  }
784  }
785 
786  return $languageOptions;
787  }
788 }
static viewSingleRecord($table, $uid, array $liveRecord=NULL, array $versionRecord=NULL)
selectVersionsInWorkspace($wsid, $filter=0, $stage=-99, $pageId=-1, $recursionLevel=0, $selectionType='tables_select', $language=NULL)
static getRecordsByField($theTable, $theField, $theValue, $whereClause='', $groupBy='', $orderBy='', $limit='', $useDeleteClause=TRUE)
getMoveToPlaceHolderFromPages($table, $pageList, $wsid, $filter, $stage)
static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=FALSE)
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
$uid
Definition: server.php:36
static getMovePlaceholder($table, $uid, $fields=' *', $workspace=NULL)
getCmdArrayForFlushWS($wsid, $flush=TRUE, $pageId=0, $language=NULL)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
static _GETset($inputGet, $key='')
static viewOnClick($pageUid, $backPath='', $rootLine='', $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=TRUE)
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.
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
selectAllVersionsFromPages($table, $pageList, $wsid, $filter, $stage, $language=NULL)
getCmdArrayForPublishWS($wsid, $doSwap, $pageId=0, $language=NULL)
static getLiveVersionOfRecord($table, $uid, $fields=' *')
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static deleteClause($table, $tableAlias='')