[TASK] Use arrays in str_replace() calls
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / TypoScript / ExtendedTemplateService.php
1 <?php
2 namespace TYPO3\CMS\Core\TypoScript;
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\Core\Utility\GeneralUtility;
32
33 /**
34 * TSParser extension class to TemplateService
35 * Contains functions for the TS module in TYPO3 backend
36 *
37 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
38 */
39 class ExtendedTemplateService extends \TYPO3\CMS\Core\TypoScript\TemplateService {
40
41 // This string is used to indicate the point in a template from where the editable constants are listed. Any vars before this point (if it exists though) is regarded as default values.
42 /**
43 * @todo Define visibility
44 */
45 public $edit_divider = '###MOD_TS:EDITABLE_CONSTANTS###';
46
47 /**
48 * @todo Define visibility
49 */
50 public $HTMLcolorList = 'aqua,beige,black,blue,brown,fuchsia,gold,gray,green,lime,maroon,navy,olive,orange,purple,red,silver,tan,teal,turquoise,yellow,white';
51
52 // internal
53 /**
54 * @todo Define visibility
55 */
56 public $categories = array(
57 'basic' => array(),
58 // Constants of superior importance for the template-layout. This is dimensions, imagefiles and enabling of various features. The most basic constants, which you would almost always want to configure.
59 'menu' => array(),
60 // Menu setup. This includes fontfiles, sizes, background images. Depending on the menutype.
61 'content' => array(),
62 // All constants related to the display of pagecontent elements
63 'page' => array(),
64 // General configuration like metatags, link targets
65 'advanced' => array(),
66 // Advanced functions, which are used very seldomly.
67 'all' => array()
68 );
69
70 // This will be filled with the available categories of the current template.
71 /**
72 * @todo Define visibility
73 */
74 public $subCategories = array(
75 // Standard categories:
76 'enable' => array('Enable features', 'a'),
77 'dims' => array('Dimensions, widths, heights, pixels', 'b'),
78 'file' => array('Files', 'c'),
79 'typo' => array('Typography', 'd'),
80 'color' => array('Colors', 'e'),
81 'links' => array('Links and targets', 'f'),
82 'language' => array('Language specific constants', 'g'),
83 // subcategories based on the default content elements
84 'cheader' => array('Content: \'Header\'', 'ma'),
85 'cheader_g' => array('Content: \'Header\', Graphical', 'ma'),
86 'ctext' => array('Content: \'Text\'', 'mb'),
87 'cimage' => array('Content: \'Image\'', 'md'),
88 'cbullets' => array('Content: \'Bullet list\'', 'me'),
89 'ctable' => array('Content: \'Table\'', 'mf'),
90 'cuploads' => array('Content: \'Filelinks\'', 'mg'),
91 'cmultimedia' => array('Content: \'Multimedia\'', 'mh'),
92 'cmedia' => array('Content: \'Media\'', 'mr'),
93 'cmailform' => array('Content: \'Form\'', 'mi'),
94 'csearch' => array('Content: \'Search\'', 'mj'),
95 'clogin' => array('Content: \'Login\'', 'mk'),
96 'cmenu' => array('Content: \'Menu/Sitemap\'', 'mm'),
97 'cshortcut' => array('Content: \'Insert records\'', 'mn'),
98 'clist' => array('Content: \'List of records\'', 'mo'),
99 'chtml' => array('Content: \'HTML\'', 'mq')
100 );
101
102 /**
103 * @todo Define visibility
104 */
105 public $backend_info = 1;
106
107 // Tsconstanteditor
108 /**
109 * @todo Define visibility
110 */
111 public $ext_inBrace = 0;
112
113 // Tsbrowser
114 /**
115 * @todo Define visibility
116 */
117 public $tsbrowser_searchKeys = array();
118
119 /**
120 * @todo Define visibility
121 */
122 public $tsbrowser_depthKeys = array();
123
124 /**
125 * @todo Define visibility
126 */
127 public $constantMode = '';
128
129 /**
130 * @todo Define visibility
131 */
132 public $regexMode = '';
133
134 /**
135 * @todo Define visibility
136 */
137 public $fixedLgd = '';
138
139 /**
140 * @todo Define visibility
141 */
142 public $resourceCheck = 0;
143
144 /**
145 * @todo Define visibility
146 */
147 public $ext_lineNumberOffset = 0;
148
149 /**
150 * @todo Define visibility
151 */
152 public $ext_localGfxPrefix = '';
153
154 /**
155 * @todo Define visibility
156 */
157 public $ext_localWebGfxPrefix = '';
158
159 /**
160 * @todo Define visibility
161 */
162 public $ext_expandAllNotes = 0;
163
164 /**
165 * @todo Define visibility
166 */
167 public $ext_noPMicons = 0;
168
169 /**
170 * @todo Define visibility
171 */
172 public $ext_noSpecialCharsOnLabels = 0;
173
174 /**
175 * @todo Define visibility
176 */
177 public $ext_listOfTemplatesArr = array();
178
179 /**
180 * @todo Define visibility
181 */
182 public $ext_lineNumberOffset_mode = '';
183
184 // Dont change...
185 /**
186 * @todo Define visibility
187 */
188 public $ext_dontCheckIssetValues = 0;
189
190 /**
191 * @todo Define visibility
192 */
193 public $ext_printAll = 0;
194
195 /**
196 * @todo Define visibility
197 */
198 public $ext_CEformName = 'forms[0]';
199
200 /**
201 * @todo Define visibility
202 */
203 public $doNotSortCategoriesBeforeMakingForm = FALSE;
204
205 // Ts analyzer
206 /**
207 * @todo Define visibility
208 */
209 public $templateTitles = array();
210
211 /**
212 * This flattens a hierarchical setuparray to $this->flatSetup
213 * The original function fetched the resource-file if any ('file.'). This functions doesn't.
214 *
215 * @param [type] $setupArray: ...
216 * @param [type] $prefix: ...
217 * @param [type] $resourceFlag: ...
218 * @return [type] ...
219 * @todo Define visibility
220 */
221 public function flattenSetup($setupArray, $prefix, $resourceFlag) {
222 if (is_array($setupArray)) {
223 // Setting absolute prefixed path for relative resources.
224 $this->getFileName_backPath = PATH_site;
225 foreach ($setupArray as $key => $val) {
226 // We don't want 'TSConstantEditor' in the flattend setup.
227 if ($prefix || substr($key, 0, 16) != 'TSConstantEditor') {
228 if (is_array($val)) {
229 $this->flattenSetup($val, $prefix . $key, $key == 'file.');
230 } elseif ($resourceFlag && $this->resourceCheck) {
231 $this->flatSetup[$prefix . $key] = $this->getFileName($val);
232 if ($this->removeFromGetFilePath && substr($this->flatSetup[$prefix . $key], 0, strlen($this->removeFromGetFilePath)) == $this->removeFromGetFilePath) {
233 $this->flatSetup[$prefix . $key] = substr($this->flatSetup[$prefix . $key], strlen($this->removeFromGetFilePath));
234 }
235 } else {
236 $this->flatSetup[$prefix . $key] = $val;
237 }
238 }
239 }
240 }
241 }
242
243 /**
244 * [Describe function...]
245 *
246 * @param [type] $all: ...
247 * @return [type] ...
248 * @todo Define visibility
249 */
250 public function substituteConstants($all) {
251 $this->Cmarker = substr(md5(uniqid('')), 0, 6);
252 return preg_replace_callback('/\\{\\$(.[^}]+)\\}/', array($this, 'substituteConstantsCallBack'), $all);
253 }
254
255 /**
256 * Call back method for preg_replace_callback in substituteConstants
257 *
258 * @param array $matches Regular expression matches
259 * @return string Replacement
260 * @see substituteConstants()
261 * @todo Define visibility
262 */
263 public function substituteConstantsCallBack($matches) {
264 switch ($this->constantMode) {
265 case 'const':
266 $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . $this->Cmarker . '_B##' . $matches[0] . '##' . $this->Cmarker . '_E##' : $matches[0];
267 break;
268 case 'subst':
269 $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? '##' . $this->Cmarker . '_B##' . $this->flatSetup[$matches[1]] . '##' . $this->Cmarker . '_E##' : $matches[0];
270 break;
271 case 'untouched':
272 $ret_val = $matches[0];
273 break;
274 default:
275 $ret_val = isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? $this->flatSetup[$matches[1]] : $matches[0];
276 }
277 return $ret_val;
278 }
279
280 /**
281 * [Describe function...]
282 *
283 * @param [type] $all: ...
284 * @return [type] ...
285 * @todo Define visibility
286 */
287 public function substituteCMarkers($all) {
288 switch ($this->constantMode) {
289 case 'const':
290 case 'subst':
291 $all = str_replace(
292 array('##' . $this->Cmarker . '_B##', '##' . $this->Cmarker . '_E##'),
293 array('<font color="green"><strong>', '</strong></font>'),
294 $all
295 );
296 break;
297 default:
298 }
299 return $all;
300 }
301
302 /**
303 * Parses the constants in $this->const with respect to the constant-editor in this module.
304 * In particular comments in the code are registered and the edit_divider is taken into account.
305 *
306 * @return [type] ...
307 * @todo Define visibility
308 */
309 public function generateConfig_constants() {
310 // These vars are also set lateron...
311 $this->setup['resources'] = $this->resources;
312 $this->setup['sitetitle'] = $this->sitetitle;
313 // Parse constants
314 $constants = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
315 // Register comments!
316 $constants->regComments = 1;
317 $constants->setup = $this->const;
318 $constants->setup = $this->mergeConstantsFromPageTSconfig($constants->setup);
319 /** @var $matchObj \TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher */
320 $matchObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Configuration\\TypoScript\\ConditionMatching\\ConditionMatcher');
321 // Matches ALL conditions in TypoScript
322 $matchObj->setSimulateMatchResult(TRUE);
323 $c = 0;
324 $cc = count($this->constants);
325 foreach ($this->constants as $str) {
326 $c++;
327 if ($c == $cc) {
328 if (strstr($str, $this->edit_divider)) {
329 $parts = explode($this->edit_divider, $str, 2);
330 $str = $parts[1];
331 $constants->parse($parts[0], $matchObj);
332 }
333 $this->flatSetup = array();
334 $this->flattenSetup($constants->setup, '', '');
335 $defaultConstants = $this->flatSetup;
336 }
337 $constants->parse($str, $matchObj);
338 }
339 $this->flatSetup = array();
340 $this->flattenSetup($constants->setup, '', '');
341 $this->setup['constants'] = $constants->setup;
342 return $this->ext_compareFlatSetups($defaultConstants);
343 }
344
345 /**
346 * [Describe function...]
347 *
348 * @param [type] $theSetup: ...
349 * @param [type] $theKey: ...
350 * @return [type] ...
351 * @todo Define visibility
352 */
353 public function ext_getSetup($theSetup, $theKey) {
354 $parts = explode('.', $theKey, 2);
355 if (strcmp($parts[0], '') && is_array($theSetup[$parts[0] . '.'])) {
356 if (strcmp(trim($parts[1]), '')) {
357 return $this->ext_getSetup($theSetup[$parts[0] . '.'], trim($parts[1]));
358 } else {
359 return array($theSetup[$parts[0] . '.'], $theSetup[$parts[0]]);
360 }
361 } else {
362 if (strcmp(trim($theKey), '')) {
363 return array(array(), $theSetup[$theKey]);
364 } else {
365 return array($theSetup, '');
366 }
367 }
368 }
369
370 /**
371 * [Describe function...]
372 *
373 * @param [type] $arr: ...
374 * @param [type] $depth_in: ...
375 * @param [type] $depthData: ...
376 * @param [type] $parentType: ...
377 * @param [type] $parentValue: ...
378 * @param boolean $alphaSort sorts the array keys / tree by alphabet when set to 1
379 * @return [type] ...
380 * @todo Define visibility
381 */
382 public function ext_getObjTree($arr, $depth_in, $depthData, $parentType = '', $parentValue = '', $alphaSort = '0') {
383 $HTML = '';
384 $a = 0;
385 if ($alphaSort == '1') {
386 ksort($arr);
387 }
388 $keyArr_num = array();
389 $keyArr_alpha = array();
390 foreach ($arr as $key => $value) {
391 // Don't do anything with comments / linenumber registrations...
392 if (substr($key, -2) != '..') {
393 $key = preg_replace('/\\.$/', '', $key);
394 if (substr($key, -1) != '.') {
395 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($key)) {
396 $keyArr_num[$key] = $arr[$key];
397 } else {
398 $keyArr_alpha[$key] = $arr[$key];
399 }
400 }
401 }
402 }
403 ksort($keyArr_num);
404 $keyArr = $keyArr_num + $keyArr_alpha;
405 $c = count($keyArr);
406 if ($depth_in) {
407 $depth_in = $depth_in . '.';
408 }
409 foreach ($keyArr as $key => $value) {
410 $a++;
411 $depth = $depth_in . $key;
412 // This excludes all constants starting with '_' from being shown.
413 if ($this->bType != 'const' || substr($depth, 0, 1) != '_') {
414 $goto = substr(md5($depth), 0, 6);
415 $deeper = is_array($arr[$key . '.']) && ($this->tsbrowser_depthKeys[$depth] || $this->ext_expandAllNotes) ? 1 : 0;
416 $PM = 'join';
417 $LN = $a == $c ? 'blank' : 'line';
418 $BTM = $a == $c ? 'bottom' : '';
419 $PM = is_array($arr[$key . '.']) && !$this->ext_noPMicons ? ($deeper ? 'minus' : 'plus') : 'join';
420 $HTML .= $depthData;
421 $theIcon = '<img src="' . $GLOBALS['BACK_PATH'] . 'gfx/ol/' . $PM . $BTM . '.gif" width="18" height="16" align="top" border="0" alt="" />';
422 if ($PM == 'join') {
423 $HTML .= $theIcon;
424 } else {
425 $urlParameters = array(
426 'id' => $GLOBALS['SOBE']->id,
427 'tsbr[' . $depth . ']' => $deeper ? 0 : 1
428 );
429 if (GeneralUtility::_GP('breakPointLN')) {
430 $urlParameters['breakPointLN'] = GeneralUtility::_GP('breakPointLN');
431 }
432 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters) . '#' . $goto;
433 $HTML .= '<a name="' . $goto . '" href="' . htmlspecialchars($aHref) . '">' . $theIcon . '</a>';
434 }
435 $label = $key;
436 // Read only...
437 if (GeneralUtility::inList('types,resources,sitetitle', $depth) && $this->bType == 'setup') {
438 $label = '<font color="#666666">' . $label . '</font>';
439 } else {
440 if ($this->linkObjects) {
441 $urlParameters = array(
442 'id' => $GLOBALS['SOBE']->id,
443 'sObj' => $depth
444 );
445 if (GeneralUtility::_GP('breakPointLN')) {
446 $urlParameters['breakPointLN'] = GeneralUtility::_GP('breakPointLN');
447 }
448 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
449 if ($this->bType != 'const') {
450 $ln = is_array($arr[$key . '.ln..']) ? 'Defined in: ' . $this->lineNumberToScript($arr[($key . '.ln..')]) : 'N/A';
451 } else {
452 $ln = '';
453 }
454 if ($this->tsbrowser_searchKeys[$depth] & 4) {
455 $label = '<strong><font color="red">' . $label . '</font></strong>';
456 }
457 // The key has matched the search string
458 $label = '<a href="' . htmlspecialchars($aHref) . '" title="' . htmlspecialchars($ln) . '">' . $label . '</a>';
459 }
460 }
461 $HTML .= '[' . $label . ']';
462 if (isset($arr[$key])) {
463 $theValue = $arr[$key];
464 if ($this->fixedLgd) {
465 $imgBlocks = ceil(1 + strlen($depthData) / 77);
466 $lgdChars = 68 - ceil(strlen(('[' . $key . ']')) * 0.8) - $imgBlocks * 3;
467 $theValue = $this->ext_fixed_lgd($theValue, $lgdChars);
468 }
469 // The value has matched the search string
470 if ($this->tsbrowser_searchKeys[$depth] & 2) {
471 $HTML .= '&nbsp;=&nbsp;<strong><font color="red">' . $this->makeHtmlspecialchars($theValue) . '</font></strong>';
472 } else {
473 $HTML .= '&nbsp;=&nbsp;<strong>' . $this->makeHtmlspecialchars($theValue) . '</strong>';
474 }
475 if ($this->ext_regComments && isset($arr[$key . '..'])) {
476 $comment = $arr[$key . '..'];
477 // Skip INCLUDE_TYPOSCRIPT comments, they are almost useless
478 if (!preg_match('/### <INCLUDE_TYPOSCRIPT:.*/', $comment)) {
479 // Remove linebreaks, replace with ' '
480 $comment = preg_replace('/[\\r\\n]/', ' ', $comment);
481 // Remove # and * if more than twice in a row
482 $comment = preg_replace('/[#\\*]{2,}/', '', $comment);
483 // Replace leading # (just if it exists) and add it again. Result: Every comment should be prefixed by a '#'.
484 $comment = preg_replace('/^[#\\*\\s]+/', '# ', $comment);
485 // Masking HTML Tags: Replace < with &lt; and > with &gt;
486 $comment = $this->makeHtmlspecialchars($comment);
487 $HTML .= ' <span class="comment">' . trim($comment) . '</span>';
488 }
489 }
490 }
491 $HTML .= '<br />';
492 if ($deeper) {
493 $HTML .= $this->ext_getObjTree($arr[$key . '.'], $depth, $depthData . '<img src="' . $GLOBALS['BACK_PATH'] . 'gfx/ol/' . $LN . '.gif" width="18" height="16" align="top" alt="" />', '', $arr[$key], $alphaSort);
494 }
495 }
496 }
497 return $HTML;
498 }
499
500 /**
501 * [Describe function...]
502 *
503 * @param [type] $lnArr: ...
504 * @return [type] ...
505 * @todo Define visibility
506 */
507 public function lineNumberToScript($lnArr) {
508 if (!is_array($this->lnToScript)) {
509 $this->lnToScript = array();
510 $c = 1;
511 $c += substr_count($GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'], LF) + 2;
512 $this->lnToScript[$c] = '[Default]';
513 foreach ($this->hierarchyInfoToRoot as $info) {
514 $c += $info['configLines'] + 1;
515 $this->lnToScript[$c] = $info['title'];
516 }
517 }
518 foreach ($lnArr as $k => $ln) {
519 foreach ($this->lnToScript as $endLn => $title) {
520 if ($endLn >= intval($ln)) {
521 $lnArr[$k] = '"' . $title . '", ' . $ln;
522 break;
523 }
524 }
525 }
526 return implode('; ', $lnArr);
527 }
528
529 /**
530 * [Describe function...]
531 *
532 * @param [type] $theValue: ...
533 * @return [type] ...
534 * @todo Define visibility
535 */
536 public function makeHtmlspecialchars($theValue) {
537 return $this->ext_noSpecialCharsOnLabels ? $theValue : htmlspecialchars($theValue);
538 }
539
540 /**
541 * [Describe function...]
542 *
543 * @param [type] $arr: ...
544 * @param [type] $depth_in: ...
545 * @param [type] $searchString: ...
546 * @param [type] $keyArray: ...
547 * @return [type] ...
548 * @todo Define visibility
549 */
550 public function ext_getSearchKeys($arr, $depth_in, $searchString, $keyArray) {
551 $keyArr = array();
552 foreach ($arr as $key => $value) {
553 $key = preg_replace('/\\.$/', '', $key);
554 if (substr($key, -1) != '.') {
555 $keyArr[$key] = 1;
556 }
557 }
558 $c = count($keyArr);
559 if ($depth_in) {
560 $depth_in = $depth_in . '.';
561 }
562 foreach ($keyArr as $key => $value) {
563 $depth = $depth_in . $key;
564 $deeper = is_array($arr[$key . '.']);
565 if ($this->regexMode) {
566 // The value has matched
567 if (preg_match('/' . $searchString . '/', $arr[$key])) {
568 $this->tsbrowser_searchKeys[$depth] += 2;
569 }
570 // The key has matched
571 if (preg_match('/' . $searchString . '/', $key)) {
572 $this->tsbrowser_searchKeys[$depth] += 4;
573 }
574 // Just open this subtree if the parent key has matched the search
575 if (preg_match('/' . $searchString . '/', $depth_in)) {
576 $this->tsbrowser_searchKeys[$depth] = 1;
577 }
578 } else {
579 // The value has matched
580 if (stristr($arr[$key], $searchString)) {
581 $this->tsbrowser_searchKeys[$depth] += 2;
582 }
583 // The key has matches
584 if (stristr($key, $searchString)) {
585 $this->tsbrowser_searchKeys[$depth] += 4;
586 }
587 // Just open this subtree if the parent key has matched the search
588 if (stristr($depth_in, $searchString)) {
589 $this->tsbrowser_searchKeys[$depth] = 1;
590 }
591 }
592 if ($deeper) {
593 $cS = count($this->tsbrowser_searchKeys);
594 $keyArray = $this->ext_getSearchKeys($arr[$key . '.'], $depth, $searchString, $keyArray);
595 if ($cS != count($this->tsbrowser_searchKeys)) {
596 $keyArray[$depth] = 1;
597 }
598 }
599 }
600 return $keyArray;
601 }
602
603 /**
604 * [Describe function...]
605 *
606 * @param [type] $pid: ...
607 * @return [type] ...
608 * @todo Define visibility
609 */
610 public function ext_getRootlineNumber($pid) {
611 if ($pid && is_array($GLOBALS['rootLine'])) {
612 foreach ($GLOBALS['rootLine'] as $key => $val) {
613 if ($val['uid'] == $pid) {
614 return $key;
615 }
616 }
617 }
618 }
619
620 /**
621 * [Describe function...]
622 *
623 * @param [type] $arr: ...
624 * @param [type] $depthData: ...
625 * @param [type] $keyArray: ...
626 * @param [type] $first: ...
627 * @return [type] ...
628 * @todo Define visibility
629 */
630 public function ext_getTemplateHierarchyArr($arr, $depthData, $keyArray, $first = 0) {
631 $keyArr = array();
632 foreach ($arr as $key => $value) {
633 $key = preg_replace('/\\.$/', '', $key);
634 if (substr($key, -1) != '.') {
635 $keyArr[$key] = 1;
636 }
637 }
638 $a = 0;
639 $c = count($keyArr);
640 static $i = 0;
641 foreach ($keyArr as $key => $value) {
642 $HTML = '';
643 $a++;
644 $deeper = is_array($arr[$key . '.']);
645 $row = $arr[$key];
646 $PM = 'join';
647 $LN = $a == $c ? 'blank' : 'line';
648 $BTM = $a == $c ? 'top' : '';
649 $PM = 'join';
650 $HTML .= $depthData;
651 $alttext = '[' . $row['templateID'] . ']';
652 $alttext .= $row['pid'] ? ' - ' . BackendUtility::getRecordPath($row['pid'], $GLOBALS['SOBE']->perms_clause, 20) : '';
653 $icon = substr($row['templateID'], 0, 3) == 'sys' ? \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord('sys_template', $row, array('title' => $alttext)) : \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('mimetypes-x-content-template-static', array('title' => $alttext));
654 if (in_array($row['templateID'], $this->clearList_const) || in_array($row['templateID'], $this->clearList_setup)) {
655 $urlParameters = array(
656 'id' => $GLOBALS['SOBE']->id,
657 'template' => $row['templateID']
658 );
659 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
660 $A_B = '<a href="' . htmlspecialchars($aHref) . '">';
661 $A_E = '</a>';
662 if (GeneralUtility::_GP('template') == $row['templateID']) {
663 $A_B = '<strong>' . $A_B;
664 $A_E .= '</strong>';
665 }
666 } else {
667 $A_B = '';
668 $A_E = '';
669 }
670 $HTML .= ($first ? '' : '<img src="' . $GLOBALS['BACK_PATH'] . 'gfx/ol/' . $PM . $BTM . '.gif" width="18" height="16" align="top" border="0" alt="" />') . $icon . $A_B . htmlspecialchars(GeneralUtility::fixed_lgd_cs($row['title'], $GLOBALS['BE_USER']->uc['titleLen'])) . $A_E . '&nbsp;&nbsp;';
671 $RL = $this->ext_getRootlineNumber($row['pid']);
672 $keyArray[] = '<tr class="' . ($i++ % 2 == 0 ? 'bgColor4' : 'bgColor6') . '">
673 <td nowrap="nowrap">' . $HTML . '</td>
674 <td align="center">' . ($row['root'] ? \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-checked') : '') . '&nbsp;&nbsp;</td>
675 <td align="center">' . ($row['clConf'] ? \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-checked') : '') . '&nbsp;&nbsp;' . '</td>
676 <td align="center">' . ($row['clConst'] ? \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-checked') : '') . '&nbsp;&nbsp;' . '</td>
677 <td align="center">' . ($row['pid'] ? $row['pid'] : '') . '</td>
678 <td align="center">' . (strcmp($RL, '') ? $RL : '') . '</td>
679 <td>' . ($row['next'] ? '&nbsp;' . $row['next'] . '&nbsp;&nbsp;' : '') . '</td>
680 </tr>';
681 if ($deeper) {
682 $keyArray = $this->ext_getTemplateHierarchyArr($arr[$key . '.'], $depthData . ($first ? '' : '<img src="' . $GLOBALS['BACK_PATH'] . 'gfx/ol/' . $LN . '.gif" width="18" height="16" align="top" />'), $keyArray);
683 }
684 }
685 return $keyArray;
686 }
687
688 /**
689 * [Describe function...]
690 *
691 * @param [type] $depthDataArr: ...
692 * @param [type] $pointer: ...
693 * @return [type] ...
694 * @todo Define visibility
695 */
696 public function ext_process_hierarchyInfo($depthDataArr, &$pointer) {
697 $parent = $this->hierarchyInfo[$pointer - 1]['templateParent'];
698 while ($pointer > 0 && $this->hierarchyInfo[$pointer - 1]['templateParent'] == $parent) {
699 $pointer--;
700 $row = $this->hierarchyInfo[$pointer];
701 $depthDataArr[$row['templateID']] = $row;
702 $depthDataArr[$row['templateID']]['bgcolor_setup'] = isset($this->clearList_setup_temp[$row['templateID']]) ? ' class="bgColor5"' : '';
703 $depthDataArr[$row['templateID']]['bgcolor_const'] = isset($this->clearList_const_temp[$row['templateID']]) ? ' class="bgColor5"' : '';
704 unset($this->clearList_setup_temp[$row['templateID']]);
705 unset($this->clearList_const_temp[$row['templateID']]);
706 $this->templateTitles[$row['templateID']] = $row['title'];
707 if ($row['templateID'] == $this->hierarchyInfo[$pointer - 1]['templateParent']) {
708 $depthDataArr[$row['templateID'] . '.'] = $this->ext_process_hierarchyInfo(array(), $pointer);
709 }
710 }
711 return $depthDataArr;
712 }
713
714 /**
715 * [Describe function...]
716 *
717 * @param [type] $config: ...
718 * @param [type] $lineNumbers: ...
719 * @param [type] $comments: ...
720 * @param [type] $crop: ...
721 * @param [type] $syntaxHL: ...
722 * @param [type] $syntaxHLBlockmode: ...
723 * @return [type] ...
724 * @todo Define visibility
725 */
726 public function ext_outputTS($config, $lineNumbers = 0, $comments = 0, $crop = 0, $syntaxHL = 0, $syntaxHLBlockmode = 0) {
727 $all = '';
728 foreach ($config as $str) {
729 $all .= LF . '[GLOBAL]' . LF . $str;
730 }
731 if ($syntaxHL) {
732 $all = preg_replace('/^[^' . LF . ']*./', '', $all);
733 $all = chop($all);
734 $tsparser = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
735 $tsparser->lineNumberOffset = $this->ext_lineNumberOffset + 1;
736 $tsparser->parentObject = $this;
737 return $tsparser->doSyntaxHighlight($all, $lineNumbers ? array($this->ext_lineNumberOffset + 1) : '', $syntaxHLBlockmode);
738 } else {
739 return $this->ext_formatTS($all, $lineNumbers, $comments, $crop);
740 }
741 }
742
743 /**
744 * Returns a new string of max. $chars length
745 * If the string is longer, it will be truncated and prepended with '...'
746 * $chars must be an integer of at least 4
747 *
748 * @param [type] $string: ...
749 * @param [type] $chars: ...
750 * @return [type] ...
751 * @todo Define visibility
752 */
753 public function ext_fixed_lgd($string, $chars) {
754 if ($chars >= 4) {
755 if (strlen($string) > $chars) {
756 if (strlen($string) > 24 && substr($string, 0, 12) == '##' . $this->Cmarker . '_B##') {
757 return '##' . $this->Cmarker . '_B##' . GeneralUtility::fixed_lgd_cs(substr($string, 12, -12), ($chars - 3)) . '##' . $this->Cmarker . '_E##';
758 } else {
759 return GeneralUtility::fixed_lgd_cs($string, $chars - 3);
760 }
761 }
762 }
763 return $string;
764 }
765
766 /**
767 * [Describe function...]
768 *
769 * @param integer $lineNumber Line Number
770 * @param [type] $str: ...
771 * @return string
772 * @todo Define visibility
773 */
774 public function ext_lnBreakPointWrap($lineNumber, $str) {
775 return '<a href="#" id="line-' . $lineNumber . '" onClick="return brPoint(' . $lineNumber . ',' . ($this->ext_lineNumberOffset_mode == 'setup' ? 1 : 0) . ');">' . $str . '</a>';
776 }
777
778 /**
779 * [Describe function...]
780 *
781 * @param [type] $input: ...
782 * @param [type] $ln: ...
783 * @param [type] $comments: ...
784 * @param [type] $crop: ...
785 * @return [type] ...
786 * @todo Define visibility
787 */
788 public function ext_formatTS($input, $ln, $comments = 1, $crop = 0) {
789 $input = preg_replace('/^[^' . LF . ']*./', '', $input);
790 $input = chop($input);
791 $cArr = explode(LF, $input);
792 $n = ceil(log10(count($cArr) + $this->ext_lineNumberOffset));
793 $lineNum = '';
794 foreach ($cArr as $k => $v) {
795 $lln = $k + $this->ext_lineNumberOffset + 1;
796 if ($ln) {
797 $lineNum = $this->ext_lnBreakPointWrap($lln, str_replace(' ', '&nbsp;', sprintf(('% ' . $n . 'd'), $lln))) . ': ';
798 }
799 $v = htmlspecialchars($v);
800 if ($crop) {
801 $v = $this->ext_fixed_lgd($v, $ln ? 71 : 77);
802 }
803 $cArr[$k] = $lineNum . str_replace(' ', '&nbsp;', $v);
804 $firstChar = substr(trim($v), 0, 1);
805 if ($firstChar == '[') {
806 $cArr[$k] = '<font color="green"><strong>' . $cArr[$k] . '</strong></font>';
807 } elseif ($firstChar == '/' || $firstChar == '#') {
808 if ($comments) {
809 $cArr[$k] = '<span class="typo3-dimmed">' . $cArr[$k] . '</span>';
810 } else {
811 unset($cArr[$k]);
812 }
813 }
814 }
815 $output = implode($cArr, '<br />') . '<br />';
816 return $output;
817 }
818
819 /**
820 * [Describe function...]
821 *
822 * @param [type] $id: ...
823 * @param [type] $template_uid: ...
824 * @return [type] ...
825 * @todo Define visibility
826 */
827 public function ext_getFirstTemplate($id, $template_uid = 0) {
828 // Query is taken from the runThroughTemplates($theRootLine) function in the parent class.
829 if (intval($id)) {
830 if ($template_uid) {
831 $addC = ' AND uid=' . $template_uid;
832 }
833 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'pid=' . intval($id) . $addC . ' ' . $this->whereClause, '', 'sorting', '1');
834 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
835 BackendUtility::workspaceOL('sys_template', $row);
836 $GLOBALS['TYPO3_DB']->sql_free_result($res);
837 // Returns the template row if found.
838 return $row;
839 }
840 }
841
842 /**
843 * [Describe function...]
844 *
845 * @param [type] $id: ...
846 * @return [type] ...
847 * @todo Define visibility
848 */
849 public function ext_getAllTemplates($id) {
850 // Query is taken from the runThroughTemplates($theRootLine) function in the parent class.
851 if (intval($id)) {
852 $outRes = array();
853 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'pid=' . intval($id) . ' ' . $this->whereClause, '', 'sorting');
854 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
855 BackendUtility::workspaceOL('sys_template', $row);
856 if (is_array($row)) {
857 $outRes[] = $row;
858 }
859 }
860 $GLOBALS['TYPO3_DB']->sql_free_result($res);
861 // Returns the template rows in an array.
862 return $outRes;
863 }
864 }
865
866 /**
867 * This function compares the flattened constants (default and all).
868 * Returns an array with the constants from the whole template which may be edited by the module.
869 *
870 * @param [type] $default: ...
871 * @return [type] ...
872 * @todo Define visibility
873 */
874 public function ext_compareFlatSetups($default) {
875 $editableComments = array();
876 foreach ($this->flatSetup as $const => $value) {
877 if (substr($const, -2) != '..' && isset($this->flatSetup[$const . '..'])) {
878 $comment = trim($this->flatSetup[$const . '..']);
879 $c_arr = explode(LF, $comment);
880 foreach ($c_arr as $k => $v) {
881 $line = trim(preg_replace('/^[#\\/]*/', '', $v));
882 if ($line) {
883 $parts = explode(';', $line);
884 foreach ($parts as $par) {
885 if (strstr($par, '=')) {
886 $keyValPair = explode('=', $par, 2);
887 switch (trim(strtolower($keyValPair[0]))) {
888 case 'type':
889 // Type:
890 $editableComments[$const]['type'] = trim($keyValPair[1]);
891 break;
892 case 'cat':
893 // List of categories.
894 $catSplit = explode('/', strtolower($keyValPair[1]));
895 $editableComments[$const]['cat'] = trim($catSplit[0]);
896 // This is the subcategory. Must be a key in $this->subCategories[]. catSplit[2] represents the search-order within the subcat.
897 $catSplit[1] = trim($catSplit[1]);
898 if ($catSplit[1] && isset($this->subCategories[$catSplit[1]])) {
899 $editableComments[$const]['subcat_name'] = $catSplit[1];
900 $editableComments[$const]['subcat'] = $this->subCategories[$catSplit[1]][1] . '/' . $catSplit[1] . '/' . trim($catSplit[2]) . 'z';
901 } else {
902 $editableComments[$const]['subcat'] = 'x' . '/' . trim($catSplit[2]) . 'z';
903 }
904 break;
905 case 'label':
906 // Label
907 $editableComments[$const]['label'] = trim($keyValPair[1]);
908 break;
909 case 'customsubcategory':
910 // Custom subCategory label
911 $customSubcategory = explode('=', $keyValPair[1], 2);
912 if (trim($customSubcategory[0])) {
913 $subCategoryKey = strtolower($customSubcategory[0]);
914 $this->subCategories[$subCategoryKey][0] = $GLOBALS['LANG']->sL($customSubcategory[1]);
915 }
916 break;
917 }
918 }
919 }
920 }
921 }
922 }
923 if (isset($editableComments[$const])) {
924 $editableComments[$const]['name'] = $const;
925 $editableComments[$const]['value'] = trim($value);
926 if (isset($default[$const])) {
927 $editableComments[$const]['default_value'] = trim($default[$const]);
928 }
929 }
930 }
931 return $editableComments;
932 }
933
934 /**
935 * [Describe function...]
936 *
937 * @param [type] $editConstArray: ...
938 * @return [type] ...
939 * @todo Define visibility
940 */
941 public function ext_categorizeEditableConstants($editConstArray) {
942 // Runs through the available constants and fills the $this->categories array with pointers and priority-info
943 foreach ($editConstArray as $constName => $constData) {
944 if (!$constData['type']) {
945 $constData['type'] = 'string';
946 }
947 $cats = explode(',', $constData['cat']);
948 // if = only one category, while allows for many. We have agreed on only one category is the most basic way...
949 foreach ($cats as $theCat) {
950 $theCat = trim($theCat);
951 if ($theCat) {
952 $this->categories[$theCat][$constName] = $constData['subcat'];
953 }
954 }
955 }
956 }
957
958 /**
959 * [Describe function...]
960 *
961 * @return [type] ...
962 * @todo Define visibility
963 */
964 public function ext_getCategoryLabelArray() {
965 // Returns array used for labels in the menu.
966 $retArr = array();
967 foreach ($this->categories as $k => $v) {
968 if (count($v)) {
969 $retArr[$k] = strtoupper($k) . ' (' . count($v) . ')';
970 }
971 }
972 return $retArr;
973 }
974
975 /**
976 * [Describe function...]
977 *
978 * @param [type] $type: ...
979 * @return [type] ...
980 * @todo Define visibility
981 */
982 public function ext_getTypeData($type) {
983 $retArr = array();
984 $type = trim($type);
985 if (!$type) {
986 $retArr['type'] = 'string';
987 } else {
988 $m = strcspn($type, ' [');
989 $retArr['type'] = strtolower(substr($type, 0, $m));
990 if (GeneralUtility::inList('int,options,file,boolean,offset,user', $retArr['type'])) {
991 $p = trim(substr($type, $m));
992 $reg = array();
993 preg_match('/\\[(.*)\\]/', $p, $reg);
994 $p = trim($reg[1]);
995 if ($p) {
996 $retArr['paramstr'] = $p;
997 switch ($retArr['type']) {
998 case 'int':
999 if (substr($retArr['paramstr'], 0, 1) == '-') {
1000 $retArr['params'] = GeneralUtility::intExplode('-', substr($retArr['paramstr'], 1));
1001 $retArr['params'][0] = intval('-' . $retArr['params'][0]);
1002 } else {
1003 $retArr['params'] = GeneralUtility::intExplode('-', $retArr['paramstr']);
1004 }
1005 $retArr['paramstr'] = $retArr['params'][0] . ' - ' . $retArr['params'][1];
1006 break;
1007 case 'options':
1008 $retArr['params'] = explode(',', $retArr['paramstr']);
1009 break;
1010 }
1011 }
1012 }
1013 }
1014 return $retArr;
1015 }
1016
1017 /**
1018 * [Describe function...]
1019 *
1020 * @param [type] $category: ...
1021 * @return [type] ...
1022 * @todo Define visibility
1023 */
1024 public function ext_getTSCE_config($category) {
1025 $catConf = $this->setup['constants']['TSConstantEditor.'][$category . '.'];
1026 $out = array();
1027 if (is_array($catConf)) {
1028 foreach ($catConf as $key => $val) {
1029 switch ($key) {
1030 case 'image':
1031 $out['imagetag'] = $this->ext_getTSCE_config_image($catConf['image']);
1032 break;
1033 case 'description':
1034
1035 case 'bulletlist':
1036
1037 case 'header':
1038 $out[$key] = $val;
1039 break;
1040 default:
1041 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($key)) {
1042 $constRefs = explode(',', $val);
1043 foreach ($constRefs as $const) {
1044 $const = trim($const);
1045 if ($const && $const <= 20) {
1046 $out['constants'][$const] .= $this->ext_getKeyImage($key);
1047 }
1048 }
1049 }
1050 }
1051 }
1052 }
1053 $this->helpConfig = $out;
1054 }
1055
1056 /**
1057 * [Describe function...]
1058 *
1059 * @param [type] $key: ...
1060 * @return [type] ...
1061 * @todo Define visibility
1062 */
1063 public function ext_getKeyImage($key) {
1064 return '<img src="' . $this->ext_localWebGfxPrefix . 'gfx/' . $key . '.gif" align="top" hspace=2>';
1065 }
1066
1067 /**
1068 * [Describe function...]
1069 *
1070 * @param [type] $imgConf: ...
1071 * @return [type] ...
1072 * @todo Define visibility
1073 */
1074 public function ext_getTSCE_config_image($imgConf) {
1075 if (substr($imgConf, 0, 4) == 'gfx/') {
1076 $iFile = $this->ext_localGfxPrefix . $imgConf;
1077 $tFile = $this->ext_localWebGfxPrefix . $imgConf;
1078 } elseif (substr($imgConf, 0, 4) == 'EXT:') {
1079 $iFile = GeneralUtility::getFileAbsFileName($imgConf);
1080 if ($iFile) {
1081 $f = \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($iFile);
1082 $tFile = $GLOBALS['BACK_PATH'] . '../' . $f;
1083 }
1084 }
1085 $imageInfo = @getImagesize($iFile);
1086 return '<img src="' . $tFile . '" ' . $imageInfo[3] . '>';
1087 }
1088
1089 /**
1090 * [Describe function...]
1091 *
1092 * @param [type] $params: ...
1093 * @return [type] ...
1094 * @todo Define visibility
1095 */
1096 public function ext_fNandV($params) {
1097 $fN = 'data[' . $params['name'] . ']';
1098 $fV = $params['value'];
1099 // Values entered from the constantsedit cannot be constants! 230502; removed \{ and set {
1100 if (preg_match('/^{[\\$][a-zA-Z0-9\\.]*}$/', trim($fV), $reg)) {
1101 $fV = '';
1102 }
1103 $fV = htmlspecialchars($fV);
1104 return array($fN, $fV, $params);
1105 }
1106
1107 /**
1108 * This functions returns the HTML-code that creates the editor-layout of the module.
1109 *
1110 * @param [type] $theConstants: ...
1111 * @param [type] $category: ...
1112 * @return [type] ...
1113 * @todo Define visibility
1114 */
1115 public function ext_printFields($theConstants, $category) {
1116 reset($theConstants);
1117 $output = '<script type="text/javascript" src="' . $GLOBALS['BACK_PATH'] . 'js/constantEditor.js"></script>
1118 ';
1119 $subcat = '';
1120 if (is_array($this->categories[$category])) {
1121 $help = $this->helpConfig;
1122 if (!$this->doNotSortCategoriesBeforeMakingForm) {
1123 asort($this->categories[$category]);
1124 }
1125 foreach ($this->categories[$category] as $name => $type) {
1126 $params = $theConstants[$name];
1127 if (is_array($params)) {
1128 if ($subcat != $params['subcat_name']) {
1129 $subcat = $params['subcat_name'];
1130 $subcat_name = $params['subcat_name'] ? $this->subCategories[$params['subcat_name']][0] : 'Others';
1131 $output .= '<h3 class="typo3-tstemplate-ceditor-subcat">' . $subcat_name . '</h3>';
1132 }
1133 $label = $GLOBALS['LANG']->sL($params['label']);
1134 $label_parts = explode(':', $label, 2);
1135 if (count($label_parts) == 2) {
1136 $head = trim($label_parts[0]);
1137 $body = trim($label_parts[1]);
1138 } else {
1139 $head = trim($label_parts[0]);
1140 $body = '';
1141 }
1142 if (strlen($head) > 35) {
1143 if (!$body) {
1144 $body = $head;
1145 }
1146 $head = GeneralUtility::fixed_lgd_cs($head, 35);
1147 }
1148 $typeDat = $this->ext_getTypeData($params['type']);
1149 $checked = '';
1150 $p_field = '';
1151 $raname = substr(md5($params['name']), 0, 10);
1152 $aname = '\'' . $raname . '\'';
1153 list($fN, $fV, $params) = $this->ext_fNandV($params);
1154 switch ($typeDat['type']) {
1155 case 'int':
1156
1157 case 'int+':
1158 $p_field = '<input id="' . $fN . '" type="text" name="' . $fN . '" value="' . $fV . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(5) . ' onChange="uFormUrl(' . $aname . ')" />';
1159 if ($typeDat['paramstr']) {
1160 $p_field .= ' Range: ' . $typeDat['paramstr'];
1161 } elseif ($typeDat['type'] == 'int+') {
1162 $p_field .= ' Range: 0 - ';
1163 } else {
1164 $p_field .= ' (Integer)';
1165 }
1166 break;
1167 case 'color':
1168 $colorNames = explode(',', ',' . $this->HTMLcolorList);
1169 $p_field = '';
1170 foreach ($colorNames as $val) {
1171 $sel = '';
1172 if ($val == strtolower($params['value'])) {
1173 $sel = ' selected';
1174 }
1175 $p_field .= '<option value="' . htmlspecialchars($val) . '"' . $sel . '>' . $val . '</option>';
1176 }
1177 $p_field = '<select id="select-' . $fN . '" rel="' . $fN . '" name="C' . $fN . '" class="typo3-tstemplate-ceditor-color-select" onChange="uFormUrl(' . $aname . ');">' . $p_field . '</select>';
1178 $p_field .= '<input type="text" id="input-' . $fN . '" rel="' . $fN . '" name="' . $fN . '" class="typo3-tstemplate-ceditor-color-input" value="' . $fV . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(7) . ' onChange="uFormUrl(' . $aname . ')" />';
1179 break;
1180 case 'wrap':
1181 $wArr = explode('|', $fV);
1182 $p_field = '<input type="text" id="' . $fN . '" name="' . $fN . '" value="' . $wArr[0] . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(29) . ' onChange="uFormUrl(' . $aname . ')" />';
1183 $p_field .= ' | ';
1184 $p_field .= '<input type="text" name="W' . $fN . '" value="' . $wArr[1] . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(15) . ' onChange="uFormUrl(' . $aname . ')" />';
1185 break;
1186 case 'offset':
1187 $wArr = explode(',', $fV);
1188 $labels = GeneralUtility::trimExplode(',', $typeDat['paramstr']);
1189 $p_field = ($labels[0] ? $labels[0] : 'x') . ':<input type="text" name="' . $fN . '" value="' . $wArr[0] . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1190 $p_field .= ' , ';
1191 $p_field .= ($labels[1] ? $labels[1] : 'y') . ':<input type="text" name="W' . $fN . '" value="' . $wArr[1] . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1192 $labelsCount = count($labels);
1193 for ($aa = 2; $aa < $labelsCount; $aa++) {
1194 if ($labels[$aa]) {
1195 $p_field .= ' , ' . $labels[$aa] . ':<input type="text" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' onChange="uFormUrl(' . $aname . ')" />';
1196 } else {
1197 $p_field .= '<input type="hidden" name="W' . $aa . $fN . '" value="' . $wArr[$aa] . '" />';
1198 }
1199 }
1200 break;
1201 case 'options':
1202 if (is_array($typeDat['params'])) {
1203 $p_field = '';
1204 foreach ($typeDat['params'] as $val) {
1205 $vParts = explode('=', $val, 2);
1206 $label = $vParts[0];
1207 $val = isset($vParts[1]) ? $vParts[1] : $vParts[0];
1208 // option tag:
1209 $sel = '';
1210 if ($val == $params['value']) {
1211 $sel = ' selected';
1212 }
1213 $p_field .= '<option value="' . htmlspecialchars($val) . '"' . $sel . '>' . $GLOBALS['LANG']->sL($label) . '</option>';
1214 }
1215 $p_field = '<select id="' . $fN . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1216 }
1217 break;
1218 case 'boolean':
1219 $p_field = '<input type="hidden" name="' . $fN . '" value="0" />';
1220 $sel = '';
1221 if ($fV) {
1222 $sel = ' checked';
1223 }
1224 $p_field .= '<input id="' . $fN . '" type="checkbox" name="' . $fN . '" value="' . ($typeDat['paramstr'] ? $typeDat['paramstr'] : 1) . '"' . $sel . ' onClick="uFormUrl(' . $aname . ')" />';
1225 break;
1226 case 'comment':
1227 $p_field = '<input type="hidden" name="' . $fN . '" value="#" />';
1228 $sel = '';
1229 if (!$fV) {
1230 $sel = ' checked';
1231 }
1232 $p_field .= '<input id="' . $fN . '" type="checkbox" name="' . $fN . '" value=""' . $sel . ' onClick="uFormUrl(' . $aname . ')" />';
1233 break;
1234 case 'file':
1235 $p_field = '<option value=""></option>';
1236 $theImage = '';
1237 // extensionlist
1238 $extList = $typeDat['paramstr'];
1239 $p_field = '<option value="">(' . $extList . ')</option>';
1240 if ($extList == 'IMAGE_EXT') {
1241 $extList = $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'];
1242 }
1243 if (trim($params['value'])) {
1244 $val = $params['value'];
1245 $p_field .= '<option value=""></option>';
1246 $p_field .= '<option value="' . htmlspecialchars($val) . '" selected>' . $val . '</option>';
1247 }
1248 $p_field = '<select id="' . $fN . '" name="' . $fN . '" onChange="uFormUrl(' . $aname . ')">' . $p_field . '</select>';
1249 $p_field .= $theImage;
1250 break;
1251 case 'user':
1252 $userFunction = $typeDat['paramstr'];
1253 $userFunctionParams = array('fieldName' => $fN, 'fieldValue' => $fV);
1254 $p_field = GeneralUtility::callUserFunction($userFunction, $userFunctionParams, $this, '');
1255 break;
1256 case 'small':
1257
1258 default:
1259 $fwidth = $typeDat['type'] == 'small' ? 10 : 46;
1260 $p_field = '<input id="' . $fN . '" type="text" name="' . $fN . '" value="' . $fV . '"' . $GLOBALS['TBE_TEMPLATE']->formWidth($fwidth) . ' onChange="uFormUrl(' . $aname . ')" />';
1261 }
1262 // Define default names and IDs
1263 $userTyposcriptID = 'userTS-' . $params['name'];
1264 $defaultTyposcriptID = 'defaultTS-' . $params['name'];
1265 $checkboxName = 'check[' . $params['name'] . ']';
1266 $checkboxID = $checkboxName;
1267 // Handle type=color specially
1268 if ($typeDat['type'] == 'color' && substr($params['value'], 0, 2) != '{$') {
1269 $color = '<div id="colorbox-' . $fN . '" class="typo3-tstemplate-ceditor-colorblock" style="background-color:' . $params['value'] . ';">&nbsp;</div>';
1270 } else {
1271 $color = '';
1272 }
1273 if (!$this->ext_dontCheckIssetValues) {
1274 // Set the default styling options
1275 if (isset($this->objReg[$params['name']])) {
1276 $checkboxValue = 'checked';
1277 $userTyposcriptStyle = '';
1278 $defaultTyposcriptStyle = 'style="display:none;"';
1279 } else {
1280 $checkboxValue = '';
1281 $userTyposcriptStyle = 'style="display:none;"';
1282 $defaultTyposcriptStyle = '';
1283 }
1284 $deleteIconHTML = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-undo', array(
1285 'class' => 'typo3-tstemplate-ceditor-control undoIcon',
1286 'alt' => 'Revert to default Constant',
1287 'title' => 'Revert to default Constant',
1288 'rel' => $params['name']
1289 ));
1290 $editIconHTML = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-open', array(
1291 'class' => 'typo3-tstemplate-ceditor-control editIcon',
1292 'alt' => 'Edit this Constant',
1293 'title' => 'Edit this Constant',
1294 'rel' => $params['name']
1295 ));
1296 $constantCheckbox = '<input type="hidden" name="' . $checkboxName . '" id="' . $checkboxID . '" value="' . $checkboxValue . '"/>';
1297 // If there's no default value for the field, use a static label.
1298 if (!$params['default_value']) {
1299 $params['default_value'] = '[Empty]';
1300 }
1301 $constantDefaultRow = '<div class="typo3-tstemplate-ceditor-row" id="' . $defaultTyposcriptID . '" ' . $defaultTyposcriptStyle . '>' . $editIconHTML . htmlspecialchars($params['default_value']) . $color . '</div>';
1302 }
1303 $constantEditRow = '<div class="typo3-tstemplate-ceditor-row" id="' . $userTyposcriptID . '" ' . $userTyposcriptStyle . '>' . $deleteIconHTML . $p_field . $color . '</div>';
1304 $constantLabel = '<dt class="typo3-tstemplate-ceditor-label">' . htmlspecialchars($head) . '</dt>';
1305 $constantName = '<dt class="typo3-dimmed">[' . $params['name'] . ']</dt>';
1306 $constantDescription = $body ? '<dd>' . htmlspecialchars($body) . '</dd>' : '';
1307 $constantData = '<dd>' . $constantCheckbox . $constantEditRow . $constantDefaultRow . '</dd>';
1308 $output .= '<a name="' . $raname . '"></a>' . $help['constants'][$params['name']];
1309 $output .= '<dl class="typo3-tstemplate-ceditor-constant">' . $constantLabel . $constantName . $constantDescription . $constantData . '</dl>';
1310 } else {
1311 debug('Error. Constant did not exist. Should not happen.');
1312 }
1313 }
1314 }
1315 return $output;
1316 }
1317
1318 /***************************
1319 *
1320 * Processing input values
1321 *
1322 ***************************/
1323 /**
1324 * @param [type] $constants: ...
1325 * @return [type] ...
1326 * @todo Define visibility
1327 */
1328 public function ext_regObjectPositions($constants) {
1329 // This runs through the lines of the constants-field of the active template and registers the constants-names
1330 // and linepositions in an array, $this->objReg
1331 $this->raw = explode(LF, $constants);
1332 $this->rawP = 0;
1333 // Resetting the objReg if the divider is found!!
1334 $this->objReg = array();
1335 $this->ext_regObjects('');
1336 }
1337
1338 /**
1339 * [Describe function...]
1340 *
1341 * @param [type] $pre: ...
1342 * @return [type] ...
1343 * @todo Define visibility
1344 */
1345 public function ext_regObjects($pre) {
1346 // Works with regObjectPositions. "expands" the names of the TypoScript objects
1347 while (isset($this->raw[$this->rawP])) {
1348 $line = ltrim($this->raw[$this->rawP]);
1349 if (strstr($line, $this->edit_divider)) {
1350 // Resetting the objReg if the divider is found!!
1351 $this->objReg = array();
1352 }
1353 $this->rawP++;
1354 if ($line) {
1355 if (substr($line, 0, 1) == '[') {
1356
1357 } elseif (strcspn($line, '}#/') != 0) {
1358 $varL = strcspn($line, ' {=<');
1359 $var = substr($line, 0, $varL);
1360 $line = ltrim(substr($line, $varL));
1361 switch (substr($line, 0, 1)) {
1362 case '=':
1363 $this->objReg[$pre . $var] = $this->rawP - 1;
1364 break;
1365 case '{':
1366 $this->ext_inBrace++;
1367 $this->ext_regObjects($pre . $var . '.');
1368 break;
1369 }
1370 $this->lastComment = '';
1371 } elseif (substr($line, 0, 1) == '}') {
1372 $this->lastComment = '';
1373 $this->ext_inBrace--;
1374 if ($this->ext_inBrace < 0) {
1375 $this->ext_inBrace = 0;
1376 } else {
1377 break;
1378 }
1379 }
1380 }
1381 }
1382 }
1383
1384 /**
1385 * [Describe function...]
1386 *
1387 * @param [type] $key: ...
1388 * @param [type] $var: ...
1389 * @return [type] ...
1390 * @todo Define visibility
1391 */
1392 public function ext_putValueInConf($key, $var) {
1393 // Puts the value $var to the TypoScript value $key in the current lines of the templates.
1394 // If the $key is not found in the template constants field, a new line is inserted in the bottom.
1395 $theValue = ' ' . trim($var);
1396 if (isset($this->objReg[$key])) {
1397 $lineNum = $this->objReg[$key];
1398 $parts = explode('=', $this->raw[$lineNum], 2);
1399 if (count($parts) == 2) {
1400 $parts[1] = $theValue;
1401 }
1402 $this->raw[$lineNum] = implode($parts, '=');
1403 } else {
1404 $this->raw[] = $key . ' =' . $theValue;
1405 }
1406 $this->changed = 1;
1407 }
1408
1409 /**
1410 * [Describe function...]
1411 *
1412 * @param [type] $key: ...
1413 * @return [type] ...
1414 * @todo Define visibility
1415 */
1416 public function ext_removeValueInConf($key) {
1417 // Removes the value in the configuration
1418 if (isset($this->objReg[$key])) {
1419 $lineNum = $this->objReg[$key];
1420 unset($this->raw[$lineNum]);
1421 }
1422 $this->changed = 1;
1423 }
1424
1425 /**
1426 * [Describe function...]
1427 *
1428 * @param [type] $arr: ...
1429 * @param [type] $settings: ...
1430 * @return [type] ...
1431 * @todo Define visibility
1432 */
1433 public function ext_depthKeys($arr, $settings) {
1434 $tsbrArray = array();
1435 foreach ($arr as $theK => $theV) {
1436 $theKeyParts = explode('.', $theK);
1437 $depth = '';
1438 $c = count($theKeyParts);
1439 $a = 0;
1440 foreach ($theKeyParts as $p) {
1441 $a++;
1442 $depth .= ($depth ? '.' : '') . $p;
1443 $tsbrArray[$depth] = $c == $a ? $theV : 1;
1444 }
1445 }
1446 // Modify settings
1447 foreach ($tsbrArray as $theK => $theV) {
1448 if ($theV) {
1449 $settings[$theK] = 1;
1450 } else {
1451 unset($settings[$theK]);
1452 }
1453 }
1454 return $settings;
1455 }
1456
1457 /**
1458 * [Describe function...]
1459 *
1460 * @param [type] $http_post_vars: ...
1461 * @param array (not used anymore)
1462 * @param [type] $theConstants: ...
1463 * @param [type] $tplRow: ...
1464 * @return [type] ...
1465 * @todo Define visibility
1466 */
1467 public function ext_procesInput($http_post_vars, $http_post_files, $theConstants, $tplRow) {
1468 $data = $http_post_vars['data'];
1469 $check = $http_post_vars['check'];
1470 $Wdata = $http_post_vars['Wdata'];
1471 $W2data = $http_post_vars['W2data'];
1472 $W3data = $http_post_vars['W3data'];
1473 $W4data = $http_post_vars['W4data'];
1474 $W5data = $http_post_vars['W5data'];
1475 if (is_array($data)) {
1476 foreach ($data as $key => $var) {
1477 if (isset($theConstants[$key])) {
1478 // If checkbox is set, update the value
1479 if ($this->ext_dontCheckIssetValues || isset($check[$key])) {
1480 // Exploding with linebreak, just to make sure that no multiline input is given!
1481 list($var) = explode(LF, $var);
1482 $typeDat = $this->ext_getTypeData($theConstants[$key]['type']);
1483 switch ($typeDat['type']) {
1484 case 'int':
1485 if ($typeDat['paramstr']) {
1486 $var = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($var, $typeDat['params'][0], $typeDat['params'][1]);
1487 } else {
1488 $var = intval($var);
1489 }
1490 break;
1491 case 'int+':
1492 $var = max(0, intval($var));
1493 break;
1494 case 'color':
1495 $col = array();
1496 if ($var && !GeneralUtility::inList($this->HTMLcolorList, strtolower($var))) {
1497 $var = preg_replace('/[^A-Fa-f0-9]*/', '', $var);
1498 $useFulHex = strlen($var) > 3;
1499 $col[] = HexDec(substr($var, 0, 1));
1500 $col[] = HexDec(substr($var, 1, 1));
1501 $col[] = HexDec(substr($var, 2, 1));
1502 if ($useFulHex) {
1503 $col[] = HexDec(substr($var, 3, 1));
1504 $col[] = HexDec(substr($var, 4, 1));
1505 $col[] = HexDec(substr($var, 5, 1));
1506 }
1507 $var = substr(('0' . DecHex($col[0])), -1) . substr(('0' . DecHex($col[1])), -1) . substr(('0' . DecHex($col[2])), -1);
1508 if ($useFulHex) {
1509 $var .= substr(('0' . DecHex($col[3])), -1) . substr(('0' . DecHex($col[4])), -1) . substr(('0' . DecHex($col[5])), -1);
1510 }
1511 $var = '#' . strtoupper($var);
1512 }
1513 break;
1514 case 'comment':
1515 if ($var) {
1516 $var = '#';
1517 } else {
1518 $var = '';
1519 }
1520 break;
1521 case 'wrap':
1522 if (isset($Wdata[$key])) {
1523 $var .= '|' . $Wdata[$key];
1524 }
1525 break;
1526 case 'offset':
1527 if (isset($Wdata[$key])) {
1528 $var = intval($var) . ',' . intval($Wdata[$key]);
1529 if (isset($W2data[$key])) {
1530 $var .= ',' . intval($W2data[$key]);
1531 if (isset($W3data[$key])) {
1532 $var .= ',' . intval($W3data[$key]);
1533 if (isset($W4data[$key])) {
1534 $var .= ',' . intval($W4data[$key]);
1535 if (isset($W5data[$key])) {
1536 $var .= ',' . intval($W5data[$key]);
1537 }
1538 }
1539 }
1540 }
1541 }
1542 break;
1543 case 'boolean':
1544 if ($var) {
1545 $var = $typeDat['paramstr'] ? $typeDat['paramstr'] : 1;
1546 }
1547 break;
1548 }
1549 if ($this->ext_printAll || strcmp($theConstants[$key]['value'], $var)) {
1550 // Put value in, if changed.
1551 $this->ext_putValueInConf($key, $var);
1552 }
1553 // Remove the entry because it has been "used"
1554 unset($check[$key]);
1555 } else {
1556 $this->ext_removeValueInConf($key);
1557 }
1558 }
1559 }
1560 }
1561 // Remaining keys in $check indicates fields that are just clicked "on" to be edited. Therefore we get the default value and puts that in the template as a start...
1562 if (!$this->ext_dontCheckIssetValues && is_array($check)) {
1563 foreach ($check as $key => $var) {
1564 if (isset($theConstants[$key])) {
1565 $dValue = $theConstants[$key]['default_value'];
1566 $this->ext_putValueInConf($key, $dValue);
1567 }
1568 }
1569 }
1570 }
1571
1572 /**
1573 * [Describe function...]
1574 *
1575 * @param [type] $id: ...
1576 * @param [type] $perms_clause: ...
1577 * @return [type] ...
1578 * @todo Define visibility
1579 */
1580 public function ext_prevPageWithTemplate($id, $perms_clause) {
1581 $rootLine = BackendUtility::BEgetRootLine($id, $perms_clause ? ' AND ' . $perms_clause : '');
1582 foreach ($rootLine as $p) {
1583 if ($this->ext_getFirstTemplate($p['uid'])) {
1584 return $p;
1585 }
1586 }
1587 }
1588
1589 }