‪TYPO3CMS  ‪main
PreviewModule.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Log\LoggerAwareInterface;
22 use Psr\Log\LoggerAwareTrait;
23 use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
42 
46 #[Autoconfigure(public: true)]
48 {
49  use LoggerAwareTrait;
50 
63  protected array ‪$config;
64 
65  public function ‪__construct(
66  protected readonly ‪CacheManager $cacheManager,
67  ) {}
68 
69  public function ‪getIconIdentifier(): string
70  {
71  return 'actions-preview';
72  }
73 
74  public function ‪getIdentifier(): string
75  {
76  return 'preview';
77  }
78 
79  public function ‪getLabel(): string
80  {
81  return $this->‪getLanguageService()->sL(
82  'LLL:EXT:adminpanel/Resources/Private/Language/locallang_preview.xlf:module.label'
83  );
84  }
85 
86  public function ‪enrich(ServerRequestInterface $request): ServerRequestInterface
87  {
88  // Backend preview params (ADMCMD_) take precedence over configured admin panel values
89  $simulateGroupByRequest = (int)($request->getQueryParams()['ADMCMD_simUser'] ?? 0);
90  $simulateTimeByRequest = (int)($request->getQueryParams()['ADMCMD_simTime'] ?? 0);
91  $this->config = [
92  'showHiddenPages' => (bool)$this->‪getConfigOptionForModule('showHiddenPages'),
93  'simulateDate' => $simulateTimeByRequest ?: (int)$this->‪getConfigOptionForModule('simulateDate'),
94  'showHiddenRecords' => (bool)$this->‪getConfigOptionForModule('showHiddenRecords'),
95  'showScheduledRecords' => (bool)$this->‪getConfigOptionForModule('showScheduledRecords'),
96  'simulateUserGroup' => $simulateGroupByRequest ?: (int)$this->‪getConfigOptionForModule('simulateUserGroup'),
97  'showFluidDebug' => (bool)$this->‪getConfigOptionForModule('showFluidDebug'),
98  ];
99  if ($this->config['showFluidDebug']) {
100  // forcibly unset fluid caching as it does not care about the tsfe based caching settings
101  // @todo: Useless?! CacheManager is initialized via bootstrap already, TYPO3_CONF_VARS is not read again?
102  unset(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['fluid_template']['frontend']);
103  $cacheInstruction = $request->getAttribute('frontend.cache.instruction', new ‪CacheInstruction());
104  $cacheInstruction->disableCache('EXT:adminpanel: "Show fluid debug output" disables cache.');
105  $request = $request->withAttribute('frontend.cache.instruction', $cacheInstruction);
106  }
108  $this->config['showHiddenPages'],
109  $this->config['showHiddenRecords'],
110  $this->config['showScheduledRecords'],
111  $this->config['simulateDate'],
112  $this->config['simulateUserGroup'],
113  $request
114  );
115 
116  return $request;
117  }
118 
119  public function ‪getPageSettings(): string
120  {
121  $view = GeneralUtility::makeInstance(StandaloneView::class);
122  $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Modules/Settings/Preview.html';
123  $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
124  $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
125 
126  $frontendGroupsRepository = GeneralUtility::makeInstance(FrontendGroupsRepository::class);
127 
128  $pageId = 0;
129  $pageArguments = ‪$GLOBALS['TYPO3_REQUEST']->getAttribute('routing');
130  if ($pageArguments instanceof ‪PageArguments) {
131  $pageId = $pageArguments->getPageId();
132  }
133 
134  $view->assignMultiple(
135  [
136  'show' => [
137  'pageId' => $pageId,
138  'hiddenPages' => $this->config['showHiddenPages'] ?? false,
139  'hiddenRecords' => $this->config['showHiddenRecords'] ?? false,
140  'showScheduledRecords' => $this->config['showScheduledRecords'] ?? false,
141  'fluidDebug' => $this->config['showFluidDebug'] ?? false,
142  ],
143  'simulateDate' => (int)($this->config['simulateDate'] ?? 0),
144  'frontendUserGroups' => [
145  'availableGroups' => $frontendGroupsRepository->getAvailableFrontendUserGroups(),
146  'selected' => (int)($this->config['simulateUserGroup'] ?? 0),
147  ],
148  'languageKey' => $this->getBackendUser()->user['lang'] ?? null,
149  ]
150  );
151  return $view->render();
152  }
153 
154  protected function ‪getConfigOptionForModule(string $option): string
155  {
156  return $this->configurationService->getConfigurationOption(
157  'preview',
158  $option
159  );
160  }
161 
168  protected function ‪initializeFrontendPreview(
169  bool $showHiddenPages,
170  bool $showHiddenRecords,
171  bool $showScheduledRecords,
172  int $simulateDate,
173  int $simulateUserGroup,
174  ServerRequestInterface $request
175  ): void {
176  $context = GeneralUtility::makeInstance(Context::class);
177  $this->‪clearPreviewSettings($context);
178 
179  // Modify visibility settings (hidden pages + hidden content)
180  $context->setAspect(
181  'visibility',
182  GeneralUtility::makeInstance(VisibilityAspect::class, $showHiddenPages, $showHiddenRecords, false, $showScheduledRecords)
183  );
184 
185  // Simulate date
186  $simTime = null;
187  if ($simulateDate) {
188  $simTime = max($simulateDate, 60);
189  ‪$GLOBALS['SIM_EXEC_TIME'] = $simTime;
190  ‪$GLOBALS['SIM_ACCESS_TIME'] = $simTime - $simTime % 60;
191  $context->setAspect(
192  'date',
193  GeneralUtility::makeInstance(
194  DateTimeAspect::class,
195  (new \DateTimeImmutable())->setTimestamp($simTime)
196  )
197  );
198  }
199  // simulate usergroup
200  if ($simulateUserGroup) {
201  $frontendUser = $request->getAttribute('frontend.user');
202  $frontendUser->user[$frontendUser->usergroup_column] = $simulateUserGroup;
203  $frontendUser->userGroups[$simulateUserGroup] = [
204  'uid' => $simulateUserGroup,
205  'title' => '_PREVIEW_',
206  ];
207  // let's fake having a user with that group, too
208  // This can be removed once #90989 is fixed
209  $frontendUser->user['uid'] = PHP_INT_MAX;
210  $context->setAspect(
211  'frontend.user',
212  GeneralUtility::makeInstance(
213  UserAspect::class,
214  $frontendUser,
215  [$simulateUserGroup]
216  )
217  );
218  }
219  $isPreview = $simulateUserGroup || $simTime || $showHiddenPages || $showHiddenRecords || $showScheduledRecords;
220  if ($context->hasAspect('frontend.preview')) {
222  $existingPreviewAspect = $context->getAspect('frontend.preview');
223  $isPreview = $existingPreviewAspect->isPreview() || $isPreview;
224  }
225  $previewAspect = GeneralUtility::makeInstance(PreviewAspect::class, $isPreview);
226  $context->setAspect('frontend.preview', $previewAspect);
227  }
228 
229  public function ‪getJavaScriptFiles(): array
230  {
231  return ['EXT:adminpanel/Resources/Public/JavaScript/modules/preview.js'];
232  }
233 
234  protected function ‪clearPreviewSettings(‪Context $context): void
235  {
236  ‪$GLOBALS['SIM_EXEC_TIME'] = ‪$GLOBALS['EXEC_TIME'];
237  ‪$GLOBALS['SIM_ACCESS_TIME'] = ‪$GLOBALS['ACCESS_TIME'];
238  $context->‪setAspect(
239  'date',
240  GeneralUtility::makeInstance(
241  DateTimeAspect::class,
242  (new \DateTimeImmutable())->setTimestamp(‪$GLOBALS['SIM_EXEC_TIME'])
243  )
244  );
245  $context->‪setAspect('visibility', GeneralUtility::makeInstance(VisibilityAspect::class));
246  }
247 
251  public function ‪getCssFiles(): array
252  {
253  return [];
254  }
255 
256  public function ‪onSubmit(array $configurationToSave, ServerRequestInterface $request): void
257  {
258  if (!array_key_exists('preview_showFluidDebug', $configurationToSave)) {
259  return;
260  }
261 
262  $currentShowFluidDebug = $this->‪getConfigOptionForModule('showFluidDebug');
263 
264  if ($configurationToSave['preview_showFluidDebug'] === $currentShowFluidDebug) {
265  return;
266  }
267 
268  $pageId = (int)$request->getParsedBody()['TSFE_ADMIN_PANEL']['preview_clearCacheId'];
269 
270  try {
271  $this->cacheManager->flushCachesInGroupByTag('pages', 'pageId_' . $pageId);
272  $this->cacheManager->getCache('fluid_template')->flush();
274  if ($this->logger !== null) {
275  $this->logger->error($exception->getMessage(), ['exception' => $exception]);
276  }
277  }
278  }
279 }
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\$config
‪array $config
Definition: PreviewModule.php:63
‪TYPO3\CMS\Core\Routing\PageArguments
Definition: PageArguments.php:26
‪TYPO3\CMS\Core\Context\VisibilityAspect
Definition: VisibilityAspect.php:31
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\initializeFrontendPreview
‪initializeFrontendPreview(bool $showHiddenPages, bool $showHiddenRecords, bool $showScheduledRecords, int $simulateDate, int $simulateUserGroup, ServerRequestInterface $request)
Definition: PreviewModule.php:168
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\onSubmit
‪onSubmit(array $configurationToSave, ServerRequestInterface $request)
Definition: PreviewModule.php:256
‪TYPO3\CMS\Adminpanel\ModuleApi\AbstractModule
Definition: AbstractModule.php:29
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getPageSettings
‪getPageSettings()
Definition: PreviewModule.php:119
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getIdentifier
‪getIdentifier()
Definition: PreviewModule.php:74
‪TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
Definition: NoSuchCacheException.php:23
‪TYPO3\CMS\Adminpanel\ModuleApi\AbstractModule\getLanguageService
‪getLanguageService()
Definition: AbstractModule.php:95
‪TYPO3\CMS\Adminpanel\Repositories\FrontendGroupsRepository
Definition: FrontendGroupsRepository.php:31
‪TYPO3\CMS\Adminpanel\ModuleApi\ResourceProviderInterface
Definition: ResourceProviderInterface.php:27
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\Context\Context\setAspect
‪setAspect(string $name, AspectInterface $aspect)
Definition: Context.php:131
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\enrich
‪enrich(ServerRequestInterface $request)
Definition: PreviewModule.php:86
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getCssFiles
‪getCssFiles()
Definition: PreviewModule.php:251
‪TYPO3\CMS\Adminpanel\Modules
Definition: CacheModule.php:18
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getConfigOptionForModule
‪getConfigOptionForModule(string $option)
Definition: PreviewModule.php:154
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:30
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\__construct
‪__construct(protected readonly CacheManager $cacheManager,)
Definition: PreviewModule.php:65
‪TYPO3\CMS\Adminpanel\ModuleApi\PageSettingsProviderInterface
Definition: PageSettingsProviderInterface.php:32
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getIconIdentifier
‪getIconIdentifier()
Definition: PreviewModule.php:69
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Frontend\Cache\CacheInstruction
Definition: CacheInstruction.php:29
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\clearPreviewSettings
‪clearPreviewSettings(Context $context)
Definition: PreviewModule.php:234
‪TYPO3\CMS\Adminpanel\ModuleApi\OnSubmitActorInterface
Definition: OnSubmitActorInterface.php:27
‪TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException
Definition: NoSuchCacheGroupException.php:23
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule
Definition: PreviewModule.php:48
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Frontend\Aspect\PreviewAspect
Definition: PreviewAspect.php:30
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getJavaScriptFiles
‪getJavaScriptFiles()
Definition: PreviewModule.php:229
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:35
‪TYPO3\CMS\Adminpanel\Modules\PreviewModule\getLabel
‪getLabel()
Definition: PreviewModule.php:79
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:37
‪TYPO3\CMS\Adminpanel\ModuleApi\RequestEnricherInterface
Definition: RequestEnricherInterface.php:37