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