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