d06cdc9fba8912a1a6743fc5cd836b2dbc5a628e
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / class.tslib_content.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 * Contains classes for Content Rendering based on TypoScript Template configuration
29 *
30 * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
31 * XHTML compliant
32 *
33 * class tslib_cObj : All main TypoScript features, rendering of content objects (cObjects). This class is the backbone of TypoScript Template rendering.
34 * class tslib_controlTable : Makes a table CTABLE (TS cObject)
35 * class tslib_tableOffset : Makes a table-offset (TS)
36 * class tslib_frameset : Generates framesets (TS)
37 *
38 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
39 */
40
41
42
43 /**
44 * This class contains all main TypoScript features.
45 * This includes the rendering of TypoScript content objects (cObjects).
46 * Is the backbone of TypoScript Template rendering.
47 *
48 * There are lots of functions you can use from your include-scripts.
49 * The class "tslib_cObj" is normally instantiated and referred to as "cObj".
50 * When you call your own PHP-code typically through a USER or USER_INT cObject then it is this class that instantiates the object and calls the main method. Before it does so it will set (if you are using classes) a reference to itself in the internal variable "cObj" of the object. Thus you can access all functions and data from this class by $this->cObj->... from within you classes written to be USER or USER_INT content objects.
51 *
52 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
53 * @package TYPO3
54 * @subpackage tslib
55 */
56 class tslib_cObj {
57
58 var $align = array(
59 'center',
60 'right',
61 'left'
62 );
63
64 /**
65 * stdWrap functions in their correct order
66 *
67 * @see stdWrap()
68 */
69 var $stdWrapOrder = array(
70 'stdWrapPreProcess' => 'hook', // this is a placeholder for the first Hook
71 'setContentToCurrent' => 'boolean',
72 'setContentToCurrent.' => 'array',
73 'setCurrent' => 'string',
74 'setCurrent.' => 'array',
75 'lang.' => 'array',
76 'data' => 'getText',
77 'data.' => 'array',
78 'field' => 'fieldName',
79 'field.' => 'array',
80 'current' => 'boolean',
81 'current.' => 'array',
82 'cObject' => 'cObject',
83 'cObject.' => 'array',
84 'numRows.' => 'array',
85 'filelist' => 'dir',
86 'filelist.' => 'array',
87 'preUserFunc' => 'functionName',
88 'stdWrapOverride' => 'hook', // this is a placeholder for the second Hook
89 'override' => 'string',
90 'override.' => 'array',
91 'preIfEmptyListNum' => 'listNum',
92 'preIfEmptyListNum.' => 'array',
93 'ifEmpty' => 'string',
94 'ifEmpty.' => 'array',
95 'ifBlank' => 'string',
96 'ifBlank.' => 'array',
97 'listNum' => 'listNum',
98 'listNum.' => 'array',
99 'trim' => 'boolean',
100 'trim.' => 'array',
101 'stdWrap' => 'stdWrap',
102 'stdWrap.' => 'array',
103 'stdWrapProcess' => 'hook', // this is a placeholder for the third Hook
104 'required' => 'boolean',
105 'required.' => 'array',
106 'if.' => 'array',
107 'fieldRequired' => 'fieldName',
108 'fieldRequired.' => 'array',
109 'csConv' => 'string',
110 'csConv.' => 'array',
111 'parseFunc' => 'objectpath',
112 'parseFunc.' => 'array',
113 'HTMLparser' => 'boolean',
114 'HTMLparser.' => 'array',
115 'split.' => 'array',
116 'replacement.' => 'array',
117 'prioriCalc' => 'boolean',
118 'prioriCalc.' => 'array',
119 'char' => 'integer',
120 'char.' => 'array',
121 'intval' => 'boolean',
122 'intval.' => 'array',
123 'hash' => 'string',
124 'hash.' => 'array',
125 'round' => 'boolean',
126 'round.' => 'array',
127 'numberFormat.' => 'array',
128 'expandList' => 'boolean',
129 'expandList.' => 'array',
130 'date' => 'dateconf',
131 'date.' => 'array',
132 'strftime' => 'strftimeconf',
133 'strftime.' => 'array',
134 'age' => 'boolean',
135 'age.' => 'array',
136 'case' => 'case',
137 'case.' => 'array',
138 'bytes' => 'boolean',
139 'bytes.' => 'array',
140 'substring' => 'parameters',
141 'substring.' => 'array',
142 'removeBadHTML' => 'boolean',
143 'removeBadHTML.' => 'array',
144 'cropHTML' => 'crop',
145 'cropHTML.' => 'array',
146 'stripHtml' => 'boolean',
147 'stripHtml.' => 'array',
148 'crop' => 'crop',
149 'crop.' => 'array',
150 'rawUrlEncode' => 'boolean',
151 'rawUrlEncode.' => 'array',
152 'htmlSpecialChars' => 'boolean',
153 'htmlSpecialChars.' => 'array',
154 'doubleBrTag' => 'string',
155 'doubleBrTag.' => 'array',
156 'br' => 'boolean',
157 'br.' => 'array',
158 'brTag' => 'string',
159 'brTag.' => 'array',
160 'encapsLines.' => 'array',
161 'keywords' => 'boolean',
162 'keywords.' => 'array',
163 'innerWrap' => 'wrap',
164 'innerWrap.' => 'array',
165 'innerWrap2' => 'wrap',
166 'innerWrap2.' => 'array',
167 'fontTag' => 'wrap',
168 'fontTag.' => 'array',
169 'addParams.' => 'array',
170 'textStyle.' => 'array',
171 'tableStyle.' => 'array',
172 'filelink.' => 'array',
173 'preCObject' => 'cObject',
174 'preCObject.' => 'array',
175 'postCObject' => 'cObject',
176 'postCObject.' => 'array',
177 'wrapAlign' => 'align',
178 'wrapAlign.' => 'array',
179 'typolink.' => 'array',
180 'TCAselectItem.' => 'array',
181 'space' => 'space',
182 'space.' => 'array',
183 'spaceBefore' => 'int',
184 'spaceBefore.' => 'array',
185 'spaceAfter' => 'int',
186 'spaceAfter.' => 'array',
187 'wrap' => 'wrap',
188 'wrap.' => 'array',
189 'noTrimWrap' => 'wrap',
190 'noTrimWrap.' => 'array',
191 'wrap2' => 'wrap',
192 'wrap2.' => 'array',
193 'dataWrap' => 'dataWrap',
194 'dataWrap.' => 'array',
195 'prepend' => 'cObject',
196 'prepend.' => 'array',
197 'append' => 'cObject',
198 'append.' => 'array',
199 'wrap3' => 'wrap',
200 'wrap3.' => 'array',
201 'outerWrap' => 'wrap',
202 'outerWrap.' => 'array',
203 'insertData' => 'boolean',
204 'insertData.' => 'array',
205 'offsetWrap' => 'space',
206 'offsetWrap.' => 'array',
207 'postUserFunc' => 'functionName',
208 'postUserFuncInt' => 'functionName',
209 'prefixComment' => 'string',
210 'prefixComment.' => 'array',
211 'editIcons' => 'string',
212 'editIcons.' => 'array',
213 'editPanel' => 'boolean',
214 'editPanel.' => 'array',
215 'stdWrapPostProcess' => 'hook', // this is a placeholder for the last Hook
216 'debug' => 'boolean',
217 'debug.' => 'array',
218 'debugFunc' => 'boolean',
219 'debugFunc.' => 'array',
220 'debugData' => 'boolean',
221 'debugData.' => 'array'
222 );
223
224 /**
225 * Holds ImageMagick parameters and extensions used for compression
226 *
227 * @see IMGTEXT()
228 *
229 * 0= Default
230 * 1= Dont change! (removes all parameters for the image_object!!)
231 * 1x = GIFs
232 * 2x = JPGs
233 */
234 var $image_compression = array(
235 10 => array(
236 'params' => '', 'ext' => 'gif'
237 ),
238 11 => array(
239 'params' => '-colors 128', 'ext' => 'gif'
240 ),
241 12 => array(
242 'params' => '-colors 64', 'ext' => 'gif'
243 ),
244 13 => array(
245 'params' => '-colors 32', 'ext' => 'gif'
246 ),
247 14 => array(
248 'params' => '-colors 16', 'ext' => 'gif'
249 ),
250 15 => array(
251 'params' => '-colors 8', 'ext' => 'gif'
252 ),
253
254 20 => array(
255 'params' => '-quality 100', 'ext' => 'jpg'
256 ),
257 21 => array(
258 'params' => '-quality 90', 'ext' => 'jpg'
259 ),
260 22 => array(
261 'params' => '-quality 80', 'ext' => 'jpg'
262 ),
263 23 => array(
264 'params' => '-quality 70', 'ext' => 'jpg'
265 ),
266 24 => array(
267 'params' => '-quality 60', 'ext' => 'jpg'
268 ),
269 25 => array(
270 'params' => '-quality 50', 'ext' => 'jpg'
271 ),
272 26 => array(
273 'params' => '-quality 40', 'ext' => 'jpg'
274 ),
275 27 => array(
276 'params' => '-quality 30', 'ext' => 'jpg'
277 ),
278 28 => array(
279 'params' => '-quality 20', 'ext' => 'jpg'
280 ),
281
282 30 => array(
283 'params' => '-colors 256', 'ext' => 'png'
284 ),
285 31 => array(
286 'params' => '-colors 128', 'ext' => 'png'
287 ),
288 32 => array(
289 'params' => '-colors 64', 'ext' => 'png'
290 ),
291 33 => array(
292 'params' => '-colors 32', 'ext' => 'png'
293 ),
294 34 => array(
295 'params' => '-colors 16', 'ext' => 'png'
296 ),
297 35 => array(
298 'params' => '-colors 8', 'ext' => 'png'
299 ),
300 39 => array(
301 'params' => '', 'ext' => 'png'
302 ),
303 );
304
305 /**
306 * ImageMagick parameters for image effects
307 *
308 * @see IMGTEXT()
309 */
310 var $image_effects = array(
311 1 => '-rotate 90',
312 2 => '-rotate 270',
313 3 => '-rotate 180',
314 10 => '-colorspace GRAY',
315 11 => '-sharpen 70',
316 20 => '-normalize',
317 23 => '-contrast',
318 25 => '-gamma 1.3',
319 26 => '-gamma 0.8'
320 );
321
322 /**
323 * Loaded with the current data-record.
324 *
325 * If the instance of this class is used to render records from the database those records are found in this array.
326 * The function stdWrap has TypoScript properties that fetch field-data from this array.
327 * @see init()
328 */
329 var $data = array();
330 protected $table = '';
331 var $oldData = array(); // Used for backup...
332 var $alternativeData = ''; // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
333 var $parameters = array(); // Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
334 var $currentValKey = 'currentValue_kidjls9dksoje';
335 var $currentRecord = ''; // This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
336 var $currentRecordTotal = 0; // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query.
337 var $currentRecordNumber = 0; // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering.
338 var $parentRecordNumber = 0; // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering.
339 var $parentRecord = array(); // If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
340 var $regObj; // This may be set as a reference to the calling object of eg. cObjGetSingle. Anyway, just use it as you like. It's used in productsLib.inc for example.
341
342
343 // internal
344 var $INT_include = 0; // Is set to 1 if the instance of this cObj is executed from a PHP_SCRIPT_INT -include script (see pagegen, bottom of document)
345 var $checkPid_cache = array(); // This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request.
346 var $checkPid_badDoktypeList = '255';
347 var $lastTypoLinkUrl = ''; // This will be set by typoLink() to the url of the most recent link created.
348 var $lastTypoLinkTarget = ''; // DO. link target.
349 var $lastTypoLinkLD = array();
350 var $substMarkerCache = array(); // Caching substituteMarkerArrayCached function
351 var $recordRegister = array(); // array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
352 var $cObjHookObjectsArr = array(); // Containig hooks for userdefined cObjects
353 protected $stdWrapHookObjects = array(); // Containing hook objects for stdWrap
354 protected $getImgResourceHookObjects; // Containing hook objects for getImgResource
355
356 /**
357 * @var array with members of tslib_content_abstract
358 */
359 protected $contentObjects = array();
360
361 /**
362 * Set to TRUE by doConvertToUserIntObject() if USER object wants to become USER_INT
363 */
364 public $doConvertToUserIntObject = FALSE;
365
366 /**
367 * Indicates current object type. Can hold one of OBJECTTYPE_ constants or FALSE.
368 * The value is set and reset inside USER() function. Any time outside of
369 * USER() it is FALSE.
370 */
371 protected $userObjectType = FALSE;
372
373 /**
374 * Indicates that object type is USER.
375 *
376 * @see tslib_cObjh::$userObjectType
377 */
378 const OBJECTTYPE_USER_INT = 1;
379
380 /**
381 * Indicates that object type is USER.
382 *
383 * @see tslib_cObjh::$userObjectType
384 */
385 const OBJECTTYPE_USER = 2;
386
387 /**
388 * Class constructor.
389 * Well, it has to be called manually since it is not a real constructor function.
390 * So after making an instance of the class, call this function and pass to it a database record and the tablename from where the record is from. That will then become the "current" record loaded into memory and accessed by the .fields property found in eg. stdWrap.
391 *
392 * @param array $data the record data that is rendered.
393 * @param string $table the table that the data record is from.
394 * @return void
395 */
396 function start($data, $table = '') {
397 global $TYPO3_CONF_VARS;
398 $this->data = $data;
399 $this->table = $table;
400 $this->currentRecord = $table ? $table . ':' . $this->data['uid'] : '';
401 $this->parameters = array();
402 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
403 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
404 $this->cObjHookObjectsArr[$classArr[0]] = t3lib_div::getUserObj($classArr[1]);
405 }
406 }
407
408 $this->stdWrapHookObjects = array();
409 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
410 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
411 $hookObject = t3lib_div::getUserObj($classData);
412
413 if (!($hookObject instanceof tslib_content_stdWrapHook)) {
414 throw new UnexpectedValueException(
415 $classData . ' must implement interface tslib_content_stdWrapHook',
416 1195043965
417 );
418 }
419
420 $this->stdWrapHookObjects[] = $hookObject;
421 }
422 }
423
424 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
425 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
426 $postInitializationProcessor = t3lib_div::getUserObj($classData);
427
428 if (!($postInitializationProcessor instanceof tslib_content_PostInitHook)) {
429 throw new UnexpectedValueException(
430 $classData . ' must implement interface tslib_content_PostInitHook',
431 1274563549
432 );
433 }
434
435 $postInitializationProcessor->postProcessContentObjectInitialization($this);
436 }
437 }
438 }
439
440 /**
441 * Clone helper.
442 *
443 * Resets the references to the TypoScript Content Object implementation
444 * objects of tslib_content_*. Otherwise they would still point to the
445 * original tslib_cObj instance's tslib_content_* instances, they in return
446 * would back-reference to the original tslib_cObj instance instead of the
447 * newly cloned tslib_cObj instance.
448 *
449 * @see http://bugs.typo3.org/view.php?id=16568
450 */
451 public function __clone() {
452 $this->contentObjects = array();
453 }
454
455 /**
456 * Gets the 'getImgResource' hook objects.
457 * The first call initializes the accordant objects.
458 *
459 * @return array The 'getImgResource' hook objects (if any)
460 */
461 protected function getGetImgResourceHookObjects() {
462 if (!isset($this->getImgResourceHookObjects)) {
463 $this->getImgResourceHookObjects = array();
464
465 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
466 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
467 $hookObject = t3lib_div::getUserObj($classData);
468
469 if (!($hookObject instanceof tslib_cObj_getImgResourceHook)) {
470 throw new UnexpectedValueException(
471 '$hookObject must implement interface tslib_cObj_getImgResourceHook',
472 1218636383
473 );
474 }
475
476 $this->getImgResourceHookObjects[] = $hookObject;
477 }
478 }
479 }
480
481 return $this->getImgResourceHookObjects;
482 }
483
484 /**
485 * Sets the internal variable parentRecord with information about current record.
486 * If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
487 *
488 * @param array $data: The record array
489 * @param string $currentRecord: This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
490 * @return void
491 * @access private
492 */
493 function setParent($data, $currentRecord) {
494 $this->parentRecord = array(
495 'data' => $data,
496 'currentRecord' => $currentRecord
497 );
498 }
499
500
501
502 /***********************************************
503 *
504 * CONTENT_OBJ:
505 *
506 ***********************************************/
507
508 /**
509 * Returns the "current" value.
510 * The "current" value is just an internal variable that can be used by functions to pass a single value on to another function later in the TypoScript processing.
511 * It's like "load accumulator" in the good old C64 days... basically a "register" you can use as you like.
512 * The TSref will tell if functions are setting this value before calling some other object so that you know if it holds any special information.
513 *
514 * @return mixed The "current" value
515 */
516 function getCurrentVal() {
517 return $this->data[$this->currentValKey];
518 }
519
520 /**
521 * Sets the "current" value.
522 *
523 * @param mixed The variable that you want to set as "current"
524 * @return void
525 * @see getCurrentVal()
526 */
527 function setCurrentVal($value) {
528 $this->data[$this->currentValKey] = $value;
529 }
530
531 /**
532 * Rendering of a "numerical array" of cObjects from TypoScript
533 * Will call ->cObjGetSingle() for each cObject found and accumulate the output.
534 *
535 * @param array $setup: array with cObjects as values.
536 * @param string $addKey: A prefix for the debugging information
537 * @return string Rendered output from the cObjects in the array.
538 * @see cObjGetSingle()
539 */
540 function cObjGet($setup, $addKey = '') {
541 if (is_array($setup)) {
542 $sKeyArray = t3lib_TStemplate::sortedKeyList($setup);
543 $content = '';
544 foreach ($sKeyArray as $theKey) {
545 $theValue = $setup[$theKey];
546 if (intval($theKey) && !strstr($theKey, '.')) {
547 $conf = $setup[$theKey . '.'];
548 $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey); // Get the contentObject
549 }
550 }
551 return $content;
552 }
553 }
554
555 /**
556 * Renders a content object
557 *
558 * @param string The content object name, eg. "TEXT" or "USER" or "IMAGE"
559 * @param array The array with TypoScript properties for the content object
560 * @param string A string label used for the internal debugging tracking.
561 * @return string cObject output
562 */
563 function cObjGetSingle($name, $conf, $TSkey = '__') {
564 global $TYPO3_CONF_VARS;
565
566 $content = '';
567 // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
568 $GLOBALS['TSFE']->cObjectDepthCounter--;
569 if ($GLOBALS['TSFE']->cObjectDepthCounter > 0) {
570 $name = trim($name);
571 if ($GLOBALS['TT']->LR)
572 $GLOBALS['TT']->push($TSkey, $name);
573
574 // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
575 if (substr($name, 0, 1) == '<') {
576 $key = trim(substr($name, 1));
577 $cF = t3lib_div::makeInstance('t3lib_TSparser');
578 // $name and $conf is loaded with the referenced values.
579 $old_conf = $conf;
580 list ($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
581 if (is_array($old_conf) && count($old_conf)) {
582 $conf = $this->joinTSarrays($conf, $old_conf);
583 }
584 // Getting the cObject
585 $GLOBALS['TT']->incStackPointer();
586 $content .= $this->cObjGetSingle($name, $conf, $key);
587 $GLOBALS['TT']->decStackPointer();
588 } else {
589
590 $hooked = FALSE;
591 // Application defined cObjects
592 foreach ($this->cObjHookObjectsArr as $cObjName => $hookObj) {
593 if (($name === $cObjName) && method_exists($hookObj, 'cObjGetSingleExt')) {
594 $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
595 $hooked = TRUE;
596 }
597 }
598 if (!$hooked) {
599 $contentObject = $this->getContentObject($name);
600 if ($contentObject) {
601 $content .= $contentObject->render($conf);
602 } else {
603 // call hook functions for extra processing
604 if ($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
605 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
606 $hookObject = t3lib_div::getUserObj($classData);
607
608 if (!($hookObject instanceof tslib_content_cObjGetSingleHook)) {
609 throw new UnexpectedValueException(
610 '$hookObject must implement interface tslib_content_cObjGetSingleHook',
611 1195043731
612 );
613 }
614 /* @var $hookObject tslib_content_cObjGetSingleHook */
615 $content .= $hookObject->getSingleContentObject($name, (array) $conf, $TSkey, $this);
616 }
617 } else {
618 // log error in AdminPanel
619 $warning = sprintf('Content Object "%s" does not exist', $name);
620 $GLOBALS['TT']->setTSlogMessage($warning, 2);
621 }
622 }
623 }
624 }
625 if ($GLOBALS['TT']->LR)
626 $GLOBALS['TT']->pull($content);
627 }
628 // Increasing on exit...
629 $GLOBALS['TSFE']->cObjectDepthCounter++;
630 return $content;
631 }
632
633 /**
634 * Returns a new content object of type $name.
635 *
636 * @param string $name
637 * @return tslib_content_abstract
638 */
639 public function getContentObject($name) {
640 $classMapping = array(
641 'HTML' => 'Html',
642 'TEXT' => 'Text',
643 'CASE' => 'Case',
644 'CLEARGIF' => 'ClearGif',
645 'COBJ_ARRAY' => 'ContentObjectArray',
646 'COA' => 'ContentObjectArray',
647 'COA_INT' => 'ContentObjectArrayInternal',
648 'USER' => 'User',
649 'USER_INT' => 'UserInternal',
650 'FILE' => 'File',
651 'IMAGE' => 'Image',
652 'IMG_RESOURCE' => 'ImageResource',
653 'IMGTEXT' => 'ImageText',
654 'CONTENT' => 'Content',
655 'RECORDS' => 'Records',
656 'HMENU' => 'HierarchicalMenu',
657 'CTABLE' => 'ContentTable',
658 'OTABLE' => 'OffsetTable',
659 'COLUMNS' => 'Columns',
660 'HRULER' => 'HorizontalRuler',
661 'CASEFUNC' => 'Case',
662 'LOAD_REGISTER' => 'LoadRegister',
663 'RESTORE_REGISTER' => 'RestoreRegister',
664 'FORM' => 'Form',
665 'SEARCHRESULT' => 'SearchResult',
666 'PHP_SCRIPT' => 'PhpScript',
667 'PHP_SCRIPT_INT' => 'PhpScriptInternal',
668 'PHP_SCRIPT_EXT' => 'PhpScriptExternal',
669 'TEMPLATE' => 'Template',
670 'FLUIDTEMPLATE' => 'FluidTemplate',
671 'MULTIMEDIA' => 'Multimedia',
672 'MEDIA' => 'Media',
673 'SWFOBJECT' => 'ShockwaveFlashObject',
674 'QTOBJECT' => 'QuicktimeObject',
675 'SVG' => 'ScalableVectorGraphics',
676 'EDITPANEL' => 'EditPanel',
677 );
678 $name = $classMapping[$name];
679
680 if (!array_key_exists($name, $this->contentObjects)) {
681 try {
682 $this->contentObjects[$name] = t3lib_div::makeInstance('tslib_content_' . $name, $this);
683 } catch (ReflectionException $e) {
684 $this->contentObjects[$name] = NULL;
685 }
686 }
687 return $this->contentObjects[$name];
688 }
689
690
691 /********************************************
692 *
693 * Functions rendering content objects (cObjects)
694 *
695 ********************************************/
696
697 /**
698 * Rendering the cObject, HTML
699 *
700 * @param array array of TypoScript properties
701 * @return string Output
702 */
703 function HTML($conf) {
704 return $this->getContentObject('HTML')->render($conf);
705 }
706
707 /**
708 * Rendering the cObject, TEXT
709 *
710 * @param array array of TypoScript properties
711 * @return string Output
712 */
713 function TEXT($conf) {
714 return $this->getContentObject('TEXT')->render($conf);
715 }
716
717 /**
718 * Rendering the cObject, CLEARGIF
719 *
720 * @param array array of TypoScript properties
721 * @return string Output
722 */
723 function CLEARGIF($conf) {
724 return $this->getContentObject('CLEARGIF')->render($conf);
725 }
726
727 /**
728 * Rendering the cObject, COBJ_ARRAY / COA and COBJ_ARRAY_INT
729 *
730 * @param array array of TypoScript properties
731 * @param string If "INT" then the cObject is a "COBJ_ARRAY_INT" (non-cached), otherwise just "COBJ_ARRAY" (cached)
732 * @return string Output
733 */
734 function COBJ_ARRAY($conf, $ext = '') {
735 if ($ext === 'INT') {
736 return $this->getContentObject('COA_INT')->render($conf);
737 } else {
738 return $this->getContentObject('COA')->render($conf);
739 }
740 }
741
742 /**
743 * Rendering the cObject, USER and USER_INT
744 *
745 * @param array array of TypoScript properties
746 * @param string If "INT" then the cObject is a "USER_INT" (non-cached), otherwise just "USER" (cached)
747 * @return string Output
748 */
749 function USER($conf, $ext = '') {
750 if ($ext === 'INT') {
751 return $this->getContentObject('USER_INT')->render($conf);
752 } else {
753 return $this->getContentObject('USER')->render($conf);
754 }
755 }
756
757 /**
758 * Retrieves a type of object called as USER or USER_INT. Object can detect their
759 * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the
760 * current object execution. In all other cases it will return FALSE to indicate
761 * a call out of context.
762 *
763 * @return mixed One of OBJECTTYPE_ class constants or FALSE
764 */
765 public function getUserObjectType() {
766 return $this->userObjectType;
767 }
768
769 /**
770 * Sets the user object type
771 *
772 * @param mixed $userObjectType
773 * @return void
774 */
775 public function setUserObjectType($userObjectType) {
776 $this->userObjectType = $userObjectType;
777 }
778
779 /**
780 * Requests the current USER object to be converted to USER_INT.
781 *
782 * @return void
783 */
784 public function convertToUserIntObject() {
785 if ($this->userObjectType !== self::OBJECTTYPE_USER) {
786 $GLOBALS['TT']->setTSlogMessage('tslib_cObj::convertToUserIntObject() ' . 'is called in the wrong context or for the wrong object type', 2);
787 } else {
788 $this->doConvertToUserIntObject = TRUE;
789 }
790 }
791
792 /**
793 * Rendering the cObject, FILE
794 *
795 * @param array array of TypoScript properties
796 * @return string Output
797 */
798 function FILE($conf) {
799 return $this->getContentObject('FILE')->render($conf);
800 }
801
802 /**
803 * Rendering the cObject, IMAGE
804 *
805 * @param array array of TypoScript properties
806 * @return string Output
807 * @see cImage()
808 */
809 function IMAGE($conf) {
810 return $this->getContentObject('IMAGE')->render($conf);
811 }
812
813 /**
814 * Rendering the cObject, IMG_RESOURCE
815 *
816 * @param array array of TypoScript properties
817 * @return string Output
818 * @see getImgResource()
819 */
820 function IMG_RESOURCE($conf) {
821 return $this->getContentObject('IMG_RESOURCE')->render($conf);
822 }
823
824 /**
825 * Rendering the cObject, IMGTEXT
826 *
827 * @param array array of TypoScript properties
828 * @return string Output
829 */
830 function IMGTEXT($conf) {
831 return $this->getContentObject('IMGTEXT')->render($conf);
832 }
833
834 /**
835 * Rendering the cObject, CONTENT
836 *
837 * @param array array of TypoScript properties
838 * @return string Output
839 */
840 function CONTENT($conf) {
841 return $this->getContentObject('CONTENT')->render($conf);
842 }
843
844 /**
845 * Rendering the cObject, RECORDS
846 *
847 * @param array array of TypoScript properties
848 * @return string Output
849 */
850 function RECORDS($conf) {
851 return $this->getContentObject('RECORDS')->render($conf);
852 }
853
854 /**
855 * Rendering the cObject, HMENU
856 *
857 * @param array array of TypoScript properties
858 * @return string Output
859 */
860 function HMENU($conf) {
861 return $this->getContentObject('HMENU')->render($conf);
862 }
863
864 /**
865 * Rendering the cObject, CTABLE
866 *
867 * @param array array of TypoScript properties
868 * @return string Output
869 */
870 function CTABLE($conf) {
871 return $this->getContentObject('CTABLE')->render($conf);
872 }
873
874 /**
875 * Rendering the cObject, OTABLE
876 *
877 * @param array array of TypoScript properties
878 * @return string Output
879 */
880 function OTABLE($conf) {
881 return $this->getContentObject('OTABLE')->render($conf);
882 }
883
884 /**
885 * Rendering the cObject, COLUMNS
886 *
887 * @param array array of TypoScript properties
888 * @return string Output
889 */
890 function COLUMNS($conf) {
891 return $this->getContentObject('COLUMNS')->render($conf);
892 }
893
894 /**
895 * Rendering the cObject, HRULER
896 *
897 * @param array array of TypoScript properties
898 * @return string Output
899 */
900 function HRULER($conf) {
901 return $this->getContentObject('HRULER')->render($conf);
902 }
903
904 /**
905 * Rendering the cObject, CASE
906 *
907 * @param array array of TypoScript properties
908 * @return string Output
909 */
910 function CASEFUNC($conf) {
911 return $this->getContentObject('CASE')->render($conf);
912 }
913
914 /**
915 * Rendering the cObject, LOAD_REGISTER and RESTORE_REGISTER
916 * NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
917 *
918 * @param array array of TypoScript properties
919 * @param string If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER"
920 * @return string Empty string (the cObject only sets internal data!)
921 */
922 function LOAD_REGISTER($conf, $name) {
923 if ($name === 'RESTORE_REGISTER') {
924 return $this->getContentObject('RESTORE_REGISTER')->render($conf);
925 } else {
926 return $this->getContentObject('LOAD_REGISTER')->render($conf);
927 }
928 }
929
930 /**
931 * Rendering the cObject, FORM
932 *
933 * @param array array of TypoScript properties
934 * @param array Alternative formdata overriding whatever comes from TypoScript
935 * @return string Output
936 */
937 function FORM($conf, $formData = '') {
938 return $this->getContentObject('FORM')->render($conf, $formData);
939 }
940
941 /**
942 * Rendering the cObject, SEARCHRESULT
943 *
944 * @param array array of TypoScript properties
945 * @return string Output
946 */
947 function SEARCHRESULT($conf) {
948 return $this->getContentObject('SEARCHRESULT')->render($conf);
949 }
950
951 /**
952 * Rendering the cObject, PHP_SCRIPT, PHP_SCRIPT_INT and PHP_SCRIPT_EXT
953 *
954 * @param array array of TypoScript properties
955 * @param string If "INT", then rendering "PHP_SCRIPT_INT"; If "EXT", then rendering "PHP_SCRIPT_EXT"; Default is rendering "PHP_SCRIPT" (cached)
956 * @return string Output
957 */
958 function PHP_SCRIPT($conf, $ext = '') {
959 if ($ext === 'INT' || $ext === 'EXT') {
960 return $this->getContentObject('PHP_SCRIPT_INT')->render($conf);
961 } else {
962 return $this->getContentObject('PHP_SCRIPT')->render($conf);
963 }
964 }
965
966 /**
967 * Rendering the cObject, TEMPLATE
968 *
969 * @param array array of TypoScript properties
970 * @return string Output
971 * @see substituteMarkerArrayCached()
972 */
973 function TEMPLATE($conf) {
974 return $this->getContentObject('TEMPLATE')->render($conf);
975 }
976
977 /**
978 * Rendering the cObject, FLUIDTEMPLATE
979 *
980 * @param array array of TypoScript properties
981 * @return string the HTML output
982 * @author Steffen Ritter <info@steffen-ritter.net>
983 * @author Benjamin Mack <benni@typo3.org>
984 */
985 protected function FLUIDTEMPLATE(array $conf) {
986 return $this->getContentObject('FLUIDTEMPLATE')->render($conf);
987 }
988
989 /**
990 * Rendering the cObject, MULTIMEDIA
991 *
992 * @param array array of TypoScript properties
993 * @return string Output
994 */
995 function MULTIMEDIA($conf) {
996 return $this->getContentObject('MULTIMEDIA')->render($conf);
997 }
998
999 /**
1000 * Rendering the cObject, MEDIA
1001 *
1002 * @param array array of TypoScript properties
1003 * @return string Output
1004 */
1005 public function MEDIA($conf) {
1006 return $this->getContentObject('MEDIA')->render($conf);
1007 }
1008
1009 /**
1010 * Rendering the cObject, SWFOBJECT
1011 *
1012 * @param array array of TypoScript properties
1013 * @return string Output
1014 */
1015 public function SWFOBJECT($conf) {
1016 return $this->getContentObject('SWFOBJECT')->render($conf);
1017 }
1018
1019 /**
1020 * Rendering the cObject, QTOBJECT
1021 *
1022 * @param array array of TypoScript properties
1023 * @return string Output
1024 */
1025 public function QTOBJECT($conf) {
1026 return $this->getContentObject('QTOBJECT')->render($conf);
1027 }
1028
1029 /**
1030 * Rendering the cObject, SVG
1031 *
1032 * @param array array of TypoScript properties
1033 * @return string Output
1034 */
1035 public function SVG($conf) {
1036 return $this->getContentObject('SVG')->render($conf);
1037 }
1038
1039 /************************************
1040 *
1041 * Various helper functions for content objects:
1042 *
1043 ************************************/
1044
1045
1046 /**
1047 * Converts a given config in Flexform to a conf-array
1048 * @param string Flexform data
1049 * @param array array to write the data into, by reference
1050 * @param boolean is set if called recursive. Don't call function with this parameter, it's used inside the function only
1051 * @access public
1052 *
1053 */
1054 public function readFlexformIntoConf($flexData, &$conf, $recursive = FALSE) {
1055 if ($recursive === FALSE) {
1056 $flexData = t3lib_div::xml2array($flexData, 'T3');
1057 }
1058
1059 if (is_array($flexData)) {
1060 if (isset($flexData['data']['sDEF']['lDEF'])) {
1061 $flexData = $flexData['data']['sDEF']['lDEF'];
1062 }
1063
1064 foreach ($flexData as $key => $value) {
1065 if (is_array($value['el']) && count($value['el']) > 0) {
1066 foreach ($value['el'] as $ekey => $element) {
1067 if (isset($element['vDEF'])) {
1068 $conf[$ekey] = $element['vDEF'];
1069 } else {
1070 if (is_array($element)) {
1071 $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
1072 } else {
1073 $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
1074 }
1075 }
1076 }
1077 } else {
1078 $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
1079 }
1080 if ($value['vDEF']) {
1081 $conf[$key] = $value['vDEF'];
1082 }
1083 }
1084 }
1085 }
1086
1087
1088 /**
1089 * Returns all parents of the given PID (Page UID) list
1090 *
1091 * @param string A list of page Content-Element PIDs (Page UIDs) / stdWrap
1092 * @param array stdWrap array for the list
1093 * @return string A list of PIDs
1094 * @access private
1095 */
1096 function getSlidePids($pidList, $pidConf) {
1097 $pidList = isset($pidConf)
1098 ? trim($this->stdWrap($pidList, $pidConf))
1099 : trim($pidList);
1100 if (!strcmp($pidList, '')) {
1101 $pidList = 'this';
1102 }
1103 if (trim($pidList)) {
1104 $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $pidList));
1105 $listArr = $this->checkPidArray($listArr);
1106 }
1107 $pidList = array();
1108 if (is_array($listArr) && count($listArr)) {
1109 foreach ($listArr as $uid) {
1110 $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
1111 if (!$page['is_siteroot']) {
1112 $pidList[] = $page['pid'];
1113 }
1114 }
1115 }
1116 return implode(',', $pidList);
1117 }
1118
1119 /**
1120 * Returns a default value for a form field in the FORM cObject.
1121 * Page CANNOT be cached because that would include the inserted value for the current user.
1122 *
1123 * @param boolean If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned.
1124 * @param string $fieldName: The POST var name to get default value for
1125 * @param string $defaultVal: The current default value
1126 * @return string The default value, either from INPUT var or the current default, based on whether caching is enabled or not.
1127 * @access private
1128 */
1129 function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
1130 if (!$GLOBALS['TSFE']->no_cache || (!isset($_POST[$fieldName]) && !isset($_GET[$fieldName])) || $noValueInsert) {
1131 return $defaultVal;
1132 } else {
1133 return t3lib_div::_GP($fieldName);
1134 }
1135 }
1136
1137 /**
1138 * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
1139 * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript.
1140 * This function is called by "$this->cImage($conf['file'],$conf);" from IMAGE().
1141 *
1142 * @param string File TypoScript resource
1143 * @param array TypoScript configuration properties
1144 * @return string <img> tag, (possibly wrapped in links and other HTML) if any image found.
1145 * @access private
1146 * @see IMAGE()
1147 */
1148 function cImage($file, $conf) {
1149 $info = $this->getImgResource($file, $conf['file.']);
1150 $GLOBALS['TSFE']->lastImageInfo = $info;
1151 if (is_array($info)) {
1152 $info[3] = t3lib_div::png_to_gif_by_imagemagick($info[3]);
1153 $GLOBALS['TSFE']->imagesOnPage[] = $info[3]; // This array is used to collect the image-refs on the page...
1154
1155
1156 $altParam = $this->getAltParam($conf);
1157 if($conf['params'] && !isset($conf['params.'])) {
1158 $params = ' ' . $conf['params'];
1159 } else {
1160 $params = isset($conf['params.'])
1161 ? ' ' . $this->stdWrap($conf['params'], $conf['params.'])
1162 : '';
1163 }
1164 $theValue = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix .
1165 t3lib_div::rawUrlEncodeFP($info[3])) . '" width="' . $info[0] . '" height="' . $info[1] . '"' .
1166 $this->getBorderAttr(' border="' . intval($conf['border']) . '"') .
1167 $params .
1168 ($altParam) . ' />';
1169 $linkWrap = isset($conf['linkWrap.'])
1170 ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.'])
1171 : $conf['linkWrap'];
1172 if ($linkWrap) {
1173 $theValue = $this->linkWrap($theValue, $linkWrap);
1174 } elseif ($conf['imageLinkWrap']) {
1175 $theValue = $this->imageLinkWrap($theValue, $info['origFile'], $conf['imageLinkWrap.']);
1176 }
1177 $wrap = isset($conf['wrap.'])
1178 ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
1179 : $conf['wrap'];
1180 if($wrap) {
1181 $theValue = $this->wrap($theValue, $conf['wrap']);
1182 }
1183 return $theValue;
1184 }
1185 }
1186
1187 /**
1188 * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict, xhtml_11, xhtml_2 or html5
1189 * or if the config parameter 'disableImgBorderAttr' is not set.
1190 *
1191 * @param string the border attribute
1192 * @return string the border attribute
1193 */
1194 function getBorderAttr($borderAttr) {
1195 if (! t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype) &&
1196 $GLOBALS['TSFE']->config['config']['doctype'] != 'html5' &&
1197 ! $GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) {
1198 return $borderAttr;
1199 }
1200 }
1201
1202 /**
1203 * Wraps the input string in link-tags that opens the image in a new window.
1204 *
1205 * @param string String to wrap, probably an <img> tag
1206 * @param string The original image file
1207 * @param array TypoScript properties for the "imageLinkWrap" function
1208 * @return string The input string, $string, wrapped as configured.
1209 * @see cImage()
1210 */
1211 function imageLinkWrap($string, $imageFile, $conf) {
1212 $a1 = '';
1213 $a2 = '';
1214 $content = $string;
1215 $enable = isset($conf['enable.'])
1216 ? $this->stdWrap($conf['enable'], $conf['enable.'])
1217 : $conf['enable'];
1218 if ($enable) {
1219 $content = $this->typolink($string, $conf['typolink.']);
1220 if(isset($conf['file.'])) {
1221 $imageFile = $this->stdWrap($imageFile, $conf['file.']);
1222 }
1223
1224 // imageFileLink:
1225 if ($content == $string && @is_file($imageFile)) {
1226 $parameterNames = array('width', 'height', 'effects', 'alternativeTempPath', 'bodyTag', 'title', 'wrap');
1227 $parameters = array();
1228
1229 $sample = isset($conf['sample.'])
1230 ? $this->stdWrap($conf['sample'], $conf['sample.'])
1231 : $conf['sample'];
1232 if ($sample) {
1233 $parameters['sample'] = 1;
1234 }
1235
1236 foreach ($parameterNames as $parameterName) {
1237 if(isset($conf[$parameterName.'.'])) {
1238 $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName.'.']);
1239 }
1240 if (isset($conf[$parameterName]) && $conf[$parameterName]) {
1241 $parameters[$parameterName] = $conf[$parameterName];
1242 }
1243 }
1244
1245 $parametersEncoded = base64_encode(serialize($parameters));
1246
1247 $md5_value = t3lib_div::hmac(
1248 implode(
1249 '|',
1250 array($imageFile, $parametersEncoded)
1251 )
1252 );
1253
1254 $params = '&md5=' . $md5_value;
1255 foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
1256 $params .= '&parameters[' . $index . ']=' . rawurlencode($chunk);
1257 }
1258
1259 $url = $GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . rawurlencode($imageFile) . $params;
1260
1261 $directImageLink = isset($conf['directImageLink.'])
1262 ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.'])
1263 : $conf['directImageLink'];
1264 if ($directImageLink) {
1265 $imgResourceConf = array(
1266 'file' => $imageFile,
1267 'file.' => $conf
1268 );
1269 $url = $this->IMG_RESOURCE($imgResourceConf);
1270 if (!$url) {
1271 // if no imagemagick / gm is available
1272 $url = $imageFile;
1273 }
1274 }
1275
1276 // Create TARGET-attribute only if the right doctype is used
1277 if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
1278 $target = isset($conf['target.'])
1279 ? $this->stdWrap($conf['target'], $conf['target.'])
1280 : $conf['target'];
1281 if ($target) {
1282 $target = sprintf(' target="%s"', $target);
1283 } else {
1284 $target = ' target="thePicture"';
1285 }
1286 } else {
1287 $target = '';
1288 }
1289 $conf['JSwindow'] = isset($conf['JSwindow.'])
1290 ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.'])
1291 : $conf['JSwindow'];
1292 if ($conf['JSwindow']) {
1293 if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
1294 $altUrl = isset($conf['JSwindow.']['altUrl.'])
1295 ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.'])
1296 : $conf['JSwindow.']['altUrl'];
1297 if ($altUrl) {
1298 $url = $altUrl .
1299 ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' .
1300 rawurlencode($imageFile) . $params);
1301 }
1302 }
1303 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
1304 $gifCreator->init();
1305 $gifCreator->mayScaleUp = 0;
1306
1307 $dims = $gifCreator->getImageScale($gifCreator->getImageDimensions($imageFile), $conf['width'], $conf['height'], '');
1308 $JSwindowExpand = isset($conf['JSwindow.']['expand.'])
1309 ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.'])
1310 : $conf['JSwindow.']['expand'];
1311 $offset = t3lib_div::intExplode(',', $JSwindowExpand . ',');
1312
1313 $newWindow = isset($conf['JSwindow.']['newWindow.'])
1314 ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.'])
1315 : $conf['JSwindow.']['newWindow'];
1316 $a1 = '<a href="' . htmlspecialchars($url) . '" onclick="' .
1317 htmlspecialchars('openPic(\'' . $GLOBALS['TSFE']->baseUrlWrap($url) . '\',\'' .
1318 ($newWindow ? md5($url) : 'thePicture') . '\',\'width=' .
1319 ($dims[0] + $offset[0]) . ',height=' . ($dims[1] + $offset[1]) .
1320 ',status=0,menubar=0\'); return false;') . '"' .
1321 $target . $GLOBALS['TSFE']->ATagParams . '>';
1322 $a2 = '</a>';
1323 $GLOBALS['TSFE']->setJS('openPic');
1324 } else {
1325 $conf['linkParams.']['parameter'] = $url;
1326 $string = $this->typoLink($string, $conf['linkParams.']);
1327 }
1328
1329 if(isset($conf['stdWrap.'])) {
1330 $string = $this->stdWrap($string, $conf['stdWrap.']);
1331 }
1332
1333 $content = $a1 . $string . $a2;
1334 }
1335 }
1336
1337 return $content;
1338 }
1339
1340 /**
1341 * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is.
1342 *
1343 * @param string The filename, being a TypoScript resource data type
1344 * @param string Additional parameters (attributes). Default is empty alt and title tags.
1345 * @return string If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string
1346 * @see FILE()
1347 */
1348 function fileResource($fName, $addParams = 'alt="" title=""') {
1349 $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName);
1350 if ($incFile) {
1351 $fileinfo = t3lib_div::split_fileref($incFile);
1352 if (t3lib_div::inList('jpg,gif,jpeg,png', $fileinfo['fileext'])) {
1353 $imgFile = $incFile;
1354 $imgInfo = @getImageSize($imgFile);
1355 return '<img src="' . $GLOBALS['TSFE']->absRefPrefix . $imgFile .
1356 '" width="' . $imgInfo[0] . '" height="' . $imgInfo[1] . '"' .
1357 $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />';
1358 } elseif (filesize($incFile) < 1024 * 1024) {
1359 return $GLOBALS['TSFE']->tmpl->fileContent($incFile);
1360 }
1361 }
1362 }
1363
1364 /**
1365 * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value.
1366 * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content.
1367 * Therefore you should call this function with the last-changed timestamp of any element you display.
1368 *
1369 * @param integer Unix timestamp (number of seconds since 1970)
1370 * @return void
1371 * @see tslib_fe::setSysLastChanged()
1372 */
1373 function lastChanged($tstamp) {
1374 $tstamp = intval($tstamp);
1375 if ($tstamp > intval($GLOBALS['TSFE']->register['SYS_LASTCHANGED'])) {
1376 $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp;
1377 }
1378 }
1379
1380 /**
1381 * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well.
1382 * The "linkWrap" data type means that this function will find any integer encapsulated in {} (curly braces) in the first wrap part and substitute it with the corresponding page uid from the rootline where the found integer is pointing to the key in the rootline. See link below.
1383 *
1384 * @param string Input string
1385 * @param string A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string
1386 * @return string Wrapped output string
1387 * @see wrap(), cImage(), FILE()
1388 */
1389 function linkWrap($content, $wrap) {
1390 $wrapArr = explode('|', $wrap);
1391 if (preg_match('/\{([0-9]*)\}/', $wrapArr[0], $reg)) {
1392 if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) {
1393 $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
1394 }
1395 }
1396 return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
1397 }
1398
1399 /**
1400 * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element.
1401 * From the $conf array it implements the properties "altText", "titleText" and "longdescURL"
1402 *
1403 * @param array TypoScript configuration properties
1404 * @param boolean If set, the longdesc attribute will be generated - must only be used for img elements!
1405 * @return string Parameter string containing alt and title parameters (if any)
1406 * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink()
1407 */
1408 function getAltParam($conf, $longDesc = TRUE) {
1409 $altText = isset($conf['altText.'])
1410 ? trim($this->stdWrap($conf['altText'], $conf['altText.']))
1411 : trim($conf['altText']);
1412 $titleText = isset($conf['titleText.'])
1413 ? trim($this->stdWrap($conf['titleText'], $conf['titleText.']))
1414 : trim($conf['titleText']);
1415 $longDesc = isset($conf['longdescURL.'])
1416 ? trim($this->stdWrap($conf['longdescURL'], $conf['longdescURL.']))
1417 : trim($conf['longdescURL']);
1418
1419 // "alt":
1420 $altParam = ' alt="' . htmlspecialchars($altText) . '"';
1421
1422 // "title":
1423 $emptyTitleHandling = 'useAlt';
1424 $emptyTitleHandling = isset($conf['emptyTitleHandling.'])
1425 ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.'])
1426 : $conf['emptyTitleHandling'];
1427 // choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
1428 if ($titleText || $emptyTitleHandling == 'keepEmpty') {
1429 $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
1430 } elseif (!$titleText && $emptyTitleHandling == 'useAlt') {
1431 $altParam .= ' title="' . htmlspecialchars($altText) . '"';
1432 }
1433
1434 // "longDesc" URL
1435 if ($longDesc) {
1436 $altParam .= ' longdesc="' . htmlspecialchars(strip_tags($longDesc)) . '"';
1437 }
1438
1439 return $altParam;
1440 }
1441
1442 /**
1443 * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields
1444 *
1445 * @param string Input string
1446 * @return string the cleaned string
1447 * @see FORM()
1448 */
1449 function cleanFormName($name) {
1450 // turn data[x][y] into data:x:y:
1451 $name = preg_replace('/\[|\]\[?/', ':', trim($name));
1452 // remove illegal chars like _
1453 return preg_replace('#[^:a-zA-Z0-9]#', '', $name);
1454 }
1455
1456 /**
1457 * An abstraction method to add parameters to an A tag.
1458 * Uses the ATagParams property.
1459 *
1460 * @param array TypoScript configuration properties
1461 * @param boolean If set, will add the global config.ATagParams to the link
1462 * @return string String containing the parameters to the A tag (if non empty, with a leading space)
1463 * @see IMGTEXT(), filelink(), makelinks(), typolink()
1464 */
1465 function getATagParams($conf, $addGlobal = 1) {
1466 $aTagParams = '';
1467 if ($conf['ATagParams.']) {
1468 $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
1469 } elseif ($conf['ATagParams']) {
1470 $aTagParams = ' ' . $conf['ATagParams'];
1471 }
1472 if ($addGlobal) {
1473 $aTagParams = ' ' . trim($GLOBALS['TSFE']->ATagParams . $aTagParams);
1474 }
1475 return $aTagParams;
1476 }
1477
1478 /**
1479 * All extension links should ask this function for additional properties to their tags.
1480 * Designed to add for instance an "onclick" property for site tracking systems.
1481 *
1482 * @param string URL of the website
1483 * @return string the additional tag properties
1484 */
1485 function extLinkATagParams($URL, $TYPE) {
1486 $out = '';
1487
1488 if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
1489 $extLinkATagParamsHandler = t3lib_div::getUserObj(
1490 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']
1491 );
1492
1493 if (method_exists($extLinkATagParamsHandler, 'main')) {
1494 $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
1495 }
1496 }
1497
1498 return trim($out) ? ' ' . trim($out) : '';
1499 }
1500
1501
1502
1503 /***********************************************
1504 *
1505 * HTML template processing functions
1506 *
1507 ***********************************************/
1508
1509 /**
1510 * Returns a subpart from the input content stream.
1511 * A subpart is a part of the input stream which is encapsulated in a
1512 * string matching the input string, $marker. If this string is found
1513 * inside of HTML comment tags the start/end points of the content block
1514 * returned will be that right outside that comment block.
1515 * Example: The contennt string is
1516 * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?"
1517 * If $marker is "###sub1###" then the content returned is
1518 * " World. How are ". The input content string could just as well have
1519 * been "Hello ###sub1### World. How are ###sub1### you?" and the result
1520 * would be the same
1521 * Wrapper for t3lib_parsehtml::getSubpart which behaves identical
1522 *
1523 * @param string The content stream, typically HTML template content.
1524 * @param string The marker string, typically on the form "###[the marker string]###"
1525 * @return string The subpart found, if found.
1526 * @see substituteSubpart(), t3lib_parsehtml::getSubpart()
1527 */
1528 public function getSubpart($content, $marker) {
1529 return t3lib_parsehtml::getSubpart($content, $marker);
1530 }
1531
1532 /**
1533 * Substitute subpart in input template stream.
1534 * This function substitutes a subpart in $content with the content of
1535 * $subpartContent.
1536 * Wrapper for t3lib_parsehtml::substituteSubpart which behaves identical
1537 *
1538 * @param string The content stream, typically HTML template content.
1539 * @param string The marker string, typically on the form "###[the marker string]###"
1540 * @param mixed The content to insert instead of the subpart found. If a string, then just plain substitution happens (includes removing the HTML comments of the subpart if found). If $subpartContent happens to be an array, it's [0] and [1] elements are wrapped around the EXISTING content of the subpart (fetched by getSubpart()) thereby not removing the original content.
1541 * @param boolean If $recursive is set, the function calls itself with the content set to the remaining part of the content after the second marker. This means that proceding subparts are ALSO substituted!
1542 * @return string The processed HTML content string.
1543 * @see getSubpart(), t3lib_parsehtml::substituteSubpart()
1544 */
1545 public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) {
1546 return t3lib_parsehtml::substituteSubpart($content, $marker, $subpartContent, $recursive);
1547 }
1548
1549 /**
1550 * Substitues multiple subparts at once
1551 *
1552 * @param string The content stream, typically HTML template content.
1553 * @param array The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content.
1554 * @return string The processed HTML content string.
1555 */
1556 public function substituteSubpartArray($content, array $subpartsContent) {
1557 return t3lib_parsehtml::substituteSubpartArray($content, $subpartsContent);
1558 }
1559
1560 /**
1561 * Substitutes a marker string in the input content
1562 * (by a simple str_replace())
1563 *
1564 * @param string The content stream, typically HTML template content.
1565 * @param string The marker string, typically on the form "###[the marker string]###"
1566 * @param mixed The content to insert instead of the marker string found.
1567 * @return string The processed HTML content string.
1568 * @see substituteSubpart()
1569 */
1570 public function substituteMarker($content, $marker, $markContent) {
1571 return t3lib_parsehtml::substituteMarker($content, $marker, $markContent);
1572 }
1573
1574 /**
1575 * Multi substitution function with caching.
1576 *
1577 * This function should be a one-stop substitution function for working
1578 * with HTML-template. It does not substitute by str_replace but by
1579 * splitting. This secures that the value inserted does not themselves
1580 * contain markers or subparts.
1581 *
1582 * Note that the "caching" won't cache the content of the substition,
1583 * but only the splitting of the template in various parts. So if you
1584 * want only one cache-entry per template, make sure you always pass the
1585 * exact same set of marker/subpart keys. Else you will be flooding the
1586 * users cache table.
1587 *
1588 * This function takes three kinds of substitutions in one:
1589 * $markContentArray is a regular marker-array where the 'keys' are
1590 * substituted in $content with their values
1591 *
1592 * $subpartContentArray works exactly like markContentArray only is whole
1593 * subparts substituted and not only a single marker.
1594 *
1595 * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where
1596 * the subparts pointed to by the main key is wrapped with the 0/1 value
1597 * alternating.
1598 *
1599 * @param string The content stream, typically HTML template content.
1600 * @param array Regular marker-array where the 'keys' are substituted in $content with their values
1601 * @param array Exactly like markContentArray only is whole subparts substituted and not only a single marker.
1602 * @param array An array of arrays with 0/1 keys where the subparts pointed to by the main key is wrapped with the 0/1 value alternating.
1603 * @return string The output content stream
1604 * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE()
1605 */
1606 public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) {
1607 $GLOBALS['TT']->push('substituteMarkerArrayCached');
1608
1609 // If not arrays then set them
1610 if (is_null($markContentArray))
1611 $markContentArray = array(); // Plain markers
1612 if (is_null($subpartContentArray))
1613 $subpartContentArray = array(); // Subparts being directly substituted
1614 if (is_null($wrappedSubpartContentArray))
1615 $wrappedSubpartContentArray = array(); // Subparts being wrapped
1616 // Finding keys and check hash:
1617 $sPkeys = array_keys($subpartContentArray);
1618 $wPkeys = array_keys($wrappedSubpartContentArray);
1619 $aKeys = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys);
1620 if (!count($aKeys)) {
1621 $GLOBALS['TT']->pull();
1622 return $content;
1623 }
1624 asort($aKeys);
1625 $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array(
1626 $content, $aKeys
1627 )));
1628 if ($this->substMarkerCache[$storeKey]) {
1629 $storeArr = $this->substMarkerCache[$storeKey];
1630 $GLOBALS['TT']->setTSlogMessage('Cached', 0);
1631 } else {
1632 $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey);
1633 if (!isset($storeArrDat)) {
1634 // Initialize storeArr
1635 $storeArr = array();
1636
1637 // Finding subparts and substituting them with the subpart as a marker
1638 foreach ($sPkeys as $sPK) {
1639 $content = $this->substituteSubpart($content, $sPK, $sPK);
1640 }
1641
1642 // Finding subparts and wrapping them with markers
1643 foreach ($wPkeys as $wPK) {
1644 $content = $this->substituteSubpart($content, $wPK, array(
1645 $wPK, $wPK
1646 ));
1647 }
1648
1649 // traverse keys and quote them for reg ex.
1650 foreach ($aKeys as $tK => $tV) {
1651 $aKeys[$tK] = preg_quote($tV, '/');
1652 }
1653 $regex = '/' . implode('|', $aKeys) . '/';
1654 // Doing regex's
1655 $storeArr['c'] = preg_split($regex, $content);
1656 preg_match_all($regex, $content, $keyList);
1657 $storeArr['k'] = $keyList[0];
1658 // Setting cache:
1659 $this->substMarkerCache[$storeKey] = $storeArr;
1660
1661 // Storing the cached data:
1662 $GLOBALS['TSFE']->sys_page->storeHash($storeKey, serialize($storeArr), 'substMarkArrayCached');
1663
1664 $GLOBALS['TT']->setTSlogMessage('Parsing', 0);
1665 } else {
1666 // Unserializing
1667 $storeArr = unserialize($storeArrDat);
1668 // Setting cache:
1669 $this->substMarkerCache[$storeKey] = $storeArr;
1670 $GLOBALS['TT']->setTSlogMessage('Cached from DB', 0);
1671 }
1672 }
1673
1674 // Substitution/Merging:
1675 // Merging content types together, resetting
1676 $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
1677
1678 $wSCA_reg = array();
1679 $content = '';
1680 // traversing the keyList array and merging the static and dynamic content
1681 foreach ($storeArr['k'] as $n => $keyN) {
1682 $content .= $storeArr['c'][$n];
1683 if (!is_array($valueArr[$keyN])) {
1684 $content .= $valueArr[$keyN];
1685 } else {
1686 $content .= $valueArr[$keyN][(intval($wSCA_reg[$keyN]) % 2)];
1687 $wSCA_reg[$keyN]++;
1688 }
1689 }
1690 $content .= $storeArr['c'][count($storeArr['k'])];
1691
1692 $GLOBALS['TT']->pull();
1693 return $content;
1694 }
1695
1696 /**
1697 * Traverses the input $markContentArray array and for each key the marker
1698 * by the same name (possibly wrapped and in upper case) will be
1699 * substituted with the keys value in the array.
1700 *
1701 * This is very useful if you have a data-record to substitute in some
1702 * content. In particular when you use the $wrap and $uppercase values to
1703 * pre-process the markers. Eg. a key name like "myfield" could effectively
1704 * be represented by the marker "###MYFIELD###" if the wrap value
1705 * was "###|###" and the $uppercase boolean TRUE.
1706 *
1707 * @param string The content stream, typically HTML template content.
1708 * @param array The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
1709 * @param string A wrap value - [part 1] | [part 2] - for the markers before substitution
1710 * @param boolean If set, all marker string substitution is done with upper-case markers.
1711 * @param boolean If set, all unused marker are deleted.
1712 * @return string The processed output stream
1713 * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
1714 */
1715 public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
1716 return t3lib_parsehtml::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
1717 }
1718
1719 /**
1720 * Substitute marker array in an array of values
1721 *
1722 * @param mixed If string, then it just calls substituteMarkerArray. If array(and even multi-dim) then for each key/value pair the marker array will be substituted (by calling this function recursively)
1723 * @param array The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content string/array values.
1724 * @return mixed The processed input variable.
1725 * @see substituteMarker()
1726 */
1727 public function substituteMarkerInObject(&$tree, array $markContentArray) {
1728 if (is_array($tree)) {
1729 foreach ($tree as $key => $value) {
1730 $this->substituteMarkerInObject($tree[$key], $markContentArray);
1731 }
1732 } else {
1733 $tree = $this->substituteMarkerArray($tree, $markContentArray);
1734 }
1735
1736 return $tree;
1737 }
1738
1739 /**
1740 * Replaces all markers and subparts in a template with the content provided in the structured array.
1741 *
1742 * @param $content
1743 * @param array $markersAndSubparts
1744 * @param string $wrap
1745 * @param bool $uppercase
1746 * @param bool $deleteUnused
1747 * @return string
1748 * @see t3lib_parsehtml::substituteMarkerAndSubpartArrayRecursive()
1749 */
1750 public function substituteMarkerAndSubpartArrayRecursive($content, array $markersAndSubparts, $wrap = '', $uppercase = FALSE,
1751 $deleteUnused = FALSE) {
1752 return t3lib_parsehtml::substituteMarkerAndSubpartArrayRecursive(
1753 $content, $markersAndSubparts, $wrap, $uppercase, $deleteUnused
1754 );
1755 }
1756
1757 /**
1758 * Adds elements to the input $markContentArray based on the values from
1759 * the fields from $fieldList found in $row
1760 *
1761 * @param array array with key/values being marker-strings/substitution values.
1762 * @param array An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray
1763 * @param string A list of fields from the $row array to add to the $markContentArray array. If empty all fields from $row will be added (unless they are integers)
1764 * @param boolean If set, all values added to $markContentArray will be nl2br()'ed
1765 * @param string Prefix string to the fieldname before it is added as a key in the $markContentArray. Notice that the keys added to the $markContentArray always start and end with "###"
1766 * @param boolean If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance.
1767 * @return array The modified $markContentArray
1768 */
1769 public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = TRUE, $prefix = 'FIELD_', $HSC = FALSE) {
1770 if ($fieldList) {
1771 $fArr = t3lib_div::trimExplode(',', $fieldList, 1);
1772 foreach ($fArr as $field) {
1773 $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field]) : $row[$field];
1774 }
1775 } else {
1776 if (is_array($row)) {
1777 foreach ($row as $field => $value) {
1778 if (!t3lib_utility_Math::canBeInterpretedAsInteger($field)) {
1779 if ($HSC) {
1780 $value = htmlspecialchars($value);
1781 }
1782
1783 $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value) : $value;
1784 }
1785 }
1786 }
1787 }
1788
1789 return $markContentArray;
1790 }
1791
1792 /***********************************************
1793 *
1794 * "stdWrap" + sub functions
1795 *
1796 ***********************************************/
1797
1798 /**
1799 * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript.
1800 * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array(holding the TypoScript "stdWrap properties")
1801 * See the link below for a complete list of properties and what they do. The order of the table with properties found in TSref (the link) follows the actual order of implementation in this function.
1802 *
1803 * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData
1804 *
1805 * @param string Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
1806 * @param array TypoScript "stdWrap properties".
1807 * @return string The processed input value
1808 */
1809 public function stdWrap($content = '', $conf = array()) {
1810 if (count($this->stdWrapHookObjects)) {
1811 foreach ($this->stdWrapHookObjects as $hookObject) {
1812 if (is_callable(array($hookObject, 'stdWrapPreProcess'))) {
1813 $conf['stdWrapPreProcess'] = 1;
1814 }
1815 ;
1816 if (is_callable(array($hookObject, 'stdWrapOverride'))) {
1817 $conf['stdWrapOverride'] = 1;
1818 }
1819 ;
1820 if (is_callable(array($hookObject, 'stdWrapProcess'))) {
1821 $conf['stdWrapProcess'] = 1;
1822 }
1823 ;
1824 if (is_callable(array($hookObject, 'stdWrapPostProcess'))) {
1825 $conf['stdWrapPostProcess'] = 1;
1826 }
1827 ;
1828 }
1829 }
1830 if (is_array($conf) && count($conf)) {
1831 // check, which of the available stdWrap functions is needed for the current conf Array
1832 // and keep only those but still in the same order
1833 $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
1834 // functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
1835 $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
1836 // additional Array to check whether a function has already been executed
1837 $isExecuted = array();
1838 // additional switch to make sure 'required', 'if' and 'fieldRequired'
1839 // will still stop rendering immediately in case they return FALSE
1840
1841 $this->stdWrapRecursionLevel++;
1842 $this->stopRendering[$this->stdWrapRecursionLevel] = FALSE;
1843
1844 // execute each funtion in the predefined order
1845 foreach ($sortedConf as $stdWrapName => $functionType) {
1846 // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
1847 if (!$isExecuted[$stdWrapName] &&
1848 !$this->stopRendering[$this->stdWrapRecursionLevel]) {
1849 $functionName = rtrim($stdWrapName, '.');
1850 $functionProperties = $functionName . '.';
1851 // if there is any code one the next level, check if it contains "official" stdWrap functions
1852 // if yes, execute them first - will make each function stdWrap aware
1853 // so additional stdWrap calls within the functions can be removed, since the result will be the same
1854 // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
1855 if (count($conf[$functionProperties]) &&
1856 !t3lib_div::inList($stdWrapDisabledFunctionTypes, $functionType)) {
1857 if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
1858 $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
1859 }
1860 }
1861 // get just that part of $conf that is needed for the particular function
1862 $singleConf = array(
1863 $functionName => $conf[$functionName],
1864 $functionProperties => $conf[$functionProperties]
1865 );
1866
1867 // in this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.''
1868 if ($functionName == 'spaceBefore' || $functionName == 'spaceAfter') {
1869 $singleConf['space.'] = $conf['space.'];
1870 }
1871
1872 // hand over the whole $conf array to the stdWrapHookObjects
1873 if ($functionType === 'hook') {
1874 $singleConf = $conf;
1875 }
1876 // check if key is still containing something, since it might have been changed by next level stdWrap before
1877 if ((isset($conf[$functionName]) || $conf[$functionProperties]) &&
1878 !($functionType == 'boolean' && !$conf[$functionName])) {
1879 //add both keys - with and without the dot - to the set of executed functions
1880 $isExecuted[$functionName] = TRUE;
1881 $isExecuted[$functionProperties] = TRUE;
1882 // call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
1883 $functionName = 'stdWrap_' . $functionName;
1884 $content = $this->$functionName(
1885 $content,
1886 $singleConf
1887 );
1888 // for booleans we have to mark the function as executed in any case, even if it has been 0, '' or false to avoid a second call based on the functionProperties, which would always be true
1889 } elseif($functionType == 'boolean' && !$conf[$functionName]) {
1890 $isExecuted[$functionName] = TRUE;
1891 $isExecuted[$functionProperties] = TRUE;
1892 }
1893 }
1894 }
1895
1896 unset($this->stopRendering[$this->stdWrapRecursionLevel]);
1897 $this->stdWrapRecursionLevel--;
1898
1899 }
1900 return $content;
1901 }
1902
1903 /**
1904 * stdWrap pre process hook
1905 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
1906 * this hook will execute functions before any other stdWrap function can modify anything
1907 *
1908 * @param string Input value undergoing processing in these functions.
1909 * @param array All stdWrap properties, not just the ones for a particular function.
1910 * @return string The processed input value
1911 */
1912 public function stdWrap_stdWrapPreProcess($content = '', $conf = array()) {
1913 foreach ($this->stdWrapHookObjects as $hookObject) {
1914 $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
1915 }
1916 return $content;
1917 }
1918
1919 /**
1920 * setContentToCurrent
1921 * actually it just does the contrary: Sets the value of 'current' based on current content
1922 *
1923 * @param string Input value undergoing processing in this function.
1924 * @param array stdWrap properties for setContentToCurrent.
1925 * @return string The processed input value
1926 */
1927 public function stdWrap_setContentToCurrent($content = '', $conf = array()) {
1928 $this->data[$this->currentValKey] = $content;
1929 return $content;
1930 }
1931
1932 /**
1933 * setCurrent
1934 * Sets the value of 'current' based on the outcome of stdWrap operations
1935 *
1936 * @param string Input value undergoing processing in this function.
1937 * @param array stdWrap properties for setCurrent.
1938 * @return string The processed input value
1939 */
1940 public function stdWrap_setCurrent($content = '', $conf = array()) {
1941 $this->data[$this->currentValKey] = $conf['setCurrent'];
1942 return $content;
1943 }
1944
1945 /**
1946 * lang
1947 * Translates content based on the language currently used by the FE
1948 *
1949 * @param string Input value undergoing processing in this function.
1950 * @param array stdWrap properties for lang.
1951 * @return string The processed input value
1952 */
1953 public function stdWrap_lang($content = '', $conf = array()) {
1954 if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) {
1955 $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']];
1956 }
1957 return $content;
1958 }
1959
1960 /**
1961 * data
1962 * Gets content from different sources based on getText functions, makes use of alternativeData, when set
1963 *
1964 * @param string Input value undergoing processing in this function.
1965 * @param array stdWrap properties for data.
1966 * @return string The processed input value
1967 */
1968 public function stdWrap_data($content = '', $conf = array()) {
1969 $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
1970 $this->alternativeData = ''; // This must be unset directly after
1971 return $content;
1972 }
1973
1974 /**
1975 * field
1976 * Gets content from a DB field
1977 *
1978 * @param string Input value undergoing processing in this function.
1979 * @param array stdWrap properties for field.
1980 * @return string The processed input value
1981 */
1982 public function stdWrap_field($content = '', $conf = array()) {
1983 $content = $this->getFieldVal($conf['field']);
1984 return $content;
1985 }
1986
1987 /**
1988 * current
1989 * Gets content that has been perviously set as 'current'
1990 * Can be set via setContentToCurrent or setCurrent or will be set automatically i.e. inside the split function
1991 *
1992 * @param string Input value undergoing processing in this function.
1993 * @param array stdWrap properties for current.
1994 * @return string The processed input value
1995 */
1996 public function stdWrap_current($content = '', $conf = array()) {
1997 $content = $this->data[$this->currentValKey];
1998 return $content;
1999 }
2000
2001 /**
2002 * cObject
2003 * Will replace the content with the value of a any official TypoScript cObject
2004 * like TEXT, COA, HMENU
2005 *
2006 * @param string Input value undergoing processing in this function.
2007 * @param array stdWrap properties for cObject.
2008 * @return string The processed input value
2009 */
2010 public function stdWrap_cObject($content = '', $conf = array()) {
2011 $content = $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject');
2012 return $content;
2013 }
2014
2015 /**
2016 * numRows
2017 * Counts the number of returned records of a DB operation
2018 * makes use of select internally
2019 *
2020 * @param string Input value undergoing processing in this function.
2021 * @param array stdWrap properties for numRows.
2022 * @return string The processed input value
2023 */
2024 public function stdWrap_numRows($content = '', $conf = array()) {
2025 $content = $this->numRows($conf['numRows.']);
2026 return $content;
2027 }
2028
2029 /**
2030 * filelist
2031 * Will create a list of files based on some additional parameters
2032 *
2033 * @param string Input value undergoing processing in this function.
2034 * @param array stdWrap properties for filelist.
2035 * @return string The processed input value
2036 */
2037 public function stdWrap_filelist($content = '', $conf = array()) {
2038 $content = $this->filelist($conf['filelist']);
2039 return $content;
2040 }
2041
2042 /**
2043 * preUserFunc
2044 * Will execute a user public function before the content will be modified by any other stdWrap function
2045 *
2046 * @param string Input value undergoing processing in this function.
2047 * @param array stdWrap properties for preUserFunc.
2048 * @return string The processed input value
2049 */
2050 public function stdWrap_preUserFunc($content = '', $conf = array()) {
2051 $content = $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
2052 return $content;
2053 }
2054
2055 /**
2056 * stdWrap override hook
2057 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
2058 * this hook will execute functions on existing content but still before the content gets modified or replaced
2059 *
2060 * @param string Input value undergoing processing in these functions.
2061 * @param array All stdWrap properties, not just the ones for a particular function.
2062 * @return string The processed input value
2063 */
2064 public function stdWrap_stdWrapOverride($content = '', $conf = array()) {
2065 foreach ($this->stdWrapHookObjects as $hookObject) {
2066 $content = $hookObject->stdWrapOverride($content, $conf, $this);
2067 }
2068 return $content;
2069 }
2070
2071 /**
2072 * override
2073 * Will override the current value of content with its own value'
2074 *
2075 * @param string Input value undergoing processing in this function.
2076 * @param array stdWrap properties for override.
2077 * @return string The processed input value
2078 */
2079 public function stdWrap_override($content = '', $conf = array()) {
2080 if (trim($conf['override'])) {
2081 $content = $conf['override'];
2082 }
2083 return $content;
2084 }
2085
2086 /**
2087 * preIfEmptyListNum
2088 * Gets a value off a CSV list before the following ifEmpty check
2089 * Makes sure that the result of ifEmpty will be TRUE in case the CSV does not contain a value at the position given by preIfEmptyListNum
2090 *
2091 * @param string Input value undergoing processing in this function.
2092 * @param array stdWrap properties for preIfEmptyListNum.
2093 * @return string The processed input value
2094 */
2095 public function stdWrap_preIfEmptyListNum($content = '', $conf = array()) {
2096 $content = $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']);
2097 return $content;
2098 }
2099
2100 /**
2101 * ifEmpty
2102 * Will set content to a replacement value in case the trimmed value of content returns FALSE
2103 * 0 (zero) will be replaced as well
2104 *
2105 * @param string Input value undergoing processing in this function.
2106 * @param array stdWrap properties for ifEmpty.
2107 * @return string The processed input value
2108 */
2109 public function stdWrap_ifEmpty($content = '', $conf = array()) {
2110 if (!trim($content)) {
2111 $content = $conf['ifEmpty'];
2112 }
2113 return $content;
2114 }
2115
2116 /**
2117 * ifBlank
2118 * Will set content to a replacement value in case the trimmed value of content has no length
2119 * 0 (zero) will not be replaced
2120 *
2121 * @param string Input value undergoing processing in this function.
2122 * @param array stdWrap properties for ifBlank.
2123 * @return string The processed input value
2124 */
2125 public function stdWrap_ifBlank($content = '', $conf = array()) {
2126 if (!strlen(trim($content))) {
2127 $content = $conf['ifBlank'];
2128 }
2129 return $content;
2130 }
2131
2132 /**
2133 * listNum
2134 * Gets a value off a CSV list after ifEmpty check
2135 * Might return an empty value in case the CSV does not contain a value at the position given by listNum
2136 * Use preIfEmptyListNum to avoid that behaviour
2137 *
2138 * @param string Input value undergoing processing in this function.
2139 * @param array stdWrap properties for listNum.
2140 * @return string The processed input value
2141 */
2142 public function stdWrap_listNum($content = '', $conf = array()) {
2143 $content = $this->listNum($content, $conf['listNum'], $conf['listNum.']['splitChar']);
2144 return $content;
2145 }
2146
2147 /**
2148 * trim
2149 * Cuts off any whitespace at the beginning and the end of the content
2150 *
2151 * @param string Input value undergoing processing in this function.
2152 * @param array stdWrap properties for trim.
2153 * @return string The processed input value
2154 */
2155 public function stdWrap_trim($content = '', $conf = array()) {
2156 $content = trim($content);
2157 return $content;
2158 }
2159
2160 /**
2161 * stdWrap
2162 * A recursive call of the stdWrap function set
2163 * This enables the user to execute stdWrap functions in another than the predefined order
2164 * It modifies the content, not the property
2165 * while the new feature of chained stdWrap functions modifies the property and not the content
2166 *
2167 * @param string Input value undergoing processing in this function.
2168 * @param array stdWrap properties for stdWrap.
2169 * @return string The processed input value
2170 */
2171 public function stdWrap_stdWrap($content = '', $conf = array()) {
2172 $content = $this->stdWrap($content, $conf['stdWrap.']);
2173 return $content;
2174 }
2175
2176 /**
2177 * stdWrap process hook
2178 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
2179 * this hook executes functions directly after the recursive stdWrap function call but still before the content gets modified
2180 *
2181 * @param string Input value undergoing processing in these functions.
2182 * @param array All stdWrap properties, not just the ones for a particular function.
2183 * @return string The processed input value
2184 */
2185 public function stdWrap_stdWrapProcess($content = '', $conf = array()) {
2186 foreach ($this->stdWrapHookObjects as $hookObject) {
2187 $content = $hookObject->stdWrapProcess($content, $conf, $this);
2188 }
2189 return $content;
2190 }
2191
2192 /**
2193 * required
2194 * Will immediately stop rendering and return an empty value
2195 * when there is no content at this point
2196 *
2197 * @param string Input value undergoing processing in this function.
2198 * @param array stdWrap properties for required.
2199 * @return string The processed input value
2200 */
2201 public function stdWrap_required($content = '', $conf = array()) {
2202 if ((string) $content == '') {
2203 $content = '';
2204 $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2205 }
2206 return $content;
2207 }
2208
2209 /**
2210 * if
2211 * Will immediately stop rendering and return an empty value
2212 * when the result of the checks returns FALSE
2213 *
2214 * @param string Input value undergoing processing in this function.
2215 * @param array stdWrap properties for if.
2216 * @return string The processed input value
2217 */
2218 public function stdWrap_if($content = '', $conf = array()) {
2219 if (!$this->checkIf($conf['if.'])) {
2220 $content = '';
2221 $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2222 }
2223 return $content;
2224 }
2225
2226 /**
2227 * fieldRequired
2228 * Will immediately stop rendering and return an empty value
2229 * when there is no content in the field given by fieldRequired
2230 *
2231 * @param string Input value undergoing processing in this function.
2232 * @param array stdWrap properties for fieldRequired.
2233 * @return string The processed input value
2234 */
2235 public function stdWrap_fieldRequired($content = '', $conf = array()) {
2236 if (!trim($this->data[$conf['fieldRequired']])) {
2237 $content = '';
2238 $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2239 }
2240 return $content;
2241 }
2242
2243 /**
2244 * csConv
2245 * Will convert the current chracter set of the content to the one given in csConv
2246 *
2247 * @param string Input value undergoing processing in this function.
2248 * @param array stdWrap properties for csConv.
2249 * @return string The processed input value
2250 */
2251 public function stdWrap_csConv($content = '', $conf = array()) {
2252 $content = $GLOBALS['TSFE']->csConv($content, $conf['csConv']);
2253 return $content;
2254 }
2255
2256 /**
2257 * parseFunc
2258 * Will parse the content based on functions given as stdWrap properties
2259 * Heavily used together with RTE based content
2260 *
2261 * @param string Input value undergoing processing in this function.
2262 * @param array stdWrap properties for parseFunc.
2263 * @return string The processed input value
2264 */
2265 public function stdWrap_parseFunc($content = '', $conf = array()) {
2266 $content = $this->parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
2267 return $content;
2268 }
2269
2270 /**
2271 * HTMLparser
2272 * Will parse HTML content based on functions given as stdWrap properties
2273 * Heavily used together with RTE based content
2274 *
2275 * @param string Input value undergoing processing in this function.
2276 * @param array stdWrap properties for HTMLparser.
2277 * @return string The processed input value
2278 */
2279 public function stdWrap_HTMLparser($content = '', $conf = array()) {
2280 if (is_array($conf['HTMLparser.'])) {
2281 $content = $this->HTMLparser_TSbridge($content, $conf['HTMLparser.']);
2282 }
2283 return $content;
2284 }
2285
2286 /**
2287 * split
2288 * Will split the content by a given token and treat the results separately
2289 * Automatically fills 'current' with a single result
2290 *
2291 * @param string Input value undergoing processing in this function.
2292 * @param array stdWrap properties for split.
2293 * @return string The processed input value
2294 */
2295 public function stdWrap_split($content = '', $conf = array()) {
2296 $content = $this->splitObj($content, $conf['split.']);
2297 return $content;
2298 }
2299
2300 /**
2301 * replacement
2302 * Will execute replacements on the content (optionally with preg-regex)
2303 *
2304 * @param string Input value undergoing processing in this function.
2305 * @param array stdWrap properties for replacement.
2306 * @return string The processed input value
2307 */
2308 public function stdWrap_replacement($content = '', $conf = array()) {
2309 $content = $this->replacement($content, $conf['replacement.']);
2310 return $content;
2311 }
2312
2313 /**
2314 * prioriCalc
2315 * Will use the content as a mathematical term and calculate the result
2316 * Can be set to 1 to just get a calculated value or 'intval' to get the integer of the result
2317 *
2318 * @param string Input value undergoing processing in this function.
2319 * @param array stdWrap properties for prioriCalc.
2320 * @return string The processed input value
2321 */
2322 public function stdWrap_prioriCalc($content = '', $conf = array()) {
2323 $content = t3lib_utility_Math::calculateWithParentheses($content);
2324 if ($conf['prioriCalc'] == 'intval')
2325 $content = intval($content);
2326 return $content;
2327 }
2328
2329 /**
2330 * char
2331 * Will return a character based on its position within the current character set
2332 *
2333 * @param string Input value undergoing processing in this function.
2334 * @param array stdWrap properties for char.
2335 * @return string The processed input value
2336 */
2337 public function stdWrap_char($content = '', $conf = array()) {
2338 $content = chr(intval($conf['char']));
2339 return $content;
2340 }
2341
2342 /**
2343 * intval
2344 * Will return an integer value of the current content
2345 *
2346 * @param string Input value undergoing processing in this function.
2347 * @param array stdWrap properties for intval.
2348 * @return string The processed input value
2349 */
2350 public function stdWrap_intval($content = '', $conf = array()) {
2351 $content = intval($content);
2352 return $content;
2353 }
2354
2355 /**
2356 * Will return a hashed value of the current content
2357 *
2358 * @param string Input value undergoing processing in this function.
2359 * @param array stdWrap properties for hash.
2360 * @return string The processed input value
2361 * @link http://php.net/manual/de/function.hash-algos.php for a list of supported hash algorithms
2362 */
2363 public function stdWrap_hash($content = '', array $conf = array()) {
2364 $algorithm = isset($conf['hash.'])
2365 ? $this->stdWrap($conf['hash'], $conf['hash.'])
2366 : $conf['hash'];
2367 if (function_exists('hash') && in_array($algorithm, hash_algos())) {
2368 $content = hash($algorithm, $content);
2369 } else {
2370 // non-existing hashing algorithm
2371 $content = '';
2372 }
2373 return $content;
2374 }
2375
2376 /**
2377 * stdWrap_round will return a rounded number with ceil(), floor() or round(), defaults to round()
2378 * Only the english number format is supported . (dot) as decimal point
2379 *
2380 * @param string Input value undergoing processing in this function.
2381 * @param array stdWrap properties for round.
2382 * @return string The processed input value
2383 */
2384 public function stdWrap_round($content = '', $conf = array()){
2385 $content = $this->round($content, $conf['round.']);
2386 return $content;
2387 }
2388
2389 /**
2390 * numberFormat
2391 * Will return a formatted number based on configuration given as stdWrap properties
2392 *
2393 * @param string Input value undergoing processing in this function.
2394 * @param array stdWrap properties for numberFormat.
2395 * @return string The processed input value
2396 */
2397 public function stdWrap_numberFormat($content = '', $conf = array()) {
2398 $content = $this->numberFormat($content, $conf['numberFormat.']);
2399 return $content;
2400 }
2401
2402 /**
2403 * expandList
2404 * Will return a formatted number based on configuration given as stdWrap properties
2405 *
2406 * @param string Input value undergoing processing in this function.
2407 * @param array stdWrap properties for expandList.
2408 * @return string The processed input value
2409 */
2410 public function stdWrap_expandList($content = '', $conf = array()) {
2411 $content = t3lib_div::expandList($content);
2412 return $content;
2413 }
2414
2415 /**
2416 * date
2417 * Will return a formatted date based on configuration given according to PHP date/gmdate properties
2418 * Will return gmdate when the property GMT returns TRUE
2419 *
2420 * @param string $content Input value undergoing processing in this function.
2421 * @param array $conf stdWrap properties for date.
2422 * @return string The processed input value
2423 */
2424 public function stdWrap_date($content = '', $conf = array()) {
2425 // check for zero length string to mimic default case of date/gmdate.
2426 $content = $content == '' ? $GLOBALS['EXEC_TIME'] : intval($content);
2427 $content = ($conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content));
2428 return $content;
2429 }
2430
2431 /**
2432 * strftime
2433 * Will return a formatted date based on configuration given according to PHP strftime/gmstrftime properties
2434 * Will return gmstrftime when the property GMT returns TRUE
2435 *
2436 * @param string Input value undergoing processing in this function.
2437 * @param array stdWrap properties for strftime.
2438 * @return string The processed input value
2439 */
2440 public function stdWrap_strftime($content = '', $conf = array()) {
2441 $content = ($conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content));
2442 $tmp_charset = $conf['strftime.']['charset'] ? $conf['strftime.']['charset'] : $GLOBALS['TSFE']->localeCharset;
2443 if ($tmp_charset) {
2444 $content = $GLOBALS['TSFE']->csConv($content, $tmp_charset);
2445 }
2446 return $content;
2447 }
2448
2449 /**
2450 * age
2451 * Will return the age of a given timestamp based on configuration given by stdWrap properties
2452 *
2453 * @param string Input value undergoing processing in this function.
2454 * @param array stdWrap properties for age.
2455 * @return string The processed input value
2456 */
2457 public function stdWrap_age($content = '', $conf = array()) {
2458 $content = $this->calcAge($GLOBALS['EXEC_TIME'] - $content, $conf['age']);
2459 return $content;
2460 }
2461
2462 /**
2463 * case
2464 * Will transform the content to be upper or lower case only
2465 * Leaves HTML tags untouched
2466 *
2467 * @param string Input value undergoing processing in this function.
2468 * @param array stdWrap properties for case.
2469 * @return string The processed input value
2470 */
2471 public function stdWrap_case($content = '', $conf = array()) {
2472 $content = $this->HTMLcaseshift($content, $conf['case']);
2473 return $content;
2474 }
2475
2476 /**
2477 * bytes
2478 * Will return the size of a given number in Bytes *
2479 *
2480 * @param string Input value undergoing processing in this function.
2481 * @param array stdWrap properties for bytes.
2482 * @return string The processed input value
2483 */
2484 public function stdWrap_bytes($content = '', $conf = array()) {
2485 $content = t3lib_div::formatSize($content, $conf['bytes.']['labels']);
2486 return $content;
2487 }
2488
2489 /**
2490 * substring
2491 * Will return a substring based on position information given by stdWrap properties
2492 *
2493 * @param string Input value undergoing processing in this function.
2494 * @param array stdWrap properties for substring.
2495 * @return string The processed input value
2496 */
2497 public function stdWrap_substring($content = '', $conf = array()) {
2498 $content = $this->substring($content, $conf['substring']);
2499 return $content;
2500 }
2501
2502 /**
2503 * removeBadHTML
2504 * Removes HTML tags based on stdWrap properties
2505 *
2506 * @param string Input value undergoing processing in this function.
2507 * @param array stdWrap properties for removeBadHTML.
2508 * @return string The processed input value
2509 */
2510 public function stdWrap_removeBadHTML($content = '', $conf = array()) {
2511 $content = $this->removeBadHTML($content, $conf['removeBadHTML.']);
2512 return $content;
2513 }
2514
2515 /**
2516 * cropHTML
2517 * Crops content to a given size while leaving HTML tags untouched
2518 *
2519 * @param string Input value undergoing processing in this function.
2520 * @param array stdWrap properties for cropHTML.
2521 * @return string The processed input value
2522 */
2523 public function stdWrap_cropHTML($content = '', $conf = array()) {
2524 $content = $this->cropHTML($content, $conf['cropHTML']);
2525 return $content;
2526 }
2527
2528 /**
2529 * stripHtml
2530 * Copmletely removes HTML tags from content
2531 *
2532 * @param string Input value undergoing processing in this function.
2533 * @param array stdWrap properties for stripHtml.
2534 * @return string The processed input value
2535 */
2536 public function stdWrap_stripHtml($content = '', $conf = array()) {
2537 $content = strip_tags($content);
2538 return $content;
2539 }
2540
2541 /**
2542 * cropHTML
2543 * Crops content to a given size without caring abhout HTML tags
2544 *
2545 * @param string Input value undergoing processing in this function.
2546 * @param array stdWrap properties for crop.
2547 * @return string The processed input value
2548 */
2549 public function stdWrap_crop($content = '', $conf = array()) {
2550 $content = $this->crop($content, $conf['crop']);
2551 return $content;
2552 }
2553
2554 /**
2555 * rawUrlEncode
2556 * Encodes content to be used within URLs
2557 *
2558 * @param string Input value undergoing processing in this function.
2559 * @param array stdWrap properties for rawUrlEncode.
2560 * @return string The processed input value
2561 */
2562 public function stdWrap_rawUrlEncode($content = '', $conf = array()) {
2563 $content = rawurlencode($content);
2564 return $content;
2565 }
2566
2567 /**
2568 * htmlSpecialChars
2569 * Transforms HTML tags to readable text by replacing special characters with their HTML entity
2570 * When preserveEntities returns TRUE, existing entities will be left untouched
2571 *
2572 * @param string Input value undergoing processing in this function.
2573 * @param array stdWrap properties for htmlSpecalChars.
2574 * @return string The processed input value
2575 */
2576 public function stdWrap_htmlSpecialChars($content = '', $conf = array()) {
2577 $content = htmlSpecialChars($content);
2578 if ($conf['htmlSpecialChars.']['preserveEntities'])
2579 $content = t3lib_div::deHSCentities($content);
2580 return $content;
2581 }
2582
2583 /**
2584 * doubleBrTag
2585 * Searches for double line breaks and replaces them with the given value
2586 *
2587 * @param string Input value undergoing processing in this function.
2588 * @param array stdWrap properties for doubleBrTag.
2589 * @return string The processed input value
2590 */
2591 public function stdWrap_doubleBrTag($content = '', $conf = array()) {
2592 $content = preg_replace("/\r?\n[\t ]*\r?\n/", $conf['doubleBrTag'], $content);
2593 return $content;
2594 }
2595
2596 /**
2597 * br
2598 * Searches for single line breaks and replaces them with a <br /> tag
2599 *
2600 * @param string Input value undergoing processing in this function.
2601 * @param array stdWrap properties for br.
2602 * @return string The processed input value
2603 */
2604 public function stdWrap_br($content = '', $conf = array()) {
2605 $content = nl2br($content);
2606 return $content;
2607 }
2608
2609 /**
2610 * brTag
2611 * Searches for single line feeds and replaces them with the given value
2612 *
2613 * @param string Input value undergoing processing in this function.
2614 * @param array stdWrap properties for brTag.
2615 * @return string The processed input value
2616 */
2617 public function stdWrap_brTag($content = '', $conf = array()) {
2618 $content = str_replace(LF, $conf['brTag'], $content);
2619 return $content;
2620 }
2621
2622 /**
2623 * encapsLines
2624 * Modifies text blocks by searching for lines which are not surrounded by HTML tags yet
2625 * and wrapping them with values given by stdWrap properties
2626 *
2627 * @param string Input value undergoing processing in this function.
2628 * @param array stdWrap properties for erncapsLines.
2629 * @return string The processed input value
2630 */
2631 public function stdWrap_encapsLines($content = '', $conf = array()) {
2632 $content = $this->encaps_lineSplit($content, $conf['encapsLines.']);
2633 return $content;
2634 }
2635
2636 /**
2637 * keywords
2638 * Transforms content into a CSV list to be used i.e. as keywords within a meta tag
2639 *
2640 * @param string Input value undergoing processing in this function.
2641 * @param array stdWrap properties for keywords.
2642 * @return string The processed input value
2643 */
2644 public function stdWrap_keywords($content = '', $conf = array()) {
2645 $content = $this->keywords($content);
2646 return $content;
2647 }
2648
2649 /**
2650 * innerWrap
2651 * First of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2652 * See wrap
2653 *
2654 * @param string Input value undergoing processing in this function.
2655 * @param array stdWrap properties for innerWrap.
2656 * @return string The processed input value
2657 */
2658 public function stdWrap_innerWrap($content = '', $conf = array()) {
2659 $content = $this->wrap($content, $conf['innerWrap']);
2660 return $content;
2661 }
2662
2663 /**
2664 * innerWrap2
2665 * Second of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2666 * See wrap
2667 *
2668 * @param string Input value undergoing processing in this function.
2669 * @param array stdWrap properties for innerWrap2.
2670 * @return string The processed input value
2671 */
2672 public function stdWrap_innerWrap2($content = '', $conf = array()) {
2673 $content = $this->wrap($content, $conf['innerWrap2']);
2674 return $content;
2675 }
2676
2677 /**
2678 * fontTag
2679 * A wrap formerly used to apply font tags to format the content
2680 * Still used by lib.stdheader although real font tags are not state of the art anymore
2681 * See wrap
2682 *
2683 * @param string Input value undergoing processing in this function.
2684 * @param array stdWrap properties for fontTag.
2685 * @return string The processed input value
2686 */
2687 public function stdWrap_fontTag($content = '', $conf = array()) {
2688 $content = $this->wrap($content, $conf['fontTag']);
2689 return $content;
2690 }
2691
2692 /**
2693 * addParams
2694 * Adds tag attributes to any content that is a tag
2695 *
2696 * @param string Input value undergoing processing in this function.
2697 * @param array stdWrap properties for addParams.
2698 * @return string The processed input value
2699 */
2700 public function stdWrap_addParams($content = '', $conf = array()) {
2701 $content = $this->addParams($content, $conf['addParams.']);
2702 return $content;
2703 }
2704
2705 /**
2706 * textStyle
2707 * Wraps content in font tags
2708 * See wrap
2709 *
2710 * @param string Input value undergoing processing in this function.
2711 * @param array stdWrap properties for textStyle.
2712 * @return string The processed input value
2713 */
2714 public function stdWrap_textStyle($content = '', $conf = array()) {
2715 $content = $this->textStyle($content, $conf['textStyle.']);
2716 return $content;
2717 }
2718
2719 /**
2720 * tableStyle
2721 * Wraps content with table tags
2722 * See wrap
2723 *
2724 * @param string Input value undergoing processing in this function.
2725 * @param array stdWrap properties for tableStyle.
2726 * @return string The processed input value
2727 */
2728 public function stdWrap_tableStyle($content = '', $conf = array()) {
2729 $content = $this->tableStyle($content, $conf['tableStyle.']);
2730 return $content;
2731 }
2732
2733 /**
2734 * filelink
2735 * Used to make lists of links to files
2736 * See wrap
2737 *
2738 * @param string Input value undergoing processing in this function.
2739 * @param array stdWrap properties for filelink.
2740 * @return string The processed input value
2741 */
2742 public function stdWrap_filelink($content = '', $conf = array()) {
2743 $content = $this->filelink($content, $conf['filelink.']);
2744 return $content;
2745 }
2746
2747 /**
2748 * preCObject
2749 * A content object that is prepended to the current content but between the innerWraps and the rest of the wraps
2750 *
2751 * @param string Input value undergoing processing in this function.
2752 * @param array stdWrap properties for preCObject.
2753 * @return string The processed input value
2754 */
2755 public function stdWrap_preCObject($content = '', $conf = array()) {
2756 $content = $this->cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content;
2757 return $content;
2758 }
2759
2760 /**
2761 * postCObject
2762 * A content object that is appended to the current content but between the innerWraps and the rest of the wraps
2763 *
2764 * @param string Input value undergoing processing in this function.
2765 * @param array stdWrap properties for postCObject.
2766 * @return string The processed input value
2767 */
2768 public function stdWrap_postCObject($content = '', $conf = array()) {
2769 $content .= $this->cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject');
2770 return $content;
2771 }
2772
2773 /**
2774 * wrapAlign
2775 * Wraps content with a div container having the style attribute text-align set to the given value
2776 * See wrap
2777 *
2778 * @param string Input value undergoing processing in this function.
2779 * @param array stdWrap properties for wrapAlign.
2780 * @return string The processed input value
2781 */
2782 public function stdWrap_wrapAlign($content = '', $conf = array()) {
2783 $wrapAlign = trim($conf['wrapAlign']);
2784 if ($wrapAlign) {
2785 $content = $this->wrap($content, '<div style="text-align:' . $wrapAlign . ';">|</div>');
2786 }
2787 return $content;
2788 }
2789
2790 /**
2791 * typolink
2792 * Wraps the content with a link tag
2793 * URLs and other attributes are created automatically by the values given in the stdWrap properties
2794 * See wrap
2795 *
2796 * @param string Input value undergoing processing in this function.
2797 * @param array stdWrap properties for typolink.
2798 * @return string The processed input value
2799 */
2800 public function stdWrap_typolink($content = '', $conf = array()) {
2801 $content = $this->typolink($content, $conf['typolink.']);
2802 return $content;
2803 }
2804
2805 /**
2806 * TCAselectItem
2807 * Returns a list of options available for a given field in the DB which has to be of the type select
2808 *
2809 * @param string Input value undergoing processing in this function.
2810 * @param array stdWrap properties for TCAselectItem.
2811 * @return string The processed input value
2812 */
2813 public function stdWrap_TCAselectItem($content = '', $conf = array()) {
2814 if (is_array($conf['TCAselectItem.'])) {
2815 $content = $this->TCAlookup($content, $conf['TCAselectItem.']);
2816 }
2817 return $content;
2818 }
2819
2820 /**
2821 * spaceBefore
2822 * Will add space before the current content
2823 * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to TRUE
2824 *
2825 * @param string Input value undergoing processing in this function.
2826 * @param array stdWrap properties for spaceBefore and space.
2827 * @return string The processed input value
2828 */
2829 public function stdWrap_spaceBefore($content = '', $conf = array()) {
2830 $content = $this->wrapSpace($content, trim($conf['spaceBefore']) . '|', $conf['space.']);
2831 return $content;
2832 }
2833
2834 /**
2835 * spaceAfter
2836 * Will add space after the current content
2837 * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to TRUE
2838 *
2839 * @param string Input value undergoing processing in this function.
2840 * @param array stdWrap properties for spaceAfter and space.
2841 * @return string The processed input value
2842 */
2843 public function stdWrap_spaceAfter($content = '', $conf = array()) {
2844 $content = $this->wrapSpace($content, '|' . trim($conf['spaceAfter']), $conf['space.']);
2845 return $content;
2846 }
2847
2848 /**
2849 * space
2850 * Will add space before or after the current content
2851 * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to TRUE
2852 * See wrap
2853 *
2854 * @param string Input value undergoing processing in this function.
2855 * @param array stdWrap properties for space.
2856 * @return string The processed input value
2857 */
2858 public function stdWrap_space($content = '', $conf = array()) {
2859 $content = $this->wrapSpace($content, trim($conf['space']), $conf['space.']);
2860 return $content;
2861 }
2862
2863 /**
2864 * wrap
2865 * This is the "mother" of all wraps
2866 * Third of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2867 * Basically it will put additional content before and after the current content using a split character as a placeholder for the current content
2868 * The default split character is | but it can be replaced with other characters by the property splitChar
2869 * Any other wrap that does not have own splitChar settings will be using the default split char though
2870 *
2871 * @param string Input value undergoing processing in this function.
2872 * @param array stdWrap properties for wrap.
2873 * @return string The processed input value
2874 */
2875 public function stdWrap_wrap($content = '', $conf = array()) {
2876 $content = $this->wrap($content, $conf['wrap'], ($conf['wrap.']['splitChar'] ? $conf['wrap.']['splitChar'] : '|'));
2877 return $content;
2878 }
2879
2880 /**
2881 * noTrimWrap
2882 * Fourth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2883 * The major difference to any other wrap is, that this one can make use of whitespace without trimming *
2884 *
2885 * @param string Input value undergoing processing in this function.
2886 * @param array stdWrap properties for noTrimWrap.
2887 * @return string The processed input value
2888 */
2889 public function stdWrap_noTrimWrap($content = '', $conf = array()) {
2890 $content = $this->noTrimWrap($content, $conf['noTrimWrap']);
2891 return $content;
2892 }
2893
2894 /**
2895 * wrap2
2896 * Fifth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2897 * The default split character is | but it can be replaced with other characters by the property splitChar
2898 *
2899 * @param string Input value undergoing processing in this function.
2900 * @param array stdWrap properties for wrap2.
2901 * @return string The processed input value
2902 */
2903 public function stdWrap_wrap2($content = '', $conf = array()) {
2904 $content = $this->wrap($content, $conf['wrap2'], ($conf['wrap2.']['splitChar'] ? $conf['wrap2.']['splitChar'] : '|'));
2905 return $content;
2906 }
2907
2908 /**
2909 * dataWrap
2910 * Sixth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2911 * Can fetch additional content the same way data does (i.e. {field:whatever}) and apply it to the wrap before that is applied to the content
2912 *
2913 * @param string Input value undergoing processing in this function.
2914 * @param array stdWrap properties for dataWrap.
2915 * @return string The processed input value
2916 */
2917 public function stdWrap_dataWrap($content = '', $conf = array()) {
2918 $content = $this->dataWrap($content, $conf['dataWrap']);
2919 return $content;
2920 }
2921
2922 /**
2923 * prepend
2924 * A content object that will be prepended to the current content after most of the wraps have already been applied
2925 *
2926 * @param string Input value undergoing processing in this function.
2927 * @param array stdWrap properties for prepend.
2928 * @return string The processed input value
2929 */
2930 public function stdWrap_prepend($content = '', $conf = array()) {
2931 $content = $this->cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content;
2932 return $content;
2933 }
2934
2935 /**
2936 * append
2937 * A content object that will be appended to the current content after most of the wraps have already been applied
2938 *
2939 * @param string Input value undergoing processing in this function.
2940 * @param array stdWrap properties for append.
2941 * @return string The processed input value
2942 */
2943 public function stdWrap_append($content = '', $conf = array()) {
2944 $content .= $this->cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append');
2945 return $content;
2946 }
2947
2948 /**
2949 * wrap3
2950 * Seventh of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2951 * The default split character is | but it can be replaced with other characters by the property splitChar
2952 *
2953 * @param string Input value undergoing processing in this function.
2954 * @param array stdWrap properties for wrap3.
2955 * @return string The processed input value
2956 */
2957 public function stdWrap_wrap3($content = '', $conf = array()) {
2958 $content = $this->wrap($content, $conf['wrap3'], ($conf['wrap3.']['splitChar'] ? $conf['wrap3.']['splitChar'] : '|'));
2959 return $content;
2960 }
2961
2962 /**
2963 * outerWrap
2964 * Eighth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content
2965 *
2966 * @param string Input value undergoing processing in this function.
2967 * @param array stdWrap properties for outerWrap.
2968 * @return string The processed input value
2969 */
2970 public function stdWrap_outerWrap($content = '', $conf = array()) {
2971 $content = $this->wrap($content, $conf['outerWrap']);
2972 return $content;
2973 }
2974
2975 /**
2976 * inserData
2977 * Can fetch additional content the same way data does and replaces any occurence of {field:whatever} with this content
2978 *
2979 * @param string Input value undergoing processing in this function.
2980 * @param array stdWrap properties for insertData.
2981 * @return string The processed input value
2982 */
2983 public function stdWrap_insertData($content = '', $conf = array()) {
2984 $content = $this->insertData($content);
2985 return $content;
2986 }
2987
2988 /**
2989 * offsetWrap
2990 * Creates a so called offset table around the content
2991 * Still here for historical reasons even not used too much nowadays
2992 *
2993 * @param string Input value undergoing processing in this function.
2994 * @param array stdWrap properties for offsetWrap.
2995 * @return string The processed input value
2996 */
2997 public function stdWrap_offsetWrap($content = '', $conf = array()) {
2998 $controlTable = t3lib_div::makeInstance('tslib_tableOffset');
2999 if ($conf['offsetWrap.']['tableParams'] || $conf['offsetWrap.']['tableParams.']) {
3000 $controlTable->tableParams = isset($conf['offsetWrap.']['tableParams.'])
3001 ? $this->stdWrap($conf['offsetWrap.']['tableParams'], $conf['offsetWrap.']['tableParams.'])
3002 : $conf['offsetWrap.']['tableParams'];
3003 }
3004 if ($conf['offsetWrap.']['tdParams'] || $conf['offsetWrap.']['tdParams.']) {
3005 $controlTable->tdParams = ' ' . (isset($conf['offsetWrap.']['tdParams.'])
3006 ? $this->stdWrap($conf['offsetWrap.']['tdParams'], $conf['offsetWrap.']['tdParams.'])
3007 : $conf['offsetWrap.']['tdParams']);
3008 }
3009 $content = $controlTable->start($content, $conf['offsetWrap']);
3010 if ($conf['offsetWrap.']['stdWrap.']) {
3011 $content = $this->stdWrap($content, $conf['offsetWrap.']['stdWrap.']);
3012 }
3013 return $content;
3014 }
3015
3016 /**
3017 * postUserFunc
3018 * Will execute a user function after the content has been modified by any other stdWrap function
3019 *
3020 * @param string Input value undergoing processing in this function.
3021 * @param array stdWrap properties for postUserFunc.
3022 * @return string The processed input value
3023 */
3024 public function stdWrap_postUserFunc($content = '', $conf = array()) {
3025 $content = $this->callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content);
3026 return $content;
3027 }
3028
3029 /**
3030 * postUserFuncInt
3031 * Will execute a user function after the content has been created and each time it is fetched from Cache
3032 * The result of this function itself will not be cached
3033 *
3034 * @param string Input value undergoing processing in this function.
3035 * @param array stdWrap properties for postUserFuncInt.
3036 * @return string The processed input value
3037 */
3038 public function stdWrap_postUserFuncInt($content = '', $conf = array()) {
3039 $substKey = 'INT_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
3040 $GLOBALS['TSFE']->config['INTincScript'][$substKey] = array(
3041 'content' => $content, 'postUserFunc' => $conf['postUserFuncInt'], 'conf' => $conf['postUserFuncInt.'], 'type' => 'POSTUSERFUNC', 'cObj' => serialize($this)
3042 );
3043 $content = '<!--' . $substKey . '-->';
3044 return $content;
3045 }
3046
3047 /**
3048 * prefixComment
3049 * Will add HTML comments to the content to make it easier to identify certain content elements within the HTML output later on
3050 *
3051 * @param string Input value undergoing processing in this function.
3052 * @param array stdWrap properties for prefixComment.
3053 * @return string The processed input value
3054 */
3055 public function stdWrap_prefixComment($content = '', $conf = array()) {
3056 if (!$GLOBALS['TSFE']->config['config']['disablePrefixComment']) {
3057 $content = $this->prefixComment($conf['prefixComment'], $conf['prefixComment.'], $content);
3058 }
3059 return $content;
3060 }
3061
3062 /**
3063 * editIcons
3064 * Will render icons for frontend editing as long as there is a BE user logged in
3065 *
3066 * @param string Input value undergoing processing in this function.
3067 * @param array stdWrap properties for editIcons.
3068 * @return string The processed input value
3069 */
3070 public function stdWrap_editIcons($content = '', $conf = array()) {
3071 if ($GLOBALS['TSFE']->beUserLogin && $conf['editIcons']) {
3072 if(!is_array($conf['editIcons.'])) {
3073 $conf['editIcons.'] = array();
3074 }
3075 $content = $this->editIcons($content, $conf['editIcons'], $conf['editIcons.']);
3076 }
3077 return $content;
3078 }
3079
3080 /**
3081 * editPanel
3082 * Will render the edit panel for frontend editing as long as there is a BE user logged in
3083 *
3084 * @param string Input value undergoing processing in this function.
3085 * @param array stdWrap properties for editPanel.
3086 * @return string The processed input value
3087 */
3088 public function stdWrap_editPanel($content = '', $conf = array()) {
3089 if ($GLOBALS['TSFE']->beUserLogin) {
3090 $content = $this->editPanel($content, $conf['editPanel.']);
3091 }
3092 return $content;
3093 }
3094
3095 /**
3096 * stdWrap post process hook
3097 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
3098 * this hook executes functions at after the content has been modified by the rest of the stdWrap functions but still before debugging
3099 *
3100 * @param string Input value undergoing processing in these functions.
3101 * @param array All stdWrap properties, not just the ones for a particular function.
3102 * @return string The processed input value
3103 */
3104 public function stdWrap_stdWrapPostProcess($content = '', $conf = array()) {
3105 foreach ($this->stdWrapHookObjects as $hookObject) {
3106 $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
3107 }
3108 return $content;
3109 }
3110
3111 /**
3112 * debug
3113 * Will output the content as readable HTML code
3114 *
3115 * @param string Input value undergoing processing in this function.
3116 * @param array stdWrap properties for debug.
3117 * @return string The processed input value
3118 */
3119 public function stdWrap_debug($content = '', $conf = array()) {
3120 $content = '<pre>' . htmlspecialchars($content) . '</pre>';
3121 return $content;
3122 }
3123
3124 /**
3125 * debugFunc
3126 * Will output the content in a debug table
3127 *
3128 * @param string Input value undergoing processing in this function.
3129 * @param array stdWrap properties for debugFunc.
3130 * @return string The processed input value
3131 */
3132 public function stdWrap_debugFunc($content =