Completed
Branch master (d17104)
by Christian
21:20
created

PreviewModule::getIconIdentifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace TYPO3\CMS\Adminpanel\Modules;
5
6
/*
7
 * This file is part of the TYPO3 CMS project.
8
 *
9
 * It is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License, either version 2
11
 * of the License, or any later version.
12
 *
13
 * For the full copyright and license information, please read the
14
 * LICENSE.txt file that was distributed with this source code.
15
 *
16
 * The TYPO3 project - inspiring people to share!
17
 */
18
19
use Psr\Http\Message\ServerRequestInterface;
20
use TYPO3\CMS\Adminpanel\ModuleApi\AbstractModule;
21
use TYPO3\CMS\Adminpanel\ModuleApi\InitializableInterface;
22
use TYPO3\CMS\Adminpanel\ModuleApi\OnSubmitActorInterface;
23
use TYPO3\CMS\Adminpanel\ModuleApi\PageSettingsProviderInterface;
24
use TYPO3\CMS\Adminpanel\ModuleApi\ResourceProviderInterface;
25
use TYPO3\CMS\Adminpanel\Repositories\FrontendGroupsRepository;
26
use TYPO3\CMS\Core\Cache\CacheManager;
27
use TYPO3\CMS\Core\Context\Context;
28
use TYPO3\CMS\Core\Context\DateTimeAspect;
29
use TYPO3\CMS\Core\Context\UserAspect;
30
use TYPO3\CMS\Core\Context\VisibilityAspect;
31
use TYPO3\CMS\Core\Utility\GeneralUtility;
32
use TYPO3\CMS\Fluid\View\StandaloneView;
33
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
34
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
35
36
/**
37
 * Admin Panel Preview Module
38
 */
39
class PreviewModule extends AbstractModule implements InitializableInterface, PageSettingsProviderInterface, OnSubmitActorInterface, ResourceProviderInterface
40
{
41
    /**
42
     * module configuration, set on initialize
43
     *
44
     * @var array
45
     */
46
    protected $config;
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public function getIconIdentifier(): string
52
    {
53
        return 'actions-preview';
54
    }
55
56
    /**
57
     * @inheritdoc
58
     */
59
    public function getIdentifier(): string
60
    {
61
        return 'preview';
62
    }
63
64
    /**
65
     * @inheritdoc
66
     */
67
    public function getLabel(): string
68
    {
69
        return $this->getLanguageService()->sL(
70
            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:module.label'
71
        );
72
    }
73
74
    /**
75
     * @inheritdoc
76
     */
77
    public function initializeModule(ServerRequestInterface $request): void
78
    {
79
        $this->config = [
80
            'showHiddenPages' => (bool)$this->getConfigOptionForModule('showHiddenPages'),
81
            'simulateDate' => $this->getConfigOptionForModule('simulateDate'),
82
            'showHiddenRecords' => (bool)$this->getConfigOptionForModule('showHiddenRecords'),
83
            'simulateUserGroup' => $this->getConfigOptionForModule('simulateUserGroup'),
84
            'showFluidDebug' => (bool)$this->getConfigOptionForModule('showFluidDebug'),
85
        ];
86
        $this->initializeFrontendPreview(
87
            $this->config['showHiddenPages'],
88
            $this->config['showHiddenRecords'],
89
            $this->config['simulateDate'],
90
            $this->config['simulateUserGroup']
91
        );
92
    }
93
94
    /**
95
     * @inheritdoc
96
     */
97
    public function getPageSettings(): string
98
    {
99
        $view = GeneralUtility::makeInstance(StandaloneView::class);
100
        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/Settings/Preview.html';
101
        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
102
        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
103
104
        $frontendGroupsRepository = GeneralUtility::makeInstance(FrontendGroupsRepository::class);
105
106
        $view->assignMultiple(
107
            [
108
                'show' => [
109
                    'pageId' => (int)$this->getTypoScriptFrontendController()->id,
110
                    'hiddenPages' => $this->config['showHiddenPages'],
111
                    'hiddenRecords' => $this->config['showHiddenRecords'],
112
                    'fluidDebug' => $this->config['showFluidDebug'],
113
                ],
114
                'simulateDate' => $this->config['simulateDate'],
115
                'frontendUserGroups' => [
116
                    'availableGroups' => $frontendGroupsRepository->getAvailableFrontendUserGroups(),
117
                    'selected' => $this->config['simulateUserGroup'],
118
                ],
119
            ]
120
        );
121
        return $view->render();
122
    }
123
124
    /**
125
     * Clear page cache if fluid debug output setting is changed
126
     *
127
     * @param array $input
128
     * @param ServerRequestInterface $request
129
     * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
130
     */
131
    public function onSubmit(array $input, ServerRequestInterface $request): void
132
    {
133
        $activeConfiguration = (int)$this->getConfigOptionForModule('showFluidDebug');
134
        if (isset($input['preview_showFluidDebug']) && (int)$input['preview_showFluidDebug'] !== $activeConfiguration) {
135
            $pageId = (int)$request->getParsedBody()['TSFE_ADMIN_PANEL']['preview_clearCacheId'];
136
            $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
137
            $cacheManager->getCache('cache_pages')->flushByTag('pageId_' . $pageId);
138
            $cacheManager->getCache('fluid_template')->flush();
139
        }
140
    }
141
142
    /**
143
     * @param string $option
144
     * @return string
145
     */
146
    protected function getConfigOptionForModule(string $option): string
147
    {
148
        return $this->configurationService->getConfigurationOption(
149
            'preview',
150
            $option
151
        );
152
    }
153
154
    /**
155
     * @return TypoScriptFrontendController
156
     */
157
    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
158
    {
159
        return $GLOBALS['TSFE'];
160
    }
161
162
    /**
163
     * Initialize frontend preview functionality incl.
164
     * simulation of users or time
165
     *
166
     * @param bool $showHiddenPages
167
     * @param bool $showHiddenRecords
168
     * @param string $simulateDate
169
     * @param string $simulateUserGroup
170
     */
171
    protected function initializeFrontendPreview(
172
        bool $showHiddenPages,
173
        bool $showHiddenRecords,
174
        string $simulateDate,
175
        string $simulateUserGroup
176
    ): void {
177
        $context = GeneralUtility::makeInstance(Context::class);
178
        $tsfe = $this->getTypoScriptFrontendController();
179
        $tsfe->clear_preview();
180
        $tsfe->fePreview = 1;
181
        // Simulate date
182
        $simTime = null;
183
        if ($simulateDate) {
184
            $simTime = $this->parseDate($simulateDate);
185
        }
186
        if ($simTime) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $simTime of type null|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
187
            $GLOBALS['SIM_EXEC_TIME'] = $simTime;
188
            $GLOBALS['SIM_ACCESS_TIME'] = $simTime - $simTime % 60;
189
            $context->setAspect('date', GeneralUtility::makeInstance(DateTimeAspect::class, new \DateTimeImmutable('@' . $GLOBALS['SIM_EXEC_TIME'])));
190
        }
191
        $context->setAspect('visibility', GeneralUtility::makeInstance(VisibilityAspect::class, $showHiddenPages, $showHiddenRecords));
192
        // simulate user
193
        $tsfe->simUserGroup = $simulateUserGroup;
0 ignored issues
show
Documentation Bug introduced by
The property $simUserGroup was declared of type integer, but $simulateUserGroup is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
194
        if ($tsfe->simUserGroup) {
195
            if ($tsfe->fe_user->user) {
196
                $tsfe->fe_user->user[$tsfe->fe_user->usergroup_column] = $tsfe->simUserGroup;
197
            } else {
198
                $tsfe->fe_user = GeneralUtility::makeInstance(FrontendUserAuthentication::class);
199
                $tsfe->fe_user->user = [
200
                    $tsfe->fe_user->usergroup_column => $tsfe->simUserGroup,
201
                ];
202
            }
203
            $context->setAspect('frontend.user', GeneralUtility::makeInstance(UserAspect::class, $tsfe->fe_user ?: null));
204
        }
205
        if (!$tsfe->simUserGroup && !$simTime && !$showHiddenPages && !$showHiddenRecords) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $simTime of type null|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
206
            $tsfe->fePreview = 0;
207
        }
208
    }
209
210
    /**
211
     * @return array
212
     */
213
    public function getJavaScriptFiles(): array
214
    {
215
        return ['EXT:adminpanel/Resources/Public/JavaScript/Modules/Preview.js'];
216
    }
217
218
    /**
219
     * @param string $simulateDate
220
     * @return int
221
     */
222
    protected function parseDate(string $simulateDate): ?int
223
    {
224
        $date = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $date is dead and can be removed.
Loading history...
225
        try {
226
            $date = new \DateTime($simulateDate);
227
        } catch (\Exception $e) {
228
            if (is_numeric($simulateDate)) {
229
                try {
230
                    $date = new \DateTime('@' . $simulateDate);
231
                } catch (\Exception $e) {
232
                    $date = false;
233
                }
234
            }
235
        }
236
        if ($date !== false) {
237
            $simTime = $date->getTimestamp();
238
        }
239
        return $simTime ?? null;
240
    }
241
242
    /**
243
     * Returns a string array with css files that will be rendered after the module
244
     *
245
     * @return array
246
     */
247
    public function getCssFiles(): array
248
    {
249
        return [];
250
    }
251
}
252