[TASK] Fix CGL violations against SuperfluousWhitespace
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / layout / db_new_content_el.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * New content elements wizard
30 * (Part of the 'cms' extension)
31 *
32 * Revised for TYPO3 3.6 November/2003 by Kasper Skårhøj
33 * XHTML compatible.
34 *
35 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
36 */
37
38 unset($MCONF);
39 require('conf.php');
40 require($BACK_PATH.'init.php');
41
42 // Unset MCONF/MLANG since all we wanted was back path etc. for this particular script.
43 unset($MCONF);
44 unset($MLANG);
45
46 // Merging locallang files/arrays:
47 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_misc.xml');
48 $LOCAL_LANG_orig = $LOCAL_LANG;
49 $LANG->includeLLFile('EXT:cms/layout/locallang_db_new_content_el.xml');
50 $LOCAL_LANG = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG_orig, $LOCAL_LANG);
51
52 // Exits if 'cms' extension is not loaded:
53 t3lib_extMgm::isLoaded('cms', 1);
54
55 /**
56 * Local position map class
57 *
58 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
59 * @package TYPO3
60 * @subpackage core
61 */
62 class ext_posMap extends t3lib_positionMap {
63 var $dontPrintPageInsertIcons = 1;
64
65 /**
66 * Wrapping the title of the record - here we just return it.
67 *
68 * @param string $str The title value.
69 * @param array $row The record row.
70 * @return string Wrapped title string.
71 */
72 function wrapRecordTitle($str, $row) {
73 return $str;
74 }
75
76 /**
77 * Create on-click event value.
78 *
79 * @param array $row The record.
80 * @param string $vv Column position value.
81 * @param integer $moveUid Move uid
82 * @param integer $pid PID value.
83 * @param integer $sys_lang System language
84 * @return string
85 */
86 function onClickInsertRecord($row, $vv, $moveUid, $pid, $sys_lang = 0) {
87 $table = 'tt_content';
88
89 $location = $this->backPath.'alt_doc.php?edit[tt_content]['.(is_array($row)?-$row['uid']:$pid).']=new&defVals[tt_content][colPos]='.$vv.'&defVals[tt_content][sys_language_uid]='.$sys_lang.'&returnUrl='.rawurlencode($GLOBALS['SOBE']->R_URI);
90
91 return 'window.location.href=\''.$location.'\'+document.editForm.defValues.value; return false;';
92 }
93 }
94
95 /**
96 * Script Class for the New Content element wizard
97 *
98 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
99 * @package TYPO3
100 * @subpackage core
101 */
102 class SC_db_new_content_el {
103
104 // Internal, static (from GPvars):
105 // Page id
106 var $id;
107 // Sys language
108 var $sys_language = 0;
109 // Return URL.
110 var $R_URI = '';
111 // If set, the content is destined for a specific column.
112 var $colPos;
113 var $uid_pid;
114
115 // Internal, static:
116 // Module TSconfig.
117 var $modTSconfig = array();
118
119 /**
120 * Internal backend template object
121 *
122 * @var mediumDoc
123 */
124 var $doc;
125
126 // Internal, dynamic:
127 // Includes a list of files to include between init() and main() - see init()
128 var $include_once = array();
129 // Used to accumulate the content of the module.
130 var $content;
131 // Access boolean.
132 var $access;
133 // config of the wizard
134 var $config;
135
136 /**
137 * Constructor, initializing internal variables.
138 *
139 * @return void
140 */
141 function init() {
142 // Setting class files to include:
143 if (is_array($GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses'])) {
144 $this->include_once = array_merge($this->include_once, $GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses']);
145 }
146
147 // Setting internal vars:
148 $this->id = intval(t3lib_div::_GP('id'));
149 $this->sys_language = intval(t3lib_div::_GP('sys_language_uid'));
150 $this->R_URI = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('returnUrl'));
151 $this->colPos = t3lib_div::_GP('colPos');
152 $this->uid_pid = intval(t3lib_div::_GP('uid_pid'));
153
154 $this->MCONF['name'] = 'xMOD_db_new_content_el';
155 $this->modTSconfig = t3lib_BEfunc::getModTSconfig($this->id, 'mod.wizards.newContentElement');
156
157 $config = t3lib_BEfunc::getPagesTSconfig($this->id);
158 $this->config = $config['mod.']['wizards.']['newContentElement.'];
159
160 // Starting the document template object:
161 $this->doc = t3lib_div::makeInstance('template');
162 $this->doc->backPath = $GLOBALS['BACK_PATH'];
163 $this->doc->setModuleTemplate('templates/db_new_content_el.html');
164 $this->doc->JScode = '';
165 $this->doc->form = '<form action="" name="editForm"><input type="hidden" name="defValues" value="" />';
166
167 // Setting up the context sensitive menu:
168 $this->doc->getContextMenuCode();
169
170 // Getting the current page and receiving access information (used in main())
171 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
172 $this->pageinfo = t3lib_BEfunc::readPageAccess($this->id, $perms_clause);
173 $this->access = is_array($this->pageinfo) ? 1 : 0;
174 }
175
176 /**
177 * Creating the module output.
178 *
179 * @return void
180 */
181 function main() {
182 if ($this->id && $this->access) {
183
184 // Init position map object:
185 $posMap = t3lib_div::makeInstance('ext_posMap');
186 $posMap->cur_sys_language = $this->sys_language;
187 $posMap->backPath = $GLOBALS['BACK_PATH'];
188
189 // If a column is pre-set:
190 if ((string)$this->colPos != '') {
191 if ($this->uid_pid < 0) {
192 $row = array();
193 $row['uid'] = abs($this->uid_pid);
194 } else {
195 $row = '';
196 }
197 $this->onClickEvent = $posMap->onClickInsertRecord($row, $this->colPos, '', $this->uid_pid, $this->sys_language);
198 } else {
199 $this->onClickEvent = '';
200 }
201
202 // ***************************
203 // Creating content
204 // ***************************
205 // use a wrapper div
206 $this->content .= '<div id="user-setup-wrapper">';
207 $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('newContentElement'));
208 $this->content .= $this->doc->spacer(5);
209
210 // Wizard
211 $code = '';
212 $wizardItems = $this->getWizardItems();
213
214 // Wrapper for wizards
215 $this->elementWrapper['sectionHeader'] = array('<h3 class="divider">', '</h3>');
216 $this->elementWrapper['section'] = array('<table border="0" cellpadding="1" cellspacing="2">', '</table>');
217 $this->elementWrapper['wizard'] = array('<tr>', '</tr>');
218 $this->elementWrapper['wizardPart'] = array('<td>', '</td>');
219 // Copy wrapper for tabs
220 $this->elementWrapperForTabs = $this->elementWrapper;
221
222 // Hook for manipulating wizardItems, wrapper, onClickEvent etc.
223 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'])) {
224 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'] as $classData) {
225 $hookObject = t3lib_div::getUserObj($classData);
226
227 if (!($hookObject instanceof cms_newContentElementWizardsHook)) {
228 throw new UnexpectedValueException('$hookObject must implement interface cms_newContentElementWizardItemsHook', 1227834741);
229 }
230
231 $hookObject->manipulateWizardItems($wizardItems, $this);
232 }
233 }
234
235 if ($this->config['renderMode'] == 'tabs' && $this->elementWrapperForTabs != $this->elementWrapper) {
236 // Restore wrapper for tabs if they are overwritten in hook
237 $this->elementWrapper = $this->elementWrapperForTabs;
238 }
239
240 // Add document inline javascript
241 $this->doc->JScode = $this->doc->wrapScriptTags('
242 function goToalt_doc() { //
243 ' . $this->onClickEvent . '
244 }
245
246 if(top.refreshMenu) {
247 top.refreshMenu();
248 } else {
249 top.TYPO3ModuleMenu.refreshMenu();
250 }
251 ');
252
253 // Traverse items for the wizard.
254 // An item is either a header or an item rendered with a radio button and title/description and icon:
255 $cc = $key = 0;
256 $menuItems = array();
257 foreach ($wizardItems as $k => $wInfo) {
258 if ($wInfo['header']) {
259 $menuItems[] = array(
260 'label' => htmlspecialchars($wInfo['header']),
261 'content' => $this->elementWrapper['section'][0]
262 );
263 $key = count($menuItems) - 1;
264 } else {
265 $content = '';
266 // Radio button:
267 $oC = "document.editForm.defValues.value=unescape('".rawurlencode($wInfo['params'])."');goToalt_doc();".(!$this->onClickEvent?"window.location.hash='#sel2';":'');
268 $content .= $this->elementWrapper['wizardPart'][0] .
269 '<input type="radio" name="tempB" value="' . htmlspecialchars($k) . '" onclick="' . htmlspecialchars($oC) . '" />' .
270 $this->elementWrapper['wizardPart'][1];
271
272 // Onclick action for icon/title:
273 $aOnClick = 'document.getElementsByName(\'tempB\')['.$cc.'].checked=1;'.$oC.'return false;';
274
275 // Icon:
276 $iInfo = @getimagesize($wInfo['icon']);
277 $content .= $this->elementWrapper['wizardPart'][0] .
278 '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">
279 <img' . t3lib_iconWorks::skinImg($this->doc->backPath, $wInfo['icon'], '') . ' alt="" /></a>' .
280 $this->elementWrapper['wizardPart'][1];
281
282 // Title + description:
283 $content .= $this->elementWrapper['wizardPart'][0] .
284 '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '"><strong>' . htmlspecialchars($wInfo['title']) . '</strong><br />' .
285 nl2br(htmlspecialchars(trim($wInfo['description']))) . '</a>' .
286 $this->elementWrapper['wizardPart'][1];
287
288 // Finally, put it together in a container:
289 $menuItems[$key]['content'] .= $this->elementWrapper['wizard'][0] . $content . $this->elementWrapper['wizard'][1];
290 $cc++;
291 }
292 }
293 // Add closing section-tag
294 foreach ($menuItems as $key => $val) {
295 $menuItems[$key]['content'] .= $this->elementWrapper['section'][1];
296 }
297
298 // Add the wizard table to the content, wrapped in tabs:
299 if ($this->config['renderMode'] == 'tabs') {
300 $this->doc->inDocStylesArray[] = '
301 .typo3-dyntabmenu-divs { background-color: #fafafa; border: 1px solid #adadad; width: 680px; }
302 .typo3-dyntabmenu-divs table { margin: 15px; }
303 .typo3-dyntabmenu-divs table td { padding: 3px; }
304 ';
305 $code = $GLOBALS['LANG']->getLL('sel1', 1) . '<br /><br />' . $this->doc->getDynTabMenu($menuItems, 'new-content-element-wizard', FALSE, FALSE);
306 } else {
307 $code = $GLOBALS['LANG']->getLL('sel1', 1) . '<br /><br />';
308 foreach ($menuItems as $section) {
309 $code .= $this->elementWrapper['sectionHeader'][0] . $section['label'] . $this->elementWrapper['sectionHeader'][1] . $section['content'];
310 }
311 }
312
313 $this->content.= $this->doc->section(!$this->onClickEvent ? $GLOBALS['LANG']->getLL('1_selectType') : '', $code, 0, 1);
314
315 // If the user must also select a column:
316 if (!$this->onClickEvent) {
317
318 // Add anchor "sel2"
319 $this->content .= $this->doc->section('', '<a name="sel2"></a>');
320 $this->content .= $this->doc->spacer(20);
321
322 // Select position
323 $code = $GLOBALS['LANG']->getLL('sel2', 1) . '<br /><br />';
324
325 // Load SHARED page-TSconfig settings and retrieve column list from there, if applicable:
326 $modTSconfig_SHARED = t3lib_BEfunc::getModTSconfig($this->id, 'mod.SHARED');
327 $colPosList = strcmp(trim($modTSconfig_SHARED['properties']['colPos_list']), '') ? trim($modTSconfig_SHARED['properties']['colPos_list']) : '1,0,2,3';
328 $colPosList = implode(',', array_unique(t3lib_div::intExplode(',', $colPosList))); // Removing duplicates, if any
329
330 // Finally, add the content of the column selector to the content:
331 $code .= $posMap->printContentElementColumns($this->id, 0, $colPosList, 1, $this->R_URI);
332 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('2_selectPosition'), $code, 0, 1);
333 }
334
335 // Close wrapper div
336 $this->content .= '</div>';
337 } else { // In case of no access:
338 $this->content = '';
339 $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('newContentElement'));
340 $this->content .= $this->doc->spacer(5);
341 }
342
343 // Setting up the buttons and markers for docheader
344 $docHeaderButtons = $this->getButtons();
345 $markers['CSH'] = $docHeaderButtons['csh'];
346 $markers['CONTENT'] = $this->content;
347
348 // Build the <body> for the module
349 $this->content = $this->doc->startPage($GLOBALS['LANG']->getLL('newContentElement'));
350 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
351 $this->content .= $this->doc->sectionEnd();
352 $this->content .= $this->doc->endPage();
353 $this->content = $this->doc->insertStylesAndJS($this->content);
354 }
355
356 /**
357 * Print out the accumulated content:
358 *
359 * @return void
360 */
361 function printContent() {
362 echo $this->content;
363 }
364
365 /**
366 * Create the panel of buttons for submitting the form or otherwise perform operations.
367 *
368 * @return array All available buttons as an assoc. array
369 */
370 protected function getButtons() {
371 $buttons = array(
372 'csh' => '',
373 'back' => ''
374 );
375
376 if ($this->id && $this->access) {
377 // CSH
378 $buttons['csh'] = t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'new_ce', $GLOBALS['BACK_PATH'], '', TRUE);
379
380 // Back
381 if ($this->R_URI) {
382 $buttons['back'] = '<a href="' . htmlspecialchars($this->R_URI) . '" class="typo3-goBack" title="' . $GLOBALS['LANG']->getLL('goBack', TRUE) . '">' .
383 t3lib_iconWorks::getSpriteIcon('actions-view-go-back') .
384 '</a>';
385 }
386 }
387
388 return $buttons;
389 }
390
391 /***************************
392 *
393 * OTHER FUNCTIONS:
394 *
395 ***************************/
396
397 /**
398 * Returns the content of wizardArray() function...
399 *
400 * @return array Returns the content of wizardArray() function...
401 */
402 function getWizardItems() {
403 return $this->wizardArray();
404 }
405
406 /**
407 * Returns the array of elements in the wizard display.
408 * For the plugin section there is support for adding elements there from a global variable.
409 *
410 * @return array
411 */
412 function wizardArray() {
413
414 if (is_array($this->config)) {
415 $wizards = $this->config['wizardItems.'];
416 }
417 $appendWizards = $this->wizard_appendWizards($wizards['elements.']);
418
419 $wizardItems = array();
420
421 if (is_array($wizards)) {
422 foreach ($wizards as $groupKey => $wizardGroup) {
423 $groupKey = preg_replace('/\.$/', '', $groupKey);
424 $showItems = t3lib_div::trimExplode(',', $wizardGroup['show'], TRUE);
425 $showAll = (strcmp($wizardGroup['show'], '*') ? FALSE : TRUE);
426 $groupItems = array();
427
428 if (is_array($appendWizards[$groupKey . '.']['elements.'])) {
429 $wizardElements = array_merge((array) $wizardGroup['elements.'], $appendWizards[$groupKey . '.']['elements.']);
430 } else {
431 $wizardElements = $wizardGroup['elements.'];
432 }
433
434 if (is_array($wizardElements)) {
435 foreach ($wizardElements as $itemKey => $itemConf) {
436 $itemKey = preg_replace('/\.$/', '', $itemKey);
437 if ($showAll || in_array($itemKey, $showItems)) {
438 $tmpItem = $this->wizard_getItem($groupKey, $itemKey, $itemConf);
439 if ($tmpItem) {
440 $groupItems[$groupKey . '_' . $itemKey] = $tmpItem;
441 }
442 }
443 }
444 }
445 if (count($groupItems)) {
446 $wizardItems[$groupKey] = $this->wizard_getGroupHeader($groupKey, $wizardGroup);
447 $wizardItems = array_merge($wizardItems, $groupItems);
448 }
449 }
450 }
451
452 // Remove elements where preset values are not allowed:
453 $this->removeInvalidElements($wizardItems);
454
455 return $wizardItems;
456 }
457
458 /**
459 *
460 * @param mixed $wizardElements
461 * @return array
462 */
463 function wizard_appendWizards($wizardElements) {
464 if (!is_array($wizardElements)) {
465 $wizardElements = array();
466 }
467 if (is_array($GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses'])) {
468 foreach ($GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses'] as $class => $path) {
469 require_once($path);
470 $modObj = t3lib_div::makeInstance($class);
471 $wizardElements = $modObj->proc($wizardElements);
472 }
473 }
474 $returnElements = array();
475 foreach ($wizardElements as $key => $wizardItem) {
476 preg_match('/^[a-zA-Z0-9]+_/', $key, $group);
477 $wizardGroup = $group[0] ? substr($group[0], 0, -1) . '.' : $key;
478 $returnElements[$wizardGroup]['elements.'][substr($key, strlen($wizardGroup)) . '.'] = $wizardItem;
479 }
480 return $returnElements;
481 }
482
483 /**
484 *
485 * @param string Not used
486 * @param string Not used
487 * @param array $itemConf
488 * @return array
489 */
490 function wizard_getItem($groupKey, $itemKey, $itemConf) {
491 $itemConf['title'] = $GLOBALS['LANG']->sL($itemConf['title']);
492 $itemConf['description'] = $GLOBALS['LANG']->sL($itemConf['description']);
493 $itemConf['tt_content_defValues'] = $itemConf['tt_content_defValues.'];
494 unset($itemConf['tt_content_defValues.']);
495 return $itemConf;
496 }
497
498 /**
499 *
500 * @param string Not used
501 * @param array $wizardGroup
502 * @return array
503 */
504 function wizard_getGroupHeader($groupKey, $wizardGroup) {
505 return array(
506 'header' => $GLOBALS['LANG']->sL($wizardGroup['header'])
507 );
508 }
509
510 /**
511 * Checks the array for elements which might contain unallowed default values and will unset them!
512 * Looks for the "tt_content_defValues" key in each element and if found it will traverse that array as fieldname / value pairs and check. The values will be added to the "params" key of the array (which should probably be unset or empty by default).
513 *
514 * @param array $wizardItems Wizard items, passed by reference
515 * @return void
516 */
517 function removeInvalidElements(&$wizardItems) {
518
519 // Load full table definition:
520 t3lib_div::loadTCA('tt_content');
521
522 // Get TCEFORM from TSconfig of current page
523 $row = array('pid' => $this->id);
524 $TCEFORM_TSconfig = t3lib_BEfunc::getTCEFORM_TSconfig('tt_content', $row);
525 $removeItems = t3lib_div::trimExplode(',', $TCEFORM_TSconfig['CType']['removeItems'], 1);
526 $keepItems = t3lib_div::trimExplode(',', $TCEFORM_TSconfig['CType']['keepItems'], 1);
527
528 $headersUsed = Array();
529 // Traverse wizard items:
530 foreach ($wizardItems as $key => $cfg) {
531
532 // Exploding parameter string, if any (old style)
533 if ($wizardItems[$key]['params']) {
534 // Explode GET vars recursively
535 $tempGetVars = t3lib_div::explodeUrl2Array($wizardItems[$key]['params'], TRUE);
536 // If tt_content values are set, merge them into the tt_content_defValues array, unset them from $tempGetVars and re-implode $tempGetVars into the param string (in case remaining parameters are around).
537 if (is_array($tempGetVars['defVals']['tt_content'])) {
538 $wizardItems[$key]['tt_content_defValues'] = array_merge(is_array($wizardItems[$key]['tt_content_defValues']) ? $wizardItems[$key]['tt_content_defValues'] : array(), $tempGetVars['defVals']['tt_content']);
539 unset($tempGetVars['defVals']['tt_content']);
540 $wizardItems[$key]['params'] = t3lib_div::implodeArrayForUrl('', $tempGetVars);
541 }
542 }
543
544 // If tt_content_defValues are defined...:
545 if (is_array($wizardItems[$key]['tt_content_defValues'])) {
546
547 // Traverse field values:
548 foreach ($wizardItems[$key]['tt_content_defValues'] as $fN => $fV) {
549 if (is_array($GLOBALS['TCA']['tt_content']['columns'][$fN])) {
550 // Get information about if the field value is OK:
551 $config = &$GLOBALS['TCA']['tt_content']['columns'][$fN]['config'];
552 $authModeDeny = ($config['type']=='select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode('tt_content', $fN, $fV, $config['authMode']));
553 $isNotInKeepItems = (count($keepItems) && !in_array($fV, $keepItems));
554
555 if ($authModeDeny || ($fN=='CType' && in_array($fV, $removeItems)) || $isNotInKeepItems) {
556 // Remove element all together:
557 unset($wizardItems[$key]);
558 break;
559 } else {
560 // Add the parameter:
561 $wizardItems[$key]['params'].= '&defVals[tt_content]['.$fN.']='.rawurlencode($fV);
562 $tmp = explode('_', $key);
563 $headersUsed[$tmp[0]] = $tmp[0];
564 }
565 }
566 }
567 }
568 }
569 // remove headers without elements
570 foreach ($wizardItems as $key => $cfg) {
571 $tmp = explode('_', $key);
572 if ($tmp[0] && !$tmp[1] && !in_array($tmp[0], $headersUsed)) {
573 unset($wizardItems[$key]);
574 }
575 }
576 }
577 }
578
579 // Make instance:
580 $SOBE = t3lib_div::makeInstance('SC_db_new_content_el');
581 $SOBE->init();
582
583 // Include files?
584 foreach($SOBE->include_once as $INC_FILE) {
585 include_once($INC_FILE);
586 }
587
588 $SOBE->main();
589 $SOBE->printContent();
590
591 ?>