‪TYPO3CMS  9.5
NewRecordController.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;
40 
46 {
48 
52  protected ‪$deprecatedPublicProperties = [
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.',
71  ];
72 
76  protected ‪$pageinfo = [];
77 
81  protected ‪$pidInfo = [];
82 
86  protected ‪$newRecordSortList;
87 
91  protected ‪$newPagesInto;
92 
96  protected ‪$newContentInto;
97 
101  protected ‪$newPagesAfter;
102 
108  protected ‪$newPagesSelectPosition = true;
109 
113  protected ‪$web_list_modTSconfig;
114 
118  protected ‪$allowedNewTables;
119 
124 
129 
133  protected ‪$allowedNewTables_pid;
134 
139 
143  protected ‪$code;
144 
148  protected ‪$R_URI;
149 
156  public ‪$id;
157 
161  protected ‪$returnUrl;
162 
168  protected ‪$pagesOnly;
169 
173  protected ‪$perms_clause;
174 
180  protected ‪$content;
181 
185  protected ‪$tRows;
186 
193 
197  public function ‪__construct()
198  {
199  $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
200  $this->‪getLanguageService()->‪includeLLFile('EXT:core/Resources/Private/Language/locallang_misc.xlf');
201 
202  // @see \TYPO3\CMS\Backend\Tree\View\NewRecordPageTreeView::expandNext()
203  ‪$GLOBALS['SOBE'] = $this;
204 
205  // @deprecated since TYPO3 v9, will be moved out of __construct() in TYPO3 v10.0
206  $this->‪init(‪$GLOBALS['TYPO3_REQUEST']);
207  }
208 
216  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
217  {
218  $response = $this->‪renderContent($request);
219 
220  if (empty($response)) {
221  $response = new ‪HtmlResponse($this->moduleTemplate->renderContent());
222  }
223 
224  return $response;
225  }
226 
232  public function ‪main()
233  {
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);
235 
236  $response = $this->‪renderContent(‪$GLOBALS['TYPO3_REQUEST']);
237 
238  if ($response instanceof ‪RedirectResponse) {
239  ‪HttpUtility::redirect($response->getHeaders()['location'][0]);
240  }
241  }
242 
248  public function ‪pagesOnly()
249  {
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);
251  $this->‪renderPositionTree();
252  }
253 
259  public function ‪regularNew()
260  {
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);
262  $this->‪renderNewRecordControls(‪$GLOBALS['TYPO3_REQUEST']);
263  }
264 
273  public function ‪sortNewRecordsByConfig($a, $b)
274  {
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);
276  return $this->‪sortTableRows($a, $b);
277  }
278 
289  public function ‪linkWrap($linkText, $table, $pid, $addContentTable = false)
290  {
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);
293  }
294 
303  public function ‪isTableAllowedForThisPage($pid_row, $checkTable)
304  {
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);
306  return $this->‪isTableAllowedOnPage($checkTable, $pid_row);
307  }
308 
324  public function ‪showNewRecLink($table, array ‪$allowedNewTables = [], array ‪$deniedNewTables = [])
325  {
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);
328  }
329 
335  protected function ‪init(ServerRequestInterface $request): void
336  {
337  $beUser = $this->‪getBackendUserAuthentication();
338  // Page-selection permission clause (reading)
339  $this->perms_clause = $beUser->getPagePermsClause(‪Permission::PAGE_SHOW);
340  // This will hide records from display - it has nothing to do with user rights!!
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(
346  'pages.uid',
347  GeneralUtility::intExplode(',', $pidList)
348  );
349  }
350  // Setting GPvars:
351  $parsedBody = $request->getParsedBody();
352  $queryParams = $request->getQueryParams();
353  // The page id to operate from
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;
357  // Setting up the context sensitive menu:
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');
361  // Creating content
362  $this->content = '';
363  $this->content .= '<h1>'
364  . $this->‪getLanguageService()->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.pagetitle')
365  . '</h1>';
366  // Id a positive id is supplied, ask for the page record with permission information contained:
367  if ($this->id > 0) {
368  $this->pageinfo = ‪BackendUtility::readPageAccess($this->id, $this->perms_clause);
369  }
370  // If a page-record was returned, the user had read-access to the page.
371  if ($this->pageinfo['uid']) {
372  // Get record of parent page
373  $this->pidInfo = ‪BackendUtility::getRecord('pages', $this->pageinfo['pid']) ?: [];
374  // Checking the permissions for the user with regard to the parent page: Can he create new pages, new
375  // content record, new page after?
376  if ($beUser->doesUserHaveAccess($this->pageinfo, 8)) {
377  $this->newPagesInto = 1;
378  }
379  if ($beUser->doesUserHaveAccess($this->pageinfo, 16)) {
380  $this->newContentInto = 1;
381  }
382  if (($beUser->isAdmin() || !empty($this->pidInfo)) && $beUser->doesUserHaveAccess($this->pidInfo, 8)) {
383  $this->newPagesAfter = 1;
384  }
385  } elseif ($beUser->isAdmin()) {
386  // Admins can do it all
387  $this->newPagesInto = 1;
388  $this->newContentInto = 1;
389  $this->newPagesAfter = 0;
390  } else {
391  // People with no permission can do nothing
392  $this->newPagesInto = 0;
393  $this->newContentInto = 0;
394  $this->newPagesAfter = 0;
395  }
396  }
397 
404  protected function ‪renderContent(ServerRequestInterface $request): ?ResponseInterface
405  {
406  // If there was a page - or if the user is admin (admins has access to the root) we proceed:
407  if (!empty($this->pageinfo['uid']) || $this->‪getBackendUserAuthentication()->isAdmin()) {
408  if (empty($this->pageinfo)) {
409  // Explicitly pass an empty array to the docHeader
410  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation([]);
411  } else {
412  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
413  }
414  // Acquiring TSconfig for this module/current page:
415  $this->web_list_modTSconfig = ‪BackendUtility::getPagesTSconfig($this->pageinfo['uid'])['mod.']['web_list.'] ?? [];
416  $this->allowedNewTables = GeneralUtility::trimExplode(',', $this->web_list_modTSconfig['allowedNewTables'] ?? '', true);
417  $this->deniedNewTables = GeneralUtility::trimExplode(',', $this->web_list_modTSconfig['deniedNewTables'] ?? '', true);
418  // Acquiring TSconfig for this module/parent page:
419  $this->web_list_modTSconfig_pid = ‪BackendUtility::getPagesTSconfig($this->pageinfo['pid'])['mod.']['web_list.'] ?? [];
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);
422  // More init:
423  if (!$this->‪isRecordCreationAllowedForTable('pages')) {
424  $this->newPagesInto = 0;
425  }
426  if (!$this->‪isRecordCreationAllowedForTable('pages', $this->allowedNewTables_pid, $this->deniedNewTables_pid)) {
427  $this->newPagesAfter = 0;
428  }
429  // Set header-HTML and return_url
430  if (is_array($this->pageinfo) && $this->pageinfo['uid']) {
431  $title = strip_tags($this->pageinfo[‪$GLOBALS['TCA']['pages']['ctrl']['label']]);
432  } else {
433  $title = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
434  }
435  $this->moduleTemplate->setTitle($title);
436  // GENERATE the HTML-output depending on mode (pagesOnly is the page wizard)
437  // Regular new element:
438  if (!$this->‪pagesOnly) {
439  $this->‪renderNewRecordControls($request);
440  } elseif ($this->‪isRecordCreationAllowedForTable('pages')) {
441  // Pages only wizard
442  $response = $this->‪renderPositionTree();
443 
444  if (!empty($response)) {
445  return $response;
446  }
447  }
448  // Add all the content to an output section
449  $this->content .= '<div>' . $this->code . '</div>';
450  // Setting up the buttons and markers for docheader
451  $this->‪getButtons();
452  // Build the <body> for the module
453  $this->moduleTemplate->setContent($this->content);
454  }
455 
456  return null;
457  }
458 
462  protected function ‪getButtons(): void
463  {
464  $lang = $this->‪getLanguageService();
465  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
466  // Regular new element:
467  if (!$this->‪pagesOnly) {
468  // New page
469  if ($this->‪isRecordCreationAllowedForTable('pages')) {
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));
474  $buttonBar->addButton($newPageButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 20);
475  }
476  // CSH
477  $cshButton = $buttonBar->makeHelpButton()->setModuleName('xMOD_csh_corebe')->setFieldName('new_regular');
478  $buttonBar->addButton($cshButton);
479  } elseif ($this->‪isRecordCreationAllowedForTable('pages')) {
480  // Pages only wizard
481  // CSH
482  $buttons['csh'] = ‪BackendUtility::cshItem('xMOD_csh_corebe', 'new_pages');
483  $cshButton = $buttonBar->makeHelpButton()->setModuleName('xMOD_csh_corebe')->setFieldName('new_pages');
484  $buttonBar->addButton($cshButton);
485  }
486  // Back
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));
492  $buttonBar->addButton($returnButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 10);
493  }
494 
495  if (is_array($this->pageinfo) && $this->pageinfo['uid']) {
496  // View
497  $pagesTSconfig = ‪BackendUtility::getPagesTSconfig($this->pageinfo['uid']);
498  if (isset($pagesTSconfig['TCEMAIN.']['preview.']['disableButtonForDokType'])) {
499  $excludeDokTypes = GeneralUtility::intExplode(
500  ',',
501  $pagesTSconfig['TCEMAIN.']['preview.']['disableButtonForDokType'],
502  true
503  );
504  } else {
505  // exclude sysfolders and recycler by default
506  $excludeDokTypes = [
510  ];
511  }
512  if (!in_array((int)$this->pageinfo['doktype'], $excludeDokTypes, true)) {
513  $viewButton = $buttonBar->makeLinkButton()
514  ->setHref('#')
515  ->setOnClick(‪BackendUtility::viewOnClick(
516  $this->pageinfo['uid'],
517  '',
518  ‪BackendUtility::BEgetRootLine($this->pageinfo['uid'])
519  ))
520  ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
521  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
522  'actions-view-page',
524  ));
525  $buttonBar->addButton($viewButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 30);
526  }
527  }
528  }
529 
535  protected function ‪renderPositionTree(): ?ResponseInterface
536  {
537  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
538  ->getQueryBuilderForTable('pages');
539  $queryBuilder->getRestrictions()
540  ->removeAll()
541  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
542  $numberOfPages = $queryBuilder
543  ->count('*')
544  ->from('pages')
545  ->execute()
546  ->fetchColumn(0);
547 
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(
553  $this->id,
554  $this->pageinfo,
555  $this->perms_clause,
556  $this->returnUrl
557  );
558  } else {
560  $uriBuilder = GeneralUtility::makeInstance(\‪TYPO3\CMS\Backend\Routing\UriBuilder::class);
561  // No pages yet, no need to prompt for position, redirect to page creation.
562  $urlParameters = [
563  'edit' => [
564  'pages' => [
565  0 => 'new'
566  ]
567  ],
568  'returnNewPageId' => 1,
569  'returnUrl' => (string)$uriBuilder->buildUriFromRoute('db_new', ['id' => $this->id, 'pagesOnly' => '1'])
570  ];
571  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
572  @ob_end_clean();
573 
574  return new ‪RedirectResponse($url);
575  }
576 
577  return null;
578  }
579 
585  protected function ‪renderNewRecordControls(ServerRequestInterface $request): void
586  {
587  $lang = $this->‪getLanguageService();
588  // Initialize array for accumulating table rows:
589  $this->tRows = [];
590  // Get TSconfig for current page
591  $pageTS = ‪BackendUtility::getPagesTSconfig($this->id);
592  // Finish initializing new pages options with TSconfig
593  // Each new page option may be hidden by TSconfig
594  // Enabled option for the position of a new page
595  $this->newPagesSelectPosition = !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageSelectPosition']);
596  // Pseudo-boolean (0/1) for backward compatibility
597  $displayNewPagesIntoLink = $this->newPagesInto && !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageInside']);
598  $displayNewPagesAfterLink = $this->newPagesAfter && !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageAfter']);
599  // Slight spacer from header:
600  $this->code .= '';
601  // New Page
602  $table = 'pages';
603  $v = ‪$GLOBALS['TCA'][$table];
604  $pageIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord(
605  $table,
606  [],
608  )->render();
609  $newPageIcon = $this->moduleTemplate->getIconFactory()->getIcon('actions-page-new', ‪Icon::SIZE_SMALL)->render();
610  $rowContent = '';
611  // New pages INSIDE this pages
612  $newPageLinks = [];
613  if ($displayNewPagesIntoLink
614  && $this->‪isTableAllowedOnPage('pages', $this->pageinfo)
615  && $this->‪getBackendUserAuthentication()->check('tables_modify', 'pages')
616  && $this->‪getBackendUserAuthentication()->workspaceCreateNewRecord(($this->pageinfo['_ORIG_uid'] ?: $this->id), 'pages')
617  ) {
618  // Create link to new page inside:
619  $recordIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord($table, [], ‪Icon::SIZE_SMALL)->render();
620  $newPageLinks[] = $this->‪renderLink(
621  $recordIcon . htmlspecialchars($lang->sL($v['ctrl']['title'])) . ' (' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.inside')) . ')',
622  $table,
623  $this->id
624  );
625  }
626  // New pages AFTER this pages
627  if ($displayNewPagesAfterLink
628  && $this->‪isTableAllowedOnPage('pages', $this->pidInfo)
629  && $this->‪getBackendUserAuthentication()->check('tables_modify', 'pages')
630  && $this->‪getBackendUserAuthentication()->workspaceCreateNewRecord($this->pidInfo['uid'], 'pages')
631  ) {
632  $newPageLinks[] = $this->‪renderLink(
633  $pageIcon . htmlspecialchars($lang->sL($v['ctrl']['title'])) . ' (' . htmlspecialchars($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.after')) . ')',
634  'pages',
635  -$this->id
636  );
637  }
638  // New pages at selection position
639  if ($this->newPagesSelectPosition && $this->‪isRecordCreationAllowedForTable('pages')) {
640  // Link to page-wizard:
641  $newPageLinks[] = '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(['pagesOnly' => 1])) . '">' . $pageIcon . htmlspecialchars($lang->getLL('pageSelectPosition')) . '</a>';
642  }
643  // Assemble all new page links
644  $numPageLinks = count($newPageLinks);
645  for ($i = 0; $i < $numPageLinks; $i++) {
646  $rowContent .= '<li>' . $newPageLinks[$i] . '</li>';
647  }
648  if ($this->‪isRecordCreationAllowedForTable('pages')) {
649  $rowContent = '<ul class="list-tree"><li>' . $newPageIcon . '<strong>' .
650  $lang->getLL('createNewPage') . '</strong><ul>' . $rowContent . '</ul></li>';
651  } else {
652  $rowContent = '<ul class="list-tree"><li><ul>' . $rowContent . '</li></ul>';
653  }
655  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
656  // Compile table row
657  $startRows = [$rowContent];
658  $iconFile = [];
659  // New tables (but not pages) INSIDE this pages
660  $isAdmin = $this->‪getBackendUserAuthentication()->‪isAdmin();
661  $newContentIcon = $this->moduleTemplate->getIconFactory()->getIcon('actions-document-new', ‪Icon::SIZE_SMALL)->render();
662  if ($this->newContentInto) {
663  if (is_array(‪$GLOBALS['TCA'])) {
664  $groupName = '';
665  foreach (‪$GLOBALS['TCA'] as $table => $v) {
666  $rootLevelConfiguration = isset($v['ctrl']['rootLevel']) ? (int)$v['ctrl']['rootLevel'] : 0;
667  if ($table !== 'pages'
668  && $this->‪isRecordCreationAllowedForTable($table)
669  && $this->‪isTableAllowedOnPage($table, $this->pageinfo)
670  && $this->‪getBackendUserAuthentication()->‪check('tables_modify', $table)
671  && ($rootLevelConfiguration === -1 || ($this->id xor $rootLevelConfiguration))
672  && $this->‪getBackendUserAuthentication()->‪workspaceCreateNewRecord(($this->pageinfo['_ORIG_uid'] ? $this->pageinfo['_ORIG_uid'] : $this->id), $table)
673  ) {
674  $newRecordIcon = $this->moduleTemplate->getIconFactory()->getIconForRecord($table, [], ‪Icon::SIZE_SMALL)->render();
675  $rowContent = '';
676  $thisTitle = '';
677  // Create new link for record:
678  $newLink = $this->‪renderLink(
679  $newRecordIcon . htmlspecialchars($lang->sL($v['ctrl']['title'])),
680  $table,
681  $this->id
682  );
683  // If the table is 'tt_content', add link to wizard
684  if ($table === 'tt_content') {
685  $groupName = $lang->getLL('createNewContent');
686  $rowContent = $newContentIcon
687  . '<strong>' . $lang->getLL('createNewContent') . '</strong>'
688  . '<ul>';
689  // If mod.newContentElementWizard.override is set, use that extension's wizard instead:
690  $moduleName = ‪BackendUtility::getPagesTSconfig($this->id)['mod.']['newContentElementWizard.']['override']
691  ?? 'new_content_element_wizard';
693  $normalizedParams = $request->getAttribute('normalizedParams');
694  $url = (string)$uriBuilder->buildUriFromRoute($moduleName, ['id' => $this->id, 'returnUrl' => $normalizedParams->getRequestUri()]);
695  $rowContent .= '<li>' . $newLink . ' ' . ‪BackendUtility::wrapInHelp($table, '') . '</li>'
696  . '<li>'
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'))
699  . '</a>'
700  . '</li>'
701  . '</ul>';
702  } else {
703  // Get the title
704  if ($v['ctrl']['readOnly'] || $v['ctrl']['hideTable'] || $v['ctrl']['is_static']) {
705  continue;
706  }
707  if ($v['ctrl']['adminOnly'] && !$isAdmin) {
708  continue;
709  }
710  $nameParts = explode('_', $table);
711  $thisTitle = '';
712  $_EXTKEY = '';
713  if ($nameParts[0] === 'tx' || $nameParts[0] === 'tt') {
714  // Try to extract extension name
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 !== '') {
720  // First try to get localisation of extension title
721  $temp = explode(':', substr($title, 9 + strlen($_EXTKEY)));
722  $langFile = $temp[0];
723  $thisTitle = $lang->sL('LLL:EXT:' . $_EXTKEY . '/' . $langFile . ':extension.title');
724  // If no localisation available, read title from ext_emconf.php
725  $extPath = ‪ExtensionManagementUtility::extPath($_EXTKEY);
726  $extEmConfFile = $extPath . 'ext_emconf.php';
727  if (!$thisTitle && is_file($extEmConfFile)) {
728  ‪$EM_CONF = [];
729  include $extEmConfFile;
730  $thisTitle = ‪$EM_CONF[$_EXTKEY]['title'];
731  }
732  $iconFile[$_EXTKEY] = '<img src="' . ‪PathUtility::getAbsoluteWebPath(‪ExtensionManagementUtility::getExtensionIcon($extPath, true)) . '" ' . 'width="16" height="16" ' . 'alt="' . $thisTitle . '" />';
733  }
734  }
735  if (empty($thisTitle)) {
736  $_EXTKEY = $nameParts[1];
737  $thisTitle = $nameParts[1];
738  $iconFile[$_EXTKEY] = '';
739  }
740  } else {
741  $_EXTKEY = 'system';
742  $thisTitle = $lang->getLL('system_records');
743  $iconFile['system'] = $this->moduleTemplate->getIconFactory()->getIcon('apps-pagetree-root', ‪Icon::SIZE_SMALL)->render();
744  }
745 
746  if ($groupName === '' || $groupName !== $_EXTKEY) {
747  $groupName = empty($v['ctrl']['groupName']) ? $_EXTKEY : $v['ctrl']['groupName'];
748  }
749  $rowContent .= $newLink;
750  }
751  // Compile table row:
752  if ($table === 'tt_content') {
753  $startRows[] = '<li>' . $rowContent . '</li>';
754  } else {
755  $this->tRows[$groupName]['title'] = $thisTitle;
756  $this->tRows[$groupName]['html'][] = $rowContent;
757  $this->tRows[$groupName]['table'][] = $table;
758  }
759  }
760  }
761  }
762  }
763  // User sort
764  if (isset($pageTS['mod.']['wizards.']['newRecord.']['order'])) {
765  $this->newRecordSortList = GeneralUtility::trimExplode(',', $pageTS['mod.']['wizards.']['newRecord.']['order'], true);
766  }
767  uksort($this->tRows, [$this, 'sortTableRows']);
768  // Compile table row:
769  $finalRows = [];
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) {
774  $row .= '<li>' . $record . ' ' . ‪BackendUtility::wrapInHelp($value['table'][$recordKey], '') . '</li>';
775  }
776  $row .= '</ul></li>';
777  $finalRows[] = $row;
778  }
779 
780  $finalRows[] = '</ul>';
781  // Make table:
782  $this->code .= implode('', $finalRows);
783  }
784 
792  protected function ‪sortTableRows(string $a, string $b): int
793  {
794  if (!empty($this->newRecordSortList)) {
795  if (in_array($a, $this->newRecordSortList) && in_array($b, $this->newRecordSortList)) {
796  // Both are in the list, return relative to position in array
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)) {
800  // First element is in array, put to top
801  $ret = -1;
802  } elseif (in_array($b, $this->newRecordSortList)) {
803  // Second element is in array, put first to bottom
804  $ret = 1;
805  } else {
806  // No element is in array, return alphabetic order
807  $ret = strnatcasecmp($this->tRows[$a]['title'], $this->tRows[$b]['title']);
808  }
809  return $ret;
810  }
811  // Return alphabetic order
812  return strnatcasecmp($this->tRows[$a]['title'], $this->tRows[$b]['title']);
813  }
814 
824  protected function ‪renderLink(string $linkText, string $table, int $pid, bool $addContentTable = false): string
825  {
826  $urlParameters = [
827  'edit' => [
828  $table => [
829  $pid => 'new'
830  ]
831  ],
832  'returnUrl' => ‪$this->returnUrl
833  ];
834 
835  if ($table === 'pages' && $addContentTable) {
836  $urlParameters['tt_content']['prev'] = 'new';
837  $urlParameters['returnNewPageId'] = 1;
838  }
839 
840  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
841  $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
842 
843  return '<a href="' . htmlspecialchars($url) . '">' . $linkText . '</a>';
844  }
845 
853  protected function ‪isTableAllowedOnPage(string $table, array $page): bool
854  {
855  if (empty($page)) {
856  return $this->‪getBackendUserAuthentication()->‪isAdmin();
857  }
858  // be_users and be_groups may not be created anywhere but in the root.
859  if ($table === 'be_users' || $table === 'be_groups') {
860  return false;
861  }
862  // Checking doktype:
863  $doktype = (int)$page['doktype'];
864  if (!($allowedTableList = ‪$GLOBALS['PAGES_TYPES'][$doktype]['allowedTables'])) {
865  $allowedTableList = ‪$GLOBALS['PAGES_TYPES']['default']['allowedTables'];
866  }
867  // If all tables or the table is listed as an allowed type, return TRUE
868  if (strstr($allowedTableList, '*') || GeneralUtility::inList($allowedTableList, $table)) {
869  return true;
870  }
871 
872  return false;
873  }
874 
891  protected function ‪isRecordCreationAllowedForTable(string $table, array ‪$allowedNewTables = [], array ‪$deniedNewTables = []): bool
892  {
893  if (!$this->‪getBackendUserAuthentication()->check('tables_modify', $table)) {
894  return false;
895  }
896 
899  // No deny/allow tables are set:
900  if (empty(‪$allowedNewTables) && empty(‪$deniedNewTables)) {
901  return true;
902  }
903 
904  return !in_array($table, ‪$deniedNewTables) && (empty(‪$allowedNewTables) || in_array($table, ‪$allowedNewTables));
905  }
906 
912  protected function ‪checkIfLanguagesExist(): bool
913  {
914  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
915  ->getQueryBuilderForTable('sys_language');
916  $queryBuilder->getRestrictions()->removeAll();
917 
918  $count = $queryBuilder
919  ->count('uid')
920  ->from('sys_language')
921  ->execute()
922  ->fetchColumn(0);
923  return (bool)$count;
924  }
925 
929  protected function ‪getLanguageService(): ‪LanguageService
930  {
931  return ‪$GLOBALS['LANG'];
932  }
933 
938  {
939  return ‪$GLOBALS['BE_USER'];
940  }
941 }
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:29
‪TYPO3\CMS\Backend\Controller\NewRecordController\$id
‪int $id
Definition: NewRecordController.php:138
‪TYPO3\CMS\Core\Localization\LanguageService\includeLLFile
‪mixed includeLLFile($fileRef, $setGlobal=true, $mergeLocalOntoDefault=false)
Definition: LanguageService.php:260
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:35
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCreateNewRecord
‪bool workspaceCreateNewRecord($pid, $table)
Definition: BackendUserAuthentication.php:1062
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:31
‪TYPO3\CMS\Backend\Controller\NewRecordController\showNewRecLink
‪bool showNewRecLink($table, array $allowedNewTables=[], array $deniedNewTables=[])
Definition: NewRecordController.php:300
‪TYPO3\CMS\Backend\Controller\NewRecordController\renderNewRecordControls
‪renderNewRecordControls(ServerRequestInterface $request)
Definition: NewRecordController.php:561
‪TYPO3\CMS\Backend\Controller\NewRecordController\pagesOnly
‪pagesOnly()
Definition: NewRecordController.php:224
‪TYPO3\CMS\Backend\Controller\NewRecordController\$deniedNewTables_pid
‪array $deniedNewTables_pid
Definition: NewRecordController.php:123
‪TYPO3\CMS\Backend\Controller\NewRecordController\$web_list_modTSconfig_pid
‪array $web_list_modTSconfig_pid
Definition: NewRecordController.php:115
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:25
‪TYPO3\CMS\Backend\Controller\NewRecordController\isTableAllowedForThisPage
‪bool isTableAllowedForThisPage($pid_row, $checkTable)
Definition: NewRecordController.php:279
‪TYPO3\CMS\Backend\Controller\NewRecordController\linkWrap
‪string linkWrap($linkText, $table, $pid, $addContentTable=false)
Definition: NewRecordController.php:265
‪TYPO3\CMS\Backend\Controller\NewRecordController\getLanguageService
‪LanguageService getLanguageService()
Definition: NewRecordController.php:905
‪TYPO3
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isAdmin
‪bool isAdmin()
Definition: BackendUserAuthentication.php:294
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:173
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:648
‪TYPO3\CMS\Backend\Controller\NewRecordController\$newContentInto
‪int $newContentInto
Definition: NewRecordController.php:89
‪TYPO3\CMS\Backend\Utility\BackendUtility\cshItem
‪static string cshItem($table, $field, $_='', $wrap='')
Definition: BackendUtility.php:2565
‪TYPO3\CMS\Backend\Controller\NewRecordController\renderPositionTree
‪ResponseInterface null renderPositionTree()
Definition: NewRecordController.php:511
‪TYPO3\CMS\Backend\Controller\NewRecordController\$code
‪string $code
Definition: NewRecordController.php:127
‪TYPO3\CMS\Backend\Controller\NewRecordController\main
‪main()
Definition: NewRecordController.php:208
‪TYPO3\CMS\Backend\Controller\NewRecordController\checkIfLanguagesExist
‪bool checkIfLanguagesExist()
Definition: NewRecordController.php:888
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:158
‪TYPO3\CMS\Backend\Controller\NewRecordController\isTableAllowedOnPage
‪bool isTableAllowedOnPage(string $table, array $page)
Definition: NewRecordController.php:829
‪TYPO3\CMS\Backend\Controller\NewRecordController\getButtons
‪getButtons()
Definition: NewRecordController.php:438
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:374
‪TYPO3\CMS\Backend\Controller\NewRecordController\$returnUrl
‪string $returnUrl
Definition: NewRecordController.php:142
‪TYPO3\CMS\Backend\Utility\BackendUtility\wrapInHelp
‪static string wrapInHelp($table, $field, $text='', array $overloadHelpText=[])
Definition: BackendUtility.php:2519
‪TYPO3\CMS\Backend\Controller\NewRecordController\renderLink
‪string renderLink(string $linkText, string $table, int $pid, bool $addContentTable=false)
Definition: NewRecordController.php:800
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:40
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Backend\Controller\NewRecordController
Definition: NewRecordController.php:46
‪TYPO3\CMS\Backend\Controller\NewRecordController\$deniedNewTables
‪array $deniedNewTables
Definition: NewRecordController.php:111
‪TYPO3\CMS\Backend\Controller\NewRecordController\$pageinfo
‪array $pageinfo
Definition: NewRecordController.php:73
‪TYPO3\CMS\Backend\Controller\NewRecordController\$web_list_modTSconfig
‪array $web_list_modTSconfig
Definition: NewRecordController.php:103
‪TYPO3\CMS\Backend\Controller\NewRecordController\$moduleTemplate
‪ModuleTemplate $moduleTemplate
Definition: NewRecordController.php:168
‪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\Tree\View\PagePositionMap
Definition: PagePositionMap.php:37
‪TYPO3\CMS\Backend\Tree\View\NewRecordPageTreeView
Definition: NewRecordPageTreeView.php:24
‪TYPO3\CMS\Backend\Controller\NewRecordController\$newPagesSelectPosition
‪bool $newPagesSelectPosition
Definition: NewRecordController.php:99
‪TYPO3\CMS\Backend\Controller\NewRecordController\$newPagesAfter
‪int $newPagesAfter
Definition: NewRecordController.php:93
‪TYPO3\CMS\Backend\Controller\NewRecordController\sortTableRows
‪int sortTableRows(string $a, string $b)
Definition: NewRecordController.php:768
‪TYPO3\CMS\Backend\Controller\NewRecordController\mainAction
‪ResponseInterface mainAction(ServerRequestInterface $request)
Definition: NewRecordController.php:192
‪TYPO3\CMS\Backend\Controller\NewRecordController\$R_URI
‪string $R_URI
Definition: NewRecordController.php:131
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:27
‪TYPO3\CMS\Backend\Controller\NewRecordController\getBackendUserAuthentication
‪BackendUserAuthentication getBackendUserAuthentication()
Definition: NewRecordController.php:913
‪TYPO3\CMS\Backend\Controller\NewRecordController\init
‪init(ServerRequestInterface $request)
Definition: NewRecordController.php:311
‪TYPO3\CMS\Backend\Controller\NewRecordController\$newPagesInto
‪int $newPagesInto
Definition: NewRecordController.php:85
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2616
‪TYPO3\CMS\Backend\Controller\NewRecordController\regularNew
‪regularNew()
Definition: NewRecordController.php:235
‪TYPO3\CMS\Backend\Controller\NewRecordController\__construct
‪__construct()
Definition: NewRecordController.php:173
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
Definition: BackendUtility.php:864
‪TYPO3\CMS\Backend\Controller\NewRecordController\renderContent
‪ResponseInterface null renderContent(ServerRequestInterface $request)
Definition: NewRecordController.php:380
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Backend\Controller\NewRecordController\$newRecordSortList
‪array $newRecordSortList
Definition: NewRecordController.php:81
‪TYPO3\CMS\Backend\Controller\NewRecordController\$pidInfo
‪array $pidInfo
Definition: NewRecordController.php:77
‪TYPO3\CMS\Frontend\Page\PageRepository\DOKTYPE_RECYCLER
‪const DOKTYPE_RECYCLER
Definition: PageRepository.php:175
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:149
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:21
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:66
‪$EM_CONF
‪$EM_CONF[$_EXTKEY]
Definition: ext_emconf.php:2
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtensionIcon
‪static string getExtensionIcon($extensionPath, $returnFullPath=false)
Definition: ExtensionManagementUtility.php:1511
‪TYPO3\CMS\Backend\Controller\NewRecordController\isRecordCreationAllowedForTable
‪bool isRecordCreationAllowedForTable(string $table, array $allowedNewTables=[], array $deniedNewTables=[])
Definition: NewRecordController.php:867
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Backend\Controller\NewRecordController\$content
‪string $content
Definition: NewRecordController.php:158
‪TYPO3\CMS\Core\Utility\PathUtility\getAbsoluteWebPath
‪static string getAbsoluteWebPath($targetPath)
Definition: PathUtility.php:42
‪TYPO3\CMS\Backend\Controller\NewRecordController\$pagesOnly
‪int $pagesOnly
Definition: NewRecordController.php:148
‪TYPO3\CMS\Core\Utility\HttpUtility\redirect
‪static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:103
‪TYPO3\CMS\Backend\Controller\NewRecordController\$deprecatedPublicProperties
‪array $deprecatedPublicProperties
Definition: NewRecordController.php:50
‪TYPO3\CMS\Backend\Controller\NewRecordController\$tRows
‪array $tRows
Definition: NewRecordController.php:162
‪TYPO3\CMS\Backend\Controller
Definition: AbstractFormEngineAjaxController.php:3
‪TYPO3\CMS\Backend\Controller\NewRecordController\sortNewRecordsByConfig
‪int sortNewRecordsByConfig($a, $b)
Definition: NewRecordController.php:249
‪TYPO3\CMS\Backend\Controller\NewRecordController\$allowedNewTables_pid
‪array $allowedNewTables_pid
Definition: NewRecordController.php:119
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:25
‪TYPO3\CMS\Backend\Controller\NewRecordController\$perms_clause
‪string $perms_clause
Definition: NewRecordController.php:152
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array bool readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:635
‪TYPO3\CMS\Backend\Controller\NewRecordController\$allowedNewTables
‪array $allowedNewTables
Definition: NewRecordController.php:107