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