[TASK] Clean up workspace preview top bar
[Packages/TYPO3.CMS.git] / typo3 / sysext / workspaces / Classes / Controller / PreviewController.php
index 3850a7d..a5774a0 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+declare(strict_types = 1);
 namespace TYPO3\CMS\Workspaces\Controller;
 
 /*
@@ -14,21 +15,22 @@ namespace TYPO3\CMS\Workspaces\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
+use TYPO3\CMS\Backend\Template\ModuleTemplate;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\View\BackendTemplateView;
-use TYPO3\CMS\Core\Messaging\FlashMessage;
-use TYPO3\CMS\Core\Messaging\FlashMessageService;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Http\HtmlResponse;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\PathUtility;
-use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
-use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Workspaces\Service\StagesService;
 use TYPO3\CMS\Workspaces\Service\WorkspaceService;
 
 /**
  * Implements the preview controller of the workspace module.
  */
-class PreviewController extends AbstractController
+class PreviewController
 {
     /**
      * @var StagesService
@@ -41,140 +43,138 @@ class PreviewController extends AbstractController
     protected $workspaceService;
 
     /**
-     * Set up the doc header properly here
+     * @var int
+     */
+    protected $pageId;
+
+    /**
+     * ModuleTemplate object
      *
-     * @param ViewInterface $view
+     * @var ModuleTemplate
      */
-    protected function initializeView(ViewInterface $view)
-    {
-        if ($view instanceof BackendTemplateView) {
-            /** @var BackendTemplateView $view */
-            parent::initializeView($view);
-            $view->getModuleTemplate()->getDocHeaderComponent()->disable();
-            $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
-        }
-    }
+    protected $moduleTemplate;
+
+    /**
+     * @var \TYPO3Fluid\Fluid\View\ViewInterface
+     */
+    protected $view;
 
     /**
-     * Initializes the controller before invoking an action method.
+     * Set up the module template
      */
-    protected function initializeAction()
+    public function __construct()
     {
-        parent::initializeAction();
-        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
         $this->stageService = GeneralUtility::makeInstance(StagesService::class);
         $this->workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
+        $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
+        $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Workspaces/Preview');
+        $this->moduleTemplate->getDocHeaderComponent()->disable();
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         $states = $this->getBackendUser()->uc['moduleData']['Workspaces']['States'];
-        $this->pageRenderer->addInlineSetting('Workspaces', 'States', $states);
-        $this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('record_edit'));
-        $this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('record_history'));
-        // @todo this part should be done with inlineLocallanglabels
-        $this->pageRenderer->addJsInlineCode('workspace-inline-code', $this->generateJavascript());
+        $this->moduleTemplate->getPageRenderer()->addInlineSetting('Workspaces', 'States', $states);
+        $this->moduleTemplate->getPageRenderer()->addInlineSetting('FormEngine', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('record_edit'));
+        $this->moduleTemplate->getPageRenderer()->addInlineSetting('RecordHistory', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('record_history'));
+        $this->moduleTemplate->getPageRenderer()->addJsInlineCode('workspace-inline-code', $this->generateJavascript());
+        $this->moduleTemplate->getPageRenderer()->addCssFile('EXT:workspaces/Resources/Public/Css/preview.css');
+        $this->moduleTemplate->getPageRenderer()->addInlineLanguageLabelFile('EXT:workspaces/Resources/Private/Language/locallang.xlf');
+    }
+
+    /**
+     * Sets up the view
+     *
+     * @param string $templateName
+     */
+    protected function initializeView(string $templateName)
+    {
+        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
+        $this->view->setTemplate($templateName);
+        $this->view->setTemplateRootPaths(['EXT:workspaces/Resources/Private/Templates/Preview']);
+        $this->view->setPartialRootPaths(['EXT:workspaces/Resources/Private/Partials']);
+        $this->view->setLayoutRootPaths(['EXT:workspaces/Resources/Private/Layouts']);
     }
 
     /**
      * Basically makes sure that the workspace preview is rendered.
      * The preview itself consists of three frames, so there are
-     * only the frames-urls we've to generate here
+     * only the frames-urls we have to generate here
      *
-     * @param int $previewWS
+     * @param ServerRequestInterface $request
+     * @return ResponseInterface
      */
-    public function indexAction($previewWS = null)
+    public function handleRequest(ServerRequestInterface $request): ResponseInterface
     {
-        $backendUser = $this->getBackendUser();
+        $this->initializeView('Index');
 
         // Get all the GET parameters to pass them on to the frames
-        $queryParameters = GeneralUtility::_GET();
+        $queryParameters = $request->getQueryParams();
+
+        $previewWS = $queryParameters['previewWS'] ?? null;
+        $this->pageId = (int)$queryParameters['id'];
 
-        // Remove the GET parameters related to the workspaces module and the page id
-        unset($queryParameters['tx_workspaces_web_workspacesworkspaces']);
-        unset($queryParameters['route']);
-        unset($queryParameters['id']);
+        // Remove the GET parameters related to the workspaces module
+        unset($queryParameters['route'], $queryParameters['token'], $queryParameters['previewWS']);
 
         // Assemble a query string from the retrieved parameters
         $queryString = GeneralUtility::implodeArrayForUrl('', $queryParameters);
 
         // fetch the next and previous stage
-        $workspaceItemsArray = $this->workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), ($filter = 1), ($stage = -99), $this->pageId, ($recursionLevel = 0), ($selectionType = 'tables_modify'));
+        $workspaceItemsArray = $this->workspaceService->selectVersionsInWorkspace($this->stageService->getWorkspaceId(), 1, -99, $this->pageId, 0, 'tables_modify');
         list(, $nextStage) = $this->stageService->getNextStageForElementCollection($workspaceItemsArray);
         list(, $previousStage) = $this->stageService->getPreviousStageForElementCollection($workspaceItemsArray);
-        /** @var $wsService WorkspaceService */
-        $wsService = GeneralUtility::makeInstance(WorkspaceService::class);
-        $wsList = $wsService->getAvailableWorkspaces();
-        $activeWorkspace = $backendUser->workspace;
-        if (!is_null($previewWS)) {
-            if (in_array($previewWS, array_keys($wsList)) && $activeWorkspace != $previewWS) {
-                $activeWorkspace = $previewWS;
-                $backendUser->setWorkspace($activeWorkspace);
-                BackendUtility::setUpdateSignal('updatePageTree');
-            }
+        $availableWorkspaces = $this->workspaceService->getAvailableWorkspaces();
+        $activeWorkspace = $this->getBackendUser()->workspace;
+        if ($previewWS !== null && in_array($previewWS, array_keys($availableWorkspaces)) && $activeWorkspace != $previewWS) {
+            $activeWorkspace = $previewWS;
+            $this->getBackendUser()->setWorkspace($activeWorkspace);
+            BackendUtility::setUpdateSignal('updatePageTree');
         }
-        /** @var $uriBuilder UriBuilder */
-        $uriBuilder = $this->objectManager->get(UriBuilder::class);
-        $wsSettingsPath = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
-        $wsSettingsUri = $uriBuilder->uriFor('singleIndex', [], ReviewController::class, 'workspaces', 'web_workspacesworkspaces');
-        $wsSettingsParams = '&tx_workspaces_web_workspacesworkspaces[controller]=Review';
-        $wsSettingsUrl = $wsSettingsPath . $wsSettingsUri . $wsSettingsParams;
-        $viewDomain = BackendUtility::getViewDomain($this->pageId);
-        $wsBaseUrl = $viewDomain . '/index.php?id=' . $this->pageId . $queryString;
-        // @todo - handle new pages here
-        // branchpoints are not handled anymore because this feature is not supposed anymore
-        if (WorkspaceService::isNewPage($this->pageId)) {
-            $wsNewPageUri = $uriBuilder->uriFor('newPage', [], self::class, 'workspaces', 'web_workspacesworkspaces');
-            $wsNewPageParams = '&tx_workspaces_web_workspacesworkspaces[controller]=Preview';
-            $liveUrl = $wsSettingsPath . $wsNewPageUri . $wsNewPageParams . '&ADMCMD_prev=IGNORE';
-        } else {
-            $liveUrl = $wsBaseUrl . '&ADMCMD_noBeUser=1&ADMCMD_prev=IGNORE';
+
+        // Base URL for frontend preview links
+        $previewBaseUrl = BackendUtility::getViewDomain($this->pageId) . '/index.php?' . $queryString;
+
+        // Build the "list view" link to the review controller
+        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+        $wsSettingsUrl = $uriBuilder->buildUriFromRoute('web_WorkspacesWorkspaces', [
+            'tx_workspaces_web_workspacesworkspaces' => ['action' => 'singleIndex']
+        ], UriBuilder::ABSOLUTE_URL);
+
+        if (!WorkspaceService::isNewPage($this->pageId)) {
+            $liveUrl = $previewBaseUrl . '&ADMCMD_noBeUser=1&ADMCMD_prev=IGNORE';
         }
-        $wsUrl = $wsBaseUrl . '&ADMCMD_prev=IGNORE&ADMCMD_view=1&ADMCMD_editIcons=1';
-        $backendDomain = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY');
+        $wsUrl = $previewBaseUrl . '&ADMCMD_prev=IGNORE&ADMCMD_view=1&ADMCMD_editIcons=1';
+
+        // Evaluate available preview modes
         $splitPreviewTsConfig = BackendUtility::getModTSconfig($this->pageId, 'workspaces.splitPreviewModes');
         $splitPreviewModes = GeneralUtility::trimExplode(',', $splitPreviewTsConfig['value']);
         $allPreviewModes = ['slider', 'vbox', 'hbox'];
         if (!array_intersect($splitPreviewModes, $allPreviewModes)) {
             $splitPreviewModes = $allPreviewModes;
         }
+        $this->moduleTemplate->getPageRenderer()->addInlineSetting('Workspaces', 'SplitPreviewModes', $splitPreviewModes);
 
-        $wsList = $wsService->getAvailableWorkspaces();
-        $activeWorkspace = $backendUser->workspace;
-
-        $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Workspaces/Preview');
-        $this->pageRenderer->addInlineSetting('Workspaces', 'SplitPreviewModes', $splitPreviewModes);
-
-        $cssFile = 'EXT:workspaces/Resources/Public/Css/preview.css';
-        $cssFile = GeneralUtility::getFileAbsFileName($cssFile);
-        $this->pageRenderer->addCssFile(PathUtility::getAbsoluteWebPath($cssFile));
-
-        $backendUser->setAndSaveSessionData('workspaces.backend_domain', GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'));
-
-        $logoPath = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/Images/typo3_logo_orange.svg');
-        $logoWidth = 22;
-        $logoHeight = 22;
+        $backendDomain = $request->getAttribute('normalizedParams')->getRequestHostOnly();
+        $this->getBackendUser()->setAndSaveSessionData('workspaces.backend_domain', $backendDomain);
 
         $this->view->assignMultiple([
-            'logoUrl' => PathUtility::getAbsoluteWebPath($logoPath),
             'logoLink' => TYPO3_URL_GENERAL,
-            'logoWidth' => $logoWidth,
-            'logoHeight' => $logoHeight,
-            'liveUrl' => $liveUrl,
+            'liveUrl' => $liveUrl ?? false,
             'wsUrl' => $wsUrl,
             'wsSettingsUrl' => $wsSettingsUrl,
             'backendDomain' => $backendDomain,
-            'activeWorkspace' => $wsList[$activeWorkspace],
+            'activeWorkspace' => $availableWorkspaces[$activeWorkspace],
             'splitPreviewModes' => $splitPreviewModes,
             'firstPreviewMode' => current($splitPreviewModes),
-            'enablePreviousStageButton' => !$this->isInvalidStage($previousStage),
-            'enableNextStageButton' => !$this->isInvalidStage($nextStage),
-            'enableDiscardStageButton' => !$this->isInvalidStage($nextStage) || !$this->isInvalidStage($previousStage),
+            'enablePreviousStageButton' => $this->isValidStage($previousStage),
+            'enableNextStageButton' => $this->isValidStage($nextStage),
+            'enableDiscardStageButton' => $this->isValidStage($nextStage) || $this->isValidStage($previousStage),
             'nextStage' => $nextStage['title'],
             'nextStageId' => $nextStage['uid'],
             'prevStage' => $previousStage['title'],
             'prevStageId' => $previousStage['uid'],
         ]);
-        foreach ($this->getAdditionalResourceService()->getLocalizationResources() as $localizationResource) {
-            $this->pageRenderer->addInlineLanguageLabelFile($localizationResource);
-        }
+
+        $this->moduleTemplate->setContent($this->view->render());
+        return new HtmlResponse($this->moduleTemplate->renderContent());
     }
 
     /**
@@ -183,44 +183,30 @@ class PreviewController extends AbstractController
      * @param array $stageArray
      * @return bool
      */
-    protected function isInvalidStage($stageArray)
-    {
-        return !(is_array($stageArray) && !empty($stageArray));
-    }
-
-    /**
-     */
-    public function newPageAction()
+    protected function isValidStage($stageArray): bool
     {
-        /** @var FlashMessage $flashMessage */
-        $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $this->getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:info.newpage.detail'), $this->getLanguageService()->sL('LLL:EXT:workspaces/Resources/Private/Language/locallang.xlf:info.newpage'), FlashMessage::INFO);
-        /** @var $flashMessageService FlashMessageService */
-        $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
-        /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
-        $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
-        $defaultFlashMessageQueue->enqueue($flashMessage);
+        return is_array($stageArray) && !empty($stageArray);
     }
 
     /**
      * Generates the JavaScript code for the backend,
      * and since we're loading a backend module outside of the actual backend
-     * this copies parts of the index.php?M=main module
+     * this copies parts of the backend main script.
      *
      * @return string
      */
-    protected function generateJavascript()
+    protected function generateJavascript(): string
     {
-        $backendUser = $this->getBackendUser();
         // If another page module was specified, replace the default Page module with the new one
-        $newPageModule = trim($backendUser->getTSConfigVal('options.overridePageModule'));
-        $pageModule = BackendUtility::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout';
-        if (!$backendUser->check('modules', $pageModule)) {
+        $pageModule = trim($this->getBackendUser()->getTSConfigVal('options.overridePageModule') ?? '');
+        $pageModule = BackendUtility::isModuleSetInTBE_MODULES($pageModule) ? $pageModule : 'web_layout';
+        if (!$this->getBackendUser()->check('modules', $pageModule)) {
             $pageModule = '';
         }
         $t3Configuration = [
-            'username' => htmlspecialchars($backendUser->user['username']),
+            'username' => htmlspecialchars($this->getBackendUser()->user['username']),
             'pageModule' => $pageModule,
-            'inWorkspace' => $backendUser->workspace !== 0,
+            'inWorkspace' => $this->getBackendUser()->workspace !== 0,
             'showRefreshLoginPopup' => (bool)($GLOBALS['TYPO3_CONF_VARS']['BE']['showRefreshLoginPopup'] ?? false)
         ];
 
@@ -228,17 +214,9 @@ class PreviewController extends AbstractController
     }
 
     /**
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @return BackendUserAuthentication
      */
-    protected function getBackendUser()
+    protected function getBackendUser(): BackendUserAuthentication
     {
         return $GLOBALS['BE_USER'];
     }