2 declare(strict_types = 1);
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
53 'pageinfo' =>
'Using $pageinfo of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
54 'pidInfo' =>
'Using $pidInfo of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
55 'newPagesInto' =>
'Using $newPagesInto of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
56 'newContentInto' =>
'Using $newContentInto of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
57 'newPagesAfter' =>
'Using $newPagesAfter of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
58 'web_list_modTSconfig' =>
'Using $web_list_modTSconfig of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
59 'allowedNewTables' =>
'Using $allowedNewTables of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
60 'deniedNewTables' =>
'Using $deniedNewTables of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
61 'web_list_modTSconfig_pid' =>
'Using $web_list_modTSconfig_pid of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
62 'allowedNewTables_pid' =>
'Using $allowedNewTables_pid of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
63 'deniedNewTables_pid' =>
'Using $deniedNewTables_pid of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
64 'code' =>
'Using $code of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
65 'R_URI' =>
'Using $R_URI of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
66 'returnUrl' =>
'Using $returnUrl of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
67 'pagesOnly' =>
'Using $pagesOnly of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
68 'perms_clause' =>
'Using $perms_clause of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
69 'content' =>
'Using $content of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
70 'tRows' =>
'Using $tRows of class NewRecordController from outside is discouraged as this variable is only used for internal storage.',
199 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
216 public function mainAction(ServerRequestInterface $request): ResponseInterface
220 if (empty($response)) {
221 $response =
new HtmlResponse($this->moduleTemplate->renderContent());
232 public function main()
234 trigger_error(
'NewRecordController->main() will be replaced by protected method renderContent() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
250 trigger_error(
'NewRecordController->pagesOnly() will be replaced by protected method renderPositionTree() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
261 trigger_error(
'NewRecordController->regularNew() will be replaced by protected method renderNewRecordControls() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
275 trigger_error(
'NewRecordController->sortNewRecordsByConfig() will be replaced by protected method sortTableRows() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
289 public function linkWrap($linkText, $table, $pid, $addContentTable =
false)
291 trigger_error(
'NewRecordController->linkWrap() will be replaced by protected method renderLink() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
292 return $this->
renderLink($linkText, $table, $pid, $addContentTable);
305 trigger_error(
'NewRecordController->isTableAllowedForThisPage() will be replaced by protected method isTableAllowedOnPage() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
326 trigger_error(
'NewRecordController->showNewRecLink() will be replaced by protected method isRecordCreationAllowedForTable() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
335 protected function init(ServerRequestInterface $request): void
341 $pidList = $beUser->getTSConfig()[
'options.'][
'hideRecords.'][
'pages'] ??
'';
342 if (!empty($pidList)) {
343 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
344 ->getQueryBuilderForTable(
'pages');
345 $this->perms_clause .=
' AND ' . $queryBuilder->expr()->notIn(
347 GeneralUtility::intExplode(
',', $pidList)
351 $parsedBody = $request->getParsedBody();
352 $queryParams = $request->getQueryParams();
354 $this->
id = (int)($parsedBody[
'id'] ?? $queryParams[
'id'] ?? 0);
355 $this->returnUrl = GeneralUtility::sanitizeLocalUrl($parsedBody[
'returnUrl'] ?? $queryParams[
'returnUrl'] ??
'');
356 $this->
pagesOnly = $parsedBody[
'pagesOnly'] ?? $queryParams[
'pagesOnly'] ??
null;
358 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Backend/ContextMenu');
359 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Backend/Tooltip');
360 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Backend/PageActions');
363 $this->content .=
'<h1>'
364 . $this->
getLanguageService()->
sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.pagetitle')
371 if ($this->pageinfo[
'uid']) {
376 if ($beUser->doesUserHaveAccess($this->pageinfo, 8)) {
377 $this->newPagesInto = 1;
379 if ($beUser->doesUserHaveAccess($this->pageinfo, 16)) {
380 $this->newContentInto = 1;
382 if (($beUser->isAdmin() || !empty($this->pidInfo)) && $beUser->doesUserHaveAccess($this->pidInfo, 8)) {
383 $this->newPagesAfter = 1;
385 } elseif ($beUser->isAdmin()) {
387 $this->newPagesInto = 1;
388 $this->newContentInto = 1;
389 $this->newPagesAfter = 0;
392 $this->newPagesInto = 0;
393 $this->newContentInto = 0;
394 $this->newPagesAfter = 0;
404 protected function renderContent(ServerRequestInterface $request): ?ResponseInterface
408 if (empty($this->pageinfo)) {
410 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation([]);
412 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
416 $this->allowedNewTables = GeneralUtility::trimExplode(
',', $this->web_list_modTSconfig[
'allowedNewTables'] ??
'',
true);
417 $this->deniedNewTables = GeneralUtility::trimExplode(
',', $this->web_list_modTSconfig[
'deniedNewTables'] ??
'',
true);
420 $this->allowedNewTables_pid = GeneralUtility::trimExplode(
',', $this->web_list_modTSconfig_pid[
'allowedNewTables'] ??
'',
true);
421 $this->deniedNewTables_pid = GeneralUtility::trimExplode(
',', $this->web_list_modTSconfig_pid[
'deniedNewTables'] ??
'',
true);
424 $this->newPagesInto = 0;
427 $this->newPagesAfter = 0;
430 if (is_array($this->pageinfo) && $this->pageinfo[
'uid']) {
431 $title = strip_tags($this->pageinfo[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'label']]);
433 $title =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename'];
435 $this->moduleTemplate->setTitle($title);
444 if (!empty($response)) {
449 $this->content .=
'<div>' . $this->code .
'</div>';
453 $this->moduleTemplate->setContent($this->content);
465 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
470 $newPageButton = $buttonBar->makeLinkButton()
471 ->setHref(GeneralUtility::linkThisScript([
'pagesOnly' =>
'1']))
472 ->setTitle($lang->sL(
'LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:newPage'))
473 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-page-new',
Icon::SIZE_SMALL));
477 $cshButton = $buttonBar->makeHelpButton()->setModuleName(
'xMOD_csh_corebe')->setFieldName(
'new_regular');
478 $buttonBar->addButton($cshButton);
483 $cshButton = $buttonBar->makeHelpButton()->setModuleName(
'xMOD_csh_corebe')->setFieldName(
'new_pages');
484 $buttonBar->addButton($cshButton);
487 if ($this->returnUrl) {
488 $returnButton = $buttonBar->makeLinkButton()
489 ->setHref($this->returnUrl)
490 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
491 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-view-go-back',
Icon::SIZE_SMALL));
495 if (is_array($this->pageinfo) && $this->pageinfo[
'uid']) {
498 if (isset($pagesTSconfig[
'TCEMAIN.'][
'preview.'][
'disableButtonForDokType'])) {
499 $excludeDokTypes = GeneralUtility::intExplode(
501 $pagesTSconfig[
'TCEMAIN.'][
'preview.'][
'disableButtonForDokType'],
512 if (!in_array((
int)$this->pageinfo[
'doktype'], $excludeDokTypes,
true)) {
513 $viewButton = $buttonBar->makeLinkButton()
516 $this->pageinfo[
'uid'],
520 ->setTitle($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
521 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
537 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
538 ->getQueryBuilderForTable(
'pages');
539 $queryBuilder->getRestrictions()
541 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
542 $numberOfPages = $queryBuilder
548 if ($numberOfPages > 0) {
549 $this->code .=
'<h3>' . htmlspecialchars($this->
getLanguageService()->getLL(
'selectPosition')) .
':</h3>';
551 $positionMap = GeneralUtility::makeInstance(PagePositionMap::class, NewRecordPageTreeView::class);
552 $this->code .= $positionMap->positionTree(
560 $uriBuilder = GeneralUtility::makeInstance(\
TYPO3\CMS\Backend\Routing\UriBuilder::class);
568 'returnNewPageId' => 1,
569 'returnUrl' => (string)$uriBuilder->buildUriFromRoute(
'db_new', [
'id' => $this->id,
'pagesOnly' =>
'1'])
571 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
595 $this->newPagesSelectPosition = !empty($pageTS[
'mod.'][
'wizards.'][
'newRecord.'][
'pages.'][
'show.'][
'pageSelectPosition']);
597 $displayNewPagesIntoLink = $this->newPagesInto && !empty($pageTS[
'mod.'][
'wizards.'][
'newRecord.'][
'pages.'][
'show.'][
'pageInside']);
598 $displayNewPagesAfterLink = $this->newPagesAfter && !empty($pageTS[
'mod.'][
'wizards.'][
'newRecord.'][
'pages.'][
'show.'][
'pageAfter']);
604 $pageIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord(
609 $newPageIcon = $this->moduleTemplate->getIconFactory()->getIcon(
'actions-page-new',
Icon::SIZE_SMALL)->render();
613 if ($displayNewPagesIntoLink
619 $recordIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord($table, [],
Icon::SIZE_SMALL)->render();
621 $recordIcon . htmlspecialchars($lang->sL($v[
'ctrl'][
'title'])) .
' (' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.inside')) .
')',
627 if ($displayNewPagesAfterLink
633 $pageIcon . htmlspecialchars($lang->sL($v[
'ctrl'][
'title'])) .
' (' . htmlspecialchars($lang->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.after')) .
')',
641 $newPageLinks[] =
'<a href="' . htmlspecialchars(GeneralUtility::linkThisScript([
'pagesOnly' => 1])) .
'">' . $pageIcon . htmlspecialchars($lang->getLL(
'pageSelectPosition')) .
'</a>';
644 $numPageLinks = count($newPageLinks);
645 for ($i = 0; $i < $numPageLinks; $i++) {
646 $rowContent .=
'<li>' . $newPageLinks[$i] .
'</li>';
649 $rowContent =
'<ul class="list-tree"><li>' . $newPageIcon .
'<strong>' .
650 $lang->getLL(
'createNewPage') .
'</strong><ul>' . $rowContent .
'</ul></li>';
652 $rowContent =
'<ul class="list-tree"><li><ul>' . $rowContent .
'</li></ul>';
655 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
657 $startRows = [$rowContent];
661 $newContentIcon = $this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-new',
Icon::SIZE_SMALL)->render();
662 if ($this->newContentInto) {
665 foreach (
$GLOBALS[
'TCA'] as $table => $v) {
666 $rootLevelConfiguration = isset($v[
'ctrl'][
'rootLevel']) ? (int)$v[
'ctrl'][
'rootLevel'] : 0;
667 if ($table !==
'pages'
671 && ($rootLevelConfiguration === -1 || ($this->
id xor $rootLevelConfiguration))
674 $newRecordIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord($table, [],
Icon::SIZE_SMALL)->render();
679 $newRecordIcon . htmlspecialchars($lang->sL($v[
'ctrl'][
'title'])),
684 if ($table ===
'tt_content') {
685 $groupName = $lang->getLL(
'createNewContent');
686 $rowContent = $newContentIcon
687 .
'<strong>' . $lang->getLL(
'createNewContent') .
'</strong>'
691 ??
'new_content_element_wizard';
693 $normalizedParams = $request->getAttribute(
'normalizedParams');
694 $url = (string)$uriBuilder->buildUriFromRoute($moduleName, [
'id' => $this->id,
'returnUrl' => $normalizedParams->getRequestUri()]);
697 .
'<a href="' . htmlspecialchars($url) .
'" data-title="' . htmlspecialchars($this->
getLanguageService()->getLL(
'newContentElement')) .
'" class="t3js-toggle-new-content-element-wizard disabled">'
698 . $newContentIcon . htmlspecialchars($lang->getLL(
'clickForWizard'))
704 if ($v[
'ctrl'][
'readOnly'] || $v[
'ctrl'][
'hideTable'] || $v[
'ctrl'][
'is_static']) {
707 if ($v[
'ctrl'][
'adminOnly'] && !$isAdmin) {
710 $nameParts = explode(
'_', $table);
713 if ($nameParts[0] ===
'tx' || $nameParts[0] ===
'tt') {
715 $title = (string)($v[
'ctrl'][
'title'] ??
'');
716 if (strpos($title,
'LLL:EXT:') === 0) {
717 $_EXTKEY = substr($title, 8);
718 $_EXTKEY = substr($_EXTKEY, 0, strpos($_EXTKEY,
'/'));
719 if ($_EXTKEY !==
'') {
721 $temp = explode(
':', substr($title, 9 + strlen($_EXTKEY)));
722 $langFile = $temp[0];
723 $thisTitle = $lang->sL(
'LLL:EXT:' . $_EXTKEY .
'/' . $langFile .
':extension.title');
726 $extEmConfFile = $extPath .
'ext_emconf.php';
727 if (!$thisTitle && is_file($extEmConfFile)) {
729 include $extEmConfFile;
730 $thisTitle =
$EM_CONF[$_EXTKEY][
'title'];
735 if (empty($thisTitle)) {
736 $_EXTKEY = $nameParts[1];
737 $thisTitle = $nameParts[1];
738 $iconFile[$_EXTKEY] =
'';
742 $thisTitle = $lang->getLL(
'system_records');
743 $iconFile[
'system'] = $this->moduleTemplate->getIconFactory()->getIcon(
'apps-pagetree-root',
Icon::SIZE_SMALL)->render();
746 if ($groupName ===
'' || $groupName !== $_EXTKEY) {
747 $groupName = empty($v[
'ctrl'][
'groupName']) ? $_EXTKEY : $v[
'ctrl'][
'groupName'];
749 $rowContent .= $newLink;
752 if ($table ===
'tt_content') {
753 $startRows[] =
'<li>' . $rowContent .
'</li>';
755 $this->tRows[$groupName][
'title'] = $thisTitle;
756 $this->tRows[$groupName][
'html'][] = $rowContent;
757 $this->tRows[$groupName][
'table'][] = $table;
764 if (isset($pageTS[
'mod.'][
'wizards.'][
'newRecord.'][
'order'])) {
765 $this->newRecordSortList = GeneralUtility::trimExplode(
',', $pageTS[
'mod.'][
'wizards.'][
'newRecord.'][
'order'],
true);
767 uksort($this->tRows, [$this,
'sortTableRows']);
770 $finalRows[] = implode(
'', $startRows);
771 foreach ($this->tRows as $key => $value) {
772 $row =
'<li>' . $iconFile[$key] .
' <strong>' . $value[
'title'] .
'</strong><ul>';
773 foreach ($value[
'html'] as $recordKey => $record) {
776 $row .=
'</ul></li>';
780 $finalRows[] =
'</ul>';
782 $this->code .= implode(
'', $finalRows);
794 if (!empty($this->newRecordSortList)) {
795 if (in_array($a, $this->newRecordSortList) && in_array($b, $this->newRecordSortList)) {
797 $sub = array_search($a, $this->newRecordSortList) - array_search($b, $this->newRecordSortList);
798 $ret = ($sub < 0 ? -1 : $sub == 0) ? 0 : 1;
799 } elseif (in_array($a, $this->newRecordSortList)) {
802 } elseif (in_array($b, $this->newRecordSortList)) {
807 $ret = strnatcasecmp($this->tRows[$a][
'title'], $this->tRows[$b][
'title']);
812 return strnatcasecmp($this->tRows[$a][
'title'], $this->tRows[$b][
'title']);
824 protected function renderLink(
string $linkText,
string $table,
int $pid,
bool $addContentTable =
false): string
835 if ($table ===
'pages' && $addContentTable) {
836 $urlParameters[
'tt_content'][
'prev'] =
'new';
837 $urlParameters[
'returnNewPageId'] = 1;
840 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
841 $url = (string)$uriBuilder->buildUriFromRoute(
'record_edit', $urlParameters);
843 return '<a href="' . htmlspecialchars($url) .
'">' . $linkText .
'</a>';
859 if ($table ===
'be_users' || $table ===
'be_groups') {
863 $doktype = (int)$page[
'doktype'];
864 if (!($allowedTableList =
$GLOBALS[
'PAGES_TYPES'][$doktype][
'allowedTables'])) {
865 $allowedTableList =
$GLOBALS[
'PAGES_TYPES'][
'default'][
'allowedTables'];
868 if (strstr($allowedTableList,
'*') || GeneralUtility::inList($allowedTableList, $table)) {
914 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
915 ->getQueryBuilderForTable(
'sys_language');
916 $queryBuilder->getRestrictions()->removeAll();
918 $count = $queryBuilder
920 ->from(
'sys_language')