‪TYPO3CMS  9.5
SiteConfigurationController.php
Go to the documentation of this file.
1 <?php
2 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 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
48 use TYPO3Fluid\Fluid\View\ViewInterface;
49 
58 {
59  protected const ‪ALLOWED_ACTIONS = ['overview', 'edit', 'save', 'delete'];
60 
64  protected ‪$moduleTemplate;
65 
69  protected ‪$view;
70 
74  protected ‪$siteFinder;
75 
79  public function ‪__construct()
80  {
81  $this->siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
82  $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
83  }
84 
91  public function ‪handleRequest(ServerRequestInterface $request): ResponseInterface
92  {
93  // forcing uncached sites will re-initialize `SiteFinder`
94  // which is used later by FormEngine (implicit behavior)
95  $this->siteFinder->getAllSites(false);
96  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
97  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
98  $action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? 'overview';
99 
100  if (!in_array($action, self::ALLOWED_ACTIONS, true)) {
101  return new ‪HtmlResponse('Action not allowed', 400);
102  }
103 
104  $this->‪initializeView($action);
105 
106  $result = call_user_func_array([$this, $action . 'Action'], [$request]);
107  if ($result instanceof ResponseInterface) {
108  return $result;
109  }
110  $this->moduleTemplate->setContent($this->view->render());
111  return new HtmlResponse($this->moduleTemplate->renderContent());
112  }
113 
118  protected function ‪overviewAction(): void
119  {
121  $allSites = $this->siteFinder->getAllSites();
122  $pages = $this->‪getAllSitePages();
123  $unassignedSites = [];
124  foreach ($allSites as $identifier => $site) {
125  $rootPageId = $site->getRootPageId();
126  if (isset($pages[$rootPageId])) {
127  $pages[$rootPageId]['siteIdentifier'] = $identifier;
128  $pages[$rootPageId]['siteConfiguration'] = $site;
129  } else {
130  $unassignedSites[] = $site;
131  }
132  }
133  $this->view->assignMultiple([
134  'pages' => $pages,
135  'unassignedSites' => $unassignedSites
136  ]);
137  }
138 
145  protected function ‪editAction(ServerRequestInterface $request): void
146  {
148 
149  // Put site and friends TCA into global TCA
150  // @todo: We might be able to get rid of that later
151  ‪$GLOBALS['TCA'] = array_merge(‪$GLOBALS['TCA'], GeneralUtility::makeInstance(SiteTcaConfiguration::class)->getTca());
152 
153  $siteIdentifier = $request->getQueryParams()['site'] ?? null;
154  $pageUid = (int)($request->getQueryParams()['pageUid'] ?? 0);
155 
156  if (empty($siteIdentifier) && empty($pageUid)) {
157  throw new \RuntimeException('Either site identifier to edit a config or page uid to add new config must be set', 1521561148);
158  }
159  $isNewConfig = empty($siteIdentifier);
160 
161  $defaultValues = [];
162  if ($isNewConfig) {
163  $defaultValues['site']['rootPageId'] = $pageUid;
164  }
165 
166  $allSites = $this->siteFinder->getAllSites();
167  if (!$isNewConfig && !isset($allSites[$siteIdentifier])) {
168  throw new \RuntimeException('Existing config for site ' . $siteIdentifier . ' not found', 1521561226);
169  }
170 
171  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
172  $returnUrl = $uriBuilder->buildUriFromRoute('site_configuration');
173 
174  $formDataGroup = GeneralUtility::makeInstance(SiteConfigurationDataGroup::class);
175  $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
176  $formDataCompilerInput = [
177  'tableName' => 'site',
178  'vanillaUid' => $isNewConfig ? $pageUid : $allSites[$siteIdentifier]->getRootPageId(),
179  'command' => $isNewConfig ? 'new' : 'edit',
180  'returnUrl' => (string)$returnUrl,
181  'customData' => [
182  'siteIdentifier' => $isNewConfig ? '' : $siteIdentifier,
183  ],
184  'defaultValues' => $defaultValues,
185  ];
186  $formData = $formDataCompiler->compile($formDataCompilerInput);
187  $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
188  $formData['renderType'] = 'outerWrapContainer';
189  $formResult = $nodeFactory->create($formData)->render();
190  // Needed to be set for 'onChange="reload"' and reload on type change to work
191  $formResult['doSaveFieldName'] = 'doSave';
192  $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
193  $formResultCompiler->mergeResult($formResult);
194  $formResultCompiler->addCssFiles();
195  // Always add rootPageId as additional field to have a reference for new records
196  $this->view->assign('rootPageId', $isNewConfig ? $pageUid : $allSites[$siteIdentifier]->getRootPageId());
197  $this->view->assign('returnUrl', $returnUrl);
198  $this->view->assign('formEngineHtml', $formResult['html']);
199  $this->view->assign('formEngineFooter', $formResultCompiler->printNeededJSFunctions());
200  }
201 
209  protected function ‪saveAction(ServerRequestInterface $request): ResponseInterface
210  {
211  // Put site and friends TCA into global TCA
212  // @todo: We might be able to get rid of that later
213  ‪$GLOBALS['TCA'] = array_merge(‪$GLOBALS['TCA'], GeneralUtility::makeInstance(SiteTcaConfiguration::class)->getTca());
214 
215  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
216  $siteTca = GeneralUtility::makeInstance(SiteTcaConfiguration::class)->getTca();
217 
218  $overviewRoute = $uriBuilder->buildUriFromRoute('site_configuration', ['action' => 'overview']);
219  $parsedBody = $request->getParsedBody();
220  if (isset($parsedBody['closeDoc']) && (int)$parsedBody['closeDoc'] === 1) {
221  // Closing means no save, just redirect to overview
222  return new RedirectResponse($overviewRoute);
223  }
224  $isSave = $parsedBody['_savedok'] ?? $parsedBody['doSave'] ?? false;
225  $isSaveClose = $parsedBody['_saveandclosedok'] ?? false;
226  if (!$isSave && !$isSaveClose) {
227  throw new \RuntimeException('Either save or save and close', 1520370364);
228  }
229 
230  if (!isset($parsedBody['data']['site']) || !is_array($parsedBody['data']['site'])) {
231  throw new \RuntimeException('No site data or site identifier given', 1521030950);
232  }
233 
234  $data = $parsedBody['data'];
235  // This can be NEW123 for new records
236  $pageId = (int)key($data['site']);
237  $sysSiteRow = current($data['site']);
238  $siteIdentifier = $sysSiteRow['identifier'] ?? '';
239 
240  $isNewConfiguration = false;
241  $currentIdentifier = '';
242  try {
243  $currentSite = $this->siteFinder->getSiteByRootPageId($pageId);
244  $currentSiteConfiguration = $currentSite->getConfiguration();
245  $currentIdentifier = $currentSite->getIdentifier();
246  } catch (SiteNotFoundException $e) {
247  $currentSiteConfiguration = [];
248  $isNewConfiguration = true;
249  $pageId = (int)$parsedBody['rootPageId'];
250  if (!$pageId > 0) {
251  // Early validation of rootPageId - it must always be given and greater than 0
252  throw new \RuntimeException('No root page id found', 1521719709);
253  }
254  }
255 
256  // Validate site identifier and do not store or further process it
257  $siteIdentifier = $this->‪validateAndProcessIdentifier($isNewConfiguration, $siteIdentifier, $pageId);
258  unset($sysSiteRow['identifier']);
259 
260  try {
261  $newSysSiteData = [];
262  // Hard set rootPageId: This is TCA readOnly and not transmitted by FormEngine, but is also the "uid" of the site record
263  $newSysSiteData['rootPageId'] = $pageId;
264  foreach ($sysSiteRow as $fieldName => $fieldValue) {
265  $type = $siteTca['site']['columns'][$fieldName]['config']['type'];
266  switch ($type) {
267  case 'input':
268  case 'text':
269  $fieldValue = $this->‪validateAndProcessValue('site', $fieldName, $fieldValue);
270  $newSysSiteData[$fieldName] = $fieldValue;
271  break;
272 
273  case 'inline':
274  $newSysSiteData[$fieldName] = [];
275  $childRowIds = GeneralUtility::trimExplode(',', $fieldValue, true);
276  if (!isset($siteTca['site']['columns'][$fieldName]['config']['foreign_table'])) {
277  throw new \RuntimeException('No foreign_table found for inline type', 1521555037);
278  }
279  $foreignTable = $siteTca['site']['columns'][$fieldName]['config']['foreign_table'];
280  foreach ($childRowIds as $childRowId) {
281  $childRowData = [];
282  if (!isset($data[$foreignTable][$childRowId])) {
283  if (!empty($currentSiteConfiguration[$fieldName][$childRowId])) {
284  // A collapsed inline record: Fetch data from existing config
285  $newSysSiteData[$fieldName][] = $currentSiteConfiguration[$fieldName][$childRowId];
286  continue;
287  }
288  throw new \RuntimeException('No data found for table ' . $foreignTable . ' with id ' . $childRowId, 1521555177);
289  }
290  $childRow = $data[$foreignTable][$childRowId];
291  foreach ($childRow as $childFieldName => $childFieldValue) {
292  if ($childFieldName === 'pid') {
293  // pid is added by inline by default, but not relevant for yml storage
294  continue;
295  }
296  $type = $siteTca[$foreignTable]['columns'][$childFieldName]['config']['type'];
297  switch ($type) {
298  case 'input':
299  case 'select':
300  case 'text':
301  $childRowData[$childFieldName] = $childFieldValue;
302  break;
303  case 'check':
304  $childRowData[$childFieldName] = (bool)$childFieldValue;
305  break;
306  default:
307  throw new \RuntimeException('TCA type ' . $type . ' not implemented in site handling', 1521555340);
308  }
309  }
310  $newSysSiteData[$fieldName][] = $childRowData;
311  }
312  break;
313 
314  case 'select':
315  $newSysSiteData[$fieldName] = ‪MathUtility::canBeInterpretedAsInteger($fieldValue) ? (int)$fieldValue : $fieldValue;
316  break;
317 
318  case 'check':
319  $newSysSiteData[$fieldName] = (bool)$fieldValue;
320  break;
321 
322  default:
323  throw new \RuntimeException('TCA type "' . $type . '" is not implemented in site handling', 1521032781);
324  }
325  }
326 
327  // keep root config objects not given via GUI
328  // this way extension authors are able to use their own objects on root level
329  // that are not configurable via GUI
330  // however: we overwrite the full subset of any GUI object to make sure we have a clean state
331  $newSysSiteData = array_merge($currentSiteConfiguration, $newSysSiteData);
332  $newSiteConfiguration = $this->‪validateFullStructure($newSysSiteData);
333 
334  // Persist the configuration
335  $siteConfigurationManager = GeneralUtility::makeInstance(SiteConfiguration::class, ‪Environment::getConfigPath() . '/sites');
336  if (!$isNewConfiguration && $currentIdentifier !== $siteIdentifier) {
337  $siteConfigurationManager->rename($currentIdentifier, $siteIdentifier);
338  }
339  $siteConfigurationManager->write($siteIdentifier, $newSiteConfiguration);
340  } catch (SiteValidationErrorException $e) {
341  // Do not store new config if a validation error is thrown, but redirect only to show a generated flash message
342  }
343 
344  $saveRoute = $uriBuilder->buildUriFromRoute('site_configuration', ['action' => 'edit', 'site' => $siteIdentifier]);
345  if ($isSaveClose) {
346  return new RedirectResponse($overviewRoute);
347  }
348  return new RedirectResponse($saveRoute);
349  }
350 
359  protected function ‪validateAndProcessIdentifier(bool $isNew, string $identifier, int $rootPageId)
360  {
361  $languageService = $this->‪getLanguageService();
362  // Normal "eval" processing of field first
363  $identifier = $this->‪validateAndProcessValue('site', 'identifier', $identifier);
364  if ($isNew) {
365  // Verify no other site with this identifier exists. If so, find a new unique name as
366  // identifier and show a flash message the identifier has been adapted
367  try {
368  $this->siteFinder->getSiteByIdentifier($identifier);
369  // Force this identifier to be unique
370  $originalIdentifier = $identifier;
371  $identifier = $identifier . '-' . str_replace('.', '', uniqid((string)mt_rand(), true));
372  $message = sprintf(
373  $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.identifierRenamed.message'),
374  $originalIdentifier,
375  $identifier
376  );
377  $messageTitle = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.identifierRenamed.title');
378  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, ‪FlashMessage::WARNING, true);
379  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
380  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
381  $defaultFlashMessageQueue->enqueue($flashMessage);
382  } catch (SiteNotFoundException $e) {
383  // Do nothing, this new identifier is ok
384  }
385  } else {
386  // If this is an existing config, the site for this identifier must have the same rootPageId, otherwise
387  // a user tried to rename a site identifier to a different site that already exists. If so, we do not rename
388  // the site and show a flash message
389  try {
390  $site = $this->siteFinder->getSiteByIdentifier($identifier);
391  if ($site->getRootPageId() !== $rootPageId) {
392  // Find original value and keep this
393  $origSite = $this->siteFinder->getSiteByRootPageId($rootPageId);
394  $originalIdentifier = $identifier;
395  $identifier = $origSite->getIdentifier();
396  $message = sprintf(
397  $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.identifierExists.message'),
398  $originalIdentifier,
399  $identifier
400  );
401  $messageTitle = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.identifierExists.title');
402  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, ‪FlashMessage::WARNING, true);
403  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
404  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
405  $defaultFlashMessageQueue->enqueue($flashMessage);
406  }
407  } catch (SiteNotFoundException $e) {
408  // User is renaming identifier which does not exist yet. That's ok
409  }
410  }
411  return $identifier;
412  }
413 
426  protected function ‪validateAndProcessValue(string $tableName, string $fieldName, $fieldValue)
427  {
428  $languageService = $this->‪getLanguageService();
429  $fieldConfig = ‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'];
430  $handledEvals = [];
431  if (!empty($fieldConfig['eval'])) {
432  $evalArray = GeneralUtility::trimExplode(',', $fieldConfig['eval'], true);
433  // Processing
434  if (in_array('alphanum_x', $evalArray, true)) {
435  $handledEvals[] = 'alphanum_x';
436  $fieldValue = preg_replace('/[^a-zA-Z0-9_-]/', '', $fieldValue);
437  }
438  if (in_array('lower', $evalArray, true)) {
439  $handledEvals[] = 'lower';
440  $fieldValue = mb_strtolower($fieldValue, 'utf-8');
441  }
442  if (in_array('trim', $evalArray, true)) {
443  $handledEvals[] = 'trim';
444  $fieldValue = trim($fieldValue);
445  }
446  if (in_array('int', $evalArray, true)) {
447  $handledEvals[] = 'int';
448  $fieldValue = (int)$fieldValue;
449  }
450  // Validation throws - these should be handled client side already,
451  // eg. 'required' being set and receiving empty, shouldn't happen server side
452  if (in_array('required', $evalArray, true)) {
453  $handledEvals[] = 'required';
454  if (empty($fieldValue)) {
455  $message = sprintf(
456  $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.required.message'),
457  $fieldName
458  );
459  $messageTitle = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.required.title');
460  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, ‪FlashMessage::WARNING, true);
461  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
462  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
463  $defaultFlashMessageQueue->enqueue($flashMessage);
464  throw new SiteValidationErrorException(
465  'Field ' . $fieldName . ' is set to required, but received empty.',
466  1521726421
467  );
468  }
469  }
470  if (!empty(array_diff($evalArray, $handledEvals))) {
471  throw new \RuntimeException('At least one not implemented \'eval\' in list ' . $fieldConfig['eval'], 1522491734);
472  }
473  }
474  if (isset($fieldConfig['range']['lower'])) {
475  $fieldValue = (int)$fieldValue < (int)$fieldConfig['range']['lower'] ? (int)$fieldConfig['range']['lower'] : (int)$fieldValue;
476  }
477  if (isset($fieldConfig['range']['upper'])) {
478  $fieldValue = (int)$fieldValue > (int)$fieldConfig['range']['upper'] ? (int)$fieldConfig['range']['upper'] : (int)$fieldValue;
479  }
480  return $fieldValue;
481  }
482 
491  protected function ‪validateFullStructure(array $newSysSiteData): array
492  {
493  $languageService = $this->‪getLanguageService();
494  // Verify there are not two error handlers with the same error code
495  if (isset($newSysSiteData['errorHandling']) && is_array($newSysSiteData['errorHandling'])) {
496  $uniqueCriteria = [];
497  $validChildren = [];
498  foreach ($newSysSiteData['errorHandling'] as $child) {
499  if (!isset($child['errorCode'])) {
500  throw new \RuntimeException('No errorCode found', 1521788518);
501  }
502  if (!in_array((int)$child['errorCode'], $uniqueCriteria, true)) {
503  $uniqueCriteria[] = (int)$child['errorCode'];
504  $validChildren[] = $child;
505  } else {
506  $message = sprintf(
507  $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.duplicateErrorCode.message'),
508  $child['errorCode']
509  );
510  $messageTitle = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.duplicateErrorCode.title');
511  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, ‪FlashMessage::WARNING, true);
512  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
513  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
514  $defaultFlashMessageQueue->enqueue($flashMessage);
515  }
516  }
517  $newSysSiteData['errorHandling'] = $validChildren;
518  }
519 
520  // Verify there is only one inline child per sys_language record configured.
521  if (!isset($newSysSiteData['languages']) || !is_array($newSysSiteData['languages']) || count($newSysSiteData['languages']) < 1) {
522  throw new \RuntimeException(
523  'No default language definition found. The interface does not allow this. Aborting',
524  1521789306
525  );
526  }
527  $uniqueCriteria = [];
528  $validChildren = [];
529  foreach ($newSysSiteData['languages'] as $child) {
530  if (!isset($child['languageId'])) {
531  throw new \RuntimeException('languageId not found', 1521789455);
532  }
533  if (!in_array((int)$child['languageId'], $uniqueCriteria, true)) {
534  $uniqueCriteria[] = (int)$child['languageId'];
535  $validChildren[] = $child;
536  } else {
537  $message = sprintf(
538  $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.duplicateLanguageId.title'),
539  $child['languageId']
540  );
541  $messageTitle = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration.xlf:validation.duplicateLanguageId.title');
542  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, ‪FlashMessage::WARNING, true);
543  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
544  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
545  $defaultFlashMessageQueue->enqueue($flashMessage);
546  }
547  }
548  $newSysSiteData['languages'] = $validChildren;
549 
550  return $newSysSiteData;
551  }
552 
559  protected function ‪deleteAction(ServerRequestInterface $request): ResponseInterface
560  {
561  $siteIdentifier = $request->getQueryParams()['site'] ?? '';
562  if (empty($siteIdentifier)) {
563  throw new \RuntimeException('Not site identifier given', 1521565182);
564  }
565  // Verify site does exist, method throws if not
566  GeneralUtility::makeInstance(SiteConfiguration::class, ‪Environment::getConfigPath() . '/sites')->delete($siteIdentifier);
567  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
568  $overviewRoute = $uriBuilder->buildUriFromRoute('site_configuration', ['action' => 'overview']);
569  return new RedirectResponse($overviewRoute);
570  }
571 
577  protected function ‪initializeView(string $templateName): void
578  {
579  $this->view = GeneralUtility::makeInstance(StandaloneView::class);
580  $this->view->setTemplate($templateName);
581  $this->view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/SiteConfiguration']);
582  $this->view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials']);
583  $this->view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
584  }
585 
589  protected function ‪configureEditViewDocHeader(): void
590  {
591  $iconFactory = $this->moduleTemplate->getIconFactory();
592  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
593  $lang = $this->‪getLanguageService();
594  $closeButton = $buttonBar->makeLinkButton()
595  ->setHref('#')
596  ->setClasses('t3js-editform-close')
597  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
598  ->setShowLabelText(true)
599  ->setIcon($iconFactory->getIcon('actions-close', ‪Icon::SIZE_SMALL));
600  $saveButton = $buttonBar->makeInputButton()
601  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
602  ->setName('_savedok')
603  ->setValue('1')
604  ->setShowLabelText(true)
605  ->setForm('siteConfigurationController')
606  ->setIcon($iconFactory->getIcon('actions-document-save', ‪Icon::SIZE_SMALL));
607  $buttonBar->addButton($closeButton);
608  $buttonBar->addButton($saveButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 2);
609  }
610 
614  protected function ‪configureOverViewDocHeader(): void
615  {
616  $iconFactory = $this->moduleTemplate->getIconFactory();
617  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
618  $reloadButton = $buttonBar->makeLinkButton()
619  ->setHref(GeneralUtility::getIndpEnv('REQUEST_URI'))
620  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
621  ->setIcon($iconFactory->getIcon('actions-refresh', ‪Icon::SIZE_SMALL));
622  $buttonBar->addButton($reloadButton, ‪ButtonBar::BUTTON_POSITION_RIGHT);
623  if ($this->‪getBackendUser()->mayMakeShortcut()) {
624  $getVars = ['id', 'route'];
625  $shortcutButton = $buttonBar->makeShortcutButton()
626  ->setModuleName('site_configuration')
627  ->setGetVariables($getVars);
628  $buttonBar->addButton($shortcutButton, ‪ButtonBar::BUTTON_POSITION_RIGHT);
629  }
630  }
631 
637  protected function ‪getAllSitePages(): array
638  {
639  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
640  $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
641  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, 0, false));
642  $statement = $queryBuilder
643  ->select('*')
644  ->from('pages')
645  ->where(
646  $queryBuilder->expr()->eq('sys_language_uid', 0),
647  $queryBuilder->expr()->orX(
648  $queryBuilder->expr()->andX(
649  $queryBuilder->expr()->eq('pid', 0),
650  $queryBuilder->expr()->neq('doktype', ‪PageRepository::DOKTYPE_SYSFOLDER)
651  ),
652  $queryBuilder->expr()->eq('is_siteroot', 1)
653  )
654  )
655  ->orderBy('pid')
656  ->addOrderBy('sorting')
657  ->execute();
658 
659  $pages = [];
660  while ($row = $statement->fetch()) {
661  $row['rootline'] = ‪BackendUtility::BEgetRootLine((int)$row['uid']);
662  array_pop($row['rootline']);
663  $row['rootline'] = array_reverse($row['rootline']);
664  $i = 0;
665  foreach ($row['rootline'] as &$record) {
666  $record['margin'] = $i++ * 20;
667  }
668  $pages[(int)$row['uid']] = $row;
669  }
670  return $pages;
671  }
672 
676  protected function ‪getLanguageService(): LanguageService
677  {
678  return ‪$GLOBALS['LANG'];
679  }
680 
684  protected function ‪getBackendUser(): BackendUserAuthentication
685  {
686  return ‪$GLOBALS['BE_USER'];
687  }
688 }
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\$siteFinder
‪SiteFinder $siteFinder
Definition: SiteConfigurationController.php:71
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:25
‪TYPO3\CMS\Backend\Configuration\SiteTcaConfiguration
Definition: SiteTcaConfiguration.php:32
‪TYPO3\CMS\Backend\Form\FormResultCompiler
Definition: FormResultCompiler.php:28
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:35
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:31
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\validateAndProcessValue
‪mixed validateAndProcessValue(string $tableName, string $fieldName, $fieldValue)
Definition: SiteConfigurationController.php:423
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\$moduleTemplate
‪ModuleTemplate $moduleTemplate
Definition: SiteConfigurationController.php:63
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction
Definition: BackendWorkspaceRestriction.php:28
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:374
‪TYPO3\CMS\Core\Configuration\SiteConfiguration
Definition: SiteConfiguration.php:38
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:40
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\__construct
‪__construct()
Definition: SiteConfigurationController.php:76
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\configureOverViewDocHeader
‪configureOverViewDocHeader()
Definition: SiteConfigurationController.php:611
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\validateAndProcessIdentifier
‪mixed validateAndProcessIdentifier(bool $isNew, string $identifier, int $rootPageId)
Definition: SiteConfigurationController.php:356
‪TYPO3\CMS\Core\Messaging\AbstractMessage\WARNING
‪const WARNING
Definition: AbstractMessage.php:28
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\overviewAction
‪overviewAction()
Definition: SiteConfigurationController.php:115
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\saveAction
‪ResponseInterface saveAction(ServerRequestInterface $request)
Definition: SiteConfigurationController.php:206
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController
Definition: SiteConfigurationController.php:58
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\deleteAction
‪ResponseInterface deleteAction(ServerRequestInterface $request)
Definition: SiteConfigurationController.php:556
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_SYSFOLDER
‪const DOKTYPE_SYSFOLDER
Definition: PageRepository.php:174
‪TYPO3\CMS\Frontend\Page\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Backend\Exception\SiteValidationErrorException
Definition: SiteValidationErrorException.php:24
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\$view
‪ViewInterface $view
Definition: SiteConfigurationController.php:67
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\getAllSitePages
‪array getAllSitePages()
Definition: SiteConfigurationController.php:634
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:27
‪TYPO3\CMS\Backend\Form\NodeFactory
Definition: NodeFactory.php:36
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:22
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:32
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\editAction
‪editAction(ServerRequestInterface $request)
Definition: SiteConfigurationController.php:142
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\initializeView
‪initializeView(string $templateName)
Definition: SiteConfigurationController.php:574
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\validateFullStructure
‪array validateFullStructure(array $newSysSiteData)
Definition: SiteConfigurationController.php:488
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\handleRequest
‪ResponseInterface handleRequest(ServerRequestInterface $request)
Definition: SiteConfigurationController.php:88
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\ALLOWED_ACTIONS
‪const ALLOWED_ACTIONS
Definition: SiteConfigurationController.php:59
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Core\Core\Environment\getConfigPath
‪static string getConfigPath()
Definition: Environment.php:183
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Form\FormDataCompiler
Definition: FormDataCompiler.php:24
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_RIGHT
‪const BUTTON_POSITION_RIGHT
Definition: ButtonBar.php:40
‪TYPO3\CMS\Backend\Form\FormDataGroup\SiteConfigurationDataGroup
Definition: SiteConfigurationDataGroup.php:31
‪TYPO3\CMS\Backend\Controller
Definition: AbstractFormEngineAjaxController.php:3
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:25
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\getLanguageService
‪LanguageService getLanguageService()
Definition: SiteConfigurationController.php:673
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: SiteConfigurationController.php:681
‪TYPO3\CMS\Backend\Controller\SiteConfigurationController\configureEditViewDocHeader
‪configureEditViewDocHeader()
Definition: SiteConfigurationController.php:586
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:25