[TASK] CGL violations "AssignmentArithmeticAndComparisonSpace"
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / ContentElement / NewContentElementController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\ContentElement;
3
4 /**
5 * Script Class for the New Content element wizard
6 *
7 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
8 * @package TYPO3
9 * @subpackage core
10 */
11 class NewContentElementController {
12
13 // Internal, static (from GPvars):
14 // Page id
15 /**
16 * @todo Define visibility
17 */
18 public $id;
19
20 // Sys language
21 /**
22 * @todo Define visibility
23 */
24 public $sys_language = 0;
25
26 // Return URL.
27 /**
28 * @todo Define visibility
29 */
30 public $R_URI = '';
31
32 // If set, the content is destined for a specific column.
33 /**
34 * @todo Define visibility
35 */
36 public $colPos;
37
38 /**
39 * @todo Define visibility
40 */
41 public $uid_pid;
42
43 // Internal, static:
44 // Module TSconfig.
45 /**
46 * @todo Define visibility
47 */
48 public $modTSconfig = array();
49
50 /**
51 * Internal backend template object
52 *
53 * @var \TYPO3\CMS\Backend\Template\MediumDocumentTemplate
54 * @todo Define visibility
55 */
56 public $doc;
57
58 // Internal, dynamic:
59 // Includes a list of files to include between init() and main() - see init()
60 /**
61 * @todo Define visibility
62 */
63 public $include_once = array();
64
65 // Used to accumulate the content of the module.
66 /**
67 * @todo Define visibility
68 */
69 public $content;
70
71 // Access boolean.
72 /**
73 * @todo Define visibility
74 */
75 public $access;
76
77 // config of the wizard
78 /**
79 * @todo Define visibility
80 */
81 public $config;
82
83 /**
84 * Constructor, initializing internal variables.
85 *
86 * @return void
87 * @todo Define visibility
88 */
89 public function init() {
90 // Setting class files to include:
91 if (is_array($GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses'])) {
92 $this->include_once = array_merge($this->include_once, $GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses']);
93 }
94 // Setting internal vars:
95 $this->id = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id'));
96 $this->sys_language = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('sys_language_uid'));
97 $this->R_URI = \TYPO3\CMS\Core\Utility\GeneralUtility::sanitizeLocalUrl(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('returnUrl'));
98 $this->colPos = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('colPos');
99 $this->uid_pid = intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('uid_pid'));
100 $this->MCONF['name'] = 'xMOD_db_new_content_el';
101 $this->modTSconfig = \TYPO3\CMS\Backend\Utility\BackendUtility::getModTSconfig($this->id, 'mod.wizards.newContentElement');
102 $config = \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($this->id);
103 $this->config = $config['mod.']['wizards.']['newContentElement.'];
104 // Starting the document template object:
105 $this->doc = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate');
106 $this->doc->backPath = $GLOBALS['BACK_PATH'];
107 $this->doc->setModuleTemplate('templates/db_new_content_el.html');
108 $this->doc->JScode = '';
109 $this->doc->form = '<form action="" name="editForm"><input type="hidden" name="defValues" value="" />';
110 // Setting up the context sensitive menu:
111 $this->doc->getContextMenuCode();
112 // Getting the current page and receiving access information (used in main())
113 $perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
114 $this->pageinfo = \TYPO3\CMS\Backend\Utility\BackendUtility::readPageAccess($this->id, $perms_clause);
115 $this->access = is_array($this->pageinfo) ? 1 : 0;
116 }
117
118 /**
119 * Creating the module output.
120 *
121 * @return void
122 * @todo Define visibility
123 */
124 public function main() {
125 if ($this->id && $this->access) {
126 // Init position map object:
127 $posMap = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('ext_posMap');
128 $posMap->cur_sys_language = $this->sys_language;
129 $posMap->backPath = $GLOBALS['BACK_PATH'];
130 // If a column is pre-set:
131 if ((string) $this->colPos != '') {
132 if ($this->uid_pid < 0) {
133 $row = array();
134 $row['uid'] = abs($this->uid_pid);
135 } else {
136 $row = '';
137 }
138 $this->onClickEvent = $posMap->onClickInsertRecord($row, $this->colPos, '', $this->uid_pid, $this->sys_language);
139 } else {
140 $this->onClickEvent = '';
141 }
142 // ***************************
143 // Creating content
144 // ***************************
145 // use a wrapper div
146 $this->content .= '<div id="user-setup-wrapper">';
147 $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('newContentElement'));
148 $this->content .= $this->doc->spacer(5);
149 // Wizard
150 $code = '';
151 $wizardItems = $this->getWizardItems();
152 // Wrapper for wizards
153 $this->elementWrapper['sectionHeader'] = array('<h3 class="divider">', '</h3>');
154 $this->elementWrapper['section'] = array('<table border="0" cellpadding="1" cellspacing="2">', '</table>');
155 $this->elementWrapper['wizard'] = array('<tr>', '</tr>');
156 $this->elementWrapper['wizardPart'] = array('<td>', '</td>');
157 // Copy wrapper for tabs
158 $this->elementWrapperForTabs = $this->elementWrapper;
159 // Hook for manipulating wizardItems, wrapper, onClickEvent etc.
160 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'])) {
161 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms']['db_new_content_el']['wizardItemsHook'] as $classData) {
162 $hookObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classData);
163 if (!$hookObject instanceof \TYPO3\CMS\Backend\Wizard\NewContentElementWizardHookInterface) {
164 throw new \UnexpectedValueException('$hookObject must implement interface cms_newContentElementWizardItemsHook', 1227834741);
165 }
166 $hookObject->manipulateWizardItems($wizardItems, $this);
167 }
168 }
169 if ($this->config['renderMode'] == 'tabs' && $this->elementWrapperForTabs != $this->elementWrapper) {
170 // Restore wrapper for tabs if they are overwritten in hook
171 $this->elementWrapper = $this->elementWrapperForTabs;
172 }
173 // Add document inline javascript
174 $this->doc->JScode = $this->doc->wrapScriptTags('
175 function goToalt_doc() { //
176 ' . $this->onClickEvent . '
177 }
178
179 if(top.refreshMenu) {
180 top.refreshMenu();
181 } else {
182 top.TYPO3ModuleMenu.refreshMenu();
183 }
184 ');
185 // Traverse items for the wizard.
186 // An item is either a header or an item rendered with a radio button and title/description and icon:
187 $cc = ($key = 0);
188 $menuItems = array();
189 foreach ($wizardItems as $k => $wInfo) {
190 if ($wInfo['header']) {
191 $menuItems[] = array(
192 'label' => htmlspecialchars($wInfo['header']),
193 'content' => $this->elementWrapper['section'][0]
194 );
195 $key = count($menuItems) - 1;
196 } else {
197 $content = '';
198 // Radio button:
199 $oC = 'document.editForm.defValues.value=unescape(\'' . rawurlencode($wInfo['params']) . '\');goToalt_doc();' . (!$this->onClickEvent ? 'window.location.hash=\'#sel2\';' : '');
200 $content .= $this->elementWrapper['wizardPart'][0] . '<input type="radio" name="tempB" value="' . htmlspecialchars($k) . '" onclick="' . htmlspecialchars($oC) . '" />' . $this->elementWrapper['wizardPart'][1];
201 // Onclick action for icon/title:
202 $aOnClick = 'document.getElementsByName(\'tempB\')[' . $cc . '].checked=1;' . $oC . 'return false;';
203 // Icon:
204 $iInfo = @getimagesize($wInfo['icon']);
205 $content .= $this->elementWrapper['wizardPart'][0] . '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">
206 <img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($this->doc->backPath, $wInfo['icon'], '') . ' alt="" /></a>' . $this->elementWrapper['wizardPart'][1];
207 // Title + description:
208 $content .= $this->elementWrapper['wizardPart'][0] . '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '"><strong>' . htmlspecialchars($wInfo['title']) . '</strong><br />' . nl2br(htmlspecialchars(trim($wInfo['description']))) . '</a>' . $this->elementWrapper['wizardPart'][1];
209 // Finally, put it together in a container:
210 $menuItems[$key]['content'] .= $this->elementWrapper['wizard'][0] . $content . $this->elementWrapper['wizard'][1];
211 $cc++;
212 }
213 }
214 // Add closing section-tag
215 foreach ($menuItems as $key => $val) {
216 $menuItems[$key]['content'] .= $this->elementWrapper['section'][1];
217 }
218 // Add the wizard table to the content, wrapped in tabs:
219 if ($this->config['renderMode'] == 'tabs') {
220 $this->doc->inDocStylesArray[] = '
221 .typo3-dyntabmenu-divs { background-color: #fafafa; border: 1px solid #adadad; width: 680px; }
222 .typo3-dyntabmenu-divs table { margin: 15px; }
223 .typo3-dyntabmenu-divs table td { padding: 3px; }
224 ';
225 $code = $GLOBALS['LANG']->getLL('sel1', 1) . '<br /><br />' . $this->doc->getDynTabMenu($menuItems, 'new-content-element-wizard', FALSE, FALSE);
226 } else {
227 $code = $GLOBALS['LANG']->getLL('sel1', 1) . '<br /><br />';
228 foreach ($menuItems as $section) {
229 $code .= $this->elementWrapper['sectionHeader'][0] . $section['label'] . $this->elementWrapper['sectionHeader'][1] . $section['content'];
230 }
231 }
232 $this->content .= $this->doc->section(!$this->onClickEvent ? $GLOBALS['LANG']->getLL('1_selectType') : '', $code, 0, 1);
233 // If the user must also select a column:
234 if (!$this->onClickEvent) {
235 // Add anchor "sel2"
236 $this->content .= $this->doc->section('', '<a name="sel2"></a>');
237 $this->content .= $this->doc->spacer(20);
238 // Select position
239 $code = $GLOBALS['LANG']->getLL('sel2', 1) . '<br /><br />';
240 // Load SHARED page-TSconfig settings and retrieve column list from there, if applicable:
241 $modTSconfig_SHARED = \TYPO3\CMS\Backend\Utility\BackendUtility::getModTSconfig($this->id, 'mod.SHARED');
242 $colPosList = strcmp(trim($modTSconfig_SHARED['properties']['colPos_list']), '') ? trim($modTSconfig_SHARED['properties']['colPos_list']) : '1,0,2,3';
243 $colPosList = implode(',', array_unique(\TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $colPosList)));
244 // Removing duplicates, if any
245 // Finally, add the content of the column selector to the content:
246 $code .= $posMap->printContentElementColumns($this->id, 0, $colPosList, 1, $this->R_URI);
247 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('2_selectPosition'), $code, 0, 1);
248 }
249 // Close wrapper div
250 $this->content .= '</div>';
251 } else {
252 // In case of no access:
253 $this->content = '';
254 $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('newContentElement'));
255 $this->content .= $this->doc->spacer(5);
256 }
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']->getLL('newContentElement'));
263 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
264 $this->content .= $this->doc->sectionEnd();
265 $this->content .= $this->doc->endPage();
266 $this->content = $this->doc->insertStylesAndJS($this->content);
267 }
268
269 /**
270 * Print out the accumulated content:
271 *
272 * @return void
273 * @todo Define visibility
274 */
275 public function printContent() {
276 echo $this->content;
277 }
278
279 /**
280 * Create the panel of buttons for submitting the form or otherwise perform operations.
281 *
282 * @return array All available buttons as an assoc. array
283 */
284 protected function getButtons() {
285 $buttons = array(
286 'csh' => '',
287 'back' => ''
288 );
289 if ($this->id && $this->access) {
290 // CSH
291 $buttons['csh'] = \TYPO3\CMS\Backend\Utility\BackendUtility::cshItem('xMOD_csh_corebe', 'new_ce', $GLOBALS['BACK_PATH'], '', TRUE);
292 // Back
293 if ($this->R_URI) {
294 $buttons['back'] = '<a href="' . htmlspecialchars($this->R_URI) . '" class="typo3-goBack" title="' . $GLOBALS['LANG']->getLL('goBack', TRUE) . '">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-view-go-back') . '</a>';
295 }
296 }
297 return $buttons;
298 }
299
300 /***************************
301 *
302 * OTHER FUNCTIONS:
303 *
304 ***************************/
305 /**
306 * Returns the content of wizardArray() function...
307 *
308 * @return array Returns the content of wizardArray() function...
309 * @todo Define visibility
310 */
311 public function getWizardItems() {
312 return $this->wizardArray();
313 }
314
315 /**
316 * Returns the array of elements in the wizard display.
317 * For the plugin section there is support for adding elements there from a global variable.
318 *
319 * @return array
320 * @todo Define visibility
321 */
322 public function wizardArray() {
323 if (is_array($this->config)) {
324 $wizards = $this->config['wizardItems.'];
325 }
326 $appendWizards = $this->wizard_appendWizards($wizards['elements.']);
327 $wizardItems = array();
328 if (is_array($wizards)) {
329 foreach ($wizards as $groupKey => $wizardGroup) {
330 $groupKey = preg_replace('/\\.$/', '', $groupKey);
331 $showItems = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $wizardGroup['show'], TRUE);
332 $showAll = strcmp($wizardGroup['show'], '*') ? FALSE : TRUE;
333 $groupItems = array();
334 if (is_array($appendWizards[$groupKey . '.']['elements.'])) {
335 $wizardElements = array_merge((array) $wizardGroup['elements.'], $appendWizards[$groupKey . '.']['elements.']);
336 } else {
337 $wizardElements = $wizardGroup['elements.'];
338 }
339 if (is_array($wizardElements)) {
340 foreach ($wizardElements as $itemKey => $itemConf) {
341 $itemKey = preg_replace('/\\.$/', '', $itemKey);
342 if ($showAll || in_array($itemKey, $showItems)) {
343 $tmpItem = $this->wizard_getItem($groupKey, $itemKey, $itemConf);
344 if ($tmpItem) {
345 $groupItems[$groupKey . '_' . $itemKey] = $tmpItem;
346 }
347 }
348 }
349 }
350 if (count($groupItems)) {
351 $wizardItems[$groupKey] = $this->wizard_getGroupHeader($groupKey, $wizardGroup);
352 $wizardItems = array_merge($wizardItems, $groupItems);
353 }
354 }
355 }
356 // Remove elements where preset values are not allowed:
357 $this->removeInvalidElements($wizardItems);
358 return $wizardItems;
359 }
360
361 /**
362 * @param mixed $wizardElements
363 * @return array
364 * @todo Define visibility
365 */
366 public function wizard_appendWizards($wizardElements) {
367 if (!is_array($wizardElements)) {
368 $wizardElements = array();
369 }
370 if (is_array($GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses'])) {
371 foreach ($GLOBALS['TBE_MODULES_EXT']['xMOD_db_new_content_el']['addElClasses'] as $class => $path) {
372 require_once $path;
373 $modObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($class);
374 $wizardElements = $modObj->proc($wizardElements);
375 }
376 }
377 $returnElements = array();
378 foreach ($wizardElements as $key => $wizardItem) {
379 preg_match('/^[a-zA-Z0-9]+_/', $key, $group);
380 $wizardGroup = $group[0] ? substr($group[0], 0, -1) . '.' : $key;
381 $returnElements[$wizardGroup]['elements.'][substr($key, strlen($wizardGroup)) . '.'] = $wizardItem;
382 }
383 return $returnElements;
384 }
385
386 /**
387 * @param string Not used
388 * @param string Not used
389 * @param array $itemConf
390 * @return array
391 * @todo Define visibility
392 */
393 public function wizard_getItem($groupKey, $itemKey, $itemConf) {
394 $itemConf['title'] = $GLOBALS['LANG']->sL($itemConf['title']);
395 $itemConf['description'] = $GLOBALS['LANG']->sL($itemConf['description']);
396 $itemConf['tt_content_defValues'] = $itemConf['tt_content_defValues.'];
397 unset($itemConf['tt_content_defValues.']);
398 return $itemConf;
399 }
400
401 /**
402 * @param string Not used
403 * @param array $wizardGroup
404 * @return array
405 * @todo Define visibility
406 */
407 public function wizard_getGroupHeader($groupKey, $wizardGroup) {
408 return array(
409 'header' => $GLOBALS['LANG']->sL($wizardGroup['header'])
410 );
411 }
412
413 /**
414 * Checks the array for elements which might contain unallowed default values and will unset them!
415 * 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).
416 *
417 * @param array $wizardItems Wizard items, passed by reference
418 * @return void
419 * @todo Define visibility
420 */
421 public function removeInvalidElements(&$wizardItems) {
422 // Load full table definition:
423 \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA('tt_content');
424 // Get TCEFORM from TSconfig of current page
425 $row = array('pid' => $this->id);
426 $TCEFORM_TSconfig = \TYPO3\CMS\Backend\Utility\BackendUtility::getTCEFORM_TSconfig('tt_content', $row);
427 $removeItems = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $TCEFORM_TSconfig['CType']['removeItems'], 1);
428 $keepItems = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $TCEFORM_TSconfig['CType']['keepItems'], 1);
429 $headersUsed = array();
430 // Traverse wizard items:
431 foreach ($wizardItems as $key => $cfg) {
432 // Exploding parameter string, if any (old style)
433 if ($wizardItems[$key]['params']) {
434 // Explode GET vars recursively
435 $tempGetVars = \TYPO3\CMS\Core\Utility\GeneralUtility::explodeUrl2Array($wizardItems[$key]['params'], TRUE);
436 // 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).
437 if (is_array($tempGetVars['defVals']['tt_content'])) {
438 $wizardItems[$key]['tt_content_defValues'] = array_merge(is_array($wizardItems[$key]['tt_content_defValues']) ? $wizardItems[$key]['tt_content_defValues'] : array(), $tempGetVars['defVals']['tt_content']);
439 unset($tempGetVars['defVals']['tt_content']);
440 $wizardItems[$key]['params'] = \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('', $tempGetVars);
441 }
442 }
443 // If tt_content_defValues are defined...:
444 if (is_array($wizardItems[$key]['tt_content_defValues'])) {
445 // Traverse field values:
446 foreach ($wizardItems[$key]['tt_content_defValues'] as $fN => $fV) {
447 if (is_array($GLOBALS['TCA']['tt_content']['columns'][$fN])) {
448 // Get information about if the field value is OK:
449 $config = &$GLOBALS['TCA']['tt_content']['columns'][$fN]['config'];
450 $authModeDeny = $config['type'] == 'select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode('tt_content', $fN, $fV, $config['authMode']);
451 $isNotInKeepItems = count($keepItems) && !in_array($fV, $keepItems);
452 if ($authModeDeny || $fN == 'CType' && in_array($fV, $removeItems) || $isNotInKeepItems) {
453 // Remove element all together:
454 unset($wizardItems[$key]);
455 break;
456 } else {
457 // Add the parameter:
458 $wizardItems[$key]['params'] .= '&defVals[tt_content][' . $fN . ']=' . rawurlencode($fV);
459 $tmp = explode('_', $key);
460 $headersUsed[$tmp[0]] = $tmp[0];
461 }
462 }
463 }
464 }
465 }
466 // remove headers without elements
467 foreach ($wizardItems as $key => $cfg) {
468 $tmp = explode('_', $key);
469 if ($tmp[0] && !$tmp[1] && !in_array($tmp[0], $headersUsed)) {
470 unset($wizardItems[$key]);
471 }
472 }
473 }
474
475 }
476
477
478 ?>