‪TYPO3CMS  ‪main
NewMultiplePagesController.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\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
26 use TYPO3\CMS\Backend\Utility\BackendUtility;
35 use TYPO3\CMS\Core\Imaging\IconSize;
41 
47 #[AsController]
49 {
50  public function ‪__construct(
51  protected readonly ‪IconFactory $iconFactory,
52  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory,
53  protected readonly ‪SelectItemProcessor $selectItemProcessor,
54  ) {}
55 
59  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
60  {
61  $view = $this->moduleTemplateFactory->create($request);
62  $backendUser = $this->‪getBackendUser();
63  $pageUid = (int)$request->getQueryParams()['id'];
64 
65  // Show only if there is a valid page and if this page may be viewed by the user
66  $pageRecord = BackendUtility::readPageAccess($pageUid, $backendUser->getPagePermsClause(‪Permission::PAGE_SHOW));
67  if (!is_array($pageRecord)) {
68  // User has no permission on parent page, should not happen, just render an empty page
69  return $view->renderResponse('Dummy/Index');
70  }
71 
72  // Doc header handling
73  $view->getDocHeaderComponent()->setMetaInformation($pageRecord);
74  $buttonBar = $view->getDocHeaderComponent()->getButtonBar();
75  $previewDataAttributes = ‪PreviewUriBuilder::create($pageUid)
76  ->withRootLine(BackendUtility::BEgetRootLine($pageUid))
77  ->buildDispatcherDataAttributes();
78  $viewButton = $buttonBar->makeLinkButton()
79  ->setHref('#')
80  ->setDataAttributes($previewDataAttributes ?? [])
81  ->setDisabled(!$previewDataAttributes)
82  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
83  ->setIcon($this->iconFactory->getIcon('actions-view-page', IconSize::SMALL))
84  ->setShowLabelText(true);
85  $buttonBar->addButton($viewButton);
86 
87  $calculatedPermissions = new ‪Permission($backendUser->calcPerms($pageRecord));
88  $canCreateNew = $backendUser->isAdmin() || $calculatedPermissions->createPagePermissionIsGranted();
89 
90  $view->assignMultiple([
91  'canCreateNew' => $canCreateNew,
92  'maxTitleLength' => $backendUser->uc['titleLen'] ?? 20,
93  'pageUid' => $pageUid,
94  ]);
95 
96  if ($canCreateNew) {
97  $newPagesData = (array)($request->getParsedBody()['pages'] ?? []);
98  if (!empty($newPagesData)) {
99  $hasNewPagesData = true;
100  $afterExisting = isset($request->getParsedBody()['createInListEnd']);
101  $hidePages = isset($request->getParsedBody()['hidePages']);
102  $hidePagesInMenu = isset($request->getParsedBody()['hidePagesInMenus']);
103  $pagesCreated = $this->‪createPages($newPagesData, $pageUid, $afterExisting, $hidePages, $hidePagesInMenu);
104  $view->assign('pagesCreated', $pagesCreated);
105  $subPages = $this->‪getSubPagesOfPage($pageUid);
106  $visiblePages = [];
107  foreach ($subPages as $page) {
108  $calculatedPermissions = new ‪Permission($backendUser->calcPerms($page));
109  if ($backendUser->isAdmin() || $calculatedPermissions->showPagePermissionIsGranted()) {
110  $visiblePages[] = $page;
111  }
112  }
113  $view->assign('visiblePages', $visiblePages);
114  } else {
115  $hasNewPagesData = false;
116  $view->assign('pageTypes', $this->‪getTypeSelectData($pageUid));
117  }
118  $view->assign('hasNewPagesData', $hasNewPagesData);
119  }
120 
121  return $view->renderResponse('Page/NewPages');
122  }
123 
134  protected function ‪createPages(array $newPagesData, int $pageUid, bool $afterExisting, bool $hidePages, bool $hidePagesInMenu): bool
135  {
136  $pagesCreated = false;
137 
138  // Set first pid to "-1 * uid of last existing sub page" if pages should be created at end
139  $firstPid = $pageUid;
140  if ($afterExisting) {
141  $subPages = $this->‪getSubPagesOfPage($pageUid);
142  $lastPage = end($subPages);
143  if (isset($lastPage['uid']) && ‪MathUtility::canBeInterpretedAsInteger($lastPage['uid'])) {
144  $firstPid = -(int)$lastPage['uid'];
145  }
146  }
147 
148  $dataMap = [];
149  $firstRecord = true;
150  $previousIdentifier = '';
151  foreach ($newPagesData as ‪$identifier => $data) {
152  if (!trim($data['title'])) {
153  continue;
154  }
155  $dataMap['pages'][‪$identifier]['hidden'] = (int)$hidePages;
156  $dataMap['pages'][‪$identifier]['nav_hide'] = (int)$hidePagesInMenu;
157  $dataMap['pages'][‪$identifier]['title'] = $data['title'];
158  $dataMap['pages'][‪$identifier]['doktype'] = $data['doktype'];
159  if ($firstRecord) {
160  $firstRecord = false;
161  $dataMap['pages'][‪$identifier]['pid'] = $firstPid;
162  } else {
163  $dataMap['pages'][‪$identifier]['pid'] = '-' . $previousIdentifier;
164  }
165  $previousIdentifier = ‪$identifier;
166  }
167 
168  if (!empty($dataMap)) {
169  $pagesCreated = true;
170  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
171  $dataHandler->start($dataMap, []);
172  $dataHandler->process_datamap();
173  BackendUtility::setUpdateSignal('updatePageTree');
174  }
175 
176  return $pagesCreated;
177  }
178 
182  protected function ‪getTypeSelectData(int $pageUid): array
183  {
184  $tsConfig = BackendUtility::getPagesTSconfig($pageUid);
185  $pagesTsConfig = $tsConfig['TCEFORM.']['pages.'] ?? [];
186 
187  // Find all available doktypes for the current user
188  $types = GeneralUtility::makeInstance(PageDoktypeRegistry::class)->getRegisteredDoktypes();
194 
195  if (!$this->‪getBackendUser()->isAdmin() && isset($this->‪getBackendUser()->groupData['pagetypes_select'])) {
196  $types = ‪GeneralUtility::intExplode(',', $this->‪getBackendUser()->groupData['pagetypes_select'], true);
197  }
198  $removeItems = isset($pagesTsConfig['doktype.']['removeItems']) ? ‪GeneralUtility::intExplode(',', $pagesTsConfig['doktype.']['removeItems'], true) : [];
199  $allowedPageTypes = array_diff($types, $removeItems);
200 
201  // Transform items to SelectItem for easier usage.
202  $pageTypeConfig = ‪$GLOBALS['TCA']['pages']['columns']['doktype']['config'];
203  $availablePageTypes = $pageTypeConfig['items'];
204  $transformToSelectItem = function (array $item) use ($pageTypeConfig): ‪SelectItem {
205  if ($item['value'] !== '--div--') {
206  $item['value'] = (int)$item['value'];
207  }
208  return ‪SelectItem::fromTcaItemArray($item, $pageTypeConfig['type']);
209  };
210  $availablePageTypes = array_map($transformToSelectItem, $availablePageTypes);
211 
212  // Filter out unavailable types.
213  $filterPageTypes = fn(‪SelectItem $item): bool => $item->‪isDivider() || in_array($item->‪getValue(), $allowedPageTypes, true);
214  $availablePageTypes = array_filter($availablePageTypes, $filterPageTypes);
215 
216  // Sort items.
217  $sortedItems = $this->selectItemProcessor->groupAndSortItems($availablePageTypes, $pageTypeConfig['itemGroups'], $pageTypeConfig['sortItems'] ?? []);
218 
219  // Collect already sorted items and group them by group label.
220  $groupedData = [];
221  $groupLabel = '';
222  foreach ($sortedItems as $selectItem) {
223  // If it is a group, save the group label for the children underneath.
224  if ($selectItem['value'] === '--div--') {
225  // Dividers defined inside the items array are not translated
226  // by the GroupAndSortService.
227  $groupLabel = $this->‪getLanguageService()->sL($selectItem['label']);
228  } else {
229  $groupedData[$groupLabel][] = $selectItem;
230  }
231  }
232 
233  return $groupedData;
234  }
235 
242  protected function ‪getSubPagesOfPage(int $pageUid): array
243  {
244  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
245  $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
246  return $queryBuilder->select('*')
247  ->from('pages')
248  ->where(
249  $queryBuilder->expr()->eq(
250  'pid',
251  $queryBuilder->createNamedParameter($pageUid, ‪Connection::PARAM_INT)
252  ),
253  $queryBuilder->expr()->eq(
254  ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'],
255  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
256  )
257  )
258  ->orderBy('sorting')
259  ->executeQuery()
260  ->fetchAllAssociative();
261  }
262 
264  {
265  return ‪$GLOBALS['LANG'];
266  }
267 
269  {
270  return ‪$GLOBALS['BE_USER'];
271  }
272 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:104
‪TYPO3\CMS\Core\DataHandling\PageDoktypeRegistry
Definition: PageDoktypeRegistry.php:37
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\getBackendUser
‪getBackendUser()
Definition: NewMultiplePagesController.php:268
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_DEFAULT
‪const DOKTYPE_DEFAULT
Definition: PageRepository.php:98
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:35
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController
Definition: NewMultiplePagesController.php:49
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\isDivider
‪isDivider()
Definition: SelectItem.php:212
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\createPages
‪bool createPages(array $newPagesData, int $pageUid, bool $afterExisting, bool $hidePages, bool $hidePagesInMenu)
Definition: NewMultiplePagesController.php:134
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SHORTCUT
‪const DOKTYPE_SHORTCUT
Definition: PageRepository.php:100
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_LINK
‪const DOKTYPE_LINK
Definition: PageRepository.php:99
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:35
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\getLanguageService
‪getLanguageService()
Definition: NewMultiplePagesController.php:263
‪TYPO3\CMS\Backend\Controller\Page
Definition: LocalizationController.php:18
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\getTypeSelectData
‪getTypeSelectData(int $pageUid)
Definition: NewMultiplePagesController.php:182
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_MOUNTPOINT
‪const DOKTYPE_MOUNTPOINT
Definition: PageRepository.php:102
‪TYPO3\CMS\Core\Schema\Struct\SelectItem
Definition: SelectItem.php:21
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\fromTcaItemArray
‪static fromTcaItemArray(array $item, string $type='select')
Definition: SelectItem.php:45
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\getValue
‪getValue()
Definition: SelectItem.php:104
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder\create
‪static static create(int $pageId)
Definition: PreviewUriBuilder.php:65
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:103
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\__construct
‪__construct(protected readonly IconFactory $iconFactory, protected readonly ModuleTemplateFactory $moduleTemplateFactory, protected readonly SelectItemProcessor $selectItemProcessor,)
Definition: NewMultiplePagesController.php:50
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor
Definition: SelectItemProcessor.php:35
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\mainAction
‪mainAction(ServerRequestInterface $request)
Definition: NewMultiplePagesController.php:59
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Controller\Page\NewMultiplePagesController\getSubPagesOfPage
‪getSubPagesOfPage(int $pageUid)
Definition: NewMultiplePagesController.php:242
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder
Definition: PreviewUriBuilder.php:44
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:756
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37