|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 /** 00028 * Contains classes for Content Rendering based on TypoScript Template configuration 00029 * 00030 * $Id: class.tslib_content.php 10547 2011-02-22 20:03:57Z lolli $ 00031 * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj 00032 * XHTML compliant 00033 * 00034 * class tslib_cObj : All main TypoScript features, rendering of content objects (cObjects). This class is the backbone of TypoScript Template rendering. 00035 * class tslib_controlTable : Makes a table CTABLE (TS cObject) 00036 * class tslib_tableOffset : Makes a table-offset (TS) 00037 * class tslib_frameset : Generates framesets (TS) 00038 * 00039 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00040 */ 00041 /** 00042 * [CLASS/FUNCTION INDEX of SCRIPT] 00043 * 00044 * 00045 * 00046 * 256: class tslib_cObj 00047 * 353: function start($data,$table='') 00048 * 387: function setParent($data,$currentRecord) 00049 * 00050 * SECTION: CONTENT_OBJ: 00051 * 412: function getCurrentVal() 00052 * 423: function setCurrentVal($value) 00053 * 436: function cObjGet($setup,$addKey='') 00054 * 460: function cObjGetSingle($name,$conf,$TSkey='__') 00055 * 00056 * SECTION: Functions rendering content objects (cObjects) 00057 * 629: function HTML($conf) 00058 * 640: function TEXT($conf) 00059 * 651: function CLEARGIF($conf) 00060 * 670: function COBJ_ARRAY($conf,$ext='') 00061 * 706: function USER($conf,$ext='') 00062 * 733: function FILE($conf) 00063 * 749: function IMAGE($conf) 00064 * 768: function IMG_RESOURCE($conf) 00065 * 780: function IMGTEXT($conf) 00066 * 1203: function CONTENT($conf) 00067 * 1290: function RECORDS($conf) 00068 * 1370: function HMENU($conf) 00069 * 1402: function CTABLE ($conf) 00070 * 1440: function OTABLE ($conf) 00071 * 1455: function COLUMNS ($conf) 00072 * 1534: function HRULER ($conf) 00073 * 1559: function CASEFUNC ($conf) 00074 * 1584: function LOAD_REGISTER($conf,$name) 00075 * 1624: function FORM($conf,$formData='') 00076 * 2145: function SEARCHRESULT($conf) 00077 * 2311: function PHP_SCRIPT($conf,$ext='') 00078 * 2354: function TEMPLATE($conf) 00079 * 2505: function MULTIMEDIA($conf) 00080 * 00081 * SECTION: Various helper functions for content objects: 00082 * 2592: function getSlidePids($pidList, $pidConf) 00083 * 2623: function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) 00084 * 2641: function cImage($file,$conf) 00085 * 2669: function getBorderAttr($borderAttr) 00086 * 2685: function imageLinkWrap($string,$imageFile,$conf) 00087 * 2765: function fileResource($fName, $addParams='alt="" title=""') 00088 * 2788: function lastChanged($tstamp) 00089 * 2805: function linkWrap($content,$wrap) 00090 * 2824: function getAltParam($conf, $longDesc=TRUE) 00091 * 2859: function cleanFormName($name) 00092 * 2875: function getATagParams($conf, $addGlobal=1) 00093 * 00094 * SECTION: HTML template processing functions 00095 * 2922: function getSubpart($content, $marker) 00096 * 2938: function substituteSubpart($content,$marker,$subpartContent,$recursive=1) 00097 * 2951: function substituteMarker($content,$marker,$markContent) 00098 * 2971: function substituteMarkerArrayCached($content,$markContentArray=array(),$subpartContentArray=array(),$wrappedSubpartContentArray=array()) 00099 * 3069: function substituteMarkerArray($content,$markContentArray,$wrap='',$uppercase=0) 00100 * 3081: function substituteMarkerInObject(&$tree, $markContentArray) 00101 * 3104: function fillInMarkerArray($markContentArray, $row, $fieldList='', $nl2br=TRUE, $prefix='FIELD_', $HSC=FALSE) 00102 * 00103 * SECTION: "stdWrap" + sub functions 00104 * 3167: function stdWrap($content,$conf) 00105 * 3364: function numRows($conf) 00106 * 3388: function listNum($content,$listNum,$char) 00107 * 3408: function checkIf($conf) 00108 * 3471: function filelist($data) 00109 * 3553: function clean_directory($theDir) 00110 * 3571: function HTMLparser_TSbridge($theValue, $conf) 00111 * 3585: function dataWrap($content,$wrap) 00112 * 3598: function insertData($str) 00113 * 3628: function prefixComment($str,$conf,$content) 00114 * 3652: function substring($content,$options) 00115 * 3670: function crop($content,$options) 00116 * 3702: function removeBadHTML($text, $conf) 00117 * 3746: function textStyle($theValue, $conf) 00118 * 3813: function tableStyle($theValue, $conf) 00119 * 3854: function addParams($content,$conf) 00120 * 3895: function filelink($theValue, $conf) 00121 * 3966: function locDataJU($jumpUrl,$conf) 00122 * 3997: function calc($val) 00123 * 4026: function calcIntExplode($delim, $string) 00124 * 4046: function splitObj($value, $conf) 00125 * 4108: function parseFunc($theValue, $conf, $ref='') 00126 * 4218: function _parseFunc ($theValue, $conf) 00127 * 4424: function encaps_lineSplit($theValue, $conf) 00128 * 4507: function http_makelinks($data,$conf) 00129 * 4574: function mailto_makelinks($data,$conf) 00130 * 4617: function getImgResource($file,$fileArray) 00131 * 00132 * SECTION: Data retrieval etc. 00133 * 4810: function getFieldVal($field) 00134 * 4830: function getData($string,$fieldArray) 00135 * 4975: function rootLineValue($key,$field,$slideBack=0,$altRootLine='') 00136 * 4997: function getGlobal($var, $source=NULL) 00137 * 5033: function getKey($key,$arr) 00138 * 5056: function TCAlookup($inputValue,$conf) 00139 * 00140 * SECTION: Link functions (typolink) 00141 * 5116: function typoLink($linktxt, $conf) 00142 * 5481: function typoLink_URL($conf) 00143 * 5499: function getTypoLink($label,$params,$urlParameters=array(),$target='') 00144 * 5526: function getTypoLink_URL($params,$urlParameters=array(),$target='') 00145 * 5538: function typolinkWrap($conf) 00146 * 5551: function currentPageUrl($urlParameters=array(),$id=0) 00147 * 5564: function getClosestMPvalueForPage($pageId, $raw=FALSE) 00148 * 5619: function getMailTo($mailAddress,$linktxt,$initP='?') 00149 * 5658: function getQueryArguments($conf,$overruleQueryArgs=array(),$forceArgs=FALSE) 00150 * 00151 * SECTION: Miscellaneous functions, stand alone 00152 * 5754: function wrap($content,$wrap,$char='|') 00153 * 5770: function noTrimWrap($content,$wrap) 00154 * 5784: function wrapSpace($content, $wrap) 00155 * 5810: function callUserFunction($funcName,$conf,$content) 00156 * 5851: function processParams($params) 00157 * 5869: function keywords($content) 00158 * 5886: function caseshift($theValue, $case) 00159 * 5911: function HTMLcaseshift($theValue, $case) 00160 * 5940: function bytes($sizeInBytes,$labels) 00161 * 5951: function calcAge($seconds,$labels) 00162 * 5983: function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName='', $replyTo='') 00163 * 6010: function URLqMark($url,$params) 00164 * 6026: function checkEmail($email) 00165 * 6038: function clearTSProperties($TSArr,$propList) 00166 * 6057: function mergeTSRef($confArr,$prop) 00167 * 6080: function joinTSarrays($conf,$old_conf) 00168 * 6103: function gifBuilderTextBox($gifbuilderConf, $conf, $text) 00169 * 6159: function linebreaks($string,$chars,$maxLines=0) 00170 * 6190: function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList) 00171 * 00172 * SECTION: Database functions, making of queries 00173 * 6260: function DBgetDelete($table, $uid, $doExec=FALSE) 00174 * 6292: function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec=FALSE) 00175 * 6334: function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec=FALSE) 00176 * 6371: function DBmayFEUserEdit($table,$row, $feUserRow, $allowedGroups='',$feEditSelf=0) 00177 * 6411: function DBmayFEUserEditSelect($table,$feUserRow,$allowedGroups='',$feEditSelf=0) 00178 * 6451: function enableFields($table,$show_hidden=0) 00179 * 6475: function getTreeList($id,$depth,$begin=0,$dontCheckEnableFields=FALSE,$addSelectFields='',$moreWhereClauses='', $prevId_array=array(), $recursionLevel=0) 00180 * 6583: function whereSelectFromList($field,$value) 00181 * 6601: function exec_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='') 00182 * 6628: function exec_mm_query_uidList($select,$local_table_uidlist,$mm_table,$foreign_table='',$whereClause='',$groupBy='',$orderBy='',$limit='') 00183 * 6649: function searchWhere($sw,$searchFieldList,$searchTable='') 00184 * 6685: function exec_getQuery($table, $conf) 00185 * 6703: function getQuery($table, $conf, $returnQueryArray=FALSE) 00186 * 6783: function getWhere($table,$conf, $returnQueryArray=FALSE) 00187 * 6878: function checkPidArray($listArr) 00188 * 6902: function checkPid($uid) 00189 * 00190 * SECTION: Frontend editing functions 00191 * 6959: function editPanel($content, $conf, $currentRecord='', $dataArr=array()) 00192 * 7146: function editIcons($content,$params, $conf=array(), $currentRecord='', $dataArr=array(),$addUrlParamStr='') 00193 * 7228: function editPanelLinkWrap($string,$formName,$cmd,$currentRecord='',$confirm='',$nPid='') 00194 * 7270: function editPanelLinkWrap_doWrap($string,$url,$currentRecord) 00195 * 7298: function editPanelPreviewBorder($table,$row,$content,$thick,$conf=array()) 00196 * 7320: function isDisabled($table,$row) 00197 * 00198 * 00199 * 7351: class tslib_frameset 00200 * 7361: function make($setup) 00201 * 7398: function frameParams($setup, $typeNum) 00202 * 7426: function framesetParams($setup) 00203 * 00204 * 00205 * 7459: class tslib_tableOffset 00206 * 7471: function start($content,$offset) 00207 * 00208 * 00209 * 7549: class tslib_controlTable 00210 * 7584: function start($offset,$cMargins) 00211 * 00212 * TOTAL FUNCTIONS: 135 00213 * (This index is automatically created/updated by the extension "extdeveval") 00214 * 00215 */ 00216 00217 00218 00219 /** 00220 * This class contains all main TypoScript features. 00221 * This includes the rendering of TypoScript content objects (cObjects). 00222 * Is the backbone of TypoScript Template rendering. 00223 * 00224 * There are lots of functions you can use from your include-scripts. 00225 * The class "tslib_cObj" is normally instantiated and referred to as "cObj". 00226 * 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. 00227 * 00228 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00229 * @package TYPO3 00230 * @subpackage tslib 00231 */ 00232 class tslib_cObj { 00233 00234 var $align = array( 00235 'center', 00236 'right', 00237 'left' 00238 ); 00239 00240 /** 00241 * stdWrap functions in their correct order 00242 * 00243 * @see stdWrap() 00244 */ 00245 var $stdWrapOrder = array( 00246 'stdWrapPreProcess' => 'hook', // this is a placeholder for the first Hook 00247 'setContentToCurrent' => 'boolean', 00248 'setContentToCurrent.' => 'array', 00249 'setCurrent' => 'string', 00250 'setCurrent.' => 'array', 00251 'lang.' => 'array', 00252 'data' => 'getText', 00253 'data.' => 'array', 00254 'field' => 'fieldName', 00255 'field.' => 'array', 00256 'current' => 'boolean', 00257 'current.' => 'array', 00258 'cObject' => 'cObject', 00259 'cObject.' => 'array', 00260 'numRows.' => 'array', 00261 'filelist' => 'dir', 00262 'filelist.' => 'array', 00263 'preUserFunc' => 'functionName', 00264 'stdWrapOverride' => 'hook', // this is a placeholder for the second Hook 00265 'override' => 'string', 00266 'override.' => 'array', 00267 'preIfEmptyListNum' => 'listNum', 00268 'preIfEmptyListNum.' => 'array', 00269 'ifEmpty' => 'string', 00270 'ifEmpty.' => 'array', 00271 'ifBlank' => 'string', 00272 'ifBlank.' => 'array', 00273 'listNum' => 'listNum', 00274 'listNum.' => 'array', 00275 'trim' => 'boolean', 00276 'trim.' => 'array', 00277 'stdWrap' => 'stdWrap', 00278 'stdWrap.' => 'array', 00279 'stdWrapProcess' => 'hook', // this is a placeholder for the third Hook 00280 'required' => 'boolean', 00281 'required.' => 'array', 00282 'if.' => 'array', 00283 'fieldRequired' => 'fieldName', 00284 'fieldRequired.' => 'array', 00285 'csConv' => 'string', 00286 'csConv.' => 'array', 00287 'parseFunc' => 'objectpath', 00288 'parseFunc.' => 'array', 00289 'HTMLparser' => 'boolean', 00290 'HTMLparser.' => 'array', 00291 'split.' => 'array', 00292 'prioriCalc' => 'boolean', 00293 'prioriCalc.' => 'array', 00294 'char' => 'integer', 00295 'char.' => 'array', 00296 'intval' => 'boolean', 00297 'intval.' => 'array', 00298 'numberFormat.' => 'array', 00299 'date' => 'dateconf', 00300 'date.' => 'array', 00301 'strftime' => 'strftimeconf', 00302 'strftime.' => 'array', 00303 'age' => 'boolean', 00304 'age.' => 'array', 00305 'case' => 'case', 00306 'case.' => 'array', 00307 'bytes' => 'boolean', 00308 'bytes.' => 'array', 00309 'substring' => 'parameters', 00310 'substring.' => 'array', 00311 'removeBadHTML' => 'boolean', 00312 'removeBadHTML.' => 'array', 00313 'cropHTML' => 'crop', 00314 'cropHTML.' => 'array', 00315 'stripHtml' => 'boolean', 00316 'stripHtml.' => 'array', 00317 'crop' => 'crop', 00318 'crop.' => 'array', 00319 'rawUrlEncode' => 'boolean', 00320 'rawUrlEncode.' => 'array', 00321 'htmlSpecialChars' => 'boolean', 00322 'htmlSpecialChars.' => 'array', 00323 'doubleBrTag' => 'string', 00324 'doubleBrTag.' => 'array', 00325 'br' => 'boolean', 00326 'br.' => 'array', 00327 'brTag' => 'string', 00328 'brTag.' => 'array', 00329 'encapsLines.' => 'array', 00330 'keywords' => 'boolean', 00331 'keywords.' => 'array', 00332 'innerWrap' => 'wrap', 00333 'innerWrap.' => 'array', 00334 'innerWrap2' => 'wrap', 00335 'innerWrap2.' => 'array', 00336 'fontTag' => 'wrap', 00337 'fontTag.' => 'array', 00338 'addParams.' => 'array', 00339 'textStyle.' => 'array', 00340 'tableStyle.' => 'array', 00341 'filelink.' => 'array', 00342 'preCObject' => 'cObject', 00343 'preCObject.' => 'array', 00344 'postCObject' => 'cObject', 00345 'postCObject.' => 'array', 00346 'wrapAlign' => 'align', 00347 'wrapAlign.' => 'array', 00348 'typolink.' => 'array', 00349 'TCAselectItem.' => 'array', 00350 'space' => 'space', 00351 'space.' => 'array', 00352 'spaceBefore' => 'int', 00353 'spaceBefore.' => 'array', 00354 'spaceAfter' => 'int', 00355 'spaceAfter.' => 'array', 00356 'wrap' => 'wrap', 00357 'wrap.' => 'array', 00358 'noTrimWrap' => 'wrap', 00359 'noTrimWrap.' => 'array', 00360 'wrap2' => 'wrap', 00361 'wrap2.' => 'array', 00362 'dataWrap' => 'dataWrap', 00363 'dataWrap.' => 'array', 00364 'prepend' => 'cObject', 00365 'prepend.' => 'array', 00366 'append' => 'cObject', 00367 'append.' => 'array', 00368 'wrap3' => 'wrap', 00369 'wrap3.' => 'array', 00370 'outerWrap' => 'wrap', 00371 'outerWrap.' => 'array', 00372 'insertData' => 'boolean', 00373 'insertData.' => 'array', 00374 'offsetWrap' => 'space', 00375 'offsetWrap.' => 'array', 00376 'postUserFunc' => 'functionName', 00377 'postUserFuncInt' => 'functionName', 00378 'prefixComment' => 'string', 00379 'prefixComment.' => 'array', 00380 'editIcons' => 'string', 00381 'editIcons.' => 'array', 00382 'editPanel' => 'boolean', 00383 'editPanel.' => 'array', 00384 'stdWrapPostProcess' => 'hook', // this is a placeholder for the last Hook 00385 'debug' => 'boolean', 00386 'debug.' => 'array', 00387 'debugFunc' => 'boolean', 00388 'debugFunc.' => 'array', 00389 'debugData' => 'boolean', 00390 'debugData.' => 'array' 00391 ); 00392 00393 /** 00394 * Holds ImageMagick parameters and extensions used for compression 00395 * 00396 * @see IMGTEXT() 00397 * 00398 * 0= Default 00399 * 1= Dont change! (removes all parameters for the image_object!!) 00400 * 1x = GIFs 00401 * 2x = JPGs 00402 */ 00403 var $image_compression = array( 00404 10 => array( 00405 'params' => '', 'ext' => 'gif' 00406 ), 00407 11 => array( 00408 'params' => '-colors 128', 'ext' => 'gif' 00409 ), 00410 12 => array( 00411 'params' => '-colors 64', 'ext' => 'gif' 00412 ), 00413 13 => array( 00414 'params' => '-colors 32', 'ext' => 'gif' 00415 ), 00416 14 => array( 00417 'params' => '-colors 16', 'ext' => 'gif' 00418 ), 00419 15 => array( 00420 'params' => '-colors 8', 'ext' => 'gif' 00421 ), 00422 00423 20 => array( 00424 'params' => '-quality 100', 'ext' => 'jpg' 00425 ), 00426 21 => array( 00427 'params' => '-quality 90', 'ext' => 'jpg' 00428 ), 00429 22 => array( 00430 'params' => '-quality 80', 'ext' => 'jpg' 00431 ), 00432 23 => array( 00433 'params' => '-quality 70', 'ext' => 'jpg' 00434 ), 00435 24 => array( 00436 'params' => '-quality 60', 'ext' => 'jpg' 00437 ), 00438 25 => array( 00439 'params' => '-quality 50', 'ext' => 'jpg' 00440 ), 00441 26 => array( 00442 'params' => '-quality 40', 'ext' => 'jpg' 00443 ), 00444 27 => array( 00445 'params' => '-quality 30', 'ext' => 'jpg' 00446 ), 00447 28 => array( 00448 'params' => '-quality 20', 'ext' => 'jpg' 00449 ), 00450 00451 30 => array( 00452 'params' => '-colors 256', 'ext' => 'png' 00453 ), 00454 31 => array( 00455 'params' => '-colors 128', 'ext' => 'png' 00456 ), 00457 32 => array( 00458 'params' => '-colors 64', 'ext' => 'png' 00459 ), 00460 33 => array( 00461 'params' => '-colors 32', 'ext' => 'png' 00462 ), 00463 34 => array( 00464 'params' => '-colors 16', 'ext' => 'png' 00465 ), 00466 35 => array( 00467 'params' => '-colors 8', 'ext' => 'png' 00468 ), 00469 39 => array( 00470 'params' => '', 'ext' => 'png' 00471 ), 00472 ); 00473 00474 /** 00475 * ImageMagick parameters for image effects 00476 * 00477 * @see IMGTEXT() 00478 */ 00479 var $image_effects = array( 00480 1 => '-rotate 90', 00481 2 => '-rotate 270', 00482 3 => '-rotate 180', 00483 10 => '-colorspace GRAY', 00484 11 => '-sharpen 70', 00485 20 => '-normalize', 00486 23 => '-contrast', 00487 25 => '-gamma 1.3', 00488 26 => '-gamma 0.8' 00489 ); 00490 00491 /** 00492 * Loaded with the current data-record. 00493 * 00494 * If the instance of this class is used to render records from the database those records are found in this array. 00495 * The function stdWrap has TypoScript properties that fetch field-data from this array. 00496 * @see init() 00497 */ 00498 var $data = array(); 00499 protected $table = ''; 00500 var $oldData = array(); // Used for backup... 00501 var $alternativeData = ''; // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap 00502 var $parameters = array(); // Used by the parseFunc function and is loaded with tag-parameters when parsing tags. 00503 var $currentValKey = 'currentValue_kidjls9dksoje'; 00504 var $currentRecord = ''; // This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered. 00505 var $currentRecordTotal = 0; // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query. 00506 var $currentRecordNumber = 0; // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering. 00507 var $parentRecordNumber = 0; // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering. 00508 var $parentRecord = array(); // If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj. 00509 var $regObj; // This may be set as a reference to the calling object of eg. cObjGetSingle. Anyway, just use it as you like. It's used in productsLib.inc for example. 00510 00511 00512 // internal 00513 var $INT_include = 0; // Is set to 1 if the instance of this cObj is executed from a PHP_SCRIPT_INT -include script (see pagegen, bottom of document) 00514 var $checkPid_cache = array(); // This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request. 00515 var $checkPid_badDoktypeList = '255'; 00516 var $lastTypoLinkUrl = ''; // This will be set by typoLink() to the url of the most recent link created. 00517 var $lastTypoLinkTarget = ''; // DO. link target. 00518 var $lastTypoLinkLD = array(); 00519 var $substMarkerCache = array(); // Caching substituteMarkerArrayCached function 00520 var $recordRegister = array(); // array that registers rendered content elements (or any table) to make sure they are not rendered recursively! 00521 var $cObjHookObjectsArr = array(); // Containig hooks for userdefined cObjects 00522 protected $stdWrapHookObjects = array(); // Containing hook objects for stdWrap 00523 protected $getImgResourceHookObjects; // Containing hook objects for getImgResource 00524 00525 /** 00526 * @var array with members of tslib_content_abstract 00527 */ 00528 protected $contentObjects = array(); 00529 00530 /** 00531 * Set to TRUE by doConvertToUserIntObject() if USER object wants to become USER_INT 00532 */ 00533 public $doConvertToUserIntObject = FALSE; 00534 00535 /** 00536 * Indicates current object type. Can hold one of OBJECTTYPE_ constants or FALSE. 00537 * The value is set and reset inside USER() function. Any time outside of 00538 * USER() it is FALSE. 00539 */ 00540 protected $userObjectType = FALSE; 00541 00542 /** 00543 * Indicates that object type is USER. 00544 * 00545 * @see tslib_cObjh::$userObjectType 00546 */ 00547 const OBJECTTYPE_USER_INT = 1; 00548 00549 /** 00550 * Indicates that object type is USER. 00551 * 00552 * @see tslib_cObjh::$userObjectType 00553 */ 00554 const OBJECTTYPE_USER = 2; 00555 00556 /** 00557 * Class constructor. 00558 * Well, it has to be called manually since it is not a real constructor function. 00559 * 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. 00560 * 00561 * @param array $data the record data that is rendered. 00562 * @param string $table the table that the data record is from. 00563 * @return void 00564 */ 00565 function start($data, $table = '') { 00566 global $TYPO3_CONF_VARS; 00567 $this->data = $data; 00568 $this->table = $table; 00569 $this->currentRecord = $table ? $table . ':' . $this->data['uid'] : ''; 00570 $this->parameters = array(); 00571 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) { 00572 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) { 00573 $this->cObjHookObjectsArr[$classArr[0]] = t3lib_div::getUserObj($classArr[1]); 00574 } 00575 } 00576 00577 $this->stdWrapHookObjects = array(); 00578 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) { 00579 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) { 00580 $hookObject = t3lib_div::getUserObj($classData); 00581 00582 if (!($hookObject instanceof tslib_content_stdWrapHook)) { 00583 throw new UnexpectedValueException( 00584 $classData . ' must implement interface tslib_content_stdWrapHook', 00585 1195043965 00586 ); 00587 } 00588 00589 $this->stdWrapHookObjects[] = $hookObject; 00590 } 00591 } 00592 00593 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) { 00594 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) { 00595 $postInitializationProcessor = t3lib_div::getUserObj($classData); 00596 00597 if (!($postInitializationProcessor instanceof tslib_content_PostInitHook)) { 00598 throw new UnexpectedValueException( 00599 $classData . ' must implement interface tslib_content_PostInitHook', 00600 1274563549 00601 ); 00602 } 00603 00604 $postInitializationProcessor->postProcessContentObjectInitialization($this); 00605 } 00606 } 00607 } 00608 00609 /** 00610 * Clone helper. 00611 * 00612 * Resets the references to the TypoScript Content Object implementation 00613 * objects of tslib_content_*. Otherwise they would still point to the 00614 * original tslib_cObj instance's tslib_content_* instances, they in return 00615 * would back-reference to the original tslib_cObj instance instead of the 00616 * newly cloned tslib_cObj instance. 00617 * 00618 * @see http://bugs.typo3.org/view.php?id=16568 00619 */ 00620 public function __clone() { 00621 $this->contentObjects = array(); 00622 } 00623 00624 /** 00625 * Gets the 'getImgResource' hook objects. 00626 * The first call initializes the accordant objects. 00627 * 00628 * @return array The 'getImgResource' hook objects (if any) 00629 */ 00630 protected function getGetImgResourceHookObjects() { 00631 if (!isset($this->getImgResourceHookObjects)) { 00632 $this->getImgResourceHookObjects = array(); 00633 00634 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) { 00635 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) { 00636 $hookObject = t3lib_div::getUserObj($classData); 00637 00638 if (!($hookObject instanceof tslib_cObj_getImgResourceHook)) { 00639 throw new UnexpectedValueException( 00640 '$hookObject must implement interface tslib_cObj_getImgResourceHook', 00641 1218636383 00642 ); 00643 } 00644 00645 $this->getImgResourceHookObjects[] = $hookObject; 00646 } 00647 } 00648 } 00649 00650 return $this->getImgResourceHookObjects; 00651 } 00652 00653 /** 00654 * Sets the internal variable parentRecord with information about current record. 00655 * 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. 00656 * 00657 * @param array $data: The record array 00658 * @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. 00659 * @return void 00660 * @access private 00661 */ 00662 function setParent($data, $currentRecord) { 00663 $this->parentRecord = array( 00664 'data' => $data, 00665 'currentRecord' => $currentRecord 00666 ); 00667 } 00668 00669 00670 00671 /*********************************************** 00672 * 00673 * CONTENT_OBJ: 00674 * 00675 ***********************************************/ 00676 00677 /** 00678 * Returns the "current" value. 00679 * 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. 00680 * It's like "load accumulator" in the good old C64 days... basically a "register" you can use as you like. 00681 * 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. 00682 * 00683 * @return mixed The "current" value 00684 */ 00685 function getCurrentVal() { 00686 return $this->data[$this->currentValKey]; 00687 } 00688 00689 /** 00690 * Sets the "current" value. 00691 * 00692 * @param mixed The variable that you want to set as "current" 00693 * @return void 00694 * @see getCurrentVal() 00695 */ 00696 function setCurrentVal($value) { 00697 $this->data[$this->currentValKey] = $value; 00698 } 00699 00700 /** 00701 * Rendering of a "numerical array" of cObjects from TypoScript 00702 * Will call ->cObjGetSingle() for each cObject found and accumulate the output. 00703 * 00704 * @param array $setup: array with cObjects as values. 00705 * @param string $addKey: A prefix for the debugging information 00706 * @return string Rendered output from the cObjects in the array. 00707 * @see cObjGetSingle() 00708 */ 00709 function cObjGet($setup, $addKey = '') { 00710 if (is_array($setup)) { 00711 $sKeyArray = t3lib_TStemplate::sortedKeyList($setup); 00712 $content = ''; 00713 foreach ($sKeyArray as $theKey) { 00714 $theValue = $setup[$theKey]; 00715 if (intval($theKey) && !strstr($theKey, '.')) { 00716 $conf = $setup[$theKey . '.']; 00717 $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey); // Get the contentObject 00718 } 00719 } 00720 return $content; 00721 } 00722 } 00723 00724 /** 00725 * Renders a content object 00726 * 00727 * @param string The content object name, eg. "TEXT" or "USER" or "IMAGE" 00728 * @param array The array with TypoScript properties for the content object 00729 * @param string A string label used for the internal debugging tracking. 00730 * @return string cObject output 00731 */ 00732 function cObjGetSingle($name, $conf, $TSkey = '__') { 00733 global $TYPO3_CONF_VARS; 00734 00735 $content = ''; 00736 // Checking that the function is not called eternally. This is done by interrupting at a depth of 100 00737 $GLOBALS['TSFE']->cObjectDepthCounter--; 00738 if ($GLOBALS['TSFE']->cObjectDepthCounter > 0) { 00739 $name = trim($name); 00740 if ($GLOBALS['TT']->LR) 00741 $GLOBALS['TT']->push($TSkey, $name); 00742 00743 // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something') 00744 if (substr($name, 0, 1) == '<') { 00745 $key = trim(substr($name, 1)); 00746 $cF = t3lib_div::makeInstance('t3lib_TSparser'); 00747 // $name and $conf is loaded with the referenced values. 00748 $old_conf = $conf; 00749 list ($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup); 00750 if (is_array($old_conf) && count($old_conf)) { 00751 $conf = $this->joinTSarrays($conf, $old_conf); 00752 } 00753 // Getting the cObject 00754 $GLOBALS['TT']->incStackPointer(); 00755 $content .= $this->cObjGetSingle($name, $conf, $key); 00756 $GLOBALS['TT']->decStackPointer(); 00757 } else { 00758 00759 $hooked = FALSE; 00760 // Application defined cObjects 00761 foreach ($this->cObjHookObjectsArr as $cObjName => $hookObj) { 00762 if (($name === $cObjName) && method_exists($hookObj, 'cObjGetSingleExt')) { 00763 $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this); 00764 $hooked = TRUE; 00765 } 00766 } 00767 if (!$hooked) { 00768 $contentObject = $this->getContentObject($name); 00769 if ($contentObject) { 00770 $content .= $contentObject->render($conf); 00771 } else { 00772 // call hook functions for extra processing 00773 if ($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) { 00774 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) { 00775 $hookObject = t3lib_div::getUserObj($classData); 00776 00777 if (!($hookObject instanceof tslib_content_cObjGetSingleHook)) { 00778 throw new UnexpectedValueException( 00779 '$hookObject must implement interface tslib_content_cObjGetSingleHook', 00780 1195043731 00781 ); 00782 } 00783 /* @var $hookObject tslib_content_cObjGetSingleHook */ 00784 $content .= $hookObject->getSingleContentObject($name, (array) $conf, $TSkey, $this); 00785 } 00786 } else { 00787 // log error in AdminPanel 00788 $warning = sprintf('Content Object "%s" does not exist', $name); 00789 $GLOBALS['TT']->setTSlogMessage($warning, 2); 00790 } 00791 } 00792 } 00793 } 00794 if ($GLOBALS['TT']->LR) 00795 $GLOBALS['TT']->pull($content); 00796 } 00797 // Increasing on exit... 00798 $GLOBALS['TSFE']->cObjectDepthCounter++; 00799 return $content; 00800 } 00801 00802 /** 00803 * Returns a new content object of type $name. 00804 * 00805 * @param string $name 00806 * @return tslib_content_abstract 00807 */ 00808 public function getContentObject($name) { 00809 $classMapping = array( 00810 'HTML' => 'Html', 00811 'TEXT' => 'Text', 00812 'CASE' => 'Case', 00813 'CLEARGIF' => 'ClearGif', 00814 'COBJ_ARRAY' => 'ContentObjectArray', 00815 'COA' => 'ContentObjectArray', 00816 'COA_INT' => 'ContentObjectArrayInternal', 00817 'USER' => 'User', 00818 'USER_INT' => 'UserInternal', 00819 'FILE' => 'File', 00820 'IMAGE' => 'Image', 00821 'IMG_RESOURCE' => 'ImageResource', 00822 'IMGTEXT' => 'ImageText', 00823 'CONTENT' => 'Content', 00824 'RECORDS' => 'Records', 00825 'HMENU' => 'HierarchicalMenu', 00826 'CTABLE' => 'ContentTable', 00827 'OTABLE' => 'OffsetTable', 00828 'COLUMNS' => 'Columns', 00829 'HRULER' => 'HorizontalRuler', 00830 'CASEFUNC' => 'Case', 00831 'LOAD_REGISTER' => 'LoadRegister', 00832 'RESTORE_REGISTER' => 'RestoreRegister', 00833 'FORM' => 'Form', 00834 'SEARCHRESULT' => 'SearchResult', 00835 'PHP_SCRIPT' => 'PhpScript', 00836 'PHP_SCRIPT_INT' => 'PhpScriptInternal', 00837 'PHP_SCRIPT_EXT' => 'PhpScriptExternal', 00838 'TEMPLATE' => 'Template', 00839 'FLUIDTEMPLATE' => 'FluidTemplate', 00840 'MULTIMEDIA' => 'Multimedia', 00841 'MEDIA' => 'Media', 00842 'SWFOBJECT' => 'ShockwaveFlashObject', 00843 'QTOBJECT' => 'QuicktimeObject', 00844 'SVG' => 'ScalableVectorGraphics', 00845 'EDITPANEL' => 'EditPanel', 00846 ); 00847 $name = $classMapping[$name]; 00848 00849 if (!array_key_exists($name, $this->contentObjects)) { 00850 try { 00851 $this->contentObjects[$name] = t3lib_div::makeInstance('tslib_content_' . $name, $this); 00852 } catch (ReflectionException $e) { 00853 $this->contentObjects[$name] = NULL; 00854 } 00855 } 00856 return $this->contentObjects[$name]; 00857 } 00858 00859 00860 /******************************************** 00861 * 00862 * Functions rendering content objects (cObjects) 00863 * 00864 ********************************************/ 00865 00866 /** 00867 * Rendering the cObject, HTML 00868 * 00869 * @param array array of TypoScript properties 00870 * @return string Output 00871 */ 00872 function HTML($conf) { 00873 return $this->getContentObject('HTML')->render($conf); 00874 } 00875 00876 /** 00877 * Rendering the cObject, TEXT 00878 * 00879 * @param array array of TypoScript properties 00880 * @return string Output 00881 */ 00882 function TEXT($conf) { 00883 return $this->getContentObject('TEXT')->render($conf); 00884 } 00885 00886 /** 00887 * Rendering the cObject, CLEARGIF 00888 * 00889 * @param array array of TypoScript properties 00890 * @return string Output 00891 */ 00892 function CLEARGIF($conf) { 00893 return $this->getContentObject('CLEARGIF')->render($conf); 00894 } 00895 00896 /** 00897 * Rendering the cObject, COBJ_ARRAY / COA and COBJ_ARRAY_INT 00898 * 00899 * @param array array of TypoScript properties 00900 * @param string If "INT" then the cObject is a "COBJ_ARRAY_INT" (non-cached), otherwise just "COBJ_ARRAY" (cached) 00901 * @return string Output 00902 */ 00903 function COBJ_ARRAY($conf, $ext = '') { 00904 if ($ext === 'INT') { 00905 return $this->getContentObject('COA_INT')->render($conf); 00906 } else { 00907 return $this->getContentObject('COA')->render($conf); 00908 } 00909 } 00910 00911 /** 00912 * Rendering the cObject, USER and USER_INT 00913 * 00914 * @param array array of TypoScript properties 00915 * @param string If "INT" then the cObject is a "USER_INT" (non-cached), otherwise just "USER" (cached) 00916 * @return string Output 00917 */ 00918 function USER($conf, $ext = '') { 00919 if ($ext === 'INT') { 00920 return $this->getContentObject('USER_INT')->render($conf); 00921 } else { 00922 return $this->getContentObject('USER')->render($conf); 00923 } 00924 } 00925 00926 /** 00927 * Retrieves a type of object called as USER or USER_INT. Object can detect their 00928 * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the 00929 * current object execution. In all other cases it will return FALSE to indicate 00930 * a call out of context. 00931 * 00932 * @return mixed One of OBJECTTYPE_ class constants or FALSE 00933 */ 00934 public function getUserObjectType() { 00935 return $this->userObjectType; 00936 } 00937 00938 /** 00939 * Sets the user object type 00940 * 00941 * @param mixed $userObjectType 00942 * @return void 00943 */ 00944 public function setUserObjectType($userObjectType) { 00945 $this->userObjectType = $userObjectType; 00946 } 00947 00948 /** 00949 * Requests the current USER object to be converted to USER_INT. 00950 * 00951 * @return void 00952 */ 00953 public function convertToUserIntObject() { 00954 if ($this->userObjectType !== self::OBJECTTYPE_USER) { 00955 $GLOBALS['TT']->setTSlogMessage('tslib_cObj::convertToUserIntObject() ' . 'is called in the wrong context or for the wrong object type', 2); 00956 } else { 00957 $this->doConvertToUserIntObject = TRUE; 00958 } 00959 } 00960 00961 /** 00962 * Rendering the cObject, FILE 00963 * 00964 * @param array array of TypoScript properties 00965 * @return string Output 00966 */ 00967 function FILE($conf) { 00968 return $this->getContentObject('FILE')->render($conf); 00969 } 00970 00971 /** 00972 * Rendering the cObject, IMAGE 00973 * 00974 * @param array array of TypoScript properties 00975 * @return string Output 00976 * @see cImage() 00977 */ 00978 function IMAGE($conf) { 00979 return $this->getContentObject('IMAGE')->render($conf); 00980 } 00981 00982 /** 00983 * Rendering the cObject, IMG_RESOURCE 00984 * 00985 * @param array array of TypoScript properties 00986 * @return string Output 00987 * @see getImgResource() 00988 */ 00989 function IMG_RESOURCE($conf) { 00990 return $this->getContentObject('IMG_RESOURCE')->render($conf); 00991 } 00992 00993 /** 00994 * Rendering the cObject, IMGTEXT 00995 * 00996 * @param array array of TypoScript properties 00997 * @return string Output 00998 */ 00999 function IMGTEXT($conf) { 01000 return $this->getContentObject('IMGTEXT')->render($conf); 01001 } 01002 01003 /** 01004 * Rendering the cObject, CONTENT 01005 * 01006 * @param array array of TypoScript properties 01007 * @return string Output 01008 */ 01009 function CONTENT($conf) { 01010 return $this->getContentObject('CONTENT')->render($conf); 01011 } 01012 01013 /** 01014 * Rendering the cObject, RECORDS 01015 * 01016 * @param array array of TypoScript properties 01017 * @return string Output 01018 */ 01019 function RECORDS($conf) { 01020 return $this->getContentObject('RECORDS')->render($conf); 01021 } 01022 01023 /** 01024 * Rendering the cObject, HMENU 01025 * 01026 * @param array array of TypoScript properties 01027 * @return string Output 01028 */ 01029 function HMENU($conf) { 01030 return $this->getContentObject('HMENU')->render($conf); 01031 } 01032 01033 /** 01034 * Rendering the cObject, CTABLE 01035 * 01036 * @param array array of TypoScript properties 01037 * @return string Output 01038 */ 01039 function CTABLE($conf) { 01040 return $this->getContentObject('CTABLE')->render($conf); 01041 } 01042 01043 /** 01044 * Rendering the cObject, OTABLE 01045 * 01046 * @param array array of TypoScript properties 01047 * @return string Output 01048 */ 01049 function OTABLE($conf) { 01050 return $this->getContentObject('OTABLE')->render($conf); 01051 } 01052 01053 /** 01054 * Rendering the cObject, COLUMNS 01055 * 01056 * @param array array of TypoScript properties 01057 * @return string Output 01058 */ 01059 function COLUMNS($conf) { 01060 return $this->getContentObject('COLUMNS')->render($conf); 01061 } 01062 01063 /** 01064 * Rendering the cObject, HRULER 01065 * 01066 * @param array array of TypoScript properties 01067 * @return string Output 01068 */ 01069 function HRULER($conf) { 01070 return $this->getContentObject('HRULER')->render($conf); 01071 } 01072 01073 /** 01074 * Rendering the cObject, CASE 01075 * 01076 * @param array array of TypoScript properties 01077 * @return string Output 01078 */ 01079 function CASEFUNC($conf) { 01080 return $this->getContentObject('CASE')->render($conf); 01081 } 01082 01083 /** 01084 * Rendering the cObject, LOAD_REGISTER and RESTORE_REGISTER 01085 * NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties. 01086 * 01087 * @param array array of TypoScript properties 01088 * @param string If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER" 01089 * @return string Empty string (the cObject only sets internal data!) 01090 */ 01091 function LOAD_REGISTER($conf, $name) { 01092 if ($name === 'RESTORE_REGISTER') { 01093 return $this->getContentObject('RESTORE_REGISTER')->render($conf); 01094 } else { 01095 return $this->getContentObject('LOAD_REGISTER')->render($conf); 01096 } 01097 } 01098 01099 /** 01100 * Rendering the cObject, FORM 01101 * 01102 * @param array array of TypoScript properties 01103 * @param array Alternative formdata overriding whatever comes from TypoScript 01104 * @return string Output 01105 */ 01106 function FORM($conf, $formData = '') { 01107 return $this->getContentObject('FORM')->render($conf, $formData); 01108 } 01109 01110 /** 01111 * Rendering the cObject, SEARCHRESULT 01112 * 01113 * @param array array of TypoScript properties 01114 * @return string Output 01115 */ 01116 function SEARCHRESULT($conf) { 01117 return $this->getContentObject('SEARCHRESULT')->render($conf); 01118 } 01119 01120 /** 01121 * Rendering the cObject, PHP_SCRIPT, PHP_SCRIPT_INT and PHP_SCRIPT_EXT 01122 * 01123 * @param array array of TypoScript properties 01124 * @param string If "INT", then rendering "PHP_SCRIPT_INT"; If "EXT", then rendering "PHP_SCRIPT_EXT"; Default is rendering "PHP_SCRIPT" (cached) 01125 * @return string Output 01126 */ 01127 function PHP_SCRIPT($conf, $ext = '') { 01128 if ($ext === 'INT' || $ext === 'EXT') { 01129 $conf['scriptSuffix'] = $ext; 01130 return $this->getContentObject('PHP_SCRIPT_INT')->render($conf); 01131 } else { 01132 return $this->getContentObject('PHP_SCRIPT')->render($conf); 01133 } 01134 } 01135 01136 /** 01137 * Rendering the cObject, TEMPLATE 01138 * 01139 * @param array array of TypoScript properties 01140 * @return string Output 01141 * @see substituteMarkerArrayCached() 01142 */ 01143 function TEMPLATE($conf) { 01144 return $this->getContentObject('TEMPLATE')->render($conf); 01145 } 01146 01147 /** 01148 * Rendering the cObject, FLUIDTEMPLATE 01149 * 01150 * @param array array of TypoScript properties 01151 * @return string the HTML output 01152 * @author Steffen Ritter <info@steffen-ritter.net> 01153 * @author Benjamin Mack <benni@typo3.org> 01154 */ 01155 protected function FLUIDTEMPLATE(array $conf) { 01156 return $this->getContentObject('FLUIDTEMPLATE')->render($conf); 01157 } 01158 01159 /** 01160 * Rendering the cObject, MULTIMEDIA 01161 * 01162 * @param array array of TypoScript properties 01163 * @return string Output 01164 */ 01165 function MULTIMEDIA($conf) { 01166 return $this->getContentObject('MULTIMEDIA')->render($conf); 01167 } 01168 01169 /** 01170 * Rendering the cObject, MEDIA 01171 * 01172 * @param array array of TypoScript properties 01173 * @return string Output 01174 */ 01175 public function MEDIA($conf) { 01176 return $this->getContentObject('MEDIA')->render($conf); 01177 } 01178 01179 /** 01180 * Rendering the cObject, SWFOBJECT 01181 * 01182 * @param array array of TypoScript properties 01183 * @return string Output 01184 */ 01185 public function SWFOBJECT($conf) { 01186 return $this->getContentObject('SWFOBJECT')->render($conf); 01187 } 01188 01189 /** 01190 * Rendering the cObject, QTOBJECT 01191 * 01192 * @param array array of TypoScript properties 01193 * @return string Output 01194 */ 01195 public function QTOBJECT($conf) { 01196 return $this->getContentObject('QTOBJECT')->render($conf); 01197 } 01198 01199 /** 01200 * Rendering the cObject, SVG 01201 * 01202 * @param array array of TypoScript properties 01203 * @return string Output 01204 */ 01205 public function SVG($conf) { 01206 return $this->getContentObject('SVG')->render($conf); 01207 } 01208 01209 /************************************ 01210 * 01211 * Various helper functions for content objects: 01212 * 01213 ************************************/ 01214 01215 01216 /** 01217 * Converts a given config in Flexform to a conf-array 01218 * @param string Flexform data 01219 * @param array array to write the data into, by reference 01220 * @param boolean is set if called recursive. Don't call function with this parameter, it's used inside the function only 01221 * @access public 01222 * 01223 */ 01224 public function readFlexformIntoConf($flexData, &$conf, $recursive = FALSE) { 01225 if ($recursive === FALSE) { 01226 $flexData = t3lib_div::xml2array($flexData, 'T3'); 01227 } 01228 01229 if (is_array($flexData)) { 01230 if (isset($flexData['data']['sDEF']['lDEF'])) { 01231 $flexData = $flexData['data']['sDEF']['lDEF']; 01232 } 01233 01234 foreach ($flexData as $key => $value) { 01235 if (is_array($value['el']) && count($value['el']) > 0) { 01236 foreach ($value['el'] as $ekey => $element) { 01237 if (isset($element['vDEF'])) { 01238 $conf[$ekey] = $element['vDEF']; 01239 } else { 01240 if (is_array($element)) { 01241 $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE); 01242 } else { 01243 $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE); 01244 } 01245 } 01246 } 01247 } else { 01248 $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE); 01249 } 01250 if ($value['vDEF']) { 01251 $conf[$key] = $value['vDEF']; 01252 } 01253 } 01254 } 01255 } 01256 01257 01258 /** 01259 * Returns all parents of the given PID (Page UID) list 01260 * 01261 * @param string A list of page Content-Element PIDs (Page UIDs) / stdWrap 01262 * @param array stdWrap array for the list 01263 * @return string A list of PIDs 01264 * @access private 01265 */ 01266 function getSlidePids($pidList, $pidConf) { 01267 $pidList = isset($pidConf) 01268 ? trim($this->stdWrap($pidList, $pidConf)) 01269 : trim($pidList); 01270 if (!strcmp($pidList, '')) { 01271 $pidList = 'this'; 01272 } 01273 if (trim($pidList)) { 01274 $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $pidList)); 01275 $listArr = $this->checkPidArray($listArr); 01276 } 01277 $pidList = array(); 01278 if (is_array($listArr) && count($listArr)) { 01279 foreach ($listArr as $uid) { 01280 $page = $GLOBALS['TSFE']->sys_page->getPage($uid); 01281 if (!$page['is_siteroot']) { 01282 $pidList[] = $page['pid']; 01283 } 01284 } 01285 } 01286 return implode(',', $pidList); 01287 } 01288 01289 /** 01290 * Returns a default value for a form field in the FORM cObject. 01291 * Page CANNOT be cached because that would include the inserted value for the current user. 01292 * 01293 * @param boolean If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned. 01294 * @param string $fieldName: The POST var name to get default value for 01295 * @param string $defaultVal: The current default value 01296 * @return string The default value, either from INPUT var or the current default, based on whether caching is enabled or not. 01297 * @access private 01298 */ 01299 function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) { 01300 if (!$GLOBALS['TSFE']->no_cache || (!isset($_POST[$fieldName]) && !isset($_GET[$fieldName])) || $noValueInsert) { 01301 return $defaultVal; 01302 } else { 01303 return t3lib_div::_GP($fieldName); 01304 } 01305 } 01306 01307 /** 01308 * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array. 01309 * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript. 01310 * This function is called by "$this->cImage($conf['file'],$conf);" from IMAGE(). 01311 * 01312 * @param string File TypoScript resource 01313 * @param array TypoScript configuration properties 01314 * @return string <img> tag, (possibly wrapped in links and other HTML) if any image found. 01315 * @access private 01316 * @see IMAGE() 01317 */ 01318 function cImage($file, $conf) { 01319 $info = $this->getImgResource($file, $conf['file.']); 01320 $GLOBALS['TSFE']->lastImageInfo = $info; 01321 if (is_array($info)) { 01322 $info[3] = t3lib_div::png_to_gif_by_imagemagick($info[3]); 01323 $GLOBALS['TSFE']->imagesOnPage[] = $info[3]; // This array is used to collect the image-refs on the page... 01324 01325 01326 // Backwards compatibility if altText is not set and alttext is set 01327 // @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6 01328 if (strlen($conf['alttext']) || is_array($conf['alttext.'])) { 01329 $GLOBALS['TSFE']->logDeprecatedTyposcript( 01330 'IMAGE.alttext', 01331 'use IMAGE.altText instead - src: ' . $info[3] . ' - original image: ' . $info['origFile'] 01332 ); 01333 if (!strlen($conf['altText']) && !is_array($conf['altText.'])) { 01334 $conf['altText'] = $conf['alttext']; 01335 $conf['altText.'] = $conf['alttext.']; 01336 } 01337 } 01338 01339 $altParam = $this->getAltParam($conf); 01340 if($conf['params'] && !isset($conf['params.'])) { 01341 $params = ' ' . $conf['params']; 01342 } else { 01343 $params = isset($conf['params.']) 01344 ? ' ' . $this->stdWrap($conf['params'], $conf['params.']) 01345 : ''; 01346 } 01347 $theValue = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . 01348 t3lib_div::rawUrlEncodeFP($info[3])) . '" width="' . $info[0] . '" height="' . $info[1] . '"' . 01349 $this->getBorderAttr(' border="' . intval($conf['border']) . '"') . 01350 $params . 01351 ($altParam) . ' />'; 01352 $linkWrap = isset($conf['linkWrap.']) 01353 ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.']) 01354 : $conf['linkWrap']; 01355 if ($linkWrap) { 01356 $theValue = $this->linkWrap($theValue, $linkWrap); 01357 } elseif ($conf['imageLinkWrap']) { 01358 $theValue = $this->imageLinkWrap($theValue, $info['origFile'], $conf['imageLinkWrap.']); 01359 } 01360 $wrap = isset($conf['wrap.']) 01361 ? $this->stdWrap($conf['wrap'], $conf['wrap.']) 01362 : $conf['wrap']; 01363 if($wrap) { 01364 $theValue = $this->wrap($theValue, $conf['wrap']); 01365 } 01366 return $theValue; 01367 } 01368 } 01369 01370 /** 01371 * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict, xhtml_11, xhtml_2 or html5 01372 * or if the config parameter 'disableImgBorderAttr' is not set. 01373 * 01374 * @param string the border attribute 01375 * @return string the border attribute 01376 */ 01377 function getBorderAttr($borderAttr) { 01378 if (! t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype) && 01379 $GLOBALS['TSFE']->config['config']['doctype'] != 'html5' && 01380 ! $GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) { 01381 return $borderAttr; 01382 } 01383 } 01384 01385 /** 01386 * Wraps the input string in link-tags that opens the image in a new window. 01387 * 01388 * @param string String to wrap, probably an <img> tag 01389 * @param string The original image file 01390 * @param array TypoScript properties for the "imageLinkWrap" function 01391 * @return string The input string, $string, wrapped as configured. 01392 * @see cImage() 01393 */ 01394 function imageLinkWrap($string, $imageFile, $conf) { 01395 $a1 = ''; 01396 $a2 = ''; 01397 $content = $string; 01398 $enable = isset($conf['enable.']) 01399 ? $this->stdWrap($conf['enable'], $conf['enable.']) 01400 : $conf['enable']; 01401 if ($enable) { 01402 $content = $this->typolink($string, $conf['typolink.']); 01403 if(isset($conf['file.'])) { 01404 $imageFile = $this->stdWrap($imageFile, $conf['file.']); 01405 } 01406 01407 // imageFileLink: 01408 if ($content == $string && @is_file($imageFile)) { 01409 $parameterNames = array('width', 'height', 'effects', 'alternativeTempPath', 'bodyTag', 'title', 'wrap'); 01410 $parameters = array(); 01411 01412 $sample = isset($conf['sample.']) 01413 ? $this->stdWrap($conf['sample'], $conf['sample.']) 01414 : $conf['sample']; 01415 if ($sample) { 01416 $parameters['sample'] = 1; 01417 } 01418 01419 foreach ($parameterNames as $parameterName) { 01420 if(isset($conf[$parameterName.'.'])) { 01421 $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName.'.']); 01422 } 01423 if (isset($conf[$parameterName]) && $conf[$parameterName]) { 01424 $parameters[$parameterName] = $conf[$parameterName]; 01425 } 01426 } 01427 01428 $parametersEncoded = base64_encode(serialize($parameters)); 01429 01430 $md5_value = t3lib_div::hmac( 01431 implode( 01432 '|', 01433 array($imageFile, $parametersEncoded) 01434 ) 01435 ); 01436 01437 $params = '&md5=' . $md5_value; 01438 foreach (str_split($parametersEncoded, 64) as $index => $chunk) { 01439 $params .= '¶meters[' . $index . ']=' . rawurlencode($chunk); 01440 } 01441 01442 $url = $GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . rawurlencode($imageFile) . $params; 01443 01444 $directImageLink = isset($conf['directImageLink.']) 01445 ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.']) 01446 : $conf['directImageLink']; 01447 if ($directImageLink) { 01448 $imgResourceConf = array( 01449 'file' => $imageFile, 01450 'file.' => $conf 01451 ); 01452 $url = $this->IMG_RESOURCE($imgResourceConf); 01453 if (!$url) { 01454 // if no imagemagick / gm is available 01455 $url = $imageFile; 01456 } 01457 } 01458 01459 // Create TARGET-attribute only if the right doctype is used 01460 if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) { 01461 $target = isset($conf['target.']) 01462 ? $this-stdWrap($conf['target'], $conf['target.']) 01463 : $conf['target']; 01464 if(!$target) { 01465 $target = sprintf(' target="%s"', $target); 01466 } else { 01467 $target = ' target="thePicture"'; 01468 } 01469 } else { 01470 $target = ''; 01471 } 01472 $conf['JSwindow'] = isset($conf['JSwindow.']) 01473 ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.']) 01474 : $conf['JSwindow']; 01475 if ($conf['JSwindow']) { 01476 if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) { 01477 $altUrl = isset($conf['JSwindow.']['altUrl.']) 01478 ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.']) 01479 : $conf['JSwindow.']['altUrl']; 01480 if ($altUrl) { 01481 $url = $altUrl . 01482 ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' . 01483 rawurlencode($imageFile) . $params); 01484 } 01485 } 01486 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder'); 01487 $gifCreator->init(); 01488 $gifCreator->mayScaleUp = 0; 01489 01490 $dims = $gifCreator->getImageScale($gifCreator->getImageDimensions($imageFile), $conf['width'], $conf['height'], ''); 01491 $JSwindowExpand = isset($conf['JSwindow.']['expand.']) 01492 ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.']) 01493 : $conf['JSwindow.']['expand']; 01494 $offset = t3lib_div::intExplode(',', $JSwindowExpand . ','); 01495 01496 $newWindow = isset($conf['JSwindow.']['newWindow.']) 01497 ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.']) 01498 : $conf['JSwindow.']['newWindow']; 01499 $a1 = '<a href="' . htmlspecialchars($url) . '" onclick="' . 01500 htmlspecialchars('openPic(\'' . $GLOBALS['TSFE']->baseUrlWrap($url) . '\',\'' . 01501 ($newWindow ? md5($url) : 'thePicture') . '\',\'width=' . 01502 ($dims[0] + $offset[0]) . ',height=' . ($dims[1] + $offset[1]) . 01503 ',status=0,menubar=0\'); return false;') . '"' . 01504 $target . $GLOBALS['TSFE']->ATagParams . '>'; 01505 $a2 = '</a>'; 01506 $GLOBALS['TSFE']->setJS('openPic'); 01507 } else { 01508 $conf['linkParams.']['parameter'] = $url; 01509 $string = $this->typoLink($string, $conf['linkParams.']); 01510 } 01511 01512 if(isset($conf['stdWrap.'])) { 01513 $string = $this->stdWrap($string, $conf['stdWrap.']); 01514 } 01515 01516 $content = $a1 . $string . $a2; 01517 } 01518 } 01519 01520 return $content; 01521 } 01522 01523 /** 01524 * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is. 01525 * 01526 * @param string The filename, being a TypoScript resource data type 01527 * @param string Additional parameters (attributes). Default is empty alt and title tags. 01528 * @return string If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string 01529 * @see FILE() 01530 */ 01531 function fileResource($fName, $addParams = 'alt="" title=""') { 01532 $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName); 01533 if ($incFile) { 01534 $fileinfo = t3lib_div::split_fileref($incFile); 01535 if (t3lib_div::inList('jpg,gif,jpeg,png', $fileinfo['fileext'])) { 01536 $imgFile = $incFile; 01537 $imgInfo = @getImageSize($imgFile); 01538 return '<img src="' . $GLOBALS['TSFE']->absRefPrefix . $imgFile . 01539 '" width="' . $imgInfo[0] . '" height="' . $imgInfo[1] . '"' . 01540 $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />'; 01541 } elseif (filesize($incFile) < 1024 * 1024) { 01542 return $GLOBALS['TSFE']->tmpl->fileContent($incFile); 01543 } 01544 } 01545 } 01546 01547 /** 01548 * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value. 01549 * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content. 01550 * Therefore you should call this function with the last-changed timestamp of any element you display. 01551 * 01552 * @param integer Unix timestamp (number of seconds since 1970) 01553 * @return void 01554 * @see tslib_fe::setSysLastChanged() 01555 */ 01556 function lastChanged($tstamp) { 01557 $tstamp = intval($tstamp); 01558 if ($tstamp > intval($GLOBALS['TSFE']->register['SYS_LASTCHANGED'])) { 01559 $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp; 01560 } 01561 } 01562 01563 /** 01564 * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well. 01565 * 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. 01566 * 01567 * @param string Input string 01568 * @param string A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string 01569 * @return string Wrapped output string 01570 * @see wrap(), cImage(), FILE() 01571 */ 01572 function linkWrap($content, $wrap) { 01573 $wrapArr = explode('|', $wrap); 01574 if (preg_match('/\{([0-9]*)\}/', $wrapArr[0], $reg)) { 01575 if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) { 01576 $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]); 01577 } 01578 } 01579 return trim($wrapArr[0]) . $content . trim($wrapArr[1]); 01580 } 01581 01582 /** 01583 * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element. 01584 * From the $conf array it implements the properties "altText", "titleText" and "longdescURL" 01585 * 01586 * @param array TypoScript configuration properties 01587 * @param boolean If set, the longdesc attribute will be generated - must only be used for img elements! 01588 * @return string Parameter string containing alt and title parameters (if any) 01589 * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink() 01590 */ 01591 function getAltParam($conf, $longDesc = TRUE) { 01592 $altText = isset($conf['altText.']) 01593 ? trim($this->stdWrap($conf['altText'], $conf['altText.'])) 01594 : trim($conf['altText']); 01595 $titleText = isset($conf['titleText.']) 01596 ? trim($this->stdWrap($conf['titleText'], $conf['titleText.'])) 01597 : trim($conf['titleText']); 01598 $longDesc = isset($conf['longdescURL.']) 01599 ? trim($this->stdWrap($conf['longdescURL'], $conf['longdescURL.'])) 01600 : trim($conf['longdescURL']); 01601 01602 // "alt": 01603 $altParam = ' alt="' . htmlspecialchars($altText) . '"'; 01604 01605 // "title": 01606 $emptyTitleHandling = 'useAlt'; 01607 $emptyTitleHandling = isset($conf['emptyTitleHandling.']) 01608 ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.']) 01609 : $conf['emptyTitleHandling']; 01610 // choices: 'keepEmpty' | 'useAlt' | 'removeAttr' 01611 if ($titleText || $emptyTitleHandling == 'keepEmpty') { 01612 $altParam .= ' title="' . htmlspecialchars($titleText) . '"'; 01613 } elseif (!$titleText && $emptyTitleHandling == 'useAlt') { 01614 $altParam .= ' title="' . htmlspecialchars($altText) . '"'; 01615 } 01616 01617 // "longDesc" URL 01618 if ($longDesc) { 01619 $altParam .= ' longdesc="' . htmlspecialchars(strip_tags($longDesc)) . '"'; 01620 } 01621 01622 return $altParam; 01623 } 01624 01625 /** 01626 * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields 01627 * 01628 * @param string Input string 01629 * @return string the cleaned string 01630 * @see FORM() 01631 */ 01632 function cleanFormName($name) { 01633 // turn data[x][y] into data:x:y: 01634 $name = preg_replace('/\[|\]\[?/', ':', trim($name)); 01635 // remove illegal chars like _ 01636 return preg_replace('#[^:a-zA-Z0-9]#', '', $name); 01637 } 01638 01639 /** 01640 * An abstraction method to add parameters to an A tag. 01641 * Uses the ATagParams property. 01642 * 01643 * @param array TypoScript configuration properties 01644 * @param boolean If set, will add the global config.ATagParams to the link 01645 * @return string String containing the parameters to the A tag (if non empty, with a leading space) 01646 * @see IMGTEXT(), filelink(), makelinks(), typolink() 01647 */ 01648 function getATagParams($conf, $addGlobal = 1) { 01649 $aTagParams = ''; 01650 if ($conf['ATagParams.']) { 01651 $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']); 01652 } elseif ($conf['ATagParams']) { 01653 $aTagParams = ' ' . $conf['ATagParams']; 01654 } 01655 if ($addGlobal) { 01656 $aTagParams = ' ' . trim($GLOBALS['TSFE']->ATagParams . $aTagParams); 01657 } 01658 return $aTagParams; 01659 } 01660 01661 /** 01662 * All extension links should ask this function for additional properties to their tags. 01663 * Designed to add for instance an "onclick" property for site tracking systems. 01664 * 01665 * @param string URL of the website 01666 * @return string the additional tag properties 01667 */ 01668 function extLinkATagParams($URL, $TYPE) { 01669 $out = ''; 01670 01671 if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) { 01672 $extLinkATagParamsHandler = t3lib_div::getUserObj( 01673 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler'] 01674 ); 01675 01676 if (method_exists($extLinkATagParamsHandler, 'main')) { 01677 $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this)); 01678 } 01679 } 01680 01681 return trim($out) ? ' ' . trim($out) : ''; 01682 } 01683 01684 01685 01686 /*********************************************** 01687 * 01688 * HTML template processing functions 01689 * 01690 ***********************************************/ 01691 01692 /** 01693 * Returns a subpart from the input content stream. 01694 * A subpart is a part of the input stream which is encapsulated in a 01695 * string matching the input string, $marker. If this string is found 01696 * inside of HTML comment tags the start/end points of the content block 01697 * returned will be that right outside that comment block. 01698 * Example: The contennt string is 01699 * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?" 01700 * If $marker is "###sub1###" then the content returned is 01701 * " World. How are ". The input content string could just as well have 01702 * been "Hello ###sub1### World. How are ###sub1### you?" and the result 01703 * would be the same 01704 * Wrapper for t3lib_parsehtml::getSubpart which behaves identical 01705 * 01706 * @param string The content stream, typically HTML template content. 01707 * @param string The marker string, typically on the form "###[the marker string]###" 01708 * @return string The subpart found, if found. 01709 * @see substituteSubpart(), t3lib_parsehtml::getSubpart() 01710 */ 01711 public function getSubpart($content, $marker) { 01712 return t3lib_parsehtml::getSubpart($content, $marker); 01713 } 01714 01715 /** 01716 * Substitute subpart in input template stream. 01717 * This function substitutes a subpart in $content with the content of 01718 * $subpartContent. 01719 * Wrapper for t3lib_parsehtml::substituteSubpart which behaves identical 01720 * 01721 * @param string The content stream, typically HTML template content. 01722 * @param string The marker string, typically on the form "###[the marker string]###" 01723 * @param mixed The content to insert instead of the subpart found. If a string, then just plain substitution happens (includes removing the HTML comments of the subpart if found). If $subpartContent happens to be an array, it's [0] and [1] elements are wrapped around the EXISTING content of the subpart (fetched by getSubpart()) thereby not removing the original content. 01724 * @param boolean If $recursive is set, the function calls itself with the content set to the remaining part of the content after the second marker. This means that proceding subparts are ALSO substituted! 01725 * @return string The processed HTML content string. 01726 * @see getSubpart(), t3lib_parsehtml::substituteSubpart() 01727 */ 01728 public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) { 01729 return t3lib_parsehtml::substituteSubpart($content, $marker, $subpartContent, $recursive); 01730 } 01731 01732 /** 01733 * Substitues multiple subparts at once 01734 * 01735 * @param string The content stream, typically HTML template content. 01736 * @param array The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content. 01737 * @return string The processed HTML content string. 01738 */ 01739 public function substituteSubpartArray($content, array $subpartsContent) { 01740 return t3lib_parsehtml::substituteSubpartArray($content, $subpartsContent); 01741 } 01742 01743 /** 01744 * Substitutes a marker string in the input content 01745 * (by a simple str_replace()) 01746 * 01747 * @param string The content stream, typically HTML template content. 01748 * @param string The marker string, typically on the form "###[the marker string]###" 01749 * @param mixed The content to insert instead of the marker string found. 01750 * @return string The processed HTML content string. 01751 * @see substituteSubpart() 01752 */ 01753 public function substituteMarker($content, $marker, $markContent) { 01754 return t3lib_parsehtml::substituteMarker($content, $marker, $markContent); 01755 } 01756 01757 /** 01758 * Multi substitution function with caching. 01759 * 01760 * This function should be a one-stop substitution function for working 01761 * with HTML-template. It does not substitute by str_replace but by 01762 * splitting. This secures that the value inserted does not themselves 01763 * contain markers or subparts. 01764 * 01765 * Note that the "caching" won't cache the content of the substition, 01766 * but only the splitting of the template in various parts. So if you 01767 * want only one cache-entry per template, make sure you always pass the 01768 * exact same set of marker/subpart keys. Else you will be flooding the 01769 * users cache table. 01770 * 01771 * This function takes three kinds of substitutions in one: 01772 * $markContentArray is a regular marker-array where the 'keys' are 01773 * substituted in $content with their values 01774 * 01775 * $subpartContentArray works exactly like markContentArray only is whole 01776 * subparts substituted and not only a single marker. 01777 * 01778 * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where 01779 * the subparts pointed to by the main key is wrapped with the 0/1 value 01780 * alternating. 01781 * 01782 * @param string The content stream, typically HTML template content. 01783 * @param array Regular marker-array where the 'keys' are substituted in $content with their values 01784 * @param array Exactly like markContentArray only is whole subparts substituted and not only a single marker. 01785 * @param array An array of arrays with 0/1 keys where the subparts pointed to by the main key is wrapped with the 0/1 value alternating. 01786 * @return string The output content stream 01787 * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE() 01788 */ 01789 public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) { 01790 $GLOBALS['TT']->push('substituteMarkerArrayCached'); 01791 01792 // If not arrays then set them 01793 if (is_null($markContentArray)) 01794 $markContentArray = array(); // Plain markers 01795 if (is_null($subpartContentArray)) 01796 $subpartContentArray = array(); // Subparts being directly substituted 01797 if (is_null($wrappedSubpartContentArray)) 01798 $wrappedSubpartContentArray = array(); // Subparts being wrapped 01799 // Finding keys and check hash: 01800 $sPkeys = array_keys($subpartContentArray); 01801 $wPkeys = array_keys($wrappedSubpartContentArray); 01802 $aKeys = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys); 01803 if (!count($aKeys)) { 01804 $GLOBALS['TT']->pull(); 01805 return $content; 01806 } 01807 asort($aKeys); 01808 $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array( 01809 $content, $aKeys 01810 ))); 01811 if ($this->substMarkerCache[$storeKey]) { 01812 $storeArr = $this->substMarkerCache[$storeKey]; 01813 $GLOBALS['TT']->setTSlogMessage('Cached', 0); 01814 } else { 01815 $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey); 01816 if (!isset($storeArrDat)) { 01817 // Initialize storeArr 01818 $storeArr = array(); 01819 01820 // Finding subparts and substituting them with the subpart as a marker 01821 foreach ($sPkeys as $sPK) { 01822 $content = $this->substituteSubpart($content, $sPK, $sPK); 01823 } 01824 01825 // Finding subparts and wrapping them with markers 01826 foreach ($wPkeys as $wPK) { 01827 $content = $this->substituteSubpart($content, $wPK, array( 01828 $wPK, $wPK 01829 )); 01830 } 01831 01832 // traverse keys and quote them for reg ex. 01833 foreach ($aKeys as $tK => $tV) { 01834 $aKeys[$tK] = preg_quote($tV, '/'); 01835 } 01836 $regex = '/' . implode('|', $aKeys) . '/'; 01837 // Doing regex's 01838 $storeArr['c'] = preg_split($regex, $content); 01839 preg_match_all($regex, $content, $keyList); 01840 $storeArr['k'] = $keyList[0]; 01841 // Setting cache: 01842 $this->substMarkerCache[$storeKey] = $storeArr; 01843 01844 // Storing the cached data: 01845 $GLOBALS['TSFE']->sys_page->storeHash($storeKey, serialize($storeArr), 'substMarkArrayCached'); 01846 01847 $GLOBALS['TT']->setTSlogMessage('Parsing', 0); 01848 } else { 01849 // Unserializing 01850 $storeArr = unserialize($storeArrDat); 01851 // Setting cache: 01852 $this->substMarkerCache[$storeKey] = $storeArr; 01853 $GLOBALS['TT']->setTSlogMessage('Cached from DB', 0); 01854 } 01855 } 01856 01857 // Substitution/Merging: 01858 // Merging content types together, resetting 01859 $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray); 01860 01861 $wSCA_reg = array(); 01862 $content = ''; 01863 // traversing the keyList array and merging the static and dynamic content 01864 foreach ($storeArr['k'] as $n => $keyN) { 01865 $content .= $storeArr['c'][$n]; 01866 if (!is_array($valueArr[$keyN])) { 01867 $content .= $valueArr[$keyN]; 01868 } else { 01869 $content .= $valueArr[$keyN][(intval($wSCA_reg[$keyN]) % 2)]; 01870 $wSCA_reg[$keyN]++; 01871 } 01872 } 01873 $content .= $storeArr['c'][count($storeArr['k'])]; 01874 01875 $GLOBALS['TT']->pull(); 01876 return $content; 01877 } 01878 01879 /** 01880 * Traverses the input $markContentArray array and for each key the marker 01881 * by the same name (possibly wrapped and in upper case) will be 01882 * substituted with the keys value in the array. 01883 * 01884 * This is very useful if you have a data-record to substitute in some 01885 * content. In particular when you use the $wrap and $uppercase values to 01886 * pre-process the markers. Eg. a key name like "myfield" could effectively 01887 * be represented by the marker "###MYFIELD###" if the wrap value 01888 * was "###|###" and the $uppercase boolean TRUE. 01889 * 01890 * @param string The content stream, typically HTML template content. 01891 * @param array The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content. 01892 * @param string A wrap value - [part 1] | [part 2] - for the markers before substitution 01893 * @param boolean If set, all marker string substitution is done with upper-case markers. 01894 * @param boolean If set, all unused marker are deleted. 01895 * @return string The processed output stream 01896 * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE() 01897 */ 01898 public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) { 01899 return t3lib_parsehtml::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused); 01900 } 01901 01902 /** 01903 * Substitute marker array in an array of values 01904 * 01905 * @param mixed If string, then it just calls substituteMarkerArray. If array(and even multi-dim) then for each key/value pair the marker array will be substituted (by calling this function recursively) 01906 * @param array The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content string/array values. 01907 * @return mixed The processed input variable. 01908 * @see substituteMarker() 01909 */ 01910 public function substituteMarkerInObject(&$tree, array $markContentArray) { 01911 if (is_array($tree)) { 01912 foreach ($tree as $key => $value) { 01913 $this->substituteMarkerInObject($tree[$key], $markContentArray); 01914 } 01915 } else { 01916 $tree = $this->substituteMarkerArray($tree, $markContentArray); 01917 } 01918 01919 return $tree; 01920 } 01921 01922 /** 01923 * Adds elements to the input $markContentArray based on the values from 01924 * the fields from $fieldList found in $row 01925 * 01926 * @param array array with key/values being marker-strings/substitution values. 01927 * @param array An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray 01928 * @param string A list of fields from the $row array to add to the $markContentArray array. If empty all fields from $row will be added (unless they are integers) 01929 * @param boolean If set, all values added to $markContentArray will be nl2br()'ed 01930 * @param string Prefix string to the fieldname before it is added as a key in the $markContentArray. Notice that the keys added to the $markContentArray always start and end with "###" 01931 * @param boolean If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance. 01932 * @return array The modified $markContentArray 01933 */ 01934 public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = TRUE, $prefix = 'FIELD_', $HSC = FALSE) { 01935 if ($fieldList) { 01936 $fArr = t3lib_div::trimExplode(',', $fieldList, 1); 01937 foreach ($fArr as $field) { 01938 $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field]) : $row[$field]; 01939 } 01940 } else { 01941 if (is_array($row)) { 01942 foreach ($row as $field => $value) { 01943 if (!t3lib_div::testInt($field)) { 01944 if ($HSC) { 01945 $value = htmlspecialchars($value); 01946 } 01947 01948 $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value) : $value; 01949 } 01950 } 01951 } 01952 } 01953 01954 return $markContentArray; 01955 } 01956 01957 /*********************************************** 01958 * 01959 * "stdWrap" + sub functions 01960 * 01961 ***********************************************/ 01962 01963 /** 01964 * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript. 01965 * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array(holding the TypoScript "stdWrap properties") 01966 * 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. 01967 * 01968 * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData 01969 * 01970 * @param string Input value undergoing processing in this function. Possibly substituted by other values fetched from another source. 01971 * @param array TypoScript "stdWrap properties". 01972 * @return string The processed input value 01973 */ 01974 public function stdWrap($content = '', $conf = array()) { 01975 if (count($this->stdWrapHookObjects)) { 01976 foreach ($this->stdWrapHookObjects as $hookObject) { 01977 if (is_callable(array($hookObject, 'stdWrapPreProcess'))) { 01978 $conf['stdWrapPreProcess'] = 1; 01979 } 01980 ; 01981 if (is_callable(array($hookObject, 'stdWrapOverride'))) { 01982 $conf['stdWrapOverride'] = 1; 01983 } 01984 ; 01985 if (is_callable(array($hookObject, 'stdWrapProcess'))) { 01986 $conf['stdWrapProcess'] = 1; 01987 } 01988 ; 01989 if (is_callable(array($hookObject, 'stdWrapPostProcess'))) { 01990 $conf['stdWrapPostProcess'] = 1; 01991 } 01992 ; 01993 } 01994 } 01995 if (is_array($conf) && count($conf)) { 01996 // check, which of the available stdWrap functions is needed for the current conf Array 01997 // and keep only those but still in the same order 01998 $sortedConf = array_intersect_key($this->stdWrapOrder, $conf); 01999 // functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions 02000 $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap'; 02001 // additional Array to check whether a function has already been executed 02002 $isExecuted = array(); 02003 // additional switch to make sure 'required', 'if' and 'fieldRequired' 02004 // will still stop rendering immediately in case they return false 02005 02006 $this->stdWrapRecursionLevel++; 02007 $this->stopRendering[$this->stdWrapRecursionLevel] = false; 02008 02009 // execute each funtion in the predefined order 02010 foreach ($sortedConf as $stdWrapName => $functionType) { 02011 // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped 02012 if (!$isExecuted[$stdWrapName] && 02013 !$this->stopRendering[$this->stdWrapRecursionLevel]) { 02014 $functionName = rtrim($stdWrapName, '.'); 02015 $functionProperties = $functionName . '.'; 02016 // if there is any code one the next level, check if it contains "official" stdWrap functions 02017 // if yes, execute them first - will make each function stdWrap aware 02018 // so additional stdWrap calls within the functions can be removed, since the result will be the same 02019 // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property 02020 if (count($conf[$functionProperties]) && 02021 !t3lib_div::inList($stdWrapDisabledFunctionTypes, $functionType)) { 02022 if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) { 02023 $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]); 02024 } 02025 } 02026 // get just that part of $conf that is needed for the particular function 02027 $singleConf = array( 02028 $functionName => $conf[$functionName], 02029 $functionProperties => $conf[$functionProperties] 02030 ); 02031 02032 // in this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.'' 02033 if ($functionName == 'spaceBefore' || $functionName == 'spaceAfter') { 02034 $singleConf['space.'] = $conf['space.']; 02035 } 02036 02037 // hand over the whole $conf array to the stdWrapHookObjects 02038 if ($functionType === 'hook') { 02039 $singleConf = $conf; 02040 } 02041 // check if key is still containing something, since it might have been changed by next level stdWrap before 02042 if ((isset($conf[$functionName]) || $conf[$functionProperties]) && 02043 !($functionType == 'boolean' && $conf[$functionName] === '0')) { 02044 //add both keys - with and without the dot - to the set of executed functions 02045 $isExecuted[$functionName] = true; 02046 $isExecuted[$functionProperties] = true; 02047 // call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array 02048 $functionName = 'stdWrap_' . $functionName; 02049 $content = $this->$functionName( 02050 $content, 02051 $singleConf 02052 ); 02053 } 02054 } 02055 } 02056 02057 unset($this->stopRendering[$this->stdWrapRecursionLevel]); 02058 $this->stdWrapRecursionLevel--; 02059 02060 } 02061 return $content; 02062 } 02063 02064 /** 02065 * stdWrap pre process hook 02066 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs 02067 * this hook will execute functions before any other stdWrap function can modify anything 02068 * 02069 * @param string Input value undergoing processing in these functions. 02070 * @param array All stdWrap properties, not just the ones for a particular function. 02071 * @return string The processed input value 02072 */ 02073 public function stdWrap_stdWrapPreProcess($content = '', $conf = array()) { 02074 foreach ($this->stdWrapHookObjects as $hookObject) { 02075 $content = $hookObject->stdWrapPreProcess($content, $conf, $this); 02076 } 02077 return $content; 02078 } 02079 02080 /** 02081 * setContentToCurrent 02082 * actually it just does the contrary: Sets the value of 'current' based on current content 02083 * 02084 * @param string Input value undergoing processing in this function. 02085 * @param array stdWrap properties for setContentToCurrent. 02086 * @return string The processed input value 02087 */ 02088 public function stdWrap_setContentToCurrent($content = '', $conf = array()) { 02089 $this->data[$this->currentValKey] = $content; 02090 return $content; 02091 } 02092 02093 /** 02094 * setCurrent 02095 * Sets the value of 'current' based on the outcome of stdWrap operations 02096 * 02097 * @param string Input value undergoing processing in this function. 02098 * @param array stdWrap properties for setCurrent. 02099 * @return string The processed input value 02100 */ 02101 public function stdWrap_setCurrent($content = '', $conf = array()) { 02102 $this->data[$this->currentValKey] = $conf['setCurrent']; 02103 return $content; 02104 } 02105 02106 /** 02107 * lang 02108 * Translates content based on the language currently used by the FE 02109 * 02110 * @param string Input value undergoing processing in this function. 02111 * @param array stdWrap properties for lang. 02112 * @return string The processed input value 02113 */ 02114 public function stdWrap_lang($content = '', $conf = array()) { 02115 if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) { 02116 $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']]; 02117 } 02118 return $content; 02119 } 02120 02121 /** 02122 * data 02123 * Gets content from different sources based on getText functions, makes use of alternativeData, when set 02124 * 02125 * @param string Input value undergoing processing in this function. 02126 * @param array stdWrap properties for data. 02127 * @return string The processed input value 02128 */ 02129 public function stdWrap_data($content = '', $conf = array()) { 02130 $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data); 02131 $this->alternativeData = ''; // This must be unset directly after 02132 return $content; 02133 } 02134 02135 /** 02136 * field 02137 * Gets content from a DB field 02138 * 02139 * @param string Input value undergoing processing in this function. 02140 * @param array stdWrap properties for field. 02141 * @return string The processed input value 02142 */ 02143 public function stdWrap_field($content = '', $conf = array()) { 02144 $content = $this->getFieldVal($conf['field']); 02145 return $content; 02146 } 02147 02148 /** 02149 * current 02150 * Gets content that has been perviously set as 'current' 02151 * Can be set via setContentToCurrent or setCurrent or will be set automatically i.e. inside the split function 02152 * 02153 * @param string Input value undergoing processing in this function. 02154 * @param array stdWrap properties for current. 02155 * @return string The processed input value 02156 */ 02157 public function stdWrap_current($content = '', $conf = array()) { 02158 $content = $this->data[$this->currentValKey]; 02159 return $content; 02160 } 02161 02162 /** 02163 * cObject 02164 * Will replace the content with the value of a any official TypoScript cObject 02165 * like TEXT, COA, HMENU 02166 * 02167 * @param string Input value undergoing processing in this function. 02168 * @param array stdWrap properties for cObject. 02169 * @return string The processed input value 02170 */ 02171 public function stdWrap_cObject($content = '', $conf = array()) { 02172 $content = $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject'); 02173 return $content; 02174 } 02175 02176 /** 02177 * numRows 02178 * Counts the number of returned records of a DB operation 02179 * makes use of select internally 02180 * 02181 * @param string Input value undergoing processing in this function. 02182 * @param array stdWrap properties for numRows. 02183 * @return string The processed input value 02184 */ 02185 public function stdWrap_numRows($content = '', $conf = array()) { 02186 $content = $this->numRows($conf['numRows.']); 02187 return $content; 02188 } 02189 02190 /** 02191 * filelist 02192 * Will create a list of files based on some additional parameters 02193 * 02194 * @param string Input value undergoing processing in this function. 02195 * @param array stdWrap properties for filelist. 02196 * @return string The processed input value 02197 */ 02198 public function stdWrap_filelist($content = '', $conf = array()) { 02199 $content = $this->filelist($conf['filelist']); 02200 return $content; 02201 } 02202 02203 /** 02204 * preUserFunc 02205 * Will execute a user public function before the content will be modified by any other stdWrap function 02206 * 02207 * @param string Input value undergoing processing in this function. 02208 * @param array stdWrap properties for preUserFunc. 02209 * @return string The processed input value 02210 */ 02211 public function stdWrap_preUserFunc($content = '', $conf = array()) { 02212 $content = $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content); 02213 return $content; 02214 } 02215 02216 /** 02217 * stdWrap override hook 02218 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs 02219 * this hook will execute functions on existing content but still before the content gets modified or replaced 02220 * 02221 * @param string Input value undergoing processing in these functions. 02222 * @param array All stdWrap properties, not just the ones for a particular function. 02223 * @return string The processed input value 02224 */ 02225 public function stdWrap_stdWrapOverride($content = '', $conf = array()) { 02226 foreach ($this->stdWrapHookObjects as $hookObject) { 02227 $content = $hookObject->stdWrapOverride($content, $conf, $this); 02228 } 02229 return $content; 02230 } 02231 02232 /** 02233 * override 02234 * Will override the current value of content with its own value' 02235 * 02236 * @param string Input value undergoing processing in this function. 02237 * @param array stdWrap properties for override. 02238 * @return string The processed input value 02239 */ 02240 public function stdWrap_override($content = '', $conf = array()) { 02241 if (trim($conf['override'])) { 02242 $content = $conf['override']; 02243 } 02244 return $content; 02245 } 02246 02247 /** 02248 * preIfEmptyListNum 02249 * Gets a value off a CSV list before the following ifEmpty check 02250 * 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 02251 * 02252 * @param string Input value undergoing processing in this function. 02253 * @param array stdWrap properties for preIfEmptyListNum. 02254 * @return string The processed input value 02255 */ 02256 public function stdWrap_preIfEmptyListNum($content = '', $conf = array()) { 02257 $content = $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']); 02258 return $content; 02259 } 02260 02261 /** 02262 * ifEmpty 02263 * Will set content to a replacement value in case the trimmed value of content returns false 02264 * 0 (zero) will be replaced as well 02265 * 02266 * @param string Input value undergoing processing in this function. 02267 * @param array stdWrap properties for ifEmpty. 02268 * @return string The processed input value 02269 */ 02270 public function stdWrap_ifEmpty($content = '', $conf = array()) { 02271 if (!trim($content)) { 02272 $content = $conf['ifEmpty']; 02273 } 02274 return $content; 02275 } 02276 02277 /** 02278 * ifBlank 02279 * Will set content to a replacement value in case the trimmed value of content has no length 02280 * 0 (zero) will not be replaced 02281 * 02282 * @param string Input value undergoing processing in this function. 02283 * @param array stdWrap properties for ifBlank. 02284 * @return string The processed input value 02285 */ 02286 public function stdWrap_ifBlank($content = '', $conf = array()) { 02287 if (!strlen(trim($content))) { 02288 $content = $conf['ifBlank']; 02289 } 02290 return $content; 02291 } 02292 02293 /** 02294 * listNum 02295 * Gets a value off a CSV list after ifEmpty check 02296 * Might return an empty value in case the CSV does not contain a value at the position given by listNum 02297 * Use preIfEmptyListNum to avoid that behaviour 02298 * 02299 * @param string Input value undergoing processing in this function. 02300 * @param array stdWrap properties for listNum. 02301 * @return string The processed input value 02302 */ 02303 public function stdWrap_listNum($content = '', $conf = array()) { 02304 $content = $this->listNum($content, $conf['listNum'], $conf['listNum.']['splitChar']); 02305 return $content; 02306 } 02307 02308 /** 02309 * trim 02310 * Cuts off any whitespace at the beginning and the end of the content 02311 * 02312 * @param string Input value undergoing processing in this function. 02313 * @param array stdWrap properties for trim. 02314 * @return string The processed input value 02315 */ 02316 public function stdWrap_trim($content = '', $conf = array()) { 02317 $content = trim($content); 02318 return $content; 02319 } 02320 02321 /** 02322 * stdWrap 02323 * A recursive call of the stdWrap function set 02324 * This enables the user to execute stdWrap functions in another than the predefined order 02325 * It modifies the content, not the property 02326 * while the new feature of chained stdWrap functions modifies the property and not the content 02327 * 02328 * @param string Input value undergoing processing in this function. 02329 * @param array stdWrap properties for stdWrap. 02330 * @return string The processed input value 02331 */ 02332 public function stdWrap_stdWrap($content = '', $conf = array()) { 02333 $content = $this->stdWrap($content, $conf['stdWrap.']); 02334 return $content; 02335 } 02336 02337 /** 02338 * stdWrap process hook 02339 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs 02340 * this hook executes functions directly after the recursive stdWrap function call but still before the content gets modified 02341 * 02342 * @param string Input value undergoing processing in these functions. 02343 * @param array All stdWrap properties, not just the ones for a particular function. 02344 * @return string The processed input value 02345 */ 02346 public function stdWrap_stdWrapProcess($content = '', $conf = array()) { 02347 foreach ($this->stdWrapHookObjects as $hookObject) { 02348 $content = $hookObject->stdWrapProcess($content, $conf, $this); 02349 } 02350 return $content; 02351 } 02352 02353 /** 02354 * required 02355 * Will immediately stop rendering and return an empty value 02356 * when there is no content at this point 02357 * 02358 * @param string Input value undergoing processing in this function. 02359 * @param array stdWrap properties for required. 02360 * @return string The processed input value 02361 */ 02362 public function stdWrap_required($content = '', $conf = array()) { 02363 if ((string) $content == '') { 02364 $content = ''; 02365 $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE; 02366 } 02367 return $content; 02368 } 02369 02370 /** 02371 * if 02372 * Will immediately stop rendering and return an empty value 02373 * when the result of the checks returns false 02374 * 02375 * @param string Input value undergoing processing in this function. 02376 * @param array stdWrap properties for if. 02377 * @return string The processed input value 02378 */ 02379 public function stdWrap_if($content = '', $conf = array()) { 02380 if (!$this->checkIf($conf['if.'])) { 02381 $content = ''; 02382 $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE; 02383 } 02384 return $content; 02385 } 02386 02387 /** 02388 * fieldRequired 02389 * Will immediately stop rendering and return an empty value 02390 * when there is no content in the field given by fieldRequired 02391 * 02392 * @param string Input value undergoing processing in this function. 02393 * @param array stdWrap properties for fieldRequired. 02394 * @return string The processed input value 02395 */ 02396 public function stdWrap_fieldRequired($content = '', $conf = array()) { 02397 if (!trim($this->data[$conf['fieldRequired']])) { 02398 $content = ''; 02399 $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE; 02400 } 02401 return $content; 02402 } 02403 02404 /** 02405 * csConv 02406 * Will convert the current chracter set of the content to the one given in csConv 02407 * 02408 * @param string Input value undergoing processing in this function. 02409 * @param array stdWrap properties for csConv. 02410 * @return string The processed input value 02411 */ 02412 public function stdWrap_csConv($content = '', $conf = array()) { 02413 $content = $GLOBALS['TSFE']->csConv($content, $conf['csConv']); 02414 return $content; 02415 } 02416 02417 /** 02418 * parseFunc 02419 * Will parse the content based on functions given as stdWrap properties 02420 * Heavily used together with RTE based content 02421 * 02422 * @param string Input value undergoing processing in this function. 02423 * @param array stdWrap properties for parseFunc. 02424 * @return string The processed input value 02425 */ 02426 public function stdWrap_parseFunc($content = '', $conf = array()) { 02427 $content = $this->parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']); 02428 return $content; 02429 } 02430 02431 /** 02432 * HTMLparser 02433 * Will parse HTML content based on functions given as stdWrap properties 02434 * Heavily used together with RTE based content 02435 * 02436 * @param string Input value undergoing processing in this function. 02437 * @param array stdWrap properties for HTMLparser. 02438 * @return string The processed input value 02439 */ 02440 public function stdWrap_HTMLparser($content = '', $conf = array()) { 02441 if (is_array($conf['HTMLparser.'])) { 02442 $content = $this->HTMLparser_TSbridge($content, $conf['HTMLparser.']); 02443 } 02444 return $content; 02445 } 02446 02447 /** 02448 * split 02449 * Will split the content by a given token and treat the results separately 02450 * Automatically fills 'current' with a single result 02451 * 02452 * @param string Input value undergoing processing in this function. 02453 * @param array stdWrap properties for split. 02454 * @return string The processed input value 02455 */ 02456 public function stdWrap_split($content = '', $conf = array()) { 02457 $content = $this->splitObj($content, $conf['split.']); 02458 return $content; 02459 } 02460 02461 /** 02462 * prioriCalc 02463 * Will use the content as a mathematical term and calculate the result 02464 * Can be set to 1 to just get a calculated value or 'intval' to get the integer of the result 02465 * 02466 * @param string Input value undergoing processing in this function. 02467 * @param array stdWrap properties for prioriCalc. 02468 * @return string The processed input value 02469 */ 02470 public function stdWrap_prioriCalc($content = '', $conf = array()) { 02471 $content = t3lib_div::calcParenthesis($content); 02472 if ($conf['prioriCalc'] == 'intval') 02473 $content = intval($content); 02474 return $content; 02475 } 02476 02477 /** 02478 * char 02479 * Will return a character based on its position within the current character set 02480 * 02481 * @param string Input value undergoing processing in this function. 02482 * @param array stdWrap properties for char. 02483 * @return string The processed input value 02484 */ 02485 public function stdWrap_char($content = '', $conf = array()) { 02486 $content = chr(intval($conf['char'])); 02487 return $content; 02488 } 02489 02490 /** 02491 * intval 02492 * Will return an integer value of the current content 02493 * 02494 * @param string Input value undergoing processing in this function. 02495 * @param array stdWrap properties for intval. 02496 * @return string The processed input value 02497 */ 02498 public function stdWrap_intval($content = '', $conf = array()) { 02499 $content = intval($content); 02500 return $content; 02501 } 02502 02503 /** 02504 * numberFormat 02505 * Will return a formatted number based on configuration given as stdWrap properties 02506 * 02507 * @param string Input value undergoing processing in this function. 02508 * @param array stdWrap properties for numberFormat. 02509 * @return string The processed input value 02510 */ 02511 public function stdWrap_numberFormat($content = '', $conf = array()) { 02512 $content = $this->numberFormat($content, $conf['numberFormat.']); 02513 return $content; 02514 } 02515 02516 /** 02517 * date 02518 * Will return a formatted date based on configuration given according to PHP date/gmdate properties 02519 * Will return gmdate when the property GMT returns true 02520 * 02521 * @param string Input value undergoing processing in this function. 02522 * @param array stdWrap properties for date. 02523 * @return string The processed input value 02524 */ 02525 public function stdWrap_date($content = '', $conf = array()) { 02526 $content = ($conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content)); 02527 return $content; 02528 } 02529 02530 /** 02531 * strftime 02532 * Will return a formatted date based on configuration given according to PHP strftime/gmstrftime properties 02533 * Will return gmstrftime when the property GMT returns true 02534 * 02535 * @param string Input value undergoing processing in this function. 02536 * @param array stdWrap properties for strftime. 02537 * @return string The processed input value 02538 */ 02539 public function stdWrap_strftime($content = '', $conf = array()) { 02540 $content = ($conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content)); 02541 $tmp_charset = $conf['strftime.']['charset'] ? $conf['strftime.']['charset'] : $GLOBALS['TSFE']->localeCharset; 02542 if ($tmp_charset) { 02543 $content = $GLOBALS['TSFE']->csConv($content, $tmp_charset); 02544 } 02545 return $content; 02546 } 02547 02548 /** 02549 * age 02550 * Will return the age of a given timestamp based on configuration given by stdWrap properties 02551 * 02552 * @param string Input value undergoing processing in this function. 02553 * @param array stdWrap properties for age. 02554 * @return string The processed input value 02555 */ 02556 public function stdWrap_age($content = '', $conf = array()) { 02557 $content = $this->calcAge($GLOBALS['EXEC_TIME'] - $content, $conf['age']); 02558 return $content; 02559 } 02560 02561 /** 02562 * case 02563 * Will transform the content to be upper or lower case only 02564 * Leaves HTML tags untouched 02565 * 02566 * @param string Input value undergoing processing in this function. 02567 * @param array stdWrap properties for case. 02568 * @return string The processed input value 02569 */ 02570 public function stdWrap_case($content = '', $conf = array()) { 02571 $content = $this->HTMLcaseshift($content, $conf['case']); 02572 return $content; 02573 } 02574 02575 /** 02576 * bytes 02577 * Will return the size of a given number in Bytes * 02578 * 02579 * @param string Input value undergoing processing in this function. 02580 * @param array stdWrap properties for bytes. 02581 * @return string The processed input value 02582 */ 02583 public function stdWrap_bytes($content = '', $conf = array()) { 02584 $content = t3lib_div::formatSize($content, $conf['bytes.']['labels']); 02585 return $content; 02586 } 02587 02588 /** 02589 * substring 02590 * Will return a substring based on position information given by stdWrap properties 02591 * 02592 * @param string Input value undergoing processing in this function. 02593 * @param array stdWrap properties for substring. 02594 * @return string The processed input value 02595 */ 02596 public function stdWrap_substring($content = '', $conf = array()) { 02597 $content = $this->substring($content, $conf['substring']); 02598 return $content; 02599 } 02600 02601 /** 02602 * removeBadHTML 02603 * Removes HTML tags based on stdWrap properties 02604 * 02605 * @param string Input value undergoing processing in this function. 02606 * @param array stdWrap properties for removeBadHTML. 02607 * @return string The processed input value 02608 */ 02609 public function stdWrap_removeBadHTML($content = '', $conf = array()) { 02610 $content = $this->removeBadHTML($content, $conf['removeBadHTML.']); 02611 return $content; 02612 } 02613 02614 /** 02615 * cropHTML 02616 * Crops content to a given size while leaving HTML tags untouched 02617 * 02618 * @param string Input value undergoing processing in this function. 02619 * @param array stdWrap properties for cropHTML. 02620 * @return string The processed input value 02621 */ 02622 public function stdWrap_cropHTML($content = '', $conf = array()) { 02623 $content = $this->cropHTML($content, $conf['cropHTML']); 02624 return $content; 02625 } 02626 02627 /** 02628 * stripHtml 02629 * Copmletely removes HTML tags from content 02630 * 02631 * @param string Input value undergoing processing in this function. 02632 * @param array stdWrap properties for stripHtml. 02633 * @return string The processed input value 02634 */ 02635 public function stdWrap_stripHtml($content = '', $conf = array()) { 02636 $content = strip_tags($content); 02637 return $content; 02638 } 02639 02640 /** 02641 * cropHTML 02642 * Crops content to a given size without caring abhout HTML tags 02643 * 02644 * @param string Input value undergoing processing in this function. 02645 * @param array stdWrap properties for crop. 02646 * @return string The processed input value 02647 */ 02648 public function stdWrap_crop($content = '', $conf = array()) { 02649 $content = $this->crop($content, $conf['crop']); 02650 return $content; 02651 } 02652 02653 /** 02654 * rawUrlEncode 02655 * Encodes content to be used within URLs 02656 * 02657 * @param string Input value undergoing processing in this function. 02658 * @param array stdWrap properties for rawUrlEncode. 02659 * @return string The processed input value 02660 */ 02661 public function stdWrap_rawUrlEncode($content = '', $conf = array()) { 02662 $content = rawurlencode($content); 02663 return $content; 02664 } 02665 02666 /** 02667 * htmlSpecialChars 02668 * Transforms HTML tags to readable text by replacing special characters with their HTML entity 02669 * When preserveEntities returns true, existing entities will be left untouched 02670 * 02671 * @param string Input value undergoing processing in this function. 02672 * @param array stdWrap properties for htmlSpecalChars. 02673 * @return string The processed input value 02674 */ 02675 public function stdWrap_htmlSpecialChars($content = '', $conf = array()) { 02676 $content = htmlSpecialChars($content); 02677 if ($conf['htmlSpecialChars.']['preserveEntities']) 02678 $content = t3lib_div::deHSCentities($content); 02679 return $content; 02680 } 02681 02682 /** 02683 * doubleBrTag 02684 * Searches for double line breaks and replaces them with the given value 02685 * 02686 * @param string Input value undergoing processing in this function. 02687 * @param array stdWrap properties for doubleBrTag. 02688 * @return string The processed input value 02689 */ 02690 public function stdWrap_doubleBrTag($content = '', $conf = array()) { 02691 $content = preg_replace("/\r?\n[\t ]*\r?\n/", $conf['doubleBrTag'], $content); 02692 return $content; 02693 } 02694 02695 /** 02696 * br 02697 * Searches for single line breaks and replaces them with a <br /> tag 02698 * 02699 * @param string Input value undergoing processing in this function. 02700 * @param array stdWrap properties for br. 02701 * @return string The processed input value 02702 */ 02703 public function stdWrap_br($content = '', $conf = array()) { 02704 $content = nl2br($content); 02705 return $content; 02706 } 02707 02708 /** 02709 * brTag 02710 * Searches for single line feeds and replaces them with the given value 02711 * 02712 * @param string Input value undergoing processing in this function. 02713 * @param array stdWrap properties for brTag. 02714 * @return string The processed input value 02715 */ 02716 public function stdWrap_brTag($content = '', $conf = array()) { 02717 $content = str_replace(LF, $conf['brTag'], $content); 02718 return $content; 02719 } 02720 02721 /** 02722 * encapsLines 02723 * Modifies text blocks by searching for lines which are not surrounded by HTML tags yet 02724 * and wrapping them with values given by stdWrap properties 02725 * 02726 * @param string Input value undergoing processing in this function. 02727 * @param array stdWrap properties for erncapsLines. 02728 * @return string The processed input value 02729 */ 02730 public function stdWrap_encapsLines($content = '', $conf = array()) { 02731 $content = $this->encaps_lineSplit($content, $conf['encapsLines.']); 02732 return $content; 02733 } 02734 02735 /** 02736 * keywords 02737 * Transforms content into a CSV list to be used i.e. as keywords within a meta tag 02738 * 02739 * @param string Input value undergoing processing in this function. 02740 * @param array stdWrap properties for keywords. 02741 * @return string The processed input value 02742 */ 02743 public function stdWrap_keywords($content = '', $conf = array()) { 02744 $content = $this->keywords($content); 02745 return $content; 02746 } 02747 02748 /** 02749 * innerWrap 02750 * First of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 02751 * See wrap 02752 * 02753 * @param string Input value undergoing processing in this function. 02754 * @param array stdWrap properties for innerWrap. 02755 * @return string The processed input value 02756 */ 02757 public function stdWrap_innerWrap($content = '', $conf = array()) { 02758 $content = $this->wrap($content, $conf['innerWrap']); 02759 return $content; 02760 } 02761 02762 /** 02763 * innerWrap2 02764 * Second of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 02765 * See wrap 02766 * 02767 * @param string Input value undergoing processing in this function. 02768 * @param array stdWrap properties for innerWrap2. 02769 * @return string The processed input value 02770 */ 02771 public function stdWrap_innerWrap2($content = '', $conf = array()) { 02772 $content = $this->wrap($content, $conf['innerWrap2']); 02773 return $content; 02774 } 02775 02776 /** 02777 * fontTag 02778 * A wrap formerly used to apply font tags to format the content 02779 * Still used by lib.stdheader although real font tags are not state of the art anymore 02780 * See wrap 02781 * 02782 * @param string Input value undergoing processing in this function. 02783 * @param array stdWrap properties for fontTag. 02784 * @return string The processed input value 02785 */ 02786 public function stdWrap_fontTag($content = '', $conf = array()) { 02787 $content = $this->wrap($content, $conf['fontTag']); 02788 return $content; 02789 } 02790 02791 /** 02792 * addParams 02793 * Adds tag attributes to any content that is a tag 02794 * 02795 * @param string Input value undergoing processing in this function. 02796 * @param array stdWrap properties for addParams. 02797 * @return string The processed input value 02798 */ 02799 public function stdWrap_addParams($content = '', $conf = array()) { 02800 $content = $this->addParams($content, $conf['addParams.']); 02801 return $content; 02802 } 02803 02804 /** 02805 * textStyle 02806 * Wraps content in font tags 02807 * See wrap 02808 * 02809 * @param string Input value undergoing processing in this function. 02810 * @param array stdWrap properties for textStyle. 02811 * @return string The processed input value 02812 */ 02813 public function stdWrap_textStyle($content = '', $conf = array()) { 02814 $content = $this->textStyle($content, $conf['textStyle.']); 02815 return $content; 02816 } 02817 02818 /** 02819 * tableStyle 02820 * Wraps content with table tags 02821 * See wrap 02822 * 02823 * @param string Input value undergoing processing in this function. 02824 * @param array stdWrap properties for tableStyle. 02825 * @return string The processed input value 02826 */ 02827 public function stdWrap_tableStyle($content = '', $conf = array()) { 02828 $content = $this->tableStyle($content, $conf['tableStyle.']); 02829 return $content; 02830 } 02831 02832 /** 02833 * filelink 02834 * Used to make lists of links to files 02835 * See wrap 02836 * 02837 * @param string Input value undergoing processing in this function. 02838 * @param array stdWrap properties for filelink. 02839 * @return string The processed input value 02840 */ 02841 public function stdWrap_filelink($content = '', $conf = array()) { 02842 $content = $this->filelink($content, $conf['filelink.']); 02843 return $content; 02844 } 02845 02846 /** 02847 * preCObject 02848 * A content object that is prepended to the current content but between the innerWraps and the rest of the wraps 02849 * 02850 * @param string Input value undergoing processing in this function. 02851 * @param array stdWrap properties for preCObject. 02852 * @return string The processed input value 02853 */ 02854 public function stdWrap_preCObject($content = '', $conf = array()) { 02855 $content = $this->cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content; 02856 return $content; 02857 } 02858 02859 /** 02860 * postCObject 02861 * A content object that is appended to the current content but between the innerWraps and the rest of the wraps 02862 * 02863 * @param string Input value undergoing processing in this function. 02864 * @param array stdWrap properties for postCObject. 02865 * @return string The processed input value 02866 */ 02867 public function stdWrap_postCObject($content = '', $conf = array()) { 02868 $content .= $this->cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject'); 02869 return $content; 02870 } 02871 02872 /** 02873 * wrapAlign 02874 * Wraps content with a div container having the style attribute text-align set to the given value 02875 * See wrap 02876 * 02877 * @param string Input value undergoing processing in this function. 02878 * @param array stdWrap properties for wrapAlign. 02879 * @return string The processed input value 02880 */ 02881 public function stdWrap_wrapAlign($content = '', $conf = array()) { 02882 $wrapAlign = trim($conf['wrapAlign']); 02883 if ($wrapAlign) { 02884 $content = $this->wrap($content, '<div style="text-align:' . $wrapAlign . ';">|</div>'); 02885 } 02886 return $content; 02887 } 02888 02889 /** 02890 * typolink 02891 * Wraps the content with a link tag 02892 * URLs and other attributes are created automatically by the values given in the stdWrap properties 02893 * See wrap 02894 * 02895 * @param string Input value undergoing processing in this function. 02896 * @param array stdWrap properties for typolink. 02897 * @return string The processed input value 02898 */ 02899 public function stdWrap_typolink($content = '', $conf = array()) { 02900 $content = $this->typolink($content, $conf['typolink.']); 02901 return $content; 02902 } 02903 02904 /** 02905 * TCAselectItem 02906 * Returns a list of options available for a given field in the DB which has to be of the type select 02907 * 02908 * @param string Input value undergoing processing in this function. 02909 * @param array stdWrap properties for TCAselectItem. 02910 * @return string The processed input value 02911 */ 02912 public function stdWrap_TCAselectItem($content = '', $conf = array()) { 02913 if (is_array($conf['TCAselectItem.'])) { 02914 $content = $this->TCAlookup($content, $conf['TCAselectItem.']); 02915 } 02916 return $content; 02917 } 02918 02919 /** 02920 * spaceBefore 02921 * Will add space before the current content 02922 * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to true 02923 * 02924 * @param string Input value undergoing processing in this function. 02925 * @param array stdWrap properties for spaceBefore and space. 02926 * @return string The processed input value 02927 */ 02928 public function stdWrap_spaceBefore($content = '', $conf = array()) { 02929 $content = $this->wrapSpace($content, trim($conf['spaceBefore']) . '|', $conf['space.']); 02930 return $content; 02931 } 02932 02933 /** 02934 * spaceAfter 02935 * Will add space after the current content 02936 * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to true 02937 * 02938 * @param string Input value undergoing processing in this function. 02939 * @param array stdWrap properties for spaceAfter and space. 02940 * @return string The processed input value 02941 */ 02942 public function stdWrap_spaceAfter($content = '', $conf = array()) { 02943 $content = $this->wrapSpace($content, '|' . trim($conf['spaceAfter']), $conf['space.']); 02944 return $content; 02945 } 02946 02947 /** 02948 * space 02949 * Will add space before or after the current content 02950 * By default this is done with a clear.gif but it can be done with CSS margins by setting the property space.useDiv to true 02951 * See wrap 02952 * 02953 * @param string Input value undergoing processing in this function. 02954 * @param array stdWrap properties for space. 02955 * @return string The processed input value 02956 */ 02957 public function stdWrap_space($content = '', $conf = array()) { 02958 $content = $this->wrapSpace($content, trim($conf['space']), $conf['space.']); 02959 return $content; 02960 } 02961 02962 /** 02963 * wrap 02964 * This is the "mother" of all wraps 02965 * Third of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 02966 * Basically it will put additional content before and after the current content using a split character as a placeholder for the current content 02967 * The default split character is | but it can be replaced with other characters by the property splitChar 02968 * Any other wrap that does not have own splitChar settings will be using the default split char though 02969 * 02970 * @param string Input value undergoing processing in this function. 02971 * @param array stdWrap properties for wrap. 02972 * @return string The processed input value 02973 */ 02974 public function stdWrap_wrap($content = '', $conf = array()) { 02975 $content = $this->wrap($content, $conf['wrap'], ($conf['wrap.']['splitChar'] ? $conf['wrap.']['splitChar'] : '|')); 02976 return $content; 02977 } 02978 02979 /** 02980 * noTrimWrap 02981 * Fourth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 02982 * The major difference to any other wrap is, that this one can make use of whitespace without trimming * 02983 * 02984 * @param string Input value undergoing processing in this function. 02985 * @param array stdWrap properties for noTrimWrap. 02986 * @return string The processed input value 02987 */ 02988 public function stdWrap_noTrimWrap($content = '', $conf = array()) { 02989 $content = $this->noTrimWrap($content, $conf['noTrimWrap']); 02990 return $content; 02991 } 02992 02993 /** 02994 * wrap2 02995 * Fifth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 02996 * The default split character is | but it can be replaced with other characters by the property splitChar 02997 * 02998 * @param string Input value undergoing processing in this function. 02999 * @param array stdWrap properties for wrap2. 03000 * @return string The processed input value 03001 */ 03002 public function stdWrap_wrap2($content = '', $conf = array()) { 03003 $content = $this->wrap($content, $conf['wrap2'], ($conf['wrap2.']['splitChar'] ? $conf['wrap2.']['splitChar'] : '|')); 03004 return $content; 03005 } 03006 03007 /** 03008 * dataWrap 03009 * Sixth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 03010 * Can fetch additional content the same way data does (i.e. {field:whatever}) and apply it to the wrap before that is applied to the content 03011 * 03012 * @param string Input value undergoing processing in this function. 03013 * @param array stdWrap properties for dataWrap. 03014 * @return string The processed input value 03015 */ 03016 public function stdWrap_dataWrap($content = '', $conf = array()) { 03017 $content = $this->dataWrap($content, $conf['dataWrap']); 03018 return $content; 03019 } 03020 03021 /** 03022 * prepend 03023 * A content object that will be prepended to the current content after most of the wraps have already been applied 03024 * 03025 * @param string Input value undergoing processing in this function. 03026 * @param array stdWrap properties for prepend. 03027 * @return string The processed input value 03028 */ 03029 public function stdWrap_prepend($content = '', $conf = array()) { 03030 $content = $this->cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content; 03031 return $content; 03032 } 03033 03034 /** 03035 * append 03036 * A content object that will be appended to the current content after most of the wraps have already been applied 03037 * 03038 * @param string Input value undergoing processing in this function. 03039 * @param array stdWrap properties for append. 03040 * @return string The processed input value 03041 */ 03042 public function stdWrap_append($content = '', $conf = array()) { 03043 $content .= $this->cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append'); 03044 return $content; 03045 } 03046 03047 /** 03048 * wrap3 03049 * Seventh of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 03050 * The default split character is | but it can be replaced with other characters by the property splitChar 03051 * 03052 * @param string Input value undergoing processing in this function. 03053 * @param array stdWrap properties for wrap3. 03054 * @return string The processed input value 03055 */ 03056 public function stdWrap_wrap3($content = '', $conf = array()) { 03057 $content = $this->wrap($content, $conf['wrap3'], ($conf['wrap3.']['splitChar'] ? $conf['wrap3.']['splitChar'] : '|')); 03058 return $content; 03059 } 03060 03061 /** 03062 * outerWrap 03063 * Eighth of a set of different wraps which will be applied in a certain order before or after other functions that modify the content 03064 * 03065 * @param string Input value undergoing processing in this function. 03066 * @param array stdWrap properties for outerWrap. 03067 * @return string The processed input value 03068 */ 03069 public function stdWrap_outerWrap($content = '', $conf = array()) { 03070 $content = $this->wrap($content, $conf['outerWrap']); 03071 return $content; 03072 } 03073 03074 /** 03075 * inserData 03076 * Can fetch additional content the same way data does and replaces any occurence of {field:whatever} with this content 03077 * 03078 * @param string Input value undergoing processing in this function. 03079 * @param array stdWrap properties for insertData. 03080 * @return string The processed input value 03081 */ 03082 public function stdWrap_insertData($content = '', $conf = array()) { 03083 $content = $this->insertData($content); 03084 return $content; 03085 } 03086 03087 /** 03088 * offsetWrap 03089 * Creates a so called offset table around the content 03090 * Still here for historical reasons even not used too much nowadays 03091 * 03092 * @param string Input value undergoing processing in this function. 03093 * @param array stdWrap properties for offsetWrap. 03094 * @return string The processed input value 03095 */ 03096 public function stdWrap_offsetWrap($content = '', $conf = array()) { 03097 $controlTable = t3lib_div::makeInstance('tslib_tableOffset'); 03098 if ($conf['offsetWrap.']['tableParams'] || $conf['offsetWrap.']['tableParams.']) { 03099 $controlTable->tableParams = isset($conf['offsetWrap.']['tableParams.']) 03100 ? $this->stdWrap($conf['offsetWrap.']['tableParams'], $conf['offsetWrap.']['tableParams.']) 03101 : $conf['offsetWrap.']['tableParams']; 03102 } 03103 if ($conf['offsetWrap.']['tdParams'] || $conf['offsetWrap.']['tdParams.']) { 03104 $controlTable->tdParams = ' ' . isset($conf['offsetWrap.']['tdParams.']) 03105 ? $this->stdWrap($conf['offsetWrap.']['tdParams'], $conf['offsetWrap.']['tdParams.']) 03106 : $conf['offsetWrap.']['tdParams']; 03107 } 03108 $content = $controlTable->start($content, $conf['offsetWrap']); 03109 if ($conf['offsetWrap.']['stdWrap.']) { 03110 $content = $this->stdWrap($content, $conf['offsetWrap.']['stdWrap.']); 03111 } 03112 return $content; 03113 } 03114 03115 /** 03116 * postUserFunc 03117 * Will execute a user function after the content has been modified by any other stdWrap function 03118 * 03119 * @param string Input value undergoing processing in this function. 03120 * @param array stdWrap properties for postUserFunc. 03121 * @return string The processed input value 03122 */ 03123 public function stdWrap_postUserFunc($content = '', $conf = array()) { 03124 $content = $this->callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content); 03125 return $content; 03126 } 03127 03128 /** 03129 * postUserFuncInt 03130 * Will execute a user function after the content has been created and each time it is fetched from Cache 03131 * The result of this function itself will not be cached 03132 * 03133 * @param string Input value undergoing processing in this function. 03134 * @param array stdWrap properties for postUserFuncInt. 03135 * @return string The processed input value 03136 */ 03137 public function stdWrap_postUserFuncInt($content = '', $conf = array()) { 03138 $substKey = 'INT_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash(); 03139 $GLOBALS['TSFE']->config['INTincScript'][$substKey] = array( 03140 'content' => $content, 'postUserFunc' => $conf['postUserFuncInt'], 'conf' => $conf['postUserFuncInt.'], 'type' => 'POSTUSERFUNC', 'cObj' => serialize($this) 03141 ); 03142 $content = '<!--' . $substKey . '-->'; 03143 return $content; 03144 } 03145 03146 /** 03147 * prefixComment 03148 * Will add HTML comments to the content to make it easier to identify certain content elements within the HTML output later on 03149 * 03150 * @param string Input value undergoing processing in this function. 03151 * @param array stdWrap properties for prefixComment. 03152 * @return string The processed input value 03153 */ 03154 public function stdWrap_prefixComment($content = '', $conf = array()) { 03155 if (!$GLOBALS['TSFE']->config['config']['disablePrefixComment']) { 03156 $content = $this->prefixComment($conf['prefixComment'], $conf['prefixComment.'], $content); 03157 } 03158 return $content; 03159 } 03160 03161 /** 03162 * editIcons 03163 * Will render icons for frontend editing as long as there is a BE user logged in 03164 * 03165 * @param string Input value undergoing processing in this function. 03166 * @param array stdWrap properties for editIcons. 03167 * @return string The processed input value 03168 */ 03169 public function stdWrap_editIcons($content = '', $conf = array()) { 03170 if ($GLOBALS['TSFE']->beUserLogin && $conf['editIcons']) { 03171 if(!is_array($conf['editIcons.'])) { 03172 $conf['editIcons.'] = array(); 03173 } 03174 $content = $this->editIcons($content, $conf['editIcons'], $conf['editIcons.']); 03175 } 03176 return $content; 03177 } 03178 03179 /** 03180 * editPanel 03181 * Will render the edit panel for frontend editing as long as there is a BE user logged in 03182 * 03183 * @param string Input value undergoing processing in this function. 03184 * @param array stdWrap properties for editPanel. 03185 * @return string The processed input value 03186 */ 03187 public function stdWrap_editPanel($content = '', $conf = array()) { 03188 if ($GLOBALS['TSFE']->beUserLogin) { 03189 $content = $this->editPanel($content, $conf['editPanel.']); 03190 } 03191 return $content; 03192 } 03193 03194 /** 03195 * stdWrap post process hook 03196 * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs 03197 * this hook executes functions at after the content has been modified by the rest of the stdWrap functions but still before debugging 03198 * 03199 * @param string Input value undergoing processing in these functions. 03200 * @param array All stdWrap properties, not just the ones for a particular function. 03201 * @return string The processed input value 03202 */ 03203 public function stdWrap_stdWrapPostProcess($content = '', $conf = array()) { 03204 foreach ($this->stdWrapHookObjects as $hookObject) { 03205 $content = $hookObject->stdWrapPostProcess($content, $conf, $this); 03206 } 03207 return $content; 03208 } 03209 03210 /** 03211 * debug 03212 * Will output the content as readable HTML code 03213 * 03214 * @param string Input value undergoing processing in this function. 03215 * @param array stdWrap properties for debug. 03216 * @return string The processed input value 03217 */ 03218 public function stdWrap_debug($content = '', $conf = array()) { 03219 $content = '<pre>' . htmlspecialchars($content) . '</pre>'; 03220 return $content; 03221 } 03222 03223 /** 03224 * debugFunc 03225 * Will output the content in a debug table 03226 * 03227 * @param string Input value undergoing processing in this function. 03228 * @param array stdWrap properties for debugFunc. 03229 * @return string The processed input value 03230 */ 03231 public function stdWrap_debugFunc($content = '', $conf = array()) { 03232 debug($conf['debugFunc'] == 2 ? array( 03233 $content 03234 ) : $content); 03235 return $content; 03236 } 03237 03238 /** 03239 * debugData 03240 * Will output the data used by the current record in a debug table 03241 * 03242 * @param string Input value undergoing processing in this function. 03243 * @param array stdWrap properties for debugData. 03244 * @return string The processed input value 03245 */ 03246 public function stdWrap_debugData($content = '', $conf = array()) { 03247 debug($this->data, '$cObj->data:'); 03248 if (is_array($this->alternativeData)) { 03249 debug($this->alternativeData, '$this->alternativeData'); 03250 } 03251 return $content; 03252 } 03253 03254 /** 03255 * Returns number of rows selected by the query made by the properties set. 03256 * Implements the stdWrap "numRows" property 03257 * 03258 * @param array TypoScript properties for the property (see link to "numRows") 03259 * @return integer The number of rows found by the select (FALSE on error) 03260 * @access private 03261 * @see stdWrap() 03262 */ 03263 function numRows($conf) { 03264 $result = FALSE; 03265 $conf['select.']['selectFields'] = 'count(*)'; 03266 03267 $res = $this->exec_getQuery($conf['table'], $conf['select.']); 03268 03269 if ($error = $GLOBALS['TYPO3_DB']->sql_error()) { 03270 $GLOBALS['TT']->setTSlogMessage($error, 3); 03271 } else { 03272 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); 03273 $result = intval($row[0]); 03274 } 03275 $GLOBALS['TYPO3_DB']->sql_free_result($res); 03276 return $result; 03277 } 03278 03279 /** 03280 * Exploding a string by the $char value (if integer its an ASCII value) and returning index $listNum 03281 * 03282 * @param string String to explode 03283 * @param string Index-number. You can place the word "last" in it and it will be substituted with the pointer to the last value. You can use math operators like "+-/*" (passed to calc()) 03284 * @param string Either a string used to explode the content string or an integer value which will then be changed into a character, eg. "10" for a linebreak char. 03285 * @return string 03286 */ 03287 function listNum($content, $listNum, $char) { 03288 $char = $char ? $char : ','; 03289 if (t3lib_div::testInt($char)) { 03290 $char = chr($char); 03291 } 03292 $temp = explode($char, $content); 03293 $last = '' . (count($temp) - 1); 03294 $index = $this->calc(str_ireplace('last', $last, $listNum)); 03295 return $temp[$index]; 03296 } 03297 03298 /** 03299 * Compares values together based on the settings in the input TypoScript array and returns TRUE or FALSE based on the comparison result. 03300 * Implements the "if" function in TYPO3 TypoScript 03301 * 03302 * @param array TypoScript properties defining what to compare 03303 * @return boolean 03304 * @see HMENU(), CASEFUNC(), IMAGE(), COLUMN(), stdWrap(), _parseFunc() 03305 */ 03306 function checkIf($conf) { 03307 if (!is_array($conf)) { 03308 return TRUE; 03309 } 03310 if (isset($conf['directReturn'])) { 03311 return $conf['directReturn'] ? 1 : 0; 03312 } 03313 $flag = TRUE; 03314 if (isset($conf['isTrue']) || isset($conf['isTrue.'])) { 03315 $isTrue = isset($conf['isTrue.']) 03316 ? trim($this->stdWrap($conf['isTrue'], $conf['isTrue.'])) 03317 : trim($conf['isTrue']); 03318 if (!$isTrue) { 03319 $flag = 0; 03320 } 03321 } 03322 if (isset($conf['isFalse']) || isset($conf['isFalse.'])) { 03323 $isFalse = isset($conf['isFalse.']) 03324 ? trim($this->stdWrap($conf['isFalse'], $conf['isFalse.'])) 03325 : trim($conf['isFalse']); 03326 if ($isFalse) { 03327 $flag = 0; 03328 } 03329 } 03330 if (isset($conf['isPositive']) || isset($conf['isPositive.'])) { 03331 $number = isset($conf['isPositive.']) 03332 ? $this->calc($this->stdWrap($conf['isPositive'], $conf['isPositive.'])) 03333 : $this->calc($conf['isPositive']); 03334 if ($number < 1) { 03335 $flag = 0; 03336 } 03337 } 03338 if ($flag) { 03339 $value = isset($conf['value.']) 03340 ? trim($this->stdWrap($conf['value'], $conf['value.'])) 03341 : trim($conf['value']); 03342 03343 if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) { 03344 $number = isset($conf['isGreaterThan.']) 03345 ? trim($this->stdWrap($conf['isGreaterThan'], $conf['isGreaterThan.'])) 03346 : trim($conf['isGreaterThan']); 03347 if ($number <= $value) { 03348 $flag = 0; 03349 } 03350 } 03351 if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) { 03352 $number = isset($conf['isLessThan.']) 03353 ? trim($this->stdWrap($conf['isLessThan'], $conf['isLessThan.'])) 03354 : trim($conf['isLessThan']); 03355 if ($number >= $value) { 03356 $flag = 0; 03357 } 03358 } 03359 if (isset($conf['equals']) || isset($conf['equals.'])) { 03360 $number = isset($conf['equals.']) 03361 ? trim($this->stdWrap($conf['equals'], $conf['equals.'])) 03362 : trim($conf['equals']); 03363 if ($number != $value) { 03364 $flag = 0; 03365 } 03366 } 03367 if (isset($conf['isInList']) || isset($conf['isInList.'])) { 03368 $number = isset($conf['isInList.']) 03369 ? trim($this->stdWrap($conf['isInList'], $conf['isInList.'])) 03370 : trim($conf['isInList']); 03371 if (!t3lib_div::inList($value, $number)) { 03372 $flag = 0; 03373 } 03374 } 03375 } 03376 if ($conf['negate']) { 03377 $flag = $flag ? 0 : 1; 03378 } 03379 return $flag; 03380 } 03381 03382 /** 03383 * Reads a directory for files and returns the filepaths in a string list separated by comma. 03384 * Implements the stdWrap property "filelist" 03385 * 03386 * @param string The command which contains information about what files/directory listing to return. See the "filelist" property of stdWrap for details. 03387 * @return string Comma list of files. 03388 * @access private 03389 * @see stdWrap() 03390 */ 03391 function filelist($data) { 03392 $data = trim($data); 03393 if ($data) { 03394 $data_arr = explode('|', $data); 03395 // read directory: 03396 if ($GLOBALS['TSFE']->lockFilePath) { // MUST exist! 03397 $path = $this->clean_directory($data_arr[0]); // Cleaning name..., only relative paths accepted. 03398 // see if path starts with lockFilePath, the additional '/' is needed because clean_directory gets rid of it 03399 $path = (t3lib_div::isFirstPartOfStr($path . '/', $GLOBALS['TSFE']->lockFilePath) ? $path : ''); 03400 } 03401 if ($path) { 03402 $items = array( 03403 'files' => array(), 03404 'sorting' => array() 03405 ); 03406 $ext_list = strtolower(t3lib_div::uniqueList($data_arr[1])); 03407 $sorting = trim($data_arr[2]); 03408 // read dir: 03409 $d = @dir($path); 03410 $tempArray = array(); 03411 if (is_object($d)) { 03412 $count = 0; 03413 while ($entry = $d->read()) { 03414 if ($entry != '.' && $entry != '..') { 03415 $wholePath = $path . '/' . $entry; // Because of odd PHP-error where <br />-tag is sometimes placed after a filename!! 03416 if (file_exists($wholePath) && filetype($wholePath) == 'file') { 03417 $info = t3lib_div::split_fileref($wholePath); 03418 if (!$ext_list || t3lib_div::inList($ext_list, $info['fileext'])) { 03419 $items['files'][] = $info['file']; 03420 switch ($sorting) { 03421 case 'name' : 03422 $items['sorting'][] = strtolower($info['file']); 03423 break; 03424 case 'size' : 03425 $items['sorting'][] = filesize($wholePath); 03426 break; 03427 case 'ext' : 03428 $items['sorting'][] = $info['fileext']; 03429 break; 03430 case 'date' : 03431 $items['sorting'][] = filectime($wholePath); 03432 break; 03433 case 'mdate' : 03434 $items['sorting'][] = filemtime($wholePath); 03435 break; 03436 default : 03437 $items['sorting'][] = $count; 03438 break; 03439 } 03440 $count++; 03441 } 03442 } 03443 } 03444 } 03445 $d->close(); 03446 } 03447 // Sort if required 03448 if (count($items['sorting'])) { 03449 if (strtolower(trim($data_arr[3])) != 'r') { 03450 asort($items['sorting']); 03451 } else { 03452 arsort($items['sorting']); 03453 } 03454 } 03455 if (count($items['files'])) { 03456 // make list 03457 reset($items['sorting']); 03458 $fullPath = trim($data_arr[4]); 03459 $list_arr = array(); 03460 foreach ($items['sorting'] as $key => $v) { 03461 $list_arr[] = $fullPath ? $path . '/' . $items['files'][$key] : $items['files'][$key]; 03462 } 03463 return implode(',', $list_arr); 03464 } 03465 } 03466 } 03467 } 03468 03469 /** 03470 * Cleans $theDir for slashes in the end of the string and returns the new path, if it exists on the server. 03471 * 03472 * @param string Absolute path to directory 03473 * @return string The directory path if it existed as was valid to access. 03474 * @access private 03475 * @see filelist() 03476 */ 03477 function clean_directory($theDir) { 03478 if (t3lib_div::validPathStr($theDir)) { // proceeds if no '//', '..' or '\' is in the $theFile 03479 $theDir = preg_replace('/[\/\. ]*$/', '', $theDir); // Removes all dots, slashes and spaces after a path... 03480 if (!t3lib_div::isAbsPath($theDir) && @is_dir($theDir)) { 03481 return $theDir; 03482 } 03483 } 03484 } 03485 03486 /** 03487 * Passes the input value, $theValue, to an instance of "t3lib_parsehtml" together with the TypoScript options which are first converted from a TS style array to a set of arrays with options for the t3lib_parsehtml class. 03488 * 03489 * @param string The value to parse by the class "t3lib_parsehtml" 03490 * @param array TypoScript properties for the parser. See link. 03491 * @return string Return value. 03492 * @see stdWrap(), t3lib_parsehtml::HTMLparserConfig(), t3lib_parsehtml::HTMLcleaner() 03493 */ 03494 function HTMLparser_TSbridge($theValue, $conf) { 03495 $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml'); 03496 $htmlParserCfg = $htmlParser->HTMLparserConfig($conf); 03497 return $htmlParser->HTMLcleaner($theValue, $htmlParserCfg[0], $htmlParserCfg[1], $htmlParserCfg[2], $htmlParserCfg[3]); 03498 } 03499 03500 /** 03501 * Wrapping input value in a regular "wrap" but parses the wrapping value first for "insertData" codes. 03502 * 03503 * @param string Input string being wrapped 03504 * @param string The wrap string, eg. "<strong></strong>" or more likely here '<a href="index.php?id={TSFE:id}"> | </a>' which will wrap the input string in a <a> tag linking to the current page. 03505 * @return string Output string wrapped in the wrapping value. 03506 * @see insertData(), stdWrap() 03507 */ 03508 function dataWrap($content, $wrap) { 03509 return $this->wrap($content, $this->insertData($wrap)); 03510 } 03511 03512 /** 03513 * Implements the "insertData" property of stdWrap meaning that if strings matching {...} is found in the input string they will be substituted with the return value from getData (datatype) which is passed the content of the curly braces. 03514 * Example: If input string is "This is the page title: {page:title}" then the part, '{page:title}', will be substituted with the current pages title field value. 03515 * 03516 * @param string Input value 03517 * @return string Processed input value 03518 * @see getData(), stdWrap(), dataWrap() 03519 */ 03520 function insertData($str) { 03521 $inside = 0; 03522 $newVal = ''; 03523 $pointer = 0; 03524 $totalLen = strlen($str); 03525 do { 03526 if (!$inside) { 03527 $len = strcspn(substr($str, $pointer), '{'); 03528 $newVal .= substr($str, $pointer, $len); 03529 $inside = 1; 03530 } else { 03531 $len = strcspn(substr($str, $pointer), '}') + 1; 03532 $newVal .= $this->getData(substr($str, $pointer + 1, $len - 2), $this->data); 03533 $inside = 0; 03534 } 03535 $pointer += $len; 03536 } while ($pointer < $totalLen); 03537 return $newVal; 03538 } 03539 03540 /** 03541 * Returns a HTML comment with the second part of input string (divided by "|") where first part is an integer telling how many trailing tabs to put before the comment on a new line. 03542 * Notice; this function (used by stdWrap) can be disabled by a "config.disablePrefixComment" setting in TypoScript. 03543 * 03544 * @param string Input value 03545 * @param array TypoScript Configuration (not used at this point.) 03546 * @param string The content to wrap the comment around. 03547 * @return string Processed input value 03548 * @see stdWrap() 03549 */ 03550 function prefixComment($str, $conf, $content) { 03551 $parts = explode('|', $str); 03552 03553 $output = LF . str_pad('', $parts[0], TAB) . 03554 '<!-- ' . htmlspecialchars($this->insertData($parts[1])) . ' [begin] -->' . LF . 03555 str_pad('', $parts[0] + 1, TAB) . 03556 $content . LF . 03557 str_pad('', $parts[0], TAB) . 03558 '<!-- ' . htmlspecialchars($this->insertData($parts[1])) . ' [end] -->' . LF . 03559 str_pad('', $parts[0] + 1, TAB); 03560 03561 return $output; 03562 } 03563 03564 /** 03565 * Implements the stdWrap property "substring" which is basically a TypoScript implementation of the PHP function, substr() 03566 * 03567 * @param string The string to perform the operation on 03568 * @param string The parameters to substring, given as a comma list of integers where the first and second number is passed as arg 1 and 2 to substr(). 03569 * @return string The processed input value. 03570 * @access private 03571 * @see stdWrap() 03572 */ 03573 function substring($content, $options) { 03574 $options = t3lib_div::intExplode(',', $options . ','); 03575 if ($options[1]) { 03576 return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0], $options[1]); 03577 } else { 03578 return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0]); 03579 } 03580 } 03581 03582 /** 03583 * Implements the stdWrap property "crop" which is a modified "substr" function allowing to limit a string lenght to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string really was cropped. 03584 * 03585 * @param string The string to perform the operation on 03586 * @param string The parameters splitted by "|": First parameter is the max number of chars of the string. Negative value means cropping from end of string. Second parameter is the pre/postfix string to apply if cropping occurs. Third parameter is a boolean value. If set then crop will be applied at nearest space. 03587 * @return string The processed input value. 03588 * @access private 03589 * @see stdWrap() 03590 */ 03591 function crop($content, $options) { 03592 $options = explode('|', $options); 03593 $chars = intval($options[0]); 03594 $afterstring = trim($options[1]); 03595 $crop2space = trim($options[2]); 03596 if ($chars) { 03597 if ($GLOBALS['TSFE']->csConvObj->strlen($GLOBALS['TSFE']->renderCharset, $content) > abs($chars)) { 03598 $truncatePosition = FALSE; 03599 if ($chars < 0) { 03600 $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $chars); 03601 if ($crop2space) { 03602 $truncatePosition = strpos($content, ' '); 03603 } 03604 $content = ($truncatePosition) ? $afterstring . substr($content, $truncatePosition) : $afterstring . $content; 03605 } else { 03606 $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, 0, $chars); 03607 if ($crop2space) { 03608 $truncatePosition = strrpos($content, ' '); 03609 } 03610 $content = ($truncatePosition) ? substr($content, 0, $truncatePosition) . $afterstring : $content . $afterstring; 03611 } 03612 } 03613 } 03614 return $content; 03615 } 03616 03617 /** 03618 * Implements the stdWrap property "cropHTML" which is a modified "substr" function allowing to limit a string length 03619 * to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string 03620 * really was cropped. 03621 * 03622 * Compared to stdWrap.crop it respects HTML tags and entities. 03623 * 03624 * @param string The string to perform the operation on 03625 * @param string The parameters splitted by "|": First parameter is the max number of chars of the string. Negative value means cropping from end of string. Second parameter is the pre/postfix string to apply if cropping occurs. Third parameter is a boolean value. If set then crop will be applied at nearest space. 03626 * @return string The processed input value. 03627 * @access private 03628 * @see stdWrap() 03629 */ 03630 function cropHTML($content, $options) { 03631 $options = explode('|', $options); 03632 $chars = intval($options[0]); 03633 $absChars = abs($chars); 03634 $replacementForEllipsis = trim($options[1]); 03635 $crop2space = trim($options[2]) === '1' ? TRUE : FALSE; 03636 03637 // Split $content into an array(even items in the array are outside the tags, odd numbers are tag-blocks). 03638 $tags = 'a|b|blockquote|body|div|em|font|form|h1|h2|h3|h4|h5|h6|i|li|map|ol|option|p|pre|sub|sup|select|span|strong|table|thead|tbody|tfoot|td|textarea|tr|u|ul|br|hr|img|input|area|link'; 03639 // TODO We should not crop inside <script> tags. 03640 $tagsRegEx = " 03641 ( 03642 (?: 03643 <!--.*?--> # a comment 03644 ) 03645 | 03646 </?(?:" . $tags . ")+ # opening tag ('<tag') or closing tag ('</tag') 03647 (?: 03648 (?: 03649 \s+\w+ # EITHER spaces, followed by word characters (attribute names) 03650 (?: 03651 \s*=?\s* # equals 03652 (?> 03653 \".*?\" # attribute values in double-quotes 03654 | 03655 '.*?' # attribute values in single-quotes 03656 | 03657 [^'\">\s]+ # plain attribute values 03658 ) 03659 )? 03660 )+\s* 03661 | # OR only spaces 03662 \s* 03663 ) 03664 /?> # closing the tag with '>' or '/>' 03665 )"; 03666 $splittedContent = preg_split('%' . $tagsRegEx . '%xs', $content, -1, PREG_SPLIT_DELIM_CAPTURE); 03667 03668 // Reverse array if we are cropping from right. 03669 if ($chars < 0) { 03670 $splittedContent = array_reverse($splittedContent); 03671 } 03672 03673 // Crop the text (chars of tag-blocks are not counted). 03674 $strLen = 0; 03675 $croppedOffset = NULL; // This is the offset of the content item which was cropped. 03676 $countSplittedContent = count($splittedContent); 03677 for ($offset = 0; $offset < $countSplittedContent; $offset++) { 03678 if ($offset % 2 === 0) { 03679 $tempContent = $GLOBALS['TSFE']->csConvObj->utf8_encode($splittedContent[$offset], $GLOBALS['TSFE']->renderCharset); 03680 $thisStrLen = $GLOBALS['TSFE']->csConvObj->strlen('utf-8', html_entity_decode($tempContent, ENT_COMPAT, 'UTF-8')); 03681 if (($strLen + $thisStrLen > $absChars)) { 03682 $croppedOffset = $offset; 03683 $cropPosition = $absChars - $strLen; 03684 // The snippet "&[^&\s;]{2,8};" in the RegEx below represents entities. 03685 $patternMatchEntityAsSingleChar = '(&[^&\s;]{2,8};|.)'; 03686 if ($crop2space) { 03687 $cropRegEx = $chars < 0 03688 ? '#(?<=\s)' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#ui' 03689 : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}(?=\s)#ui'; 03690 } else { 03691 $cropRegEx = $chars < 0 03692 ? '#' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#ui' 03693 : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}#ui'; 03694 } 03695 if (preg_match($cropRegEx, $tempContent, $croppedMatch)) { 03696 $tempContent = $croppedMatch[0]; 03697 } 03698 $splittedContent[$offset] = $GLOBALS['TSFE']->csConvObj->utf8_decode($tempContent, $GLOBALS['TSFE']->renderCharset); 03699 break; 03700 } else { 03701 $strLen += $thisStrLen; 03702 } 03703 } 03704 } 03705 03706 // Close cropped tags. 03707 $closingTags = array(); 03708 if ($croppedOffset !== NULL) { 03709 $tagName = ''; 03710 $openingTagRegEx = '#^<(\w+)(?:\s|>)#'; 03711 $closingTagRegEx = '#^</(\w+)(?:\s|>)#'; 03712 for ($offset = $croppedOffset - 1; $offset >= 0; $offset = $offset - 2) { 03713 if (substr($splittedContent[$offset], -2) === '/>') { 03714 // Ignore empty element tags (e.g. <br />). 03715 continue; 03716 } 03717 preg_match($chars < 0 ? $closingTagRegEx : $openingTagRegEx, $splittedContent[$offset], $matches); 03718 $tagName = isset($matches[1]) ? $matches[1] : NULL; 03719 if ($tagName !== NULL) { 03720 // Seek for the closing (or opening) tag. 03721 $seekingTagName = ''; 03722 $countSplittedContent = count($splittedContent); 03723 for ($seekingOffset = $offset + 2; $seekingOffset < $countSplittedContent; $seekingOffset = $seekingOffset + 2) { 03724 preg_match($chars < 0 ? $openingTagRegEx : $closingTagRegEx, $splittedContent[$seekingOffset], $matches); 03725 $seekingTagName = isset($matches[1]) ? $matches[1] : NULL; 03726 if ($tagName === $seekingTagName) { // We found a matching tag. 03727 // Add closing tag only if it occurs after the cropped content item. 03728 if ($seekingOffset > $croppedOffset) { 03729 $closingTags[] = $splittedContent[$seekingOffset]; 03730 } 03731 break; 03732 } 03733 } 03734 } 03735 } 03736 // Drop the cropped items of the content array. The $closingTags will be added later on again. 03737 array_splice($splittedContent, $croppedOffset + 1); 03738 } 03739 $splittedContent = array_merge($splittedContent, array( 03740 $croppedOffset !== NULL ? $replacementForEllipsis : '' 03741 ), $closingTags); 03742 03743 // Reverse array once again if we are cropping from the end. 03744 if ($chars < 0) { 03745 $splittedContent = array_reverse($splittedContent); 03746 } 03747 03748 return implode('', $splittedContent); 03749 } 03750 03751 /** 03752 * Function for removing malicious HTML code when you want to provide some HTML code user-editable. 03753 * The purpose is to avoid XSS attacks and the code will be continously modified to remove such code. 03754 * For a complete reference with javascript-on-events, see http://www.wdvl.com/Authoring/JavaScript/Events/events_target.html 03755 * 03756 * @param string Input string to be cleaned. 03757 * @param array TypoScript configuration. 03758 * @return string Return string 03759 * @author Thomas Bley (all from moregroupware cvs code / readmessage.inc.php, published under gpl by Thomas) 03760 * @author Kasper Sk�rh�j 03761 */ 03762 function removeBadHTML($text, $conf) { 03763 03764 // Copyright 2002-2003 Thomas Bley 03765 $text = preg_replace( 03766 array( 03767 "'<script[^>]*?>.*?</script[^>]*?>'si", "'<applet[^>]*?>.*?</applet[^>]*?>'si", "'<object[^>]*?>.*?</object[^>]*?>'si", "'<iframe[^>]*?>.*?</iframe[^>]*?>'si", "'<frameset[^>]*?>.*?</frameset[^>]*?>'si", "'<style[^>]*?>.*?</style[^>]*?>'si", "'<marquee[^>]*?>.*?</marquee[^>]*?>'si", "'<script[^>]*?>'si", "'<meta[^>]*?>'si", "'<base[^>]*?>'si", "'<applet[^>]*?>'si", "'<object[^>]*?>'si", "'<link[^>]*?>'si", "'<iframe[^>]*?>'si", "'<frame[^>]*?>'si", "'<frameset[^>]*?>'si", "'<input[^>]*?>'si", "'<form[^>]*?>'si", "'<embed[^>]*?>'si", "'background-image:url'si", "'<\w+.*?(onabort|onbeforeunload|onblur|onchange|onclick|ondblclick|ondragdrop|onerror|onfilterchange|onfocus|onhelp|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onmove|onreadystatechange|onreset|onresize|onscroll|onselect|onselectstart|onsubmit|onunload).*?>'si" 03768 ), 03769 '', 03770 $text 03771 ); 03772 03773 $text = preg_replace( 03774 '/<a[^>]*href[[:space:]]*=[[:space:]]*["\']?[[:space:]]*javascript[^>]*/i', 03775 '', 03776 $text 03777 ); 03778 03779 // Return clean content 03780 return $text; 03781 } 03782 03783 /** 03784 * Implements the stdWrap property "textStyle"; This generates a <font>-tag (and a <div>-tag for align-attributes) which is wrapped around the input value. 03785 * 03786 * @param string The input value 03787 * @param array TypoScript properties for the "TypoScript function" '->textStyle' 03788 * @return string The processed output value 03789 * @access private 03790 * @see stdWrap() 03791 */ 03792 function textStyle($theValue, $conf) { 03793 $conf['face.'][1] = 'Times New Roman'; 03794 $conf['face.'][2] = 'Verdana,Arial,Helvetica,Sans serif'; 03795 $conf['face.'][3] = 'Arial,Helvetica,Sans serif'; 03796 03797 $conf['size.'][1] = 1; 03798 $conf['size.'][2] = 2; 03799 $conf['size.'][3] = 3; 03800 $conf['size.'][4] = 4; 03801 $conf['size.'][5] = 5; 03802 $conf['size.'][10] = '+1'; 03803 $conf['size.'][11] = '-1'; 03804 03805 $conf['color.'][240] = 'black'; 03806 $conf['color.'][241] = 'white'; 03807 $conf['color.'][242] = '#333333'; 03808 $conf['color.'][243] = 'gray'; 03809 $conf['color.'][244] = 'silver'; 03810 $conf['color.'][245] = 'red'; 03811 $conf['color.'][246] = 'navy'; 03812 $conf['color.'][247] = 'yellow'; 03813 $conf['color.'][248] = 'green'; 03814 $conf['color.'][249] = 'olive'; 03815 $conf['color.'][250] = 'maroon'; 03816 03817 $face = $this->data[$conf['face.']['field']]; 03818 $size = $this->data[$conf['size.']['field']]; 03819 $color = $this->data[$conf['color.']['field']]; 03820 $align = $this->data[$conf['align.']['field']]; 03821 $properties = $this->data[$conf['properties.']['field']]; 03822 if (!$properties) { 03823 $properties = isset($conf['properties.']['default.']) 03824 ? $this->stdWrap($conf['properties.']['default'], $conf['properties.']['default.']) 03825 : $conf['properties.']['default']; 03826 } 03827 03828 // properties 03829 if (($properties & 8)) { 03830 $theValue = $this->HTMLcaseshift($theValue, 'upper'); 03831 } 03832 if (($properties & 1)) { 03833 $theValue = '<strong>' . $theValue . '</strong>'; 03834 } 03835 if (($properties & 2)) { 03836 $theValue = '<i>' . $theValue . '</i>'; 03837 } 03838 if (($properties & 4)) { 03839 $theValue = '<u>' . $theValue . '</u>'; 03840 } 03841 03842 // Fonttag 03843 $theFace = $conf['face.'][$face]; 03844 if(!$theFace) { 03845 $theFace = isset($conf['face.']['default.']) 03846 ? $this->stdWrap($conf['face.']['default'], $conf['face.']['default.']) 03847 : $conf['face.']['default']; 03848 } 03849 03850 $theSize = $conf['size.'][$size]; 03851 if(!$theSize) { 03852 $theSize = isset($conf['size.']['default.']) 03853 ? $this->stdWrap($conf['size.']['default'], $conf['size.']['default.']) 03854 : $conf['size.']['default']; 03855 } 03856 03857 $theColor = $conf['color.'][$color]; 03858 if(!$theColor) { 03859 $theColor = isset($conf['color.']['default.']) 03860 ? $this->stdWrap($conf['color.']['default'], $conf['color.']['default.']) 03861 : $conf['color.']['default.']; 03862 } 03863 03864 if ($conf['altWrap']) { 03865 $theValue = $this->wrap($theValue, $conf['altWrap']); 03866 } elseif ($theFace || $theSize || $theColor) { 03867 $fontWrap = '<font' . ($theFace ? ' face="' . $theFace . '"' : '') . 03868 ($theSize ? ' size="' . $theSize . '"' : '') . 03869 ($theColor ? ' color="' . $theColor . '"' : '') . 03870 '>|</font>'; 03871 $theValue = $this->wrap($theValue, $fontWrap); 03872 } 03873 // align 03874 if ($align) { 03875 $theValue = $this->wrap($theValue, '<div style="text-align:' . $align . ';">|</div>'); 03876 } 03877 // return 03878 return $theValue; 03879 } 03880 03881 /** 03882 * Implements the stdWrap property "tableStyle"; Basically this generates a <table>-tag with properties which is wrapped around the input value. 03883 * 03884 * @param string The input value 03885 * @param array TypoScript properties for the "TypoScript function" '->textStyle' 03886 * @return string The processed output value 03887 * @access private 03888 * @see stdWrap() 03889 */ 03890 function tableStyle($theValue, $conf) { 03891 $conf['color.'][240] = 'black'; 03892 $conf['color.'][241] = 'white'; 03893 $conf['color.'][242] = '#333333'; 03894 $conf['color.'][243] = 'gray'; 03895 $conf['color.'][244] = 'silver'; 03896 03897 $align = isset($conf['align.']) 03898 ? $this->stdWrap($conf['align'], $conf['align.']) 03899 : $conf['align']; 03900 $border = isset($conf['border.']) 03901 ? intval($this->stdWrap($conf['border'], $conf['border.'])) 03902 : intval($conf['border']); 03903 $cellspacing = isset($conf['cellspacing.']) 03904 ? intval($this->stdWrap($conf['cellspacing'], $conf['cellspacing.'])) 03905 : intval($conf['cellspacing']); 03906 $cellpadding = isset($conf['cellpadding.']) 03907 ? intval($this->stdWrap($conf['cellpadding'], $conf['cellpadding.'])) 03908 : intval($conf['cellpadding']); 03909 03910 $color = $this->data[$conf['color.']['field']]; 03911 $theColor = $conf['color.'][$color] ? $conf['color.'][$color] : $conf['color.']['default']; 03912 // Assembling the table tag 03913 $tableTagArray = array( 03914 '<table' 03915 ); 03916 $tableTagArray[] = 'border="' . $border . '"'; 03917 $tableTagArray[] = 'cellspacing="' . $cellspacing . '"'; 03918 $tableTagArray[] = 'cellpadding="' . $cellpadding . '"'; 03919 if ($align) { 03920 $tableTagArray[] = 'align="' . $align . '"'; 03921 } 03922 if ($theColor) { 03923 $tableTagArray[] = 'bgcolor="' . $theColor . '"'; 03924 } 03925 03926 if ($conf['params']) { 03927 $tableTagArray[] = $conf['params']; 03928 } 03929 03930 $tableWrap = implode(' ', $tableTagArray) . '> | </table>'; 03931 $theValue = $this->wrap($theValue, $tableWrap); 03932 // return 03933 return $theValue; 03934 } 03935 03936 /** 03937 * Implements the TypoScript function "addParams" 03938 * 03939 * @param string The string with the HTML tag. 03940 * @param array The TypoScript configuration properties 03941 * @return string The modified string 03942 * @todo Make it XHTML compatible. Will not present "/>" endings of tags right now. Further getting the tagname might fail if it is not separated by a normal space from the attributes. 03943 */ 03944 function addParams($content, $conf) { 03945 $lowerCaseAttributes = TRUE; // For XHTML compliance. 03946 03947 03948 if (!is_array($conf)) { 03949 return $content; 03950 } 03951 03952 $key = 1; 03953 $parts = explode('<', $content); 03954 if (intval($conf['_offset'])) 03955 $key = intval($conf['_offset']) < 0 ? count($parts) + intval($conf['_offset']) : intval($conf['_offset']); 03956 $subparts = explode('>', $parts[$key]); 03957 if (trim($subparts[0])) { 03958 // Get attributes and name 03959 $attribs = t3lib_div::get_tag_attributes('<' . $subparts[0] . '>'); 03960 list ($tagName) = explode(' ', $subparts[0], 2); 03961 // adds/overrides attributes 03962 foreach ($conf as $pkey => $val) { 03963 if (substr($pkey, -1) != '.' && substr($pkey, 0, 1) != '_') { 03964 $tmpVal = isset($conf[$pkey . '.']) 03965 ? $this->stdWrap($conf[$pkey], $conf[$pkey . '.']) 03966 : $conf[$pkey]; 03967 if ($lowerCaseAttributes) { 03968 $pkey = strtolower($pkey); 03969 } 03970 if (strcmp($tmpVal, '')) { 03971 $attribs[$pkey] = $tmpVal; 03972 } 03973 } 03974 } 03975 03976 // Re-assembles the tag and content 03977 $subparts[0] = trim($tagName . ' ' . t3lib_div::implodeAttributes($attribs)); 03978 $parts[$key] = implode('>', $subparts); 03979 $content = implode('<', $parts); 03980 } 03981 return $content; 03982 } 03983 03984 /** 03985 * Creates a list of links to files. 03986 * Implements the stdWrap property "filelink" 03987 * 03988 * @param string The filename to link to, possibly prefixed with $conf[path] 03989 * @param array TypoScript parameters for the TypoScript function ->filelink 03990 * @return string The link to the file possibly with icons, thumbnails, size in bytes shown etc. 03991 * @access private 03992 * @see stdWrap() 03993 */ 03994 function filelink($theValue, $conf) { 03995 $conf['path'] = isset($conf['path.']) 03996 ? $this->stdWrap($conf['path'], $conf['path.']) 03997 : $conf['path']; 03998 $theFile = trim($conf['path']) . $theValue; 03999 if (@is_file($theFile)) { 04000 $theFileEnc = str_replace('%2F', '/', rawurlencode($theFile)); 04001 04002 // the jumpURL feature will be taken care of by typoLink, only "jumpurl.secure = 1" is applyable needed for special link creation 04003 if ($conf['jumpurl.']['secure']) { 04004 $alternativeJumpUrlParameter = isset($conf['jumpurl.']['parameter.']) 04005 ? $this->stdWrap($conf['jumpurl.']['parameter'], $conf['jumpurl.']['parameter.']) 04006 : $conf['jumpurl.']['parameter']; 04007 $typoLinkConf = array( 04008 'parameter' => ($alternativeJumpUrlParameter ? $alternativeJumpUrlParameter : ($GLOBALS['TSFE']->id . ',' . $GLOBALS['TSFE']->type)), 04009 'fileTarget' => $conf['target'], 04010 'ATagParams' => $this->getATagParams($conf), 04011 'additionalParams' => '&jumpurl=' . rawurlencode($theFileEnc) . $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) . $GLOBALS['TSFE']->getMethodUrlIdToken 04012 ); 04013 } else { 04014 $typoLinkConf = array( 04015 'parameter' => $theFileEnc, 04016 'fileTarget' => $conf['target'], 04017 'ATagParams' => $this->getATagParams($conf) 04018 ); 04019 } 04020 04021 // if the global jumpURL feature is activated, but is disabled for this 04022 // filelink, the global parameter needs to be disabled as well for this link creation 04023 $globalJumpUrlEnabled = $GLOBALS['TSFE']->config['config']['jumpurl_enable']; 04024 if ($globalJumpUrlEnabled && isset($conf['jumpurl']) && $conf['jumpurl'] == 0) { 04025 $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 0; 04026 // if the global jumpURL feature is deactivated, but is wanted for this link, then activate it for now 04027 } else if (!$globalJumpUrlEnabled && $conf['jumpurl']) { 04028 $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 1; 04029 } 04030 $theLinkWrap = $this->typoLink('|', $typoLinkConf); 04031 04032 // now the original value is set again 04033 $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = $globalJumpUrlEnabled; 04034 04035 $theSize = filesize($theFile); 04036 $fI = t3lib_div::split_fileref($theFile); 04037 if ($conf['icon']) { 04038 $iconP = t3lib_extMgm::siteRelPath('cms') . 'tslib/media/fileicons/'; 04039 $icon = @is_file($iconP . $fI['fileext'] . '.gif') ? $iconP . $fI['fileext'] . '.gif' : $iconP . 'default.gif'; 04040 // Checking for images: If image, then return link to thumbnail. 04041 $IEList = isset($conf['icon_image_ext_list.']) 04042 ? $this->stdWrap($conf['icon_image_ext_list'], $conf['icon_image_ext_list.']) 04043 : $conf['icon_image_ext_list']; 04044 $image_ext_list = str_replace(' ', '', strtolower($IEList)); 04045 if ($fI['fileext'] && t3lib_div::inList($image_ext_list, $fI['fileext'])) { 04046 if ($conf['iconCObject']) { 04047 $icon = $this->cObjGetSingle($conf['iconCObject'], $conf['iconCObject.'], 'iconCObject'); 04048 } else { 04049 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) { 04050 $thumbSize = ''; 04051 if ($conf['icon_thumbSize'] || $conf['icon_thumbSize.']) { 04052 $thumbSize = '&size=' . isset($conf['icon_thumbSize.']) 04053 ? $this->stdWrap($conf['icon_thumbSize'], $conf['icon_thumbSize.']) 04054 : $conf['icon_thumbSize']; 04055 } 04056 $check = basename($theFile) . ':' . filemtime($theFile) . ':' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']; 04057 $md5sum = '&md5sum=' . t3lib_div::shortMD5($check); 04058 $icon = 't3lib/thumbs.php?dummy=' . $GLOBALS['EXEC_TIME'] . '&file=' . 04059 rawurlencode('../' . $theFile) . $thumbSize . $md5sum; 04060 } else { 04061 $icon = t3lib_extMgm::siteRelPath('cms') . 'tslib/media/miscicons/notfound_thumb.gif'; 04062 } 04063 $icon = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . $icon) . '"' . 04064 $this->getBorderAttr(' border="0"') . '' . $this->getAltParam($conf) . ' />'; 04065 } 04066 } else { 04067 $icon = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . $icon) . 04068 '" width="18" height="16"' . $this->getBorderAttr(' border="0"') . 04069 $this->getAltParam($conf) . ' />'; 04070 } 04071 if ($conf['icon_link']) { 04072 $icon = $this->wrap($icon, $theLinkWrap); 04073 } 04074 $icon = isset($conf['icon.']) 04075 ? $this->stdWrap($icon, $conf['icon.']) 04076 : $icon; 04077 } 04078 if ($conf['size']) { 04079 $size = isset($conf['size.']) 04080 ? $this->stdWrap($theSize, $conf['size.']) 04081 : $theSize; 04082 } 04083 04084 // Wrapping file label 04085 if ($conf['removePrependedNumbers']) { 04086 $theValue = preg_replace('/_[0-9][0-9](\.[[:alnum:]]*)$/', '\1', $theValue); 04087 } 04088 if(isset($conf['labelStdWrap.'])) { 04089 $theValue = $this->stdWrap($theValue, $conf['labelStdWrap.']); 04090 } 04091 04092 // Wrapping file 04093 $wrap = isset($conf['wrap.']) 04094 ? $this->stdWrap($conf['wrap'], $conf['wrap.']) 04095 : $conf['wrap']; 04096 if ($conf['ATagBeforeWrap']) { 04097 $theValue = $this->wrap($this->wrap($theValue, $wrap), $theLinkWrap); 04098 } else { 04099 $theValue = $this->wrap($this->wrap($theValue, $theLinkWrap), $wrap); 04100 } 04101 $file = isset($conf['file.']) 04102 ? $this->stdWrap($theValue, $conf['file.']) 04103 : $theValue; 04104 // output 04105 $output = $icon . $file . $size; 04106 if(isset($conf['stdWrap.'])) { 04107 $output = $this->stdWrap($output, $conf['stdWrap.']); 04108 } 04109 04110 return $output; 04111 } 04112 } 04113 04114 /** 04115 * Returns a URL parameter string setting parameters for secure downloads by "jumpurl". 04116 * Helper function for filelink() 04117 * 04118 * @param string The URL to jump to, basically the filepath 04119 * @param array TypoScript properties for the "jumpurl.secure" property of "filelink" 04120 * @return string URL parameters like "&juSecure=1....." 04121 * @access private 04122 * @see filelink() 04123 */ 04124 function locDataJU($jumpUrl, $conf) { 04125 $fI = pathinfo($jumpUrl); 04126 $mimetype = ''; 04127 $mimetypeValue = ''; 04128 if ($fI['extension']) { 04129 $mimeTypes = t3lib_div::trimExplode(',', $conf['mimeTypes'], 1); 04130 foreach ($mimeTypes as $v) { 04131 $parts = explode('=', $v, 2); 04132 if (strtolower($fI['extension']) == strtolower(trim($parts[0]))) { 04133 $mimetypeValue = trim($parts[1]); 04134 $mimetype = '&mimeType=' . rawurlencode($mimetypeValue); 04135 break; 04136 } 04137 } 04138 } 04139 $locationData = $GLOBALS['TSFE']->id . ':' . $this->currentRecord; 04140 $rec = '&locationData=' . rawurlencode($locationData); 04141 $hArr = array( 04142 $jumpUrl, $locationData, $mimetypeValue 04143 ); 04144 $juHash = '&juHash=' . t3lib_div::hmac(serialize($hArr)); 04145 return '&juSecure=1' . $mimetype . $rec . $juHash; 04146 } 04147 04148 /** 04149 * Performs basic mathematical evaluation of the input string. Does NOT take parathesis and operator precedence into account! (for that, see t3lib_div::calcPriority()) 04150 * 04151 * @param string The string to evaluate. Example: "3+4*10/5" will generate "35". Only integer numbers can be used. 04152 * @return integer The result (might be a float if you did a division of the numbers). 04153 * @see t3lib_div::calcPriority() 04154 */ 04155 function calc($val) { 04156 $parts = t3lib_div::splitCalc($val, '+-*/'); 04157 $value = 0; 04158 foreach ($parts as $part) { 04159 $theVal = $part[1]; 04160 $sign = $part[0]; 04161 if ((string) intval($theVal) == (string) $theVal) { 04162 $theVal = intval($theVal); 04163 } else { 04164 $theVal = 0; 04165 } 04166 if ($sign == '-') { 04167 $value -= $theVal; 04168 } 04169 if ($sign == '+') { 04170 $value += $theVal; 04171 } 04172 if ($sign == '/') { 04173 if (intval($theVal)) 04174 $value /= intval($theVal); 04175 } 04176 if ($sign == '*') { 04177 $value *= $theVal; 04178 } 04179 } 04180 return $value; 04181 } 04182 04183 /** 04184 * This explodes a comma-list into an array where the values are parsed through tslib_cObj::calc() and intval() (so you are sure to have integers in the output array) 04185 * Used to split and calculate min and max values for GMENUs. 04186 * 04187 * @param string Delimited to explode by 04188 * @param string The string with parts in (where each part is evaluated by ->calc()) 04189 * @return array And array with evaluated values. 04190 * @see calc(), tslib_gmenu::makeGifs() 04191 */ 04192 function calcIntExplode($delim, $string) { 04193 $temp = explode($delim, $string); 04194 foreach ($temp as $key => $val) { 04195 $temp[$key] = intval(tslib_cObj::calc($val)); 04196 } 04197 return $temp; 04198 } 04199 04200 /** 04201 * Implements the "split" property of stdWrap; Splits a string based on a token (given in TypoScript properties), sets the "current" value to each part and then renders a content object pointer to by a number. 04202 * In classic TypoScript (like 'content (default)'/'styles.content (default)') this is used to render tables, splitting rows and cells by tokens and putting them together again wrapped in <td> tags etc. 04203 * Implements the "optionSplit" processing of the TypoScript options for each splitted value to parse. 04204 * 04205 * @param string The string value to explode by $conf[token] and process each part 04206 * @param array TypoScript properties for "split" 04207 * @return string Compiled result 04208 * @access private 04209 * @see stdWrap(), t3lib_menu::procesItemStates() 04210 */ 04211 function splitObj($value, $conf) { 04212 $conf['token'] = isset($conf['token.']) 04213 ? $this->stdWrap($conf['token'], $conf['token.']) 04214 : $conf['token']; 04215 if (!$conf['token']) { 04216 return $value; 04217 } 04218 $conf['max'] = isset($conf['max.']) 04219 ? intval($this->stdWrap($conf['max'], $conf['max.'])) 04220 : intval($conf['max']); 04221 $conf['min'] = isset($conf['min.']) 04222 ? intval($this->stdWrap($conf['min'], $conf['min.'])) 04223 : intval($conf['min']); 04224 04225 $valArr = explode($conf['token'], $value); 04226 04227 if (count($valArr) && (t3lib_div::testInt($conf['returnKey']) || $conf['returnKey.'])) { 04228 $key = isset($conf['returnKey.']) 04229 ? intval($this->stdWrap($conf['returnKey'], $conf['returnKey.'])) 04230 : intval($conf['returnKey']); 04231 $content = isset($valArr[$key]) ? $valArr[$key] : ''; 04232 } else { 04233 // calculate splitCount 04234 $splitCount = count($valArr); 04235 $max = isset($conf['max.']) 04236 ? $this->stdWrap($conf['max'],$conf['max.']) 04237 : $conf['max']; 04238 if ($max && $splitCount > $max) { 04239 $splitCount = $max; 04240 } 04241 $min = isset($conf['min.']) 04242 ? $this->stdWrap($conf['min'],$conf['min.']) 04243 : $conf['min']; 04244 if ($min && $splitCount < $min) { 04245 $splitCount = $min; 04246 } 04247 04248 $wrap = isset($conf['wrap.']) 04249 ? $this->stdWrap($conf['wrap'], $conf['wrap.']) 04250 : $conf['wrap']; 04251 $cObjNum = isset($conf['cObjNum.']) 04252 ? $this->stdWrap($conf['cObjNum'], $conf['cObjNum.']) 04253 : $conf['cObjNum']; 04254 if ($wrap || $cObjNum) { 04255 $splitArr = array(); 04256 $splitArr['wrap'] = $wrap; 04257 $splitArr['cObjNum'] = $cObjNum; 04258 $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $splitCount); 04259 } 04260 04261 $content = ''; 04262 for ($a = 0; $a < $splitCount; $a++) { 04263 $GLOBALS['TSFE']->register['SPLIT_COUNT'] = $a; 04264 $value = '' . $valArr[$a]; 04265 $this->data[$this->currentValKey] = $value; 04266 if ($splitArr[$a]['cObjNum']) { 04267 $objName = intval($splitArr[$a]['cObjNum']); 04268 $value = isset($conf[$objName . '.']) 04269 ? $this->stdWrap($this->cObjGet($conf[$objName . '.'], $objName . '.'), $conf[$objName . '.']) 04270 : $this->cObjGet($conf[$objName . '.'], $objName . '.'); 04271 } 04272 $wrap = isset($splitArr[$a]['wrap.']) 04273 ? $this->stdWrap($splitArr[$a]['wrap'], $splitArr[$a]['wrap.']) 04274 : $splitArr[$a]['wrap']; 04275 if ($wrap) { 04276 $value = $this->wrap($value, $wrap); 04277 } 04278 $content .= $value; 04279 } 04280 } 04281 return $content; 04282 } 04283 04284 /** 04285 * Implements the stdWrap property "numberFormat" 04286 * This is a Wrapper function for php's number_format() 04287 * 04288 * @param float Value to process 04289 * @param array TypoScript Configuration for numberFormat 04290 * @return string The formated number 04291 */ 04292 function numberFormat($content, $conf) { 04293 $decimals = isset($conf['decimals.']) 04294 ? $this->stdWrap($conf['decimals'], $conf['decimals.']) 04295 : $conf['decimals']; 04296 $dec_point = isset($conf['dec_point.']) 04297 ? $this->stdWrap($conf['dec_point'], $conf['dec_point.']) 04298 : $conf['dec_point']; 04299 $thousands_sep = isset($conf['thousands_sep.']) 04300 ? $this->stdWrap($conf['thousands_sep'], $conf['thousands_sep.']) 04301 : $conf['thousands_sep']; 04302 return number_format($content, $decimals, $dec_point, $thousands_sep); 04303 } 04304 04305 /** 04306 * Implements the stdWrap property, "parseFunc". 04307 * This is a function with a lot of interesting uses. In classic TypoScript this is used to process text 04308 * from the bodytext field; This included highlighting of search words, changing http:// and mailto: prefixed strings into links, 04309 * parsing <typolist>, <typohead> and <typocode> tags etc. 04310 * It is still a very important function for processing of bodytext which is normally stored in the database 04311 * in a format which is not fully ready to be outputted. 04312 * This situation has not become better by having a RTE around... 04313 * 04314 * This function is actually just splitting the input content according to the configuration of "external blocks". 04315 * This means that before the input string is actually "parsed" it will be splitted into the parts configured to BE parsed 04316 * (while other parts/blocks should NOT be parsed). 04317 * Therefore the actual processing of the parseFunc properties goes on in ->_parseFunc() 04318 * 04319 * @param string The value to process. 04320 * @param array TypoScript configuration for parseFunc 04321 * @param string Reference to get configuration from. Eg. "< lib.parseFunc" which means that the configuration of the object path "lib.parseFunc" will be retrieved and MERGED with what is in $conf! 04322 * @return string The processed value 04323 * @see _parseFunc() 04324 */ 04325 function parseFunc($theValue, $conf, $ref = '') { 04326 04327 // Fetch / merge reference, if any 04328 if ($ref) { 04329 $temp_conf = array( 04330 'parseFunc' => $ref, 'parseFunc.' => $conf 04331 ); 04332 $temp_conf = $this->mergeTSRef($temp_conf, 'parseFunc'); 04333 $conf = $temp_conf['parseFunc.']; 04334 } 04335 04336 // Process: 04337 if (strcmp($conf['externalBlocks'], '')) { 04338 $tags = strtolower(implode(',', t3lib_div::trimExplode(',', $conf['externalBlocks']))); 04339 $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml'); 04340 $parts = $htmlParser->splitIntoBlock($tags, $theValue); 04341 04342 foreach ($parts as $k => $v) { 04343 if ($k % 2) { // font: 04344 $tagName = strtolower($htmlParser->getFirstTagName($v)); 04345 $cfg = $conf['externalBlocks.'][$tagName . '.']; 04346 if ($cfg['stripNLprev'] || $cfg['stripNL']) { 04347 $parts[$k - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $parts[$k - 1]); 04348 } 04349 if ($cfg['stripNLnext'] || $cfg['stripNL']) { 04350 $parts[$k + 1] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $parts[$k + 1]); 04351 } 04352 } 04353 } 04354 04355 foreach ($parts as $k => $v) { 04356 if ($k % 2) { 04357 $tag = $htmlParser->getFirstTag($v); 04358 $tagName = strtolower($htmlParser->getFirstTagName($v)); 04359 $cfg = $conf['externalBlocks.'][$tagName . '.']; 04360 if ($cfg['callRecursive']) { 04361 $parts[$k] = $this->parseFunc($htmlParser->removeFirstAndLastTag($v), $conf); 04362 if (!$cfg['callRecursive.']['dontWrapSelf']) { 04363 if ($cfg['callRecursive.']['alternativeWrap']) { 04364 $parts[$k] = $this->wrap($parts[$k], $cfg['callRecursive.']['alternativeWrap']); 04365 } else { 04366 if (is_array($cfg['callRecursive.']['tagStdWrap.'])) { 04367 $tag = $this->stdWrap($tag, $cfg['callRecursive.']['tagStdWrap.']); 04368 } 04369 $parts[$k] = $tag . $parts[$k] . '</' . $tagName . '>'; 04370 } 04371 } 04372 } elseif ($cfg['HTMLtableCells']) { 04373 $rowParts = $htmlParser->splitIntoBlock('tr', $parts[$k]); 04374 foreach ($rowParts as $kk => $vv) { 04375 if ($kk % 2) { 04376 $colParts = $htmlParser->splitIntoBlock('td,th', $vv); 04377 $cc = 0; 04378 foreach ($colParts as $kkk => $vvv) { 04379 if ($kkk % 2) { 04380 $cc++; 04381 $tag = $htmlParser->getFirstTag($vvv); 04382 $tagName = strtolower($htmlParser->getFirstTagName($vvv)); 04383 $colParts[$kkk] = $htmlParser->removeFirstAndLastTag($vvv); 04384 04385 if ($cfg['HTMLtableCells.'][$cc . '.']['callRecursive'] || (!isset($cfg['HTMLtableCells.'][$cc . '.']['callRecursive']) && $cfg['HTMLtableCells.']['default.']['callRecursive'])) { 04386 if ($cfg['HTMLtableCells.']['addChr10BetweenParagraphs']) 04387 $colParts[$kkk] = str_replace('</p><p>', '</p>' . LF . '<p>', $colParts[$kkk]); 04388 $colParts[$kkk] = $this->parseFunc($colParts[$kkk], $conf); 04389 } 04390 04391 $tagStdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.']) ? $cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.'] : $cfg['HTMLtableCells.']['default.']['tagStdWrap.']; 04392 if (is_array($tagStdWrap)) { 04393 $tag = $this->stdWrap($tag, $tagStdWrap); 04394 } 04395 04396 $stdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['stdWrap.']) ? $cfg['HTMLtableCells.'][$cc . '.']['stdWrap.'] : $cfg['HTMLtableCells.']['default.']['stdWrap.']; 04397 if (is_array($stdWrap)) { 04398 $colParts[$kkk] = $this->stdWrap($colParts[$kkk], $stdWrap); 04399 } 04400 04401 $colParts[$kkk] = $tag . $colParts[$kkk] . '</' . $tagName . '>'; 04402 } 04403 } 04404 $rowParts[$kk] = implode('', $colParts); 04405 } 04406 } 04407 $parts[$k] = implode('', $rowParts); 04408 } 04409 04410 if (is_array($cfg['stdWrap.'])) { 04411 $parts[$k] = $this->stdWrap($parts[$k], $cfg['stdWrap.']); 04412 } 04413 } else { 04414 $parts[$k] = $this->_parseFunc($parts[$k], $conf); 04415 } 04416 } 04417 04418 return implode('', $parts); 04419 } else 04420 return $this->_parseFunc($theValue, $conf); 04421 } 04422 04423 /** 04424 * Helper function for parseFunc() 04425 * 04426 * @param string The value to process. 04427 * @param array TypoScript configuration for parseFunc 04428 * @return string The processed value 04429 * @access private 04430 * @see parseFunc() 04431 */ 04432 function _parseFunc($theValue, $conf) { 04433 if (!$this->checkIf($conf['if.'])) { 04434 return $theValue; 04435 } 04436 $inside = 0; // Indicates that the data is from within a tag. 04437 $pointer = 0; // Pointer to the total string position 04438 $currentTag = ''; // Loaded with the current typo-tag if any. 04439 $stripNL = 0; 04440 $contentAccum = array(); 04441 $contentAccumP = 0; 04442 04443 $allowTags = strtolower(str_replace(' ', '', $conf['allowTags'])); 04444 $denyTags = strtolower(str_replace(' ', '', $conf['denyTags'])); 04445 04446 $totalLen = strlen($theValue); 04447 do { 04448 if (!$inside) { 04449 if (!is_array($currentTag)) { 04450 // These operations should only be performed on code outside the typotags... 04451 // data: this checks that we enter tags ONLY if the first char in the tag is alphanumeric OR '/' 04452 $len_p = 0; 04453 $c = 100; 04454 do { 04455 $len = strcspn(substr($theValue, $pointer + $len_p), '<'); 04456 $len_p += $len + 1; 04457 $endChar = ord(strtolower(substr($theValue, $pointer + $len_p, 1))); 04458 $c--; 04459 } while ($c > 0 && $endChar && ($endChar < 97 || $endChar > 122) && $endChar != 47); 04460 $len = $len_p - 1; 04461 } else { 04462 // If we're inside a currentTag, just take it to the end of that tag! 04463 $tempContent = strtolower(substr($theValue, $pointer)); 04464 $len = strpos($tempContent, '</' . $currentTag[0]); 04465 if (is_string($len) && !$len) { 04466 $len = strlen($tempContent); 04467 } 04468 } 04469 04470 $data = substr($theValue, $pointer, $len); // $data is the content until the next <tag-start or end is detected. In case of a currentTag set, this would mean all data between the start- and end-tags 04471 if ($data != '') { 04472 if ($stripNL) { 04473 // If the previous tag was set to strip NewLines in the beginning of the next data-chunk. 04474 $data = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $data); 04475 } 04476 04477 if (!is_array($currentTag)) { // These operations should only be performed on code outside the tags... 04478 // Constants 04479 $tmpConstants = $GLOBALS['TSFE']->tmpl->setup['constants.']; 04480 if ($conf['constants'] && is_array($tmpConstants)) { 04481 foreach ($tmpConstants as $key => $val) { 04482 if (is_string($val)) { 04483 $data = str_replace('###' . $key . '###', $val, $data); 04484 } 04485 } 04486 } 04487 // Short 04488 if (is_array($conf['short.'])) { 04489 $shortWords = $conf['short.']; 04490 krsort($shortWords); 04491 foreach ($shortWords as $key => $val) { 04492 if (is_string($val)) { 04493 $data = str_replace($key, $val, $data); 04494 } 04495 } 04496 } 04497 04498 // stdWrap 04499 if (is_array($conf['plainTextStdWrap.'])) { 04500 $data = $this->stdWrap($data, $conf['plainTextStdWrap.']); 04501 } 04502 // userFunc 04503 if ($conf['userFunc']) { 04504 $data = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $data); 04505 } 04506 04507 // Makelinks: (Before search-words as we need the links to be generated when searchwords go on...!) 04508 if ($conf['makelinks']) { 04509 $data = $this->http_makelinks($data, $conf['makelinks.']['http.']); 04510 $data = $this->mailto_makelinks($data, $conf['makelinks.']['mailto.']); 04511 } 04512 04513 // Search Words: 04514 if ($GLOBALS['TSFE']->no_cache && $conf['sword'] && is_array($GLOBALS['TSFE']->sWordList) && $GLOBALS['TSFE']->sWordRegEx) { 04515 $newstring = ''; 04516 do { 04517 $pregSplitMode = 'i'; 04518 if (isset($GLOBALS['TSFE']->config['config']['sword_noMixedCase']) && !empty($GLOBALS['TSFE']->config['config']['sword_noMixedCase'])) { 04519 $pregSplitMode = ''; 04520 } 04521 $pieces = preg_split('/' . $GLOBALS['TSFE']->sWordRegEx . '/' . $pregSplitMode, $data, 2); 04522 $newstring .= $pieces[0]; 04523 $match_len = strlen($data) - (strlen($pieces[0]) + strlen($pieces[1])); 04524 if (strstr($pieces[0], '<') || strstr($pieces[0], '>')) { 04525 $inTag = strrpos($pieces[0], '<') > strrpos($pieces[0], '>'); // Returns TRUE, if a '<' is closer to the string-end than '>'. This is the case if we're INSIDE a tag (that could have been made by makelinks...) and we must secure, that the inside of a tag is not marked up. 04526 } 04527 // The searchword: 04528 $match = substr($data, strlen($pieces[0]), $match_len); 04529 04530 if (trim($match) && strlen($match) > 1 && !$inTag) { 04531 $match = $this->wrap($match, $conf['sword']); 04532 } 04533 // Concatenate the Search Word again. 04534 $newstring .= $match; 04535 $data = $pieces[1]; 04536 } while ($pieces[1]); 04537 $data = $newstring; 04538 } 04539 } 04540 $contentAccum[$contentAccumP] .= $data; 04541 } 04542 $inside = 1; 04543 } else { 04544 // tags 04545 $len = strcspn(substr($theValue, $pointer), '>') + 1; 04546 $data = substr($theValue, $pointer, $len); 04547 04548 $tag = explode(' ', trim(substr($data, 1, -1)), 2); 04549 $tag[0] = strtolower($tag[0]); 04550 if (substr($tag[0], 0, 1) == '/') { 04551 $tag[0] = substr($tag[0], 1); 04552 $tag['out'] = 1; 04553 } 04554 if ($conf['tags.'][$tag[0]]) { 04555 $treated = 0; 04556 $stripNL = 0; 04557 // in-tag 04558 if (!$currentTag && !$tag['out']) { 04559 $currentTag = $tag; // $currentTag (array!) is the tag we are currently processing 04560 $contentAccumP++; 04561 $treated = 1; 04562 // in-out-tag: img and other empty tags 04563 if (preg_match('/^(area|base|br|col|hr|img|input|meta|param)$/i', $tag[0])) { 04564 $tag['out'] = 1; 04565 } 04566 } 04567 // out-tag 04568 if ($currentTag[0] == $tag[0] && $tag['out']) { 04569 $theName = $conf['tags.'][$tag[0]]; 04570 $theConf = $conf['tags.'][$tag[0] . '.']; 04571 $stripNL = ($theConf['stripNL'] ? 1 : 0); // This flag indicates, that NL- (13-10-chars) should be stripped first and last. 04572 $breakOut = ($theConf['breakoutTypoTagContent'] ? 1 : 0); // This flag indicates, that this TypoTag section should NOT be included in the nonTypoTag content. 04573 04574 04575 $this->parameters = array(); 04576 if ($currentTag[1]) { 04577 $params = t3lib_div::get_tag_attributes($currentTag[1]); 04578 if (is_array($params)) { 04579 foreach ($params as $option => $val) { 04580 $this->parameters[strtolower($option)] = $val; 04581 } 04582 } 04583 } 04584 $this->parameters['allParams'] = trim($currentTag[1]); 04585 if ($stripNL) { // Removes NL in the beginning and end of the tag-content AND at the end of the currentTagBuffer. $stripNL depends on the configuration of the current tag 04586 $contentAccum[$contentAccumP - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP - 1]); 04587 $contentAccum[$contentAccumP] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $contentAccum[$contentAccumP]); 04588 $contentAccum[$contentAccumP] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP]); 04589 } 04590 $this->data[$this->currentValKey] = $contentAccum[$contentAccumP]; 04591 $newInput = $this->cObjGetSingle($theName, $theConf, '/parseFunc/.tags.' . $tag[0]); // fetch the content object 04592 04593 04594 $contentAccum[$contentAccumP] = $newInput; 04595 $contentAccumP++; 04596 04597 // If the TypoTag section 04598 if (!$breakOut) { 04599 $contentAccum[$contentAccumP - 2] .= $contentAccum[$contentAccumP - 1] . $contentAccum[$contentAccumP]; 04600 unset($contentAccum[$contentAccumP]); 04601 unset($contentAccum[$contentAccumP - 1]); 04602 $contentAccumP -= 2; 04603 } 04604 04605 unset($currentTag); 04606 $treated = 1; 04607 } 04608 // other tags... 04609 if (!$treated) { 04610 $contentAccum[$contentAccumP] .= $data; 04611 } 04612 } else { 04613 // If a tag was not a typo tag, then it is just added to the content 04614 $stripNL = 0; 04615 if (t3lib_div::inList($allowTags, $tag[0]) || ($denyTags != '*' && !t3lib_div::inList($denyTags, $tag[0]))) { 04616 $contentAccum[$contentAccumP] .= $data; 04617 } else { 04618 $contentAccum[$contentAccumP] .= HTMLSpecialChars($data); 04619 } 04620 } 04621 $inside = 0; 04622 } 04623 $pointer += $len; 04624 } while ($pointer < $totalLen); 04625 04626 // Parsing nonTypoTag content (all even keys): 04627 reset($contentAccum); 04628 for ($a = 0; $a < count($contentAccum); $a++) { 04629 if ($a % 2 != 1) { 04630 // stdWrap 04631 if (is_array($conf['nonTypoTagStdWrap.'])) { 04632 $contentAccum[$a] = $this->stdWrap($contentAccum[$a], $conf['nonTypoTagStdWrap.']); 04633 } 04634 // userFunc 04635 if ($conf['nonTypoTagUserFunc']) { 04636 $contentAccum[$a] = $this->callUserFunction( 04637 $conf['nonTypoTagUserFunc'], 04638 $conf['nonTypoTagUserFunc.'], 04639 $contentAccum[$a] 04640 ); 04641 } 04642 } 04643 } 04644 return implode('', $contentAccum); 04645 } 04646 04647 /** 04648 * Lets you split the content by LF and proces each line independently. Used to format content made with the RTE. 04649 * 04650 * @param string The input value 04651 * @param array TypoScript options 04652 * @return string The processed input value being returned; Splitted lines imploded by LF again. 04653 * @access private 04654 */ 04655 function encaps_lineSplit($theValue, $conf) { 04656 $lParts = explode(LF, $theValue); 04657 04658 $encapTags = t3lib_div::trimExplode(',', strtolower($conf['encapsTagList']), 1); 04659 $nonWrappedTag = $conf['nonWrappedTag']; 04660 $defaultAlign = isset($conf['defaultAlign.']) 04661 ? trim($this->stdWrap($conf['defaultAlign'], $conf['defaultAlign.'])) 04662 : trim($conf['defaultAlign']); 04663 04664 if (!strcmp('', $theValue)) 04665 return ''; 04666 04667 foreach ($lParts as $k => $l) { 04668 $sameBeginEnd = 0; 04669 $emptyTag = 0; 04670 $l = trim($l); 04671 $attrib = array(); 04672 $nWrapped = 0; 04673 if (substr($l, 0, 1) == '<' && substr($l, -1) == '>') { 04674 $fwParts = explode('>', substr($l, 1), 2); 04675 list($tagName, $tagParams) = explode(' ',$fwParts[0], 2); 04676 if (!$fwParts[1]) { 04677 if (substr($tagName, -1) == '/') { 04678 $tagName = substr($tagName, 0, -1); 04679 } 04680 if (substr($fwParts[0], -1) == '/') { 04681 $sameBeginEnd = 1; 04682 $emptyTag = 1; 04683 $attrib = t3lib_div::get_tag_attributes('<'.substr($fwParts[0], 0, -1).'>'); 04684 } 04685 } else { 04686 $backParts = t3lib_div::revExplode('<', substr($fwParts[1],0,-1), 2); 04687 $attrib = t3lib_div::get_tag_attributes('<'.$fwParts[0].'>'); 04688 $str_content = $backParts[0]; 04689 $sameBeginEnd = (substr(strtolower($backParts[1]),1,strlen($tagName))==strtolower($tagName)); 04690 } 04691 } 04692 04693 if ($sameBeginEnd && in_array(strtolower($tagName), $encapTags)) { 04694 $uTagName = strtoupper($tagName); 04695 $uTagName = strtoupper($conf['remapTag.'][$uTagName] ? $conf['remapTag.'][$uTagName] : $uTagName); 04696 } else { 04697 $uTagName = strtoupper($nonWrappedTag); 04698 // The line will be wrapped: $uTagName should not be an empty tag 04699 $emptyTag = 0; 04700 $str_content = $lParts[$k]; 04701 $nWrapped = 1; 04702 $attrib = array(); 04703 } 04704 04705 // Wrapping all inner-content: 04706 if (is_array($conf['innerStdWrap_all.'])) { 04707 $str_content = $this->stdWrap($str_content, $conf['innerStdWrap_all.']); 04708 } 04709 04710 if ($uTagName) { 04711 // Setting common attributes 04712 if (is_array($conf['addAttributes.'][$uTagName . '.'])) { 04713 foreach ($conf['addAttributes.'][$uTagName . '.'] as $kk => $vv) { 04714 if (!is_array($vv)) { 04715 if ((string) $conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] == 'blank') { 04716 if (!strcmp($attrib[$kk], '')) 04717 $attrib[$kk] = $vv; 04718 } elseif ((string) $conf['addAttributes.'][$uTagName . '.'][$kk . '.']['setOnly'] == 'exists') { 04719 if (!isset($attrib[$kk])) 04720 $attrib[$kk] = $vv; 04721 } else { 04722 $attrib[$kk] = $vv; 04723 } 04724 } 04725 } 04726 } 04727 // Wrapping all inner-content: 04728 if (is_array($conf['encapsLinesStdWrap.'][$uTagName . '.'])) { 04729 $str_content = $this->stdWrap($str_content, $conf['encapsLinesStdWrap.'][$uTagName . '.']); 04730 } 04731 // Default align 04732 if (!$attrib['align'] && $defaultAlign) 04733 $attrib['align'] = $defaultAlign; 04734 04735 $params = t3lib_div::implodeAttributes($attrib, 1); 04736 if ($conf['removeWrapping'] && !($emptyTag && $conf['removeWrapping.']['keepSingleTag'])) { 04737 $str_content = $str_content; 04738 } else { 04739 if ($emptyTag) { 04740 $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').' />'; 04741 } else { 04742 $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').'>'.$str_content.'</'.strtolower($uTagName).'>'; 04743 } 04744 } 04745 } 04746 04747 if ($nWrapped && $conf['wrapNonWrappedLines']) { 04748 $str_content = $this->wrap($str_content, $conf['wrapNonWrappedLines']); 04749 } 04750 $lParts[$k] = $str_content; 04751 } 04752 04753 return implode(LF, $lParts); 04754 } 04755 04756 /** 04757 * Finds URLS in text and makes it to a real link. 04758 * Will find all strings prefixed with "http://" in the $data string and make them into a link, linking to the URL we should have found. 04759 * 04760 * @param string The string in which to search for "http://" 04761 * @param array Configuration for makeLinks, see link 04762 * @return string The processed input string, being returned. 04763 * @see _parseFunc() 04764 */ 04765 function http_makelinks($data, $conf) { 04766 $aTagParams = $this->getATagParams($conf); 04767 $textpieces = explode('http://', $data); 04768 $pieces = count($textpieces); 04769 $textstr = $textpieces[0]; 04770 $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type; 04771 for ($i = 1; $i < $pieces; $i++) { 04772 $len = strcspn($textpieces[$i], chr(32) . TAB . CRLF); 04773 if (trim(substr($textstr, -1)) == '' && $len) { 04774 04775 $lastChar = substr($textpieces[$i], $len - 1, 1); 04776 if (!preg_match('/[A-Za-z0-9\/#_-]/', $lastChar)) { 04777 $len--; 04778 } // Included '\/' 3/12 04779 04780 04781 $parts[0] = substr($textpieces[$i], 0, $len); 04782 $parts[1] = substr($textpieces[$i], $len); 04783 04784 $keep = $conf['keep']; 04785 $linkParts = parse_url('http://' . $parts[0]); 04786 $linktxt = ''; 04787 if (strstr($keep, 'scheme')) { 04788 $linktxt = 'http://'; 04789 } 04790 $linktxt .= $linkParts['host']; 04791 if (strstr($keep, 'path')) { 04792 $linktxt .= $linkParts['path']; 04793 if (strstr($keep, 'query') && $linkParts['query']) { // added $linkParts['query'] 3/12 04794 $linktxt .= '?' . $linkParts['query']; 04795 } elseif ($linkParts['path'] == '/') { // If query is NOT added and the path is '/' then remove the slash ('/') (added 3/12) 04796 $linktxt = substr($linktxt, 0, -1); 04797 } 04798 } 04799 $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget; 04800 if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) { 04801 $res = '<a' . ' href="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . 04802 $GLOBALS['TSFE']->config['mainScript'] . $initP . 04803 '&jumpurl=' . rawurlencode('http://' . $parts[0]) . $GLOBALS['TSFE']->getMethodUrlIdToken) . '"' . 04804 ($target ? ' target="' . $target . '"' : '') . 04805 $aTagParams . $this->extLinkATagParams('http://' . $parts[0], 'url') . 04806 '>'; 04807 } else { 04808 $res = '<a' . ' href="http://' . htmlspecialchars($parts[0]) . '"' . 04809 ($target ? ' target="' . $target . '"' : '') . 04810 $aTagParams . $this->extLinkATagParams('http://' . $parts[0], 'url') . 04811 '>'; 04812 } 04813 $wrap = isset($conf['wrap.']) 04814 ? $this->stdWrap($conf['wrap'], $conf['wrap.']) 04815 : $conf['wrap']; 04816 if ($conf['ATagBeforeWrap']) { 04817 $res = $res . $this->wrap($linktxt, $wrap) . '</a>'; 04818 } else { 04819 $res = $this->wrap($res . $linktxt . '</a>', $wrap); 04820 } 04821 $textstr .= $res . $parts[1]; 04822 } else { 04823 $textstr .= 'http://' . $textpieces[$i]; 04824 } 04825 } 04826 return $textstr; 04827 } 04828 04829 /** 04830 * Will find all strings prefixed with "mailto:" in the $data string and make them into a link, 04831 * linking to the email address they point to. 04832 * 04833 * @param string The string in which to search for "mailto:" 04834 * @param array Configuration for makeLinks, see link 04835 * @return string The processed input string, being returned. 04836 * @see _parseFunc() 04837 */ 04838 function mailto_makelinks($data, $conf) { 04839 // http-split 04840 $aTagParams = $this->getATagParams($conf); 04841 $textpieces = explode('mailto:', $data); 04842 $pieces = count($textpieces); 04843 $textstr = $textpieces[0]; 04844 $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type; 04845 for ($i = 1; $i < $pieces; $i++) { 04846 $len = strcspn($textpieces[$i], chr(32) . TAB . CRLF); 04847 if (trim(substr($textstr, -1)) == '' && $len) { 04848 $lastChar = substr($textpieces[$i], $len - 1, 1); 04849 if (!preg_match('/[A-Za-z0-9]/', $lastChar)) { 04850 $len--; 04851 } 04852 04853 $parts[0] = substr($textpieces[$i], 0, $len); 04854 $parts[1] = substr($textpieces[$i], $len); 04855 $linktxt = preg_replace('/\?.*/', '', $parts[0]); 04856 list ($mailToUrl, $linktxt) = $this->getMailTo($parts[0], $linktxt, $initP); 04857 $mailToUrl = $GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' ? $mailToUrl : htmlspecialchars($mailToUrl); 04858 $res = '<a href="' . $mailToUrl . '"' . $aTagParams . '>'; 04859 $wrap = isset($conf['wrap.']) 04860 ? $this->stdWrap($conf['wrap'], $conf['wrap.']) 04861 : $conf['wrap']; 04862 if ($conf['ATagBeforeWrap']) { 04863 $res = $res . $this->wrap($linktxt, $wrap) . '</a>'; 04864 } else { 04865 $res = $this->wrap($res . $linktxt . '</a>', $wrap); 04866 } 04867 $textstr .= $res . $parts[1]; 04868 } else { 04869 $textstr .= 'mailto:' . $textpieces[$i]; 04870 } 04871 } 04872 return $textstr; 04873 } 04874 04875 /** 04876 * Creates and returns a TypoScript "imgResource". 04877 * The value ($file) can either be a file reference (TypoScript resource) or the string "GIFBUILDER". 04878 * In the first case a current image is returned, possibly scaled down or otherwise processed. 04879 * In the latter case a GIFBUILDER image is returned; This means an image is made by TYPO3 from layers of elements as GIFBUILDER defines. 04880 * In the function IMG_RESOURCE() this function is called like $this->getImgResource($conf['file'],$conf['file.']); 04881 * 04882 * @param string A "imgResource" TypoScript data type. Either a TypoScript file resource or the string GIFBUILDER. See description above. 04883 * @param array TypoScript properties for the imgResource type 04884 * @return array Returns info-array. info[origFile] = original file. 04885 * @see IMG_RESOURCE(), cImage(), tslib_gifBuilder 04886 */ 04887 function getImgResource($file, $fileArray) { 04888 if (is_array($fileArray)) { 04889 switch ($file) { 04890 case 'GIFBUILDER' : 04891 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder'); 04892 $gifCreator->init(); 04893 $theImage = ''; 04894 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) { 04895 $gifCreator->start($fileArray, $this->data); 04896 $theImage = $gifCreator->gifBuild(); 04897 } 04898 $imageResource = $gifCreator->getImageDimensions($theImage); 04899 break; 04900 default : 04901 if ($fileArray['import.']) { 04902 $ifile = $this->stdWrap('', $fileArray['import.']); 04903 if ($ifile) { 04904 $file = $fileArray['import'] . $ifile; 04905 } 04906 } 04907 $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file); 04908 if ($theImage) { 04909 $fileArray['width'] = isset($fileArray['width.']) 04910 ? $this->stdWrap($fileArray['width'], $fileArray['width.']) 04911 : $fileArray['width']; 04912 $fileArray['height'] = isset($fileArray['height.']) 04913 ? $this->stdWrap($fileArray['height'], $fileArray['height.']) 04914 : $fileArray['height']; 04915 $fileArray['ext'] = isset($fileArray['ext.']) 04916 ? $this->stdWrap($fileArray['ext'], $fileArray['ext.']) 04917 : $fileArray['ext']; 04918 $fileArray['maxW'] = isset($fileArray['maxW.']) 04919 ? intval($this->stdWrap($fileArray['maxW'], $fileArray['maxW.'])) 04920 : intval($fileArray['maxW']); 04921 $fileArray['maxH'] = isset($fileArray['maxH.']) 04922 ? intval($this->stdWrap($fileArray['maxH'], $fileArray['maxH.'])) 04923 : intval($fileArray['maxH']); 04924 $fileArray['minW'] = isset($fileArray['minW.']) 04925 ? intval($this->stdWrap($fileArray['minW'], $fileArray['minW.'])) 04926 : intval($fileArray['minW']); 04927 $fileArray['minH'] = isset($fileArray['minH.']) 04928 ? intval($this->stdWrap($fileArray['minH'], $fileArray['minH.'])) 04929 : intval($fileArray['minH']); 04930 $fileArray['noScale'] = isset($fileArray['noScale.']) 04931 ? $this->stdWrap($fileArray['noScale'], $fileArray['noScale.']) 04932 : $fileArray['noScale']; 04933 $maskArray = $fileArray['m.']; 04934 $maskImages = array(); 04935 if (is_array($fileArray['m.'])) { // Must render mask images and include in hash-calculating - else we cannot be sure the filename is unique for the setup! 04936 $maskImages['m_mask'] = $this->getImgResource($maskArray['mask'], $maskArray['mask.']); 04937 $maskImages['m_bgImg'] = $this->getImgResource($maskArray['bgImg'], $maskArray['bgImg.']); 04938 $maskImages['m_bottomImg'] = $this->getImgResource($maskArray['bottomImg'], $maskArray['bottomImg.']); 04939 $maskImages['m_bottomImg_mask'] = $this->getImgResource($maskArray['bottomImg_mask'], $maskArray['bottomImg_mask.']); 04940 } 04941 $hash = t3lib_div::shortMD5($theImage . serialize($fileArray) . serialize($maskImages)); 04942 if (!isset($GLOBALS['TSFE']->tmpl->fileCache[$hash])) { 04943 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder'); 04944 $gifCreator->init(); 04945 04946 if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) { 04947 $filename = basename($theImage); 04948 // remove extension 04949 $filename = substr($filename, 0, strrpos($filename, '.')); 04950 // strip everything non-ascii 04951 $filename = preg_replace('/[^A-Za-z0-9_-]/', '', trim($filename)); 04952 $gifCreator->filenamePrefix = substr($filename, 0, intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix'])) . '_'; 04953 unset($filename); 04954 } 04955 04956 if ($fileArray['sample']) { 04957 $gifCreator->scalecmd = '-sample'; 04958 $GLOBALS['TT']->setTSlogMessage('Sample option: Images are scaled with -sample.'); 04959 } 04960 if ($fileArray['alternativeTempPath'] && t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['allowedTempPaths'], $fileArray['alternativeTempPath'])) { 04961 $gifCreator->tempPath = $fileArray['alternativeTempPath']; 04962 $GLOBALS['TT']->setTSlogMessage('Set alternativeTempPath: ' . $fileArray['alternativeTempPath']); 04963 } 04964 04965 if (!trim($fileArray['ext'])) { 04966 $fileArray['ext'] = 'web'; 04967 } 04968 $options = array(); 04969 if ($fileArray['maxW']) { 04970 $options['maxW'] = $fileArray['maxW']; 04971 } 04972 if ($fileArray['maxH']) { 04973 $options['maxH'] = $fileArray['maxH']; 04974 } 04975 if ($fileArray['minW']) { 04976 $options['minW'] = $fileArray['minW']; 04977 } 04978 if ($fileArray['minH']) { 04979 $options['minH'] = $fileArray['minH']; 04980 } 04981 if ($fileArray['noScale']) { 04982 $options['noScale'] = $fileArray['noScale']; 04983 } 04984 04985 // checks to see if m (the mask array) is defined 04986 if (is_array($maskArray) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) { 04987 // Filename: 04988 $fI = t3lib_div::split_fileref($theImage); 04989 $imgExt = (strtolower($fI['fileext']) == $gifCreator->gifExtension ? $gifCreator->gifExtension : 'jpg'); 04990 $dest = $gifCreator->tempPath . $hash . '.' . $imgExt; 04991 if (!file_exists($dest)) { // Generate! 04992 $m_mask = $maskImages['m_mask']; 04993 $m_bgImg = $maskImages['m_bgImg']; 04994 if ($m_mask && $m_bgImg) { 04995 $negate = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_negate_mask'] ? ' -negate' : ''; 04996 04997 $temp_ext = 'png'; 04998 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_gif']) { // If ImageMagick version 5+ 04999 $temp_ext = $gifCreator->gifExtension; 05000 } 05001 05002 $tempFileInfo = $gifCreator->imageMagickConvert($theImage, $temp_ext, $fileArray['width'], $fileArray['height'], $fileArray['params'], $fileArray['frame'], $options); 05003 if (is_array($tempFileInfo)) { 05004 $m_bottomImg = $maskImages['m_bottomImg']; 05005 if ($m_bottomImg) { 05006 $m_bottomImg_mask = $maskImages['m_bottomImg_mask']; 05007 } 05008 // Scaling: **** 05009 $tempScale = array(); 05010 $command = '-geometry ' . $tempFileInfo[0] . 'x' . $tempFileInfo[1] . '!'; 05011 $command = $this->modifyImageMagickStripProfileParameters($command, $fileArray); 05012 $tmpStr = $gifCreator->randomName(); 05013 05014 // m_mask 05015 $tempScale['m_mask'] = $tmpStr . '_mask.' . $temp_ext; 05016 $gifCreator->imageMagickExec($m_mask[3], $tempScale['m_mask'], $command . $negate); 05017 // m_bgImg 05018 $tempScale['m_bgImg'] = $tmpStr . '_bgImg.' . trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']); 05019 $gifCreator->imageMagickExec($m_bgImg[3], $tempScale['m_bgImg'], $command); 05020 05021 // m_bottomImg / m_bottomImg_mask 05022 if ($m_bottomImg && $m_bottomImg_mask) { 05023 $tempScale['m_bottomImg'] = $tmpStr . '_bottomImg.' . $temp_ext; 05024 $gifCreator->imageMagickExec($m_bottomImg[3], $tempScale['m_bottomImg'], $command); 05025 $tempScale['m_bottomImg_mask'] = $tmpStr . '_bottomImg_mask.' . $temp_ext; 05026 $gifCreator->imageMagickExec($m_bottomImg_mask[3], $tempScale['m_bottomImg_mask'], $command . $negate); 05027 05028 // BEGIN combining: 05029 // The image onto the background 05030 $gifCreator->combineExec($tempScale['m_bgImg'], $tempScale['m_bottomImg'], $tempScale['m_bottomImg_mask'], $tempScale['m_bgImg']); 05031 } 05032 // The image onto the background 05033 $gifCreator->combineExec($tempScale['m_bgImg'], $tempFileInfo[3], $tempScale['m_mask'], $dest); 05034 // Unlink the temp-images... 05035 foreach ($tempScale as $file) { 05036 if (@is_file($file)) { 05037 unlink($file); 05038 } 05039 } 05040 } 05041 } 05042 } 05043 // Finish off 05044 if (($fileArray['reduceColors'] || ($imgExt == 'png' && !$gifCreator->png_truecolor)) && is_file($dest)) { 05045 $reduced = $gifCreator->IMreduceColors($dest, t3lib_div::intInRange($fileArray['reduceColors'], 256, $gifCreator->truecolorColors, 256)); 05046 if (is_file($reduced)) { 05047 unlink($dest); 05048 rename($reduced, $dest); 05049 } 05050 } 05051 $GLOBALS['TSFE']->tmpl->fileCache[$hash] = $gifCreator->getImageDimensions($dest); 05052 } else { // Normal situation: 05053 $fileArray['params'] = $this->modifyImageMagickStripProfileParameters($fileArray['params'], $fileArray); 05054 $GLOBALS['TSFE']->tmpl->fileCache[$hash] = $gifCreator->imageMagickConvert($theImage, $fileArray['ext'], $fileArray['width'], $fileArray['height'], $fileArray['params'], $fileArray['frame'], $options); 05055 if (($fileArray['reduceColors'] || ($imgExt == 'png' && !$gifCreator->png_truecolor)) && is_file($GLOBALS['TSFE']->tmpl->fileCache[$hash][3])) { 05056 $reduced = $gifCreator->IMreduceColors($GLOBALS['TSFE']->tmpl->fileCache[$hash][3], t3lib_div::intInRange($fileArray['reduceColors'], 256, $gifCreator->truecolorColors, 256)); 05057 if (is_file($reduced)) { 05058 unlink($GLOBALS['TSFE']->tmpl->fileCache[$hash][3]); 05059 rename($reduced, $GLOBALS['TSFE']->tmpl->fileCache[$hash][3]); 05060 } 05061 } 05062 } 05063 $GLOBALS['TSFE']->tmpl->fileCache[$hash]['origFile'] = $theImage; 05064 $GLOBALS['TSFE']->tmpl->fileCache[$hash]['origFile_mtime'] = @filemtime($theImage); // This is needed by tslib_gifbuilder, ln 100ff in order for the setup-array to create a unique filename hash. 05065 $GLOBALS['TSFE']->tmpl->fileCache[$hash]['fileCacheHash'] = $hash; 05066 } 05067 $imageResource = $GLOBALS['TSFE']->tmpl->fileCache[$hash]; 05068 } 05069 05070 break; 05071 } 05072 } 05073 $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file); 05074 // If image was processed by GIFBUILDER: 05075 // ($imageResource indicates that it was processed the regular way) 05076 if (!isset($imageResource) && $theImage) { 05077 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder'); 05078 /* @var $gifCreator tslib_gifbuilder */ 05079 $gifCreator->init(); 05080 $info = $gifCreator->imageMagickConvert($theImage, 'WEB', '', '', '', '', ''); 05081 $info['origFile'] = $theImage; 05082 $info['origFile_mtime'] = @filemtime($theImage); // This is needed by tslib_gifbuilder, ln 100ff in order for the setup-array to create a unique filename hash. 05083 $imageResource = $info; 05084 } 05085 05086 // Hook 'getImgResource': Post-processing of image resources 05087 if (isset($imageResource)) { 05088 foreach ($this->getGetImgResourceHookObjects() as $hookObject) { 05089 $imageResource = $hookObject->getImgResourcePostProcess($file, (array) $fileArray, $imageResource, $this); 05090 } 05091 } 05092 05093 return $imageResource; 05094 } 05095 05096 /** 05097 * Modifies the parameters for ImageMagick for stripping of profile information. 05098 * 05099 * @param string $parameters: The parameters to be modified (if required) 05100 * @param array $configuration: The TypoScript configuration of [IMAGE].file 05101 * @param string The modified parameters 05102 */ 05103 protected function modifyImageMagickStripProfileParameters($parameters, array $configuration) { 05104 // Strips profile information of image to save some space: 05105 if (isset($configuration['stripProfile'])) { 05106 if ($configuration['stripProfile']) { 05107 $parameters = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_stripProfileCommand'] . $parameters; 05108 } else { 05109 $parameters .= '###SkipStripProfile###'; 05110 } 05111 } 05112 return $parameters; 05113 } 05114 05115 05116 05117 /*********************************************** 05118 * 05119 * Data retrieval etc. 05120 * 05121 ***********************************************/ 05122 05123 05124 /** 05125 * Returns the value for the field from $this->data. If "//" is found in the $field value that token will split the field values apart and the first field having a non-blank value will be returned. 05126 * 05127 * @param string The fieldname, eg. "title" or "navtitle // title" (in the latter case the value of $this->data[navtitle] is returned if not blank, otherwise $this->data[title] will be) 05128 * @return string 05129 */ 05130 function getFieldVal($field) { 05131 if (!strstr($field, '//')) { 05132 return $this->data[trim($field)]; 05133 } else { 05134 $sections = t3lib_div::trimExplode('//', $field, 1); 05135 foreach ($sections as $k) { 05136 if (strcmp($this->data[$k], '')) 05137 return $this->data[$k]; 05138 } 05139 } 05140 } 05141 05142 /** 05143 * Implements the TypoScript data type "getText". This takes a string with parameters and based on those a value from somewhere in the system is returned. 05144 * 05145 * @param string The parameter string, eg. "field : title" or "field : navtitle // field : title" (in the latter case and example of how the value is FIRST splitted by "//" is shown) 05146 * @param mixed Alternative field array; If you set this to an array this variable will be used to look up values for the "field" key. Otherwise the current page record in $GLOBALS['TSFE']->page is used. 05147 * @return string The value fetched 05148 * @see getFieldVal() 05149 */ 05150 function getData($string, $fieldArray) { 05151 global $TYPO3_CONF_VARS; 05152 05153 if (!is_array($fieldArray)) { 05154 $fieldArray = $GLOBALS['TSFE']->page; 05155 } 05156 $retVal = ''; 05157 $sections = explode('//', $string); 05158 05159 while (!$retVal and list ($secKey, $secVal) = each($sections)) { 05160 $parts = explode(':', $secVal, 2); 05161 $key = trim($parts[1]); 05162 if ((string) $key != '') { 05163 $type = strtolower(trim($parts[0])); 05164 switch ($type) { 05165 case 'gpvar' : 05166 t3lib_div::deprecationLog('Using gpvar in TypoScript getText is deprecated since TYPO3 4.3 - Use gp instead of gpvar.'); 05167 // Fall Through 05168 case 'gp' : 05169 // Merge GET and POST and get $key out of the merged array 05170 $retVal = $this->getGlobal($key, t3lib_div::array_merge_recursive_overrule(t3lib_div::_GET(), t3lib_div::_POST())); 05171 break; 05172 case 'tsfe' : 05173 $retVal = $this->getGlobal('TSFE|' . $key); 05174 break; 05175 case 'getenv' : 05176 $retVal = getenv($key); 05177 break; 05178 case 'getindpenv' : 05179 $retVal = t3lib_div::getIndpEnv($key); 05180 break; 05181 case 'field' : 05182 $retVal = $fieldArray[$key]; 05183 break; 05184 case 'parameters' : 05185 $retVal = $this->parameters[$key]; 05186 break; 05187 case 'register' : 05188 $retVal = $GLOBALS['TSFE']->register[$key]; 05189 break; 05190 case 'global' : 05191 $retVal = $this->getGlobal($key); 05192 break; 05193 case 'leveltitle' : 05194 $nkey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine); 05195 $retVal = $this->rootLineValue($nkey, 'title', stristr($key, 'slide')); 05196 break; 05197 case 'levelmedia' : 05198 $nkey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine); 05199 $retVal = $this->rootLineValue($nkey, 'media', stristr($key, 'slide')); 05200 break; 05201 case 'leveluid' : 05202 $nkey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine); 05203 $retVal = $this->rootLineValue($nkey, 'uid', stristr($key, 'slide')); 05204 break; 05205 case 'levelfield' : 05206 $keyP = t3lib_div::trimExplode(',', $key); 05207 $nkey = $this->getKey($keyP[0], $GLOBALS['TSFE']->tmpl->rootLine); 05208 $retVal = $this->rootLineValue($nkey, $keyP[1], strtolower($keyP[2]) == 'slide'); 05209 break; 05210 case 'fullrootline' : 05211 $keyP = t3lib_div::trimExplode(',', $key); 05212 $fullKey = intval($keyP[0]) - count($GLOBALS['TSFE']->tmpl->rootLine) + count($GLOBALS['TSFE']->rootLine); 05213 if ($fullKey >= 0) { 05214 $retVal = $this->rootLineValue($fullKey, $keyP[1], stristr($keyP[2], 'slide'), $GLOBALS['TSFE']->rootLine); 05215 } 05216 break; 05217 case 'date' : 05218 if (!$key) { 05219 $key = 'd/m Y'; 05220 } 05221 $retVal = date($key, $GLOBALS['EXEC_TIME']); 05222 break; 05223 case 'page' : 05224 $retVal = $GLOBALS['TSFE']->page[$key]; 05225 break; 05226 case 'current' : 05227 $retVal = $this->data[$this->currentValKey]; 05228 break; 05229 case 'level' : 05230 $retVal = count($GLOBALS['TSFE']->tmpl->rootLine) - 1; 05231 break; 05232 case 'db' : 05233 $selectParts = t3lib_div::trimExplode(':', $key); 05234 $db_rec = $GLOBALS['TSFE']->sys_page->getRawRecord($selectParts[0], $selectParts[1]); 05235 if (is_array($db_rec) && $selectParts[2]) { 05236 $retVal = $db_rec[$selectParts[2]]; 05237 } 05238 break; 05239 case 'lll' : 05240 $retVal = $GLOBALS['TSFE']->sL('LLL:' . $key); 05241 break; 05242 case 'path' : 05243 $retVal = $GLOBALS['TSFE']->tmpl->getFileName($key); 05244 break; 05245 case 'cobj' : 05246 switch ((string) $key) { 05247 case 'parentRecordNumber' : 05248 $retVal = $this->parentRecordNumber; 05249 break; 05250 } 05251 break; 05252 case 'debug' : 05253 switch ((string) $key) { 05254 case 'rootLine' : 05255 $retVal = t3lib_utility_Debug::viewArray($GLOBALS['TSFE']->tmpl->rootLine); 05256 break; 05257 case 'fullRootLine' : 05258 $retVal = t3lib_utility_Debug::viewArray($GLOBALS['TSFE']->rootLine); 05259 break; 05260 case 'data' : 05261 $retVal = t3lib_utility_Debug::viewArray($this->data); 05262 break; 05263 } 05264 break; 05265 } 05266 } 05267 05268 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'])) { 05269 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'] as $classData) { 05270 $hookObject = t3lib_div::getUserObj($classData); 05271 05272 if (!($hookObject instanceof tslib_content_getDataHook)) { 05273 throw new UnexpectedValueException('$hookObject must implement interface tslib_content_getDataHook', 1195044480); 05274 } 05275 05276 $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $this); 05277 } 05278 } 05279 } 05280 05281 return $retVal; 05282 } 05283 05284 /** 05285 * Returns a value from the current rootline (site) from $GLOBALS['TSFE']->tmpl->rootLine; 05286 * 05287 * @param string Which level in the root line 05288 * @param string The field in the rootline record to return (a field from the pages table) 05289 * @param boolean If set, then we will traverse through the rootline from outer level towards the root level until the value found is TRUE 05290 * @param mixed If you supply an array for this it will be used as an alternative root line array 05291 * @return string The value from the field of the rootline. 05292 * @access private 05293 * @see getData() 05294 */ 05295 function rootLineValue($key, $field, $slideBack = 0, $altRootLine = '') { 05296 $rootLine = is_array($altRootLine) ? $altRootLine : $GLOBALS['TSFE']->tmpl->rootLine; 05297 if (!$slideBack) { 05298 return $rootLine[$key][$field]; 05299 } else { 05300 for ($a = $key; $a >= 0; $a--) { 05301 $val = $rootLine[$a][$field]; 05302 if ($val) { 05303 return $val; 05304 } 05305 } 05306 } 05307 } 05308 05309 /** 05310 * Return global variable where the input string $var defines array keys separated by "|" 05311 * Example: $var = "HTTP_SERVER_VARS | something" will return the value $GLOBALS['HTTP_SERVER_VARS']['something'] value 05312 * 05313 * @param string Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back. 05314 * @param array Alternative array than $GLOBAL to get variables from. 05315 * @return mixed Whatever value. If none, then blank string. 05316 * @see getData() 05317 */ 05318 function getGlobal($keyString, $source = NULL) { 05319 $keys = explode('|', $keyString); 05320 $numberOfLevels = count($keys); 05321 $rootKey = trim($keys[0]); 05322 $value = isset($source) ? $source[$rootKey] : $GLOBALS[$rootKey]; 05323 05324 for ($i = 1; $i < $numberOfLevels && isset($value); $i++) { 05325 $currentKey = trim($keys[$i]); 05326 if (is_object($value)) { 05327 $value = $value->$currentKey; 05328 } elseif (is_array($value)) { 05329 $value = $value[$currentKey]; 05330 } else { 05331 $value = ''; 05332 break; 05333 } 05334 } 05335 05336 if (!is_scalar($value)) { 05337 $value = ''; 05338 } 05339 return $value; 05340 } 05341 05342 /** 05343 * Processing of key values pointing to entries in $arr; Here negative values are converted to positive keys pointer to an entry in the array but from behind (based on the negative value). 05344 * Example: entrylevel = -1 means that entryLevel ends up pointing at the outermost-level, -2 means the level before the outermost... 05345 * 05346 * @param integer The integer to transform 05347 * @param array array in which the key should be found. 05348 * @return integer The processed integer key value. 05349 * @access private 05350 * @see getData() 05351 */ 05352 function getKey($key, $arr) { 05353 $key = intval($key); 05354 if (is_array($arr)) { 05355 if ($key < 0) { 05356 $key = count($arr) + $key; 05357 } 05358 if ($key < 0) { 05359 $key = 0; 05360 } 05361 } 05362 return $key; 05363 } 05364 05365 05366 /** 05367 * Looks up the incoming value in the defined TCA configuration 05368 * Works only with TCA-type 'select' and options defined in 'items' 05369 * 05370 * @param mixed Comma-separated list of values to look up 05371 * @param array TS-configuration array, see TSref for details 05372 * @return string String of translated values, seperated by $delimiter. If no matches were found, the input value is simply returned. 05373 * @todo It would be nice it this function basically looked up any type of value, db-relations etc. 05374 */ 05375 function TCAlookup($inputValue, $conf) { 05376 global $TCA; 05377 05378 $table = $conf['table']; 05379 $field = $conf['field']; 05380 $delimiter = $conf['delimiter'] ? $conf['delimiter'] : ' ,'; 05381 05382 $GLOBALS['TSFE']->includeTCA(); 05383 t3lib_div::loadTCA($table); 05384 05385 if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$field]) && is_array($TCA[$table]['columns'][$field]['config']['items'])) { 05386 $values = t3lib_div::trimExplode(',', $inputValue); 05387 $output = array(); 05388 foreach ($values as $value) { 05389 // Traverse the items-array... 05390 foreach ($TCA[$table]['columns'][$field]['config']['items'] as $item) { 05391 // ... and return the first found label where the value was equal to $key 05392 if (!strcmp($item[1], trim($value))) { 05393 $output[] = $GLOBALS['TSFE']->sL($item[0]); 05394 } 05395 } 05396 } 05397 $returnValue = implode($delimiter, $output); 05398 } else { 05399 $returnValue = $inputValue; 05400 } 05401 return $returnValue; 05402 } 05403 05404 05405 05406 /*********************************************** 05407 * 05408 * Link functions (typolink) 05409 * 05410 ***********************************************/ 05411 05412 05413 /** 05414 * Implements the "typolink" property of stdWrap (and others) 05415 * Basically the input string, $linktext, is (typically) wrapped in a <a>-tag linking to some page, email address, file or URL based on a parameter defined by the configuration array $conf. 05416 * This function is best used from internal functions as is. There are some API functions defined after this function which is more suited for general usage in external applications. 05417 * Generally the concept "typolink" should be used in your own applications as an API for making links to pages with parameters and more. The reason for this is that you will then automatically make links compatible with all the centralized functions for URL simulation and manipulation of parameters into hashes and more. 05418 * For many more details on the parameters and how they are intepreted, please see the link to TSref below. 05419 * 05420 * @param string The string (text) to link 05421 * @param array TypoScript configuration (see link below) 05422 * @return string A link-wrapped string. 05423 * @see stdWrap(), tslib_pibase::pi_linkTP() 05424 */ 05425 function typoLink($linktxt, $conf) { 05426 $LD = array(); 05427 $finalTagParts = array(); 05428 $finalTagParts['aTagParams'] = $this->getATagParams($conf); 05429 05430 $link_param = isset($conf['parameter.']) 05431 ? trim($this->stdWrap($conf['parameter'], $conf['parameter.'])) 05432 : trim($conf['parameter']); 05433 05434 $sectionMark = isset($conf['section.']) 05435 ? trim($this->stdWrap($conf['section'], $conf['section.'])) 05436 : trim($conf['section']); 05437 $sectionMark = $sectionMark ? (t3lib_div::testInt($sectionMark) ? '#c' : '#') . $sectionMark : ''; 05438 $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type; 05439 $this->lastTypoLinkUrl = ''; 05440 $this->lastTypoLinkTarget = ''; 05441 if ($link_param) { 05442 $enableLinksAcrossDomains = $GLOBALS['TSFE']->config['config']['typolinkEnableLinksAcrossDomains']; 05443 $link_paramA = t3lib_div::unQuoteFilenames($link_param, TRUE); 05444 05445 // Check for link-handler keyword: 05446 list ($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_paramA[0]), 2); 05447 if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword] && strcmp($linkHandlerValue, '')) { 05448 $linkHandlerObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]); 05449 05450 if (method_exists($linkHandlerObj, 'main')) { 05451 return $linkHandlerObj->main($linktxt, $conf, $linkHandlerKeyword, $linkHandlerValue, $link_param, $this); 05452 } 05453 } 05454 05455 $link_param = trim($link_paramA[0]); // Link parameter value 05456 $linkClass = trim($link_paramA[2]); // Link class 05457 if ($linkClass == '-') 05458 $linkClass = ''; // The '-' character means 'no class'. Necessary in order to specify a title as fourth parameter without setting the target or class! 05459 $forceTarget = trim($link_paramA[1]); // Target value 05460 if ($forceTarget == '-') { 05461 $forceTarget = ''; // The '-' character means 'no target'. Necessary in order to specify a class as third parameter without setting the target! 05462 } 05463 $forceTitle = trim($link_paramA[3]); // Title value 05464 if ($forceTitle == '-') { 05465 $forceTitle = ''; // The '-' character means 'no title'. Necessary in order to specify further parameters without setting the title! 05466 } 05467 if (isset($link_paramA[4]) && strlen(trim($link_paramA[4])) > 0) { 05468 $forceParams = trim($link_paramA[4]); // params value 05469 $conf['additionalParams'] .= $forceParams[0] == '&' ? $forceParams : '&' . $forceParams; 05470 } 05471 05472 // Check, if the target is coded as a JS open window link: 05473 $JSwindowParts = array(); 05474 $JSwindowParams = ''; 05475 $onClick = ''; 05476 if ($forceTarget && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $forceTarget, $JSwindowParts)) { 05477 // Take all pre-configured and inserted parameters and compile parameter list, including width+height: 05478 $JSwindow_tempParamsArr = t3lib_div::trimExplode(',', strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]), TRUE); 05479 $JSwindow_paramsArr = array(); 05480 foreach ($JSwindow_tempParamsArr as $JSv) { 05481 list ($JSp, $JSv) = explode('=', $JSv); 05482 $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv; 05483 } 05484 // Add width/height: 05485 $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1]; 05486 $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2]; 05487 // Imploding into string: 05488 $JSwindowParams = implode(',', $JSwindow_paramsArr); 05489 $forceTarget = ''; // Resetting the target since we will use onClick. 05490 } 05491 05492 // Internal target: 05493 $target = isset($conf['target']) ? $conf['target'] : $GLOBALS['TSFE']->intTarget; 05494 if ($conf['target.']) { 05495 $target = $this->stdWrap($target, $conf['target.']); 05496 } 05497 05498 // Title tag 05499 $title = $conf['title']; 05500 if ($conf['title.']) { 05501 $title = $this->stdWrap($title, $conf['title.']); 05502 } 05503 05504 // Parse URL: 05505 $pU = parse_url($link_param); 05506 05507 // Detecting kind of link: 05508 if (strstr($link_param, '@') && (!$pU['scheme'] || $pU['scheme'] == 'mailto')) { // If it's a mail address: 05509 $link_param = preg_replace('/^mailto:/i', '', $link_param); 05510 list ($this->lastTypoLinkUrl, $linktxt) = $this->getMailTo($link_param, $linktxt, $initP); 05511 $finalTagParts['url'] = $this->lastTypoLinkUrl; 05512 $finalTagParts['TYPE'] = 'mailto'; 05513 } else { 05514 $isLocalFile = 0; 05515 $fileChar = intval(strpos($link_param, '/')); 05516 $urlChar = intval(strpos($link_param, '.')); 05517 05518 // Firsts, test if $link_param is numeric and page with such id exists. If yes, do not attempt to link to file 05519 if (!t3lib_div::testInt($link_param) || count($GLOBALS['TSFE']->sys_page->getPage_noCheck($link_param)) == 0) { 05520 // Detects if a file is found in site-root (or is a 'virtual' simulateStaticDocument file!) and if so it will be treated like a normal file. 05521 list ($rootFileDat) = explode('?', rawurldecode($link_param)); 05522 $containsSlash = strstr($rootFileDat, '/'); 05523 $rFD_fI = pathinfo($rootFileDat); 05524 if (trim($rootFileDat) && !$containsSlash && (@is_file(PATH_site . $rootFileDat) || t3lib_div::inList('php,html,htm', strtolower($rFD_fI['extension'])))) { 05525 $isLocalFile = 1; 05526 } elseif ($containsSlash) { 05527 $isLocalFile = 2; // Adding this so realurl directories are linked right (non-existing). 05528 } 05529 } 05530 05531 if ($pU['scheme'] || ($isLocalFile != 1 && $urlChar && (!$containsSlash || $urlChar < $fileChar))) { // url (external): If doubleSlash or if a '.' comes before a '/'. 05532 $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget; 05533 if ($conf['extTarget.']) { 05534 $target = $this->stdWrap($target, $conf['extTarget.']); 05535 } 05536 if ($forceTarget) { 05537 $target = $forceTarget; 05538 } 05539 if ($linktxt == '') 05540 $linktxt = $link_param; 05541 if (!$pU['scheme']) { 05542 $scheme = 'http://'; 05543 } else { 05544 $scheme = ''; 05545 } 05546 if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) { 05547 $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix . 05548 $GLOBALS['TSFE']->config['mainScript'] . $initP . 05549 '&jumpurl=' . rawurlencode($scheme . $link_param) . 05550 $GLOBALS['TSFE']->getMethodUrlIdToken; 05551 } else { 05552 $this->lastTypoLinkUrl = $scheme . $link_param; 05553 } 05554 $this->lastTypoLinkTarget = $target; 05555 $finalTagParts['url'] = $this->lastTypoLinkUrl; 05556 $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : ''; 05557 $finalTagParts['TYPE'] = 'url'; 05558 $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']); 05559 } elseif ($containsSlash || $isLocalFile) { // file (internal) 05560 $splitLinkParam = explode('?', $link_param); 05561 if (file_exists(rawurldecode($splitLinkParam[0])) || $isLocalFile) { 05562 if ($linktxt == '') 05563 $linktxt = rawurldecode($link_param); 05564 if ($GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $conf['jumpurl']) { 05565 $theFileEnc = str_replace('%2F', '/', rawurlencode(rawurldecode($link_param))); 05566 $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix . 05567 $GLOBALS['TSFE']->config['mainScript'] . $initP . 05568 '&jumpurl=' . rawurlencode($link_param) . 05569 ($conf['jumpurl.']['secure'] ? $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) : '') . 05570 $GLOBALS['TSFE']->getMethodUrlIdToken; 05571 } else { 05572 $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix . $link_param; 05573 } 05574 $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf); 05575 $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $GLOBALS['TSFE']->fileTarget; 05576 if ($conf['fileTarget.']) { 05577 $target = $this->stdWrap($target, $conf['fileTarget.']); 05578 } 05579 if ($forceTarget) { 05580 $target = $forceTarget; 05581 } 05582 $this->lastTypoLinkTarget = $target; 05583 05584 $finalTagParts['url'] = $this->lastTypoLinkUrl; 05585 $finalTagParts['targetParams'] = $target ? ' target="' . $target . '"' : ''; 05586 $finalTagParts['TYPE'] = 'file'; 05587 $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']); 05588 } else { 05589 $GLOBALS['TT']->setTSlogMessage( 05590 "typolink(): File '" . $splitLinkParam[0] . "' did not exist, so '" . $linktxt . "' was not linked.", 1 05591 ); 05592 return $linktxt; 05593 } 05594 } else { // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to definition in $TCA!) 05595 if ($conf['no_cache.']) { 05596 $conf['no_cache'] = $this->stdWrap($conf['no_cache'], $conf['no_cache.']); 05597 } 05598 // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/parameters triplet 05599 $pairParts = t3lib_div::trimExplode(',', $link_param, TRUE); 05600 $link_param = $pairParts[0]; 05601 $link_params_parts = explode('#', $link_param); 05602 $link_param = trim($link_params_parts[0]); // Link-data del 05603 if (!strcmp($link_param, '')) { 05604 $link_param = $GLOBALS['TSFE']->id; 05605 } // If no id or alias is given 05606 if ($link_params_parts[1] && !$sectionMark) { 05607 $sectionMark = trim($link_params_parts[1]); 05608 $sectionMark = (t3lib_div::testInt($sectionMark) ? '#c' : '#') . $sectionMark; 05609 } 05610 05611 if (count($pairParts) > 1) { 05612 $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0; // Overruling 'type' 05613 $conf['additionalParams'] .= isset($pairParts[2]) ? $pairParts[2] : ''; 05614 } 05615 // Checking if the id-parameter is an alias. 05616 if (!t3lib_div::testInt($link_param)) { 05617 $link_param = $GLOBALS['TSFE']->sys_page->getPageIdFromAlias($link_param); 05618 } 05619 05620 // Link to page even if access is missing? 05621 if (strlen($conf['linkAccessRestrictedPages'])) { 05622 $disableGroupAccessCheck = ($conf['linkAccessRestrictedPages'] ? TRUE : FALSE); 05623 } else { 05624 $disableGroupAccessCheck = ($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] ? TRUE : FALSE); 05625 } 05626 05627 // Looking up the page record to verify its existence: 05628 $page = $GLOBALS['TSFE']->sys_page->getPage($link_param, $disableGroupAccessCheck); 05629 05630 if (count($page)) { 05631 // MointPoints, look for closest MPvar: 05632 $MPvarAcc = array(); 05633 if (!$GLOBALS['TSFE']->config['config']['MP_disableTypolinkClosestMPvalue']) { 05634 $temp_MP = $this->getClosestMPvalueForPage($page['uid'], TRUE); 05635 if ($temp_MP) 05636 $MPvarAcc['closest'] = $temp_MP; 05637 } 05638 // Look for overlay Mount Point: 05639 $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($page['uid'], $page); 05640 if (is_array($mount_info) && $mount_info['overlay']) { 05641 $page = $GLOBALS['TSFE']->sys_page->getPage($mount_info['mount_pid'], $disableGroupAccessCheck); 05642 if (!count($page)) { 05643 $GLOBALS['TT']->setTSlogMessage( 05644 "typolink(): Mount point '" . $mount_info['mount_pid'] . "' was not available, so '" . 05645 $linktxt . "' was not linked.", 1 05646 ); 05647 return $linktxt; 05648 } 05649 $MPvarAcc['re-map'] = $mount_info['MPvar']; 05650 } 05651 05652 // Setting title if blank value to link: 05653 if ($linktxt == '') 05654 $linktxt = $page['title']; 05655 05656 // Query Params: 05657 $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : ''; 05658 $addQueryParams .= isset($conf['additionalParams.']) 05659 ? trim($this->stdWrap($conf['additionalParams'], $conf['additionalParams.'])) 05660 : trim($conf['additionalParams']); 05661 if ($addQueryParams == '&' || substr($addQueryParams, 0, 1) != '&') { 05662 $addQueryParams = ''; 05663 } 05664 if ($conf['useCacheHash']) { 05665 // Mind the order below! See http://bugs.typo3.org/view.php?id=5117 05666 $params = $GLOBALS['TSFE']->linkVars . $addQueryParams; 05667 if (trim($params, '& ') != '') { 05668 $addQueryParams .= '&cHash=' . t3lib_div::generateCHash($params); 05669 } 05670 unset($params); 05671 } 05672 05673 $targetDomain = ''; 05674 $currentDomain = t3lib_div::getIndpEnv('HTTP_HOST'); 05675 // Mount pages are always local and never link to another domain 05676 if (count($MPvarAcc)) { 05677 // Add "&MP" var: 05678 $addQueryParams .= '&MP=' . rawurlencode(implode(',', $MPvarAcc)); 05679 } elseif (strpos($addQueryParams, '&MP=') === FALSE && $GLOBALS['TSFE']->config['config']['typolinkCheckRootline']) { 05680 05681 // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from 05682 // menu. Mount points always work in the content of the current domain and we must not change 05683 // domain if MP variables exist. 05684 05685 05686 // If we link across domains and page is free type shortcut, we must resolve the shortcut first! 05687 // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because 05688 // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked 05689 if ($enableLinksAcrossDomains && $page['doktype'] == t3lib_pageSelect::DOKTYPE_SHORTCUT && $page['shortcut_mode'] == t3lib_pageSelect::SHORTCUT_MODE_NONE) { 05690 $page2 = $page; // Save in case of broken destination or endless loop 05691 $maxLoopCount = 20; // Same as in RealURL, seems enough 05692 while ($maxLoopCount && is_array($page) && $page['doktype'] == t3lib_pageSelect::DOKTYPE_SHORTCUT && $page['shortcut_mode'] == t3lib_pageSelect::SHORTCUT_MODE_NONE) { 05693 $page = $GLOBALS['TSFE']->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck); 05694 $maxLoopCount--; 05695 } 05696 if (count($page) == 0 || $maxLoopCount == 0) { 05697 // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop) 05698 $page = $page2; 05699 } 05700 } 05701 05702 // Find all domain records in the rootline of the target page 05703 $targetPageRootline = $GLOBALS['TSFE']->sys_page->getRootLine($page['uid']); 05704 $foundDomains = array(); 05705 $firstFoundDomains = array(); 05706 $firstFoundForcedDomains = array(); 05707 $targetPageRootlinePids = array(); 05708 foreach ($targetPageRootline as $data) { 05709 $targetPageRootlinePids[] = intval($data['uid']); 05710 } 05711 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 05712 'pid, domainName, forced', 05713 'sys_domain', 05714 'pid IN (' . implode(',', $targetPageRootlinePids) . ') ' . ' AND redirectTo=\'\' ' . $this->enableFields('sys_domain'), 05715 '', 05716 'sorting ASC' 05717 ); 05718 // TODO maybe it makes sense to hold all sys_domain records in a cache to save additional DB querys on each typolink 05719 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 05720 $foundDomains[] = preg_replace('/\/$/', '', $row['domainName']); 05721 if (!isset($firstFoundDomains[$row['pid']])) { 05722 $firstFoundDomains[$row['pid']] = preg_replace('/\/$/', '', $row['domainName']); 05723 } 05724 if ($row['forced'] && !isset($firstFoundForcedDomains[$row['pid']])) { 05725 $firstFoundForcedDomains[$row['pid']] = preg_replace('/\/$/', '', $row['domainName']); 05726 } 05727 } 05728 $GLOBALS['TYPO3_DB']->sql_free_result($res); 05729 05730 // Set targetDomain to first found domain record if the target page cannot be reached within the current domain 05731 if (count($foundDomains) > 0 && (!in_array($currentDomain, $foundDomains) || count($firstFoundForcedDomains) > 0)) { 05732 foreach ($targetPageRootlinePids as $pid) { 05733 // Always use the 'forced' domain if we found one 05734 if (isset($firstFoundForcedDomains[$pid])) { 05735 $targetDomain = $firstFoundForcedDomains[$pid]; 05736 break; 05737 } 05738 // Use the first found domain record 05739 if ($targetDomain === '' && isset($firstFoundDomains[$pid])) { 05740 $targetDomain = $firstFoundDomains[$pid]; 05741 } 05742 } 05743 // Do not prepend the domain if its the current hostname 05744 if ($targetDomain === $currentDomain) { 05745 $targetDomain = ''; 05746 } 05747 } 05748 } 05749 05750 $absoluteUrlScheme = 'http'; 05751 // URL shall be absolute: 05752 if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl'] || $page['url_scheme'] > 0) { 05753 // Override scheme: 05754 if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) { 05755 $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme']; 05756 } elseif ($page['url_scheme'] > 0) { 05757 $absoluteUrlScheme = ((int) $page['url_scheme'] === t3lib_utility_http::SCHEME_HTTP) ? 'http' : 'https'; 05758 } 05759 05760 // If no domain records are defined, use current domain: 05761 if ($targetDomain === '' && $conf['forceAbsoluteUrl'] || 05762 $absoluteUrlScheme !== parse_url(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'), PHP_URL_SCHEME)) { 05763 $targetDomain = $currentDomain; 05764 } 05765 } 05766 05767 // If target page has a different domain and the current domain's linking scheme (e.g. simulateStaticDocuments/RealURL/...) should not be used 05768 if (strlen($targetDomain) && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) { 05769 $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget; 05770 if ($conf['extTarget.']) { 05771 $target = $this->stdWrap($target, $conf['extTarget.']); 05772 } 05773 if ($forceTarget) { 05774 $target = $forceTarget; 05775 } 05776 $LD['target'] = $target; 05777 $this->lastTypoLinkUrl = $this->URLqMark( 05778 $absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'], $addQueryParams 05779 ) . $sectionMark; 05780 } else { // Internal link or current domain's linking scheme should be used 05781 if ($forceTarget) { 05782 $target = $forceTarget; 05783 } 05784 $LD = $GLOBALS['TSFE']->tmpl->linkData( 05785 $page, 05786 $target, 05787 $conf['no_cache'], 05788 '', 05789 '', 05790 $addQueryParams, 05791 $theTypeP, 05792 $targetDomain 05793 ); 05794 if (strlen($targetDomain)) { 05795 // We will add domain only if URL does not have it already. 05796 05797 05798 if ($enableLinksAcrossDomains) { 05799 // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only 05800 // to the current web site. If we have domain here it means we link across 05801 // domains. absRefPrefix can contain domain name, which will screw up 05802 // the link to the external domain. 05803 $prefixLength = strlen($GLOBALS['TSFE']->config['config']['absRefPrefix']); 05804 if (substr($LD['totalURL'], 0, $prefixLength) == $GLOBALS['TSFE']->config['config']['absRefPrefix']) { 05805 $LD['totalURL'] = substr($LD['totalURL'], $prefixLength); 05806 } 05807 } 05808 $urlParts = parse_url($LD['totalURL']); 05809 if ($urlParts['host'] == '') { 05810 $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . 05811 ($LD['totalURL']{0} == '/' ? '' : '/') . $LD['totalURL']; 05812 } 05813 } 05814 $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'], '') . $sectionMark; 05815 } 05816 05817 $this->lastTypoLinkTarget = $LD['target']; 05818 $targetPart = $LD['target'] ? ' target="' . $LD['target'] . '"' : ''; 05819 05820 // If sectionMark is set, there is no baseURL AND the current page is the page the link is to, check if there are any additional parameters or addQueryString parameters and if not, drop the url. 05821 if ($sectionMark && !$GLOBALS['TSFE']->config['config']['baseURL'] 05822 && $page['uid'] == $GLOBALS['TSFE']->id && !trim($addQueryParams) 05823 && !($conf['addQueryString'] && $conf['addQueryString.'])) { 05824 05825 list (, $URLparams) = explode('?', $this->lastTypoLinkUrl); 05826 list ($URLparams) = explode('#', $URLparams); 05827 parse_str($URLparams . $LD['orig_type'], $URLparamsArray); 05828 if (intval($URLparamsArray['type']) == $GLOBALS['TSFE']->type) { // type nums must match as well as page ids 05829 unset($URLparamsArray['id']); 05830 unset($URLparamsArray['type']); 05831 if (!count($URLparamsArray)) { // If there are no parameters left.... set the new url. 05832 $this->lastTypoLinkUrl = $sectionMark; 05833 } 05834 } 05835 } 05836 05837 // If link is to a access restricted page which should be redirected, then find new URL: 05838 if ($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] 05839 && $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] !== 'NONE' 05840 && !$GLOBALS['TSFE']->checkPageGroupAccess($page)) { 05841 05842 $thePage = $GLOBALS['TSFE']->sys_page->getPage($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages']); 05843 05844 $addParams = $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages_addParams']; 05845 $addParams = str_replace('###RETURN_URL###', rawurlencode($this->lastTypoLinkUrl), $addParams); 05846 $addParams = str_replace('###PAGE_ID###', $page['uid'], $addParams); 05847 $this->lastTypoLinkUrl = $this->getTypoLink_URL( 05848 $thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''), 05849 $addParams, 05850 $target 05851 ); 05852 $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf); 05853 $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl; 05854 $LD = $this->lastTypoLinkLD; 05855 } 05856 05857 // Rendering the tag. 05858 $finalTagParts['url'] = $this->lastTypoLinkUrl; 05859 $finalTagParts['targetParams'] = $targetPart; 05860 $finalTagParts['TYPE'] = 'page'; 05861 } else { 05862 $GLOBALS['TT']->setTSlogMessage( 05863 "typolink(): Page id '" . $link_param . "' was not found, so '" . $linktxt . "' was not linked.", 1 05864 ); 05865 return $linktxt; 05866 } 05867 } 05868 } 05869 05870 $this->lastTypoLinkLD = $LD; 05871 05872 if ($forceTitle) { 05873 $title = $forceTitle; 05874 } 05875 05876 if ($JSwindowParams) { 05877 05878 // Create TARGET-attribute only if the right doctype is used 05879 if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) { 05880 $target = ' target="FEopenLink"'; 05881 } else { 05882 $target = ''; 05883 } 05884 05885 $onClick = "vHWin=window.open('" . $GLOBALS['TSFE']->baseUrlWrap($finalTagParts['url']) . 05886 "','FEopenLink','" . $JSwindowParams . "');vHWin.focus();return false;"; 05887 $res = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . 05888 $target . ' onclick="' . htmlspecialchars($onClick) . '"' . 05889 ($title ? ' title="' . $title . '"' : '') . 05890 ($linkClass ? ' class="' . $linkClass . '"' : '') . 05891 $finalTagParts['aTagParams'] . '>'; 05892 } else { 05893 if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' && $finalTagParts['TYPE'] === 'mailto') { 05894 $res = '<a href="' . $finalTagParts['url'] . '"' . 05895 ($title ? ' title="' . $title . '"' : '') . 05896 $finalTagParts['targetParams'] . 05897 ($linkClass ? ' class="' . $linkClass . '"' : '') . 05898 $finalTagParts['aTagParams'] . '>'; 05899 } else { 05900 $res = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . 05901 ($title ? ' title="' . $title . '"' : '') . 05902 $finalTagParts['targetParams'] . 05903 ($linkClass ? ' class="' . $linkClass . '"' : '') . 05904 $finalTagParts['aTagParams'] . '>'; 05905 } 05906 } 05907 05908 // Call user function: 05909 if ($conf['userFunc']) { 05910 $finalTagParts['TAG'] = $res; 05911 $res = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts); 05912 } 05913 05914 // Hook: Call post processing function for link rendering: 05915 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']) 05916 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) { 05917 05918 $_params = array( 05919 'conf' => &$conf, 05920 'linktxt' => &$linktxt, 05921 'finalTag' => &$res, 05922 'finalTagParts' => &$finalTagParts 05923 ); 05924 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) { 05925 t3lib_div::callUserFunction($_funcRef, $_params, $this); 05926 } 05927 } 05928 05929 // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made: 05930 if ($conf['returnLast']) { 05931 switch ($conf['returnLast']) { 05932 case 'url' : 05933 return $this->lastTypoLinkUrl; 05934 break; 05935 case 'target' : 05936 return $this->lastTypoLinkTarget; 05937 break; 05938 } 05939 } 05940 05941 $wrap = isset($conf['wrap.']) 05942 ? $this->stdWrap($conf['wrap'], $conf['wrap.']) 05943 : $conf['wrap']; 05944 if ($conf['ATagBeforeWrap']) { 05945 return $res . $this->wrap($linktxt, $wrap) . '</a>'; 05946 } else { 05947 return $this->wrap($res . $linktxt . '</a>', $wrap); 05948 } 05949 } else { 05950 return $linktxt; 05951 } 05952 } 05953 05954 /** 05955 * Forces a given URL to be absolute. 05956 * 05957 * @param string $url The URL to be forced to be absolute 05958 * @param array $configuration TypoScript configuration of typolink 05959 * @return string The absolute URL 05960 */ 05961 protected function forceAbsoluteUrl($url, array $configuration) { 05962 if (!empty($url) && isset($configuration['forceAbsoluteUrl']) && $configuration['forceAbsoluteUrl']) { 05963 if (preg_match('#^(?:([a-z]+)(://))?([^/]*)(.*)$#', $url, $matches)) { 05964 $urlParts = array( 05965 'scheme' => $matches[1], 05966 'delimiter' => '://', 05967 'host' => $matches[3], 05968 'path' => $matches[4] 05969 ); 05970 05971 // Set scheme and host if not yet part of the URL: 05972 if (empty($urlParts['host'])) { 05973 $urlParts['scheme'] = 'http'; 05974 $urlParts['host'] = t3lib_div::getIndpEnv('HTTP_HOST'); 05975 $isUrlModified = TRUE; 05976 } 05977 05978 // Override scheme: 05979 $forceAbsoluteUrl = & $configuration['forceAbsoluteUrl.']['scheme']; 05980 if (!empty($forceAbsoluteUrl) && $urlParts['scheme'] !== $forceAbsoluteUrl) { 05981 $urlParts['scheme'] = $forceAbsoluteUrl; 05982 $isUrlModified = TRUE; 05983 } 05984 05985 // Recreate the absolute URL: 05986 if ($isUrlModified) { 05987 $url = implode('', $urlParts); 05988 } 05989 } 05990 } 05991 05992 return $url; 05993 } 05994 05995 /** 05996 * Based on the input "TypoLink" TypoScript configuration this will return the generated URL 05997 * 05998 * @param array TypoScript properties for "typolink" 05999 * @return string The URL of the link-tag that typolink() would by itself return 06000 * @see typoLink() 06001 */ 06002 function typoLink_URL($conf) { 06003 $this->typolink('|', $conf); 06004 return $this->lastTypoLinkUrl; 06005 } 06006 06007 /** 06008 * Returns a linked string made from typoLink parameters. 06009 * 06010 * This function takes $label as a string, wraps it in a link-tag based on the $params string, which should contain data like that you would normally pass to the popular <LINK>-tag in the TSFE. 06011 * Optionally you can supply $urlParameters which is an array with key/value pairs that are rawurlencoded and appended to the resulting url. 06012 * 06013 * @param string Text string being wrapped by the link. 06014 * @param string Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file. 06015 * @param array An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet. 06016 * @param string Specific target set, if any. (Default is using the current) 06017 * @return string The wrapped $label-text string 06018 * @see getTypoLink_URL() 06019 */ 06020 function getTypoLink($label, $params, $urlParameters = array(), $target = '') { 06021 $conf = array(); 06022 $conf['parameter'] = $params; 06023 if ($target) { 06024 $conf['target'] = $target; 06025 $conf['extTarget'] = $target; 06026 $conf['fileTarget'] = $target; 06027 } 06028 if (is_array($urlParameters)) { 06029 if (count($urlParameters)) { 06030 $conf['additionalParams'] .= t3lib_div::implodeArrayForUrl('', $urlParameters); 06031 } 06032 } else { 06033 $conf['additionalParams'] .= $urlParameters; 06034 } 06035 $out = $this->typolink($label, $conf); 06036 return $out; 06037 } 06038 06039 /** 06040 * Returns the URL of a "typolink" create from the input parameter string, url-parameters and target 06041 * 06042 * @param string Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file. 06043 * @param array An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet. 06044 * @param string Specific target set, if any. (Default is using the current) 06045 * @return string The URL 06046 * @see getTypoLink() 06047 */ 06048 function getTypoLink_URL($params, $urlParameters = array(), $target = '') { 06049 $this->getTypoLink('', $params, $urlParameters, $target); 06050 return $this->lastTypoLinkUrl; 06051 } 06052 06053 /** 06054 * Generates a typolink and returns the two link tags - start and stop - in an array 06055 * 06056 * @param array "typolink" TypoScript properties 06057 * @return array An array with two values in key 0+1, each value being the start and close <a>-tag of the typolink properties being inputted in $conf 06058 * @see typolink() 06059 */ 06060 function typolinkWrap($conf) { 06061 $k = md5(microtime()); 06062 return explode($k, $this->typolink($k, $conf)); 06063 } 06064 06065 /** 06066 * Returns the current page URL 06067 * 06068 * @param array Optionally you can specify additional URL parameters. An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet. 06069 * @param integer An alternative ID to the current id ($GLOBALS['TSFE']->id) 06070 * @return string The URL 06071 * @see getTypoLink_URL() 06072 */ 06073 function currentPageUrl($urlParameters = array(), $id = 0) { 06074 return $this->getTypoLink_URL($id ? $id : $GLOBALS['TSFE']->id, $urlParameters, $GLOBALS['TSFE']->sPre); 06075 } 06076 06077 /** 06078 * Returns the &MP variable value for a page id. 06079 * The function will do its best to find a MP value that will keep the page id inside the current Mount Point rootline if any. 06080 * 06081 * @param integer page id 06082 * @param boolean If TRUE, the MPvalue is returned raw. Normally it is encoded as &MP=... variable 06083 * @return string MP value, prefixed with &MP= (depending on $raw) 06084 * @see typolink() 06085 */ 06086 function getClosestMPvalueForPage($pageId, $raw = FALSE) { 06087 // MointPoints: 06088 if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $GLOBALS['TSFE']->MP) { 06089 06090 if (!strcmp($GLOBALS['TSFE']->id, $pageId)) { // same page as current. 06091 $MP = $GLOBALS['TSFE']->MP; 06092 } else { // ... otherwise find closest meeting point: 06093 $tCR_rootline = $GLOBALS['TSFE']->sys_page->getRootLine($pageId, '', TRUE); // Gets rootline of linked-to page 06094 $inverseTmplRootline = array_reverse($GLOBALS['TSFE']->tmpl->rootLine); 06095 06096 $rl_mpArray = array(); 06097 $startMPaccu = FALSE; 06098 06099 // Traverse root line of link uid and inside of that the REAL root line of current position. 06100 foreach ($tCR_rootline as $tCR_data) { 06101 foreach ($inverseTmplRootline as $rlKey => $invTmplRLRec) { 06102 06103 // Force accumulating when in overlay mode: Links to this page have to stay within the current branch 06104 if ($invTmplRLRec['_MOUNT_OL'] && ($tCR_data['uid'] == $invTmplRLRec['uid'])) { 06105 $startMPaccu = TRUE; 06106 } 06107 06108 // Accumulate MP data: 06109 if ($startMPaccu && $invTmplRLRec['_MP_PARAM']) { 06110 $rl_mpArray[] = $invTmplRLRec['_MP_PARAM']; 06111 } 06112 06113 // If two PIDs matches and this is NOT the site root, start accumulation of MP data (on the next level): 06114 // (The check for site root is done so links to branches outsite the site but sharing the site roots PID 06115 // is NOT detected as within the branch!) 06116 if ($tCR_data['pid'] == $invTmplRLRec['pid'] && count($inverseTmplRootline) != $rlKey + 1) { 06117 $startMPaccu = TRUE; 06118 } 06119 } 06120 if ($startMPaccu) 06121 break; // Good enough... 06122 } 06123 06124 if (count($rl_mpArray)) { 06125 $MP = implode(',', array_reverse($rl_mpArray)); 06126 } 06127 } 06128 } 06129 06130 return !$raw ? ($MP ? '&MP=' . rawurlencode($MP) : '') : $MP; 06131 } 06132 06133 /** 06134 * Creates a href attibute for given $mailAddress. 06135 * The function uses spamProtectEmailAddresses and Jumpurl functionality for encoding the mailto statement. 06136 * If spamProtectEmailAddresses is disabled, it'll just return a string like "mailto:user@example.tld". 06137 * 06138 * @param string Email address 06139 * @param string Link text, default will be the email address. 06140 * @param string Initial link parameters, only used if Jumpurl functionality is enabled. Example: ?id=5&type=0 06141 * @return string Returns a numerical array with two elements: 1) $mailToUrl, string ready to be inserted into the href attribute of the <a> tag, b) $linktxt: The string between starting and ending <a> tag. 06142 */ 06143 function getMailTo($mailAddress, $linktxt, $initP = '?') { 06144 if (!strcmp($linktxt, '')) { 06145 $linktxt = $mailAddress; 06146 } 06147 06148 $mailToUrl = 'mailto:' . $mailAddress; 06149 06150 if (!$GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $GLOBALS['TSFE']->config['config']['jumpurl_mailto_disable']) { 06151 if ($GLOBALS['TSFE']->spamProtectEmailAddresses) { 06152 if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii') { 06153 $mailToUrl = $GLOBALS['TSFE']->encryptEmail($mailToUrl); 06154 } else { 06155 $mailToUrl = "javascript:linkTo_UnCryptMailto('" . $GLOBALS['TSFE']->encryptEmail($mailToUrl) . "');"; 06156 } 06157 if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']) { 06158 $atLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']); 06159 } 06160 $spamProtectedMailAddress = str_replace('@', ($atLabel ? $atLabel : '(at)'), $mailAddress); 06161 06162 if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']) { 06163 $lastDotLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']); 06164 $lastDotLabel = $lastDotLabel ? $lastDotLabel : '(dot)'; 06165 $spamProtectedMailAddress = preg_replace('/\.([^\.]+)$/', $lastDotLabel . '$1', $spamProtectedMailAddress); 06166 } 06167 $linktxt = str_ireplace($mailAddress, $spamProtectedMailAddress, $linktxt); 06168 } 06169 } else { 06170 $mailToUrl = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . 06171 $initP . '&jumpurl=' . rawurlencode($mailToUrl) . $GLOBALS['TSFE']->getMethodUrlIdToken; 06172 } 06173 return array( 06174 $mailToUrl, $linktxt 06175 ); 06176 } 06177 06178 /** 06179 * Gets the query arguments and assembles them for URLs. 06180 * Arguments may be removed or set, depending on configuration. 06181 * 06182 * @param string Configuration 06183 * @param array Multidimensional key/value pairs that overrule incoming query arguments 06184 * @param boolean If set, key/value pairs not in the query but the overrule array will be set 06185 * @return string The URL query part (starting with a &) 06186 */ 06187 public function getQueryArguments($conf, $overruleQueryArguments = array(), $forceOverruleArguments = FALSE) { 06188 switch ((string) $conf['method']) { 06189 case 'GET' : 06190 $currentQueryArray = t3lib_div::_GET(); 06191 break; 06192 case 'POST' : 06193 $currentQueryArray = t3lib_div::_POST(); 06194 break; 06195 case 'GET,POST' : 06196 $currentQueryArray = array_merge(t3lib_div::_GET(), t3lib_div::_POST()); 06197 break; 06198 case 'POST,GET' : 06199 $currentQueryArray = array_merge(t3lib_div::_POST(), t3lib_div::_GET()); 06200 break; 06201 default : 06202 $currentQueryArray = t3lib_div::explodeUrl2Array(t3lib_div::getIndpEnv('QUERY_STRING'), TRUE); 06203 } 06204 06205 if ($conf['exclude']) { 06206 $exclude = str_replace(',', '&', $conf['exclude']); 06207 $exclude = t3lib_div::explodeUrl2Array($exclude, TRUE); 06208 // never repeat id 06209 $exclude['id'] = 0; 06210 $newQueryArray = t3lib_div::arrayDiffAssocRecursive($currentQueryArray, $exclude); 06211 } else { 06212 $newQueryArray = $currentQueryArray; 06213 } 06214 06215 if ($forceOverruleArguments) { 06216 $newQueryArray = t3lib_div::array_merge_recursive_overrule($newQueryArray, $overruleQueryArguments); 06217 } else { 06218 $newQueryArray = t3lib_div::array_merge_recursive_overrule($newQueryArray, $overruleQueryArguments, TRUE); 06219 } 06220 06221 return t3lib_div::implodeArrayForUrl('', $newQueryArray); 06222 } 06223 06224 06225 06226 /*********************************************** 06227 * 06228 * Miscellaneous functions, stand alone 06229 * 06230 ***********************************************/ 06231 06232 /** 06233 * Wrapping a string. 06234 * Implements the TypoScript "wrap" property. 06235 * Example: $content = "HELLO WORLD" and $wrap = "<strong> | </strong>", result: "<strong>HELLO WORLD</strong>" 06236 * 06237 * @param string The content to wrap 06238 * @param string The wrap value, eg. "<strong> | </strong>" 06239 * @param string The char used to split the wrapping value, default is "|" 06240 * @return string Wrapped input string 06241 * @see noTrimWrap() 06242 */ 06243 function wrap($content, $wrap, $char = '|') { 06244 if ($wrap) { 06245 $wrapArr = explode($char, $wrap); 06246 return trim($wrapArr[0]) . $content . trim($wrapArr[1]); 06247 } else 06248 return $content; 06249 } 06250 06251 /** 06252 * Wrapping a string, preserving whitespace in wrap value. 06253 * Notice that the wrap value uses part 1/2 to wrap (and not 0/1 which wrap() does) 06254 * 06255 * @param string The content to wrap, eg. "HELLO WORLD" 06256 * @param string The wrap value, eg. " | <strong> | </strong>" 06257 * @return string Wrapped input string, eg. " <strong> HELLO WORD </strong>" 06258 * @see wrap() 06259 */ 06260 function noTrimWrap($content, $wrap) { 06261 if ($wrap) { 06262 $wrapArr = explode('|', $wrap); 06263 return $wrapArr[1] . $content . $wrapArr[2]; 06264 } else 06265 return $content; 06266 } 06267 06268 /** 06269 * Adds space above/below the input HTML string. It is done by adding a clear-gif and <br /> tag before and/or after the content. 06270 * 06271 * @param string The content to add space above/below to. 06272 * @param string A value like "10 | 20" where the first part denotes the space BEFORE and the second part denotes the space AFTER (in pixels) 06273 * @param array Configuration from TypoScript 06274 * @return string Wrapped string 06275 */ 06276 function wrapSpace($content, $wrap, array $conf = NULL) { 06277 if (trim($wrap)) { 06278 $wrapArray = explode('|', $wrap); 06279 $wrapBefore = intval($wrapArray[0]); 06280 $wrapAfter = intval($wrapArray[1]); 06281 $useDivTag = (isset($conf['useDiv']) && $conf['useDiv']); 06282 if ($wrapBefore) { 06283 if ($useDivTag) { 06284 $content = '<div class="content-spacer spacer-before" style="height:' . $wrapBefore . 'px;"></div>' . $content; 06285 } else { 06286 $content = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 06287 'clear.gif" width="1" height="' . $wrapBefore . '"' . 06288 $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />' . $content; 06289 } 06290 } 06291 if ($wrapAfter) { 06292 if ($useDivTag) { 06293 $content .= '<div class="content-spacer spacer-after" style="height:' . $wrapAfter . 'px;"></div>'; 06294 } else { 06295 $content .= '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 06296 'clear.gif" width="1" height="' . $wrapAfter . '"' . 06297 $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />'; 06298 } 06299 } 06300 } 06301 return $content; 06302 } 06303 06304 /** 06305 * Calling a user function/class-method 06306 * Notice: For classes the instantiated object will have the internal variable, $cObj, set to be a *reference* to $this (the parent/calling object). 06307 * 06308 * @param string The functionname, eg "user_myfunction" or "user_myclass->main". Notice that there are rules for the names of functions/classes you can instantiate. If a function cannot be called for some reason it will be seen in the TypoScript log in the AdminPanel. 06309 * @param array The TypoScript configuration to pass the function 06310 * @param string The content string to pass the function 06311 * @return string The return content from the function call. Should probably be a string. 06312 * @see USER(), stdWrap(), typoLink(), _parseFunc() 06313 */ 06314 function callUserFunction($funcName, $conf, $content) { 06315 $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix']; 06316 if ($pre && !t3lib_div::isFirstPartOfStr(trim($funcName), $pre) && !t3lib_div::isFirstPartOfStr(trim($funcName), 'tx_')) { 06317 $GLOBALS['TT']->setTSlogMessage('Function "' . $funcName . '" was not prepended with "' . $pre . '"', 3); 06318 return $content; 06319 } 06320 // Split parts 06321 $parts = explode('->', $funcName); 06322 if (count($parts) == 2) { // Class 06323 // Check whether class is available and try to reload includeLibs if possible: 06324 if ($this->isClassAvailable($parts[0], $conf)) { 06325 $classObj = t3lib_div::makeInstance($parts[0]); 06326 if (is_object($classObj) && method_exists($classObj, $parts[1])) { 06327 $classObj->cObj = $this; 06328 $content = call_user_func_array(array( 06329 $classObj, $parts[1] 06330 ), array( 06331 $content, $conf 06332 )); 06333 } else { 06334 $GLOBALS['TT']->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', 3); 06335 } 06336 } else { 06337 $GLOBALS['TT']->setTSlogMessage('Class "' . $parts[0] . '" did not exist', 3); 06338 } 06339 } else { // Function 06340 if (function_exists($funcName)) { 06341 $content = call_user_func($funcName, $content, $conf); 06342 } else { 06343 $GLOBALS['TT']->setTSlogMessage('Function "' . $funcName . '" did not exist', 3); 06344 } 06345 } 06346 return $content; 06347 } 06348 06349 /** 06350 * Parses a set of text lines with "[parameters] = [values]" into an array with parameters as keys containing the value 06351 * If lines are empty or begins with "/" or "#" then they are ignored. 06352 * 06353 * @param string Text which the parameters 06354 * @return array array with the parameters as key/value pairs 06355 */ 06356 function processParams($params) { 06357 $paramArr = array(); 06358 $lines = t3lib_div::trimExplode(LF, $params, 1); 06359 foreach ($lines as $val) { 06360 $pair = explode('=', $val, 2); 06361 if (!t3lib_div::inList('#,/', substr(trim($pair[0]), 0, 1))) { 06362 $paramArr[trim($pair[0])] = trim($pair[1]); 06363 } 06364 } 06365 return $paramArr; 06366 } 06367 06368 /** 06369 * Cleans up a string of keywords. Keywords at splitted by "," (comma) ";" (semi colon) and linebreak 06370 * 06371 * @param string String of keywords 06372 * @return string Cleaned up string, keywords will be separated by a comma only. 06373 */ 06374 function keywords($content) { 06375 $listArr = preg_split('/[,;' . LF . ']/', $content); 06376 foreach ($listArr as $k => $v) { 06377 $listArr[$k] = trim($v); 06378 } 06379 return implode(',', $listArr); 06380 } 06381 06382 /** 06383 * Changing character case of a string, converting typically used western charset characters as well. 06384 * 06385 * @param string The string to change case for. 06386 * @param string The direction; either "upper" or "lower" 06387 * @return string 06388 * @see HTMLcaseshift() 06389 */ 06390 function caseshift($theValue, $case) { 06391 $case = strtolower($case); 06392 switch ($case) { 06393 case 'upper' : 06394 $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $theValue, 'toUpper'); 06395 break; 06396 case 'lower' : 06397 $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $theValue, 'toLower'); 06398 break; 06399 } 06400 return $theValue; 06401 } 06402 06403 /** 06404 * Shifts the case of characters outside of HTML tags in the input string 06405 * 06406 * @param string The string to change case for. 06407 * @param string The direction; either "upper" or "lower" 06408 * @return string 06409 * @see caseshift() 06410 */ 06411 function HTMLcaseshift($theValue, $case) { 06412 $inside = 0; 06413 $newVal = ''; 06414 $pointer = 0; 06415 $totalLen = strlen($theValue); 06416 do { 06417 if (!$inside) { 06418 $len = strcspn(substr($theValue, $pointer), '<'); 06419 $newVal .= $this->caseshift(substr($theValue, $pointer, $len), $case); 06420 $inside = 1; 06421 } else { 06422 $len = strcspn(substr($theValue, $pointer), '>') + 1; 06423 $newVal .= substr($theValue, $pointer, $len); 06424 $inside = 0; 06425 } 06426 $pointer += $len; 06427 } while ($pointer < $totalLen); 06428 return $newVal; 06429 } 06430 06431 /** 06432 * Returns the 'age' of the tstamp $seconds 06433 * 06434 * @param integer Seconds to return age for. Example: "70" => "1 min", "3601" => "1 hrs" 06435 * @param string $labels are the labels of the individual units. Defaults to : ' min| hrs| days| yrs' 06436 * @return string The formatted string 06437 */ 06438 function calcAge($seconds, $labels) { 06439 if (t3lib_div::testInt($labels)) { 06440 $labels = ' min| hrs| days| yrs| min| hour| day| year'; 06441 } else { 06442 $labels = str_replace('"', '', $labels); 06443 } 06444 06445 $labelArr = explode('|', $labels); 06446 if (count($labelArr) == 4) { 06447 $labelArr = array_merge($labelArr, $labelArr); 06448 } 06449 $absSeconds = abs($seconds); 06450 $sign = ($seconds > 0 ? 1 : -1); 06451 if ($absSeconds < 3600) { 06452 $val = round($absSeconds / 60); 06453 $seconds = ($sign * $val) . ($val == 1 ? $labelArr[4] : $labelArr[0]); 06454 } elseif ($absSeconds < 24 * 3600) { 06455 $val = round($absSeconds / 3600); 06456 $seconds = ($sign * $val) . ($val == 1 ? $labelArr[5] : $labelArr[1]); 06457 } elseif ($absSeconds < 365 * 24 * 3600) { 06458 $val = round($absSeconds / (24 * 3600)); 06459 $seconds = ($sign * $val) . ($val == 1 ? $labelArr[6] : $labelArr[2]); 06460 } else { 06461 $val = round($absSeconds / (365 * 24 * 3600)); 06462 $seconds = ($sign * $val) . ($val == 1 ? $labelArr[7] : $labelArr[3]); 06463 } 06464 return $seconds; 06465 } 06466 06467 /** 06468 * Sending a notification email using $GLOBALS['TSFE']->plainMailEncoded() 06469 * 06470 * @param string The message content. If blank, no email is sent. 06471 * @param string Comma list of recipient email addresses 06472 * @param string Email address of recipient of an extra mail. The same mail will be sent ONCE more; not using a CC header but sending twice. 06473 * @param string "From" email address 06474 * @param string Optional "From" name 06475 * @param string Optional "Reply-To" header email address. 06476 * @return boolean Returns TRUE if sent 06477 */ 06478 function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName = '', $replyTo = '') { 06479 // Sends order emails: 06480 $headers = array(); 06481 if ($email_from) { 06482 $headers[] = 'From: ' . $email_fromName . ' <' . $email_from . '>'; 06483 } 06484 if ($replyTo) { 06485 $headers[] = 'Reply-To: ' . $replyTo; 06486 } 06487 06488 $recipients = implode(',', t3lib_div::trimExplode(',', $recipients, 1)); 06489 06490 $emailContent = trim($msg); 06491 if ($emailContent) { 06492 $parts = explode(LF, $emailContent, 2); // First line is subject 06493 $subject = trim($parts[0]); 06494 $plain_message = trim($parts[1]); 06495 06496 if ($recipients) 06497 $GLOBALS['TSFE']->plainMailEncoded($recipients, $subject, $plain_message, implode(LF, $headers)); 06498 if ($cc) 06499 $GLOBALS['TSFE']->plainMailEncoded($cc, $subject, $plain_message, implode(LF, $headers)); 06500 return TRUE; 06501 } 06502 } 06503 06504 /** 06505 * Checks if $url has a '?' in it and if not, a '?' is inserted between $url and $params, which are anyway concatenated and returned 06506 * 06507 * @param string Input URL 06508 * @param string URL parameters 06509 * @return string 06510 */ 06511 function URLqMark($url, $params) { 06512 if ($params && !strstr($url, '?')) { 06513 return $url . '?' . $params; 06514 } else { 06515 return $url . $params; 06516 } 06517 } 06518 06519 /** 06520 * Clears TypoScript properties listed in $propList from the input TypoScript array. 06521 * 06522 * @param array TypoScript array of values/properties 06523 * @param string List of properties to clear both value/properties for. Eg. "myprop,another_property" 06524 * @return array The TypoScript array 06525 * @see gifBuilderTextBox() 06526 */ 06527 function clearTSProperties($TSArr, $propList) { 06528 $list = explode(',', $propList); 06529 foreach ($list as $prop) { 06530 $prop = trim($prop); 06531 unset($TSArr[$prop]); 06532 unset($TSArr[$prop . '.']); 06533 } 06534 return $TSArr; 06535 } 06536 06537 /** 06538 * Resolves a TypoScript reference value to the full set of properties BUT overridden with any local properties set. 06539 * So the reference is resolved but overlaid with local TypoScript properties of the reference value. 06540 * 06541 * @param array The TypoScript array 06542 * @param string The property name: If this value is a reference (eg. " < plugins.tx_something") then the reference will be retrieved and inserted at that position (into the properties only, not the value...) AND overlaid with the old properties if any. 06543 * @return array The modified TypoScript array 06544 * @see user_plaintext::typolist(),user_plaintext::typohead() 06545 */ 06546 function mergeTSRef($confArr, $prop) { 06547 if (substr($confArr[$prop], 0, 1) == '<') { 06548 $key = trim(substr($confArr[$prop], 1)); 06549 $cF = t3lib_div::makeInstance('t3lib_TSparser'); 06550 // $name and $conf is loaded with the referenced values. 06551 $old_conf = $confArr[$prop . '.']; 06552 list ($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup); 06553 if (is_array($old_conf) && count($old_conf)) { 06554 $conf = $this->joinTSarrays($conf, $old_conf); 06555 } 06556 $confArr[$prop . '.'] = $conf; 06557 } 06558 return $confArr; 06559 } 06560 06561 /** 06562 * Merges two TypoScript propery array, overlaing the $old_conf onto the $conf array 06563 * 06564 * @param array TypoScript property array, the "base" 06565 * @param array TypoScript property array, the "overlay" 06566 * @return array The resulting array 06567 * @see mergeTSRef(), tx_tstemplatestyler_modfunc1::joinTSarrays() 06568 */ 06569 function joinTSarrays($conf, $old_conf) { 06570 if (is_array($old_conf)) { 06571 foreach ($old_conf as $key => $val) { 06572 if (is_array($val)) { 06573 $conf[$key] = $this->joinTSarrays($conf[$key], $val); 06574 } else { 06575 $conf[$key] = $val; 06576 } 06577 } 06578 } 06579 return $conf; 06580 } 06581 06582 /** 06583 * This function creates a number of TEXT-objects in a Gifbuilder configuration in order to create a text-field like thing. Used with the script tslib/media/scripts/postit.inc 06584 * 06585 * @param array TypoScript properties for Gifbuilder - TEXT GIFBUILDER objects are added to this array and returned. 06586 * @param array TypoScript properties for this function 06587 * @param string The text string to write onto the GIFBUILDER file 06588 * @return array The modified $gifbuilderConf array 06589 * @see media/scripts/postit.inc 06590 */ 06591 function gifBuilderTextBox($gifbuilderConf, $conf, $text) { 06592 $chars = intval($conf['chars']) ? intval($conf['chars']) : 20; 06593 $lineDist = intval($conf['lineDist']) ? intval($conf['lineDist']) : 20; 06594 $Valign = strtolower(trim($conf['Valign'])); 06595 $tmplObjNumber = intval($conf['tmplObjNumber']); 06596 $maxLines = intval($conf['maxLines']); 06597 06598 if ($tmplObjNumber && $gifbuilderConf[$tmplObjNumber] == 'TEXT') { 06599 $textArr = $this->linebreaks($text, $chars, $maxLines); 06600 $angle = intval($gifbuilderConf[$tmplObjNumber . '.']['angle']); 06601 foreach ($textArr as $c => $textChunk) { 06602 $index = $tmplObjNumber + 1 + ($c * 2); 06603 // Workarea 06604 $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $index); 06605 $rad_angle = 2 * pi() / 360 * $angle; 06606 $x_d = sin($rad_angle) * $lineDist; 06607 $y_d = cos($rad_angle) * $lineDist; 06608 06609 $diff_x_d = 0; 06610 $diff_y_d = 0; 06611 if ($Valign == 'center') { 06612 $diff_x_d = $x_d * count($textArr); 06613 $diff_x_d = $diff_x_d / 2; 06614 $diff_y_d = $y_d * count($textArr); 06615 $diff_y_d = $diff_y_d / 2; 06616 } 06617 06618 06619 $x_d = round($x_d * $c - $diff_x_d); 06620 $y_d = round($y_d * $c - $diff_y_d); 06621 06622 $gifbuilderConf[$index] = 'WORKAREA'; 06623 $gifbuilderConf[$index . '.']['set'] = $x_d . ',' . $y_d; 06624 // Text 06625 $index++; 06626 $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $index); 06627 $gifbuilderConf[$index] = 'TEXT'; 06628 $gifbuilderConf[$index . '.'] = $this->clearTSProperties($gifbuilderConf[$tmplObjNumber . '.'], 'text'); 06629 $gifbuilderConf[$index . '.']['text'] = $textChunk; 06630 } 06631 $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $tmplObjNumber); 06632 } 06633 return $gifbuilderConf; 06634 } 06635 06636 /** 06637 * Splits a text string into lines and returns an array with these lines but a max number of lines. 06638 * 06639 * @param string The string to break 06640 * @param integer Max number of characters per line. 06641 * @param integer Max number of lines in all. 06642 * @return array array with lines. 06643 * @access private 06644 * @see gifBuilderTextBox() 06645 */ 06646 function linebreaks($string, $chars, $maxLines = 0) { 06647 $lines = explode(LF, $string); 06648 $lineArr = array(); 06649 $c = 0; 06650 foreach ($lines as $paragraph) { 06651 $words = explode(' ', $paragraph); 06652 foreach ($words as $word) { 06653 if (strlen($lineArr[$c] . $word) > $chars) { 06654 $c++; 06655 } 06656 if (!$maxLines || $c < $maxLines) { 06657 $lineArr[$c] .= $word . ' '; 06658 } 06659 } 06660 $c++; 06661 } 06662 return $lineArr; 06663 } 06664 06665 /** 06666 * Returns a JavaScript <script> section with some function calls to JavaScript functions from "t3lib/jsfunc.updateform.js" (which is also included by setting a reference in $GLOBALS['TSFE']->additionalHeaderData['JSincludeFormupdate']) 06667 * The JavaScript codes simply transfers content into form fields of a form which is probably used for editing information by frontend users. Used by fe_adminLib.inc. 06668 * 06669 * @param array Data array which values to load into the form fields from $formName (only field names found in $fieldList) 06670 * @param string The form name 06671 * @param string A prefix for the data array 06672 * @param string The list of fields which are loaded 06673 * @return string 06674 * @access private 06675 * @see user_feAdmin::displayCreateScreen() 06676 */ 06677 function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList) { 06678 $JSPart = ''; 06679 $updateValues = t3lib_div::trimExplode(',', $fieldList); 06680 foreach ($updateValues as $fKey) { 06681 $value = $dataArray[$fKey]; 06682 if (is_array($value)) { 06683 foreach ($value as $Nvalue) { 06684 $JSPart .= " 06685 updateForm('" . $formName . "','" . $arrPrefix . "[" . $fKey . "][]'," . t3lib_div::quoteJSvalue($Nvalue, TRUE) . ");"; 06686 } 06687 06688 } else { 06689 $JSPart .= " 06690 updateForm('" . $formName . "','" . $arrPrefix . "[" . $fKey . "]'," . t3lib_div::quoteJSvalue($value, TRUE) . ");"; 06691 } 06692 } 06693 $JSPart = '<script type="text/javascript"> 06694 /*<![CDATA[*/ ' . $JSPart . ' 06695 /*]]>*/ 06696 </script> 06697 '; 06698 $GLOBALS['TSFE']->additionalHeaderData['JSincludeFormupdate'] = '<script type="text/javascript" src="' . t3lib_div::createVersionNumberedFilename($GLOBALS['TSFE']->absRefPrefix . 't3lib/jsfunc.updateform.js') . '"></script>'; 06699 return $JSPart; 06700 } 06701 06702 /** 06703 * Includes resources if the config property 'includeLibs' is set. 06704 * 06705 * @param array $config: TypoScript configuration 06706 * @return boolean Whether a configuration for including libs was found and processed 06707 */ 06708 public function includeLibs(array $config) { 06709 $librariesIncluded = FALSE; 06710 06711 if (isset($config['includeLibs']) && $config['includeLibs']) { 06712 $libraries = t3lib_div::trimExplode(',', $config['includeLibs'], TRUE); 06713 $GLOBALS['TSFE']->includeLibraries($libraries); 06714 $librariesIncluded = TRUE; 06715 } 06716 06717 return $librariesIncluded; 06718 } 06719 06720 /** 06721 * Checks whether a PHP class is available. If the check fails, the method tries to 06722 * determine the correct includeLibs to make the class available automatically. 06723 * 06724 * TypoScript example that can cause this: 06725 * | plugin.tx_myext_pi1 = USER 06726 * | plugin.tx_myext_pi1 { 06727 * | includeLibs = EXT:myext/pi1/class.tx_myext_pi1.php 06728 * | userFunc = tx_myext_pi1->main 06729 * | } 06730 * | 10 = USER 06731 * | 10.userFunc = tx_myext_pi1->renderHeader 06732 * 06733 * @param string $className: The name of the PHP class to be checked 06734 * @param array $config: TypoScript configuration (naturally of a USER or COA cObject) 06735 * @return boolean Whether the class is available 06736 * @link http://bugs.typo3.org/view.php?id=9654 06737 * @TODO This method was introduced in TYPO3 4.3 and can be removed if the autoload was integrated 06738 */ 06739 protected function isClassAvailable($className, array $config = NULL) { 06740 if (class_exists($className)) { 06741 return TRUE; 06742 } elseif ($config) { 06743 $pluginConfiguration = & $GLOBALS['TSFE']->tmpl->setup['plugin.'][$className . '.']; 06744 if (isset($pluginConfiguration['includeLibs']) && $pluginConfiguration['includeLibs']) { 06745 $config['includeLibs'] = $pluginConfiguration['includeLibs']; 06746 return $this->includeLibs($config); 06747 } 06748 } 06749 return FALSE; 06750 } 06751 06752 06753 06754 /*********************************************** 06755 * 06756 * Database functions, making of queries 06757 * 06758 ***********************************************/ 06759 06760 /** 06761 * Returns an UPDATE/DELETE sql query which will "delete" the record. 06762 * If the $TCA config for the table tells us to NOT "physically" delete the record but rather set the "deleted" field to "1" then an UPDATE query is returned doing just that. Otherwise it truely is a DELETE query. 06763 * 06764 * @param string The table name, should be in $TCA 06765 * @param integer The UID of the record from $table which we are going to delete 06766 * @param boolean If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!! 06767 * @return string The query, ready to execute unless $doExec was TRUE in which case the return value is FALSE. 06768 * @see DBgetUpdate(), DBgetInsert(), user_feAdmin 06769 */ 06770 function DBgetDelete($table, $uid, $doExec = FALSE) { 06771 if (intval($uid)) { 06772 if ($GLOBALS['TCA'][$table]['ctrl']['delete']) { 06773 if ($doExec) { 06774 return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), array( 06775 $GLOBALS['TCA'][$table]['ctrl']['delete'] => 1 06776 )); 06777 } else { 06778 return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid=' . intval($uid), array( 06779 $GLOBALS['TCA'][$table]['ctrl']['delete'] => 1 06780 )); 06781 } 06782 } else { 06783 if ($doExec) { 06784 return $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid=' . intval($uid)); 06785 } else { 06786 return $GLOBALS['TYPO3_DB']->DELETEquery($table, 'uid=' . intval($uid)); 06787 } 06788 } 06789 } 06790 } 06791 06792 /** 06793 * Returns an UPDATE sql query. 06794 * If a "tstamp" field is configured for the $table tablename in $TCA then that field is automatically updated to the current time. 06795 * Notice: It is YOUR responsibility to make sure the data being updated is valid according the tablefield types etc. Also no logging is performed of the update. It's just a nice general usage API function for creating a quick query. 06796 * NOTICE: From TYPO3 3.6.0 this function ALWAYS adds slashes to values inserted in the query. 06797 * 06798 * @param string The table name, should be in $TCA 06799 * @param integer The UID of the record from $table which we are going to update 06800 * @param array The data array where key/value pairs are fieldnames/values for the record to update. 06801 * @param string Comma list of fieldnames which are allowed to be updated. Only values from the data record for fields in this list will be updated!! 06802 * @param boolean If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!! 06803 * @return string The query, ready to execute unless $doExec was TRUE in which case the return value is FALSE. 06804 * @see DBgetInsert(), DBgetDelete(), user_feAdmin 06805 */ 06806 function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec = FALSE) { 06807 unset($dataArr['uid']); // uid can never be set 06808 $uid = intval($uid); 06809 06810 if ($uid) { 06811 $fieldList = implode(',', t3lib_div::trimExplode(',', $fieldList, 1)); 06812 $updateFields = array(); 06813 06814 foreach ($dataArr as $f => $v) { 06815 if (t3lib_div::inList($fieldList, $f)) { 06816 $updateFields[$f] = $v; 06817 } 06818 } 06819 06820 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) { 06821 $updateFields[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME']; 06822 } 06823 06824 if (count($updateFields)) { 06825 if ($doExec) { 06826 return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . intval($uid), $updateFields); 06827 } else { 06828 return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid=' . intval($uid), $updateFields); 06829 } 06830 } 06831 } 06832 } 06833 06834 /** 06835 * Returns an INSERT sql query which automatically added "system-fields" according to $TCA 06836 * Automatically fields for "tstamp", "crdate", "cruser_id", "fe_cruser_id" and "fe_crgroup_id" is updated if they are configured in the "ctrl" part of $TCA. 06837 * The "pid" field is overridden by the input $pid value if >= 0 (zero). "uid" can never be set as a field 06838 * NOTICE: From TYPO3 3.6.0 this function ALWAYS adds slashes to values inserted in the query. 06839 * 06840 * @param string The table name, should be in $TCA 06841 * @param integer The PID value for the record to insert 06842 * @param array The data array where key/value pairs are fieldnames/values for the record to insert 06843 * @param string Comma list of fieldnames which are allowed to be inserted. Only values from the data record for fields in this list will be inserted!! 06844 * @param boolean If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!! 06845 * @return string The query, ready to execute unless $doExec was TRUE in which case the return value is FALSE. 06846 * @see DBgetUpdate(), DBgetDelete(), user_feAdmin 06847 */ 06848 function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec = FALSE) { 06849 $extraList = 'pid'; 06850 if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) { 06851 $field = $GLOBALS['TCA'][$table]['ctrl']['tstamp']; 06852 $dataArr[$field] = $GLOBALS['EXEC_TIME']; 06853 $extraList .= ',' . $field; 06854 } 06855 if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) { 06856 $field = $GLOBALS['TCA'][$table]['ctrl']['crdate']; 06857 $dataArr[$field] = $GLOBALS['EXEC_TIME']; 06858 $extraList .= ',' . $field; 06859 } 06860 if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) { 06861 $field = $GLOBALS['TCA'][$table]['ctrl']['cruser_id']; 06862 $dataArr[$field] = 0; 06863 $extraList .= ',' . $field; 06864 } 06865 if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) { 06866 $field = $GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']; 06867 $dataArr[$field] = intval($GLOBALS['TSFE']->fe_user->user['uid']); 06868 $extraList .= ',' . $field; 06869 } 06870 if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) { 06871 $field = $GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']; 06872 list ($dataArr[$field]) = explode(',', $GLOBALS['TSFE']->fe_user->user['usergroup']); 06873 $dataArr[$field] = intval($dataArr[$field]); 06874 $extraList .= ',' . $field; 06875 } 06876 06877 unset($dataArr['uid']); // uid can never be set 06878 if ($pid >= 0) { 06879 $dataArr['pid'] = $pid; 06880 } // Set pid < 0 and the dataarr-pid will be used! 06881 $fieldList = implode(',', t3lib_div::trimExplode(',', $fieldList . ',' . $extraList, 1)); 06882 06883 $insertFields = array(); 06884 foreach ($dataArr as $f => $v) { 06885 if (t3lib_div::inList($fieldList, $f)) { 06886 $insertFields[$f] = $v; 06887 } 06888 } 06889 06890 if ($doExec) { 06891 return $GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $insertFields); 06892 } else { 06893 return $GLOBALS['TYPO3_DB']->INSERTquery($table, $insertFields); 06894 } 06895 } 06896 06897 /** 06898 * Checks if a frontend user is allowed to edit a certain record 06899 * 06900 * @param string The table name, found in $TCA 06901 * @param array The record data array for the record in question 06902 * @param array The array of the fe_user which is evaluated, typ. $GLOBALS['TSFE']->fe_user->user 06903 * @param string Commalist of the only fe_groups uids which may edit the record. If not set, then the usergroup field of the fe_user is used. 06904 * @param boolean True, if the fe_user may edit his own fe_user record. 06905 * @return boolean 06906 * @see user_feAdmin 06907 */ 06908 function DBmayFEUserEdit($table, $row, $feUserRow, $allowedGroups = '', $feEditSelf = 0) { 06909 $groupList = $allowedGroups 06910 ? implode(',', array_intersect( 06911 t3lib_div::trimExplode(',', $feUserRow['usergroup'], 1), 06912 t3lib_div::trimExplode(',', $allowedGroups, 1) 06913 )) 06914 : $feUserRow['usergroup']; 06915 $ok = 0; 06916 // points to the field that allows further editing from frontend if not set. If set the record is locked. 06917 if (!$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] || !$row[$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']]) { 06918 // points to the field (integer) that holds the fe_users-id of the creator fe_user 06919 if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) { 06920 $rowFEUser = intval($row[$GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']]); 06921 if ($rowFEUser && $rowFEUser == $feUserRow['uid']) { 06922 $ok = 1; 06923 } 06924 } 06925 // If $feEditSelf is set, fe_users may always edit them selves... 06926 if ($feEditSelf && $table == 'fe_users' && !strcmp($feUserRow['uid'], $row['uid'])) { 06927 $ok = 1; 06928 } 06929 // points to the field (integer) that holds the fe_group-id of the creator fe_user's first group 06930 if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) { 06931 $rowFEUser = intval($row[$GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']]); 06932 if ($rowFEUser) { 06933 if (t3lib_div::inList($groupList, $rowFEUser)) { 06934 $ok = 1; 06935 } 06936 } 06937 } 06938 } 06939 return $ok; 06940 } 06941 06942 /** 06943 * Returns part of a where clause for selecting records from the input table name which the user may edit. 06944 * Conceptually close to the function DBmayFEUserEdit(); It does the same thing but not for a single record, 06945 * rather for a select query selecting all records which the user HAS access to. 06946 * 06947 * @param string The table name 06948 * @param array The array of the fe_user which is evaluated, typ. $GLOBALS['TSFE']->fe_user->user 06949 * @param string Commalist of the only fe_groups uids which may edit the record. If not set, then the usergroup field of the fe_user is used. 06950 * @param boolean True, if the fe_user may edit his own fe_user record. 06951 * @return string The where clause part. ALWAYS returns a string. If no access at all, then " AND 1=0" 06952 * @see DBmayFEUserEdit(), user_feAdmin::displayEditScreen() 06953 */ 06954 function DBmayFEUserEditSelect($table, $feUserRow, $allowedGroups = '', $feEditSelf = 0) { 06955 // Returns where-definition that selects user-editable records. 06956 $groupList = $allowedGroups ? implode(',', array_intersect(t3lib_div::trimExplode(',', $feUserRow['usergroup'], 1), t3lib_div::trimExplode(',', $allowedGroups, 1))) : $feUserRow['usergroup']; 06957 $OR_arr = array(); 06958 // points to the field (integer) that holds the fe_users-id of the creator fe_user 06959 if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) { 06960 $OR_arr[] = $GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id'] . '=' . $feUserRow['uid']; 06961 } 06962 // points to the field (integer) that holds the fe_group-id of the creator fe_user's first group 06963 if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) { 06964 $values = t3lib_div::intExplode(',', $groupList); 06965 foreach ($values as $theGroupUid) { 06966 if ($theGroupUid) { 06967 $OR_arr[] = $GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id'] . '=' . $theGroupUid; 06968 } 06969 } 06970 } 06971 // If $feEditSelf is set, fe_users may always edit them selves... 06972 if ($feEditSelf && $table == 'fe_users') { 06973 $OR_arr[] = 'uid=' . intval($feUserRow['uid']); 06974 } 06975 06976 $whereDef = ' AND 1=0'; 06977 if (count($OR_arr)) { 06978 $whereDef = ' AND (' . implode(' OR ', $OR_arr) . ')'; 06979 if ($GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']) { 06980 $whereDef .= ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] . '=0'; 06981 } 06982 } 06983 return $whereDef; 06984 } 06985 06986 /** 06987 * Returns a part of a WHERE clause which will filter out records with start/end times or hidden/fe_groups fields 06988 * set to values that should de-select them according to the current time, preview settings or user login. 06989 * Definitely a frontend function. 06990 * THIS IS A VERY IMPORTANT FUNCTION: Basically you must add the output from this function for EVERY select query you create 06991 * for selecting records of tables in your own applications - thus they will always be filtered according to the "enablefields" 06992 * configured in TCA 06993 * Simply calls t3lib_pageSelect::enableFields() BUT will send the show_hidden flag along! 06994 * This means this function will work in conjunction with the preview facilities of the frontend engine/Admin Panel. 06995 * 06996 * @param string The table for which to get the where clause 06997 * @param boolean If set, then you want NOT to filter out hidden records. Otherwise hidden record are filtered based on the current preview settings. 06998 * @return string The part of the where clause on the form " AND [fieldname]=0 AND ...". Eg. " AND hidden=0 AND starttime < 123345567" 06999 * @see t3lib_pageSelect::enableFields() 07000 */ 07001 function enableFields($table, $show_hidden = 0) { 07002 return $GLOBALS['TSFE']->sys_page->enableFields( 07003 $table, 07004 $show_hidden ? $show_hidden : ($table == 'pages' ? $GLOBALS['TSFE']->showHiddenPage : $GLOBALS['TSFE']->showHiddenRecords) 07005 ); 07006 } 07007 07008 /** 07009 * Generates a list of Page-uid's from $id. List does not include $id itself 07010 * (unless the id specified is negative in which case it does!) 07011 * The only pages WHICH PREVENTS DECENDING in a branch are 07012 * - deleted pages, 07013 * - pages in a recycler (doktype = 255) or of the Backend User Section (doktpe = 6) type 07014 * - pages that has the extendToSubpages set, WHERE start/endtime, hidden 07015 * and fe_users would hide the records. 07016 * Apart from that, pages with enable-fields excluding them, will also be 07017 * removed. HOWEVER $dontCheckEnableFields set will allow 07018 * enableFields-excluded pages to be included anyway - including 07019 * extendToSubpages sections! 07020 * Mount Pages are also descended but notice that these ID numbers are not 07021 * useful for links unless the correct MPvar is set. 07022 * 07023 * @param integer The id of the start page from which point in the page tree to decend. IF NEGATIVE the id itself is included in the end of the list (only if $begin is 0) AND the output does NOT contain a last comma. Recommended since it will resolve the input ID for mount pages correctly and also check if the start ID actually exists! 07024 * @param integer The number of levels to decend. If you want to decend infinitely, just set this to 100 or so. Should be at least "1" since zero will just make the function return (no decend...) 07025 * @param integer $begin is an optional integer that determines at which level in the tree to start collecting uid's. Zero means 'start right away', 1 = 'next level and out' 07026 * @param boolean See function description 07027 * @param string Additional fields to select. Syntax: ",[fieldname],[fieldname],..." 07028 * @param string Additional where clauses. Syntax: " AND [fieldname]=[value] AND ..." 07029 * @param array array of IDs from previous recursions. In order to prevent infinite loops with mount pages. 07030 * @param integer Internal: Zero for the first recursion, incremented for each recursive call. 07031 * @return string Returns the list with a comma in the end (if any pages selected and not if $id is negative and $id is added itself) - which means the input page id can comfortably be appended to the output string if you need it to. 07032 * @see tslib_fe::checkEnableFields(), tslib_fe::checkPagerecordForIncludeSection() 07033 */ 07034 public function getTreeList($id, $depth, $begin = 0, $dontCheckEnableFields = FALSE, $addSelectFields = '', $moreWhereClauses = '', array $prevId_array = array(), $recursionLevel = 0) { 07035 07036 // Init vars: 07037 $allFields = 'uid,hidden,starttime,endtime,fe_group,extendToSubpages,doktype,php_tree_stop,mount_pid,mount_pid_ol,t3ver_state' . 07038 $addSelectFields; 07039 $depth = intval($depth); 07040 $begin = intval($begin); 07041 $id = intval($id); 07042 $theList = ''; 07043 $addId = 0; 07044 $requestHash = ''; 07045 07046 if ($id) { 07047 07048 // First level, check id (second level, this is done BEFORE the recursive call) 07049 if (!$recursionLevel) { 07050 07051 // check tree list cache 07052 07053 // first, create the hash for this request - not sure yet whether we need all these parameters though 07054 $parameters = array( 07055 $id, 07056 $depth, 07057 $begin, 07058 $dontCheckEnableFields, 07059 $addSelectFields, 07060 $moreWhereClauses, 07061 $prevId_array, 07062 $GLOBALS['TSFE']->gr_list 07063 ); 07064 $requestHash = md5(serialize($parameters)); 07065 07066 $cacheEntry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow( 07067 'treelist', 07068 'cache_treelist', 07069 'md5hash = \'' . $requestHash . '\' AND ( expires > ' . $GLOBALS['EXEC_TIME'] . 07070 ' OR expires = 0 )' 07071 ); 07072 07073 if (is_array($cacheEntry)) { 07074 // cache hit 07075 return $cacheEntry['treelist']; 07076 } 07077 07078 // If Id less than zero it means we should add the real id to list: 07079 if ($id < 0) { 07080 $addId = $id = abs($id); 07081 } 07082 // Check start page: 07083 if ($GLOBALS['TSFE']->sys_page->getRawRecord('pages', $id, 'uid')) { 07084 07085 // Find mount point if any: 07086 $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($id); 07087 if (is_array($mount_info)) { 07088 $id = $mount_info['mount_pid']; 07089 // In Overlay mode, use the mounted page uid as added ID!: 07090 if ($addId && $mount_info['overlay']) { 07091 $addId = $id; 07092 } 07093 } 07094 } else { 07095 return ''; // Return blank if the start page was NOT found at all! 07096 } 07097 } 07098 07099 // Add this ID to the array of IDs 07100 if ($begin <= 0) { 07101 $prevId_array[] = $id; 07102 } 07103 07104 // Select sublevel: 07105 if ($depth > 0) { 07106 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 07107 $allFields, 07108 'pages', 07109 'pid = ' . intval($id) . ' AND deleted = 0 ' . $moreWhereClauses, '', 'sorting' 07110 ); 07111 07112 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 07113 $GLOBALS['TSFE']->sys_page->versionOL('pages', $row); 07114 07115 if ($row['doktype'] == t3lib_pageSelect::DOKTYPE_RECYCLER || $row['doktype'] == t3lib_pageSelect::DOKTYPE_BE_USER_SECTION || $row['t3ver_state'] > 0) { 07116 // Doing this after the overlay to make sure changes 07117 // in the overlay are respected. 07118 // However, we do not process pages below of and 07119 // including of type recycler and BE user section 07120 continue; 07121 } 07122 07123 // Find mount point if any: 07124 $next_id = $row['uid']; 07125 $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($next_id, $row); 07126 07127 // Overlay mode: 07128 if (is_array($mount_info) && $mount_info['overlay']) { 07129 $next_id = $mount_info['mount_pid']; 07130 07131 $res2 = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 07132 $allFields, 07133 'pages', 07134 'uid = ' . intval($next_id) . ' AND deleted = 0 ' . $moreWhereClauses, 07135 '', 07136 'sorting' 07137 ); 07138 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res2); 07139 $GLOBALS['TYPO3_DB']->sql_free_result($res2); 07140 07141 $GLOBALS['TSFE']->sys_page->versionOL('pages', $row); 07142 07143 if ($row['doktype'] == t3lib_pageSelect::DOKTYPE_RECYCLER || $row['doktype'] == t3lib_pageSelect::DOKTYPE_BE_USER_SECTION || $row['t3ver_state'] > 0) { 07144 // Doing this after the overlay to make sure 07145 // changes in the overlay are respected. 07146 07147 // see above 07148 continue; 07149 } 07150 } 07151 // Add record: 07152 if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkPagerecordForIncludeSection($row)) { 07153 // Add ID to list: 07154 if ($begin <= 0) { 07155 if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkEnableFields($row)) { 07156 $theList .= $next_id . ','; 07157 } 07158 } 07159 // Next level: 07160 if ($depth > 1 && !$row['php_tree_stop']) { 07161 // Normal mode: 07162 if (is_array($mount_info) && !$mount_info['overlay']) { 07163 $next_id = $mount_info['mount_pid']; 07164 } 07165 // Call recursively, if the id is not in prevID_array: 07166 if (!in_array($next_id, $prevId_array)) { 07167 $theList .= tslib_cObj::getTreeList( 07168 $next_id, 07169 $depth - 1, 07170 $begin - 1, 07171 $dontCheckEnableFields, 07172 $addSelectFields, 07173 $moreWhereClauses, 07174 $prevId_array, 07175 $recursionLevel + 1 07176 ); 07177 } 07178 } 07179 } 07180 } 07181 $GLOBALS['TYPO3_DB']->sql_free_result($res); 07182 } 07183 07184 // If first run, check if the ID should be returned: 07185 if (!$recursionLevel) { 07186 if ($addId) { 07187 if ($begin > 0) { 07188 $theList .= 0; 07189 } else { 07190 $theList .= $addId; 07191 } 07192 } 07193 07194 $GLOBALS['TYPO3_DB']->exec_INSERTquery( 07195 'cache_treelist', 07196 array( 07197 'md5hash' => $requestHash, 07198 'pid' => $id, 07199 'treelist' => $theList, 07200 'tstamp' => $GLOBALS['EXEC_TIME'] 07201 ) 07202 ); 07203 } 07204 } 07205 // Return list: 07206 return $theList; 07207 } 07208 07209 /** 07210 * Executes a SELECT query for joining three tables according to the MM-relation standards used for tables configured in $TCA. That means MM-joins where the join table has the fields "uid_local" and "uid_foreign" 07211 * 07212 * @param string List of fields to select 07213 * @param string The local table 07214 * @param string The join-table; The "uid_local" field of this table will be matched with $local_table's "uid" field. 07215 * @param string Optionally: The foreign table; The "uid" field of this table will be matched with $mm_table's "uid_foreign" field. If you set this field to blank the join will be over only the $local_table and $mm_table 07216 * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! 07217 * @param string Optional GROUP BY field(s), if none, supply blank string. 07218 * @param string Optional ORDER BY field(s), if none, supply blank string. 07219 * @param string Optional LIMIT value ([begin,]max), if none, supply blank string. 07220 * @return pointer SQL result pointer 07221 * @see mm_query_uidList() 07222 */ 07223 function exec_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') { 07224 return $GLOBALS['TYPO3_DB']->exec_SELECTquery( 07225 $select, 07226 $local_table . ',' . $mm_table . ($foreign_table ? ',' . $foreign_table : ''), 07227 $local_table . '.uid=' . $mm_table . '.uid_local' . 07228 ($foreign_table ? ' AND ' . $foreign_table . '.uid=' . $mm_table . '.uid_foreign' : '') . 07229 $whereClause, // whereClauseMightContainGroupOrderBy 07230 $groupBy, 07231 $orderBy, 07232 $limit 07233 ); 07234 } 07235 07236 /** 07237 * Executes a SELECT query for joining two tables according to the MM-relation standards used for tables configured in $TCA. That means MM-joins where the join table has the fields "uid_local" and "uid_foreign" 07238 * The two tables joined is the join table ($mm_table) and the foreign table ($foreign_table) - so the "local table" is not included but instead you can supply a list of UID integers from the local table to match in the join-table. 07239 * 07240 * @param string List of fields to select 07241 * @param string List of UID integers, eg. "1,2,3,456" 07242 * @param string The join-table; The "uid_local" field of this table will be matched with the list of UID numbers from $local_table_uidlist 07243 * @param string Optionally: The foreign table; The "uid" field of this table will be matched with $mm_table's "uid_foreign" field. If you set this field to blank only records from the $mm_table is returned. No join performed. 07244 * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! 07245 * @param string Optional GROUP BY field(s), if none, supply blank string. 07246 * @param string Optional ORDER BY field(s), if none, supply blank string. 07247 * @param string Optional LIMIT value ([begin,]max), if none, supply blank string. 07248 * @return pointer SQL result pointer 07249 * @see mm_query() 07250 */ 07251 function exec_mm_query_uidList($select, $local_table_uidlist, $mm_table, $foreign_table = '', $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') { 07252 return $GLOBALS['TYPO3_DB']->exec_SELECTquery( 07253 $select, 07254 $mm_table . ($foreign_table ? ',' . $foreign_table : ''), 07255 $mm_table . '.uid_local IN (' . $local_table_uidlist . ')' . 07256 ($foreign_table ? ' AND ' . $foreign_table . '.uid=' . $mm_table . '.uid_foreign' : '') . 07257 $whereClause, // whereClauseMightContainGroupOrderBy 07258 $groupBy, 07259 $orderBy, 07260 $limit 07261 ); 07262 } 07263 07264 /** 07265 * Generates a search where clause based on the input search words (AND operation - all search words must be found in record.) 07266 * Example: The $sw is "content management, system" (from an input form) and the $searchFieldList is "bodytext,header" then the output will be ' AND (bodytext LIKE "%content%" OR header LIKE "%content%") AND (bodytext LIKE "%management%" OR header LIKE "%management%") AND (bodytext LIKE "%system%" OR header LIKE "%system%")' 07267 * 07268 * @param string The search words. These will be separated by space and comma. 07269 * @param string The fields to search in 07270 * @param string The table name you search in (recommended for DBAL compliance. Will be prepended field names as well) 07271 * @return string The WHERE clause. 07272 */ 07273 function searchWhere($sw, $searchFieldList, $searchTable = '') { 07274 global $TYPO3_DB; 07275 07276 $prefixTableName = $searchTable ? $searchTable . '.' : ''; 07277 $where = ''; 07278 if ($sw) { 07279 $searchFields = explode(',', $searchFieldList); 07280 $kw = preg_split('/[ ,]/', $sw); 07281 07282 foreach ($kw as $val) { 07283 $val = trim($val); 07284 $where_p = array(); 07285 if (strlen($val) >= 2) { 07286 $val = $TYPO3_DB->escapeStrForLike($TYPO3_DB->quoteStr($val, $searchTable), $searchTable); 07287 foreach ($searchFields as $field) { 07288 $where_p[] = $prefixTableName . $field . ' LIKE \'%' . $val . '%\''; 07289 } 07290 } 07291 if (count($where_p)) { 07292 $where .= ' AND (' . implode(' OR ', $where_p) . ')'; 07293 } 07294 } 07295 } 07296 return $where; 07297 } 07298 07299 /** 07300 * Executes a SELECT query for records from $table and with conditions based on the configuration in the $conf array 07301 * This function is preferred over ->getQuery() if you just need to create and then execute a query. 07302 * 07303 * @param string The table name 07304 * @param array The TypoScript configuration properties 07305 * @return mixed A SQL result pointer 07306 * @see getQuery() 07307 */ 07308 function exec_getQuery($table, $conf) { 07309 $queryParts = $this->getQuery($table, $conf, TRUE); 07310 07311 return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts); 07312 } 07313 07314 /** 07315 * Creates and returns a SELECT query for records from $table and with conditions based on the configuration in the $conf array 07316 * Implements the "select" function in TypoScript 07317 * 07318 * @param string See ->exec_getQuery() 07319 * @param array See ->exec_getQuery() 07320 * @param boolean If set, the function will return the query not as a string but array with the various parts. RECOMMENDED! 07321 * @return mixed A SELECT query if $returnQueryArray is FALSE, otherwise the SELECT query in an array as parts. 07322 * @access private 07323 * @see CONTENT(), numRows() 07324 */ 07325 function getQuery($table, $conf, $returnQueryArray = FALSE) { 07326 07327 // Handle PDO-style named parameter markers first 07328 $queryMarkers = $this->getQueryMarkers($table, $conf); 07329 07330 // replace the markers in the non-stdWrap properties 07331 foreach ($queryMarkers as $marker => $markerValue) { 07332 $properties = array( 07333 'uidInList', 'selectFields', 'where', 'max', 'begin', 'groupBy', 'orderBy', 'join', 'leftjoin', 'rightjoin' 07334 ); 07335 foreach ($properties as $property) { 07336 if ($conf[$property]) { 07337 $conf[$property] = str_replace('###' . $marker . '###', $markerValue, $conf[$property]); 07338 } 07339 } 07340 } 07341 07342 // Construct WHERE clause: 07343 $conf['pidInList'] = isset($conf['pidInList.']) 07344 ? trim($this->stdWrap($conf['pidInList'], $conf['pidInList.'])) 07345 : trim($conf['pidInList']); 07346 07347 // Handle recursive function for the pidInList 07348 if (isset($conf['recursive'])) { 07349 $conf['recursive'] = intval($conf['recursive']); 07350 if ($conf['recursive'] > 0) { 07351 foreach (explode(',', $conf['pidInList']) as $value) { 07352 if ($value === 'this') { 07353 $value = $GLOBALS['TSFE']->id; 07354 } 07355 $pidList .= $value . ',' . $this->getTreeList($value, $conf['recursive']); 07356 } 07357 $conf['pidInList'] = trim($pidList, ','); 07358 } 07359 } 07360 07361 if (!strcmp($conf['pidInList'], '')) { 07362 $conf['pidInList'] = 'this'; 07363 } 07364 $queryParts = $this->getWhere($table, $conf, TRUE); 07365 07366 // Fields: 07367 $queryParts['SELECT'] = $conf['selectFields'] ? $conf['selectFields'] : '*'; 07368 07369 // Setting LIMIT: 07370 if ($conf['max'] || $conf['begin']) { 07371 $error = 0; 07372 07373 // Finding the total number of records, if used: 07374 if (strstr(strtolower($conf['begin'] . $conf['max']), 'total')) { 07375 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, $queryParts['WHERE'], $queryParts['GROUPBY']); 07376 if ($error = $GLOBALS['TYPO3_DB']->sql_error()) { 07377 $GLOBALS['TT']->setTSlogMessage($error); 07378 } else { 07379 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res); 07380 $conf['max'] = str_ireplace('total', $row[0], $conf['max']); 07381 $conf['begin'] = str_ireplace('total', $row[0], $conf['begin']); 07382 } 07383 $GLOBALS['TYPO3_DB']->sql_free_result($res); 07384 } 07385 if (!$error) { 07386 $conf['begin'] = t3lib_div::intInRange(ceil($this->calc($conf['begin'])), 0); 07387 $conf['max'] = t3lib_div::intInRange(ceil($this->calc($conf['max'])), 0); 07388 if ($conf['begin'] && !$conf['max']) { 07389 $conf['max'] = 100000; 07390 } 07391 07392 if ($conf['begin'] && $conf['max']) { 07393 $queryParts['LIMIT'] = $conf['begin'] . ',' . $conf['max']; 07394 } elseif (!$conf['begin'] && $conf['max']) { 07395 $queryParts['LIMIT'] = $conf['max']; 07396 } 07397 } 07398 } 07399 07400 if (!$error) { 07401 07402 // Setting up tablejoins: 07403 $joinPart = ''; 07404 if ($conf['join']) { 07405 $joinPart = 'JOIN ' . trim($conf['join']); 07406 } elseif ($conf['leftjoin']) { 07407 $joinPart = 'LEFT OUTER JOIN ' . trim($conf['leftjoin']); 07408 } elseif ($conf['rightjoin']) { 07409 $joinPart = 'RIGHT OUTER JOIN ' . trim($conf['rightjoin']); 07410 } 07411 07412 // Compile and return query: 07413 $queryParts['FROM'] = trim($table . ' ' . $joinPart); 07414 07415 // replace the markers in the queryParts to handle stdWrap 07416 // enabled properties 07417 foreach ($queryMarkers as $marker => $markerValue) { 07418 foreach ($queryParts as $queryPartKey => &$queryPartValue) { 07419 $queryPartValue = str_replace('###' . $marker . '###', $markerValue, $queryPartValue); 07420 } 07421 } 07422 07423 $query = $GLOBALS['TYPO3_DB']->SELECTquery( 07424 $queryParts['SELECT'], 07425 $queryParts['FROM'], 07426 $queryParts['WHERE'], 07427 $queryParts['GROUPBY'], 07428 $queryParts['ORDERBY'], 07429 $queryParts['LIMIT'] 07430 ); 07431 07432 return $returnQueryArray ? $queryParts : $query; 07433 } 07434 } 07435 07436 /** 07437 * Helper function for getQuery(), creating the WHERE clause of the SELECT query 07438 * 07439 * @param string The table name 07440 * @param array The TypoScript configuration properties 07441 * @param boolean If set, the function will return the query not as a string but array with the various parts. RECOMMENDED! 07442 * @return mixed A WHERE clause based on the relevant parts of the TypoScript properties for a "select" function in TypoScript, see link. If $returnQueryArray is FALSE the where clause is returned as a string with WHERE, GROUP BY and ORDER BY parts, otherwise as an array with these parts. 07443 * @access private 07444 * @see getQuery() 07445 */ 07446 function getWhere($table, $conf, $returnQueryArray = FALSE) { 07447 global $TCA; 07448 07449 // Init: 07450 $query = ''; 07451 $pid_uid_flag = 0; 07452 $queryParts = array( 07453 'SELECT' => '', 07454 'FROM' => '', 07455 'WHERE' => '', 07456 'GROUPBY' => '', 07457 'ORDERBY' => '', 07458 'LIMIT' => '' 07459 ); 07460 07461 if (trim($conf['uidInList'])) { 07462 $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['uidInList'])); 07463 if (count($listArr) == 1) { 07464 $query .= ' AND ' . $table . '.uid=' . intval($listArr[0]); 07465 } else { 07466 $query .= ' AND ' . $table . '.uid IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($listArr)) . ')'; 07467 } 07468 $pid_uid_flag++; 07469 } 07470 // static_* tables are allowed to be fetched from root page 07471 if (substr($table, 0, 7) == 'static_') { 07472 $pid_uid_flag++; 07473 } 07474 if (trim($conf['pidInList'])) { 07475 $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['pidInList'])); 07476 // removes all pages which are not visible for the user! 07477 $listArr = $this->checkPidArray($listArr); 07478 if (count($listArr)) { 07479 $query .= ' AND ' . $table . '.pid IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($listArr)) . ')'; 07480 $pid_uid_flag++; 07481 } else { 07482 $pid_uid_flag = 0; // If not uid and not pid then uid is set to 0 - which results in nothing!! 07483 } 07484 } 07485 if (!$pid_uid_flag) { // If not uid and not pid then uid is set to 0 - which results in nothing!! 07486 $query .= ' AND ' . $table . '.uid=0'; 07487 } 07488 if ($where = trim($conf['where'])) { 07489 $query .= ' AND ' . $where; 07490 } 07491 07492 if ($conf['languageField']) { 07493 if ($GLOBALS['TSFE']->sys_language_contentOL && $TCA[$table] && $TCA[$table]['ctrl']['languageField'] 07494 && $TCA[$table]['ctrl']['transOrigPointerField']) { 07495 // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will 07496 // OVERLAY the records with localized versions! 07497 $sys_language_content = '0,-1'; 07498 } else { 07499 $sys_language_content = intval($GLOBALS['TSFE']->sys_language_content); 07500 } 07501 $query .= ' AND ' . $conf['languageField'] . ' IN (' . $sys_language_content . ')'; 07502 } 07503 07504 $andWhere = isset($conf['andWhere.']) 07505 ? trim($this->stdWrap($conf['andWhere'], $conf['andWhere.'])) 07506 : trim($conf['andWhere']); 07507 if ($andWhere) { 07508 $query .= ' AND ' . $andWhere; 07509 } 07510 07511 // enablefields 07512 if ($table == 'pages') { 07513 $query .= ' ' . $GLOBALS['TSFE']->sys_page->where_hid_del . $GLOBALS['TSFE']->sys_page->where_groupAccess; 07514 } else { 07515 $query .= $this->enableFields($table); 07516 } 07517 07518 // MAKE WHERE: 07519 if ($query) { 07520 $queryParts['WHERE'] = trim(substr($query, 4)); // Stripping of " AND"... 07521 $query = 'WHERE ' . $queryParts['WHERE']; 07522 } 07523 07524 // GROUP BY 07525 if (trim($conf['groupBy'])) { 07526 $queryParts['GROUPBY'] = isset($conf['groupBy.']) 07527 ? trim($this->stdWrap($conf['groupBy'], $conf['groupBy.'])) 07528 : trim($conf['groupBy']); 07529 } 07530 07531 // ORDER BY 07532 if (trim($conf['orderBy'])) { 07533 $queryParts['ORDERBY'] = isset($conf['orderBy.']) 07534 ? trim($this->stdWrap($conf['orderBy'], $conf['orderBy.'])) 07535 : trim($conf['orderBy']); 07536 $query .= ' ORDER BY ' . $queryParts['ORDERBY']; 07537 } 07538 07539 // Return result: 07540 return $returnQueryArray ? $queryParts : $query; 07541 } 07542 07543 /** 07544 * Removes Page UID numbers from the input array which are not available due to enableFields() or the list of bad doktype numbers ($this->checkPid_badDoktypeList) 07545 * 07546 * @param array array of Page UID numbers for select and for which pages with enablefields and bad doktypes should be removed. 07547 * @return array Returns the array of remaining page UID numbers 07548 * @access private 07549 * @see getWhere(),checkPid() 07550 */ 07551 function checkPidArray($listArr) { 07552 $outArr = array(); 07553 if (is_array($listArr) && count($listArr)) { 07554 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 07555 'uid', 07556 'pages', 07557 'uid IN (' . implode(',', $listArr) . ')' . $this->enableFields('pages') . 07558 ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')' 07559 ); 07560 if ($error = $GLOBALS['TYPO3_DB']->sql_error()) { 07561 $GLOBALS['TT']->setTSlogMessage($error . ': ' . $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery, 3); 07562 } else { 07563 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { 07564 $outArr[] = $row['uid']; 07565 } 07566 } 07567 $GLOBALS['TYPO3_DB']->sql_free_result($res); 07568 } 07569 return $outArr; 07570 } 07571 07572 /** 07573 * Checks if a page UID is available due to enableFields() AND the list of bad doktype numbers ($this->checkPid_badDoktypeList) 07574 * 07575 * @param integer Page UID to test 07576 * @return boolean True if OK 07577 * @access private 07578 * @see getWhere(), checkPidArray() 07579 */ 07580 function checkPid($uid) { 07581 $uid = intval($uid); 07582 if (!isset($this->checkPid_cache[$uid])) { 07583 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( 07584 'uid', 07585 'pages', 07586 'uid=' . intval($uid) . $this->enableFields('pages') . 07587 ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')' 07588 ); 07589 $this->checkPid_cache[$uid] = (bool) $count; 07590 } 07591 return $this->checkPid_cache[$uid]; 07592 } 07593 07594 /** 07595 * Builds list of marker values for handling PDO-like parameter markers in select parts. 07596 * Marker values support stdWrap functionality thus allowing a way to use stdWrap functionality in various properties of 'select' AND prevents SQL-injection problems by quoting and escaping of numeric values, strings, NULL values and comma separated lists. 07597 * 07598 * @param string $table Table to select records from 07599 * @param array $conf Select part of CONTENT definition 07600 * @return array List of values to replace markers with 07601 * @access private 07602 * @see getQuery() 07603 */ 07604 function getQueryMarkers($table, $conf) { 07605 07606 // parse markers and prepare their values 07607 $markerValues = array(); 07608 if (is_array($conf['markers.'])) { 07609 foreach ($conf['markers.'] as $dottedMarker => $dummy) { 07610 $marker = rtrim($dottedMarker, '.'); 07611 if ($dottedMarker == $marker . '.') { 07612 // parse definition 07613 $tempValue = isset($conf['markers.'][$dottedMarker]) 07614 ? $this->stdWrap($conf['markers.'][$dottedMarker]['value'], $conf['markers.'][$dottedMarker]) 07615 : $conf['markers.'][$dottedMarker]['value']; 07616 // quote/escape if needed 07617 if (is_numeric($tempValue)) { 07618 if ((int) $tempValue == $tempValue) { 07619 // handle integer 07620 $markerValues[$marker] = intval($tempValue); 07621 } else { 07622 // handle float 07623 $markerValues[$marker] = floatval($tempValue); 07624 } 07625 } elseif (is_null($tempValue)) { 07626 // it represents NULL 07627 $markerValues[$marker] = 'NULL'; 07628 } elseif ($conf['markers.'][$dottedMarker]['commaSeparatedList'] == 1) { 07629 // see if it is really a comma separated list of values 07630 $explodeValues = t3lib_div::trimExplode(',', $tempValue); 07631 if (count($explodeValues) > 1) { 07632 // handle each element of list separately 07633 $tempArray = array(); 07634 foreach ($explodeValues as $listValue) { 07635 if (is_numeric($listValue)) { 07636 if ((int) $listValue == $listValue) { 07637 $tempArray[] = intval($listValue); 07638 } else { 07639 $tempArray[] = floatval($listValue); 07640 } 07641 } else { 07642 // if quoted, remove quotes before 07643 // escaping. 07644 if (preg_match('/^\'([^\']*)\'$/', $listValue, $matches)) { 07645 $listValue = $matches[1]; 07646 } elseif (preg_match('/^\"([^\"]*)\"$/', $listValue, $matches)) { 07647 $listValue = $matches[1]; 07648 } 07649 $tempArray[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($listValue, $table); 07650 } 07651 } 07652 $markerValues[$marker] = implode(',', $tempArray); 07653 } else { 07654 // handle remaining values as string 07655 $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table); 07656 } 07657 } else { 07658 // handle remaining values as string 07659 $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table); 07660 } 07661 } 07662 } 07663 } 07664 return $markerValues; 07665 } 07666 07667 07668 07669 /*********************************************** 07670 * 07671 * Frontend editing functions 07672 * 07673 ***********************************************/ 07674 07675 /** 07676 * Generates the "edit panels" which can be shown for a page or records on a page when the Admin Panel is enabled for a backend users surfing the frontend. 07677 * With the "edit panel" the user will see buttons with links to editing, moving, hiding, deleting the element 07678 * This function is used for the cObject EDITPANEL and the stdWrap property ".editPanel" 07679 * 07680 * @param string A content string containing the content related to the edit panel. For cObject "EDITPANEL" this is empty but not so for the stdWrap property. The edit panel is appended to this string and returned. 07681 * @param array TypoScript configuration properties for the editPanel 07682 * @param string The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW" 07683 * @param array Alternative data array to use. Default is $this->data 07684 * @return string The input content string with the editPanel appended. This function returns only an edit panel appended to the content string if a backend user is logged in (and has the correct permissions). Otherwise the content string is directly returned. 07685 */ 07686 function editPanel($content, $conf, $currentRecord = '', $dataArr = array()) { 07687 07688 if ($GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit)) { 07689 if (!$currentRecord) { 07690 $currentRecord = $this->currentRecord; 07691 } 07692 07693 if (!count($dataArr)) { 07694 $dataArr = $this->data; 07695 } 07696 07697 // Delegate rendering of the edit panel to the t3lib_frontendedit class. 07698 $content = $GLOBALS['BE_USER']->frontendEdit->displayEditPanel($content, $conf, $currentRecord, $dataArr); 07699 } 07700 07701 return $content; 07702 } 07703 07704 /** 07705 * Adds an edit icon to the content string. The edit icon links to alt_doc.php with proper parameters for editing the table/fields of the context. 07706 * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well). 07707 * 07708 * @param string The content to which the edit icons should be appended 07709 * @param string The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to alt_doc.php 07710 * @param array TypoScript properties for configuring the edit icons. 07711 * @param string The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW" 07712 * @param array Alternative data array to use. Default is $this->data 07713 * @param string Additional URL parameters for the link pointing to alt_doc.php 07714 * @return string The input content string, possibly with edit icons added (not necessarily in the end but just after the last string of normal content. 07715 */ 07716 function editIcons($content, $params, array $conf = array(), $currentRecord = '', $dataArr = array(), $addUrlParamStr = '') { 07717 if ($GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit)) { 07718 if (!$currentRecord) { 07719 $currentRecord = $this->currentRecord; 07720 } 07721 07722 if (!count($dataArr)) { 07723 $dataArr = $this->data; 07724 } 07725 07726 // Delegate rendering of the edit panel to the t3lib_frontendedit class. 07727 $content = $GLOBALS['BE_USER']->frontendEdit->displayEditIcons( 07728 $content, 07729 $params, 07730 $conf, 07731 $currentRecord, 07732 $dataArr, 07733 $addUrlParamStr 07734 ); 07735 } 07736 07737 return $content; 07738 } 07739 07740 07741 /** 07742 * Returns TRUE if the input table/row would be hidden in the frontend (according nto the current time and simulate user group) 07743 * 07744 * @param string The table name 07745 * @param array The data record 07746 * @return boolean 07747 * @access private 07748 * @see editPanelPreviewBorder() 07749 */ 07750 function isDisabled($table, $row) { 07751 global $TCA; 07752 if (($TCA[$table]['ctrl']['enablecolumns']['disabled'] 07753 && $row[$TCA[$table]['ctrl']['enablecolumns']['disabled']]) 07754 || ($TCA[$table]['ctrl']['enablecolumns']['fe_group'] && $GLOBALS['TSFE']->simUserGroup 07755 && $row[$TCA[$table]['ctrl']['enablecolumns']['fe_group']] == $GLOBALS['TSFE']->simUserGroup) 07756 || ($TCA[$table]['ctrl']['enablecolumns']['starttime'] 07757 && $row[$TCA[$table]['ctrl']['enablecolumns']['starttime']] > $GLOBALS['EXEC_TIME']) 07758 || ($TCA[$table]['ctrl']['enablecolumns']['endtime'] 07759 && $row[$TCA[$table]['ctrl']['enablecolumns']['endtime']] 07760 && $row[$TCA[$table]['ctrl']['enablecolumns']['endtime']] < $GLOBALS['EXEC_TIME'])) { 07761 07762 return TRUE; 07763 } 07764 } 07765 } 07766 07767 07768 07769 /** 07770 * Rendering of framesets 07771 * 07772 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 07773 * @package TYPO3 07774 * @subpackage tslib 07775 */ 07776 class tslib_frameset { 07777 07778 /** 07779 * Generates a frameset based on input configuration in a TypoScript array. 07780 * 07781 * @param array The TypoScript properties of the PAGE object property "frameSet.". See link. 07782 * @return string A <frameset> tag. 07783 * @see TSpagegen::renderContentWithHeader() 07784 */ 07785 function make($setup) { 07786 $content = ''; 07787 if (is_array($setup)) { 07788 $sKeyArray = t3lib_TStemplate::sortedKeyList($setup); 07789 foreach ($sKeyArray as $theKey) { 07790 $theValue = $setup[$theKey]; 07791 if (intval($theKey) && $conf = $setup[$theKey . '.']) { 07792 switch ($theValue) { 07793 case 'FRAME' : 07794 $typeNum = intval($GLOBALS['TSFE']->tmpl->setup[$conf['obj'] . '.']['typeNum']); 07795 if (!$conf['src'] && !$typeNum) { 07796 $typeNum = -1; 07797 } 07798 $content .= '<frame' . $this->frameParams($conf, $typeNum) . ' />' . LF; 07799 break; 07800 case 'FRAMESET' : 07801 $frameset = t3lib_div::makeInstance('tslib_frameset'); 07802 $content .= $frameset->make($conf) . LF; 07803 break; 07804 } 07805 } 07806 } 07807 return '<frameset' . $this->framesetParams($setup) . '>' . LF . $content . '</frameset>'; 07808 } 07809 } 07810 07811 /** 07812 * Creates the attributes for a <frame> tag based on a $conf array and the type number 07813 * 07814 * @param array Configuration for the parameter generation for the FRAME set. See link 07815 * @param integer The typenumber to use for the link. 07816 * @return string String with attributes for the frame-tag. With a prefixed space character. 07817 * @access private 07818 * @link http://typo3.org/documentation/document-library/references/doc_core_tsref/current/view/7/9/ 07819 * @see make(), t3lib_TStemplate::linkData() 07820 */ 07821 function frameParams($setup, $typeNum) { 07822 $paramStr = ''; 07823 $name = $setup['obj']; 07824 07825 if ($setup['src'] || $setup['src.']) { 07826 $src = $setup['src']; 07827 if (is_array($setup['src.'])) { 07828 $src = $GLOBALS['TSFE']->cObj->stdWrap($src, $setup['src.']); 07829 } 07830 $paramStr .= ' src="' . htmlspecialchars($src) . '"'; 07831 } else { 07832 $LD = $GLOBALS['TSFE']->tmpl->linkData( 07833 $GLOBALS['TSFE']->page, 07834 '', 07835 $GLOBALS['TSFE']->no_cache, 07836 '', 07837 '', 07838 ($setup['options'] ? '&' . $setup['options'] : '') . 07839 $GLOBALS['TSFE']->cObj->getClosestMPvalueForPage($GLOBALS['TSFE']->page['uid']), intval($typeNum) 07840 ); 07841 $finalURL = $LD['totalURL']; 07842 $paramStr .= ' src="' . htmlspecialchars($finalURL) . '"'; 07843 } 07844 if ($setup['name']) { 07845 $paramStr .= ' name="' . $setup['name'] . '"'; 07846 } else { 07847 $paramStr .= ' name="' . $name . '"'; 07848 } 07849 if ($setup['params']) { 07850 $paramStr .= ' ' . $setup['params']; 07851 } 07852 return $paramStr; 07853 } 07854 07855 /** 07856 * Creates the attributes for a <frameset> tag based on a conf array($setup) 07857 * 07858 * @param array The setup array(TypoScript properties) 07859 * @return string Attributes with preceeding space. 07860 * @access private 07861 * @see make() 07862 */ 07863 function framesetParams($setup) { 07864 $paramStr = ''; 07865 if ($setup['cols']) { 07866 $paramStr .= ' cols="' . $setup['cols'] . '"'; 07867 } 07868 if ($setup['rows']) { 07869 $paramStr .= ' rows="' . $setup['rows'] . '"'; 07870 } 07871 if ($setup['params']) { 07872 $paramStr .= ' ' . $setup['params']; 07873 } 07874 return $paramStr; 07875 } 07876 } 07877 07878 07879 07880 /** 07881 * Rendering of tables for offset 07882 * 07883 * @see tslib_cObj::OTABLE(), tslib_cObj::stdWrap() 07884 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 07885 * @package TYPO3 07886 * @subpackage tslib 07887 */ 07888 class tslib_tableOffset { 07889 var $tableParams = 'border="0" cellspacing="0" cellpadding="0"'; 07890 var $default_tableParams = 'border="0" cellspacing="0" cellpadding="0"'; 07891 var $tdParams = ' width="99%" valign="top"'; 07892 07893 /** 07894 * Wrapping the input content string in a table which will space it out from top/left/right/bottom 07895 * 07896 * @param string The HTML content string 07897 * @param string List of offset parameters; x,y,r,b,w,h 07898 * @return string The HTML content string being wrapped in a <table> offsetting the content as the $offset parameters defined 07899 */ 07900 function start($content, $offset) { 07901 $valPairs = t3lib_div::intExplode(',', $offset . ',,,,,'); 07902 07903 if ($valPairs[0] || $valPairs[1] || $valPairs[2] || $valPairs[3] || $valPairs[4] || $valPairs[5]) { 07904 // If width is defined AND there has been no change to the default table params, then extend them to a tablewidth of 1 07905 if ($valPairs[4] && $this->default_tableParams == $this->tableParams) { 07906 $this->tableParams .= ' width="1"'; 07907 } 07908 // Init: 07909 $this->begin = LF . '<table ' . $this->tableParams . '>'; 07910 $this->end = '</table>'; 07911 $rows = array(); 07912 $widthImg = ''; 07913 $heightImg = ''; 07914 // If width is required, set so bottom column will display for sure 07915 if ($valPairs[4]) { 07916 if (!$valPairs[3]) 07917 $valPairs[3] = 1; 07918 $widthImg = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' . 07919 $valPairs[4] . '" height="1" alt="" title="" />'; 07920 } 07921 // If height is required, set so right column will display for sure 07922 if ($valPairs[5]) { 07923 if (!$valPairs[2]) 07924 $valPairs[2] = 1; 07925 $valPairs[2] = 1; 07926 $heightImg = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="1" height="' . 07927 $valPairs[5] . '" alt="" title="" />'; 07928 } 07929 07930 // First row: 07931 if ($valPairs[1]) { // top 07932 $rows[1] .= '<tr>'; 07933 $rows[1] .= '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' . 07934 ($valPairs[0] ? $valPairs[0] : 1) . '" height="' . $valPairs[1] . '" alt="" title="" /></td>'; 07935 if ($valPairs[0]) 07936 $rows[1] .= '<td></td>'; 07937 if ($valPairs[2]) 07938 $rows[1] .= '<td></td>'; 07939 $rows[1] .= '</tr>'; 07940 } 07941 // Middle row: 07942 $rows[2] .= '<tr>'; 07943 if ($valPairs[0]) { 07944 $rows[2] .= $valPairs[1] ? '<td></td>' : '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 07945 'clear.gif" width="' . $valPairs[0] . '" height="1" alt="" title="" /></td>'; 07946 } 07947 $rows[2] .= '<td' . $this->tdParams . '>' . $content . '</td>'; 07948 if ($valPairs[2]) { 07949 $rows[2] .= $valPairs[3] ? '<td>' . $heightImg . '</td>' : '<td><img src="' . 07950 $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' . $valPairs[2] . '" height="' . 07951 ($valPairs[5] ? $valPairs[5] : 1) . '" alt="" title="" /></td>'; 07952 } 07953 $rows[2] .= '</tr>'; 07954 // Bottom row: 07955 if ($valPairs[3]) { // bottom 07956 $rows[3] .= '<tr>'; 07957 if ($valPairs[0]) 07958 $rows[3] .= '<td></td>'; 07959 if ($valPairs[2]) 07960 $rows[3] .= '<td>' . $widthImg . '</td>'; 07961 $rows[3] .= '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="' . 07962 ($valPairs[2] ? $valPairs[2] : ($valPairs[4] ? $valPairs[4] : 1)) . '" height="' . 07963 $valPairs[3] . '" alt="" title="" /></td>'; 07964 $rows[3] .= '</tr>'; 07965 } 07966 return $this->begin . implode('', $rows) . $this->end; 07967 } else 07968 return $content; 07969 } 07970 } 07971 07972 07973 07974 /** 07975 * Rendering of tables for content positioning 07976 * 07977 * @see tslib_cObj::CTABLE() 07978 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 07979 * @package TYPO3 07980 * @subpackage tslib 07981 */ 07982 class tslib_controlTable { 07983 var $offX = 0; // offset, x 07984 var $offY = 0; // offset, y 07985 07986 07987 var $tm = ''; // top menu 07988 var $lm = ''; // left menu 07989 var $rm = ''; // right menu 07990 var $bm = ''; // bottom menu 07991 var $content = ''; // content 07992 07993 07994 var $tmTDparams = 'valign="top"'; // top menu TDparams 07995 var $lmTDparams = 'valign="top"'; // left menu TDparams 07996 var $rmTDparams = 'valign="top"'; // right menu TDparams 07997 var $bmTDparams = 'valign="top"'; // bottom menu TDparams 07998 var $contentTDparams = 'valign="top"'; // content TDparams 07999 08000 08001 var $cMl = 1; // content margin, left 08002 var $cMr = 1; // content margin, right 08003 var $cMt = 0; // content margin, top 08004 var $cMb = 1; // content margin, bottom 08005 08006 08007 var $contentW = 0; // Places a little gif-spacer in the bottom of the content frame 08008 08009 08010 var $tableParams = 'border="0" cellspacing="0" cellpadding="0"'; 08011 08012 /** 08013 * Wrapping internal vars ->tm, ->lm, ->rm, ->bm and ->content in a table where each content part is stored in a cell. 08014 * The two arguments to this function defines some offsets and margins to use in the arrangement of the content in the table. 08015 * 08016 * @param string List of offset parameters; x,y 08017 * @param string List of margin parameters; left, top, right, bottom 08018 * @return string The content strings wrapped in a <table> as the parameters defined 08019 * @see tslib_cObj::CTABLE() 08020 */ 08021 function start($offset, $cMargins) { 08022 $offArr = t3lib_div::intExplode(',', $offset); 08023 $cMargArr = t3lib_div::intExplode(',', $cMargins); 08024 08025 $cols = 0; 08026 $rows = 0; 08027 08028 if ($this->lm) 08029 $cols++; 08030 if ($this->rm) 08031 $cols++; 08032 if ($cMargArr[0]) 08033 $cols++; 08034 if ($cMargArr[2]) 08035 $cols++; 08036 if ($cMargArr[1] || $cMargArr[3] || $this->tm || $this->bm || $this->content || $this->contentW) 08037 $cols++; 08038 08039 if ($cMargArr[1]) 08040 $rows++; 08041 if ($cMargArr[3]) 08042 $rows++; 08043 if ($this->tm) 08044 $rows++; 08045 if ($this->bm) 08046 $rows++; 08047 if ($this->content) 08048 $rows++; 08049 if ($this->contentW) 08050 $rows++; 08051 if (!$rows && $cols) 08052 $rows = 1; // If there are no rows in the middle but still som columns... 08053 08054 08055 if ($rows && $cols) { 08056 $res = LF . '<table ' . $this->tableParams . '>'; 08057 // top offset: 08058 if ($offArr[1]) { 08059 $xoff = $offArr[0] ? 1 : 0; 08060 if ($cols + $xoff > 1) { 08061 $colspan = ' colspan="' . ($cols + $xoff) . '"'; 08062 } 08063 $res .= '<tr><td' . $colspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08064 'clear.gif" width="1" height="' . $offArr[1] . '" alt="" title="" /></td></tr>'; 08065 } 08066 // The rows: 08067 if ($rows > 1) { 08068 $rowspan = ' rowspan="' . ($rows) . '"'; 08069 } 08070 $res .= '<tr>'; 08071 if ($offArr[0]) { 08072 $res .= '<td' . $rowspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08073 'clear.gif" height="1" width="' . $offArr[0] . '" alt="" title="" /></td>'; 08074 } 08075 if ($this->lm) { 08076 $res .= '<td' . $rowspan . ' ' . $this->lmTDparams . '>' . $this->lm . '</td>'; 08077 } 08078 if ($cMargArr[0]) { 08079 $res .= '<td' . $rowspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08080 'clear.gif" height="1" width="' . $cMargArr[0] . '" alt="" title="" /></td>'; 08081 } 08082 // content... 08083 08084 08085 $middle = array(); 08086 if ($this->tm) { 08087 $middle[] = '<td ' . $this->tmTDparams . '>' . $this->tm . '</td>'; 08088 } 08089 if ($cMargArr[1]) { 08090 $middle[] = '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08091 'clear.gif" width="1" height="' . $cMargArr[1] . '" alt="" title="" /></td>'; 08092 } 08093 if ($this->content) { 08094 $middle[] = '<td ' . $this->contentTDparams . '>' . $this->content . '</td>'; 08095 } 08096 if ($cMargArr[3]) { 08097 $middle[] = '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08098 'clear.gif" width="1" height="' . $cMargArr[3] . '" alt="" title="" /></td>'; 08099 } 08100 if ($this->bm) { 08101 $middle[] = '<td ' . $this->bmTDparams . '>' . $this->bm . '</td>'; 08102 } 08103 if ($this->contentW) { 08104 $middle[] = '<td><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08105 'clear.gif" height="1" width="' . $this->contentW . '" alt="" title="" /></td>'; 08106 } 08107 if (isset($middle[0])) { 08108 $res .= $middle[0]; 08109 } 08110 08111 // Left of content 08112 if ($cMargArr[2]) { 08113 $res .= '<td' . $rowspan . '><img src="' . $GLOBALS['TSFE']->absRefPrefix . 08114 'clear.gif" height="1" width="' . $cMargArr[2] . '" alt="" title="" /></td>'; 08115 } 08116 if ($this->rm) { 08117 $res .= '<td' . $rowspan . ' ' . $this->rmTDparams . '>' . $this->rm . '</td>'; 08118 } 08119 $res .= '</tr>'; 08120 08121 // More than the two rows 08122 $mCount = count($middle); 08123 for ($a = 1; $a < $mCount; $a++) { 08124 $res .= '<tr>' . $middle[$a] . '</tr>'; 08125 } 08126 $res .= '</table>'; 08127 return $res; 08128 } 08129 } 08130 } 08131 08132 08133 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php'])) { 08134 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php']); 08135 } 08136 08137 ?>
1.8.0