[TASK] Move record-related entrypoints to backend routing
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / NewRecordController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Psr\Http\Message\ServerRequestInterface;
18 use Psr\Http\Message\ResponseInterface;
19 use TYPO3\CMS\Core\Http\Response;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Backend\Utility\IconUtility;
22 use TYPO3\CMS\Core\Database\DatabaseConnection;
23 use TYPO3\CMS\Core\Imaging\Icon;
24 use TYPO3\CMS\Core\Imaging\IconFactory;
25 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Backend\Template\DocumentTemplate;
28 use TYPO3\CMS\Backend\Tree\View\PagePositionMap;
29 use TYPO3\CMS\Backend\Tree\View\NewRecordPageTreeView;
30 use TYPO3\CMS\Core\Utility\HttpUtility;
31 use TYPO3\CMS\Frontend\Page\PageRepository;
32
33
34 /**
35 * Script class for 'db_new'
36 */
37 class NewRecordController implements \TYPO3\CMS\Core\Http\ControllerInterface {
38
39 /**
40 * @var array
41 */
42 public $pageinfo;
43
44 /**
45 * @var array
46 */
47 public $pidInfo;
48
49 /**
50 * @var array
51 */
52 protected $newRecordSortList;
53
54 /**
55 * @var int
56 */
57 public $newPagesInto;
58
59 /**
60 * @var int
61 */
62 public $newContentInto;
63
64 /**
65 * @var int
66 */
67 public $newPagesAfter;
68
69 /**
70 * Determines, whether "Select Position" for new page should be shown
71 *
72 * @var bool
73 */
74 protected $newPagesSelectPosition = TRUE;
75
76 /**
77 * @var array
78 */
79 public $web_list_modTSconfig;
80
81 /**
82 * @var array
83 */
84 public $allowedNewTables;
85
86 /**
87 * @var array
88 */
89 public $deniedNewTables;
90
91 /**
92 * @var array
93 */
94 public $web_list_modTSconfig_pid;
95
96 /**
97 * @var array
98 */
99 public $allowedNewTables_pid;
100
101 /**
102 * @var array
103 */
104 public $deniedNewTables_pid;
105
106 /**
107 * @var string
108 */
109 public $code;
110
111 /**
112 * @var string
113 */
114 public $R_URI;
115
116 /**
117 * @var int
118 */
119 public $id;
120
121 /**
122 * @var string
123 */
124 public $returnUrl;
125
126 /**
127 * pagesOnly flag.
128 *
129 * @var int
130 */
131 public $pagesOnly;
132
133 /**
134 * @var string
135 */
136 public $perms_clause;
137
138 /**
139 * Document template object
140 *
141 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
142 */
143 public $doc;
144
145 /**
146 * Accumulated HTML output
147 *
148 * @var string
149 */
150 public $content;
151
152 /**
153 * @var array
154 */
155 public $tRows;
156
157 /**
158 * @var IconFactory
159 */
160 protected $iconFactory;
161
162 /**
163 * Constructor
164 */
165 public function __construct() {
166 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
167 $GLOBALS['SOBE'] = $this;
168 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_misc.xlf');
169 $this->init();
170 }
171
172 /**
173 * Constructor function for the class
174 *
175 * @return void
176 */
177 protected function init() {
178 $beUser = $this->getBackendUserAuthentication();
179 // Page-selection permission clause (reading)
180 $this->perms_clause = $beUser->getPagePermsClause(1);
181 // This will hide records from display - it has nothing to do with user rights!!
182 if ($pidList = $beUser->getTSConfigVal('options.hideRecords.pages')) {
183 if ($pidList = $this->getDatabaseConnection()->cleanIntList($pidList)) {
184 $this->perms_clause .= ' AND pages.uid NOT IN (' . $pidList . ')';
185 }
186 }
187 // Setting GPvars:
188 // The page id to operate from
189 $this->id = (int)GeneralUtility::_GP('id');
190 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
191 $this->pagesOnly = GeneralUtility::_GP('pagesOnly');
192 // Create instance of template class for output
193 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
194 $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/db_new.html');
195 $this->doc->JScode = '';
196 // Setting up the context sensitive menu:
197 $this->doc->getContextMenuCode();
198 // Creating content
199 $this->content = '';
200 $this->content .= $this->doc->header($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.pagetitle'));
201 // Id a positive id is supplied, ask for the page record with permission information contained:
202 if ($this->id > 0) {
203 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
204 }
205 // If a page-record was returned, the user had read-access to the page.
206 if ($this->pageinfo['uid']) {
207 // Get record of parent page
208 $this->pidInfo = BackendUtility::getRecord('pages', $this->pageinfo['pid']);
209 // Checking the permissions for the user with regard to the parent page: Can he create new pages, new content record, new page after?
210 if ($beUser->doesUserHaveAccess($this->pageinfo, 8)) {
211 $this->newPagesInto = 1;
212 }
213 if ($beUser->doesUserHaveAccess($this->pageinfo, 16)) {
214 $this->newContentInto = 1;
215 }
216 if (($beUser->isAdmin() || is_array($this->pidInfo)) && $beUser->doesUserHaveAccess($this->pidInfo, 8)) {
217 $this->newPagesAfter = 1;
218 }
219 } elseif ($beUser->isAdmin()) {
220 // Admins can do it all
221 $this->newPagesInto = 1;
222 $this->newContentInto = 1;
223 $this->newPagesAfter = 0;
224 } else {
225 // People with no permission can do nothing
226 $this->newPagesInto = 0;
227 $this->newContentInto = 0;
228 $this->newPagesAfter = 0;
229 }
230 }
231
232 /**
233 * Injects the request object for the current request or subrequest
234 * As this controller goes only through the main() method, it is rather simple for now
235 *
236 * @param ServerRequestInterface $request
237 * @return ResponseInterface $response
238 */
239 public function processRequest(ServerRequestInterface $request) {
240 $this->main();
241
242 /** @var Response $response */
243 $response = GeneralUtility::makeInstance(Response::class);
244 $response->getBody()->write($this->content);
245 return $response;
246 }
247
248 /**
249 * Main processing, creating the list of new record tables to select from
250 *
251 * @return void
252 */
253 public function main() {
254 // If there was a page - or if the user is admin (admins has access to the root) we proceed:
255 if ($this->pageinfo['uid'] || $this->getBackendUserAuthentication()->isAdmin()) {
256 // Acquiring TSconfig for this module/current page:
257 $this->web_list_modTSconfig = BackendUtility::getModTSconfig($this->pageinfo['uid'], 'mod.web_list');
258 $this->allowedNewTables = GeneralUtility::trimExplode(',', $this->web_list_modTSconfig['properties']['allowedNewTables'], TRUE);
259 $this->deniedNewTables = GeneralUtility::trimExplode(',', $this->web_list_modTSconfig['properties']['deniedNewTables'], TRUE);
260 // Acquiring TSconfig for this module/parent page:
261 $this->web_list_modTSconfig_pid = BackendUtility::getModTSconfig($this->pageinfo['pid'], 'mod.web_list');
262 $this->allowedNewTables_pid = GeneralUtility::trimExplode(',', $this->web_list_modTSconfig_pid['properties']['allowedNewTables'], TRUE);
263 $this->deniedNewTables_pid = GeneralUtility::trimExplode(',', $this->web_list_modTSconfig_pid['properties']['deniedNewTables'], TRUE);
264 // More init:
265 if (!$this->showNewRecLink('pages')) {
266 $this->newPagesInto = 0;
267 }
268 if (!$this->showNewRecLink('pages', $this->allowedNewTables_pid, $this->deniedNewTables_pid)) {
269 $this->newPagesAfter = 0;
270 }
271 // Set header-HTML and return_url
272 if (is_array($this->pageinfo) && $this->pageinfo['uid']) {
273 $iconImgTag = IconUtility::getSpriteIconForRecord('pages', $this->pageinfo, array('title' => htmlspecialchars($this->pageinfo['_thePath'])));
274 $title = strip_tags($this->pageinfo[$GLOBALS['TCA']['pages']['ctrl']['label']]);
275 } else {
276 $iconImgTag = IconUtility::getSpriteIcon('apps-pagetree-root', array('title' => htmlspecialchars($this->pageinfo['_thePath'])));
277 $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
278 }
279 $this->code = '<span class="typo3-moduleHeader">' . $this->doc->wrapClickMenuOnIcon($iconImgTag, 'pages', $this->pageinfo['uid']) . htmlspecialchars(GeneralUtility::fixed_lgd_cs($title, 45)) . '</span><br />';
280 $this->R_URI = $this->returnUrl;
281 // GENERATE the HTML-output depending on mode (pagesOnly is the page wizard)
282 // Regular new element:
283 if (!$this->pagesOnly) {
284 $this->regularNew();
285 } elseif ($this->showNewRecLink('pages')) {
286 // Pages only wizard
287 $this->pagesOnly();
288 }
289 // Add all the content to an output section
290 $this->content .= $this->doc->section('', $this->code);
291 // Setting up the buttons and markers for docheader
292 $docHeaderButtons = $this->getButtons();
293 $markers['CSH'] = $docHeaderButtons['csh'];
294 $markers['CONTENT'] = $this->content;
295 // Build the <body> for the module
296 $this->content = $this->doc->startPage($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.pagetitle'));
297 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
298 $this->content .= $this->doc->endPage();
299 $this->content = $this->doc->insertStylesAndJS($this->content);
300 }
301 }
302
303 /**
304 * Create the panel of buttons for submitting the form or otherwise perform operations.
305 *
306 * @return array All available buttons as an assoc. array
307 */
308 protected function getButtons() {
309 $buttons = array(
310 'csh' => '',
311 'back' => '',
312 'view' => '',
313 'new_page' => ''
314 );
315 // Regular new element:
316 if (!$this->pagesOnly) {
317 // New page
318 if ($this->showNewRecLink('pages')) {
319 $buttons['new_page'] = '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('pagesOnly' => '1'))) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:newPage', TRUE) . '">' . IconUtility::getSpriteIcon('actions-page-new') . '</a>';
320 }
321 // CSH
322 $buttons['csh'] = BackendUtility::cshItem('xMOD_csh_corebe', 'new_regular');
323 } elseif ($this->showNewRecLink('pages')) {
324 // Pages only wizard
325 // CSH
326 $buttons['csh'] = BackendUtility::cshItem('xMOD_csh_corebe', 'new_pages');
327 }
328 // Back
329 if ($this->R_URI) {
330 $buttons['back'] = '<a href="' . htmlspecialchars($this->R_URI) . '" class="typo3-goBack" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.goBack', TRUE) . '">' . IconUtility::getSpriteIcon('actions-view-go-back') . '</a>';
331 }
332 if (is_array($this->pageinfo) && $this->pageinfo['uid']) {
333 // View
334 $pagesTSconfig = BackendUtility::getPagesTSconfig($this->pageinfo['uid']);
335 if (isset($pagesTSconfig['TCEMAIN.']['preview.']['disableButtonForDokType'])) {
336 $excludeDokTypes = GeneralUtility::intExplode(',', $pagesTSconfig['TCEMAIN.']['preview.']['disableButtonForDokType'], TRUE);
337 } else {
338 // exclude sysfolders and recycler by default
339 $excludeDokTypes = array(PageRepository::DOKTYPE_RECYCLER, PageRepository::DOKTYPE_SYSFOLDER, PageRepository::DOKTYPE_SPACER);
340 }
341 if (!in_array((int)$this->pageinfo['doktype'], $excludeDokTypes, TRUE)) {
342 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick($this->pageinfo['uid'], '', BackendUtility::BEgetRootLine($this->pageinfo['uid']))) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', TRUE) . '">' . $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL) . '</a>';
343 }
344 }
345 return $buttons;
346 }
347
348 /**
349 * Creates the position map for pages wizard
350 *
351 * @return void
352 */
353 public function pagesOnly() {
354 $numberOfPages = $this->getDatabaseConnection()->exec_SELECTcountRows('*', 'pages', '1=1' . BackendUtility::deleteClause('pages'));
355 if ($numberOfPages > 0) {
356 $this->code .= '
357 <h3>' . htmlspecialchars($this->getLanguageService()->getLL('selectPosition')) . ':</h3>
358 ';
359 $positionMap = GeneralUtility::makeInstance(PagePositionMap::class, NewRecordPageTreeView::class);
360 /** @var $positionMap \TYPO3\CMS\Backend\Tree\View\PagePositionMap */
361 $this->code .= $positionMap->positionTree($this->id, $this->pageinfo, $this->perms_clause, $this->R_URI);
362 } else {
363 // No pages yet, no need to prompt for position, redirect to page creation.
364 $javascript = stripslashes(BackendUtility::editOnClick('&edit[pages][0]=new&returnNewPageId=1', '', BackendUtility::getModuleUrl('db_new', array('id' => $this->id, 'pagesOnly' => '1'))));
365 $startPos = strpos($javascript, 'href=\'') + 6;
366 $endPos = strpos($javascript, '\';');
367 $url = substr($javascript, $startPos, $endPos - $startPos);
368 @ob_end_clean();
369 HttpUtility::redirect($url);
370 }
371 }
372
373 /**
374 * Create a regular new element (pages and records)
375 *
376 * @return void
377 */
378 public function regularNew() {
379
380 /** @var IconFactory $iconFactory */
381 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
382 $lang = $this->getLanguageService();
383 // Initialize array for accumulating table rows:
384 $this->tRows = array();
385 // Get TSconfig for current page
386 $pageTS = BackendUtility::getPagesTSconfig($this->id);
387 // Finish initializing new pages options with TSconfig
388 // Each new page option may be hidden by TSconfig
389 // Enabled option for the position of a new page
390 $this->newPagesSelectPosition = !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageSelectPosition']);
391 // Pseudo-boolean (0/1) for backward compatibility
392 $displayNewPagesIntoLink = $this->newPagesInto && !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageInside']) ? 1 : 0;
393 $displayNewPagesAfterLink = $this->newPagesAfter && !empty($pageTS['mod.']['wizards.']['newRecord.']['pages.']['show.']['pageAfter']) ? 1 : 0;
394 // Slight spacer from header:
395 $this->code .= '';
396 // New Page
397 $table = 'pages';
398 $v = $GLOBALS['TCA'][$table];
399 $pageIcon = IconUtility::getSpriteIconForRecord($table, array());
400 $newPageIcon = IconUtility::getSpriteIcon('actions-page-new');
401 $rowContent = '';
402 // New pages INSIDE this pages
403 $newPageLinks = array();
404 if ($displayNewPagesIntoLink && $this->isTableAllowedForThisPage($this->pageinfo, 'pages') && $this->getBackendUserAuthentication()->check('tables_modify', 'pages') && $this->getBackendUserAuthentication()->workspaceCreateNewRecord(($this->pageinfo['_ORIG_uid'] ?: $this->id), 'pages')) {
405 // Create link to new page inside:
406 $newPageLinks[] = $this->linkWrap(IconUtility::getSpriteIconForRecord($table, array()) . $lang->sL($v['ctrl']['title'], TRUE) . ' (' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.inside', TRUE) . ')', $table, $this->id);
407 }
408 // New pages AFTER this pages
409 if ($displayNewPagesAfterLink && $this->isTableAllowedForThisPage($this->pidInfo, 'pages') && $this->getBackendUserAuthentication()->check('tables_modify', 'pages') && $this->getBackendUserAuthentication()->workspaceCreateNewRecord($this->pidInfo['uid'], 'pages')) {
410 $newPageLinks[] = $this->linkWrap($pageIcon . $lang->sL($v['ctrl']['title'], TRUE) . ' (' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.after', TRUE) . ')', 'pages', -$this->id);
411 }
412 // New pages at selection position
413 if ($this->newPagesSelectPosition && $this->showNewRecLink('pages')) {
414 // Link to page-wizard:
415 $newPageLinks[] = '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('pagesOnly' => 1))) . '">' . $pageIcon . htmlspecialchars($lang->getLL('pageSelectPosition')) . '</a>';
416 }
417 // Assemble all new page links
418 $numPageLinks = count($newPageLinks);
419 for ($i = 0; $i < $numPageLinks; $i++) {
420 $rowContent .= '<li>' . $newPageLinks[$i] . '</li>';
421 }
422 if ($this->showNewRecLink('pages')) {
423 $rowContent = '<ul class="list-tree"><li>' .$newPageIcon . '<strong>' .
424 $lang->getLL('createNewPage') . '</strong><ul>' . $rowContent . '</ul></li>';
425 } else {
426 $rowContent = '<ul class="list-tree"><li><ul>' . $rowContent . '</li></ul>';
427 }
428 // Compile table row
429 $startRows = array($rowContent);
430 $iconFile = array();
431 // New tables (but not pages) INSIDE this pages
432 $isAdmin = $this->getBackendUserAuthentication()->isAdmin();
433 $newContentIcon = $iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL);
434 if ($this->newContentInto) {
435 if (is_array($GLOBALS['TCA'])) {
436 $groupName = '';
437 foreach ($GLOBALS['TCA'] as $table => $v) {
438 if ($table != 'pages'
439 && $this->showNewRecLink($table)
440 && $this->isTableAllowedForThisPage($this->pageinfo, $table)
441 && $this->getBackendUserAuthentication()->check('tables_modify', $table)
442 && (($v['ctrl']['rootLevel'] xor $this->id) || $v['ctrl']['rootLevel'] == -1)
443 && $this->getBackendUserAuthentication()->workspaceCreateNewRecord(($this->pageinfo['_ORIG_uid'] ? $this->pageinfo['_ORIG_uid'] : $this->id), $table)
444 ) {
445 $newRecordIcon = IconUtility::getSpriteIconForRecord($table, array());
446 $rowContent = '';
447 $thisTitle = '';
448 // Create new link for record:
449 $newLink = $this->linkWrap($newRecordIcon . $lang->sL($v['ctrl']['title'], TRUE), $table, $this->id);
450 // If the table is 'tt_content', create link to wizard
451 if ($table == 'tt_content') {
452 $groupName = $lang->getLL('createNewContent');
453 $rowContent = $newContentIcon . '<strong>' . $lang->getLL('createNewContent') . '</strong><ul>';
454 // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's wizard instead:
455 $overrideExt = $this->web_list_modTSconfig['properties']['newContentWiz.']['overrideWithExtension'];
456 $pathToWizard = ExtensionManagementUtility::isLoaded($overrideExt) ? ExtensionManagementUtility::extRelPath($overrideExt) . 'mod1/db_new_content_el.php?' : BackendUtility::getModuleUrl('new_content_element') . '&';
457 $href = $pathToWizard . 'id=' . $this->id . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'));
458 $rowContent .= '<li>' . $newLink . ' ' . BackendUtility::wrapInHelp($table, '') . '</li><li><a href="' . htmlspecialchars($href) . '">' . $newContentIcon . htmlspecialchars($lang->getLL('clickForWizard')) . '</a></li></ul>';
459 } else {
460 // Get the title
461 if ($v['ctrl']['readOnly'] || $v['ctrl']['hideTable'] || $v['ctrl']['is_static']) {
462 continue;
463 }
464 if ($v['ctrl']['adminOnly'] && !$isAdmin) {
465 continue;
466 }
467 $nameParts = explode('_', $table);
468 $thisTitle = '';
469 $_EXTKEY = '';
470 if ($nameParts[0] == 'tx' || $nameParts[0] == 'tt') {
471 // Try to extract extension name
472 if (substr($v['ctrl']['title'], 0, 8) == 'LLL:EXT:') {
473 $_EXTKEY = substr($v['ctrl']['title'], 8);
474 $_EXTKEY = substr($_EXTKEY, 0, strpos($_EXTKEY, '/'));
475 if ($_EXTKEY != '') {
476 // First try to get localisation of extension title
477 $temp = explode(':', substr($v['ctrl']['title'], 9 + strlen($_EXTKEY)));
478 $langFile = $temp[0];
479 $thisTitle = $lang->sL('LLL:EXT:' . $_EXTKEY . '/' . $langFile . ':extension.title');
480 // If no localisation available, read title from ext_emconf.php
481 $extEmConfFile = ExtensionManagementUtility::extPath($_EXTKEY) . 'ext_emconf.php';
482 if (!$thisTitle && is_file($extEmConfFile)) {
483 $EM_CONF = array();
484 include $extEmConfFile;
485 $thisTitle = $EM_CONF[$_EXTKEY]['title'];
486 }
487 $iconFile[$_EXTKEY] = '<img ' . 'src="' . ExtensionManagementUtility::extRelPath($_EXTKEY) . $GLOBALS['TYPO3_LOADED_EXT'][$_EXTKEY]['ext_icon'] . '" ' . 'width="16" height="16" ' . 'alt="' . $thisTitle . '" />';
488 }
489 }
490 if (empty($thisTitle)) {
491 $_EXTKEY = $nameParts[1];
492 $thisTitle = $nameParts[1];
493 $iconFile[$_EXTKEY] = '';
494 }
495 } else {
496 if ($table === 'pages_language_overlay' && !$this->checkIfLanguagesExist()) {
497 continue;
498 }
499 $_EXTKEY = 'system';
500 $thisTitle = $lang->getLL('system_records');
501 $iconFile['system'] = IconUtility::getSpriteIcon('apps-pagetree-root');
502 }
503 if ($groupName == '' || $groupName != $_EXTKEY) {
504 $groupName = empty($v['ctrl']['groupName']) ? $_EXTKEY : $v['ctrl']['groupName'];
505 }
506 $rowContent .= $newLink;
507 }
508 // Compile table row:
509 if ($table == 'tt_content') {
510 $startRows[] = '<li>' . $rowContent . '</li>';
511 } else {
512 $this->tRows[$groupName]['title'] = $thisTitle;
513 $this->tRows[$groupName]['html'][] = $rowContent;
514 $this->tRows[$groupName]['table'][] = $table;
515 }
516 }
517 }
518 }
519 }
520 // User sort
521 if (isset($pageTS['mod.']['wizards.']['newRecord.']['order'])) {
522 $this->newRecordSortList = GeneralUtility::trimExplode(',', $pageTS['mod.']['wizards.']['newRecord.']['order'], TRUE);
523 }
524 uksort($this->tRows, array($this, 'sortNewRecordsByConfig'));
525 // Compile table row:
526 $finalRows = array();
527 $finalRows[] = implode('', $startRows);
528 foreach ($this->tRows as $key => $value) {
529 $row = '<li>' . $iconFile[$key] . ' <strong>' . $value['title'] . '</strong><ul>';
530 foreach ($value['html'] as $recordKey => $record) {
531 $row .= '<li>' . $record . ' ' . BackendUtility::wrapInHelp($value['table'][$recordKey], '') . '</li>';
532 }
533 $row .= '</ul></li>';
534 $finalRows[] = $row;
535 }
536 // Make table:
537 $this->code .= implode('', $finalRows);
538 }
539
540 /**
541 * User array sort function used by regularNew
542 *
543 * @param string $a First array element for compare
544 * @param string $b First array element for compare
545 * @return int -1 for lower, 0 for equal, 1 for greater
546 */
547 public function sortNewRecordsByConfig($a, $b) {
548 if (!empty($this->newRecordSortList)) {
549 if (in_array($a, $this->newRecordSortList) && in_array($b, $this->newRecordSortList)) {
550 // Both are in the list, return relative to position in array
551 $sub = array_search($a, $this->newRecordSortList) - array_search($b, $this->newRecordSortList);
552 $ret = ($sub < 0 ? -1 : $sub == 0) ? 0 : 1;
553 } elseif (in_array($a, $this->newRecordSortList)) {
554 // First element is in array, put to top
555 $ret = -1;
556 } elseif (in_array($b, $this->newRecordSortList)) {
557 // Second element is in array, put first to bottom
558 $ret = 1;
559 } else {
560 // No element is in array, return alphabetic order
561 $ret = strnatcasecmp($this->tRows[$a]['title'], $this->tRows[$b]['title']);
562 }
563 return $ret;
564 } else {
565 // Return alphabetic order
566 return strnatcasecmp($this->tRows[$a]['title'], $this->tRows[$b]['title']);
567 }
568 }
569
570 /**
571 * Ending page output and echo'ing content to browser.
572 *
573 * @return void
574 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use processRequest() instead
575 */
576 public function printContent() {
577 GeneralUtility::logDeprecatedFunction();
578 echo $this->content;
579 }
580
581 /**
582 * Links the string $code to a create-new form for a record in $table created on page $pid
583 *
584 * @param string $linkText Link text
585 * @param string $table Table name (in which to create new record)
586 * @param int $pid PID value for the "&edit['.$table.']['.$pid.']=new" command (positive/negative)
587 * @param bool $addContentTable If $addContentTable is set, then a new tt_content record is created together with pages
588 * @return string The link.
589 */
590 public function linkWrap($linkText, $table, $pid, $addContentTable = FALSE) {
591 $parameters = '&edit[' . $table . '][' . $pid . ']=new';
592 if ($table == 'pages' && $addContentTable) {
593 $parameters .= '&edit[tt_content][prev]=new&returnNewPageId=1';
594 } elseif ($table == 'pages_language_overlay') {
595 $parameters .= '&overrideVals[pages_language_overlay][doktype]=' . (int)$this->pageinfo['doktype'];
596 }
597 $onClick = BackendUtility::editOnClick($parameters, '', $this->returnUrl);
598 return '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $linkText . '</a>';
599 }
600
601 /**
602 * Returns TRUE if the tablename $checkTable is allowed to be created on the page with record $pid_row
603 *
604 * @param array $pid_row Record for parent page.
605 * @param string $checkTable Table name to check
606 * @return bool Returns TRUE if the tablename $checkTable is allowed to be created on the page with record $pid_row
607 */
608 public function isTableAllowedForThisPage($pid_row, $checkTable) {
609 if (!is_array($pid_row)) {
610 return $this->getBackendUserAuthentication()->isAdmin();
611 }
612 // be_users and be_groups may not be created anywhere but in the root.
613 if ($checkTable == 'be_users' || $checkTable == 'be_groups') {
614 return FALSE;
615 }
616 // Checking doktype:
617 $doktype = (int)$pid_row['doktype'];
618 if (!($allowedTableList = $GLOBALS['PAGES_TYPES'][$doktype]['allowedTables'])) {
619 $allowedTableList = $GLOBALS['PAGES_TYPES']['default']['allowedTables'];
620 }
621 // If all tables or the table is listed as an allowed type, return TRUE
622 if (strstr($allowedTableList, '*') || GeneralUtility::inList($allowedTableList, $checkTable)) {
623 return TRUE;
624 }
625
626 return FALSE;
627 }
628
629 /**
630 * Returns TRUE if:
631 * - $allowedNewTables and $deniedNewTables are empty
632 * - the table is not found in $deniedNewTables and $allowedNewTables is not set or the $table tablename is found in $allowedNewTables
633 *
634 * If $table tablename is found in $allowedNewTables and $deniedNewTables, $deniedNewTables
635 * has priority over $allowedNewTables.
636 *
637 * @param string $table Table name to test if in allowedTables
638 * @param array $allowedNewTables Array of new tables that are allowed.
639 * @param array $deniedNewTables Array of new tables that are not allowed.
640 * @return bool Returns TRUE if a link for creating new records should be displayed for $table
641 */
642 public function showNewRecLink($table, array $allowedNewTables = array(), array $deniedNewTables = array()) {
643
644 if (!$this->getBackendUserAuthentication()->check('tables_modify', $table)) {
645 return FALSE;
646 }
647
648 $allowedNewTables = $allowedNewTables ?: $this->allowedNewTables;
649 $deniedNewTables = $deniedNewTables ?: $this->deniedNewTables;
650 // No deny/allow tables are set:
651 if (empty($allowedNewTables) && empty($deniedNewTables)) {
652 return TRUE;
653 }
654
655 return !in_array($table, $deniedNewTables) && (empty($allowedNewTables) || in_array($table, $allowedNewTables));
656 }
657
658 /**
659 * Checks if sys_language records are present
660 *
661 * @return bool
662 */
663 protected function checkIfLanguagesExist() {
664 $languageCount = $this->getDatabaseConnection()->exec_SELECTcountRows('uid', 'sys_language', '1=1');
665 if ($languageCount) {
666 $languageCount = TRUE;
667 }
668 return $languageCount;
669 }
670
671 /**
672 * Return language service instance
673 *
674 * @return \TYPO3\CMS\Lang\LanguageService
675 */
676 protected function getLanguageService() {
677 return $GLOBALS['LANG'];
678 }
679
680 /**
681 * Returns the global BackendUserAuthentication object.
682 *
683 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
684 */
685 protected function getBackendUserAuthentication() {
686 return $GLOBALS['BE_USER'];
687 }
688
689 /**
690 * Returns the database connection
691 *
692 * @return DatabaseConnection
693 */
694 protected function getDatabaseConnection() {
695 return $GLOBALS['TYPO3_DB'];
696 }
697
698 }