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