‪TYPO3CMS  11.5
ReviewController.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
25 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Core\Page\PageRenderer;
37 
42 {
46  protected ‪$moduleTemplate;
47 
51  protected ‪$view;
52 
56  protected ‪$pageId;
57 
61  protected PageRenderer ‪$pageRenderer;
64 
65  public function ‪__construct(
69  PageRenderer ‪$pageRenderer,
72  ) {
73  $this->workspaceService = ‪$workspaceService;
74  $this->stagesService = ‪$stagesService;
75  $this->iconFactory = ‪$iconFactory;
76  $this->pageRenderer = ‪$pageRenderer;
77  $this->uriBuilder = ‪$uriBuilder;
78  $this->moduleTemplateFactory = ‪$moduleTemplateFactory;
79  }
80 
84  protected function ‪initializeAction()
85  {
86  $icons = [
87  'language' => $this->iconFactory->getIcon('flags-multiple', ‪Icon::SIZE_SMALL)->render(),
88  'integrity' => $this->iconFactory->getIcon('status-dialog-information', ‪Icon::SIZE_SMALL)->render(),
89  'success' => $this->iconFactory->getIcon('status-dialog-ok', ‪Icon::SIZE_SMALL)->render(),
90  'info' => $this->iconFactory->getIcon('status-dialog-information', ‪Icon::SIZE_SMALL)->render(),
91  'warning' => $this->iconFactory->getIcon('status-dialog-warning', ‪Icon::SIZE_SMALL)->render(),
92  'error' => $this->iconFactory->getIcon('status-dialog-error', ‪Icon::SIZE_SMALL)->render(),
93  ];
94  $this->pageRenderer->addInlineSetting('Workspaces', 'icons', $icons);
95  $this->pageRenderer->addInlineLanguageLabelFile('EXT:workspaces/Resources/Private/Language/locallang.xlf');
96  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Workspaces/Backend');
97  $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/MultiRecordSelection');
98  $this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', (string)$this->uriBuilder->buildUriFromRoute('record_edit'));
99  $this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', (string)$this->uriBuilder->buildUriFromRoute('record_history'));
100  $this->pageRenderer->addInlineSetting('Workspaces', 'id', $this->pageId);
101  $this->pageRenderer->addInlineSetting('WebLayout', 'moduleUrl', (string)$this->uriBuilder->buildUriFromRoute(
102  trim($this->‪getBackendUser()->getTSConfig()['options.']['overridePageModule'] ?? 'web_layout')
103  ));
104  }
105 
113  public function ‪indexAction(ServerRequestInterface $request): ResponseInterface
114  {
115  $this->moduleTemplate = $this->moduleTemplateFactory->create($request);
116  $queryParams = $request->getQueryParams();
117  $this->pageId = (int)($queryParams['id'] ?? 0);
118 
119  $this->‪initializeAction();
120 
121  $this->view = GeneralUtility::makeInstance(StandaloneView::class);
122  $this->view->setTemplate('Index');
123  // This is only needed for translate VH to resolve 'label only' to default locallang.xlf files
124  $this->view->getRequest()->setControllerExtensionName('Workspaces');
125  $this->view->setTemplateRootPaths(['EXT:workspaces/Resources/Private/Templates/Review']);
126  $this->view->setPartialRootPaths(['EXT:workspaces/Resources/Private/Partials']);
127  $this->view->setLayoutRootPaths(['EXT:workspaces/Resources/Private/Layouts']);
128 
129  $backendUser = $this->‪getBackendUser();
130  $pageTitle = '';
131 
132  if ($this->pageId) {
133  $pageRecord = BackendUtility::getRecord('pages', $this->pageId);
134  if ($pageRecord) {
135  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pageRecord);
136  $pageTitle = BackendUtility::getRecordTitle('pages', $pageRecord);
137  }
138  }
139  $availableWorkspaces = $this->workspaceService->getAvailableWorkspaces();
140  $customWorkspaceExists = $this->‪customWorkspaceExists($availableWorkspaces);
141  $activeWorkspace = (int)$backendUser->workspace;
142  $activeWorkspaceTitle = ‪WorkspaceService::getWorkspaceTitle($activeWorkspace);
143  if (isset($queryParams['workspace'])) {
144  $switchWs = (int)$queryParams['workspace'];
145  if (array_key_exists($switchWs, $availableWorkspaces) && $activeWorkspace !== $switchWs) {
146  $activeWorkspace = $switchWs;
147  $backendUser->setWorkspace($activeWorkspace);
148  $activeWorkspaceTitle = ‪WorkspaceService::getWorkspaceTitle($activeWorkspace);
149  $this->view->assign('workspaceSwitched', GeneralUtility::jsonEncodeForHtmlAttribute(['id' => $activeWorkspace, 'title' => $activeWorkspaceTitle]));
150  }
151  }
152  $workspaceIsAccessible = $backendUser->workspace !== ‪WorkspaceService::LIVE_WORKSPACE_ID;
153 
154  $this->moduleTemplate->setTitle(
155  $this->‪getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang_mod.xlf:mlang_tabs_tab') . ' [' . $activeWorkspaceTitle . ']',
156  $pageTitle
157  );
158 
159  $this->view->assignMultiple([
160  'isAdmin' => $backendUser->isAdmin(),
161  'customWorkspaceExists' => $customWorkspaceExists,
162  'showGrid' => $workspaceIsAccessible,
163  'showLegend' => $workspaceIsAccessible,
164  'pageUid' => $this->pageId,
165  'pageTitle' => $pageTitle,
166  'activeWorkspaceUid' => $activeWorkspace,
167  'activeWorkspaceTitle' => $activeWorkspaceTitle,
168  'availableLanguages' => $this->getSystemLanguages($this->pageId),
169  'availableStages' => $this->stagesService->getStagesForWSUser(),
170  'availableSelectStages' => $this->getAvailableSelectStages(),
171  'stageActions' => $this->getStageActions(),
172  'showEntireWorkspaceDropDown' => !(($backendUser->workspaceRec['publish_access'] ?? 0) & 4),
173  'selectedLanguage' => $this->getLanguageSelection(),
174  'selectedDepth' => $this->getDepthSelection(),
175  'selectedStage' => $this->getStageSelection(),
176  ]);
177 
178  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
179  if ($this->‪canCreatePreviewLink($this->pageId, $activeWorkspace)) {
180  $showButton = $buttonBar->makeLinkButton()
181  ->setHref('#')
182  ->setClasses('t3js-preview-link')
183  ->setShowLabelText(true)
184  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:tooltip.generatePagePreview'))
185  ->setIcon($this->iconFactory->getIcon('actions-version-workspaces-preview-link', ‪Icon::SIZE_SMALL));
186  $buttonBar->addButton($showButton);
187  }
188 
189  if ($backendUser->isAdmin() && $activeWorkspace) {
190  $editWorkspaceRecordUrl = (string)$this->uriBuilder->buildUriFromRoute('record_edit', [
191  'edit' => [
192  'sys_workspace' => [
193  $activeWorkspace => 'edit',
194  ],
195  ],
196  'returnUrl' => (string)$this->uriBuilder->buildUriFromRoute('web_WorkspacesWorkspaces', ['id' => $this->pageId]),
197  ]);
198  $editSettingsButton = $buttonBar->makeLinkButton()
199  ->setHref($editWorkspaceRecordUrl)
200  ->setShowLabelText(true)
201  ->setTitle($this->‪getLanguageService()->‪sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:button.editWorkspaceSettings'))
202  ->setIcon($this->iconFactory->getIcon('actions-cog-alt', ‪Icon::SIZE_SMALL));
203  $buttonBar->addButton(
204  $editSettingsButton,
206  90
207  );
208  }
209 
210  $shortcutButton = $buttonBar->makeShortcutButton()
211  ->setRouteIdentifier('web_WorkspacesWorkspaces')
212  ->setDisplayName(sprintf('%s: %s [%d]', $activeWorkspaceTitle, $pageTitle, $this->pageId))
213  ->setArguments(['id' => (int)‪$this->pageId]);
214  $buttonBar->addButton($shortcutButton);
215 
216  $this->‪makeActionMenu($this->‪prepareWorkspaceTabs($availableWorkspaces, $activeWorkspace));
217 
218  $this->moduleTemplate->setContent($this->view->render());
219  return new HtmlResponse($this->moduleTemplate->renderContent());
220  }
221 
227  protected function ‪makeActionMenu(array $availableWorkspaces): void
228  {
229  $actionMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
230  $actionMenu->setIdentifier('workspaceSelector');
231  $actionMenu->setLabel('');
232  foreach ($availableWorkspaces as $workspaceData) {
233  $menuItem = $actionMenu
234  ->makeMenuItem()
235  ->setTitle($workspaceData['title'])
236  ->setHref($workspaceData['url']);
237  if ($workspaceData['active']) {
238  $menuItem->setActive(true);
239  }
240  $actionMenu->addMenuItem($menuItem);
241  }
242  $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($actionMenu);
243  }
244 
252  protected function ‪prepareWorkspaceTabs(array $workspaceList, int $activeWorkspace)
253  {
254  $tabs = [];
255  $tabs[] = [
256  'title' => $workspaceList[$activeWorkspace],
257  'itemId' => 'workspace-' . $activeWorkspace,
258  'active' => true,
259  'url' => $this->‪getModuleUri(),
260  ];
261 
262  foreach ($workspaceList as $workspaceId => $workspaceTitle) {
263  if ($workspaceId === $activeWorkspace) {
264  continue;
265  }
266  $tabs[] = [
267  'title' => $workspaceTitle,
268  'itemId' => 'workspace-' . $workspaceId,
269  'active' => false,
270  'url' => $this->‪getModuleUri((int)$workspaceId),
271  ];
272  }
273 
274  return $tabs;
275  }
276 
283  protected function ‪getModuleUri(int $workspaceId = null): string
284  {
285  $parameters = [
286  'id' => ‪$this->pageId,
287  ];
288  if ($workspaceId !== null) {
289  $parameters['workspace'] = $workspaceId;
290  }
291  return (string)$this->uriBuilder->buildUriFromRoute('web_WorkspacesWorkspaces', $parameters);
292  }
293 
301  protected function ‪canCreatePreviewLink(int $pageUid, int $workspaceUid): bool
302  {
303  if ($pageUid > 0 && $workspaceUid > 0) {
304  $pageRecord = BackendUtility::getRecord('pages', $pageUid);
305  BackendUtility::workspaceOL('pages', $pageRecord, $workspaceUid);
306  if (‪VersionState::cast($pageRecord['t3ver_state'])->equals(‪VersionState::DELETE_PLACEHOLDER)) {
307  return false;
308  }
309  return true;
310  }
311  return false;
312  }
313 
319  protected function ‪getLanguageSelection(): string
320  {
321  $moduleData = $this->‪getBackendUser()->‪getModuleData('workspaces') ?? [];
322  return (string)($moduleData['settings']['language'] ?? 'all');
323  }
324 
325  protected function ‪getDepthSelection(): int
326  {
327  $moduleData = $this->‪getBackendUser()->‪getModuleData('workspaces') ?? [];
328  return (int)($moduleData['settings']['depth'] ?? ($this->pageId === 0 ? 999 : 1));
329  }
330 
331  protected function ‪getStageSelection(): int
332  {
333  $moduleData = $this->‪getBackendUser()->‪getModuleData('workspaces') ?? [];
334  return (int)($moduleData['settings']['stage'] ?? -99);
335  }
336 
343  protected function ‪customWorkspaceExists(array $workspaceList): bool
344  {
345  foreach (array_keys($workspaceList) as $workspaceId) {
346  if ($workspaceId > 0) {
347  return true;
348  }
349  }
350  return false;
351  }
352 
356  protected function ‪getLanguageService(): LanguageService
357  {
358  return ‪$GLOBALS['LANG'];
359  }
360 
364  protected function ‪getBackendUser(): BackendUserAuthentication
365  {
366  return ‪$GLOBALS['BE_USER'];
367  }
368 
375  protected function ‪getSystemLanguages(int ‪$pageId): array
376  {
377  $languages = GeneralUtility::makeInstance(TranslationConfigurationProvider::class)->getSystemLanguages(‪$pageId);
378  if (isset($languages[-1])) {
379  $languages[-1]['uid'] = 'all';
380  }
381  $activeLanguage = $this->‪getLanguageSelection();
382  foreach ($languages as &$language) {
383  // needs to be strict type checking as this is not possible in fluid
384  if ((string)$language['uid'] === $activeLanguage) {
385  $language['active'] = true;
386  }
387  }
388  return $languages;
389  }
390 
394  protected function ‪getStageActions(): array
395  {
396  $actions = [];
397  $currentWorkspace = $this->workspaceService->getCurrentWorkspace();
398  $backendUser = $this->‪getBackendUser();
399  $massActionsEnabled = (bool)($backendUser->getTSConfig()['options.']['workspaces.']['enableMassActions'] ?? true);
400  if ($massActionsEnabled) {
401  $publishAccess = $backendUser->workspacePublishAccess($currentWorkspace);
402  if ($publishAccess && !(($backendUser->workspaceRec['publish_access'] ?? 0) & 1)) {
403  $actions[] = ['action' => 'publish', 'title' => $this->‪getLanguageService()->‪sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:label_doaction_publish')];
404  }
405  if ($currentWorkspace !== ‪WorkspaceService::LIVE_WORKSPACE_ID) {
406  $actions[] = ['action' => 'discard', 'title' => $this->‪getLanguageService()->‪sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:label_doaction_discard')];
407  }
408  }
409  return $actions;
410  }
411 
416  protected function ‪getAvailableSelectStages(): array
417  {
418  $stages = $this->stagesService->getStagesForWSUser();
419 
420  return array_merge([
421  [
422  'uid' => -99,
423  'label' => $this->‪getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang_mod_user_ws.xlf:stage_all'),
424  ],
425  ], array_filter($stages, static fn(array $stage): bool => (int)($stage['uid'] ?? 0) !== -20));
426  }
427 }
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:30
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$moduleTemplate
‪ModuleTemplate $moduleTemplate
Definition: ReviewController.php:45
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:36
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:32
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getDepthSelection
‪getDepthSelection()
Definition: ReviewController.php:322
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$workspaceService
‪WorkspaceService $workspaceService
Definition: ReviewController.php:55
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getAvailableSelectStages
‪getAvailableSelectStages()
Definition: ReviewController.php:413
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:26
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:29
‪TYPO3\CMS\Workspaces\Controller\ReviewController\customWorkspaceExists
‪bool customWorkspaceExists(array $workspaceList)
Definition: ReviewController.php:340
‪TYPO3\CMS\Workspaces\Controller\ReviewController
Definition: ReviewController.php:42
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getLanguageSelection
‪string getLanguageSelection()
Definition: ReviewController.php:316
‪TYPO3\CMS\Workspaces\Controller\ReviewController\indexAction
‪ResponseInterface indexAction(ServerRequestInterface $request)
Definition: ReviewController.php:110
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$iconFactory
‪IconFactory $iconFactory
Definition: ReviewController.php:57
‪TYPO3\CMS\Workspaces\Controller\ReviewController\makeActionMenu
‪makeActionMenu(array $availableWorkspaces)
Definition: ReviewController.php:224
‪TYPO3\CMS\Workspaces\Service\WorkspaceService\LIVE_WORKSPACE_ID
‪const LIVE_WORKSPACE_ID
Definition: WorkspaceService.php:46
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:61
‪TYPO3\CMS\Workspaces\Controller\ReviewController\initializeAction
‪initializeAction()
Definition: ReviewController.php:81
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:161
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$stagesService
‪StagesService $stagesService
Definition: ReviewController.php:56
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:46
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$pageId
‪int $pageId
Definition: ReviewController.php:53
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$pageRenderer
‪PageRenderer $pageRenderer
Definition: ReviewController.php:58
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:40
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getModuleData
‪mixed getModuleData($module, $type='')
Definition: AbstractUserAuthentication.php:1054
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$view
‪StandaloneView $view
Definition: ReviewController.php:49
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getModuleUri
‪string getModuleUri(int $workspaceId=null)
Definition: ReviewController.php:280
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: ReviewController.php:361
‪TYPO3\CMS\Workspaces\Controller\ReviewController\__construct
‪__construct(WorkspaceService $workspaceService, StagesService $stagesService, IconFactory $iconFactory, PageRenderer $pageRenderer, UriBuilder $uriBuilder, ModuleTemplateFactory $moduleTemplateFactory)
Definition: ReviewController.php:62
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getLanguageService
‪LanguageService getLanguageService()
Definition: ReviewController.php:353
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Workspaces\Controller\ReviewController\canCreatePreviewLink
‪bool canCreatePreviewLink(int $pageUid, int $workspaceUid)
Definition: ReviewController.php:298
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$moduleTemplateFactory
‪ModuleTemplateFactory $moduleTemplateFactory
Definition: ReviewController.php:60
‪TYPO3\CMS\Workspaces\Service\WorkspaceService
Definition: WorkspaceService.php:36
‪TYPO3\CMS\Workspaces\Service\StagesService
Definition: StagesService.php:32
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:24
‪TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider
Definition: TranslationConfigurationProvider.php:37
‪TYPO3\CMS\Workspaces\Controller\ReviewController\prepareWorkspaceTabs
‪array prepareWorkspaceTabs(array $workspaceList, int $activeWorkspace)
Definition: ReviewController.php:249
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:31
‪TYPO3\CMS\Workspaces\Controller\ReviewController\$uriBuilder
‪UriBuilder $uriBuilder
Definition: ReviewController.php:59
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getSystemLanguages
‪array getSystemLanguages(int $pageId)
Definition: ReviewController.php:372
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getStageSelection
‪getStageSelection()
Definition: ReviewController.php:328
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Workspaces\Controller
Definition: AjaxController.php:16
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:26
‪TYPO3\CMS\Workspaces\Service\WorkspaceService\getWorkspaceTitle
‪static string getWorkspaceTitle($wsId)
Definition: WorkspaceService.php:120
‪TYPO3\CMS\Workspaces\Controller\ReviewController\getStageActions
‪getStageActions()
Definition: ReviewController.php:391