‪TYPO3CMS  9.5
PreviewUriBuilder.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
32 
39 {
43  protected ‪$pageCache = [];
44 
49 
50  public function ‪__construct()
51  {
52  $this->workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
53  }
54 
62  public function ‪buildUriForPage(int $uid, int $languageId = 0): string
63  {
64  $previewKeyword = $this->‪compilePreviewKeyword(
65  (int)$this->‪getBackendUser()->user['uid'],
66  $this->‪getPreviewLinkLifetime() * 3600,
67  $this->workspaceService->getCurrentWorkspace()
68  );
69 
70  $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
71  try {
72  $site = $siteFinder->getSiteByPageId($uid);
73  try {
74  $language = $site->getLanguageById($languageId);
75  } catch (\InvalidArgumentException $e) {
76  $language = $site->getDefaultLanguage();
77  }
78  $uri = $site->getRouter()->generateUri($uid, ['ADMCMD_prev' => $previewKeyword, '_language' => $language], '');
79  return (string)$uri;
80  } catch (SiteNotFoundException | InvalidRouteArgumentsException $e) {
81  $linkParams = [
82  'ADMCMD_prev' => $previewKeyword,
83  'id' => $uid,
84  'L' => $languageId
85  ];
86  return ‪BackendUtility::getViewDomain($uid) . '/index.php?' . ‪HttpUtility::buildQueryString($linkParams);
87  }
88  }
89 
96  public function ‪buildUrisForAllLanguagesOfPage(int $pageId): array
97  {
98  $previewLanguages = $this->‪getAvailableLanguages($pageId);
99  $previewLinks = [];
100 
101  foreach ($previewLanguages as $languageUid => $language) {
102  $previewLinks[$language] = $this->‪buildUriForPage($pageId, $languageUid);
103  }
104 
105  return $previewLinks;
106  }
107 
116  public function ‪buildUriForWorkspaceSplitPreview(int $uid, bool $addDomain = false): string
117  {
118  // In case a $pageUid is submitted we need to make sure it points to a live-page
119  if ($uid > 0) {
120  $uid = $this->‪getLivePageUid($uid);
121  }
122  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
123  // the actual uid will be appended directly in BackendUtility Hook
124  $viewScript = $uriBuilder->buildUriFromRoute('workspace_previewcontrols', ['id' => $uid]);
125  if ($addDomain === true) {
126  $viewScript = $uriBuilder->buildUriFromRoute('workspace_previewcontrols', ['id' => $uid]);
127  return ‪BackendUtility::getViewDomain($uid) . 'index.php?redirect_url=' . urlencode((string)$viewScript);
128  }
129  return (string)$viewScript;
130  }
131 
141  public function ‪buildUriForElement(string $table, int $uid, array $liveRecord = null, array $versionRecord = null): string
142  {
143  if ($table === 'pages') {
145  }
146 
147  if ($liveRecord === null) {
148  $liveRecord = ‪BackendUtility::getLiveVersionOfRecord($table, $uid);
149  }
150  if ($versionRecord === null) {
151  $versionRecord = ‪BackendUtility::getRecord($table, $uid);
152  }
153  if (‪VersionState::cast($versionRecord['t3ver_state'])->equals(‪VersionState::MOVE_POINTER)) {
154  $movePlaceholder = ‪BackendUtility::getMovePlaceholder($table, $liveRecord['uid'], 'pid');
155  }
156 
157  // Directly use pid value and consider move placeholders
158  $previewPageId = (empty($movePlaceholder['pid']) ? $liveRecord['pid'] : $movePlaceholder['pid']);
159  $additionalParameters = '&previewWS=' . $versionRecord['t3ver_wsid'];
160  // Add language parameter if record is a localization
162  $languageField = ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'];
163  if ($versionRecord[$languageField] > 0) {
164  $additionalParameters .= '&L=' . $versionRecord[$languageField];
165  }
166  }
167 
168  $pageTsConfig = ‪BackendUtility::getPagesTSconfig($previewPageId);
169  $viewUrl = '';
170 
171  // Directly use determined direct page id
172  if ($table === 'tt_content') {
173  $viewUrl = ‪BackendUtility::viewOnClick($previewPageId, '', null, '', '', $additionalParameters);
174  } elseif (!empty($pageTsConfig['options.']['workspaces.']['previewPageId.'][$table]) || !empty($pageTsConfig['options.']['workspaces.']['previewPageId'])) {
175  // Analyze Page TSconfig options.workspaces.previewPageId
176  if (!empty($pageTsConfig['options.']['workspaces.']['previewPageId.'][$table])) {
177  $previewConfiguration = $pageTsConfig['options.']['workspaces.']['previewPageId.'][$table];
178  } else {
179  $previewConfiguration = $pageTsConfig['options.']['workspaces.']['previewPageId'];
180  }
181  // Extract possible settings (e.g. "field:pid")
182  list($previewKey, $previewValue) = explode(':', $previewConfiguration, 2);
183  if ($previewKey === 'field') {
184  $previewPageId = (int)$liveRecord[$previewValue];
185  } else {
186  $previewPageId = (int)$previewConfiguration;
187  }
188  $viewUrl = ‪BackendUtility::viewOnClick($previewPageId, '', null, '', '', $additionalParameters);
189  } elseif (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['viewSingleRecord'])) {
190  // Call user function to render the single record view
191  $_params = [
192  'table' => $table,
193  'uid' => $uid,
194  'record' => $liveRecord,
195  'liveRecord' => $liveRecord,
196  'versionRecord' => $versionRecord,
197  ];
198  $_funcRef = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['viewSingleRecord'];
199  $null = null;
200  $viewUrl = GeneralUtility::callUserFunction($_funcRef, $_params, $null);
201  }
202 
203  return $viewUrl;
204  }
205 
214  protected function ‪compilePreviewKeyword(int $backendUserUid, int $ttl = 172800, int $workspaceId = null): string
215  {
216  $keyword = md5(uniqid(microtime(), true));
217  GeneralUtility::makeInstance(ConnectionPool::class)
218  ->getConnectionForTable('sys_preview')
219  ->insert(
220  'sys_preview',
221  [
222  'keyword' => $keyword,
223  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
224  'endtime' => ‪$GLOBALS['EXEC_TIME'] + $ttl,
225  'config' => json_encode([
226  'fullWorkspace' => $workspaceId,
227  'BEUSER_uid' => $backendUserUid
228  ])
229  ]
230  );
231 
232  return $keyword;
233  }
234 
242  protected function ‪getPreviewLinkLifetime(): int
243  {
244  $ttlHours = (int)($this->‪getBackendUser()->‪getTSConfig()['options.']['workspaces.']['previewLinkTTLHours'] ?? 0);
245  return $ttlHours ?: 24 * 2;
246  }
247 
256  protected function ‪getLivePageUid(int $uid): int
257  {
258  if (!isset($this->pageCache[$uid])) {
259  $pageRecord = ‪BackendUtility::getRecord('pages', $uid);
260  if (is_array($pageRecord)) {
261  $this->pageCache[$uid] = $pageRecord['t3ver_oid'] ? (int)$pageRecord['t3ver_oid'] : $uid;
262  } else {
263  throw new \InvalidArgumentException('uid is supposed to point to an existing page - given value was: ' . $uid, 1290628113);
264  }
265  }
266  return $this->pageCache[$uid];
267  }
268 
275  protected function ‪getAvailableLanguages(int $pageId): array
276  {
277  $languageOptions = [];
278  $translationConfigurationProvider = GeneralUtility::makeInstance(TranslationConfigurationProvider::class);
279  $systemLanguages = $translationConfigurationProvider->getSystemLanguages($pageId);
280 
281  if ($this->‪getBackendUser()->checkLanguageAccess(0)) {
282  // Use configured label for default language
283  $languageOptions[0] = $systemLanguages[0]['title'];
284  }
285 
286  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
287  ->getQueryBuilderForTable('pages');
288  $queryBuilder->getRestrictions()
289  ->removeAll()
290  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
291  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
292 
293  $result = $queryBuilder->select('sys_language_uid')
294  ->from('pages')
295  ->where(
296  $queryBuilder->expr()->eq(
297  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
298  $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
299  )
300  )
301  ->execute();
302 
303  while ($row = $result->fetch()) {
304  $languageId = (int)$row['sys_language_uid'];
305  // Only add links to active languages the user has access to
306  if (isset($systemLanguages[$languageId]) && $this->‪getBackendUser()->‪checkLanguageAccess($languageId)) {
307  $languageOptions[$languageId] = $systemLanguages[$languageId]['title'];
308  }
309  }
310 
311  return $languageOptions;
312  }
313 
317  protected function ‪getBackendUser(): BackendUserAuthentication
318  {
319  return ‪$GLOBALS['BE_USER'];
320  }
321 }
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\$pageCache
‪array $pageCache
Definition: PreviewUriBuilder.php:42
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\buildUriForWorkspaceSplitPreview
‪string buildUriForWorkspaceSplitPreview(int $uid, bool $addDomain=false)
Definition: PreviewUriBuilder.php:114
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\$workspaceService
‪WorkspaceService $workspaceService
Definition: PreviewUriBuilder.php:46
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig($objectString=null, $config=null)
Definition: BackendUserAuthentication.php:1232
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction
Definition: BackendWorkspaceRestriction.php:28
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_POINTER
‪const MOVE_POINTER
Definition: VersionState.php:72
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\__construct
‪__construct()
Definition: PreviewUriBuilder.php:48
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\getPreviewLinkLifetime
‪int getPreviewLinkLifetime()
Definition: PreviewUriBuilder.php:240
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\buildUriForPage
‪string buildUriForPage(int $uid, int $languageId=0)
Definition: PreviewUriBuilder.php:60
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:182
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\getAvailableLanguages
‪array getAvailableLanguages(int $pageId)
Definition: PreviewUriBuilder.php:273
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:160
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionOfRecord
‪static array null getLiveVersionOfRecord($table, $uid, $fields=' *')
Definition: BackendUtility.php:4213
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder
Definition: PreviewUriBuilder.php:39
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: PreviewUriBuilder.php:315
‪TYPO3\CMS\Backend\Utility\BackendUtility\getMovePlaceholder
‪static array bool getMovePlaceholder($table, $uid, $fields=' *', $workspace=null)
Definition: BackendUtility.php:4311
‪TYPO3\CMS\Backend\Utility\BackendUtility\getViewDomain
‪static string getViewDomain($pageId, $rootLine=null)
Definition: BackendUtility.php:2864
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:733
‪TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException
Definition: InvalidRouteArgumentsException.php:23
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Workspaces\Service\WorkspaceService
Definition: WorkspaceService.php:34
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2616
‪TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider
Definition: TranslationConfigurationProvider.php:35
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionIdOfRecord
‪static int getLiveVersionIdOfRecord($table, $uid)
Definition: BackendUtility.php:4229
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableLocalizable
‪static bool isTableLocalizable($table)
Definition: BackendUtility.php:616
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
Definition: BackendUtility.php:864
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Workspaces\Preview
Definition: PreviewUriBuilder.php:3
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\buildUrisForAllLanguagesOfPage
‪array buildUrisForAllLanguagesOfPage(int $pageId)
Definition: PreviewUriBuilder.php:94
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\buildUriForElement
‪string buildUriForElement(string $table, int $uid, array $liveRecord=null, array $versionRecord=null)
Definition: PreviewUriBuilder.php:139
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\compilePreviewKeyword
‪string compilePreviewKeyword(int $backendUserUid, int $ttl=172800, int $workspaceId=null)
Definition: PreviewUriBuilder.php:212
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder\getLivePageUid
‪int getLivePageUid(int $uid)
Definition: PreviewUriBuilder.php:254