ReviewController.php 13 KB
Newer Older
1
<?php
2

3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
7
8
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
9
 *
10
11
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
14
 * The TYPO3 project - inspiring people to share!
 */
15

16
17
namespace TYPO3\CMS\Workspaces\Controller;

18
19
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
20
use TYPO3\CMS\Backend\Routing\UriBuilder;
21
use TYPO3\CMS\Backend\Template\ModuleTemplate;
22
use TYPO3\CMS\Backend\Utility\BackendUtility;
23
use TYPO3\CMS\Backend\View\BackendTemplateView;
24
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
25
use TYPO3\CMS\Core\Http\HtmlResponse;
26
use TYPO3\CMS\Core\Imaging\Icon;
27
28
29
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Page\PageRenderer;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
use TYPO3\CMS\Core\Versioning\VersionState;
32
use TYPO3\CMS\Fluid\View\StandaloneView;
Wouter Wolters's avatar
Wouter Wolters committed
33
use TYPO3\CMS\Workspaces\Service\WorkspaceService;
34

35
/**
36
 * @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API.
37
 */
38
class ReviewController
39
{
40
41
42
43
44
    /**
     * @var ModuleTemplate
     */
    protected $moduleTemplate;

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    /**
     * @var string
     */
    protected $defaultViewObjectName = BackendTemplateView::class;

    /**
     * @var BackendTemplateView
     */
    protected $view;

    /**
     * @var PageRenderer
     */
    protected $pageRenderer;

    /**
     * @var int
     */
    protected $pageId;

65
    public function __construct()
66
    {
67
        $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
68
69
    }

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    /**
     * Initializes the controller before invoking an action method.
     */
    protected function initializeAction()
    {
        $this->pageRenderer = $this->getPageRenderer();
        $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
        $lang = $this->getLanguageService();
        $icons = [
            'language' => $iconFactory->getIcon('flags-multiple', Icon::SIZE_SMALL)->render(),
            'integrity' => $iconFactory->getIcon('status-dialog-information', Icon::SIZE_SMALL)->render(),
            'success' => $iconFactory->getIcon('status-dialog-ok', Icon::SIZE_SMALL)->render(),
            'info' => $iconFactory->getIcon('status-dialog-information', Icon::SIZE_SMALL)->render(),
            'warning' => $iconFactory->getIcon('status-dialog-warning', Icon::SIZE_SMALL)->render(),
            'error' => $iconFactory->getIcon('status-dialog-error', Icon::SIZE_SMALL)->render()
        ];
        $this->pageRenderer->addInlineSetting('Workspaces', 'icons', $icons);
        $this->pageRenderer->addInlineSetting('Workspaces', 'id', $this->pageId);
        $this->pageRenderer->addInlineSetting('Workspaces', 'depth', $this->pageId === 0 ? 999 : 1);
        $this->pageRenderer->addInlineSetting('Workspaces', 'language', $this->getLanguageSelection());
        $this->pageRenderer->addInlineLanguageLabelArray([
            'title' => $lang->getLL('title'),
92
93
94
95
96
97
98
99
100
            'path' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path'),
            'table' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.table'),
            'depth' => $lang->sL('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:Depth'),
            'depth_0' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
            'depth_1' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
            'depth_2' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
            'depth_3' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
            'depth_4' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
            'depth_infi' => $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi')
101
102
103
104
105
106
107
108
109
        ]);
        $this->pageRenderer->addInlineLanguageLabelFile('EXT:workspaces/Resources/Private/Language/locallang.xlf');
        $states = $this->getBackendUser()->uc['moduleData']['Workspaces']['States'];
        $this->pageRenderer->addInlineSetting('Workspaces', 'States', $states);

        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
        $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Workspaces/Backend');
        $this->pageRenderer->addInlineSetting('FormEngine', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('record_edit'));
        $this->pageRenderer->addInlineSetting('RecordHistory', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('record_history'));
110
        $this->pageRenderer->addInlineSetting('Workspaces', 'id', $this->pageId);
111
112
    }

113
114
115
    /**
     * Renders the review module user dependent with all workspaces.
     * The module will show all records of one workspace.
116
117
118
     *
     * @param ServerRequestInterface $request
     * @return ResponseInterface
119
     */
120
    public function indexAction(ServerRequestInterface $request): ResponseInterface
121
    {
122
123
124
125
126
127
128
129
130
131
132
133
134
        $queryParams = $request->getQueryParams();
        $this->pageId = (int)($queryParams['id'] ?? 0);

        $this->initializeAction();

        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
        $this->view->setTemplate('Index');
        // This is only needed for translate VH to resolve 'label only' to default locallang.xlf files
        $this->view->getRequest()->setControllerExtensionName('Workspaces');
        $this->view->setTemplateRootPaths(['EXT:workspaces/Resources/Private/Templates/Review']);
        $this->view->setPartialRootPaths(['EXT:workspaces/Resources/Private/Partials']);
        $this->view->setLayoutRootPaths(['EXT:workspaces/Resources/Private/Layouts']);

135
        $backendUser = $this->getBackendUser();
136
        $moduleTemplate = $this->moduleTemplate;
137
        $pageTitle = '';
138

139
140
        if ($this->pageId) {
            $pageRecord = BackendUtility::getRecord('pages', $this->pageId);
141
            if ($pageRecord) {
142
                $moduleTemplate->getDocHeaderComponent()->setMetaInformation($pageRecord);
143
                $pageTitle = BackendUtility::getRecordTitle('pages', $pageRecord);
144
            }
145
        }
146
        $wsList = GeneralUtility::makeInstance(WorkspaceService::class)->getAvailableWorkspaces();
147
        $customWorkspaceExists = $this->customWorkspaceExists($wsList);
148
        $activeWorkspace = (int)$backendUser->workspace;
149
        $activeWorkspaceTitle = WorkspaceService::getWorkspaceTitle($activeWorkspace);
150
        $performWorkspaceSwitch = false;
151
152
153
        if ((int)($queryParams['workspace'] ?? 0) > 0) {
            $switchWs = (int)$queryParams['workspace'];
            if (array_key_exists($switchWs, $wsList) && $activeWorkspace !== $switchWs) {
154
155
156
157
                $activeWorkspace = $switchWs;
                $backendUser->setWorkspace($activeWorkspace);
                $performWorkspaceSwitch = true;
                BackendUtility::setUpdateSignal('updatePageTree');
158
159
            }
        }
160
        $this->pageRenderer->addInlineSetting('Workspaces', 'isLiveWorkspace', (int)$backendUser->workspace === 0);
161
162
        $this->pageRenderer->addInlineSetting('Workspaces', 'workspaceTabs', $this->prepareWorkspaceTabs($wsList, $activeWorkspace));
        $this->pageRenderer->addInlineSetting('Workspaces', 'activeWorkspaceId', $activeWorkspace);
163
        $workspaceIsAccessible = $backendUser->workspace !== WorkspaceService::LIVE_WORKSPACE_ID;
164
        $this->view->assignMultiple([
165
166
            'isAdmin' => $backendUser->isAdmin(),
            'customWorkspaceExists' => $customWorkspaceExists,
167
168
            'showGrid' => $workspaceIsAccessible,
            'showLegend' => $workspaceIsAccessible,
169
            'pageUid' => $this->pageId,
170
            'pageTitle' => $pageTitle,
171
172
173
            'performWorkspaceSwitch' => $performWorkspaceSwitch,
            'workspaceList' => $this->prepareWorkspaceTabs($wsList, $activeWorkspace),
            'activeWorkspaceUid' => $activeWorkspace,
174
            'activeWorkspaceTitle' => $activeWorkspaceTitle,
175
176
        ]);

177
178
        $buttonBar = $moduleTemplate->getDocHeaderComponent()->getButtonBar();
        if ($this->canCreatePreviewLink($this->pageId, $activeWorkspace)) {
179
            $iconFactory = $moduleTemplate->getIconFactory();
180
181
            $showButton = $buttonBar->makeLinkButton()
                ->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($iconFactory->getIcon('actions-version-workspaces-preview-link', Icon::SIZE_SMALL));
186
187
            $buttonBar->addButton($showButton);
        }
188
        $shortcutButton = $buttonBar->makeShortcutButton()
189
            ->setRouteIdentifier('web_WorkspacesWorkspaces')
190
            ->setDisplayName(sprintf('%s: %s [%d]', $activeWorkspaceTitle, $pageTitle, $this->pageId))
191
            ->setArguments(['id' => (int)$this->pageId]);
192
193
194
195
        $buttonBar->addButton($shortcutButton);

        $this->moduleTemplate->setContent($this->view->render());
        return new HtmlResponse($this->moduleTemplate->renderContent());
196
    }
197

198
199
200
201
202
203
204
    /**
     * Prepares available workspace tabs.
     *
     * @param array $workspaceList
     * @param int $activeWorkspace
     * @return array
     */
205
    protected function prepareWorkspaceTabs(array $workspaceList, int $activeWorkspace)
206
    {
207
        $tabs = [];
208

209
        if ($activeWorkspace !== WorkspaceService::LIVE_WORKSPACE_ID) {
210
            $tabs[] = [
211
212
213
214
                'title' => $workspaceList[$activeWorkspace],
                'itemId' => 'workspace-' . $activeWorkspace,
                'workspaceId' => $activeWorkspace,
                'triggerUrl' => $this->getModuleUri($activeWorkspace),
215
            ];
216
        }
217

218
        foreach ($workspaceList as $workspaceId => $workspaceTitle) {
219
220
221
            if ($workspaceId === $activeWorkspace
                || $workspaceId === WorkspaceService::LIVE_WORKSPACE_ID
            ) {
222
223
                continue;
            }
224
            $tabs[] = [
225
226
227
228
                'title' => $workspaceTitle,
                'itemId' => 'workspace-' . $workspaceId,
                'workspaceId' => $workspaceId,
                'triggerUrl' => $this->getModuleUri($workspaceId),
229
            ];
230
        }
231

232
233
        return $tabs;
    }
234

235
236
237
238
239
240
    /**
     * Gets the module URI.
     *
     * @param int $workspaceId
     * @return string
     */
241
    protected function getModuleUri(int $workspaceId): string
242
    {
243
        $parameters = [
244
245
            'id' => $this->pageId,
            'workspace' => $workspaceId,
246
        ];
247
        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
248
        return (string)$uriBuilder->buildUriFromRoute('web_WorkspacesWorkspaces', $parameters);
249
    }
250

251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    /**
     * Determine whether this page for the current
     *
     * @param int $pageUid
     * @param int $workspaceUid
     * @return bool
     */
    protected function canCreatePreviewLink(int $pageUid, int $workspaceUid): bool
    {
        if ($pageUid > 0 && $workspaceUid > 0) {
            $pageRecord = BackendUtility::getRecord('pages', $pageUid);
            BackendUtility::workspaceOL('pages', $pageRecord, $workspaceUid);
            if (VersionState::cast($pageRecord['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
                return false;
            }
            return true;
        }
        return false;
    }

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
    /**
     * Gets the selected language.
     *
     * @return string
     */
    protected function getLanguageSelection(): string
    {
        $language = 'all';
        $backendUser = $this->getBackendUser();
        if (isset($backendUser->uc['moduleData']['Workspaces'][$backendUser->workspace]['language'])) {
            $language = $backendUser->uc['moduleData']['Workspaces'][$backendUser->workspace]['language'];
        }
        return $language;
    }

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
    /**
     * Returns true if at least one custom workspace next to live workspace exists.
     *
     * @param array $workspaceList
     * @return bool
     */
    protected function customWorkspaceExists(array $workspaceList): bool
    {
        foreach (array_keys($workspaceList) as $workspaceId) {
            if ($workspaceId > 0) {
                return true;
            }
        }
        return false;
    }

302
303
304
305
306
307
308
309
310
311
    /**
     * @return PageRenderer
     */
    protected function getPageRenderer(): PageRenderer
    {
        return GeneralUtility::makeInstance(PageRenderer::class);
    }

    /**
     * @return LanguageService
312
     */
313
    protected function getLanguageService(): LanguageService
314
315
316
    {
        return $GLOBALS['LANG'];
    }
317
318
319
320

    /**
     * @return BackendUserAuthentication
     */
321
    protected function getBackendUser(): BackendUserAuthentication
322
323
324
    {
        return $GLOBALS['BE_USER'];
    }
325
}