PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/typo3/sysext/cms/tslib/class.tslib_content.php

https://bitbucket.org/linxpinx/mercurial
PHP | 8482 lines | 5452 code | 889 blank | 2141 comment | 1421 complexity | e3ae4b6f9839aee5a8f8d74520ec6656 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, Unlicense, LGPL-2.1, Apache-2.0
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 1999-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
  6. * All rights reserved
  7. *
  8. * This script is part of the TYPO3 project. The TYPO3 project is
  9. * free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * The GNU General Public License can be found at
  15. * http://www.gnu.org/copyleft/gpl.html.
  16. * A copy is found in the textfile GPL.txt and important notices to the license
  17. * from the author is found in LICENSE.txt distributed with these scripts.
  18. *
  19. *
  20. * This script is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * This copyright notice MUST APPEAR in all copies of the script!
  26. ***************************************************************/
  27. /**
  28. * Contains classes for Content Rendering based on TypoScript Template configuration
  29. *
  30. * $Id: class.tslib_content.php 8420 2010-07-28 09:15:53Z ohader $
  31. * Revised for TYPO3 3.6 June/2003 by Kasper Skaarhoj
  32. * XHTML compliant
  33. *
  34. * class tslib_cObj : All main TypoScript features, rendering of content objects (cObjects). This class is the backbone of TypoScript Template rendering.
  35. * class tslib_controlTable : Makes a table CTABLE (TS cObject)
  36. * class tslib_tableOffset : Makes a table-offset (TS)
  37. * class tslib_frameset : Generates framesets (TS)
  38. *
  39. * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
  40. */
  41. /**
  42. * [CLASS/FUNCTION INDEX of SCRIPT]
  43. *
  44. *
  45. *
  46. * 256: class tslib_cObj
  47. * 353: function start($data,$table='')
  48. * 387: function setParent($data,$currentRecord)
  49. *
  50. * SECTION: CONTENT_OBJ:
  51. * 412: function getCurrentVal()
  52. * 423: function setCurrentVal($value)
  53. * 436: function cObjGet($setup,$addKey='')
  54. * 460: function cObjGetSingle($name,$conf,$TSkey='__')
  55. *
  56. * SECTION: Functions rendering content objects (cObjects)
  57. * 629: function HTML($conf)
  58. * 640: function TEXT($conf)
  59. * 651: function CLEARGIF($conf)
  60. * 670: function COBJ_ARRAY($conf,$ext='')
  61. * 706: function USER($conf,$ext='')
  62. * 733: function FILE($conf)
  63. * 749: function IMAGE($conf)
  64. * 768: function IMG_RESOURCE($conf)
  65. * 780: function IMGTEXT($conf)
  66. * 1203: function CONTENT($conf)
  67. * 1290: function RECORDS($conf)
  68. * 1370: function HMENU($conf)
  69. * 1402: function CTABLE ($conf)
  70. * 1440: function OTABLE ($conf)
  71. * 1455: function COLUMNS ($conf)
  72. * 1534: function HRULER ($conf)
  73. * 1559: function CASEFUNC ($conf)
  74. * 1584: function LOAD_REGISTER($conf,$name)
  75. * 1624: function FORM($conf,$formData='')
  76. * 2145: function SEARCHRESULT($conf)
  77. * 2311: function PHP_SCRIPT($conf,$ext='')
  78. * 2354: function TEMPLATE($conf)
  79. * 2505: function MULTIMEDIA($conf)
  80. *
  81. * SECTION: Various helper functions for content objects:
  82. * 2592: function getSlidePids($pidList, $pidConf)
  83. * 2623: function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal)
  84. * 2641: function cImage($file,$conf)
  85. * 2669: function getBorderAttr($borderAttr)
  86. * 2685: function imageLinkWrap($string,$imageFile,$conf)
  87. * 2765: function fileResource($fName, $addParams='alt="" title=""')
  88. * 2788: function lastChanged($tstamp)
  89. * 2805: function linkWrap($content,$wrap)
  90. * 2824: function getAltParam($conf, $longDesc=true)
  91. * 2859: function cleanFormName($name)
  92. * 2875: function getATagParams($conf, $addGlobal=1)
  93. *
  94. * SECTION: HTML template processing functions
  95. * 2922: function getSubpart($content, $marker)
  96. * 2938: function substituteSubpart($content,$marker,$subpartContent,$recursive=1)
  97. * 2951: function substituteMarker($content,$marker,$markContent)
  98. * 2971: function substituteMarkerArrayCached($content,$markContentArray=array(),$subpartContentArray=array(),$wrappedSubpartContentArray=array())
  99. * 3069: function substituteMarkerArray($content,$markContentArray,$wrap='',$uppercase=0)
  100. * 3081: function substituteMarkerInObject(&$tree, $markContentArray)
  101. * 3104: function fillInMarkerArray($markContentArray, $row, $fieldList='', $nl2br=TRUE, $prefix='FIELD_', $HSC=FALSE)
  102. *
  103. * SECTION: "stdWrap" + sub functions
  104. * 3167: function stdWrap($content,$conf)
  105. * 3364: function numRows($conf)
  106. * 3388: function listNum($content,$listNum,$char)
  107. * 3408: function checkIf($conf)
  108. * 3471: function filelist($data)
  109. * 3553: function clean_directory($theDir)
  110. * 3571: function HTMLparser_TSbridge($theValue, $conf)
  111. * 3585: function dataWrap($content,$wrap)
  112. * 3598: function insertData($str)
  113. * 3628: function prefixComment($str,$conf,$content)
  114. * 3652: function substring($content,$options)
  115. * 3670: function crop($content,$options)
  116. * 3702: function removeBadHTML($text, $conf)
  117. * 3746: function textStyle($theValue, $conf)
  118. * 3813: function tableStyle($theValue, $conf)
  119. * 3854: function addParams($content,$conf)
  120. * 3895: function filelink($theValue, $conf)
  121. * 3966: function locDataJU($jumpUrl,$conf)
  122. * 3997: function calc($val)
  123. * 4026: function calcIntExplode($delim, $string)
  124. * 4046: function splitObj($value, $conf)
  125. * 4108: function parseFunc($theValue, $conf, $ref='')
  126. * 4218: function _parseFunc ($theValue, $conf)
  127. * 4424: function encaps_lineSplit($theValue, $conf)
  128. * 4507: function http_makelinks($data,$conf)
  129. * 4574: function mailto_makelinks($data,$conf)
  130. * 4617: function getImgResource($file,$fileArray)
  131. *
  132. * SECTION: Data retrieval etc.
  133. * 4810: function getFieldVal($field)
  134. * 4830: function getData($string,$fieldArray)
  135. * 4975: function rootLineValue($key,$field,$slideBack=0,$altRootLine='')
  136. * 4997: function getGlobal($var, $source=NULL)
  137. * 5033: function getKey($key,$arr)
  138. * 5056: function TCAlookup($inputValue,$conf)
  139. *
  140. * SECTION: Link functions (typolink)
  141. * 5116: function typoLink($linktxt, $conf)
  142. * 5481: function typoLink_URL($conf)
  143. * 5499: function getTypoLink($label,$params,$urlParameters=array(),$target='')
  144. * 5526: function getTypoLink_URL($params,$urlParameters=array(),$target='')
  145. * 5538: function typolinkWrap($conf)
  146. * 5551: function currentPageUrl($urlParameters=array(),$id=0)
  147. * 5564: function getClosestMPvalueForPage($pageId, $raw=FALSE)
  148. * 5619: function getMailTo($mailAddress,$linktxt,$initP='?')
  149. * 5658: function getQueryArguments($conf,$overruleQueryArgs=array(),$forceArgs=FALSE)
  150. *
  151. * SECTION: Miscellaneous functions, stand alone
  152. * 5754: function wrap($content,$wrap,$char='|')
  153. * 5770: function noTrimWrap($content,$wrap)
  154. * 5784: function wrapSpace($content, $wrap)
  155. * 5810: function callUserFunction($funcName,$conf,$content)
  156. * 5851: function processParams($params)
  157. * 5869: function keywords($content)
  158. * 5886: function caseshift($theValue, $case)
  159. * 5911: function HTMLcaseshift($theValue, $case)
  160. * 5940: function bytes($sizeInBytes,$labels)
  161. * 5951: function calcAge($seconds,$labels)
  162. * 5983: function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName='', $replyTo='')
  163. * 6010: function URLqMark($url,$params)
  164. * 6026: function checkEmail($email)
  165. * 6038: function clearTSProperties($TSArr,$propList)
  166. * 6057: function mergeTSRef($confArr,$prop)
  167. * 6080: function joinTSarrays($conf,$old_conf)
  168. * 6103: function gifBuilderTextBox($gifbuilderConf, $conf, $text)
  169. * 6159: function linebreaks($string,$chars,$maxLines=0)
  170. * 6190: function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList)
  171. *
  172. * SECTION: Database functions, making of queries
  173. * 6260: function DBgetDelete($table, $uid, $doExec=FALSE)
  174. * 6292: function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec=FALSE)
  175. * 6334: function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec=FALSE)
  176. * 6371: function DBmayFEUserEdit($table,$row, $feUserRow, $allowedGroups='',$feEditSelf=0)
  177. * 6411: function DBmayFEUserEditSelect($table,$feUserRow,$allowedGroups='',$feEditSelf=0)
  178. * 6451: function enableFields($table,$show_hidden=0)
  179. * 6475: function getTreeList($id,$depth,$begin=0,$dontCheckEnableFields=FALSE,$addSelectFields='',$moreWhereClauses='', $prevId_array=array(), $recursionLevel=0)
  180. * 6583: function whereSelectFromList($field,$value)
  181. * 6601: function exec_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
  182. * 6628: function exec_mm_query_uidList($select,$local_table_uidlist,$mm_table,$foreign_table='',$whereClause='',$groupBy='',$orderBy='',$limit='')
  183. * 6649: function searchWhere($sw,$searchFieldList,$searchTable='')
  184. * 6685: function exec_getQuery($table, $conf)
  185. * 6703: function getQuery($table, $conf, $returnQueryArray=FALSE)
  186. * 6783: function getWhere($table,$conf, $returnQueryArray=FALSE)
  187. * 6878: function checkPidArray($listArr)
  188. * 6902: function checkPid($uid)
  189. *
  190. * SECTION: Frontend editing functions
  191. * 6959: function editPanel($content, $conf, $currentRecord='', $dataArr=array())
  192. * 7146: function editIcons($content,$params, $conf=array(), $currentRecord='', $dataArr=array(),$addUrlParamStr='')
  193. * 7228: function editPanelLinkWrap($string,$formName,$cmd,$currentRecord='',$confirm='',$nPid='')
  194. * 7270: function editPanelLinkWrap_doWrap($string,$url,$currentRecord)
  195. * 7298: function editPanelPreviewBorder($table,$row,$content,$thick,$conf=array())
  196. * 7320: function isDisabled($table,$row)
  197. *
  198. *
  199. * 7351: class tslib_frameset
  200. * 7361: function make($setup)
  201. * 7398: function frameParams($setup, $typeNum)
  202. * 7426: function framesetParams($setup)
  203. *
  204. *
  205. * 7459: class tslib_tableOffset
  206. * 7471: function start($content,$offset)
  207. *
  208. *
  209. * 7549: class tslib_controlTable
  210. * 7584: function start($offset,$cMargins)
  211. *
  212. * TOTAL FUNCTIONS: 135
  213. * (This index is automatically created/updated by the extension "extdeveval")
  214. *
  215. */
  216. // Object TypoScript library included:
  217. if(t3lib_extMgm::isLoaded('obts')) {
  218. require_once(t3lib_extMgm::extPath('obts').'_tsobject/_tso.php');
  219. }
  220. /**
  221. * This class contains all main TypoScript features.
  222. * This includes the rendering of TypoScript content objects (cObjects).
  223. * Is the backbone of TypoScript Template rendering.
  224. *
  225. * There are lots of functions you can use from your include-scripts.
  226. * The class "tslib_cObj" is normally instantiated and referred to as "cObj".
  227. * 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.
  228. *
  229. * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
  230. * @package TYPO3
  231. * @subpackage tslib
  232. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&cHash=4ad9d7acb4
  233. */
  234. class tslib_cObj {
  235. var $align = Array ('center', 'right', 'left');
  236. /**
  237. * Holds ImageMagick parameters and extensions used for compression
  238. *
  239. * @see IMGTEXT()
  240. *
  241. * 0= Default
  242. * 1= Dont change! (removes all parameters for the image_object!!)
  243. * 1x = GIFs
  244. * 2x = JPGs
  245. */
  246. var $image_compression = Array(
  247. 10 => Array('params'=>'', 'ext'=>'gif'),
  248. 11 => Array('params'=>'-colors 128', 'ext'=>'gif'),
  249. 12 => Array('params'=>'-colors 64', 'ext'=>'gif'),
  250. 13 => Array('params'=>'-colors 32', 'ext'=>'gif'),
  251. 14 => Array('params'=>'-colors 16', 'ext'=>'gif'),
  252. 15 => Array('params'=>'-colors 8', 'ext'=>'gif'),
  253. 30 => Array('params'=>'-colors 256', 'ext'=>'png'),
  254. 31 => Array('params'=>'-colors 128', 'ext'=>'png'),
  255. 32 => Array('params'=>'-colors 64', 'ext'=>'png'),
  256. 33 => Array('params'=>'-colors 32', 'ext'=>'png'),
  257. 34 => Array('params'=>'-colors 16', 'ext'=>'png'),
  258. 35 => Array('params'=>'-colors 8', 'ext'=>'png'),
  259. 39 => Array('params'=>'', 'ext'=>'png'),
  260. 20 => Array('params'=>'-quality 100', 'ext'=>'jpg'),
  261. 21 => Array('params'=>'-quality 90', 'ext'=>'jpg'),
  262. 22 => Array('params'=>'-quality 80', 'ext'=>'jpg'),
  263. 23 => Array('params'=>'-quality 70', 'ext'=>'jpg'),
  264. 24 => Array('params'=>'-quality 60', 'ext'=>'jpg'),
  265. 25 => Array('params'=>'-quality 50', 'ext'=>'jpg'),
  266. 26 => Array('params'=>'-quality 40', 'ext'=>'jpg'),
  267. 27 => Array('params'=>'-quality 30', 'ext'=>'jpg'),
  268. 28 => Array('params'=>'-quality 20', 'ext'=>'jpg')
  269. );
  270. /**
  271. * ImageMagick parameters for image effects
  272. *
  273. * @see IMGTEXT()
  274. */
  275. var $image_effects = Array(
  276. 1 => '-rotate 90',
  277. 2 => '-rotate 270',
  278. 3 => '-rotate 180',
  279. 10 => '-colorspace GRAY',
  280. 11 => '-sharpen 70',
  281. 20 => '-normalize',
  282. 23 => '-contrast',
  283. 25 => '-gamma 1.3',
  284. 26 => '-gamma 0.8'
  285. );
  286. /**
  287. * Loaded with the current data-record.
  288. *
  289. * If the instance of this class is used to render records from the database those records are found in this array.
  290. * The function stdWrap has TypoScript properties that fetch field-data from this array.
  291. * @see init()
  292. */
  293. var $data = Array();
  294. protected $table = '';
  295. var $oldData = Array(); // Used for backup...
  296. var $alternativeData =''; // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
  297. var $parameters = Array(); // Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
  298. var $currentValKey = 'currentValue_kidjls9dksoje';
  299. 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.
  300. var $currentRecordTotal = 0; // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query.
  301. var $currentRecordNumber = 0; // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering.
  302. var $parentRecordNumber = 0; // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering.
  303. 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.
  304. 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.
  305. // internal
  306. 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)
  307. 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.
  308. var $checkPid_badDoktypeList = '255';
  309. var $lastTypoLinkUrl=''; // This will be set by typoLink() to the url of the most recent link created.
  310. var $lastTypoLinkTarget=''; // DO. link target.
  311. var $lastTypoLinkLD = array();
  312. var $substMarkerCache=array(); // Caching substituteMarkerArrayCached function
  313. var $recordRegister=array(); // Array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
  314. var $cObjHookObjectsArr = array(); // Containig hooks for userdefined cObjects
  315. protected $stdWrapHookObjects = array(); // Containing hook objects for stdWrap
  316. protected $getImgResourceHookObjects; // Containing hook objects for getImgResource
  317. /**
  318. * Set to true by doConvertToUserIntObject() if USER object wants to become USER_INT
  319. */
  320. protected $doConvertToUserIntObject = false;
  321. /**
  322. * Indicates current object type. Can hold one of OBJECTTYPE_ constants or false.
  323. * The value is set and reset inside USER() function. Any time outside of
  324. * USER() it is false.
  325. */
  326. protected $userObjectType = false;
  327. /**
  328. * Indicates that object type is USER.
  329. *
  330. * @see tslib_cObjh::$userObjectType
  331. */
  332. const OBJECTTYPE_USER_INT = 1;
  333. /**
  334. * Indicates that object type is USER.
  335. *
  336. * @see tslib_cObjh::$userObjectType
  337. */
  338. const OBJECTTYPE_USER = 2;
  339. /**
  340. * Class constructor.
  341. * Well, it has to be called manually since it is not a real constructor function.
  342. * 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.
  343. *
  344. * @param array $data the record data that is rendered.
  345. * @param string $table the table that the data record is from.
  346. * @return void
  347. */
  348. function start($data,$table='') {
  349. global $TYPO3_CONF_VARS;
  350. $this->data = $data;
  351. $this->table = $table;
  352. $this->currentRecord = $table ? $table.':'.$this->data['uid'] : '';
  353. $this->parameters = Array();
  354. if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
  355. foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
  356. $this->cObjHookObjectsArr[$classArr[0]] = t3lib_div::getUserObj($classArr[1]);
  357. }
  358. }
  359. $this->stdWrapHookObjects = array();
  360. if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
  361. foreach($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
  362. $hookObject = t3lib_div::getUserObj($classData);
  363. if(!($hookObject instanceof tslib_content_stdWrapHook)) {
  364. throw new UnexpectedValueException('$hookObject must implement interface tslib_content_stdWrapHook', 1195043965);
  365. }
  366. $this->stdWrapHookObjects[] = $hookObject;
  367. }
  368. }
  369. if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
  370. foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
  371. $postInitializationProcessor = t3lib_div::getUserObj($classData);
  372. if(!($postInitializationProcessor instanceof tslib_content_PostInitHook)) {
  373. throw new UnexpectedValueException('$postInitializationProcessor must implement interface tslib_content_PostInitHook', 1274563549);
  374. }
  375. $postInitializationProcessor->postProcessContentObjectInitialization($this);
  376. }
  377. }
  378. }
  379. /**
  380. * Gets the 'getImgResource' hook objects.
  381. * The first call initializes the accordant objects.
  382. *
  383. * @return array The 'getImgResource' hook objects (if any)
  384. */
  385. protected function getGetImgResourceHookObjects() {
  386. if (!isset($this->getImgResourceHookObjects)) {
  387. $this->getImgResourceHookObjects = array();
  388. if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
  389. foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
  390. $hookObject = t3lib_div::getUserObj($classData);
  391. if(!($hookObject instanceof tslib_cObj_getImgResourceHook)) {
  392. throw new UnexpectedValueException('$hookObject must implement interface tslib_cObj_getImgResourceHook', 1218636383);
  393. }
  394. $this->getImgResourceHookObjects[] = $hookObject;
  395. }
  396. }
  397. }
  398. return $this->getImgResourceHookObjects;
  399. }
  400. /**
  401. * Sets the internal variable parentRecord with information about current record.
  402. * 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.
  403. *
  404. * @param array $data: The record array
  405. * @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.
  406. * @return void
  407. * @access private
  408. */
  409. function setParent($data,$currentRecord) {
  410. $this->parentRecord=array('data'=>$data, 'currentRecord'=>$currentRecord);
  411. }
  412. /***********************************************
  413. *
  414. * CONTENT_OBJ:
  415. *
  416. ***********************************************/
  417. /**
  418. * Returns the "current" value.
  419. * 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.
  420. * It's like "load accumulator" in the good old C64 days... basically a "register" you can use as you like.
  421. * 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.
  422. *
  423. * @return mixed The "current" value
  424. */
  425. function getCurrentVal() {
  426. return $this->data[$this->currentValKey];
  427. }
  428. /**
  429. * Sets the "current" value.
  430. *
  431. * @param mixed The variable that you want to set as "current"
  432. * @return void
  433. * @see getCurrentVal()
  434. */
  435. function setCurrentVal($value) {
  436. $this->data[$this->currentValKey] = $value;
  437. }
  438. /**
  439. * Rendering of a "numerical array" of cObjects from TypoScript
  440. * Will call ->cObjGetSingle() for each cObject found and accumulate the output.
  441. *
  442. * @param array $setup: Array with cObjects as values.
  443. * @param string $addKey: A prefix for the debugging information
  444. * @return string Rendered output from the cObjects in the array.
  445. * @see cObjGetSingle()
  446. */
  447. function cObjGet($setup,$addKey='') {
  448. if (is_array($setup)) {
  449. $sKeyArray=t3lib_TStemplate::sortedKeyList($setup);
  450. $content ='';
  451. foreach($sKeyArray as $theKey) {
  452. $theValue=$setup[$theKey];
  453. if (intval($theKey) && !strstr($theKey,'.')) {
  454. $conf=$setup[$theKey.'.'];
  455. $content.=$this->cObjGetSingle($theValue,$conf,$addKey.$theKey); // Get the contentObject
  456. }
  457. }
  458. return $content;
  459. }
  460. }
  461. /**
  462. * Renders a content object
  463. *
  464. * @param string The content object name, eg. "TEXT" or "USER" or "IMAGE"
  465. * @param array The array with TypoScript properties for the content object
  466. * @param string A string label used for the internal debugging tracking.
  467. * @return string cObject output
  468. * @example http://typo3.org/doc.0.html?&encryptionKey=&tx_extrepmgm_pi1[extUid]=267&tx_extrepmgm_pi1[tocEl]=153&cHash=7e74f4d331
  469. */
  470. function cObjGetSingle($name,$conf,$TSkey='__') {
  471. global $TYPO3_CONF_VARS;
  472. $content='';
  473. // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
  474. $GLOBALS['TSFE']->cObjectDepthCounter--;
  475. if ($GLOBALS['TSFE']->cObjectDepthCounter>0) {
  476. $name = trim($name);
  477. if ($GLOBALS['TT']->LR) $GLOBALS['TT']->push($TSkey, $name);
  478. // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
  479. if (substr($name,0,1)=='<') {
  480. $key = trim(substr($name,1));
  481. $cF = t3lib_div::makeInstance('t3lib_TSparser');
  482. // $name and $conf is loaded with the referenced values.
  483. $old_conf=$conf;
  484. list($name, $conf) = $cF->getVal($key,$GLOBALS['TSFE']->tmpl->setup);
  485. if (is_array($old_conf) && count($old_conf)) {
  486. $conf = $this->joinTSarrays($conf,$old_conf);
  487. }
  488. // Getting the cObject
  489. $GLOBALS['TT']->incStackPointer();
  490. $content.=$this->cObjGetSingle($name,$conf,$key);
  491. $GLOBALS['TT']->decStackPointer();
  492. } else {
  493. $hooked = false;
  494. // Application defined cObjects
  495. foreach ($this->cObjHookObjectsArr as $cObjName => $hookObj) {
  496. if (($name===$cObjName) && method_exists($hookObj, 'cObjGetSingleExt')) {
  497. $content.= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
  498. $hooked = true;
  499. }
  500. }
  501. if (!$hooked && isset($GLOBALS['OBTS']['tso_list'][$name]) && t3lib_extMgm::isLoaded('obts')) {
  502. $content.= obts_dtutil::renderDatatypeContent($name, $GLOBALS['OBTS']['tso_list'][$name], $conf, $this);
  503. } elseif (!$hooked) {
  504. // Traditional Content Object branching:
  505. switch($name) {
  506. case 'COBJ_ARRAY':
  507. case 'COA':
  508. $content.=$this->COBJ_ARRAY($conf);
  509. break;
  510. case 'COA_INT':
  511. $content.=$this->COBJ_ARRAY($conf,'INT');
  512. break;
  513. case 'HTML':
  514. $content.=$this->HTML($conf);
  515. break;
  516. case 'TEXT':
  517. $content.=$this->TEXT($conf);
  518. break;
  519. case 'CLEARGIF':
  520. $content.=$this->CLEARGIF($conf);
  521. break;
  522. case 'FILE':
  523. $content.=$this->FILE($conf);
  524. break;
  525. case 'IMAGE':
  526. $content.=$this->IMAGE($conf);
  527. break;
  528. case 'IMG_RESOURCE':
  529. $content.=$this->IMG_RESOURCE($conf);
  530. break;
  531. case 'IMGTEXT':
  532. $content.=$this->IMGTEXT($conf);
  533. break;
  534. case 'CONTENT':
  535. $content.=$this->CONTENT($conf);
  536. break;
  537. case 'RECORDS':
  538. $content.=$this->RECORDS($conf);
  539. break;
  540. case 'HMENU':
  541. $content.=$this->HMENU($conf);
  542. break;
  543. case 'CTABLE':
  544. $content.=$this->CTABLE($conf);
  545. break;
  546. case 'OTABLE':
  547. $content.=$this->OTABLE($conf);
  548. break;
  549. case 'COLUMNS':
  550. $content.=$this->COLUMNS($conf);
  551. break;
  552. case 'HRULER':
  553. $content.=$this->HRULER($conf);
  554. break;
  555. case 'CASE':
  556. $content.=$this->CASEFUNC($conf);
  557. break;
  558. case 'LOAD_REGISTER':
  559. case 'RESTORE_REGISTER':
  560. $this->LOAD_REGISTER($conf,$name);
  561. break;
  562. case 'FORM':
  563. $content.=$this->FORM($conf);
  564. break;
  565. case 'SEARCHRESULT':
  566. $content.=$this->SEARCHRESULT($conf);
  567. break;
  568. case 'PHP_SCRIPT':
  569. $content.=$this->PHP_SCRIPT($conf);
  570. break;
  571. case 'PHP_SCRIPT_EXT':
  572. $content.=$this->PHP_SCRIPT($conf,'EXT');
  573. break;
  574. case 'PHP_SCRIPT_INT':
  575. $content.=$this->PHP_SCRIPT($conf,'INT');
  576. break;
  577. case 'USER':
  578. $content.=$this->USER($conf);
  579. break;
  580. case 'USER_INT':
  581. $content.=$this->USER($conf,'INT');
  582. break;
  583. case 'TEMPLATE':
  584. $content.=$this->TEMPLATE($conf);
  585. break;
  586. case 'EDITPANEL':
  587. if ($GLOBALS['TSFE']->beUserLogin) {$content.=$this->editPanel($content, $conf);}
  588. break;
  589. case 'MULTIMEDIA':
  590. $content.=$this->MULTIMEDIA($conf);
  591. break;
  592. case 'MEDIA':
  593. $content.=$this->MEDIA($conf);
  594. break;
  595. case 'SWFOBJECT':
  596. $content.=$this->SWFOBJECT($conf);
  597. break;
  598. case 'QTOBJECT':
  599. $content.=$this->QTOBJECT($conf);
  600. break;
  601. default:
  602. // call hook functions for extra processing
  603. if($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
  604. foreach($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
  605. $hookObject = t3lib_div::getUserObj($classData);
  606. if(!($hookObject instanceof tslib_content_cObjGetSingleHook)) {
  607. throw new UnexpectedValueException('$hookObject must implement interface tslib_content_cObjGetSingleHook', 1195043731);
  608. }
  609. /* @var $hookObject tslib_content_cObjGetSingleHook */
  610. $content .= $hookObject->getSingleContentObject($name, (array) $conf, $TSkey, $this);
  611. }
  612. }
  613. break;
  614. }
  615. }
  616. }
  617. if ($GLOBALS['TT']->LR) $GLOBALS['TT']->pull($content);
  618. }
  619. // Increasing on exit...
  620. $GLOBALS['TSFE']->cObjectDepthCounter++;
  621. return $content;
  622. }
  623. /********************************************
  624. *
  625. * Functions rendering content objects (cObjects)
  626. *
  627. ********************************************/
  628. /**
  629. * Rendering the cObject, HTML
  630. *
  631. * @param array Array of TypoScript properties
  632. * @return string Output
  633. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=349&cHash=d3fd0c70b4
  634. */
  635. function HTML($conf) {
  636. return $this->stdWrap($conf['value'],$conf['value.']);
  637. }
  638. /**
  639. * Rendering the cObject, TEXT
  640. *
  641. * @param array Array of TypoScript properties
  642. * @return string Output
  643. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=350&cHash=b49de28f83
  644. */
  645. function TEXT($conf) {
  646. return $this->stdWrap($conf['value'],$conf);
  647. }
  648. /**
  649. * Rendering the cObject, CLEARGIF
  650. *
  651. * @param array Array of TypoScript properties
  652. * @return string Output
  653. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=355&cHash=70c0f19915
  654. */
  655. function CLEARGIF($conf) {
  656. $w = $this->stdWrap($conf['width'],$conf['width.']);
  657. $h = $this->stdWrap($conf['height'],$conf['height.']);
  658. $w = $w ? $w : 1;
  659. $h = $h ? $h : 1;
  660. $wrap = $conf['wrap'] ? $conf['wrap'] : '|<br />';
  661. $theValue = $this->wrap('<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$w.'" height="'.$h.'"'.$this->getBorderAttr(' border="0"').' alt="" title="" />', $wrap);
  662. return $this->stdWrap($theValue,$conf['stdWrap.']);
  663. }
  664. /**
  665. * Rendering the cObject, COBJ_ARRAY / COA and COBJ_ARRAY_INT
  666. *
  667. * @param array Array of TypoScript properties
  668. * @param string If "INT" then the cObject is a "COBJ_ARRAY_INT" (non-cached), otherwise just "COBJ_ARRAY" (cached)
  669. * @return string Output
  670. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=351&cHash=a09db0329c
  671. */
  672. function COBJ_ARRAY($conf,$ext='') {
  673. if (is_array($conf)) {
  674. $content = '';
  675. switch($ext) {
  676. case 'INT':
  677. $substKey = $ext . '_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
  678. $content .= '<!--'.$substKey.'-->';
  679. $GLOBALS['TSFE']->config[$ext . 'incScript'][$substKey] = array (
  680. 'file' => $conf['includeLibs'],
  681. 'conf' => $conf,
  682. 'cObj' => serialize($this),
  683. 'type' => 'COA'
  684. );
  685. break;
  686. default:
  687. if ($this->checkIf($conf['if.'])) {
  688. $this->includeLibs($conf);
  689. $content = $this->cObjGet($conf);
  690. if ($conf['wrap']) {
  691. $content = $this->wrap($content, $conf['wrap']);
  692. }
  693. if ($conf['stdWrap.']) {
  694. $content = $this->stdWrap($content, $conf['stdWrap.']);
  695. }
  696. }
  697. break;
  698. }
  699. return $content;
  700. } else {
  701. $GLOBALS['TT']->setTSlogMessage('No elements in this content object array (COBJ_ARRAY, COA, COA_INT).', 2);
  702. }
  703. }
  704. /**
  705. * Rendering the cObject, USER and USER_INT
  706. *
  707. * @param array Array of TypoScript properties
  708. * @param string If "INT" then the cObject is a "USER_INT" (non-cached), otherwise just "USER" (cached)
  709. * @return string Output
  710. * @link http://typo3.org/documentation/document-library/references/doc_core_tsref/4.1.0/view/8/22/
  711. */
  712. function USER($conf, $ext = '') {
  713. $content = '';
  714. switch ($ext) {
  715. case 'INT':
  716. $this->userObjectType = self::OBJECTTYPE_USER_INT;
  717. $substKey = $ext . '_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
  718. $content.='<!--' . $substKey . '-->';
  719. $GLOBALS['TSFE']->config[$ext . 'incScript'][$substKey] = array(
  720. 'file' => $conf['includeLibs'],
  721. 'conf' => $conf,
  722. 'cObj' => serialize($this),
  723. 'type' => 'FUNC'
  724. );
  725. break;
  726. default:
  727. if ($this->userObjectType === false) {
  728. // Come here only if we are not called from $TSFE->INTincScript_process()!
  729. $this->userObjectType = self::OBJECTTYPE_USER;
  730. }
  731. $this->includeLibs($conf);
  732. $tempContent = $this->callUserFunction($conf['userFunc'], $conf, '');
  733. if ($this->doConvertToUserIntObject) {
  734. $this->doConvertToUserIntObject = false;
  735. $content = $this->USER($conf, 'INT');
  736. } else {
  737. $content .= $tempContent;
  738. }
  739. break;
  740. }
  741. $this->userObjectType = false;
  742. return $content;
  743. }
  744. /**
  745. * Retrieves a type of object called as USER or USER_INT. Object can detect their
  746. * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the
  747. * current object execution. In all other cases it will return false to indicate
  748. * a call out of context.
  749. *
  750. * @return mixed One of OBJECTTYPE_ class constants or false
  751. */
  752. public function getUserObjectType() {
  753. return $this->userObjectType;
  754. }
  755. /**
  756. * Requests the current USER object to be converted to USER_INT.
  757. *
  758. * @return void
  759. */
  760. public function convertToUserIntObject() {
  761. if ($this->userObjectType !== self::OBJECTTYPE_USER) {
  762. $GLOBALS['TT']->setTSlogMessage('tslib_cObj::convertToUserIntObject() ' .
  763. 'is called in the wrong context or for the wrong object type', 2);
  764. }
  765. else {
  766. $this->doConvertToUserIntObject = true;
  767. }
  768. }
  769. /**
  770. * Rendering the cObject, FILE
  771. *
  772. * @param array Array of TypoScript properties
  773. * @return string Output
  774. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=352&cHash=379c60f8bc
  775. */
  776. function FILE($conf) {
  777. $theValue = $this->fileResource($this->stdWrap($conf['file'],$conf['file.']), trim($this->getAltParam($conf, false)));
  778. if ($conf['linkWrap']) {
  779. $theValue = $this->linkWrap($theValue,$conf['linkWrap']);
  780. }
  781. return $this->wrap($theValue,$conf['wrap']);
  782. }
  783. /**
  784. * Rendering the cObject, IMAGE
  785. *
  786. * @param array Array of TypoScript properties
  787. * @return string Output
  788. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=353&cHash=440681ea56
  789. * @see cImage()
  790. */
  791. function IMAGE($conf) {
  792. $content='';
  793. if ($this->checkIf($conf['if.'])) {
  794. $theValue = $this->cImage($conf['file'],$conf);
  795. if ($conf['stdWrap.']) {
  796. $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
  797. }
  798. return $theValue;
  799. }
  800. }
  801. /**
  802. * Rendering the cObject, IMG_RESOURCE
  803. *
  804. * @param array Array of TypoScript properties
  805. * @return string Output
  806. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=354&cHash=46f9299706
  807. * @see getImgResource()
  808. */
  809. function IMG_RESOURCE($conf) {
  810. $GLOBALS['TSFE']->lastImgResourceInfo = $this->getImgResource($conf['file'],$conf['file.']);
  811. return $this->stdWrap($GLOBALS['TSFE']->lastImgResourceInfo[3],$conf['stdWrap.']);
  812. }
  813. /**
  814. * Rendering the cObject, IMGTEXT
  815. *
  816. * @param array Array of TypoScript properties
  817. * @return string Output
  818. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=363&cHash=cf2969bce1
  819. */
  820. function IMGTEXT($conf) {
  821. $content='';
  822. if (is_array($conf['text.'])) {
  823. $content.= $this->stdWrap($this->cObjGet($conf['text.'],'text.'),$conf['text.']); // this gets the surrounding content
  824. }
  825. $imgList=trim($this->stdWrap($conf['imgList'],$conf['imgList.'])); // gets images
  826. if ($imgList) {
  827. $imgs = t3lib_div::trimExplode(',',$imgList);
  828. $imgStart = intval($this->stdWrap($conf['imgStart'],$conf['imgStart.']));
  829. $imgCount= count($imgs)-$imgStart;
  830. $imgMax = intval($this->stdWrap($conf['imgMax'],$conf['imgMax.']));
  831. if ($imgMax) {
  832. $imgCount = t3lib_div::intInRange($imgCount,0,$imgMax); // reduces the number of images.
  833. }
  834. $imgPath = $this->stdWrap($conf['imgPath'],$conf['imgPath.']);
  835. // initialisation
  836. $caption='';
  837. $captionArray = array();
  838. if (!$conf['captionSplit'] && !$conf['imageTextSplit'] && is_array($conf['caption.'])) {
  839. $caption = $this->stdWrap($this->cObjGet($conf['caption.'], 'caption.'),$conf['caption.']); // global caption, no splitting
  840. }
  841. if ($conf['captionSplit'] && $conf['captionSplit.']['cObject']) {
  842. $legacyCaptionSplit = 1;
  843. $capSplit = $this->stdWrap($conf['captionSplit.']['token'], $conf['captionSplit.']['token.']);
  844. if (!$capSplit) {$capSplit=LF;}
  845. $captionArray = explode($capSplit, $this->cObjGetSingle($conf['captionSplit.']['cObject'], $conf['captionSplit.']['cObject.'], 'captionSplit.cObject'));
  846. foreach ($captionArray as $ca_key => $ca_val) {
  847. $captionArray[$ca_key] = $this->stdWrap(trim($captionArray[$ca_key]), $conf['captionSplit.']['stdWrap.']);
  848. }
  849. }
  850. $tablecode='';
  851. $position=$this->stdWrap($conf['textPos'],$conf['textPos.']);
  852. $tmppos = $position&7;
  853. $contentPosition = $position&24;
  854. $align = $this->align[$tmppos];
  855. $cap = ($caption)?1:0;
  856. $txtMarg = intval($this->stdWrap($conf['textMargin'],$conf['textMargin.']));
  857. if (!$conf['textMargin_outOfText'] && $contentPosition<16) {
  858. $txtMarg=0;
  859. }
  860. $cols = intval($this->stdWrap($conf['cols'],$conf['cols.']));
  861. $rows = intval($this->stdWrap($conf['rows'],$conf['rows.']));
  862. $colspacing = intval($this->stdWrap($conf['colSpace'],$conf['colSpace.']));
  863. $rowspacing = intval($this->stdWrap($conf['rowSpace'],$conf['rowSpace.']));
  864. $border = intval($this->stdWrap($conf['border'],$conf['border.'])) ? 1:0;
  865. $borderColor = $this->stdWrap($conf['borderCol'],$conf['borderCol.']);
  866. $borderThickness = intval($this->stdWrap($conf['borderThick'],$conf['borderThick.']));
  867. $borderColor=$borderColor?$borderColor:'black';
  868. $borderThickness=$borderThickness?$borderThickness:1;
  869. $caption_align = $this->stdWrap($conf['captionAlign'],$conf['captionAlign.']);
  870. if (!$caption_align) {
  871. $caption_align = $align;
  872. }
  873. // generate cols
  874. $colCount = ($cols > 1) ? $cols : 1;
  875. if ($colCount > $imgCount) {$colCount = $imgCount;}
  876. $rowCount = ($colCount > 1) ? ceil($imgCount / $colCount) : $imgCount;
  877. // generate rows
  878. if ($rows>1) {
  879. $rowCount = $rows;
  880. if ($rowCount > $imgCount) {$rowCount = $imgCount;}
  881. $colCount = ($rowCount>1) ? ceil($imgCount / $rowCount) : $imgCount;
  882. }
  883. // max Width
  884. $colRelations = trim($this->stdWrap($conf['colRelations'],$conf['colRelations.']));
  885. $maxW = intval($this->stdWrap($conf['maxW'],$conf['maxW.']));
  886. $maxWInText = intval($this->stdWrap($conf['maxWInText'],$conf['maxWInText.']));
  887. if (!$maxWInText) { // If maxWInText is not set, it's calculated to the 50 % of the max...
  888. $maxWInText = round($maxW/2);
  889. }
  890. if ($maxWInText && $contentPosition>=16) { // inText
  891. $maxW = $maxWInText;
  892. }
  893. if ($maxW && $colCount > 0) { // If there is a max width and if colCount is greater than column
  894. /* debug($border*$borderThickness*2);
  895. debug($maxW);
  896. debug($colspacing);
  897. debug(($maxW-$colspacing*($colCount-1)-$colCount*$border*$borderThickness*2));
  898. */
  899. $maxW = ceil(($maxW-$colspacing*($colCount-1)-$colCount*$border*$borderThickness*2)/$colCount);
  900. }
  901. // create the relation between rows
  902. $colMaxW = Array();
  903. if ($colRelations) {
  904. $rel_parts = explode(':',$colRelations);
  905. $rel_total = 0;
  906. for ($a=0;$a<$colCount;$a++) {
  907. $rel_parts[$a] = intval($rel_parts[$a]);
  908. $rel_total+= $rel_parts[$a];
  909. }
  910. if ($rel_total) {
  911. for ($a=0;$a<$colCount;$a++) {
  912. $colMaxW[$a] = round(($maxW*$colCount)/$rel_total*$rel_parts[$a]);
  913. }
  914. if (min($colMaxW)<=0 || max($rel_parts)/min($rel_parts)>10) { // The difference in size between the largest and smalles must be within a factor of ten.
  915. $colMaxW = Array();
  916. }
  917. }
  918. }
  919. $image_compression = intval($this->stdWrap($conf['image_compression'],$conf['image_compression.']));
  920. $image_effects = intval($this->stdWrap($conf['image_effects'],$conf['image_effects.']));
  921. $image_frames = intval($this->stdWrap($conf['image_frames.']['key'],$conf['image_frames.']['key.']));
  922. // fetches pictures
  923. $splitArr=array();
  924. $splitArr['imgObjNum']=$conf['imgObjNum'];
  925. $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr,$imgCount);
  926. // EqualHeight
  927. $equalHeight = intval($this->stdWrap($conf['equalH'],$conf['equalH.']));
  928. if ($equalHeight) { // Initiate gifbuilder object in order to get dimensions AND calculate the imageWidth's
  929. $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
  930. $gifCreator->init();
  931. $relations = Array();
  932. $relations_cols = Array();
  933. $totalMaxW = $maxW*$colCount;
  934. for($a=0;$a<$imgCount;$a++) {
  935. $imgKey = $a+$imgStart;
  936. $imgInfo = $gifCreator->getImageDimensions($imgPath.$imgs[$imgKey]);
  937. $relations[$a] = $imgInfo[1] / $equalHeight; // relationship between the original height and the wished height
  938. if ($relations[$a]) { // if relations is zero, then the addition of this value is omitted as the image is not expected to display because of some error.
  939. $relations_cols[floor($a/$colCount)] += $imgInfo[0]/$relations[$a]; // counts the total width of the row with the new height taken into consideration.
  940. }
  941. }
  942. }
  943. $imageRowsFinalWidths = Array(); // contains the width of every image row
  944. $imageRowsMaxHeights = Array();
  945. $imgsTag=array();
  946. $origImages=array();
  947. for($a=0;$a<$imgCount;$a++) {
  948. $GLOBALS['TSFE']->register['IMAGE_NUM'] = $a;
  949. $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $a;
  950. $imgKey = $a+$imgStart;
  951. $totalImagePath = $imgPath.$imgs[$imgKey];
  952. $this->data[$this->currentValKey] = $totalImagePath;
  953. $imgObjNum = intval($splitArr[$a]['imgObjNum']);
  954. $imgConf = $conf[$imgObjNum.'.'];
  955. if ($equalHeight) {
  956. $scale = 1;
  957. if ($totalMaxW) {
  958. $rowTotalMaxW = $relations_cols[floor($a/$colCount)];
  959. if ($rowTotalMaxW > $totalMaxW) {
  960. $scale = $rowTotalMaxW / $totalMaxW;
  961. }
  962. }
  963. // transfer info to the imageObject. Please note, that
  964. $imgConf['file.']['height'] = round($equalHeight/$scale);
  965. unset($imgConf['file.']['width']);
  966. unset($imgConf['file.']['maxW']);
  967. unset($imgConf['file.']['maxH']);
  968. unset($imgConf['file.']['minW']);
  969. unset($imgConf['file.']['minH']);
  970. unset($imgConf['file.']['width.']);
  971. unset($imgConf['file.']['maxW.']);
  972. unset($imgConf['file.']['maxH.']);
  973. unset($imgConf['file.']['minW.']);
  974. unset($imgConf['file.']['minH.']);
  975. $maxW = 0; // setting this to zero, so that it doesn't disturb
  976. }
  977. if ($maxW) {
  978. if (count($colMaxW)) {
  979. $imgConf['file.']['maxW'] = $colMaxW[($a%$colCount)];
  980. } else {
  981. $imgConf['file.']['maxW'] = $maxW;
  982. }
  983. }
  984. // Image Object supplied:
  985. if (is_array($imgConf)) {
  986. if ($this->image_effects[$image_effects]) {
  987. $imgConf['file.']['params'].= ' '.$this->image_effects[$image_effects];
  988. }
  989. if ($image_frames) {
  990. if (is_array($conf['image_frames.'][$image_frames.'.'])) {
  991. $imgConf['file.']['m.'] = $conf['image_frames.'][$image_frames.'.'];
  992. }
  993. }
  994. if ($image_compression && $imgConf['file']!='GIFBUILDER') {
  995. if ($image_compression==1) {
  996. $tempImport = $imgConf['file.']['import'];
  997. $tempImport_dot = $imgConf['file.']['import.'];
  998. unset($imgConf['file.']);
  999. $imgConf['file.']['import'] = $tempImport;
  1000. $imgConf['file.']['import.'] = $tempImport_dot;
  1001. } elseif (isset($this->image_compression[$image_compression])) {
  1002. $imgConf['file.']['params'].= ' '.$this->image_compression[$image_compression]['params'];
  1003. $imgConf['file.']['ext'] = $this->image_compression[$image_compression]['ext'];
  1004. unset($imgConf['file.']['ext.']);
  1005. }
  1006. }
  1007. // "alt", "title" and "longdesc" attributes:
  1008. if (!strlen($imgConf['altText']) && !is_array($imgConf['altText.'])) {
  1009. $imgConf['altText'] = $conf['altText'];
  1010. $imgConf['altText.'] = $conf['altText.'];
  1011. }
  1012. if (!strlen($imgConf['titleText']) && !is_array($imgConf['titleText.'])) {
  1013. $imgConf['titleText'] = $conf['titleText'];
  1014. $imgConf['titleText.'] = $conf['titleText.'];
  1015. }
  1016. if (!strlen($imgConf['longdescURL']) && !is_array($imgConf['longdescURL.'])) {
  1017. $imgConf['longdescURL'] = $conf['longdescURL'];
  1018. $imgConf['longdescURL.'] = $conf['longdescURL.'];
  1019. }
  1020. } else {
  1021. $imgConf = array(
  1022. 'altText' => $conf['altText'],
  1023. 'titleText' => $conf['titleText'],
  1024. 'longdescURL' => $conf['longdescURL'],
  1025. 'file' => $totalImagePath
  1026. );
  1027. }
  1028. $imgsTag[$imgKey] = $this->IMAGE($imgConf);
  1029. // Store the original filepath
  1030. $origImages[$imgKey]=$GLOBALS['TSFE']->lastImageInfo;
  1031. $imageRowsFinalWidths[floor($a/$colCount)] += $GLOBALS['TSFE']->lastImageInfo[0];
  1032. if ($GLOBALS['TSFE']->lastImageInfo[1]>$imageRowsMaxHeights[floor($a/$colCount)]) {
  1033. $imageRowsMaxHeights[floor($a/$colCount)] = $GLOBALS['TSFE']->lastImageInfo[1];
  1034. }
  1035. }
  1036. // calculating the tableWidth:
  1037. // TableWidth problems: It creates problems if the pictures are NOT as wide as the tableWidth.
  1038. $tableWidth = max($imageRowsFinalWidths)+ $colspacing*($colCount-1) + $colCount*$border*$borderThickness*2;
  1039. // make table for pictures
  1040. $index=$imgStart;
  1041. $noRows = $this->stdWrap($conf['noRows'],$conf['noRows.']);
  1042. $noCols = $this->stdWrap($conf['noCols'],$conf['noCols.']);
  1043. if ($noRows) {$noCols=0;} // noRows overrides noCols. They cannot exist at the same time.
  1044. if ($equalHeight) {
  1045. $noCols=1;
  1046. $noRows=0;
  1047. }
  1048. $rowCount_temp=1;
  1049. $colCount_temp=$colCount;
  1050. if ($noRows) {
  1051. $rowCount_temp = $rowCount;
  1052. $rowCount=1;
  1053. }
  1054. if ($noCols) {
  1055. $colCount=1;
  1056. }
  1057. // col- and rowspans calculated
  1058. $colspan = (($colspacing) ? $colCount*2-1 : $colCount);
  1059. $rowspan = (($rowspacing) ? $rowCount*2-1 : $rowCount) + $cap;
  1060. // Edit icons:
  1061. $editIconsHTML = $conf['editIcons']&&$GLOBALS['TSFE']->beUserLogin ? $this->editIcons('',$conf['editIcons'],$conf['editIcons.']) : '';
  1062. // strech out table:
  1063. $tablecode='';
  1064. $flag=0;
  1065. if ($conf['noStretchAndMarginCells']!=1) {
  1066. $tablecode.='<tr>';
  1067. if ($txtMarg && $align=='right') { // If right aligned, the textborder is added on the right side
  1068. $tablecode.='<td rowspan="'.($rowspan+1).'" valign="top"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$txtMarg.'" height="1" alt="" title="" />'.($editIconsHTML?'<br />'.$editIconsHTML:'').'</td>';
  1069. $editIconsHTML='';
  1070. $flag=1;
  1071. }
  1072. $tablecode.='<td colspan="'.$colspan.'"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$tableWidth.'" height="1" alt="" /></td>';
  1073. if ($txtMarg && $align=='left') { // If left aligned, the textborder is added on the left side
  1074. $tablecode.='<td rowspan="'.($rowspan+1).'" valign="top"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$txtMarg.'" height="1" alt="" title="" />'.($editIconsHTML?'<br />'.$editIconsHTML:'').'</td>';
  1075. $editIconsHTML='';
  1076. $flag=1;
  1077. }
  1078. if ($flag) $tableWidth+=$txtMarg+1;
  1079. // $tableWidth=0;
  1080. $tablecode.='</tr>';
  1081. }
  1082. // draw table
  1083. for ($c=0;$c<$rowCount;$c++) { // Looping through rows. If 'noRows' is set, this is '1 time', but $rowCount_temp will hold the actual number of rows!
  1084. if ($c && $rowspacing) { // If this is NOT the first time in the loop AND if space is required, a row-spacer is added. In case of "noRows" rowspacing is done further down.
  1085. $tablecode.='<tr><td colspan="'.$colspan.'"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$rowspacing.'"'.$this->getBorderAttr(' border="0"').' alt="" title="" /></td></tr>';
  1086. }
  1087. $tablecode.='<tr>'; // starting row
  1088. for ($b=0; $b<$colCount_temp; $b++) { // Looping through the columns
  1089. if ($b && $colspacing) { // If this is NOT the first iteration AND if column space is required. In case of "noCols", the space is done without a separate cell.
  1090. if (!$noCols) {
  1091. $tablecode.='<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$colspacing.'" height="1"'.$this->getBorderAttr(' border="0"').' alt="" title="" /></td>';
  1092. } else {
  1093. $colSpacer='<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.($border?$colspacing-6:$colspacing).'" height="'.($imageRowsMaxHeights[$c]+($border?$borderThickness*2:0)).'"'.$this->getBorderAttr(' border="0"').' align="'.($border?'left':'top').'" alt="" title="" />';
  1094. $colSpacer='<td valign="top">'.$colSpacer.'</td>'; // added 160301, needed for the new "noCols"-table...
  1095. $tablecode.=$colSpacer;
  1096. }
  1097. }
  1098. if (!$noCols || ($noCols && !$b)) {
  1099. $tablecode.='<td valign="top">'; // starting the cell. If "noCols" this cell will hold all images in the row, otherwise only a single image.
  1100. if ($noCols) {$tablecode.='<table width="'.$imageRowsFinalWidths[$c].'" border="0" cellpadding="0" cellspacing="0"><tr>';} // In case of "noCols" we must set the table-tag that surrounds the images in the row.
  1101. }
  1102. for ($a=0;$a<$rowCount_temp;$a++) { // Looping through the rows IF "noRows" is set. "noRows" means that the rows of images is not rendered by physical table rows but images are all in one column and spaced apart with clear-gifs. This loop is only one time if "noRows" is not set.
  1103. $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgIndex; // register previous imgIndex
  1104. $imgIndex = $index+$a*$colCount_temp;
  1105. $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgIndex;
  1106. if ($imgsTag[$imgIndex]) {
  1107. if ($rowspacing && $noRows && $a) { // Puts distance between the images IF "noRows" is set and this is the first iteration of the loop
  1108. $tablecode.= '<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$rowspacing.'" alt="" title="" /><br />';
  1109. }
  1110. if ($legacyCaptionSplit) {
  1111. $thisCaption = $captionArray[$imgIndex];
  1112. } else if ($conf['captionSplit'] || $conf['imageTextSplit']) {
  1113. $thisCaption = $this->stdWrap($this->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
  1114. }
  1115. $imageHTML = $imgsTag[$imgIndex].'<br />';
  1116. $Talign = (!trim($thisCaption) && !$noRows) ? ' align="left"' : ''; // this is necessary if the tablerows are supposed to space properly together! "noRows" is excluded because else the images "layer" together.
  1117. if ($border) {$imageHTML='<table border="0" cellpadding="'.$borderThickness.'" cellspacing="0" bgcolor="'.$borderColor.'"'.$Talign.'><tr><td>'.$imageHTML.'</td></tr></table>';}
  1118. $imageHTML.=$editIconsHTML;
  1119. $editIconsHTML='';
  1120. $imageHTML.=$thisCaption; // Adds caption.
  1121. if ($noCols) {$imageHTML='<td valign="top">'.$imageHTML.'</td>';} // If noCols, put in table cell.
  1122. $tablecode.=$imageHTML;
  1123. }
  1124. }
  1125. $index++;
  1126. if (!$noCols || ($noCols && $b+1==$colCount_temp)) {
  1127. if ($noCols) {$tablecode.='</tr></table>';} // In case of "noCols" we must finish the table that surrounds the images in the row.
  1128. $tablecode.='</td>'; // Ending the cell. In case of "noCols" the cell holds all pictures!
  1129. }
  1130. }
  1131. $tablecode.='</tr>'; // ending row
  1132. }
  1133. if ($c) {
  1134. switch ($contentPosition) {
  1135. case '0': // above
  1136. case '8': // below
  1137. switch ($align) { // These settings are needed for Firefox
  1138. case 'center':
  1139. $table_align = 'margin-left: auto; margin-right: auto';
  1140. break;
  1141. case 'right':
  1142. $table_align = 'margin-left: auto; margin-right: 0px';
  1143. break;
  1144. default: // Most of all: left
  1145. $table_align = 'margin-left: 0px; margin-right: auto';
  1146. }
  1147. $table_align = 'style="'.$table_align.'"';
  1148. break;
  1149. case '16': // in text
  1150. $table_align = 'align="'.$align.'"';
  1151. break;
  1152. default:
  1153. $table_align = '';
  1154. }
  1155. // Table-tag is inserted
  1156. $tablecode = '<table'.($tableWidth?' width="'.$tableWidth.'"':'').' border="0" cellspacing="0" cellpadding="0" '.$table_align.' class="imgtext-table">'.$tablecode;
  1157. if ($editIconsHTML) { // IF this value is not long since reset.
  1158. $tablecode.='<tr><td colspan="'.$colspan.'">'.$editIconsHTML.'</td></tr>';
  1159. $editIconsHTML='';
  1160. }
  1161. if ($cap) {
  1162. $tablecode.='<tr><td colspan="'.$colspan.'" align="'.$caption_align.'">'.$caption.'</td></tr>';
  1163. }
  1164. $tablecode.='</table>';
  1165. if ($conf['tableStdWrap.']) {$tablecode=$this->stdWrap($tablecode,$conf['tableStdWrap.']);}
  1166. }
  1167. $spaceBelowAbove = intval($this->stdWrap($conf['spaceBelowAbove'],$conf['spaceBelowAbove.']));
  1168. switch ($contentPosition) {
  1169. case '0': // above
  1170. $output= '<div style="text-align:'.$align.';">'.$tablecode.'</div>'.$this->wrapSpace($content, $spaceBelowAbove.'|0');
  1171. break;
  1172. case '8': // below
  1173. $output= $this->wrapSpace($content, '0|'.$spaceBelowAbove).'<div style="text-align:'.$align.';">'.$tablecode.'</div>';
  1174. break;
  1175. case '16': // in text
  1176. $output= $tablecode.$content;
  1177. break;
  1178. case '24': // in text, no wrap
  1179. $theResult = '';
  1180. $theResult.= '<table border="0" cellspacing="0" cellpadding="0" class="imgtext-nowrap"><tr>';
  1181. if ($align=='right') {
  1182. $theResult.= '<td valign="top">'.$content.'</td><td valign="top">'.$tablecode.'</td>';
  1183. } else {
  1184. $theResult.= '<td valign="top">'.$tablecode.'</td><td valign="top">'.$content.'</td>';
  1185. }
  1186. $theResult.= '</tr></table>';
  1187. $output= $theResult;
  1188. break;
  1189. }
  1190. } else {
  1191. $output= $content;
  1192. }
  1193. if ($conf['stdWrap.']) {
  1194. $output = $this->stdWrap($output, $conf['stdWrap.']);
  1195. }
  1196. return $output;
  1197. }
  1198. /**
  1199. * Rendering the cObject, CONTENT
  1200. *
  1201. * @param array Array of TypoScript properties
  1202. * @return string Output
  1203. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=356&cHash=9f3b5c6ba2
  1204. */
  1205. function CONTENT($conf) {
  1206. $theValue='';
  1207. $originalRec = $GLOBALS['TSFE']->currentRecord;
  1208. if ($originalRec) { // If the currentRecord is set, we register, that this record has invoked this function. It's should not be allowed to do this again then!!
  1209. $GLOBALS['TSFE']->recordRegister[$originalRec]++;
  1210. }
  1211. $conf['table'] = trim($this->stdWrap($conf['table'], $conf['table.']));
  1212. if ($conf['table']=='pages' || substr($conf['table'],0,3)=='tt_' || substr($conf['table'],0,3)=='fe_' || substr($conf['table'],0,3)=='tx_' || substr($conf['table'],0,4)=='ttx_' || substr($conf['table'],0,5)=='user_' || substr($conf['table'],0,7)=='static_') {
  1213. $renderObjName = $conf['renderObj'] ? $conf['renderObj'] : '<'.$conf['table'];
  1214. $renderObjKey = $conf['renderObj'] ? 'renderObj' : '';
  1215. $renderObjConf = $conf['renderObj.'];
  1216. $slide = intval($conf['slide'])?intval($conf['slide']):0;
  1217. $slideCollect = intval($conf['slide.']['collect'])?intval($conf['slide.']['collect']):0;
  1218. $slideCollectReverse = intval($conf['slide.']['collectReverse'])?true:false;
  1219. $slideCollectFuzzy = $slideCollect?(intval($conf['slide.']['collectFuzzy'])?true:false):true;
  1220. $again = false;
  1221. do {
  1222. $res = $this->exec_getQuery($conf['table'],$conf['select.']);
  1223. if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
  1224. $GLOBALS['TT']->setTSlogMessage($error,3);
  1225. } else {
  1226. $this->currentRecordTotal = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
  1227. $GLOBALS['TT']->setTSlogMessage('NUMROWS: '.$GLOBALS['TYPO3_DB']->sql_num_rows($res));
  1228. $cObj =t3lib_div::makeInstance('tslib_cObj');
  1229. $cObj->setParent($this->data,$this->currentRecord);
  1230. $this->currentRecordNumber=0;
  1231. $cobjValue = '';
  1232. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1233. // Versioning preview:
  1234. $GLOBALS['TSFE']->sys_page->versionOL($conf['table'],$row,TRUE);
  1235. // Language overlay:
  1236. if (is_array($row) && $GLOBALS['TSFE']->sys_language_contentOL) {
  1237. $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay($conf['table'],$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_contentOL);
  1238. }
  1239. if (is_array($row)) { // Might be unset in the sys_language_contentOL
  1240. if (!$GLOBALS['TSFE']->recordRegister[$conf['table'].':'.$row['uid']]) {
  1241. $this->currentRecordNumber++;
  1242. $cObj->parentRecordNumber = $this->currentRecordNumber;
  1243. $GLOBALS['TSFE']->currentRecord = $conf['table'].':'.$row['uid'];
  1244. $this->lastChanged($row['tstamp']);
  1245. $cObj->start($row,$conf['table']);
  1246. $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
  1247. $cobjValue .= $tmpValue;
  1248. }
  1249. }
  1250. }
  1251. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  1252. }
  1253. if ($slideCollectReverse) {
  1254. $theValue = $cobjValue.$theValue;
  1255. } else {
  1256. $theValue .= $cobjValue;
  1257. }
  1258. if ($slideCollect>0) {
  1259. $slideCollect--;
  1260. }
  1261. if ($slide) {
  1262. if ($slide>0) {
  1263. $slide--;
  1264. }
  1265. $conf['select.']['pidInList'] = $this->getSlidePids($conf['select.']['pidInList'], $conf['select.']['pidInList.']);
  1266. $again = strlen($conf['select.']['pidInList'])?true:false;
  1267. }
  1268. } while ($again&&(($slide&&!strlen($tmpValue)&&$slideCollectFuzzy)||($slide&&$slideCollect)));
  1269. }
  1270. $theValue = $this->wrap($theValue,$conf['wrap']);
  1271. if ($conf['stdWrap.']) $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
  1272. $GLOBALS['TSFE']->currentRecord = $originalRec; // Restore
  1273. return $theValue;
  1274. }
  1275. /**
  1276. * Rendering the cObject, RECORDS
  1277. *
  1278. * @param array Array of TypoScript properties
  1279. * @return string Output
  1280. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=357&cHash=303e959472
  1281. */
  1282. function RECORDS($conf) {
  1283. $theValue='';
  1284. $originalRec = $GLOBALS['TSFE']->currentRecord;
  1285. if ($originalRec) { // If the currentRecord is set, we register, that this record has invoked this function. It's should not be allowed to do this again then!!
  1286. $GLOBALS['TSFE']->recordRegister[$originalRec]++;
  1287. }
  1288. $conf['source'] = $this->stdWrap($conf['source'],$conf['source.']);
  1289. if ($conf['tables'] && $conf['source']) {
  1290. $allowedTables = $conf['tables'];
  1291. if (is_array($conf['conf.'])) {
  1292. foreach ($conf['conf.'] as $k => $v) {
  1293. if (substr($k,-1)!='.') $allowedTables.=','.$k;
  1294. }
  1295. }
  1296. $loadDB = t3lib_div::makeInstance('FE_loadDBGroup');
  1297. $loadDB->start($conf['source'], $allowedTables);
  1298. foreach ($loadDB->tableArray as $table => $v) {
  1299. if (is_array($GLOBALS['TCA'][$table])) {
  1300. $loadDB->additionalWhere[$table]=$this->enableFields($table);
  1301. }
  1302. }
  1303. $loadDB->getFromDB();
  1304. reset($loadDB->itemArray);
  1305. $data = $loadDB->results;
  1306. $cObj =t3lib_div::makeInstance('tslib_cObj');
  1307. $cObj->setParent($this->data,$this->currentRecord);
  1308. $this->currentRecordNumber=0;
  1309. $this->currentRecordTotal = count($loadDB->itemArray);
  1310. foreach ($loadDB->itemArray as $val) {
  1311. $row = $data[$val['table']][$val['id']];
  1312. // Versioning preview:
  1313. $GLOBALS['TSFE']->sys_page->versionOL($val['table'],$row);
  1314. // Language overlay:
  1315. if (is_array($row) && $GLOBALS['TSFE']->sys_language_contentOL) {
  1316. $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay($val['table'],$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_contentOL);
  1317. }
  1318. if (is_array($row)) { // Might be unset in the content overlay things...
  1319. if (!$conf['dontCheckPid']) {
  1320. $row = $this->checkPid($row['pid']) ? $row : '';
  1321. }
  1322. if ($row && !$GLOBALS['TSFE']->recordRegister[$val['table'].':'.$val['id']]) {
  1323. $renderObjName = $conf['conf.'][$val['table']] ? $conf['conf.'][$val['table']] : '<'.$val['table'];
  1324. $renderObjKey = $conf['conf.'][$val['table']] ? 'conf.'.$val['table'] : '';
  1325. $renderObjConf = $conf['conf.'][$val['table'].'.'];
  1326. $this->currentRecordNumber++;
  1327. $cObj->parentRecordNumber=$this->currentRecordNumber;
  1328. $GLOBALS['TSFE']->currentRecord = $val['table'].':'.$val['id'];
  1329. $this->lastChanged($row['tstamp']);
  1330. $cObj->start($row,$val['table']);
  1331. $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
  1332. $theValue .= $tmpValue;
  1333. }# else debug($GLOBALS['TSFE']->recordRegister,'RECORDS');
  1334. }
  1335. }
  1336. }
  1337. if ($conf['wrap']) $theValue = $this->wrap($theValue,$conf['wrap']);
  1338. if ($conf['stdWrap.']) $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
  1339. $GLOBALS['TSFE']->currentRecord = $originalRec; // Restore
  1340. return $theValue;
  1341. }
  1342. /**
  1343. * Rendering the cObject, HMENU
  1344. *
  1345. * @param array Array of TypoScript properties
  1346. * @return string Output
  1347. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=358&cHash=5400c1c06a
  1348. */
  1349. function HMENU($conf) {
  1350. $content='';
  1351. if ($this->checkIf($conf['if.'])) {
  1352. $cls = strtolower($conf[1]);
  1353. if (t3lib_div::inList($GLOBALS['TSFE']->tmpl->menuclasses,$cls)) {
  1354. if ($conf['special.']['value.']) {
  1355. $conf['special.']['value'] = $this->stdWrap($conf['special.']['value'], $conf['special.']['value.']);
  1356. }
  1357. $GLOBALS['TSFE']->register['count_HMENU']++;
  1358. $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']=0;
  1359. $GLOBALS['TSFE']->applicationData['GMENU_LAYERS']['WMid']=array();
  1360. $GLOBALS['TSFE']->applicationData['GMENU_LAYERS']['WMparentId']=array();
  1361. $menu = t3lib_div::makeInstance('tslib_'.$cls);
  1362. $menu->parent_cObj = $this;
  1363. $menu->start($GLOBALS['TSFE']->tmpl, $GLOBALS['TSFE']->sys_page, '', $conf, 1);
  1364. $menu->makeMenu();
  1365. $content.=$menu->writeMenu();
  1366. }
  1367. if ($conf['wrap']) $content=$this->wrap($content, $conf['wrap']);
  1368. if ($conf['stdWrap.']) $content = $this->stdWrap($content, $conf['stdWrap.']);
  1369. }
  1370. return $content;
  1371. }
  1372. /**
  1373. * Rendering the cObject, CTABLE
  1374. *
  1375. * @param array Array of TypoScript properties
  1376. * @return string Output
  1377. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=359&cHash=2e0065b4e7
  1378. */
  1379. function CTABLE ($conf) {
  1380. $controlTable = t3lib_div::makeInstance('tslib_controlTable');
  1381. if ($conf['tableParams']) {
  1382. $controlTable->tableParams = $conf['tableParams'];
  1383. }
  1384. // loads the pagecontent
  1385. $controlTable->contentW = $conf['cWidth'];
  1386. // loads the menues if any
  1387. if (is_array($conf['c.'])) {
  1388. $controlTable->content = $this->cObjGet($conf['c.'],'c.');
  1389. $controlTable->contentTDparams = isset($conf['c.']['TDParams']) ? $conf['c.']['TDParams'] : 'valign="top"';
  1390. }
  1391. if (is_array($conf['lm.'])) {
  1392. $controlTable->lm = $this->cObjGet($conf['lm.'],'lm.');
  1393. $controlTable->lmTDparams = isset($conf['lm.']['TDParams']) ? $conf['lm.']['TDParams'] : 'valign="top"';
  1394. }
  1395. if (is_array($conf['tm.'])) {
  1396. $controlTable->tm = $this->cObjGet($conf['tm.'],'tm.');
  1397. $controlTable->tmTDparams = isset($conf['tm.']['TDParams']) ? $conf['tm.']['TDParams'] : 'valign="top"';
  1398. }
  1399. if (is_array($conf['rm.'])) {
  1400. $controlTable->rm = $this->cObjGet($conf['rm.'],'rm.');
  1401. $controlTable->rmTDparams = isset($conf['rm.']['TDParams']) ? $conf['rm.']['TDParams'] : 'valign="top"';
  1402. }
  1403. if (is_array($conf['bm.'])) {
  1404. $controlTable->bm = $this->cObjGet($conf['bm.'],'bm.');
  1405. $controlTable->bmTDparams = isset($conf['bm.']['TDParams']) ? $conf['bm.']['TDParams'] : 'valign="top"';
  1406. }
  1407. return $controlTable->start($conf['offset'],$conf['cMargins']);
  1408. }
  1409. /**
  1410. * Rendering the cObject, OTABLE
  1411. *
  1412. * @param array Array of TypoScript properties
  1413. * @return string Output
  1414. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=360&cHash=02c9552d38
  1415. */
  1416. function OTABLE ($conf) {
  1417. $controlTable = t3lib_div::makeInstance('tslib_tableOffset');
  1418. if ($conf['tableParams']) {
  1419. $controlTable->tableParams = $conf['tableParams'];
  1420. }
  1421. return $controlTable->start($this->cObjGet($conf),$conf['offset']);
  1422. }
  1423. /**
  1424. * Rendering the cObject, COLUMNS
  1425. *
  1426. * @param array Array of TypoScript properties
  1427. * @return string Output
  1428. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=361&cHash=7e4e228cad
  1429. */
  1430. function COLUMNS ($conf) {
  1431. $content='';
  1432. if (is_array($conf) && $this->checkIf($conf['if.'])) {
  1433. $tdRowCount=0;
  1434. $tableParams = $conf['tableParams'] ? ' '.$conf['tableParams'] : ' border="0" cellspacing="0" cellpadding="0"';
  1435. $TDparams = $conf['TDparams'] ? ' '.$conf['TDparams']:' valign="top"';
  1436. $rows = t3lib_div::intInRange($conf['rows'],2,20);
  1437. $totalWidth = intval($conf['totalWidth']);
  1438. $columnWidth=0;
  1439. $totalGapWidth=0;
  1440. $gapData = Array(
  1441. 'gapWidth' => $this->stdWrap($conf['gapWidth'],$conf['gapWidth.']),
  1442. 'gapBgCol' => $this->stdWrap($conf['gapBgCol'],$conf['gapBgCol.']),
  1443. 'gapLineThickness' => $this->stdWrap($conf['gapLineThickness'],$conf['gapLineThickness.']),
  1444. 'gapLineCol' => $this->stdWrap($conf['gapLineCol'],$conf['gapLineCol.'])
  1445. );
  1446. $gapData = $GLOBALS['TSFE']->tmpl->splitConfArray($gapData,$rows-1);
  1447. foreach ($gapData as $val) {
  1448. $totalGapWidth+=intval($val['gapWidth']);
  1449. }
  1450. if ($totalWidth) {
  1451. $columnWidth = ceil(($totalWidth-$totalGapWidth)/$rows);
  1452. $TDparams.=' width="'.$columnWidth.'"';
  1453. $tableParams.=' width="'.$totalWidth.'"';
  1454. } else {
  1455. $TDparams.=' width="'.floor(100/$rows).'%"';
  1456. $tableParams.=' width="100%"';
  1457. }
  1458. for ($a=1;$a<=$rows;$a++) {
  1459. $tdRowCount++;
  1460. $content.='<td'.$TDparams.'>';
  1461. $content.=$this->cObjGetSingle($conf[$a],$conf[$a.'.'], $a);
  1462. $content.='</td>';
  1463. if ($a < $rows) {
  1464. $gapConf = $gapData[($a-1)];
  1465. $gapWidth = intval($gapConf['gapWidth']);
  1466. if ($gapWidth) {
  1467. $tdPar = $gapConf['gapBgCol'] ? ' bgcolor="'.$gapConf['gapBgCol'].'"' : '';
  1468. $gapLine = intval($gapConf['gapLineThickness']);
  1469. if ($gapLine) {
  1470. $gapSurround = t3lib_div::intInRange(($gapWidth-$gapLine)/2, 1, 1000);
  1471. // right gap
  1472. $content.='<td'.$tdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapSurround.'" height="1" alt="" title="" /></td>';
  1473. $tdRowCount++;
  1474. // line:
  1475. $GtdPar = $gapConf['gapLineCol'] ? ' bgcolor="'.$gapConf['gapLineCol'].'"' : ' bgcolor="black"';
  1476. $content.='<td'.$GtdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapLine.'" height="1" alt="" title="" /></td>';
  1477. $tdRowCount++;
  1478. // left gap
  1479. $content.='<td'.$tdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapSurround.'" height="1" alt="" title="" /></td>';
  1480. $tdRowCount++;
  1481. } else {
  1482. $content.='<td'.$tdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapWidth.'" height="1" alt="" title="" /></td>';
  1483. $tdRowCount++;
  1484. }
  1485. }
  1486. }
  1487. }
  1488. $content = '<tr>'.$content.'</tr>';
  1489. $content = '<table'.$tableParams.'>'.$content.'</table>';
  1490. $content.= $this->cObjGetSingle($conf['after'],$conf['after.'], 'after');
  1491. if ($conf['stdWrap.']) {
  1492. $content = $this->stdWrap($content,$conf['stdWrap.']);
  1493. }
  1494. }
  1495. return $content;
  1496. }
  1497. /**
  1498. * Rendering the cObject, HRULER
  1499. *
  1500. * @param array Array of TypoScript properties
  1501. * @return string Output
  1502. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=362&cHash=2a462aa084
  1503. */
  1504. function HRULER ($conf) {
  1505. $lineThickness = t3lib_div::intInRange($this->stdWrap($conf['lineThickness'],$conf['lineThickness.']),1,50);
  1506. $lineColor = $conf['lineColor'] ? $conf['lineColor'] : 'black';
  1507. $spaceBefore = intval($conf['spaceLeft']);
  1508. $spaceAfter = intval($conf['spaceRight']);
  1509. $tableWidth = $conf['tableWidth'] ? $conf['tableWidth'] : '99%';
  1510. $content='';
  1511. $content.='<table border="0" cellspacing="0" cellpadding="0" width="'.htmlspecialchars($tableWidth).'" summary=""><tr>';
  1512. if ($spaceBefore) {$content.='<td width="1"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$spaceBefore.'" height="1" alt="" title="" /></td>'; }
  1513. $content.='<td bgcolor="'.$lineColor.'"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$lineThickness.'" alt="" title="" /></td>';
  1514. if ($spaceAfter) {$content.='<td width="1"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$spaceAfter.'" height="1" alt="" title="" /></td>'; }
  1515. $content.='</tr></table>';
  1516. $content = $this->stdWrap($content, $conf['stdWrap.']);
  1517. return $content;
  1518. }
  1519. /**
  1520. * Rendering the cObject, CASE
  1521. *
  1522. * @param array Array of TypoScript properties
  1523. * @return string Output
  1524. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=364&cHash=cffedd09e3
  1525. */
  1526. function CASEFUNC ($conf){
  1527. $content='';
  1528. if ($this->checkIf($conf['if.'])) {
  1529. if ($conf['setCurrent'] || $conf['setCurrent.']){$this->data[$this->currentValKey] = $this->stdWrap($conf['setCurrent'], $conf['setCurrent.']);}
  1530. $key = $this->stdWrap($conf['key'],$conf['key.']);
  1531. $key = strlen($conf[$key]) ? $key : 'default';
  1532. $name = $conf[$key];
  1533. $theValue = $this->cObjGetSingle($name,$conf[$key.'.'], $key);
  1534. if ($conf['stdWrap.']) {
  1535. $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
  1536. }
  1537. return $theValue;
  1538. }
  1539. }
  1540. /**
  1541. * Rendering the cObject, LOAD_REGISTER and RESTORE_REGISTER
  1542. * NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
  1543. *
  1544. * @param array Array of TypoScript properties
  1545. * @param string If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER"
  1546. * @return string Empty string (the cObject only sets internal data!)
  1547. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=365&cHash=4935524e2e
  1548. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=366&cHash=4f9485e8cc
  1549. */
  1550. function LOAD_REGISTER($conf,$name) {
  1551. if ($name=='RESTORE_REGISTER') {
  1552. $GLOBALS['TSFE']->register = array_pop($GLOBALS['TSFE']->registerStack);
  1553. } else {
  1554. array_push($GLOBALS['TSFE']->registerStack,$GLOBALS['TSFE']->register);
  1555. if (is_array($conf)) {
  1556. foreach ($conf as $theKey => $theValue) {
  1557. if (!strstr($theKey,'.') || !isset($conf[substr($theKey,0,-1)])) { // Only if 1) the property is set but not the value itself, 2) the value and/or any property
  1558. if (strstr($theKey,'.')) {
  1559. $theKey = substr($theKey,0,-1);
  1560. }
  1561. $GLOBALS['TSFE']->register[$theKey] = $this->stdWrap($conf[$theKey],$conf[$theKey.'.']);
  1562. }
  1563. }
  1564. }
  1565. }
  1566. return '';
  1567. }
  1568. /**
  1569. * Rendering the cObject, FORM
  1570. *
  1571. * Note on $formData:
  1572. * In the optional $formData array each entry represents a line in the ordinary setup.
  1573. * In those entries each entry (0,1,2...) represents a space normally divided by the '|' line.
  1574. *
  1575. * $formData [] = array('Name:', 'name=input, 25 ', 'Default value....');
  1576. * $formData [] = array('Email:', 'email=input, 25 ', 'Default value for email....');
  1577. *
  1578. * - corresponds to the $conf['data'] value being :
  1579. * Name:|name=input, 25 |Default value....||Email:|email=input, 25 |Default value for email....
  1580. *
  1581. * If $formData is an array the value of $conf['data'] is ignored.
  1582. *
  1583. * @param array Array of TypoScript properties
  1584. * @param array Alternative formdata overriding whatever comes from TypoScript
  1585. * @return string Output
  1586. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=367&cHash=bbc518d930
  1587. */
  1588. function FORM($conf,$formData='') {
  1589. $content='';
  1590. if (is_array($formData)) {
  1591. $dataArr = $formData;
  1592. } else {
  1593. $data = $this->stdWrap($conf['data'],$conf['data.']);
  1594. // Clearing dataArr
  1595. $dataArr = array();
  1596. // Getting the original config
  1597. if (trim($data)) {
  1598. $data = str_replace(LF,'||',$data);
  1599. $dataArr = explode('||',$data);
  1600. }
  1601. // Adding the new dataArray config form:
  1602. if (is_array($conf['dataArray.'])) { // dataArray is supplied
  1603. $sKeyArray = t3lib_TStemplate::sortedKeyList($conf['dataArray.'], TRUE);
  1604. foreach ($sKeyArray as $theKey) {
  1605. $dAA = $conf['dataArray.'][$theKey.'.'];
  1606. if (is_array($dAA)) {
  1607. $temp = array();
  1608. list($temp[0]) = explode('|',$dAA['label.'] ? $this->stdWrap($dAA['label'],$dAA['label.']) : $dAA['label']);
  1609. list($temp[1]) = explode('|',$dAA['type']);
  1610. if ($dAA['required']) {
  1611. $temp[1] = '*'.$temp[1];
  1612. }
  1613. list($temp[2]) = explode('|',$dAA['value.'] ? $this->stdWrap($dAA['value'],$dAA['value.']) : $dAA['value']);
  1614. // If value Array is set, then implode those values.
  1615. if (is_array($dAA['valueArray.'])) {
  1616. $temp_accum = array();
  1617. foreach ($dAA['valueArray.'] as $dAKey_vA => $dAA_vA) {
  1618. if (is_array($dAA_vA) && !strcmp(intval($dAKey_vA).'.',$dAKey_vA)) {
  1619. $temp_vA=array();
  1620. list($temp_vA[0])= explode('=',$dAA_vA['label.'] ? $this->stdWrap($dAA_vA['label'],$dAA_vA['label.']) : $dAA_vA['label']);
  1621. if ($dAA_vA['selected']) {$temp_vA[0]='*'.$temp_vA[0];}
  1622. list($temp_vA[1])= explode(',',$dAA_vA['value']);
  1623. }
  1624. $temp_accum[] = implode('=',$temp_vA);
  1625. }
  1626. $temp[2] = implode(',',$temp_accum);
  1627. }
  1628. list($temp[3]) = explode('|',$dAA['specialEval.'] ? $this->stdWrap($dAA['specialEval'],$dAA['specialEval.']) : $dAA['specialEval']);
  1629. // adding the form entry to the dataArray
  1630. $dataArr[] = implode('|',$temp);
  1631. }
  1632. }
  1633. }
  1634. }
  1635. $attachmentCounter = '';
  1636. $hiddenfields = '';
  1637. $fieldlist = Array();
  1638. $propertyOverride = Array();
  1639. $fieldname_hashArray = Array();
  1640. $cc = 0;
  1641. $xhtmlStrict = t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2',$GLOBALS['TSFE']->xhtmlDoctype);
  1642. // Formname
  1643. if ($conf['formName']) {
  1644. $formname = $this->cleanFormName($conf['formName']);
  1645. } else {
  1646. $formname = $GLOBALS['TSFE']->uniqueHash();
  1647. $formname = 'a'.$formname; // form name has to start with a letter to reach XHTML compliance
  1648. }
  1649. if (isset($conf['fieldPrefix'])) {
  1650. if ($conf['fieldPrefix']) {
  1651. $prefix = $this->cleanFormName($conf['fieldPrefix']);
  1652. } else {
  1653. $prefix = '';
  1654. }
  1655. } else {
  1656. $prefix = $formname;
  1657. }
  1658. foreach ($dataArr as $val) {
  1659. $cc++;
  1660. $confData=Array();
  1661. if (is_array($formData)) {
  1662. $parts = $val;
  1663. $val = 1; // true...
  1664. } else {
  1665. $val = trim($val);
  1666. $parts = explode('|',$val);
  1667. }
  1668. if ($val && strcspn($val,'#/')) {
  1669. // label:
  1670. $confData['label'] = trim($parts[0]);
  1671. // field:
  1672. $fParts = explode(',',$parts[1]);
  1673. $fParts[0]=trim($fParts[0]);
  1674. if (substr($fParts[0],0,1)=='*') {
  1675. $confData['required']=1;
  1676. $fParts[0] = substr($fParts[0],1);
  1677. }
  1678. $typeParts = explode('=',$fParts[0]);
  1679. $confData['type'] = trim(strtolower(end($typeParts)));
  1680. if (count($typeParts)==1) {
  1681. $confData['fieldname'] = $this->cleanFormName($parts[0]);
  1682. if (strtolower(preg_replace('/[^[:alnum:]]/','',$confData['fieldname']))=='email') {$confData['fieldname']='email';}
  1683. // Duplicate fieldnames resolved
  1684. if (isset($fieldname_hashArray[md5($confData['fieldname'])])) {
  1685. $confData['fieldname'].='_'.$cc;
  1686. }
  1687. $fieldname_hashArray[md5($confData['fieldname'])]=$confData['fieldname'];
  1688. // Attachment names...
  1689. if ($confData['type']=='file') {
  1690. $confData['fieldname']='attachment'.$attachmentCounter;
  1691. $attachmentCounter=intval($attachmentCounter)+1;
  1692. }
  1693. } else {
  1694. $confData['fieldname'] = str_replace(' ','_',trim($typeParts[0]));
  1695. }
  1696. $fieldCode='';
  1697. if ($conf['wrapFieldName']) {
  1698. $confData['fieldname'] = $this->wrap($confData['fieldname'],$conf['wrapFieldName']);
  1699. }
  1700. // Set field name as current:
  1701. $this->setCurrentVal($confData['fieldname']);
  1702. // Additional parameters
  1703. if (trim($confData['type'])) {
  1704. $addParams=trim($conf['params']);
  1705. if (is_array($conf['params.']) && isset($conf['params.'][$confData['type']])) {
  1706. $addParams=trim($conf['params.'][$confData['type']]);
  1707. }
  1708. if (strcmp('',$addParams)) { $addParams=' '.$addParams; }
  1709. } else $addParams='';
  1710. if ($conf['dontMd5FieldNames']) {
  1711. $fName = $confData['fieldname'];
  1712. } else {
  1713. $fName = md5($confData['fieldname']);
  1714. }
  1715. // Accessibility: Set id = fieldname attribute:
  1716. if ($conf['accessibility'] || $xhtmlStrict) {
  1717. $elementIdAttribute = ' id="'.$prefix.$fName.'"';
  1718. } else {
  1719. $elementIdAttribute = '';
  1720. }
  1721. // Create form field based on configuration/type:
  1722. switch ($confData['type']) {
  1723. case 'textarea':
  1724. $cols=trim($fParts[1]) ? intval($fParts[1]) : 20;
  1725. $compWidth = doubleval($conf['compensateFieldWidth'] ? $conf['compensateFieldWidth'] : $GLOBALS['TSFE']->compensateFieldWidth);
  1726. $compWidth = $compWidth ? $compWidth : 1;
  1727. $cols = t3lib_div::intInRange($cols*$compWidth, 1, 120);
  1728. $rows=trim($fParts[2]) ? t3lib_div::intInRange($fParts[2],1,30) : 5;
  1729. $wrap=trim($fParts[3]);
  1730. if ($conf['noWrapAttr'] || $wrap === 'disabled') {
  1731. $wrap='';
  1732. } else {
  1733. $wrap = $wrap ? ' wrap="'.$wrap.'"' : ' wrap="virtual"';
  1734. }
  1735. $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], str_replace('\n',LF,trim($parts[2])));
  1736. $fieldCode=sprintf('<textarea name="%s"%s cols="%s" rows="%s"%s%s>%s</textarea>',
  1737. $confData['fieldname'], $elementIdAttribute, $cols, $rows, $wrap, $addParams, t3lib_div::formatForTextarea($default));
  1738. break;
  1739. case 'input':
  1740. case 'password':
  1741. $size=trim($fParts[1]) ? intval($fParts[1]) : 20;
  1742. $compWidth = doubleval($conf['compensateFieldWidth'] ? $conf['compensateFieldWidth'] : $GLOBALS['TSFE']->compensateFieldWidth);
  1743. $compWidth = $compWidth ? $compWidth : 1;
  1744. $size = t3lib_div::intInRange($size*$compWidth, 1, 120);
  1745. $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], trim($parts[2]));
  1746. if ($confData['type']=='password') {
  1747. $default='';
  1748. }
  1749. $max=trim($fParts[2]) ? ' maxlength="'.t3lib_div::intInRange($fParts[2],1,1000).'"' : "";
  1750. $theType = $confData['type']=='input' ? 'text' : 'password';
  1751. $fieldCode=sprintf('<input type="%s" name="%s"%s size="%s"%s value="%s"%s />',
  1752. $theType, $confData['fieldname'], $elementIdAttribute, $size, $max, htmlspecialchars($default), $addParams);
  1753. break;
  1754. case 'file':
  1755. $size=trim($fParts[1]) ? t3lib_div::intInRange($fParts[1],1,60) : 20;
  1756. $fieldCode=sprintf('<input type="file" name="%s"%s size="%s"%s />',
  1757. $confData['fieldname'], $elementIdAttribute, $size, $addParams);
  1758. break;
  1759. case 'check':
  1760. // alternative default value:
  1761. $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], trim($parts[2]));
  1762. $checked = $default ? ' checked="checked"' : '';
  1763. $fieldCode=sprintf('<input type="checkbox" value="%s" name="%s"%s%s%s />',
  1764. 1, $confData['fieldname'], $elementIdAttribute, $checked, $addParams);
  1765. break;
  1766. case 'select':
  1767. $option='';
  1768. $valueParts = explode(',',$parts[2]);
  1769. // size
  1770. if (strtolower(trim($fParts[1]))=='auto') {$fParts[1]=count($valueParts);} // Auto size set here. Max 20
  1771. $size=trim($fParts[1]) ? t3lib_div::intInRange($fParts[1],1,20) : 1;
  1772. // multiple
  1773. $multiple = strtolower(trim($fParts[2]))=='m' ? ' multiple="multiple"' : '';
  1774. $items=array(); // Where the items will be
  1775. $defaults=array(); //RTF
  1776. $pCount = count($valueParts);
  1777. for($a=0;$a<$pCount;$a++) {
  1778. $valueParts[$a]=trim($valueParts[$a]);
  1779. if (substr($valueParts[$a],0,1)=='*') { // Finding default value
  1780. $sel='selected';
  1781. $valueParts[$a] = substr($valueParts[$a],1);
  1782. } else $sel='';
  1783. // Get value/label
  1784. $subParts=explode('=',$valueParts[$a]);
  1785. $subParts[1] = (isset($subParts[1])?trim($subParts[1]):trim($subParts[0])); // Sets the value
  1786. $items[] = $subParts; // Adds the value/label pair to the items-array
  1787. if ($sel) {$defaults[]=$subParts[1];} // Sets the default value if value/label pair is marked as default.
  1788. }
  1789. // alternative default value:
  1790. $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], $defaults);
  1791. if (!is_array($default)) {
  1792. $defaults=array();
  1793. $defaults[] = $default;
  1794. } else $defaults=$default;
  1795. // Create the select-box:
  1796. $iCount = count($items);
  1797. for($a=0;$a<$iCount;$a++) {
  1798. $option.='<option value="'.$items[$a][1].'"'.(in_array($items[$a][1],$defaults)?' selected="selected"':'').'>'.trim($items[$a][0]).'</option>'; //RTF
  1799. }
  1800. if ($multiple) $confData['fieldname'].='[]'; // The fieldname must be prepended '[]' if multiple select. And the reason why it's prepended is, because the required-field list later must also have [] prepended.
  1801. $fieldCode=sprintf('<select name="%s"%s size="%s"%s%s>%s</select>',
  1802. $confData['fieldname'], $elementIdAttribute, $size, $multiple, $addParams, $option); //RTF
  1803. break;
  1804. case 'radio':
  1805. $option='';
  1806. $valueParts = explode(',',$parts[2]);
  1807. $items=array(); // Where the items will be
  1808. $default='';
  1809. $pCount = count($valueParts);
  1810. for($a=0;$a<$pCount;$a++) {
  1811. $valueParts[$a]=trim($valueParts[$a]);
  1812. if (substr($valueParts[$a],0,1)=='*') {
  1813. $sel='checked';
  1814. $valueParts[$a] = substr($valueParts[$a],1);
  1815. } else $sel='';
  1816. // Get value/label
  1817. $subParts=explode('=',$valueParts[$a]);
  1818. $subParts[1] = (isset($subParts[1])?trim($subParts[1]):trim($subParts[0])); // Sets the value
  1819. $items[] = $subParts; // Adds the value/label pair to the items-array
  1820. if ($sel) {$default=$subParts[1];} // Sets the default value if value/label pair is marked as default.
  1821. }
  1822. // alternative default value:
  1823. $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], $default);
  1824. // Create the select-box:
  1825. $iCount = count($items);
  1826. for($a=0;$a<$iCount;$a++) {
  1827. $radioId = $prefix.$fName.$this->cleanFormName($items[$a][0]);
  1828. if ($conf['accessibility']) {
  1829. $radioLabelIdAttribute = ' id="'.$radioId.'"';
  1830. } else {
  1831. $radioLabelIdAttribute = '';
  1832. }
  1833. $option .= '<input type="radio" name="'.$confData['fieldname'].'"'.$radioLabelIdAttribute.' value="'.$items[$a][1].'"'.(!strcmp($items[$a][1],$default)?' checked="checked"':'').$addParams.' />';
  1834. if ($conf['accessibility']) {
  1835. $option .= '<label for="'.$radioId.'">' . $this->stdWrap(trim($items[$a][0]), $conf['radioWrap.']) . '</label>';
  1836. } else {
  1837. $option .= $this->stdWrap(trim($items[$a][0]), $conf['radioWrap.']);
  1838. }
  1839. }
  1840. if ($conf['accessibility']) {
  1841. $accessibilityWrap = $conf['radioWrap.']['accessibilityWrap'];
  1842. $search = array(
  1843. '###RADIO_FIELD_ID###',
  1844. '###RADIO_GROUP_LABEL###'
  1845. );
  1846. $replace = array(
  1847. $elementIdAttribute,
  1848. $confData['label']
  1849. );
  1850. $accessibilityWrap = str_replace($search, $replace, $accessibilityWrap);
  1851. $option = $this->wrap($option, $accessibilityWrap);
  1852. }
  1853. $fieldCode = $option;
  1854. break;
  1855. case 'hidden':
  1856. $value = trim($parts[2]);
  1857. // If this form includes an auto responder message, include a HMAC checksum field
  1858. // in order to verify potential abuse of this feature.
  1859. if (strlen($value) && t3lib_div::inList($confData['fieldname'], 'auto_respond_msg')) {
  1860. $hmacChecksum = t3lib_div::hmac($value);
  1861. $hiddenfields .= sprintf('<input type="hidden" name="auto_respond_checksum" id="%sauto_respond_checksum" value="%s" />',
  1862. $prefix, $hmacChecksum);
  1863. }
  1864. if (strlen($value) && t3lib_div::inList('recipient_copy,recipient',$confData['fieldname']) && $GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
  1865. break;
  1866. }
  1867. if (strlen($value) && t3lib_div::inList('recipient_copy,recipient',$confData['fieldname'])) {
  1868. $value = $GLOBALS['TSFE']->codeString($value);
  1869. }
  1870. $hiddenfields.= sprintf('<input type="hidden" name="%s"%s value="%s" />',
  1871. $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value));
  1872. break;
  1873. case 'property':
  1874. if (t3lib_div::inList('type,locationData,goodMess,badMess,emailMess',$confData['fieldname'])) {
  1875. $value=trim($parts[2]);
  1876. $propertyOverride[$confData['fieldname']] = $value;
  1877. $conf[$confData['fieldname']] = $value;
  1878. }
  1879. break;
  1880. case 'submit':
  1881. $value=trim($parts[2]);
  1882. if ($conf['image.']) {
  1883. $this->data[$this->currentValKey] = $value;
  1884. $image = $this->IMG_RESOURCE($conf['image.']);
  1885. $params = $conf['image.']['params'] ? ' '.$conf['image.']['params'] : '';
  1886. $params.= $this->getAltParam($conf['image.'], false);
  1887. $params.= $addParams;
  1888. } else {
  1889. $image = '';
  1890. }
  1891. if ($image) {
  1892. $fieldCode=sprintf('<input type="image" name="%s"%s src="%s"%s />',
  1893. $confData['fieldname'], $elementIdAttribute, $image, $params);
  1894. } else {
  1895. $fieldCode=sprintf('<input type="submit" name="%s"%s value="%s"%s />',
  1896. $confData['fieldname'], $elementIdAttribute, t3lib_div::deHSCentities(htmlspecialchars($value)), $addParams);
  1897. }
  1898. break;
  1899. case 'reset':
  1900. $value=trim($parts[2]);
  1901. $fieldCode=sprintf('<input type="reset" name="%s"%s value="%s"%s />',
  1902. $confData['fieldname'], $elementIdAttribute, t3lib_div::deHSCentities(htmlspecialchars($value)), $addParams);
  1903. break;
  1904. case 'label':
  1905. $fieldCode = nl2br(htmlspecialchars(trim($parts[2])));
  1906. break;
  1907. default:
  1908. $confData['type'] = 'comment';
  1909. $fieldCode = trim($parts[2]).'&nbsp;';
  1910. break;
  1911. }
  1912. if ($fieldCode) {
  1913. // Checking for special evaluation modes:
  1914. if (t3lib_div::inList('textarea,input,password',$confData['type']) && strlen(trim($parts[3]))) {
  1915. $modeParameters = t3lib_div::trimExplode(':',$parts[3]);
  1916. } else {
  1917. $modeParameters = array();
  1918. }
  1919. // Adding evaluation based on settings:
  1920. switch ((string)$modeParameters[0]) {
  1921. case 'EREG':
  1922. $fieldlist[] = '_EREG';
  1923. $fieldlist[] = $modeParameters[1];
  1924. $fieldlist[] = $modeParameters[2];
  1925. $fieldlist[] = $confData['fieldname'];
  1926. $fieldlist[] = $confData['label'];
  1927. $confData['required'] = 1; // Setting this so "required" layout is used.
  1928. break;
  1929. case 'EMAIL':
  1930. $fieldlist[] = '_EMAIL';
  1931. $fieldlist[] = $confData['fieldname'];
  1932. $fieldlist[] = $confData['label'];
  1933. $confData['required'] = 1; // Setting this so "required" layout is used.
  1934. break;
  1935. default:
  1936. if ($confData['required']) {
  1937. $fieldlist[] = $confData['fieldname'];
  1938. $fieldlist[] = $confData['label'];
  1939. }
  1940. break;
  1941. }
  1942. // Field:
  1943. $fieldLabel = $confData['label'];
  1944. if ($conf['accessibility'] && trim($fieldLabel) && !preg_match('/^(label|hidden|comment)$/',$confData['type'])) {
  1945. $fieldLabel = '<label for="'.$prefix.$fName.'">'.$fieldLabel.'</label>';
  1946. }
  1947. // Getting template code:
  1948. $fieldCode = $this->stdWrap($fieldCode, $conf['fieldWrap.']);
  1949. $labelCode = $this->stdWrap($fieldLabel, $conf['labelWrap.']);
  1950. $commentCode = $this->stdWrap($confData['label'], $conf['commentWrap.']); // RTF
  1951. $result = $conf['layout'];
  1952. if ($conf['REQ'] && $confData['required']) {
  1953. if (is_array($conf['REQ.']['fieldWrap.']))
  1954. $fieldCode = $this->stdWrap($fieldCode, $conf['REQ.']['fieldWrap.']);
  1955. if (is_array($conf['REQ.']['labelWrap.']))
  1956. $labelCode = $this->stdWrap($fieldLabel, $conf['REQ.']['labelWrap.']);
  1957. if ($conf['REQ.']['layout']) {
  1958. $result = $conf['REQ.']['layout'];
  1959. }
  1960. }
  1961. if ($confData['type']=='comment' && $conf['COMMENT.']['layout']) {
  1962. $result = $conf['COMMENT.']['layout'];
  1963. }
  1964. if ($confData['type']=='check' && $conf['CHECK.']['layout']) {
  1965. $result = $conf['CHECK.']['layout'];
  1966. }
  1967. if ($confData['type']=='radio' && $conf['RADIO.']['layout']) {
  1968. $result = $conf['RADIO.']['layout'];
  1969. }
  1970. if ($confData['type']=='label' && $conf['LABEL.']['layout']) {
  1971. $result = $conf['LABEL.']['layout'];
  1972. }
  1973. $result = str_replace('###FIELD###',$fieldCode,$result);
  1974. $result = str_replace('###LABEL###',$labelCode,$result);
  1975. $result = str_replace('###COMMENT###',$commentCode,$result); //RTF
  1976. $content.= $result;
  1977. }
  1978. }
  1979. }
  1980. if ($conf['stdWrap.']) { $content = $this->stdWrap($content, $conf['stdWrap.']); }
  1981. // redirect (external: where to go afterwards. internal: where to submit to)
  1982. $theRedirect = $this->stdWrap($conf['redirect'], $conf['redirect.']); // redirect should be set to the page to redirect to after an external script has been used. If internal scripts is used, and if no 'type' is set that dictates otherwise, redirect is used as the url to jump to as long as it's an integer (page)
  1983. $page = $GLOBALS['TSFE']->page;
  1984. if (!$theRedirect) { // Internal: Just submit to current page
  1985. $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'],'index.php', '', $this->getClosestMPvalueForPage($page['uid']));
  1986. } elseif (t3lib_div::testInt($theRedirect)) { // Internal: Submit to page with ID $theRedirect
  1987. $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($theRedirect);
  1988. $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'],'index.php', '', $this->getClosestMPvalueForPage($page['uid']));
  1989. } else { // External URL, redirect-hidden field is rendered!
  1990. $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'],'', '', $this->getClosestMPvalueForPage($page['uid']));
  1991. $LD['totalURL'] = $theRedirect;
  1992. $hiddenfields.= '<input type="hidden" name="redirect" value="'.htmlspecialchars($LD['totalURL']).'" />'; // 18-09-00 added
  1993. }
  1994. // Formtype (where to submit to!):
  1995. $formtype = $propertyOverride['type'] ? $propertyOverride['type'] : $this->stdWrap($conf['type'], $conf['type.']);
  1996. if (t3lib_div::testInt($formtype)) { // Submit to a specific page
  1997. $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($formtype);
  1998. $LD_A = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'], '', '', $this->getClosestMPvalueForPage($page['uid']));
  1999. $action = $LD_A['totalURL'];
  2000. } elseif ($formtype) { // Submit to external script
  2001. $LD_A = $LD;
  2002. $action = $formtype;
  2003. } elseif (t3lib_div::testInt($theRedirect)) {
  2004. $LD_A = $LD;
  2005. $action = $LD_A['totalURL'];
  2006. } else { // Submit to "nothing" - which is current page
  2007. $LD_A = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page, $conf['target'], $conf['no_cache'], '', '', $this->getClosestMPvalueForPage($page['uid']));
  2008. $action = $LD_A['totalURL'];
  2009. }
  2010. // Recipient:
  2011. $theEmail = $this->stdWrap($conf['recipient'], $conf['recipient.']);
  2012. if ($theEmail && !$GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
  2013. $theEmail = $GLOBALS['TSFE']->codeString($theEmail);
  2014. $hiddenfields.= '<input type="hidden" name="recipient" value="'.htmlspecialchars($theEmail).'" />';
  2015. }
  2016. // location data:
  2017. if ($conf['locationData']) {
  2018. if ($conf['locationData']=='HTTP_POST_VARS' && isset($_POST['locationData'])) {
  2019. $locationData = t3lib_div::_POST('locationData');
  2020. } else {
  2021. $locationData = $GLOBALS['TSFE']->id.':'.$this->currentRecord; // locationData is [hte page id]:[tablename]:[uid of record]. Indicates on which page the record (from tablename with uid) is shown. Used to check access.
  2022. }
  2023. $hiddenfields.='<input type="hidden" name="locationData" value="'.htmlspecialchars($locationData).'" />';
  2024. }
  2025. // hidden fields:
  2026. if (is_array($conf['hiddenFields.'])) {
  2027. foreach ($conf['hiddenFields.'] as $hF_key => $hF_conf) {
  2028. if (substr($hF_key,-1)!='.') {
  2029. $hF_value = $this->cObjGetSingle($hF_conf,$conf['hiddenFields.'][$hF_key.'.'],'hiddenfields');
  2030. if (strlen($hF_value) && t3lib_div::inList('recipient_copy,recipient',$hF_key)) {
  2031. if ($GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail']) {
  2032. continue;
  2033. }
  2034. $hF_value = $GLOBALS['TSFE']->codeString($hF_value);
  2035. }
  2036. $hiddenfields.= '<input type="hidden" name="'.$hF_key.'" value="'.htmlspecialchars($hF_value).'" />';
  2037. }
  2038. }
  2039. }
  2040. // Wrap all hidden fields in a div tag (see http://bugs.typo3.org/view.php?id=678)
  2041. $hiddenfields = '<div style="display:none;">'.$hiddenfields.'</div>';
  2042. if ($conf['REQ']) {
  2043. $validateForm = ' onsubmit="return validateForm(\'' .
  2044. $formname . '\',\'' . implode(',',$fieldlist) . '\',' .
  2045. t3lib_div::quoteJSvalue($conf['goodMess']) . ',' .
  2046. t3lib_div::quoteJSvalue($conf['badMess']) . ',' .
  2047. t3lib_div::quoteJSvalue($conf['emailMess']) . ')"';
  2048. $GLOBALS['TSFE']->additionalHeaderData['JSFormValidate'] =
  2049. '<script type="text/javascript" src="' .
  2050. t3lib_div::createVersionNumberedFilename($GLOBALS['TSFE']->absRefPrefix .
  2051. 't3lib/jsfunc.validateform.js') .
  2052. '"></script>';
  2053. } else {
  2054. $validateForm = '';
  2055. }
  2056. // Create form tag:
  2057. $theTarget = ($theRedirect?$LD['target']:$LD_A['target']);
  2058. $content = array(
  2059. '<form'.
  2060. ' action="'.htmlspecialchars($action).'"'.
  2061. ' id="'.$formname.'"'.($xhtmlStrict ? '' : ' name="'.$formname.'"').
  2062. ' enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'"'.
  2063. ' method="'.($conf['method']?$conf['method']:'post').'"'.
  2064. ($theTarget ? ' target="'.$theTarget.'"' : '').
  2065. $validateForm.
  2066. '>',
  2067. $hiddenfields.$content,
  2068. '</form>'
  2069. );
  2070. if ($conf['arrayReturnMode']) {
  2071. $content['validateForm']=$validateForm;
  2072. $content['formname']=$formname;
  2073. return $content;
  2074. } else {
  2075. return implode('',$content);
  2076. }
  2077. }
  2078. /**
  2079. * Rendering the cObject, SEARCHRESULT
  2080. *
  2081. * @param array Array of TypoScript properties
  2082. * @return string Output
  2083. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=368&cHash=d00731cd7b
  2084. */
  2085. function SEARCHRESULT($conf) {
  2086. if (t3lib_div::_GP('sword') && t3lib_div::_GP('scols')) {
  2087. $search = t3lib_div::makeInstance('tslib_search');
  2088. $search->register_and_explode_search_string(t3lib_div::_GP('sword'));
  2089. $search->register_tables_and_columns(t3lib_div::_GP('scols'),$conf['allowedCols']);
  2090. // depth
  2091. $depth=100;
  2092. // the startId is found
  2093. $theStartId=0;
  2094. if (t3lib_div::testInt(t3lib_div::_GP('stype'))) {
  2095. $temp_theStartId=t3lib_div::_GP('stype');
  2096. $rootLine = $GLOBALS['TSFE']->sys_page->getRootLine($temp_theStartId);
  2097. // The page MUST have a rootline with the Level0-page of the current site inside!!
  2098. foreach ($rootLine as $val) {
  2099. if($val['uid']==$GLOBALS['TSFE']->tmpl->rootLine[0]['uid']) {
  2100. $theStartId = $temp_theStartId;
  2101. }
  2102. }
  2103. } else if (t3lib_div::_GP('stype')) {
  2104. if (substr(t3lib_div::_GP('stype'),0,1)=='L') {
  2105. $pointer = intval(substr(t3lib_div::_GP('stype'),1));
  2106. $theRootLine = $GLOBALS['TSFE']->tmpl->rootLine;
  2107. // location Data:
  2108. $locDat_arr = explode(':',t3lib_div::_POST('locationData'));
  2109. $pId = intval($locDat_arr[0]);
  2110. if ($pId) {
  2111. $altRootLine = $GLOBALS['TSFE']->sys_page->getRootLine($pId);
  2112. ksort($altRootLine);
  2113. if (count($altRootLine)) {
  2114. // check if the rootline has the real Level0 in it!!
  2115. $hitRoot=0;
  2116. $theNewRoot=array();
  2117. foreach ($altRootLine as $val) {
  2118. if($hitRoot || $val['uid']==$GLOBALS['TSFE']->tmpl->rootLine[0]['uid']) {
  2119. $hitRoot=1;
  2120. $theNewRoot[]=$val;
  2121. }
  2122. }
  2123. if ($hitRoot) {
  2124. $theRootLine = $theNewRoot; // Override the real rootline if any thing
  2125. }
  2126. }
  2127. }
  2128. $key = $this->getKey($pointer,$theRootLine);
  2129. $theStartId = $theRootLine[$key]['uid'];
  2130. }
  2131. }
  2132. if (!$theStartId) {
  2133. // If not set, we use current page
  2134. $theStartId = $GLOBALS['TSFE']->id;
  2135. }
  2136. // generate page-tree
  2137. $search->pageIdList.= $this->getTreeList(-1*$theStartId,$depth);
  2138. $endClause = 'pages.uid IN ('.$search->pageIdList.')
  2139. AND pages.doktype in ('.$GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'].($conf['addExtUrlsAndShortCuts']?',3,4':'').')
  2140. AND pages.no_search=0'.
  2141. $this->enableFields($search->fTable).
  2142. $this->enableFields('pages');
  2143. if ($conf['languageField.'][$search->fTable]) {
  2144. $endClause.= ' AND '.$search->fTable.'.'.$conf['languageField.'][$search->fTable].' = '.intval($GLOBALS['TSFE']->sys_language_uid); // (using sys_language_uid which is the ACTUAL language of the page. sys_language_content is only for selecting DISPLAY content!)
  2145. }
  2146. // build query
  2147. $search->build_search_query($endClause);
  2148. // count...
  2149. if (t3lib_div::testInt(t3lib_div::_GP('scount'))) {
  2150. $search->res_count = t3lib_div::_GP('scount');
  2151. } else {
  2152. $search->count_query();
  2153. }
  2154. // range
  2155. $spointer = intval(t3lib_div::_GP('spointer'));
  2156. if (isset($conf['range'])) {
  2157. $theRange = intval($conf['range']);
  2158. } else {
  2159. $theRange = 20;
  2160. }
  2161. // Order By:
  2162. if (!$conf['noOrderBy']) {
  2163. $search->queryParts['ORDERBY'] = 'pages.lastUpdated, pages.tstamp';
  2164. }
  2165. $search->queryParts['LIMIT'] = $spointer.','.$theRange;
  2166. // search...
  2167. $search->execute_query();
  2168. if ($GLOBALS['TYPO3_DB']->sql_num_rows($search->result)) {
  2169. $GLOBALS['TSFE']->register['SWORD_PARAMS'] = $search->get_searchwords();
  2170. $total = $search->res_count;
  2171. $rangeLow = t3lib_div::intInRange($spointer+1,1,$total);
  2172. $rangeHigh = t3lib_div::intInRange($spointer+$theRange,1,$total);
  2173. // prev/next url:
  2174. $LD = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page,$conf['target'],1,'', '', $this->getClosestMPvalueForPage($GLOBALS['TSFE']->page['uid']));
  2175. $targetPart = $LD['target'] ? ' target="'.htmlspecialchars($LD['target']).'"' : '';
  2176. $urlParams = $this->URLqMark($LD['totalURL'],
  2177. '&sword='.rawurlencode(t3lib_div::_GP('sword')).
  2178. '&scols='.rawurlencode(t3lib_div::_GP('scols')).
  2179. '&stype='.rawurlencode(t3lib_div::_GP('stype')).
  2180. '&scount='.$total);
  2181. // substitution:
  2182. $result= $this->cObjGetSingle($conf['layout'],$conf['layout.'], 'layout');
  2183. $result = str_replace('###RANGELOW###',$rangeLow,$result);
  2184. $result = str_replace('###RANGEHIGH###',$rangeHigh,$result);
  2185. $result = str_replace('###TOTAL###',$total,$result);
  2186. if ($rangeHigh<$total) {
  2187. $next = $this->cObjGetSingle($conf['next'], $conf['next.'], 'next');
  2188. $next = '<a href="'.htmlspecialchars($urlParams.'&spointer='.($spointer+$theRange)).'"'.$targetPart.$GLOBALS['TSFE']->ATagParams.'>'.$next.'</a>';
  2189. } else $next='';
  2190. $result = str_replace('###NEXT###',$next,$result);
  2191. if ($rangeLow>1) {
  2192. $prev = $this->cObjGetSingle($conf['prev'], $conf['prev.'], 'prev');
  2193. $prev = '<a href="'.htmlspecialchars($urlParams.'&spointer='.($spointer-$theRange)).'"'.$targetPart.$GLOBALS['TSFE']->ATagParams.'>'.$prev.'</a>';
  2194. } else $prev='';
  2195. $result = str_replace('###PREV###',$prev,$result);
  2196. // searching result
  2197. $theValue = $this->cObjGetSingle($conf['resultObj'], $conf['resultObj.'],'resultObj');
  2198. $cObj = t3lib_div::makeInstance('tslib_cObj');
  2199. $cObj->setParent($this->data,$this->currentRecord);
  2200. $renderCode='';
  2201. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($search->result)) {
  2202. // versionOL() here? This is search result displays, is that possible to preview anyway? Or are records selected here already future versions?
  2203. $cObj->start($row);
  2204. $renderCode.=$cObj->cObjGetSingle($conf['renderObj'], $conf['renderObj.'],'renderObj');
  2205. }
  2206. $theValue.=$this->wrap($renderCode,$conf['renderWrap']);
  2207. $theValue = str_replace('###RESULT###',$theValue,$result);
  2208. } else {
  2209. $theValue = $this->cObjGetSingle($conf['noResultObj'], $conf['noResultObj.'],'noResultObj');
  2210. }
  2211. $GLOBALS['TT']->setTSlogMessage('Search in fields: '.$search->listOfSearchFields);
  2212. // wrapping
  2213. $content=$theValue;
  2214. if ($conf['wrap']) {
  2215. $content=$this->wrap($content, $conf['wrap']);
  2216. }
  2217. if ($conf['stdWrap.']) {
  2218. $content=$this->stdWrap($content, $conf['stdWrap.']);
  2219. }
  2220. // returning
  2221. $GLOBALS['TSFE']->set_no_cache();
  2222. return $content;
  2223. }
  2224. }
  2225. /**
  2226. * Rendering the cObject, PHP_SCRIPT, PHP_SCRIPT_INT and PHP_SCRIPT_EXT
  2227. *
  2228. * @param array Array of TypoScript properties
  2229. * @param string If "INT", then rendering "PHP_SCRIPT_INT"; If "EXT", then rendering "PHP_SCRIPT_EXT"; Default is rendering "PHP_SCRIPT" (cached)
  2230. * @return string Output
  2231. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=370&cHash=aa107f2ad8
  2232. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=371&cHash=53f71d025e
  2233. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=372&cHash=91fe391e1c
  2234. */
  2235. function PHP_SCRIPT($conf,$ext='') {
  2236. $incFile = $GLOBALS['TSFE']->tmpl->getFileName($conf['file']);
  2237. $content='';
  2238. if ($incFile && $GLOBALS['TSFE']->checkFileInclude($incFile)) {
  2239. switch($ext) {
  2240. case 'INT':
  2241. case 'EXT':
  2242. $substKey = $ext.'_SCRIPT.'.$GLOBALS['TSFE']->uniqueHash();
  2243. $content.='<!--'.$substKey.'-->';
  2244. $GLOBALS['TSFE']->config[$ext.'incScript'][$substKey] = array(
  2245. 'file'=>$incFile,
  2246. 'conf'=>$conf,
  2247. 'type'=>'SCRIPT'
  2248. );
  2249. if ($ext=='INT') {
  2250. $GLOBALS['TSFE']->config[$ext.'incScript'][$substKey]['cObj'] = serialize($this);
  2251. } else {
  2252. $GLOBALS['TSFE']->config[$ext.'incScript'][$substKey]['data'] = $this->data;
  2253. }
  2254. break;
  2255. default:
  2256. // Added 31-12-00: Make backup...
  2257. $this->oldData = $this->data;
  2258. // Include file..
  2259. include('./'.$incFile);
  2260. // Added 31-12-00: restore...
  2261. if ($RESTORE_OLD_DATA) {
  2262. $this->data = $this->oldData;
  2263. }
  2264. break;
  2265. }
  2266. }
  2267. return $content;
  2268. }
  2269. /**
  2270. * Rendering the cObject, TEMPLATE
  2271. *
  2272. * @param array Array of TypoScript properties
  2273. * @return string Output
  2274. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=373&cHash=109a171b1e
  2275. * @see substituteMarkerArrayCached()
  2276. */
  2277. function TEMPLATE($conf) {
  2278. $subparts = Array();
  2279. $marks = Array();
  2280. $wraps = Array();
  2281. $content='';
  2282. list($PRE,$POST) = explode('|',$conf['markerWrap'] ? $conf['markerWrap'] : '### | ###');
  2283. $POST = trim($POST);
  2284. $PRE = trim($PRE);
  2285. // Getting the content
  2286. $content = $this->cObjGetSingle($conf['template'],$conf['template.'],'template');
  2287. if ($conf['workOnSubpart']) {
  2288. $content = $this->getSubpart($content, $PRE.$conf['workOnSubpart'].$POST);
  2289. }
  2290. // Fixing all relative paths found:
  2291. if ($conf['relPathPrefix']) {
  2292. $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
  2293. $content = $htmlParser->prefixResourcePath($conf['relPathPrefix'],$content,$conf['relPathPrefix.']);
  2294. }
  2295. if ($content) {
  2296. if ($conf['nonCachedSubst']) { // NON-CACHED:
  2297. // Getting marks
  2298. if (is_array($conf['marks.'])) {
  2299. foreach ($conf['marks.'] as $theKey => $theValue) {
  2300. if (!strstr($theKey,'.')) {
  2301. $content = str_replace(
  2302. $PRE.$theKey.$POST,
  2303. $this->cObjGetSingle($theValue,$conf['marks.'][$theKey.'.'],'marks.'.$theKey),
  2304. $content);
  2305. }
  2306. }
  2307. }
  2308. // Getting subparts.
  2309. if (is_array($conf['subparts.'])) {
  2310. foreach ($conf['subparts.'] as $theKey => $theValue) {
  2311. if (!strstr($theKey,'.')) {
  2312. $subpart = $this->getSubpart($content, $PRE.$theKey.$POST);
  2313. if ($subpart) {
  2314. $this->setCurrentVal($subpart);
  2315. $content = $this->substituteSubpart(
  2316. $content,
  2317. $PRE.$theKey.$POST,
  2318. $this->cObjGetSingle($theValue,$conf['subparts.'][$theKey.'.'],'subparts.'.$theKey),
  2319. 1
  2320. );
  2321. }
  2322. }
  2323. }
  2324. }
  2325. // Getting subpart wraps
  2326. if (is_array($conf['wraps.'])) {
  2327. foreach ($conf['wraps.'] as $theKey => $theValue) {
  2328. if (!strstr($theKey,'.')) {
  2329. $subpart = $this->getSubpart($content, $PRE.$theKey.$POST);
  2330. if ($subpart) {
  2331. $this->setCurrentVal($subpart);
  2332. $content = $this->substituteSubpart(
  2333. $content,
  2334. $PRE.$theKey.$POST,
  2335. explode('|',$this->cObjGetSingle($theValue,$conf['wraps.'][$theKey.'.'],'wraps.'.$theKey)),
  2336. 1
  2337. );
  2338. }
  2339. }
  2340. }
  2341. }
  2342. } else { // CACHED
  2343. // Getting subparts.
  2344. if (is_array($conf['subparts.'])) {
  2345. foreach ($conf['subparts.'] as $theKey => $theValue) {
  2346. if (!strstr($theKey,'.')) {
  2347. $subpart = $this->getSubpart($content, $PRE.$theKey.$POST);
  2348. if ($subpart) {
  2349. $GLOBALS['TSFE']->register['SUBPART_'.$theKey] = $subpart;
  2350. $subparts[$theKey]['name'] = $theValue;
  2351. $subparts[$theKey]['conf'] = $conf['subparts.'][$theKey.'.'];
  2352. }
  2353. }
  2354. }
  2355. }
  2356. // Getting marks
  2357. if (is_array($conf['marks.'])) {
  2358. foreach ($conf['marks.'] as $theKey => $theValue) {
  2359. if (!strstr($theKey,'.')) {
  2360. $marks[$theKey]['name'] = $theValue;
  2361. $marks[$theKey]['conf'] = $conf['marks.'][$theKey.'.'];
  2362. }
  2363. }
  2364. }
  2365. // Getting subpart wraps
  2366. if (is_array($conf['wraps.'])) {
  2367. foreach ($conf['wraps.'] as $theKey => $theValue) {
  2368. if (!strstr($theKey,'.')) {
  2369. $wraps[$theKey]['name'] = $theValue;
  2370. $wraps[$theKey]['conf'] = $conf['wraps.'][$theKey.'.'];
  2371. }
  2372. }
  2373. }
  2374. // Getting subparts
  2375. $subpartArray =array();
  2376. foreach ($subparts as $theKey => $theValue) {
  2377. // Set current with the content of the subpart...
  2378. $this->data[$this->currentValKey] = $GLOBALS['TSFE']->register['SUBPART_'.$theKey];
  2379. // Get subpart cObject and substitute it!
  2380. $subpartArray[$PRE.$theKey.$POST] = $this->cObjGetSingle($theValue['name'],$theValue['conf'],'subparts.'.$theKey);
  2381. }
  2382. $this->data[$this->currentValKey] = ''; // Reset current to empty
  2383. // Getting marks
  2384. $markerArray =array();
  2385. foreach ($marks as $theKey => $theValue) {
  2386. $markerArray[$PRE.$theKey.$POST] = $this->cObjGetSingle($theValue['name'],$theValue['conf'],'marks.'.$theKey);
  2387. }
  2388. // Getting wraps
  2389. $subpartWraps =array();
  2390. foreach ($wraps as $theKey => $theValue) {
  2391. $subpartWraps[$PRE.$theKey.$POST] = explode('|',$this->cObjGetSingle($theValue['name'],$theValue['conf'],'wraps.'.$theKey));
  2392. }
  2393. // Substitution
  2394. if ($conf['substMarksSeparately']) {
  2395. $content = $this->substituteMarkerArrayCached($content,array(),$subpartArray,$subpartWraps);
  2396. $content = $this->substituteMarkerArray($content, $markerArray);
  2397. } else {
  2398. $content = $this->substituteMarkerArrayCached($content,$markerArray,$subpartArray,$subpartWraps);
  2399. }
  2400. }
  2401. }
  2402. return $content;
  2403. }
  2404. /**
  2405. * Rendering the cObject, MULTIMEDIA
  2406. *
  2407. * @param array Array of TypoScript properties
  2408. * @return string Output
  2409. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=374&cHash=efd88ab4a9
  2410. */
  2411. function MULTIMEDIA($conf) {
  2412. $content='';
  2413. $filename=$this->stdWrap($conf['file'],$conf['file.']);
  2414. $incFile = $GLOBALS['TSFE']->tmpl->getFileName($filename);
  2415. if ($incFile) {
  2416. $fileinfo = t3lib_div::split_fileref($incFile);
  2417. if (t3lib_div::inList('txt,html,htm',$fileinfo['fileext'])) {
  2418. $content = $GLOBALS['TSFE']->tmpl->fileContent($incFile);
  2419. } else {
  2420. // default params...
  2421. $parArray=array();
  2422. // src is added
  2423. $parArray['src']='src="'.$GLOBALS['TSFE']->absRefPrefix.$incFile.'"';
  2424. if (t3lib_div::inList('au,wav,mp3',$fileinfo['fileext'])) {
  2425. }
  2426. if (t3lib_div::inList('avi,mov,mpg,asf,wmv',$fileinfo['fileext'])) {
  2427. $parArray['width'] = 'width="' . ($conf['width'] ? $conf['width'] : 200) . '"';
  2428. $parArray['height'] = 'height="' . ($conf['height'] ? $conf['height'] : 200) . '"';
  2429. }
  2430. if (t3lib_div::inList('swf,swa,dcr',$fileinfo['fileext'])) {
  2431. $parArray['quality'] = 'quality="high"';
  2432. }
  2433. if (t3lib_div::inList('class',$fileinfo['fileext'])) {
  2434. $parArray['width'] = 'width="' . ($conf['width'] ? $conf['width'] : 200) . '"';
  2435. $parArray['height'] = 'height="' . ($conf['height'] ? $conf['height'] : 200) . '"';
  2436. }
  2437. // fetching params
  2438. $lines = explode(LF, $this->stdWrap($conf['params'],$conf['params.']));
  2439. foreach ($lines as $l) {
  2440. $parts = explode('=', $l);
  2441. $parameter = strtolower(trim($parts[0]));
  2442. $value = trim($parts[1]);
  2443. if ((string)$value!='') {
  2444. $parArray[$parameter] = $parameter.'="'.htmlspecialchars($value).'"';
  2445. } else {
  2446. unset($parArray[$parameter]);
  2447. }
  2448. }
  2449. if ($fileinfo['fileext']=='class') {
  2450. unset($parArray['src']);
  2451. $parArray['code'] = 'code="'.htmlspecialchars($fileinfo['file']).'"';
  2452. $parArray['codebase'] = 'codebase="'.htmlspecialchars($fileinfo['path']).'"';
  2453. $content='<applet '.implode(' ',$parArray).'></applet>';
  2454. } else {
  2455. $content='<embed '.implode(' ',$parArray).'></embed>';
  2456. }
  2457. }
  2458. }
  2459. if ($conf['stdWrap.']) {
  2460. $content=$this->stdWrap($content, $conf['stdWrap.']);
  2461. }
  2462. return $content;
  2463. }
  2464. /**
  2465. * Rendering the cObject, SWFOBJECT
  2466. *
  2467. * @param array Array of TypoScript properties
  2468. * @return string Output
  2469. */
  2470. public function MEDIA($conf) {
  2471. $content = '';
  2472. $flexParams = $this->stdWrap($conf['flexParams'], $conf['flexParams.']);
  2473. if (substr($flexParams, 0, 1) === '<') {
  2474. // it is a content element
  2475. $this->readFlexformIntoConf($flexParams, $conf['parameter.']);
  2476. $url = $conf['parameter.']['mmFile'];
  2477. $url = $this->stdWrap($url, $conf['file.']);
  2478. } else {
  2479. // it is a TS object
  2480. $url = $this->stdWrap($conf['file'], $conf['file.']);
  2481. }
  2482. $mode = is_file(PATH_site . $url) ? 'file' : 'url';
  2483. if ($mode === 'file') {
  2484. $filename = $GLOBALS['TSFE']->tmpl->getFileName($url);
  2485. $fileinfo = t3lib_div::split_fileref($filename);
  2486. $conf['file'] = $filename;
  2487. } else {
  2488. $conf['file'] = $this->typoLink_URL(array('parameter' => $url));
  2489. }
  2490. $renderType = $conf['renderType'];
  2491. if (isset($conf['parameter.']['mmRenderType'])) {
  2492. $renderType = $conf['parameter.']['mmRenderType'];
  2493. }
  2494. if ($renderType === 'auto') {
  2495. // default renderType is swf
  2496. $renderType = 'swf';
  2497. $handler = array_keys($conf['fileExtHandler.']);
  2498. if (in_array($fileinfo['fileext'], $handler)) {
  2499. $renderType = strtolower($conf['fileExtHandler.'][$fileinfo['fileext']]);
  2500. }
  2501. }
  2502. $forcePlayer = isset($conf['parameter.']['mmFile']) ? intval($conf['parameter.']['mmforcePlayer']) : $conf['forcePlayer'];
  2503. $conf['forcePlayer'] = $forcePlayer;
  2504. $conf['type'] = isset($conf['parameter.']['mmType']) ? $conf['parameter.']['mmType'] : $conf['type'];
  2505. $mime = $renderType . 'object';
  2506. $typeConf = $conf['mimeConf.'][$mime . '.'][$conf['type'] . '.'] ? $conf['mimeConf.'][$mime . '.'][$conf['type'] . '.'] : array();
  2507. $conf['predefined'] = array();
  2508. $width = intval($conf['parameter.']['mmWidth']);
  2509. $height = intval($conf['parameter.']['mmHeight']);
  2510. if ($width) {
  2511. $conf['width'] = $width;
  2512. } else {
  2513. $conf['width'] = intval($conf['width']) ? $conf['width'] : $typeConf['defaultWidth'];
  2514. }
  2515. if ($height) {
  2516. $conf['height'] = $height;
  2517. } else {
  2518. $conf['height'] = intval($conf['height']) ? $conf['height'] : $typeConf['defaultHeight'];
  2519. }
  2520. if (is_array($conf['parameter.']['mmMediaOptions'])) {
  2521. $params = array();
  2522. foreach ($conf['parameter.']['mmMediaOptions'] as $key => $value) {
  2523. if ($key == 'mmMediaCustomParameterContainer') {
  2524. foreach ($value as $val) {
  2525. //custom parameter entry
  2526. $rawTS = $val['mmParamCustomEntry'];
  2527. //read and merge
  2528. $tmp = t3lib_div::trimExplode(LF, $rawTS);
  2529. if (count($tmp)) {
  2530. foreach ($tmp as $tsLine) {
  2531. if (substr($tsLine, 0, 1) != '#' && $pos = strpos($tsLine, '.')) {
  2532. $parts[0] = substr($tsLine, 0, $pos);
  2533. $parts[1] = substr($tsLine, $pos + 1);
  2534. $valueParts = t3lib_div::trimExplode('=', $parts[1], true);
  2535. switch (strtolower($parts[0])) {
  2536. case 'flashvars':
  2537. $conf['flashvars.'][$valueParts[0]] = $valueParts[1];
  2538. break;
  2539. case 'params':
  2540. $conf['params.'][$valueParts[0]] = $valueParts[1];
  2541. break;
  2542. case 'attributes':
  2543. $conf['attributes.'][$valueParts[0]] = $valueParts[1];
  2544. break;
  2545. }
  2546. }
  2547. }
  2548. }
  2549. }
  2550. } elseif ($key == 'mmMediaOptionsContainer') {
  2551. foreach ($value as $val) {
  2552. if (isset($val['mmParamSet'])) {
  2553. $pName = $val['mmParamName'];
  2554. $pSet = $val['mmParamSet'];
  2555. $pValue = $pSet == 2 ? $val['mmParamValue'] : ($pSet == 0 ? 'false' : 'true');
  2556. $conf['predefined'][$pName] = $pValue;
  2557. }
  2558. }
  2559. }
  2560. }
  2561. }
  2562. // render MEDIA
  2563. if ($mode == 'url' && !$forcePlayer) {
  2564. // url is called direct, not with player
  2565. if ($url == '' && !$conf['allowEmptyUrl']) {
  2566. return '<p style="background-color: yellow;">' . $GLOBALS['TSFE']->sL('LLL:EXT:cms/locallang_ttc.xml:media.noFile', true) . '</p>';
  2567. }
  2568. $conf = array_merge($conf['mimeConf.']['swfobject.'], $conf);
  2569. $conf[$conf['type'] . '.']['player'] = strpos($url, '://') === false ? 'http://' . $url : $url;
  2570. $conf['installUrl'] = 'null';
  2571. $conf['flashvars'] = array_merge((array) $conf['flashvars'], $conf['predefined']);
  2572. }
  2573. switch ($renderType) {
  2574. case 'swf':
  2575. $conf[$conf['type'] . '.'] = array_merge($conf['mimeConf.']['swfobject.'][$conf['type'] . '.'], $typeConf);
  2576. $conf = array_merge($conf['mimeConf.']['swfobject.'], $conf);
  2577. unset($conf['mimeConf.']);
  2578. $conf['flashvars.'] = array_merge((array) $conf['flashvars.'], $conf['predefined']);
  2579. $content = $this->SWFOBJECT($conf);
  2580. break;
  2581. case 'qt':
  2582. $conf[$conf['type'] . '.'] = array_merge($conf['mimeConf.']['swfobject.'][$conf['type'] . '.'], $typeConf);
  2583. $conf = array_merge($conf['mimeConf.']['qtobject.'], $conf);
  2584. unset($conf['mimeConf.']);
  2585. $conf['params.'] = array_merge((array) $conf['params.'], $conf['predefined']);
  2586. $content = $this->QTOBJECT($conf);
  2587. break;
  2588. case 'embed':
  2589. $paramsArray = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.'], $conf['predefined']);
  2590. $conf['params']= '';
  2591. foreach ($paramsArray as $key => $value) {
  2592. $conf['params'] .= $key . '=' . $value . LF;
  2593. }
  2594. $content = $this->MULTIMEDIA($conf);
  2595. break;
  2596. default:
  2597. if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['customMediaRender'])) {
  2598. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['customMediaRender'] as $classRef) {
  2599. $hookObj = t3lib_div::getUserObj($classRef);
  2600. $conf['file'] = $url;
  2601. $conf['mode'] = $mode;
  2602. $content = $hookObj->customMediaRender($renderType, $conf, $this);
  2603. }
  2604. }
  2605. }
  2606. return $content;
  2607. }
  2608. /**
  2609. * Rendering the cObject, SWFOBJECT
  2610. *
  2611. * @param array Array of TypoScript properties
  2612. * @return string Output
  2613. */
  2614. public function SWFOBJECT($conf) {
  2615. $content = '';
  2616. $flashvars = $params = $attributes = '';
  2617. $prefix = '';
  2618. if ($GLOBALS['TSFE']->baseUrl) {
  2619. $prefix = $GLOBALS['TSFE']->baseUrl;
  2620. }
  2621. if ($GLOBALS['TSFE']->absRefPrefix) {
  2622. $prefix = $GLOBALS['TSFE']->absRefPrefix;
  2623. };
  2624. $typeConf = $conf[$conf['type'] . '.'];
  2625. //add SWFobject js-file
  2626. $GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/flashmedia/swfobject/swfobject.js');
  2627. $player = $this->stdWrap($conf[$conf['type'] . '.']['player'], $conf[$conf['type'] . '.']['player.']);
  2628. $installUrl = $conf['installUrl'] ? $conf['installUrl'] : $prefix . TYPO3_mainDir . 'contrib/flashmedia/swfobject/expressInstall.swf';
  2629. $filename = $this->stdWrap($conf['file'], $conf['file.']);
  2630. if ($filename && $conf['forcePlayer']) {
  2631. if (strpos($filename, '://') !== FALSE) {
  2632. $conf['flashvars.']['file'] = $filename;
  2633. } else {
  2634. if ($prefix) {
  2635. $conf['flashvars.']['file'] = $prefix . $filename;
  2636. } else {
  2637. $conf['flashvars.']['file'] = str_repeat('../', substr_count($player, '/')) . $filename;
  2638. }
  2639. }
  2640. } else {
  2641. $player = $filename;
  2642. }
  2643. // Write calculated values in conf for the hook
  2644. $conf['player'] = $player;
  2645. $conf['installUrl'] = $installUrl;
  2646. $conf['filename'] = $filename;
  2647. $conf['prefix'] = $prefix;
  2648. // merge with default parameters
  2649. $conf['flashvars.'] = array_merge((array) $typeConf['default.']['flashvars.'], (array) $conf['flashvars.']);
  2650. $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
  2651. $conf['attributes.'] = array_merge((array) $typeConf['default.']['attributes.'], (array) $conf['attributes.']);
  2652. $conf['embedParams'] = 'flashvars, params, attributes';
  2653. // Hook for manipulating the conf array, it's needed for some players like flowplayer
  2654. if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'])) {
  2655. foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'] as $classRef) {
  2656. t3lib_div::callUserFunction($classRef, $conf, $this);
  2657. }
  2658. }
  2659. if (is_array($conf['flashvars.'])) {
  2660. t3lib_div::remapArrayKeys($conf['flashvars.'], $typeConf['mapping.']['flashvars.']);
  2661. }
  2662. $flashvars = 'var flashvars = ' . (count($conf['flashvars.']) ? json_encode($conf['flashvars.']) : '{}') . ';';
  2663. if (is_array($conf['params.'])) {
  2664. t3lib_div::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
  2665. }
  2666. $params = 'var params = ' . (count($conf['params.']) ? json_encode($conf['params.']) : '{}') . ';';
  2667. if (is_array($conf['attributes.'])) {
  2668. t3lib_div::remapArrayKeys($conf['attributes.'], $typeConf['attributes.']['params.']);
  2669. }
  2670. $attributes = 'var attributes = ' . (count($conf['attributes.']) ? json_encode($conf['attributes.']) : '{}') . ';';
  2671. $flashVersion = $this->stdWrap($conf['flashVersion'], $conf['flashVersion.']);
  2672. if (!$flashVersion) {
  2673. $flashVersion = '9';
  2674. }
  2675. $replaceElementIdString = uniqid('mmswf');
  2676. $GLOBALS['TSFE']->register['MMSWFID'] = $replaceElementIdString;
  2677. $alternativeContent = $this->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']);
  2678. $layout = $this->stdWrap($conf['layout'], $conf['layout.']);
  2679. $layout = str_replace('###ID###', $replaceElementIdString, $layout);
  2680. $layout = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>', $layout);
  2681. $width = $this->stdWrap($conf['width'], $conf['width.']);
  2682. $height = $this->stdWrap($conf['height'], $conf['height.']);
  2683. $width = $width ? $width : $conf[$conf['type'] . '.']['defaultWidth'];
  2684. $height = $height ? $height : $conf[$conf['type'] . '.']['defaultHeight'];
  2685. $embed = 'swfobject.embedSWF("' . $conf['player'] . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '",
  2686. "' . $flashVersion . '", "' . $installUrl . '", ' . $conf['embedParams'] . ');';
  2687. $content = $layout . '
  2688. <script type="text/javascript">
  2689. ' . $flashvars . '
  2690. ' . $params . '
  2691. ' . $attributes . '
  2692. ' . $embed . '
  2693. </script>';
  2694. return $content;
  2695. }
  2696. /**
  2697. * Rendering the cObject, QTOBJECT
  2698. *
  2699. * @param array Array of TypoScript properties
  2700. * @return string Output
  2701. */
  2702. public function QTOBJECT($conf) {
  2703. $content = '';
  2704. $params = '';
  2705. $prefix = '';
  2706. if ($GLOBALS['TSFE']->baseUrl) {
  2707. $prefix = $GLOBALS['TSFE']->baseUrl;
  2708. }
  2709. if ($GLOBALS['TSFE']->absRefPrefix) {
  2710. $prefix = $GLOBALS['TSFE']->absRefPrefix;
  2711. }
  2712. $filename = $this->stdWrap($conf['file'],$conf['file.']);
  2713. $typeConf = $conf[$conf['type'] . '.'];
  2714. //add QTobject js-file
  2715. $GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/flashmedia/qtobject/qtobject.js');
  2716. $replaceElementIdString = uniqid('mmqt');
  2717. $GLOBALS['TSFE']->register['MMQTID'] = $replaceElementIdString;
  2718. $qtObject = 'QTObject' . $replaceElementIdString;
  2719. // merge with default parameters
  2720. $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
  2721. if (is_array($conf['params.'])) {
  2722. t3lib_div::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
  2723. foreach ($conf['params.'] as $key => $value) {
  2724. $params .= $qtObject . '.addParam("' .$key . '", "' . $value . '");' . LF;
  2725. }
  2726. }
  2727. $params = ($params ? substr($params, 0, -2) : '') . LF . $qtObject . '.write("' . $replaceElementIdString . '");';
  2728. $alternativeContent = $this->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']);
  2729. $layout = $this->stdWrap($conf['layout'], $conf['layout.']);
  2730. $layout = str_replace('###ID###', $replaceElementIdString, $layout);
  2731. $layout = str_replace('###QTOBJECT###', '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>', $layout);
  2732. $width = $this->stdWrap($conf['width'], $conf['width.']);
  2733. $height = $this->stdWrap($conf['height'], $conf['height.']);
  2734. $width = $width ? $width : $conf[$conf['type'] . '.']['defaultWidth'];
  2735. $height = $height ? $height : $conf[$conf['type'] . '.']['defaultHeight'];
  2736. $embed = 'var ' . $qtObject . ' = new QTObject("' . $prefix . $filename . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '");';
  2737. $content = $layout . '
  2738. <script type="text/javascript">
  2739. ' . $embed . '
  2740. ' . $params . '
  2741. </script>';
  2742. return $content;
  2743. }
  2744. /************************************
  2745. *
  2746. * Various helper functions for content objects:
  2747. *
  2748. ************************************/
  2749. /**
  2750. * Converts a given config in Flexform to a conf-Array
  2751. * @param string Flexform data
  2752. * @param array Array to write the data into, by reference
  2753. * @param boolean is set if called recursive. Don't call function with this parameter, it's used inside the function only
  2754. * @access public
  2755. *
  2756. */
  2757. public function readFlexformIntoConf($flexData, &$conf, $recursive=FALSE) {
  2758. if ($recursive === FALSE) {
  2759. $flexData = t3lib_div::xml2array($flexData, 'T3');
  2760. }
  2761. if (is_array($flexData)) {
  2762. if (isset($flexData['data']['sDEF']['lDEF'])) {
  2763. $flexData = $flexData['data']['sDEF']['lDEF'];
  2764. }
  2765. foreach ($flexData as $key => $value) {
  2766. if (is_array($value['el']) && count($value['el']) > 0) {
  2767. foreach ($value['el'] as $ekey => $element) {
  2768. if (isset($element['vDEF'])) {
  2769. $conf[$ekey] = $element['vDEF'];
  2770. } else {
  2771. if(is_array($element)) {
  2772. $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
  2773. } else {
  2774. $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
  2775. }
  2776. }
  2777. }
  2778. } else {
  2779. $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
  2780. }
  2781. if ($value['vDEF']) {
  2782. $conf[$key] = $value['vDEF'];
  2783. }
  2784. }
  2785. }
  2786. }
  2787. /**
  2788. * Returns all parents of the given PID (Page UID) list
  2789. *
  2790. * @param string A list of page Content-Element PIDs (Page UIDs) / stdWrap
  2791. * @param array stdWrap array for the list
  2792. * @return string A list of PIDs
  2793. * @access private
  2794. */
  2795. function getSlidePids($pidList, $pidConf) {
  2796. $pidList = trim($this->stdWrap($pidList,$pidConf));
  2797. if (!strcmp($pidList,'')) {
  2798. $pidList = 'this';
  2799. }
  2800. if (trim($pidList)) {
  2801. $listArr = t3lib_div::intExplode(',',str_replace('this',$GLOBALS['TSFE']->contentPid,$pidList));
  2802. $listArr = $this->checkPidArray($listArr);
  2803. }
  2804. $pidList = array();
  2805. if (is_array($listArr)&&count($listArr)) {
  2806. foreach ($listArr as $uid) {
  2807. $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
  2808. if (!$page['is_siteroot']) {
  2809. $pidList[] = $page['pid'];
  2810. }
  2811. }
  2812. }
  2813. return implode(',', $pidList);
  2814. }
  2815. /**
  2816. * Returns a default value for a form field in the FORM cObject.
  2817. * Page CANNOT be cached because that would include the inserted value for the current user.
  2818. *
  2819. * @param boolean If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned.
  2820. * @param string $fieldName: The POST var name to get default value for
  2821. * @param string $defaultVal: The current default value
  2822. * @return string The default value, either from INPUT var or the current default, based on whether caching is enabled or not.
  2823. * @access private
  2824. */
  2825. function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
  2826. if (!$GLOBALS['TSFE']->no_cache || (!isset($_POST[$fieldName]) && !isset($_GET[$fieldName])) || $noValueInsert) {
  2827. return $defaultVal;
  2828. } else {
  2829. return t3lib_div::_GP($fieldName);
  2830. }
  2831. }
  2832. /**
  2833. * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
  2834. * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript. This function is called by "$this->cImage($conf['file'],$conf);" from IMAGE().
  2835. *
  2836. * @param string File TypoScript resource
  2837. * @param array TypoScript configuration properties
  2838. * @return string <img> tag, (possibly wrapped in links and other HTML) if any image found.
  2839. * @access private
  2840. * @see IMAGE()
  2841. */
  2842. function cImage($file,$conf) {
  2843. $info = $this->getImgResource($file,$conf['file.']);
  2844. $GLOBALS['TSFE']->lastImageInfo=$info;
  2845. if (is_array($info)) {
  2846. $info[3] = t3lib_div::png_to_gif_by_imagemagick($info[3]);
  2847. $GLOBALS['TSFE']->imagesOnPage[]=$info[3]; // This array is used to collect the image-refs on the page...
  2848. if (!strlen($conf['altText']) && !is_array($conf['altText.'])) { // Backwards compatible:
  2849. if ($conf['altText'] || $conf['altText.']) {
  2850. $GLOBALS['TSFE']->logDeprecatedTyposcript('IMAGE.alttext');
  2851. }
  2852. $conf['altText'] = $conf['alttext'];
  2853. $conf['altText.'] = $conf['alttext.'];
  2854. }
  2855. $altParam = $this->getAltParam($conf);
  2856. $theValue = '<img src="'.htmlspecialchars($GLOBALS['TSFE']->absRefPrefix.t3lib_div::rawUrlEncodeFP($info[3])).'" width="'.$info[0].'" height="'.$info[1].'"'.$this->getBorderAttr(' border="'.intval($conf['border']).'"').(($conf['params'] || is_array($conf['params.']))?' '.$this->stdWrap($conf['params'],$conf['params.']):'').($altParam).' />';
  2857. if ($conf['linkWrap']) {
  2858. $theValue = $this->linkWrap($theValue,$conf['linkWrap']);
  2859. } elseif ($conf['imageLinkWrap']) {
  2860. $theValue = $this->imageLinkWrap($theValue,$info['origFile'],$conf['imageLinkWrap.']);
  2861. }
  2862. return $this->wrap($theValue,$conf['wrap']);
  2863. }
  2864. }
  2865. /**
  2866. * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict,xhtml_11 or xhtml_2 or if the config parameter 'disableImgBorderAttr' is not set.
  2867. *
  2868. * @param string the border attribute
  2869. * @return string the border attribute
  2870. */
  2871. function getBorderAttr($borderAttr) {
  2872. if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2',$GLOBALS['TSFE']->xhtmlDoctype) && !$GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) {
  2873. return $borderAttr;
  2874. }
  2875. }
  2876. /**
  2877. * Wraps the input string in link-tags that opens the image in a new window.
  2878. *
  2879. * @param string String to wrap, probably an <img> tag
  2880. * @param string The original image file
  2881. * @param array TypoScript properties for the "imageLinkWrap" function
  2882. * @return string The input string, $string, wrapped as configured.
  2883. * @see cImage()
  2884. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=316&cHash=2848266da6
  2885. */
  2886. function imageLinkWrap($string,$imageFile,$conf) {
  2887. $a1='';
  2888. $a2='';
  2889. $content=$string;
  2890. if ($this->stdWrap($conf['enable'],$conf['enable.'])) {
  2891. $content=$this->typolink($string, $conf['typolink.']);
  2892. $imageFile = $this->stdWrap($imageFile, $conf['file.']);
  2893. // imageFileLink:
  2894. if ($content==$string && @is_file($imageFile)) {
  2895. $params = '';
  2896. if ($conf['width']) {$params.='&width='.rawurlencode($conf['width']);}
  2897. if ($conf['height']) {$params.='&height='.rawurlencode($conf['height']);}
  2898. if ($conf['effects']) {$params.='&effects='.rawurlencode($conf['effects']);}
  2899. if ($conf['sample']) {$params.='&sample=1';}
  2900. if ($conf['alternativeTempPath']) {$params.='&alternativeTempPath='.rawurlencode($conf['alternativeTempPath']);}
  2901. if ($conf['bodyTag']) {$params.='&bodyTag='.rawurlencode($conf['bodyTag']);}
  2902. if ($conf['title']) {$params.='&title='.rawurlencode($conf['title']);}
  2903. if ($conf['wrap']) {$params.='&wrap='.rawurlencode($conf['wrap']);}
  2904. $md5_value = md5(
  2905. $imageFile.'|'.
  2906. $conf['width'].'|'.
  2907. $conf['height'].'|'.
  2908. $conf['effects'].'|'.
  2909. $conf['bodyTag'].'|'.
  2910. $conf['title'].'|'.
  2911. $conf['wrap'].'|'.
  2912. $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'].'|');
  2913. $params.= '&md5='.$md5_value;
  2914. $url = $GLOBALS['TSFE']->absRefPrefix.'index.php?eID=tx_cms_showpic&file='.rawurlencode($imageFile).$params;
  2915. if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
  2916. $altUrl = $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.']);
  2917. if ($altUrl) {
  2918. $url = $altUrl . ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file='.rawurlencode($imageFile).$params);
  2919. }
  2920. }
  2921. // Create TARGET-attribute only if the right doctype is used
  2922. if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
  2923. if (isset($conf['target'])) {
  2924. $target = sprintf(' target="%s"', $conf['target']);
  2925. } else {
  2926. $target = ' target="thePicture"';
  2927. }
  2928. } else {
  2929. $target = '';
  2930. }
  2931. if ($conf['JSwindow']) {
  2932. $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
  2933. $gifCreator->init();
  2934. $gifCreator->mayScaleUp = 0;
  2935. $dims = $gifCreator->getImageScale($gifCreator->getImageDimensions($imageFile),$conf['width'],$conf['height'],'');
  2936. $offset = t3lib_div::intExplode(',',$conf['JSwindow.']['expand'].',');
  2937. $a1='<a href="'. htmlspecialchars($url) .'" onclick="'.
  2938. htmlspecialchars('openPic(\''.$GLOBALS['TSFE']->baseUrlWrap($url).'\',\''.($conf['JSwindow.']['newWindow']?md5($url):'thePicture').'\',\'width='.($dims[0]+$offset[0]).',height='.($dims[1]+$offset[1]).',status=0,menubar=0\'); return false;').
  2939. '"'.$target.$GLOBALS['TSFE']->ATagParams.'>';
  2940. $a2='</a>';
  2941. $GLOBALS['TSFE']->setJS('openPic');
  2942. } else {
  2943. $a1='<a href="'.htmlspecialchars($url).'"'.$target.$GLOBALS['TSFE']->ATagParams.'>';
  2944. $a2='</a>';
  2945. }
  2946. $string = $this->stdWrap($string,$conf['stdWrap.']);
  2947. $content=$a1.$string.$a2;
  2948. }
  2949. }
  2950. return $content;
  2951. }
  2952. /**
  2953. * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is.
  2954. *
  2955. * @param string The filename, being a TypoScript resource data type
  2956. * @param string Additional parameters (attributes). Default is empty alt and title tags.
  2957. * @return string If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string
  2958. * @see FILE()
  2959. */
  2960. function fileResource($fName, $addParams='alt="" title=""') {
  2961. $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName);
  2962. if ($incFile) {
  2963. $fileinfo = t3lib_div::split_fileref($incFile);
  2964. if (t3lib_div::inList('jpg,gif,jpeg,png',$fileinfo['fileext'])) {
  2965. $imgFile = $incFile;
  2966. $imgInfo = @getImageSize($imgFile);
  2967. return '<img src="'.$GLOBALS['TSFE']->absRefPrefix.$imgFile.'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'"'.$this->getBorderAttr(' border="0"').' '.$addParams.' />';
  2968. } elseif (filesize($incFile)<1024*1024) {
  2969. return $GLOBALS['TSFE']->tmpl->fileContent($incFile);
  2970. }
  2971. }
  2972. }
  2973. /**
  2974. * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value.
  2975. * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content.
  2976. * Therefore you should call this function with the last-changed timestamp of any element you display.
  2977. *
  2978. * @param integer Unix timestamp (number of seconds since 1970)
  2979. * @return void
  2980. * @see tslib_fe::setSysLastChanged()
  2981. */
  2982. function lastChanged($tstamp) {
  2983. $tstamp = intval($tstamp);
  2984. if ($tstamp>intval($GLOBALS['TSFE']->register['SYS_LASTCHANGED'])) {
  2985. $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp;
  2986. }
  2987. }
  2988. /**
  2989. * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well.
  2990. * 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.
  2991. *
  2992. * @param string Input string
  2993. * @param string A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string
  2994. * @return string Wrapped output string
  2995. * @see wrap(), cImage(), FILE()
  2996. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=282&cHash=831a95115d
  2997. */
  2998. function linkWrap($content,$wrap) {
  2999. $wrapArr = explode('|', $wrap);
  3000. if (preg_match('/\{([0-9]*)\}/',$wrapArr[0],$reg)) {
  3001. if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) {
  3002. $wrapArr[0] = str_replace($reg[0],$uid,$wrapArr[0]);
  3003. }
  3004. }
  3005. return trim($wrapArr[0]).$content.trim($wrapArr[1]);
  3006. }
  3007. /**
  3008. * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element.
  3009. * From the $conf array it implements the properties "altText", "titleText" and "longdescURL"
  3010. *
  3011. * @param array TypoScript configuration properties
  3012. * @param boolean If set, the longdesc attribute will be generated - must only be used for img elements!
  3013. * @return string Parameter string containing alt and title parameters (if any)
  3014. * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink()
  3015. */
  3016. function getAltParam($conf, $longDesc=true) {
  3017. $altText = trim($this->stdWrap($conf['altText'], $conf['altText.']));
  3018. $titleText = trim($this->stdWrap($conf['titleText'],$conf['titleText.']));
  3019. $longDesc = trim($this->stdWrap($conf['longdescURL'],$conf['longdescURL.']));
  3020. // "alt":
  3021. $altParam = ' alt="'.htmlspecialchars($altText).'"';
  3022. // "title":
  3023. $emptyTitleHandling = 'useAlt';
  3024. if ($conf['emptyTitleHandling']) {
  3025. // choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
  3026. $emptyTitleHandling = $conf['emptyTitleHandling'];
  3027. }
  3028. if ($titleText || $emptyTitleHandling == 'keepEmpty') {
  3029. $altParam.= ' title="'.htmlspecialchars($titleText).'"';
  3030. } elseif (!$titleText && $emptyTitleHandling == 'useAlt') {
  3031. $altParam.= ' title="'.htmlspecialchars($altText).'"';
  3032. }
  3033. // "longDesc" URL
  3034. if ($longDesc) {
  3035. $altParam.= ' longdesc="'.htmlspecialchars(strip_tags($longDesc)).'"';
  3036. }
  3037. return $altParam;
  3038. }
  3039. /**
  3040. * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields
  3041. *
  3042. * @param string Input string
  3043. * @return string the cleaned string
  3044. * @see FORM()
  3045. */
  3046. function cleanFormName($name) {
  3047. // turn data[x][y] into data:x:y:
  3048. $name = preg_replace('/\[|\]\[?/',':',trim($name));
  3049. // remove illegal chars like _
  3050. return preg_replace('#[^:a-zA-Z0-9]#','',$name);
  3051. }
  3052. /**
  3053. * An abstraction method to add parameters to an A tag.
  3054. * Uses the ATagParams property.
  3055. *
  3056. * @param array TypoScript configuration properties
  3057. * @param boolean If set, will add the global config.ATagParams to the link
  3058. * @return string String containing the parameters to the A tag (if non empty, with a leading space)
  3059. * @see IMGTEXT(), filelink(), makelinks(), typolink()
  3060. */
  3061. function getATagParams($conf, $addGlobal=1) {
  3062. $aTagParams = '';
  3063. if ($conf['ATagParams.']) {
  3064. $aTagParams = ' '.$this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
  3065. } elseif ($conf['ATagParams']) {
  3066. $aTagParams = ' '.$conf['ATagParams'];
  3067. }
  3068. if ($addGlobal) {
  3069. $aTagParams = ' '.trim($GLOBALS['TSFE']->ATagParams.$aTagParams);
  3070. }
  3071. return $aTagParams;
  3072. }
  3073. /**
  3074. * All extension links should ask this function for additional properties to their tags.
  3075. * Designed to add for instance an "onclick" property for site tracking systems.
  3076. *
  3077. * @param string URL of the website
  3078. * @return string the additional tag properties
  3079. */
  3080. function extLinkATagParams($URL, $TYPE) {
  3081. $out = '';
  3082. if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
  3083. $extLinkATagParamsHandler = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']);
  3084. if(method_exists($extLinkATagParamsHandler, 'main')) {
  3085. $out.= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
  3086. }
  3087. }
  3088. return trim($out) ? ' '.trim($out) : '' ;
  3089. }
  3090. /***********************************************
  3091. *
  3092. * HTML template processing functions
  3093. *
  3094. ***********************************************/
  3095. /**
  3096. * Returns a subpart from the input content stream.
  3097. * A subpart is a part of the input stream which is encapsulated in a
  3098. * string matching the input string, $marker. If this string is found
  3099. * inside of HTML comment tags the start/end points of the content block
  3100. * returned will be that right outside that comment block.
  3101. * Example: The contennt string is
  3102. * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?"
  3103. * If $marker is "###sub1###" then the content returned is
  3104. * " World. How are ". The input content string could just as well have
  3105. * been "Hello ###sub1### World. How are ###sub1### you?" and the result
  3106. * would be the same
  3107. * Wrapper for t3lib_parsehtml::getSubpart which behaves identical
  3108. *
  3109. * @param string The content stream, typically HTML template content.
  3110. * @param string The marker string, typically on the form "###[the marker string]###"
  3111. * @return string The subpart found, if found.
  3112. * @see substituteSubpart(), t3lib_parsehtml::getSubpart()
  3113. */
  3114. public function getSubpart($content, $marker) {
  3115. return t3lib_parsehtml::getSubpart($content, $marker);
  3116. }
  3117. /**
  3118. * Substitute subpart in input template stream.
  3119. * This function substitutes a subpart in $content with the content of
  3120. * $subpartContent.
  3121. * Wrapper for t3lib_parsehtml::substituteSubpart which behaves identical
  3122. *
  3123. * @param string The content stream, typically HTML template content.
  3124. * @param string The marker string, typically on the form "###[the marker string]###"
  3125. * @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.
  3126. * @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!
  3127. * @return string The processed HTML content string.
  3128. * @see getSubpart(), t3lib_parsehtml::substituteSubpart()
  3129. */
  3130. public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) {
  3131. return t3lib_parsehtml::substituteSubpart(
  3132. $content,
  3133. $marker,
  3134. $subpartContent,
  3135. $recursive
  3136. );
  3137. }
  3138. /**
  3139. * Substitues multiple subparts at once
  3140. *
  3141. * @param string The content stream, typically HTML template content.
  3142. * @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.
  3143. * @return string The processed HTML content string.
  3144. */
  3145. public function substituteSubpartArray($content, array $subpartsContent) {
  3146. return t3lib_parsehtml::substituteSubpartArray(
  3147. $content,
  3148. $subpartsContent
  3149. );
  3150. }
  3151. /**
  3152. * Substitutes a marker string in the input content
  3153. * (by a simple str_replace())
  3154. *
  3155. * @param string The content stream, typically HTML template content.
  3156. * @param string The marker string, typically on the form "###[the marker string]###"
  3157. * @param mixed The content to insert instead of the marker string found.
  3158. * @return string The processed HTML content string.
  3159. * @see substituteSubpart()
  3160. */
  3161. public function substituteMarker($content, $marker, $markContent) {
  3162. return t3lib_parsehtml::substituteMarker(
  3163. $content,
  3164. $marker,
  3165. $markContent
  3166. );
  3167. }
  3168. /**
  3169. * Multi substitution function with caching.
  3170. *
  3171. * This function should be a one-stop substitution function for working
  3172. * with HTML-template. It does not substitute by str_replace but by
  3173. * splitting. This secures that the value inserted does not themselves
  3174. * contain markers or subparts.
  3175. *
  3176. * Note that the "caching" won't cache the content of the substition,
  3177. * but only the splitting of the template in various parts. So if you
  3178. * want only one cache-entry per template, make sure you always pass the
  3179. * exact same set of marker/subpart keys. Else you will be flooding the
  3180. * users cache table.
  3181. *
  3182. * This function takes three kinds of substitutions in one:
  3183. * $markContentArray is a regular marker-array where the 'keys' are
  3184. * substituted in $content with their values
  3185. *
  3186. * $subpartContentArray works exactly like markContentArray only is whole
  3187. * subparts substituted and not only a single marker.
  3188. *
  3189. * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where
  3190. * the subparts pointed to by the main key is wrapped with the 0/1 value
  3191. * alternating.
  3192. *
  3193. * @param string The content stream, typically HTML template content.
  3194. * @param array Regular marker-array where the 'keys' are substituted in $content with their values
  3195. * @param array Exactly like markContentArray only is whole subparts substituted and not only a single marker.
  3196. * @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.
  3197. * @return string The output content stream
  3198. * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE()
  3199. */
  3200. public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) {
  3201. $GLOBALS['TT']->push('substituteMarkerArrayCached');
  3202. // If not arrays then set them
  3203. if (is_null($markContentArray)) $markContentArray=array(); // Plain markers
  3204. if (is_null($subpartContentArray)) $subpartContentArray=array(); // Subparts being directly substituted
  3205. if (is_null($wrappedSubpartContentArray)) $wrappedSubpartContentArray=array(); // Subparts being wrapped
  3206. // Finding keys and check hash:
  3207. $sPkeys = array_keys($subpartContentArray);
  3208. $wPkeys = array_keys($wrappedSubpartContentArray);
  3209. $aKeys = array_merge(array_keys($markContentArray),$sPkeys,$wPkeys);
  3210. if (!count($aKeys)) {
  3211. $GLOBALS['TT']->pull();
  3212. return $content;
  3213. }
  3214. asort($aKeys);
  3215. $storeKey = md5('substituteMarkerArrayCached_storeKey:'.serialize(array($content,$aKeys)));
  3216. if ($this->substMarkerCache[$storeKey]) {
  3217. $storeArr = $this->substMarkerCache[$storeKey];
  3218. $GLOBALS['TT']->setTSlogMessage('Cached',0);
  3219. } else {
  3220. $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey);
  3221. if (!isset($storeArrDat)) {
  3222. // Initialize storeArr
  3223. $storeArr=array();
  3224. // Finding subparts and substituting them with the subpart as a marker
  3225. foreach ($sPkeys as $sPK) {
  3226. $content =$this->substituteSubpart($content,$sPK,$sPK);
  3227. }
  3228. // Finding subparts and wrapping them with markers
  3229. foreach ($wPkeys as $wPK) {
  3230. $content =$this->substituteSubpart($content,$wPK,array($wPK,$wPK));
  3231. }
  3232. // traverse keys and quote them for reg ex.
  3233. foreach ($aKeys as $tK => $tV) {
  3234. $aKeys[$tK] = preg_quote($tV, '/');
  3235. }
  3236. $regex = '/' . implode('|', $aKeys) . '/';
  3237. // Doing regex's
  3238. $storeArr['c'] = preg_split($regex, $content);
  3239. preg_match_all($regex, $content, $keyList);
  3240. $storeArr['k']=$keyList[0];
  3241. // Setting cache:
  3242. $this->substMarkerCache[$storeKey] = $storeArr;
  3243. // Storing the cached data:
  3244. $GLOBALS['TSFE']->sys_page->storeHash($storeKey, serialize($storeArr), 'substMarkArrayCached');
  3245. $GLOBALS['TT']->setTSlogMessage('Parsing',0);
  3246. } else {
  3247. // Unserializing
  3248. $storeArr = unserialize($storeArrDat);
  3249. // Setting cache:
  3250. $this->substMarkerCache[$storeKey] = $storeArr;
  3251. $GLOBALS['TT']->setTSlogMessage('Cached from DB',0);
  3252. }
  3253. }
  3254. // Substitution/Merging:
  3255. // Merging content types together, resetting
  3256. $valueArr = array_merge($markContentArray,$subpartContentArray,$wrappedSubpartContentArray);
  3257. $wSCA_reg=array();
  3258. $content = '';
  3259. // traversing the keyList array and merging the static and dynamic content
  3260. foreach ($storeArr['k'] as $n => $keyN) {
  3261. $content.=$storeArr['c'][$n];
  3262. if (!is_array($valueArr[$keyN])) {
  3263. $content.=$valueArr[$keyN];
  3264. } else {
  3265. $content.=$valueArr[$keyN][(intval($wSCA_reg[$keyN])%2)];
  3266. $wSCA_reg[$keyN]++;
  3267. }
  3268. }
  3269. $content.=$storeArr['c'][count($storeArr['k'])];
  3270. $GLOBALS['TT']->pull();
  3271. return $content;
  3272. }
  3273. /**
  3274. * Traverses the input $markContentArray array and for each key the marker
  3275. * by the same name (possibly wrapped and in upper case) will be
  3276. * substituted with the keys value in the array.
  3277. *
  3278. * This is very useful if you have a data-record to substitute in some
  3279. * content. In particular when you use the $wrap and $uppercase values to
  3280. * pre-process the markers. Eg. a key name like "myfield" could effectively
  3281. * be represented by the marker "###MYFIELD###" if the wrap value
  3282. * was "###|###" and the $uppercase boolean true.
  3283. *
  3284. * @param string The content stream, typically HTML template content.
  3285. * @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.
  3286. * @param string A wrap value - [part 1] | [part 2] - for the markers before substitution
  3287. * @param boolean If set, all marker string substitution is done with upper-case markers.
  3288. * @param boolean If set, all unused marker are deleted.
  3289. * @return string The processed output stream
  3290. * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
  3291. */
  3292. public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = false, $deleteUnused = false) {
  3293. return t3lib_parsehtml::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
  3294. }
  3295. /**
  3296. * Substitute marker array in an array of values
  3297. *
  3298. * @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)
  3299. * @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.
  3300. * @return mixed The processed input variable.
  3301. * @see substituteMarker()
  3302. */
  3303. public function substituteMarkerInObject(&$tree, array $markContentArray) {
  3304. if (is_array ($tree)) {
  3305. foreach ($tree as $key => $value) {
  3306. $this->substituteMarkerInObject ($tree[$key], $markContentArray);
  3307. }
  3308. } else {
  3309. $tree = $this->substituteMarkerArray($tree, $markContentArray);
  3310. }
  3311. return $tree;
  3312. }
  3313. /**
  3314. * Adds elements to the input $markContentArray based on the values from
  3315. * the fields from $fieldList found in $row
  3316. *
  3317. * @param array Array with key/values being marker-strings/substitution values.
  3318. * @param array An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray
  3319. * @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)
  3320. * @param boolean If set, all values added to $markContentArray will be nl2br()'ed
  3321. * @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 "###"
  3322. * @param boolean If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance.
  3323. * @return array The modified $markContentArray
  3324. */
  3325. public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = true, $prefix = 'FIELD_', $HSC = false) {
  3326. if ($fieldList) {
  3327. $fArr = t3lib_div::trimExplode(',', $fieldList, 1);
  3328. foreach ($fArr as $field) {
  3329. $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field]) : $row[$field];
  3330. }
  3331. } else {
  3332. if (is_array($row)) {
  3333. foreach ($row as $field => $value) {
  3334. if (!t3lib_div::testInt($field)) {
  3335. if ($HSC) {
  3336. $value = htmlspecialchars($value);
  3337. }
  3338. $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value) : $value;
  3339. }
  3340. }
  3341. }
  3342. }
  3343. return $markContentArray;
  3344. }
  3345. /***********************************************
  3346. *
  3347. * "stdWrap" + sub functions
  3348. *
  3349. ***********************************************/
  3350. /**
  3351. * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript.
  3352. * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array (holding the TypoScript "stdWrap properties")
  3353. * 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.
  3354. *
  3355. * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData
  3356. *
  3357. * @param string Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
  3358. * @param array TypoScript "stdWrap properties".
  3359. * @return string The processed input value
  3360. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=314&cHash=02ab044c7b
  3361. */
  3362. function stdWrap($content,$conf) {
  3363. if (is_array($conf)) {
  3364. foreach($this->stdWrapHookObjects as $hookObject) {
  3365. $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
  3366. }
  3367. // Setting current value, if so
  3368. if ($conf['setContentToCurrent']){$this->data[$this->currentValKey]=$content;}
  3369. if ($conf['setCurrent'] || $conf['setCurrent.']){$this->data[$this->currentValKey] = $this->stdWrap($conf['setCurrent'], $conf['setCurrent.']);}
  3370. // Getting data:
  3371. if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) {
  3372. $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']];
  3373. }
  3374. if ($conf['data']){$content=$this->getData($conf['data'], is_array($this->alternativeData)?$this->alternativeData:$this->data);}
  3375. $this->alternativeData=''; // This must be unset directly after
  3376. if ($conf['field']) {$content=$this->getFieldVal($conf['field']);}
  3377. if ($conf['current']) {$content=$this->data[$this->currentValKey];}
  3378. if ($conf['cObject']) {$content=$this->cObjGetSingle($conf['cObject'],$conf['cObject.'],'/stdWrap/.cObject');}
  3379. if ($conf['numRows.']) {$content=$this->numRows($conf['numRows.']);}
  3380. if ($conf['filelist'] || $conf['filelist.']) {$content=$this->filelist($this->stdWrap($conf['filelist'], $conf['filelist.']));}
  3381. if ($conf['preUserFunc']) {$content = $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);}
  3382. foreach($this->stdWrapHookObjects as $hookObject) {
  3383. $content = $hookObject->stdWrapOverride($content, $conf, $this);
  3384. }
  3385. // Overriding values, evaluating conditions
  3386. if ($conf['override'] || $conf['override.']){
  3387. $override = $this->stdWrap($conf['override'], $conf['override.']);
  3388. if (trim($override)) {$content=$override;}
  3389. }
  3390. if (isset($conf['preIfEmptyListNum']) || isset($conf['preIfEmptyListNum.']['stdWrap.'])) {
  3391. $preIfEmptyListNumber = isset($conf['preIfEmptyListNum.']['stdWrap.']) ? $this->stdWrap($conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['stdWrap.']) : $conf['preIfEmptyListNum'];
  3392. $content=$this->listNum($content,$preIfEmptyListNumber,$conf['preIfEmptyListNum.']['splitChar']);
  3393. }
  3394. if (!trim($content) && ($conf['ifEmpty'] || $conf['ifEmpty.'])) {
  3395. $content = $this->stdWrap($conf['ifEmpty'], $conf['ifEmpty.']);
  3396. }
  3397. if (!strlen(trim($content)) && ($conf['ifBlank'] || $conf['ifBlank.'])) {
  3398. $content = $this->stdWrap($conf['ifBlank'], $conf['ifBlank.']);
  3399. }
  3400. // values...
  3401. if (isset($conf['listNum']) || isset($conf['listNum.']['stdWrap.'])) {
  3402. $listNumber = isset($conf['listNum.']['stdWrap.']) ? $this->stdWrap($conf['listNum'], $conf['listNum.']['stdWrap.']) : $conf['listNum'];
  3403. $content=$this->listNum($content,$listNumber,$conf['listNum.']['splitChar']);
  3404. }
  3405. if ($conf['trim']) { $content=trim($content); }
  3406. // Call stdWrap recursively
  3407. if ($conf['stdWrap.']) { $content=$this->stdWrap($content,$conf['stdWrap.']); }
  3408. foreach($this->stdWrapHookObjects as $hookObject) {
  3409. $content = $hookObject->stdWrapProcess($content, $conf, $this);
  3410. }
  3411. if ( ($conf['required'] && (string)$content=='') || ($conf['if.'] && !$this->checkIf($conf['if.'])) || ($conf['fieldRequired'] && !trim($this->data[$conf['fieldRequired']])) ){
  3412. $content = '';
  3413. } else {
  3414. // Perform data processing:
  3415. if ($conf['csConv']) { $content=$GLOBALS['TSFE']->csConv($content,$conf['csConv']); }
  3416. if ($conf['parseFunc.'] || $conf['parseFunc']) {$content=$this->parseFunc($content,$conf['parseFunc.'],$conf['parseFunc']);}
  3417. if ($conf['HTMLparser'] && is_array($conf['HTMLparser.'])) {$content=$this->HTMLparser_TSbridge($content,$conf['HTMLparser.']);}
  3418. if ($conf['split.']){$content=$this->splitObj($content,$conf['split.']);}
  3419. if ($conf['prioriCalc']){$content=t3lib_div::calcParenthesis($content); if ($conf['prioriCalc']=='intval') $content=intval($content);}
  3420. if ((string)$conf['char']!=''){$content=chr(intval($conf['char']));}
  3421. if ($conf['intval']){$content=intval($content);}
  3422. if ($conf['date']) {
  3423. $content = ($conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content));
  3424. }
  3425. if ($conf['strftime']) {
  3426. $content = ($conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content));
  3427. $tmp_charset = $conf['strftime.']['charset'] ? $conf['strftime.']['charset'] : $GLOBALS['TSFE']->localeCharset;
  3428. if ($tmp_charset) {
  3429. $content = $GLOBALS['TSFE']->csConv($content,$tmp_charset);
  3430. }
  3431. }
  3432. if ($conf['age']) {
  3433. $content = $this->calcAge($GLOBALS['EXEC_TIME'] - $content, $conf['age']);
  3434. }
  3435. if ($conf['case']){$content=$this->HTMLcaseshift($content, $conf['case']);}
  3436. if ($conf['bytes']){$content=t3lib_div::formatSize($content, $conf['bytes.']['labels']);}
  3437. if ($conf['substring']){$content=$this->substring($content,$conf['substring']);}
  3438. if ($conf['removeBadHTML']) {$content = $this->removeBadHTML($content, $conf['removeBadHTML.']);}
  3439. if ($conf['cropHTML']) {$content=$this->cropHTML($content, $conf['cropHTML']);}
  3440. if ($conf['stripHtml']){$content = strip_tags($content);}
  3441. if ($conf['crop']){$content=$this->crop($content, $conf['crop']);}
  3442. if ($conf['rawUrlEncode']){$content = rawurlencode($content);}
  3443. if ($conf['htmlSpecialChars']){
  3444. $content=htmlSpecialChars($content);
  3445. if ($conf['htmlSpecialChars.']['preserveEntities']) $content = t3lib_div::deHSCentities($content);
  3446. }
  3447. if ($conf['doubleBrTag']) {
  3448. $content=preg_replace("/\r?\n[\t ]*\r?\n/",$conf['doubleBrTag'],$content);
  3449. }
  3450. if ($conf['br']) {$content=nl2br($content);}
  3451. if ($conf['brTag']) {$content= str_replace(LF,$conf['brTag'],$content);}
  3452. if ($conf['encapsLines.']) {$content=$this->encaps_lineSplit($content,$conf['encapsLines.']);}
  3453. if ($conf['keywords']) {$content= $this->keywords($content);}
  3454. if ($conf['innerWrap'] || $conf['innerWrap.']){$content=$this->wrap($content, $this->stdWrap($conf['innerWrap'], $conf['innerWrap.']));}
  3455. if ($conf['innerWrap2'] || $conf['innerWrap2.']){$content=$this->wrap($content, $this->stdWrap($conf['innerWrap2'], $conf['innerWrap2.']));}
  3456. if ($conf['fontTag']){$content=$this->wrap($content, $conf['fontTag']);}
  3457. if ($conf['addParams.']) {$content=$this->addParams($content,$conf['addParams.']);}
  3458. if ($conf['textStyle.']) {$content=$this->textStyle($content,$conf['textStyle.']);}
  3459. if ($conf['tableStyle.']) {$content=$this->tableStyle($content,$conf['tableStyle.']);}
  3460. if ($conf['filelink.']) {$content=$this->filelink($content,$conf['filelink.']);}
  3461. if ($conf['preCObject']) {$content=$this->cObjGetSingle($conf['preCObject'],$conf['preCObject.'],'/stdWrap/.preCObject').$content;}
  3462. if ($conf['postCObject']) {$content.=$this->cObjGetSingle($conf['postCObject'],$conf['postCObject.'],'/stdWrap/.postCObject');}
  3463. if ($conf['wrapAlign'] || $conf['wrapAlign.']){
  3464. $wrapAlign = trim($this->stdWrap($conf['wrapAlign'], $conf['wrapAlign.']));
  3465. if ($wrapAlign) {$content=$this->wrap($content, '<div style="text-align:'.$wrapAlign.';">|</div>');}
  3466. }
  3467. if ($conf['typolink.']){$content=$this->typolink($content, $conf['typolink.']);}
  3468. if (is_array($conf['TCAselectItem.'])) {$content=$this->TCAlookup($content,$conf['TCAselectItem.']);}
  3469. // Spacing
  3470. if ($conf['space'] || $conf['space.']) {
  3471. $space = trim($this->stdWrap($conf['space'], $conf['space.']));
  3472. $content = $this->wrapSpace($content, $space, $conf['space.']);
  3473. }
  3474. $spaceBefore = '';
  3475. if ($conf['spaceBefore'] || $conf['spaceBefore.']) {
  3476. $spaceBefore = trim($this->stdWrap($conf['spaceBefore'], $conf['spaceBefore.']));
  3477. }
  3478. $spaceAfter = '';
  3479. if ($conf['spaceAfter'] || $conf['spaceAfter.']) {
  3480. $spaceAfter = trim($this->stdWrap($conf['spaceAfter'], $conf['spaceAfter.']));
  3481. }
  3482. if ($spaceBefore || $spaceAfter) {
  3483. $content = $this->wrapSpace($content, $spaceBefore.'|'.$spaceAfter, $conf['space.']);
  3484. }
  3485. // Wraps
  3486. if ($conf['wrap']){$content=$this->wrap($content, $conf['wrap'], ($conf['wrap.']['splitChar']?$conf['wrap.']['splitChar']:'|'));}
  3487. if ($conf['noTrimWrap']){$content=$this->noTrimWrap($content, $conf['noTrimWrap']);}
  3488. if ($conf['wrap2']){$content=$this->wrap($content, $conf['wrap2'], ($conf['wrap2.']['splitChar']?$conf['wrap2.']['splitChar']:'|'));}
  3489. if ($conf['dataWrap']){$content=$this->dataWrap($content, $conf['dataWrap']);}
  3490. if ($conf['prepend']){$content=$this->cObjGetSingle($conf['prepend'],$conf['prepend.'],'/stdWrap/.prepend').$content;}
  3491. if ($conf['append']){$content.=$this->cObjGetSingle($conf['append'],$conf['append.'],'/stdWrap/.append');}
  3492. if ($conf['wrap3']){$content=$this->wrap($content, $conf['wrap3'], ($conf['wrap3.']['splitChar']?$conf['wrap3.']['splitChar']:'|'));}
  3493. if ($conf['outerWrap'] || $conf['outerWrap.']){$content=$this->wrap($content, $this->stdWrap($conf['outerWrap'], $conf['outerWrap.']));}
  3494. if ($conf['insertData']) {$content = $this->insertData($content);}
  3495. if ($conf['offsetWrap']){
  3496. $controlTable = t3lib_div::makeInstance('tslib_tableOffset');
  3497. if ($conf['offsetWrap.']['tableParams'] || $conf['offsetWrap.']['tableParams.']) {$controlTable->tableParams = $this->stdWrap($conf['offsetWrap.']['tableParams'], $conf['offsetWrap.']['tableParams.']);}
  3498. if ($conf['offsetWrap.']['tdParams'] || $conf['offsetWrap.']['tdParams.']) {$controlTable->tdParams = ' '.$this->stdWrap($conf['offsetWrap.']['tdParams'], $conf['offsetWrap.']['tdParams.']);}
  3499. $content=$controlTable->start($content,$conf['offsetWrap']);
  3500. if ($conf['offsetWrap.']['stdWrap.']) { $content=$this->stdWrap($content,$conf['offsetWrap.']['stdWrap.']); }
  3501. }
  3502. if ($conf['postUserFunc']) {$content = $this->callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content);}
  3503. if ($conf['postUserFuncInt']) {
  3504. $substKey = 'INT_SCRIPT.'.$GLOBALS['TSFE']->uniqueHash();
  3505. $GLOBALS['TSFE']->config['INTincScript'][$substKey] = array(
  3506. 'content' => $content,
  3507. 'postUserFunc' => $conf['postUserFuncInt'],
  3508. 'conf' => $conf['postUserFuncInt.'],
  3509. 'type' => 'POSTUSERFUNC',
  3510. 'cObj' => serialize($this),
  3511. );
  3512. $content ='<!--'.$substKey.'-->';
  3513. }
  3514. // Various:
  3515. if ($conf['prefixComment'] && !$GLOBALS['TSFE']->config['config']['disablePrefixComment']) {
  3516. $content = $this->prefixComment($conf['prefixComment'], $conf['prefixComment.'], $content);
  3517. }
  3518. if ($conf['editIcons'] && $GLOBALS['TSFE']->beUserLogin) {
  3519. $content = $this->editIcons($content, $conf['editIcons'], $conf['editIcons.']);
  3520. }
  3521. if ($conf['editPanel'] && $GLOBALS['TSFE']->beUserLogin) {
  3522. $content = $this->editPanel($content, $conf['editPanel.']);
  3523. }
  3524. }
  3525. foreach($this->stdWrapHookObjects as $hookObject) {
  3526. $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
  3527. }
  3528. //Debug:
  3529. if ($conf['debug']) {$content = '<pre>'.htmlspecialchars($content).'</pre>';}
  3530. if ($conf['debugFunc']) {debug($conf['debugFunc']==2?array($content):$content);}
  3531. if ($conf['debugData']) {
  3532. echo '<strong>$cObj->data:</strong>';
  3533. debug($this->data,'$cObj->data:');
  3534. if (is_array($this->alternativeData)) {
  3535. echo '<strong>$cObj->alternativeData:</strong>';
  3536. debug($this->alternativeData,'$this->alternativeData');
  3537. }
  3538. }
  3539. }
  3540. return $content;
  3541. }
  3542. /**
  3543. * Returns number of rows selected by the query made by the properties set.
  3544. * Implements the stdWrap "numRows" property
  3545. *
  3546. * @param array TypoScript properties for the property (see link to "numRows")
  3547. * @return integer The number of rows found by the select (FALSE on error)
  3548. * @access private
  3549. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=317&cHash=e28e53e634
  3550. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=318&cHash=a98cb4e7e6
  3551. * @see stdWrap()
  3552. */
  3553. function numRows($conf) {
  3554. $result = FALSE;
  3555. $conf['select.']['selectFields'] = 'count(*)';
  3556. $res = $this->exec_getQuery($conf['table'],$conf['select.']);
  3557. if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
  3558. $GLOBALS['TT']->setTSlogMessage($error,3);
  3559. } else {
  3560. $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
  3561. $result = intval($row[0]);
  3562. }
  3563. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  3564. return $result;
  3565. }
  3566. /**
  3567. * Exploding a string by the $char value (if integer its an ASCII value) and returning index $listNum
  3568. *
  3569. * @param string String to explode
  3570. * @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())
  3571. * @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.
  3572. * @return string
  3573. */
  3574. function listNum($content,$listNum,$char) {
  3575. $char = $char ? $char : ',';
  3576. if (t3lib_div::testInt($char)) {
  3577. $char = chr($char);
  3578. }
  3579. $temp = explode($char,$content);
  3580. $last = ''.(count($temp)-1);
  3581. $index=$this->calc(str_ireplace('last',$last,$listNum));
  3582. return $temp[$index];
  3583. }
  3584. /**
  3585. * Compares values together based on the settings in the input TypoScript array and returns true or false based on the comparison result.
  3586. * Implements the "if" function in TYPO3 TypoScript
  3587. *
  3588. * @param array TypoScript properties defining what to compare
  3589. * @return boolean
  3590. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=320&cHash=da01618eab
  3591. * @see HMENU(), CASEFUNC(), IMAGE(), COLUMN(), stdWrap(), _parseFunc()
  3592. */
  3593. function checkIf($conf) {
  3594. if (!is_array($conf)) {return true;}
  3595. if (isset($conf['directReturn'])) {return $conf['directReturn'] ? 1 : 0;}
  3596. $flag = true;
  3597. if (isset($conf['isTrue']) || isset($conf['isTrue.'])) {
  3598. $isTrue = trim($this->stdWrap($conf['isTrue'],$conf['isTrue.']));
  3599. if (!$isTrue) {
  3600. $flag=0;
  3601. }
  3602. }
  3603. if (isset($conf['isFalse']) || isset($conf['isFalse.'])) {
  3604. $isFalse = trim($this->stdWrap($conf['isFalse'],$conf['isFalse.']));
  3605. if ($isFalse) {
  3606. $flag=0;
  3607. }
  3608. }
  3609. if (isset($conf['isPositive']) || isset($conf['isPositive.'])) {
  3610. $number = $this->calc($this->stdWrap($conf['isPositive'],$conf['isPositive.']));
  3611. if ($number<1) {
  3612. $flag=0;
  3613. }
  3614. }
  3615. if ($flag) {
  3616. $value = trim($this->stdWrap($conf['value'],$conf['value.']));
  3617. if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) {
  3618. $number = trim($this->stdWrap($conf['isGreaterThan'],$conf['isGreaterThan.']));
  3619. if ($number<=$value) {
  3620. $flag=0;
  3621. }
  3622. }
  3623. if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) {
  3624. $number = trim($this->stdWrap($conf['isLessThan'],$conf['isLessThan.']));
  3625. if ($number>=$value) {
  3626. $flag=0;
  3627. }
  3628. }
  3629. if (isset($conf['equals']) || isset($conf['equals.'])) {
  3630. $number = trim($this->stdWrap($conf['equals'],$conf['equals.']));
  3631. if ($number!=$value) {
  3632. $flag=0;
  3633. }
  3634. }
  3635. if (isset($conf['isInList']) || isset($conf['isInList.'])) {
  3636. $number = trim($this->stdWrap($conf['isInList'],$conf['isInList.']));
  3637. if (!t3lib_div::inList($value,$number)) {
  3638. $flag=0;
  3639. }
  3640. }
  3641. }
  3642. if ($conf['negate']) {$flag = $flag ? 0 : 1;}
  3643. return $flag;
  3644. }
  3645. /**
  3646. * Reads a directory for files and returns the filepaths in a string list separated by comma.
  3647. * Implements the stdWrap property "filelist"
  3648. *
  3649. * @param string The command which contains information about what files/directory listing to return. See the "filelist" property of stdWrap for details.
  3650. * @return string Comma list of files.
  3651. * @access private
  3652. * @see stdWrap()
  3653. */
  3654. function filelist($data) {
  3655. $data = trim($data);
  3656. if ($data) {
  3657. $data_arr = explode('|',$data);
  3658. // read directory:
  3659. if ($GLOBALS['TSFE']->lockFilePath) { // MUST exist!
  3660. $path = $this->clean_directory($data_arr[0]); // Cleaning name..., only relative paths accepted.
  3661. // see if path starts with lockFilePath, the additional '/' is needed because clean_directory gets rid of it
  3662. $path = (t3lib_div::isFirstPartOfStr($path . '/', $GLOBALS['TSFE']->lockFilePath) ? $path : '');
  3663. }
  3664. if ($path) {
  3665. $items = Array('files'=>array(), 'sorting'=>array());
  3666. $ext_list = strtolower(t3lib_div::uniqueList($data_arr[1]));
  3667. $sorting = trim($data_arr[2]);
  3668. // read dir:
  3669. $d = @dir($path);
  3670. $tempArray=Array();
  3671. if (is_object($d)) {
  3672. $count=0;
  3673. while($entry=$d->read()) {
  3674. if ($entry!='.' && $entry!='..') {
  3675. $wholePath = $path.'/'.$entry; // Because of odd PHP-error where <br />-tag is sometimes placed after a filename!!
  3676. if (file_exists($wholePath) && filetype($wholePath)=='file') {
  3677. $info = t3lib_div::split_fileref($wholePath);
  3678. if (!$ext_list || t3lib_div::inList($ext_list,$info['fileext'])) {
  3679. $items['files'][] = $info['file'];
  3680. switch($sorting) {
  3681. case 'name':
  3682. $items['sorting'][] = strtolower($info['file']);
  3683. break;
  3684. case 'size':
  3685. $items['sorting'][] = filesize($wholePath);
  3686. break;
  3687. case 'ext':
  3688. $items['sorting'][] = $info['fileext'];
  3689. break;
  3690. case 'date':
  3691. $items['sorting'][] = filectime($wholePath);
  3692. break;
  3693. case 'mdate':
  3694. $items['sorting'][] = filemtime($wholePath);
  3695. break;
  3696. default:
  3697. $items['sorting'][] = $count;
  3698. break;
  3699. }
  3700. $count++;
  3701. }
  3702. }
  3703. }
  3704. }
  3705. $d->close();
  3706. }
  3707. // Sort if required
  3708. if (count($items['sorting'])) {
  3709. if (strtolower(trim($data_arr[3]))!='r') {
  3710. asort($items['sorting']);
  3711. } else {
  3712. arsort($items['sorting']);
  3713. }
  3714. }
  3715. if (count($items['files'])) {
  3716. // make list
  3717. reset($items['sorting']);
  3718. $fullPath = trim($data_arr[4]);
  3719. $list_arr=Array();
  3720. foreach ($items['sorting'] as $key => $v) {
  3721. $list_arr[]= $fullPath ? $path.'/'.$items['files'][$key] : $items['files'][$key];
  3722. }
  3723. return implode(',',$list_arr);
  3724. }
  3725. }
  3726. }
  3727. }
  3728. /**
  3729. * Cleans $theDir for slashes in the end of the string and returns the new path, if it exists on the server.
  3730. *
  3731. * @param string Absolute path to directory
  3732. * @return string The directory path if it existed as was valid to access.
  3733. * @access private
  3734. * @see filelist()
  3735. */
  3736. function clean_directory($theDir) {
  3737. if (t3lib_div::validPathStr($theDir)) { // proceeds if no '//', '..' or '\' is in the $theFile
  3738. $theDir = preg_replace('/[\/\. ]*$/','',$theDir); // Removes all dots, slashes and spaces after a path...
  3739. if (!t3lib_div::isAbsPath($theDir) && @is_dir($theDir)) {
  3740. return $theDir;
  3741. }
  3742. }
  3743. }
  3744. /**
  3745. * 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.
  3746. *
  3747. * @param string The value to parse by the class "t3lib_parsehtml"
  3748. * @param array TypoScript properties for the parser. See link.
  3749. * @return string Return value.
  3750. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=330&cHash=664e0296bf
  3751. * @see stdWrap(), t3lib_parsehtml::HTMLparserConfig(), t3lib_parsehtml::HTMLcleaner()
  3752. */
  3753. function HTMLparser_TSbridge($theValue, $conf) {
  3754. $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
  3755. $htmlParserCfg = $htmlParser->HTMLparserConfig($conf);
  3756. return $htmlParser->HTMLcleaner($theValue,$htmlParserCfg[0],$htmlParserCfg[1],$htmlParserCfg[2],$htmlParserCfg[3]);
  3757. }
  3758. /**
  3759. * Wrapping input value in a regular "wrap" but parses the wrapping value first for "insertData" codes.
  3760. *
  3761. * @param string Input string being wrapped
  3762. * @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.
  3763. * @return string Output string wrapped in the wrapping value.
  3764. * @see insertData(), stdWrap()
  3765. */
  3766. function dataWrap($content,$wrap) {
  3767. return $this->wrap($content,$this->insertData($wrap));
  3768. }
  3769. /**
  3770. * 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.
  3771. * 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.
  3772. *
  3773. * @param string Input value
  3774. * @return string Processed input value
  3775. * @see getData(), stdWrap(), dataWrap()
  3776. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=314&cHash=02ab044c7b
  3777. */
  3778. function insertData($str) {
  3779. $inside=0;
  3780. $newVal='';
  3781. $pointer=0;
  3782. $totalLen = strlen($str);
  3783. do {
  3784. if (!$inside) {
  3785. $len = strcspn(substr($str,$pointer),'{');
  3786. $newVal.= substr($str,$pointer,$len);
  3787. $inside = 1;
  3788. } else {
  3789. $len = strcspn(substr($str,$pointer),'}')+1;
  3790. $newVal.= $this->getData(substr($str,$pointer+1,$len-2),$this->data);
  3791. $inside = 0;
  3792. }
  3793. $pointer+=$len;
  3794. } while($pointer<$totalLen);
  3795. return $newVal;
  3796. }
  3797. /**
  3798. * 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.
  3799. * Notice; this function (used by stdWrap) can be disabled by a "config.disablePrefixComment" setting in TypoScript.
  3800. *
  3801. * @param string Input value
  3802. * @param array TypoScript Configuration (not used at this point.)
  3803. * @param string The content to wrap the comment around.
  3804. * @return string Processed input value
  3805. * @see stdWrap()
  3806. */
  3807. function prefixComment($str,$conf,$content) {
  3808. $parts = explode('|',$str);
  3809. $output =
  3810. LF.str_pad('',$parts[0],TAB).
  3811. '<!-- '.htmlspecialchars($this->insertData($parts[1])).' [begin] -->'.
  3812. LF.str_pad('',$parts[0]+1,TAB).
  3813. $content.
  3814. LF.str_pad('',$parts[0],TAB).
  3815. '<!-- '.htmlspecialchars($this->insertData($parts[1])).' [end] -->'.
  3816. LF.str_pad('',$parts[0]+1,TAB);
  3817. return $output;
  3818. }
  3819. /**
  3820. * Implements the stdWrap property "substring" which is basically a TypoScript implementation of the PHP function, substr()
  3821. *
  3822. * @param string The string to perform the operation on
  3823. * @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().
  3824. * @return string The processed input value.
  3825. * @access private
  3826. * @see stdWrap()
  3827. */
  3828. function substring($content,$options) {
  3829. $options = t3lib_div::intExplode(',',$options.',');
  3830. if ($options[1]) {
  3831. return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset,$content,$options[0],$options[1]);
  3832. } else {
  3833. return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset,$content,$options[0]);
  3834. }
  3835. }
  3836. /**
  3837. * 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.
  3838. *
  3839. * @param string The string to perform the operation on
  3840. * @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.
  3841. * @return string The processed input value.
  3842. * @access private
  3843. * @see stdWrap()
  3844. */
  3845. function crop($content,$options) {
  3846. $options = explode('|',$options);
  3847. $chars = intval($options[0]);
  3848. $afterstring = trim($options[1]);
  3849. $crop2space = trim($options[2]);
  3850. if ($chars) {
  3851. if (strlen($content)>abs($chars)) {
  3852. if ($chars<0) {
  3853. $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset,$content,$chars);
  3854. $trunc_at = strpos($content, ' ');
  3855. $content = ($trunc_at&&$crop2space) ? $afterstring.substr($content,$trunc_at) : $afterstring.$content;
  3856. } else {
  3857. $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset,$content,0,$chars);
  3858. $trunc_at = strrpos($content, ' ');
  3859. $content = ($trunc_at&&$crop2space) ? substr($content, 0, $trunc_at).$afterstring : $content.$afterstring;
  3860. }
  3861. }
  3862. }
  3863. return $content;
  3864. }
  3865. /**
  3866. * Implements the stdWrap property "cropHTML" which is a modified "substr" function allowing to limit a string length
  3867. * to a certain number of chars (from either start or end of string) and having a pre/postfix applied if the string
  3868. * really was cropped.
  3869. *
  3870. * Compared to stdWrap.crop it respects HTML tags and entities.
  3871. *
  3872. * @param string The string to perform the operation on
  3873. * @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.
  3874. * @return string The processed input value.
  3875. * @access private
  3876. * @see stdWrap()
  3877. */
  3878. function cropHTML($content, $options) {
  3879. $options = explode('|', $options);
  3880. $chars = intval($options[0]);
  3881. $absChars = abs($chars);
  3882. $replacementForEllipsis = trim($options[1]);
  3883. $crop2space = trim($options[2]) === '1' ? TRUE : FALSE;
  3884. // Split $content into an array (even items in the array are outside the tags, odd numbers are tag-blocks).
  3885. $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';
  3886. // TODO We should not crop inside <script> tags.
  3887. $tagsRegEx = "
  3888. (
  3889. (?:
  3890. <!--.*?--> # a comment
  3891. )
  3892. |
  3893. </?(?:". $tags . ")+ # opening tag ('<tag') or closing tag ('</tag')
  3894. (?:
  3895. (?:
  3896. \s+\w+ # EITHER spaces, followed by word characters (attribute names)
  3897. (?:
  3898. \s*=?\s* # equals
  3899. (?>
  3900. \".*?\" # attribute values in double-quotes
  3901. |
  3902. '.*?' # attribute values in single-quotes
  3903. |
  3904. [^'\">\s]+ # plain attribute values
  3905. )
  3906. )?
  3907. )+\s*
  3908. | # OR only spaces
  3909. \s*
  3910. )
  3911. /?> # closing the tag with '>' or '/>'
  3912. )";
  3913. $splittedContent = preg_split('%' . $tagsRegEx . '%xs', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
  3914. // Reverse array if we are cropping from right.
  3915. if ($chars < 0) {
  3916. $splittedContent = array_reverse($splittedContent);
  3917. }
  3918. // Crop the text (chars of tag-blocks are not counted).
  3919. $strLen = 0;
  3920. $croppedOffset = NULL; // This is the offset of the content item which was cropped.
  3921. $countSplittedContent = count($splittedContent);
  3922. for ($offset = 0; $offset < $countSplittedContent; $offset++) {
  3923. if ($offset%2 === 0) {
  3924. $tempContent = $GLOBALS['TSFE']->csConvObj->utf8_encode($splittedContent[$offset], $GLOBALS['TSFE']->renderCharset);
  3925. $thisStrLen = $GLOBALS['TSFE']->csConvObj->strlen('utf-8', html_entity_decode($tempContent, ENT_COMPAT, 'UTF-8'));
  3926. if (($strLen + $thisStrLen > $absChars)) {
  3927. $croppedOffset = $offset;
  3928. $cropPosition = $absChars - $strLen;
  3929. // The snippet "&[^&\s;]{2,8};" in the RegEx below represents entities.
  3930. $patternMatchEntityAsSingleChar = '(&[^&\s;]{2,8};|.)';
  3931. if ($crop2space) {
  3932. $cropRegEx = $chars < 0 ?
  3933. '#(?<=\s)' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#ui' :
  3934. '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}(?=\s)#ui';
  3935. } else {
  3936. $cropRegEx = $chars < 0 ?
  3937. '#' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#ui' :
  3938. '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}#ui';
  3939. }
  3940. if (preg_match($cropRegEx, $tempContent, $croppedMatch)) {
  3941. $tempContent = $croppedMatch[0];
  3942. }
  3943. $splittedContent[$offset] = $GLOBALS['TSFE']->csConvObj->utf8_decode($tempContent, $GLOBALS['TSFE']->renderCharset);
  3944. break;
  3945. } else {
  3946. $strLen += $thisStrLen;
  3947. }
  3948. }
  3949. }
  3950. // Close cropped tags.
  3951. $closingTags = array();
  3952. if($croppedOffset !== NULL) {
  3953. $tagName = '';
  3954. $openingTagRegEx = '#^<(\w+)(?:\s|>)#';
  3955. $closingTagRegEx = '#^</(\w+)(?:\s|>)#';
  3956. for ($offset = $croppedOffset - 1; $offset >= 0; $offset = $offset - 2) {
  3957. if (substr($splittedContent[$offset], -2) === '/>') {
  3958. // Ignore empty element tags (e.g. <br />).
  3959. continue;
  3960. }
  3961. preg_match($chars < 0 ? $closingTagRegEx : $openingTagRegEx, $splittedContent[$offset], $matches);
  3962. $tagName = isset($matches[1]) ? $matches[1] : NULL;
  3963. if ($tagName !== NULL) {
  3964. // Seek for the closing (or opening) tag.
  3965. $seekingTagName = '';
  3966. $countSplittedContent = count($splittedContent);
  3967. for ($seekingOffset = $offset + 2; $seekingOffset < $countSplittedContent; $seekingOffset = $seekingOffset + 2) {
  3968. preg_match($chars < 0 ? $openingTagRegEx : $closingTagRegEx, $splittedContent[$seekingOffset], $matches);
  3969. $seekingTagName = isset($matches[1]) ? $matches[1] : NULL;
  3970. if ($tagName === $seekingTagName) { // We found a matching tag.
  3971. // Add closing tag only if it occurs after the cropped content item.
  3972. if ($seekingOffset > $croppedOffset) {
  3973. $closingTags[] = $splittedContent[$seekingOffset];
  3974. }
  3975. break;
  3976. }
  3977. }
  3978. }
  3979. }
  3980. // Drop the cropped items of the content array. The $closingTags will be added later on again.
  3981. array_splice($splittedContent, $croppedOffset + 1);
  3982. }
  3983. $splittedContent = array_merge($splittedContent, array($croppedOffset !== NULL ? $replacementForEllipsis : ''), $closingTags);
  3984. // Reverse array once again if we are cropping from the end.
  3985. if ($chars < 0) {
  3986. $splittedContent = array_reverse($splittedContent);
  3987. }
  3988. return implode('', $splittedContent);
  3989. }
  3990. /**
  3991. * Function for removing malicious HTML code when you want to provide some HTML code user-editable.
  3992. * The purpose is to avoid XSS attacks and the code will be continously modified to remove such code.
  3993. * For a complete reference with javascript-on-events, see http://www.wdvl.com/Authoring/JavaScript/Events/events_target.html
  3994. *
  3995. * @param string Input string to be cleaned.
  3996. * @param array TypoScript configuration.
  3997. * @return string Return string
  3998. * @author Thomas Bley (all from moregroupware cvs code / readmessage.inc.php, published under gpl by Thomas)
  3999. * @author Kasper Skaarhoj
  4000. */
  4001. function removeBadHTML($text, $conf) {
  4002. // Copyright 2002-2003 Thomas Bley
  4003. $text = preg_replace(
  4004. array(
  4005. "'<script[^>]*?>.*?</script[^>]*?>'si",
  4006. "'<applet[^>]*?>.*?</applet[^>]*?>'si",
  4007. "'<object[^>]*?>.*?</object[^>]*?>'si",
  4008. "'<iframe[^>]*?>.*?</iframe[^>]*?>'si",
  4009. "'<frameset[^>]*?>.*?</frameset[^>]*?>'si",
  4010. "'<style[^>]*?>.*?</style[^>]*?>'si",
  4011. "'<marquee[^>]*?>.*?</marquee[^>]*?>'si",
  4012. "'<script[^>]*?>'si",
  4013. "'<meta[^>]*?>'si",
  4014. "'<base[^>]*?>'si",
  4015. "'<applet[^>]*?>'si",
  4016. "'<object[^>]*?>'si",
  4017. "'<link[^>]*?>'si",
  4018. "'<iframe[^>]*?>'si",
  4019. "'<frame[^>]*?>'si",
  4020. "'<frameset[^>]*?>'si",
  4021. "'<input[^>]*?>'si",
  4022. "'<form[^>]*?>'si",
  4023. "'<embed[^>]*?>'si",
  4024. "'background-image:url'si",
  4025. "'<\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",
  4026. ), '', $text);
  4027. $text = preg_replace('/<a[^>]*href[[:space:]]*=[[:space:]]*["\']?[[:space:]]*javascript[^>]*/i','',$text);
  4028. // Return clean content
  4029. return $text;
  4030. }
  4031. /**
  4032. * Implements the stdWrap property "textStyle"; This generates a <font>-tag (and a <div>-tag for align-attributes) which is wrapped around the input value.
  4033. *
  4034. * @param string The input value
  4035. * @param array TypoScript properties for the "TypoScript function" '->textStyle'
  4036. * @return string The processed output value
  4037. * @access private
  4038. * @see stdWrap()
  4039. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=322&cHash=a14b745a18
  4040. */
  4041. function textStyle($theValue, $conf) {
  4042. $conf['face.'][1] = 'Times New Roman';
  4043. $conf['face.'][2] = 'Verdana,Arial,Helvetica,Sans serif';
  4044. $conf['face.'][3] = 'Arial,Helvetica,Sans serif';
  4045. $conf['size.'][1] = 1;
  4046. $conf['size.'][2] = 2;
  4047. $conf['size.'][3] = 3;
  4048. $conf['size.'][4] = 4;
  4049. $conf['size.'][5] = 5;
  4050. $conf['size.'][10] = '+1';
  4051. $conf['size.'][11] = '-1';
  4052. $conf['color.'][240] = 'black';
  4053. $conf['color.'][241] = 'white';
  4054. $conf['color.'][242] = '#333333';
  4055. $conf['color.'][243] = 'gray';
  4056. $conf['color.'][244] = 'silver';
  4057. $conf['color.'][245] = 'red';
  4058. $conf['color.'][246] = 'navy';
  4059. $conf['color.'][247] = 'yellow';
  4060. $conf['color.'][248] = 'green';
  4061. $conf['color.'][249] = 'olive';
  4062. $conf['color.'][250] = 'maroon';
  4063. $face = $this->data[$conf['face.']['field']];
  4064. $size = $this->data[$conf['size.']['field']];
  4065. $color = $this->data[$conf['color.']['field']];
  4066. $align = $this->data[$conf['align.']['field']];
  4067. $properties = $this->data[$conf['properties.']['field']];
  4068. if (!$properties) {
  4069. $properties=$this->stdWrap($conf['properties.']['default'],$conf['properties.']['default.']);
  4070. }
  4071. // properties
  4072. if (($properties&8)) {$theValue=$this->HTMLcaseshift($theValue, 'upper');}
  4073. if (($properties&1)) {$theValue='<strong>'.$theValue.'</strong>';}
  4074. if (($properties&2)) {$theValue='<i>'.$theValue.'</i>';}
  4075. if (($properties&4)) {$theValue='<u>'.$theValue.'</u>';}
  4076. // Fonttag
  4077. $theFace = $conf['face.'][$face] ? $conf['face.'][$face] : $this->stdWrap($conf['face.']['default'],$conf['face.']['default.']);
  4078. $theSize = $conf['size.'][$size] ? $conf['size.'][$size] : $this->stdWrap($conf['size.']['default'],$conf['size.']['default.']);
  4079. $theColor = $conf['color.'][$color] ? $conf['color.'][$color] : $this->stdWrap($conf['color.']['default'],$conf['color.']['default.']);
  4080. if ($conf['altWrap']) {
  4081. $theValue=$this->wrap($theValue, $conf['altWrap']);
  4082. } elseif ($theFace || $theSize || $theColor) {
  4083. $fontWrap = '<font'.($theFace?' face="'.$theFace.'"':'').($theSize?' size="'.$theSize.'"':'').($theColor?' color="'.$theColor.'"':'').'>|</font>';
  4084. $theValue=$this->wrap($theValue, $fontWrap);
  4085. }
  4086. // align
  4087. if ($align) {$theValue=$this->wrap($theValue, '<div style="text-align:'.$align.';">|</div>');}
  4088. // return
  4089. return $theValue;
  4090. }
  4091. /**
  4092. * Implements the stdWrap property "tableStyle"; Basically this generates a <table>-tag with properties which is wrapped around the input value.
  4093. *
  4094. * @param string The input value
  4095. * @param array TypoScript properties for the "TypoScript function" '->textStyle'
  4096. * @return string The processed output value
  4097. * @access private
  4098. * @see stdWrap()
  4099. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=324&cHash=34410ebff3
  4100. */
  4101. function tableStyle($theValue, $conf) {
  4102. $conf['color.'][240] = 'black';
  4103. $conf['color.'][241] = 'white';
  4104. $conf['color.'][242] = '#333333';
  4105. $conf['color.'][243] = 'gray';
  4106. $conf['color.'][244] = 'silver';
  4107. $align = $this->stdWrap($conf['align'],$conf['align.']);
  4108. $border = intval($this->stdWrap($conf['border'],$conf['border.']));
  4109. $cellspacing = intval($this->stdWrap($conf['cellspacing'],$conf['cellspacing.']));
  4110. $cellpadding = intval($this->stdWrap($conf['cellpadding'],$conf['cellpadding.']));
  4111. $color = $this->data[$conf['color.']['field']];
  4112. $theColor = $conf['color.'][$color] ? $conf['color.'][$color] : $conf['color.']['default'];
  4113. // Assembling the table tag
  4114. $tableTagArray = Array('<table');
  4115. $tableTagArray[]='border="'.$border.'"';
  4116. $tableTagArray[]='cellspacing="'.$cellspacing.'"';
  4117. $tableTagArray[]='cellpadding="'.$cellpadding.'"';
  4118. if ($align) {$tableTagArray[]='align="'.$align.'"';}
  4119. if ($theColor) {$tableTagArray[]='bgcolor="'.$theColor.'"';}
  4120. if ($conf['params']) {
  4121. $tableTagArray[] = $conf['params'];
  4122. }
  4123. $tableWrap = implode(' ',$tableTagArray).'> | </table>';
  4124. $theValue=$this->wrap($theValue, $tableWrap);
  4125. // return
  4126. return $theValue;
  4127. }
  4128. /**
  4129. * Implements the TypoScript function "addParams"
  4130. *
  4131. * @param string The string with the HTML tag.
  4132. * @param array The TypoScript configuration properties
  4133. * @return string The modified string
  4134. * @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.
  4135. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=325&cHash=ae4272e694
  4136. */
  4137. function addParams($content,$conf) {
  4138. $lowerCaseAttributes = TRUE; // For XHTML compliance.
  4139. if (!is_array($conf)) { return $content; }
  4140. $key = 1;
  4141. $parts = explode('<',$content);
  4142. if (intval($conf['_offset'])) $key = intval($conf['_offset'])<0 ? count($parts)+intval($conf['_offset']) : intval($conf['_offset']);
  4143. $subparts=explode('>',$parts[$key]);
  4144. if (trim($subparts[0])) {
  4145. // Get attributes and name
  4146. $attribs = t3lib_div::get_tag_attributes('<'.$subparts[0].'>');
  4147. list($tagName) = explode(' ',$subparts[0],2);
  4148. // adds/overrides attributes
  4149. foreach ($conf as $pkey => $val) {
  4150. if (substr($pkey,-1)!='.' && substr($pkey,0,1)!='_') {
  4151. $tmpVal=$this->stdWrap($conf[$pkey],$conf[$pkey.'.']);
  4152. if ($lowerCaseAttributes) { $pkey = strtolower($pkey); }
  4153. if (strcmp($tmpVal,'')) {$attribs[$pkey]=$tmpVal;}
  4154. }
  4155. }
  4156. // Re-assembles the tag and content
  4157. $subparts[0] = trim($tagName.' '.t3lib_div::implodeAttributes($attribs));
  4158. $parts[$key] = implode('>',$subparts);
  4159. $content = implode('<',$parts);
  4160. }
  4161. return $content;
  4162. }
  4163. /**
  4164. * Creates a list of links to files.
  4165. * Implements the stdWrap property "filelink"
  4166. *
  4167. * @param string The filename to link to, possibly prefixed with $conf[path]
  4168. * @param array TypoScript parameters for the TypoScript function ->filelink
  4169. * @return string The link to the file possibly with icons, thumbnails, size in bytes shown etc.
  4170. * @access private
  4171. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=326&cHash=5618043c18
  4172. * @see stdWrap()
  4173. */
  4174. function filelink($theValue, $conf) {
  4175. $conf['path'] = $this->stdWrap($conf['path'], $conf['path.']);
  4176. $theFile = trim($conf['path']) . $theValue;
  4177. if (@is_file($theFile)) {
  4178. $theFileEnc = str_replace('%2F', '/', rawurlencode($theFile));
  4179. // the jumpURL feature will be taken care of by typoLink, only "jumpurl.secure = 1" is applyable needed for special link creation
  4180. if ($conf['jumpurl.']['secure']) {
  4181. $alternativeJumpUrlParameter = $this->stdWrap($conf['jumpurl.']['parameter'], $conf['jumpurl.']['parameter.']);
  4182. $typoLinkConf = array(
  4183. 'parameter' => ($alternativeJumpUrlParameter ? $alternativeJumpUrlParameter : ($GLOBALS['TSFE']->id . ',' . $GLOBALS['TSFE']->type)),
  4184. 'fileTarget' => $conf['target'],
  4185. 'ATagParams' => $this->getATagParams($conf),
  4186. 'additionalParams' => '&jumpurl=' . rawurlencode($theFileEnc) . $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) . $GLOBALS['TSFE']->getMethodUrlIdToken
  4187. );
  4188. } else {
  4189. $typoLinkConf = array(
  4190. 'parameter' => $theFileEnc,
  4191. 'fileTarget' => $conf['target'],
  4192. 'ATagParams' => $this->getATagParams($conf)
  4193. );
  4194. }
  4195. // if the global jumpURL feature is activated, but is disabled for this
  4196. // filelink, the global parameter needs to be disabled as well for this link creation
  4197. $globalJumpUrlEnabled = $GLOBALS['TSFE']->config['config']['jumpurl_enable'];
  4198. if ($globalJumpUrlEnabled && isset($conf['jumpurl']) && $conf['jumpurl'] == 0) {
  4199. $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 0;
  4200. // if the global jumpURL feature is deactivated, but is wanted for this link, then activate it for now
  4201. } else if (!$globalJumpUrlEnabled && $conf['jumpurl']) {
  4202. $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 1;
  4203. }
  4204. $theLinkWrap = $this->typoLink('|', $typoLinkConf);
  4205. // now the original value is set again
  4206. $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = $globalJumpUrlEnabled;
  4207. $theSize = filesize($theFile);
  4208. $fI = t3lib_div::split_fileref($theFile);
  4209. if ($conf['icon']) {
  4210. $iconP = t3lib_extMgm::siteRelPath('cms').'tslib/media/fileicons/';
  4211. $icon = @is_file($iconP.$fI['fileext'].'.gif') ? $iconP.$fI['fileext'].'.gif' : $iconP.'default.gif';
  4212. // Checking for images: If image, then return link to thumbnail.
  4213. $IEList = $this->stdWrap($conf['icon_image_ext_list'],$conf['icon_image_ext_list.']);
  4214. $image_ext_list = str_replace(' ','',strtolower($IEList));
  4215. if ($fI['fileext'] && t3lib_div::inList($image_ext_list, $fI['fileext'])) {
  4216. if ($conf['iconCObject']) {
  4217. $icon = $this->cObjGetSingle($conf['iconCObject'],$conf['iconCObject.'],'iconCObject');
  4218. } else {
  4219. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) {
  4220. $thumbSize = '';
  4221. if ($conf['icon_thumbSize'] || $conf['icon_thumbSize.']) { $thumbSize = '&size='.$this->stdWrap($conf['icon_thumbSize'], $conf['icon_thumbSize.']); }
  4222. $check = basename($theFile).':'.filemtime($theFile).':'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
  4223. $md5sum = '&md5sum='.t3lib_div::shortMD5($check);
  4224. $icon = 't3lib/thumbs.php?dummy='.$GLOBALS['EXEC_TIME'].'&file='.rawurlencode('../'.$theFile).$thumbSize.$md5sum;
  4225. } else {
  4226. $icon = t3lib_extMgm::siteRelPath('cms').'tslib/media/miscicons/notfound_thumb.gif';
  4227. }
  4228. $icon = '<img src="'.htmlspecialchars($GLOBALS['TSFE']->absRefPrefix.$icon).'"'.$this->getBorderAttr(' border="0"').''.$this->getAltParam($conf).' />';
  4229. }
  4230. } else {
  4231. $icon = '<img src="'.htmlspecialchars($GLOBALS['TSFE']->absRefPrefix.$icon).'" width="18" height="16"'.$this->getBorderAttr(' border="0"').''.$this->getAltParam($conf).' />';
  4232. }
  4233. if ($conf['icon_link']) {$icon = $this->wrap($icon, $theLinkWrap);}
  4234. $icon = $this->stdWrap($icon,$conf['icon.']);
  4235. }
  4236. if ($conf['size']) {
  4237. $size = $this->stdWrap($theSize,$conf['size.']);
  4238. }
  4239. // Wrapping file label
  4240. if ($conf['removePrependedNumbers']) $theValue=preg_replace('/_[0-9][0-9](\.[[:alnum:]]*)$/','\1',$theValue);
  4241. $theValue = $this->stdWrap($theValue,$conf['labelStdWrap.']);
  4242. // Wrapping file
  4243. if ($conf['ATagBeforeWrap']) {
  4244. $theValue = $this->wrap($this->wrap($theValue, $conf['wrap']), $theLinkWrap);
  4245. } else {
  4246. $theValue = $this->wrap($this->wrap($theValue, $theLinkWrap), $conf['wrap']);
  4247. }
  4248. $file = $this->stdWrap($theValue,$conf['file.']);
  4249. // output
  4250. return $this->stdWrap($icon.$file.$size, $conf['stdWrap.']);
  4251. }
  4252. }
  4253. /**
  4254. * Returns a URL parameter string setting parameters for secure downloads by "jumpurl".
  4255. * Helper function for filelink()
  4256. *
  4257. * @param string The URL to jump to, basically the filepath
  4258. * @param array TypoScript properties for the "jumpurl.secure" property of "filelink"
  4259. * @return string URL parameters like "&juSecure=1....."
  4260. * @access private
  4261. * @see filelink()
  4262. */
  4263. function locDataJU($jumpUrl,$conf) {
  4264. $fI = pathinfo($jumpUrl);
  4265. $mimetype='';
  4266. if ($fI['extension']) {
  4267. $mimeTypes = t3lib_div::trimExplode(',',$conf['mimeTypes'],1);
  4268. foreach ($mimeTypes as $v) {
  4269. $parts = explode('=',$v,2);
  4270. if (strtolower($fI['extension']) == strtolower(trim($parts[0]))) {
  4271. $mimetypeValue = trim($parts[1]);
  4272. $mimetype = '&mimeType=' . rawurlencode($mimetypeValue);
  4273. break;
  4274. }
  4275. }
  4276. }
  4277. $locationData = $GLOBALS['TSFE']->id.':'.$this->currentRecord;
  4278. $rec='&locationData='.rawurlencode($locationData);
  4279. $hArr = array(
  4280. $jumpUrl,
  4281. $locationData,
  4282. $mimetypeValue,
  4283. $GLOBALS['TSFE']->TYPO3_CONF_VARS['SYS']['encryptionKey']
  4284. );
  4285. $juHash='&juHash='.t3lib_div::shortMD5(serialize($hArr));
  4286. return '&juSecure=1'.$mimetype.$rec.$juHash;
  4287. }
  4288. /**
  4289. * Performs basic mathematical evaluation of the input string. Does NOT take parathesis and operator precedence into account! (for that, see t3lib_div::calcPriority())
  4290. *
  4291. * @param string The string to evaluate. Example: "3+4*10/5" will generate "35". Only integer numbers can be used.
  4292. * @return integer The result (might be a float if you did a division of the numbers).
  4293. * @see t3lib_div::calcPriority()
  4294. */
  4295. function calc($val) {
  4296. $parts= t3lib_div::splitCalc($val,'+-*/');
  4297. $value=0;
  4298. foreach ($parts as $part) {
  4299. $theVal = $part[1];
  4300. $sign = $part[0];
  4301. if ((string)intval($theVal)==(string)$theVal) {
  4302. $theVal = intval($theVal);
  4303. } else {
  4304. $theVal =0;
  4305. }
  4306. if ($sign=='-') {$value-=$theVal;}
  4307. if ($sign=='+') {$value+=$theVal;}
  4308. if ($sign=='/') {if (intval($theVal)) $value/=intval($theVal);}
  4309. if ($sign=='*') {$value*=$theVal;}
  4310. }
  4311. return $value;
  4312. }
  4313. /**
  4314. * 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)
  4315. * Used to split and calculate min and max values for GMENUs.
  4316. *
  4317. * @param string Delimited to explode by
  4318. * @param string The string with parts in (where each part is evaluated by ->calc())
  4319. * @return array And array with evaluated values.
  4320. * @see calc(), tslib_gmenu::makeGifs()
  4321. */
  4322. function calcIntExplode($delim, $string) {
  4323. $temp = explode($delim,$string);
  4324. foreach ($temp as $key => $val) {
  4325. $temp[$key]=intval(tslib_cObj::calc($val));
  4326. }
  4327. return $temp;
  4328. }
  4329. /**
  4330. * 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.
  4331. * 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.
  4332. * Implements the "optionSplit" processing of the TypoScript options for each splitted value to parse.
  4333. *
  4334. * @param string The string value to explode by $conf[token] and process each part
  4335. * @param array TypoScript properties for "split"
  4336. * @return string Compiled result
  4337. * @access private
  4338. * @see stdWrap(), t3lib_menu::procesItemStates()
  4339. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=319&cHash=1871864c8f
  4340. */
  4341. function splitObj($value, $conf) {
  4342. $conf['token']=$this->stdWrap($conf['token'],$conf['token.']);
  4343. if (!$conf['token']) {
  4344. return $value;
  4345. }
  4346. $conf['max']=intval($this->stdWrap($conf['max'],$conf['max.']));
  4347. $conf['min']=intval($this->stdWrap($conf['min'],$conf['min.']));
  4348. $valArr=explode($conf['token'],$value);
  4349. if (count($valArr) && (t3lib_div::testInt($conf['returnKey']) || $conf['returnKey.'])) {
  4350. $key = intval($this->stdWrap($conf['returnKey'],$conf['returnKey.']));
  4351. $content = isset($valArr[$key]) ? $valArr[$key] : '';
  4352. } else {
  4353. // calculate splitCount
  4354. $splitCount = count($valArr);
  4355. if ($conf['max'] && $splitCount>$conf['max']) {
  4356. $splitCount=$conf['max'];
  4357. }
  4358. if ($conf['min'] && $splitCount<$conf['min']) {
  4359. $splitCount=$conf['min'];
  4360. }
  4361. if ($conf['wrap'] || $conf['cObjNum']) {
  4362. $splitArr=array();
  4363. $splitArr['wrap']=$conf['wrap'];
  4364. $splitArr['cObjNum']=$conf['cObjNum'];
  4365. $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr,$splitCount);
  4366. }
  4367. $content='';
  4368. for($a=0;$a<$splitCount;$a++) {
  4369. $GLOBALS['TSFE']->register['SPLIT_COUNT']=$a;
  4370. $value = ''.$valArr[$a];
  4371. $this->data[$this->currentValKey] = $value;
  4372. if ($splitArr[$a]['cObjNum']) {
  4373. $objName=intval($splitArr[$a]['cObjNum']);
  4374. $value = $this->stdWrap($this->cObjGet($conf[$objName.'.'],$objName.'.'),$conf[$objName.'.']);
  4375. }
  4376. if ($splitArr[$a]['wrap']) {
  4377. $value=$this->wrap($value,$splitArr[$a]['wrap']);
  4378. }
  4379. $content.=$value;
  4380. }
  4381. }
  4382. return $content;
  4383. }
  4384. /**
  4385. * Implements the stdWrap property, "parseFunc".
  4386. * This is a function with a lot of interesting uses. In classic TypoScript this is used to process text from the bodytext field; This included highlighting of search words, changing http:// and mailto: prefixed strings into links, parsing <typolist>, <typohead> and <typocode> tags etc.
  4387. * It is still a very important function for processing of bodytext which is normally stored in the database in a format which is not fully ready to be outputted. This situation has not become better by having a RTE around...
  4388. *
  4389. * This function is actually just splitting the input content according to the configuration of "external blocks". This means that before the input string is actually "parsed" it will be splitted into the parts configured to BE parsed (while other parts/blocks should NOT be parsed). Therefore the actual processing of the parseFunc properties goes on in ->_parseFunc()
  4390. *
  4391. * @param string The value to process.
  4392. * @param array TypoScript configuration for parseFunc
  4393. * @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!
  4394. * @return string The processed value
  4395. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=327&cHash=33331f0396
  4396. * @see _parseFunc()
  4397. */
  4398. function parseFunc($theValue, $conf, $ref='') {
  4399. // Fetch / merge reference, if any
  4400. if ($ref) {
  4401. $temp_conf = array(
  4402. 'parseFunc' => $ref,
  4403. 'parseFunc.' => $conf
  4404. );
  4405. $temp_conf = $this->mergeTSRef($temp_conf, 'parseFunc');
  4406. $conf = $temp_conf['parseFunc.'];
  4407. }
  4408. // Process:
  4409. if (strcmp($conf['externalBlocks'],'')) {
  4410. $tags = strtolower(implode(',',t3lib_div::trimExplode(',',$conf['externalBlocks'])));
  4411. $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
  4412. $parts = $htmlParser->splitIntoBlock($tags,$theValue);
  4413. foreach ($parts as $k => $v) {
  4414. if ($k%2) { // font:
  4415. $tagName=strtolower($htmlParser->getFirstTagName($v));
  4416. $cfg=$conf['externalBlocks.'][$tagName.'.'];
  4417. if ($cfg['stripNLprev'] || $cfg['stripNL']) {
  4418. $parts[$k-1]=preg_replace('/'.CR.'?'.LF.'[ ]*$/', '', $parts[$k-1]);
  4419. }
  4420. if ($cfg['stripNLnext'] || $cfg['stripNL']) {
  4421. $parts[$k+1]=preg_replace('/^[ ]*'.CR.'?'.LF.'/', '', $parts[$k+1]);
  4422. }
  4423. }
  4424. }
  4425. foreach ($parts as $k => $v) {
  4426. if ($k%2) {
  4427. $tag=$htmlParser->getFirstTag($v);
  4428. $tagName=strtolower($htmlParser->getFirstTagName($v));
  4429. $cfg=$conf['externalBlocks.'][$tagName.'.'];
  4430. if ($cfg['callRecursive']) {
  4431. $parts[$k]=$this->parseFunc($htmlParser->removeFirstAndLastTag($v), $conf);
  4432. if (!$cfg['callRecursive.']['dontWrapSelf']) {
  4433. if ($cfg['callRecursive.']['alternativeWrap']) {
  4434. $parts[$k] = $this->wrap($parts[$k], $cfg['callRecursive.']['alternativeWrap']);
  4435. } else {
  4436. if (is_array($cfg['callRecursive.']['tagStdWrap.'])) {
  4437. $tag = $this->stdWrap($tag,$cfg['callRecursive.']['tagStdWrap.']);
  4438. }
  4439. $parts[$k]=$tag.$parts[$k].'</'.$tagName.'>';
  4440. }
  4441. }
  4442. } elseif($cfg['HTMLtableCells']) {
  4443. $rowParts = $htmlParser->splitIntoBlock('tr',$parts[$k]);
  4444. foreach ($rowParts as $kk => $vv) {
  4445. if ($kk%2) {
  4446. $colParts = $htmlParser->splitIntoBlock('td,th',$vv);
  4447. $cc=0;
  4448. foreach ($colParts as $kkk => $vvv) {
  4449. if ($kkk%2) {
  4450. $cc++;
  4451. $tag=$htmlParser->getFirstTag($vvv);
  4452. $tagName=strtolower($htmlParser->getFirstTagName($vvv));
  4453. $colParts[$kkk] = $htmlParser->removeFirstAndLastTag($vvv);
  4454. if ($cfg['HTMLtableCells.'][$cc.'.']['callRecursive'] || (!isset($cfg['HTMLtableCells.'][$cc.'.']['callRecursive']) && $cfg['HTMLtableCells.']['default.']['callRecursive'])) {
  4455. if ($cfg['HTMLtableCells.']['addChr10BetweenParagraphs']) $colParts[$kkk]=str_replace('</p><p>','</p>'.LF.'<p>',$colParts[$kkk]);
  4456. $colParts[$kkk] = $this->parseFunc($colParts[$kkk], $conf);
  4457. }
  4458. $tagStdWrap = is_array($cfg['HTMLtableCells.'][$cc.'.']['tagStdWrap.'])?$cfg['HTMLtableCells.'][$cc.'.']['tagStdWrap.']:$cfg['HTMLtableCells.']['default.']['tagStdWrap.'];
  4459. if (is_array($tagStdWrap)) {
  4460. $tag = $this->stdWrap($tag,$tagStdWrap);
  4461. }
  4462. $stdWrap = is_array($cfg['HTMLtableCells.'][$cc.'.']['stdWrap.'])?$cfg['HTMLtableCells.'][$cc.'.']['stdWrap.']:$cfg['HTMLtableCells.']['default.']['stdWrap.'];
  4463. if (is_array($stdWrap)) {
  4464. $colParts[$kkk] = $this->stdWrap($colParts[$kkk],$stdWrap);
  4465. }
  4466. $colParts[$kkk]=$tag.$colParts[$kkk].'</'.$tagName.'>';
  4467. }
  4468. }
  4469. $rowParts[$kk] = implode('',$colParts);
  4470. }
  4471. }
  4472. $parts[$k] = implode('',$rowParts);
  4473. }
  4474. if (is_array($cfg['stdWrap.'])) {
  4475. $parts[$k] = $this->stdWrap($parts[$k],$cfg['stdWrap.']);
  4476. }
  4477. } else {
  4478. $parts[$k]=$this->_parseFunc($parts[$k], $conf);
  4479. }
  4480. }
  4481. return implode('',$parts);
  4482. } else return $this->_parseFunc($theValue, $conf);
  4483. }
  4484. /**
  4485. * Helper function for parseFunc()
  4486. *
  4487. * @param string The value to process.
  4488. * @param array TypoScript configuration for parseFunc
  4489. * @return string The processed value
  4490. * @access private
  4491. * @see parseFunc()
  4492. */
  4493. function _parseFunc ($theValue, $conf) {
  4494. if (!$this->checkIf($conf['if.'])) {
  4495. return $theValue;
  4496. }
  4497. $inside=0; // Indicates that the data is from within a tag.
  4498. $pointer=0; // Pointer to the total string position
  4499. $currentTag=''; // Loaded with the current typo-tag if any.
  4500. $stripNL=0;
  4501. $contentAccum=array();
  4502. $contentAccumP=0;
  4503. $allowTags=strtolower(str_replace(' ','',$conf['allowTags']));
  4504. $denyTags=strtolower(str_replace(' ','',$conf['denyTags']));
  4505. $totalLen = strlen($theValue);
  4506. do {
  4507. if (!$inside) {
  4508. if (!is_array($currentTag)) { // These operations should only be performed on code outside the typotags...
  4509. // data: this checks that we enter tags ONLY if the first char in the tag is alphanumeric OR '/'
  4510. $len_p=0;
  4511. $c=100;
  4512. do {
  4513. $len = strcspn(substr($theValue,$pointer+$len_p),'<');
  4514. $len_p+=$len+1;
  4515. $endChar = ord(strtolower(substr($theValue,$pointer+$len_p,1)));
  4516. $c--;
  4517. } while ($c>0 && $endChar && ($endChar<97 || $endChar>122) && $endChar!=47);
  4518. $len = $len_p-1;
  4519. } else {
  4520. // If we're inside a currentTag, just take it to the end of that tag!
  4521. $tempContent = strtolower(substr($theValue,$pointer));
  4522. $len = strpos ($tempContent, '</'.$currentTag[0]);
  4523. if (is_string ($len) && !$len) {
  4524. $len = strlen($tempContent);
  4525. }
  4526. }
  4527. $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
  4528. if ($data!='') {
  4529. if ($stripNL) { // If the previous tag was set to strip NewLines in the beginning of the next data-chunk.
  4530. $data = preg_replace('/^[ ]*'.CR.'?'.LF.'/', '', $data);
  4531. }
  4532. if (!is_array($currentTag)) { // These operations should only be performed on code outside the tags...
  4533. // Constants
  4534. $tmpConstants = $GLOBALS['TSFE']->tmpl->setup['constants.'];
  4535. if ($conf['constants'] && is_array($tmpConstants)) {
  4536. foreach ($tmpConstants as $key => $val) {
  4537. if (is_string($val)) {
  4538. $data = str_replace('###'.$key.'###', $val, $data);
  4539. }
  4540. }
  4541. }
  4542. // Short
  4543. if (is_array($conf['short.'])) {
  4544. $shortWords = $conf['short.'];
  4545. krsort($shortWords);
  4546. foreach ($shortWords as $key => $val) {
  4547. if (is_string($val)) {
  4548. $data = str_replace($key, $val, $data);
  4549. }
  4550. }
  4551. }
  4552. // stdWrap
  4553. if (is_array($conf['plainTextStdWrap.'])) {$data = $this->stdWrap($data,$conf['plainTextStdWrap.']);}
  4554. // userFunc
  4555. if ($conf['userFunc']) {$data = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $data);}
  4556. // Makelinks: (Before search-words as we need the links to be generated when searchwords go on...!)
  4557. if ($conf['makelinks']) {
  4558. $data = $this->http_makelinks($data,$conf['makelinks.']['http.']);
  4559. $data = $this->mailto_makelinks($data,$conf['makelinks.']['mailto.']);
  4560. }
  4561. // Search Words:
  4562. if ($GLOBALS['TSFE']->no_cache && $conf['sword'] && is_array($GLOBALS['TSFE']->sWordList) && $GLOBALS['TSFE']->sWordRegEx) {
  4563. $newstring = '';
  4564. do {
  4565. $pregSplitMode = 'i';
  4566. if (isset($GLOBALS['TSFE']->config['config']['sword_noMixedCase']) &&
  4567. !empty($GLOBALS['TSFE']->config['config']['sword_noMixedCase'])) {
  4568. $pregSplitMode = '';
  4569. }
  4570. $pieces = preg_split('/' . $GLOBALS['TSFE']->sWordRegEx . '/' . $pregSplitMode, $data, 2);
  4571. $newstring.=$pieces[0];
  4572. $match_len = strlen($data)-(strlen($pieces[0])+strlen($pieces[1]));
  4573. if (strstr($pieces[0],'<') || strstr($pieces[0],'>')) {
  4574. $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.
  4575. }
  4576. // The searchword:
  4577. $match = substr($data,strlen($pieces[0]),$match_len);
  4578. if (trim($match) && strlen($match)>1 && !$inTag) {
  4579. $match = $this->wrap($match, $conf['sword']);
  4580. }
  4581. // Concatenate the Search Word again.
  4582. $newstring.= $match;
  4583. $data=$pieces[1];
  4584. } while ($pieces[1]);
  4585. $data = $newstring;
  4586. }
  4587. }
  4588. $contentAccum[$contentAccumP].=$data;
  4589. }
  4590. $inside = 1;
  4591. } else {
  4592. // tags
  4593. $len = strcspn(substr($theValue,$pointer),'>')+1;
  4594. $data = substr($theValue,$pointer,$len);
  4595. $tag = explode(' ',trim(substr($data,1,-1)),2);
  4596. $tag[0]=strtolower($tag[0]);
  4597. if (substr($tag[0],0,1)=='/') {
  4598. $tag[0]=substr($tag[0],1);
  4599. $tag['out']=1;
  4600. }
  4601. if($conf['tags.'][$tag[0]]) {
  4602. $treated=0;
  4603. $stripNL = 0;
  4604. // in-tag
  4605. if (!$currentTag && !$tag['out']) {
  4606. $currentTag=$tag; // $currentTag (array!) is the tag we are currently processing
  4607. $contentAccumP++;
  4608. $treated=1;
  4609. // in-out-tag: img and other empty tags
  4610. if ($tag[0]=='img' || substr($tag[1],-3,2)==' /') {
  4611. $tag['out']=1;
  4612. }
  4613. }
  4614. // out-tag
  4615. if ($currentTag[0]==$tag[0] && $tag['out']) {
  4616. $theName = $conf['tags.'][$tag[0]];
  4617. $theConf = $conf['tags.'][$tag[0].'.'];
  4618. $stripNL = ($theConf['stripNL'] ? 1 : 0); // This flag indicates, that NL- (13-10-chars) should be stripped first and last.
  4619. $breakOut = ($theConf['breakoutTypoTagContent'] ? 1 : 0); // This flag indicates, that this TypoTag section should NOT be included in the nonTypoTag content.
  4620. $this->parameters=Array();
  4621. if ($currentTag[1]) {
  4622. $params=t3lib_div::get_tag_attributes($currentTag[1]);
  4623. if (is_array($params)) {
  4624. foreach ($params as $option => $val) {
  4625. $this->parameters[strtolower($option)]=$val;
  4626. }
  4627. }
  4628. }
  4629. $this->parameters['allParams']=trim($currentTag[1]);
  4630. 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
  4631. $contentAccum[$contentAccumP-1] = preg_replace('/'.CR.'?'.LF.'[ ]*$/', '', $contentAccum[$contentAccumP-1]);
  4632. $contentAccum[$contentAccumP] = preg_replace('/^[ ]*'.CR.'?'.LF.'/', '', $contentAccum[$contentAccumP]);
  4633. $contentAccum[$contentAccumP] = preg_replace('/'.CR.'?'.LF.'[ ]*$/', '', $contentAccum[$contentAccumP]);
  4634. }
  4635. $this->data[$this->currentValKey] = $contentAccum[$contentAccumP];
  4636. $newInput=$this->cObjGetSingle($theName,$theConf,'/parseFunc/.tags.'.$tag[0]); // fetch the content object
  4637. $contentAccum[$contentAccumP]=$newInput;
  4638. $contentAccumP++;
  4639. // If the TypoTag section
  4640. if (!$breakOut) {
  4641. $contentAccum[$contentAccumP-2].=$contentAccum[$contentAccumP-1].$contentAccum[$contentAccumP];
  4642. unset($contentAccum[$contentAccumP]);
  4643. unset($contentAccum[$contentAccumP-1]);
  4644. $contentAccumP-=2;
  4645. }
  4646. unset($currentTag);
  4647. $treated=1;
  4648. }
  4649. // other tags...
  4650. if (!$treated) {
  4651. $contentAccum[$contentAccumP].=$data;
  4652. }
  4653. } else {
  4654. // If a tag was not a typo tag, then it is just added to the content
  4655. $stripNL = 0;
  4656. if (t3lib_div::inList($allowTags,$tag[0]) || ($denyTags!='*' && !t3lib_div::inList($denyTags,$tag[0]))) {
  4657. $contentAccum[$contentAccumP].=$data;
  4658. } else {
  4659. $contentAccum[$contentAccumP].=HTMLSpecialChars($data);
  4660. }
  4661. }
  4662. $inside = 0;
  4663. }
  4664. $pointer+=$len;
  4665. } while($pointer<$totalLen);
  4666. // Parsing nonTypoTag content (all even keys):
  4667. reset($contentAccum);
  4668. for ($a=0;$a<count($contentAccum);$a++) {
  4669. if ($a%2 != 1) {
  4670. // stdWrap
  4671. if (is_array($conf['nonTypoTagStdWrap.'])) {$contentAccum[$a] = $this->stdWrap($contentAccum[$a],$conf['nonTypoTagStdWrap.']);}
  4672. // userFunc
  4673. if ($conf['nonTypoTagUserFunc']) {$contentAccum[$a] = $this->callUserFunction($conf['nonTypoTagUserFunc'], $conf['nonTypoTagUserFunc.'], $contentAccum[$a]);}
  4674. }
  4675. }
  4676. return implode('',$contentAccum);
  4677. }
  4678. /**
  4679. * Lets you split the content by LF and proces each line independently. Used to format content made with the RTE.
  4680. *
  4681. * @param string The input value
  4682. * @param array TypoScript options
  4683. * @return string The processed input value being returned; Splitted lines imploded by LF again.
  4684. * @access private
  4685. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=323&cHash=a19312be78
  4686. */
  4687. function encaps_lineSplit($theValue, $conf) {
  4688. $lParts = explode(LF,$theValue);
  4689. $encapTags = t3lib_div::trimExplode(',',strtolower($conf['encapsTagList']),1);
  4690. $nonWrappedTag = $conf['nonWrappedTag'];
  4691. $defaultAlign=trim($this->stdWrap($conf['defaultAlign'],$conf['defaultAlign.']));
  4692. if (!strcmp('',$theValue)) return '';
  4693. foreach ($lParts as $k => $l) {
  4694. $sameBeginEnd=0;
  4695. $l=trim($l);
  4696. $attrib=array();
  4697. $nWrapped=0;
  4698. $byPass=0;
  4699. if (substr($l,0,1)=='<' && substr($l,-1)=='>') {
  4700. $fwParts = explode('>',substr($l,1),2);
  4701. $backParts = t3lib_div::revExplode('<', substr($fwParts[1],0,-1), 2);
  4702. $attrib = t3lib_div::get_tag_attributes('<'.$fwParts[0].'>');
  4703. list($tagName) = explode(' ',$fwParts[0]);
  4704. $str_content = $backParts[0];
  4705. $sameBeginEnd = (substr(strtolower($backParts[1]),1,strlen($tagName))==strtolower($tagName));
  4706. }
  4707. if ($sameBeginEnd && in_array(strtolower($tagName),$encapTags)) {
  4708. $uTagName = strtoupper($tagName);
  4709. $uTagName = strtoupper($conf['remapTag.'][$uTagName]?$conf['remapTag.'][$uTagName]:$uTagName);
  4710. } else {
  4711. $uTagName = strtoupper($nonWrappedTag);
  4712. $str_content = $lParts[$k];
  4713. $nWrapped=1;
  4714. $attrib=array();
  4715. }
  4716. // Wrapping all inner-content:
  4717. if (is_array($conf['innerStdWrap_all.'])) {$str_content = $this->stdWrap($str_content,$conf['innerStdWrap_all.']);}
  4718. if ($uTagName) {
  4719. // Setting common attributes
  4720. if (is_array($conf['addAttributes.'][$uTagName.'.'])) {
  4721. foreach ($conf['addAttributes.'][$uTagName.'.'] as $kk => $vv) {
  4722. if (!is_array($vv)) {
  4723. if ((string)$conf['addAttributes.'][$uTagName.'.'][$kk.'.']['setOnly']=='blank') {
  4724. if (!strcmp($attrib[$kk],'')) $attrib[$kk]=$vv;
  4725. } elseif ((string)$conf['addAttributes.'][$uTagName.'.'][$kk.'.']['setOnly']=='exists') {
  4726. if (!isset($attrib[$kk])) $attrib[$kk]=$vv;
  4727. } else {
  4728. $attrib[$kk]=$vv;
  4729. }
  4730. }
  4731. }
  4732. }
  4733. // Wrapping all inner-content:
  4734. if (is_array($conf['encapsLinesStdWrap.'][$uTagName.'.'])) {$str_content = $this->stdWrap($str_content,$conf['encapsLinesStdWrap.'][$uTagName.'.']);}
  4735. // Default align
  4736. if (!$attrib['align'] && $defaultAlign) $attrib['align']=$defaultAlign;
  4737. $params = t3lib_div::implodeAttributes($attrib,1);
  4738. if ($conf['removeWrapping']) {
  4739. $str_content=$str_content;
  4740. } else {
  4741. $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').'>'.$str_content.'</'.strtolower($uTagName).'>';
  4742. }
  4743. }
  4744. if ($nWrapped && $conf['wrapNonWrappedLines']) {$str_content = $this->wrap($str_content,$conf['wrapNonWrappedLines']);}
  4745. $lParts[$k] = $str_content;
  4746. }
  4747. return implode(LF,$lParts);
  4748. }
  4749. /**
  4750. * Finds URLS in text and makes it to a real link.
  4751. * 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.
  4752. *
  4753. * @param string The string in which to search for "http://"
  4754. * @param array Configuration for makeLinks, see link
  4755. * @return string The processed input string, being returned.
  4756. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=328&cHash=c1135706d7
  4757. * @see _parseFunc()
  4758. */
  4759. function http_makelinks($data,$conf) {
  4760. $aTagParams = $this->getATagParams($conf);
  4761. $textpieces = explode('http://', $data);
  4762. $pieces = count($textpieces);
  4763. $textstr = $textpieces[0];
  4764. $initP = '?id='.$GLOBALS['TSFE']->id.'&type='.$GLOBALS['TSFE']->type;
  4765. for($i=1; $i<$pieces; $i++) {
  4766. $len=strcspn($textpieces[$i],chr(32).TAB.CRLF);
  4767. if (trim(substr($textstr,-1))=='' && $len) {
  4768. $lastChar=substr($textpieces[$i],$len-1,1);
  4769. if (!preg_match('/[A-Za-z0-9\/#_-]/',$lastChar)) {$len--;} // Included '\/' 3/12
  4770. $parts[0]=substr($textpieces[$i],0,$len);
  4771. $parts[1]=substr($textpieces[$i],$len);
  4772. $keep=$conf['keep'];
  4773. $linkParts=parse_url('http://'.$parts[0]);
  4774. $linktxt='';
  4775. if (strstr($keep,'scheme')) {
  4776. $linktxt='http://';
  4777. }
  4778. $linktxt.= $linkParts['host'];
  4779. if (strstr($keep,'path')) {
  4780. $linktxt.= $linkParts['path'];
  4781. if (strstr($keep,'query') && $linkParts['query']) { // added $linkParts['query'] 3/12
  4782. $linktxt.= '?'.$linkParts['query'];
  4783. } elseif ($linkParts['path']=='/') { // If query is NOT added and the path is '/' then remove the slash ('/') (added 3/12)
  4784. $linktxt=substr($linktxt,0,-1);
  4785. }
  4786. }
  4787. $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
  4788. if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
  4789. $res = '<a'.
  4790. ' href="'.htmlspecialchars($GLOBALS['TSFE']->absRefPrefix.$GLOBALS['TSFE']->config['mainScript'].$initP.'&jumpurl='.rawurlencode('http://'.$parts[0]).$GLOBALS['TSFE']->getMethodUrlIdToken).'"'.
  4791. ($target ? ' target="'.$target.'"' : '').
  4792. $aTagParams.
  4793. $this->extLinkATagParams('http://'.$parts[0], 'url').
  4794. '>';
  4795. } else {
  4796. $res = '<a'.
  4797. ' href="http://'.htmlspecialchars($parts[0]).'"'.
  4798. ($target ? ' target="'.$target.'"' : '').
  4799. $aTagParams.
  4800. $this->extLinkATagParams('http://'.$parts[0], 'url').
  4801. '>';
  4802. }
  4803. if ($conf['ATagBeforeWrap']) {
  4804. $res= $res.$this->wrap($linktxt, $conf['wrap']).'</a>';
  4805. } else {
  4806. $res= $this->wrap($res.$linktxt.'</a>', $conf['wrap']);
  4807. }
  4808. $textstr.=$res.$parts[1];
  4809. } else {
  4810. $textstr.='http://'.$textpieces[$i];
  4811. }
  4812. }
  4813. return $textstr;
  4814. }
  4815. /**
  4816. * Will find all strings prefixed with "mailto:" in the $data string and make them into a link, linking to the email address they point to.
  4817. *
  4818. * @param string The string in which to search for "mailto:"
  4819. * @param array Configuration for makeLinks, see link
  4820. * @return string The processed input string, being returned.
  4821. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=328&cHash=c1135706d7
  4822. * @see _parseFunc()
  4823. */
  4824. function mailto_makelinks($data,$conf) {
  4825. // http-split
  4826. $aTagParams = $this->getATagParams($conf);
  4827. $textpieces = explode('mailto:', $data);
  4828. $pieces = count($textpieces);
  4829. $textstr = $textpieces[0];
  4830. $initP = '?id='.$GLOBALS['TSFE']->id.'&type='.$GLOBALS['TSFE']->type;
  4831. for($i=1; $i<$pieces; $i++) {
  4832. $len = strcspn($textpieces[$i],chr(32).TAB.CRLF);
  4833. if (trim(substr($textstr,-1))=='' && $len) {
  4834. $lastChar = substr($textpieces[$i],$len-1,1);
  4835. if (!preg_match('/[A-Za-z0-9]/',$lastChar)) {$len--;}
  4836. $parts[0] = substr($textpieces[$i],0,$len);
  4837. $parts[1] = substr($textpieces[$i],$len);
  4838. $linktxt = preg_replace('/\?.*/','',$parts[0]);
  4839. list($mailToUrl,$linktxt) = $this->getMailTo($parts[0],$linktxt,$initP);
  4840. $mailToUrl = $GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii'?$mailToUrl:htmlspecialchars($mailToUrl);
  4841. $res = '<a href="'.$mailToUrl.'"'.$aTagParams.'>';
  4842. if ($conf['ATagBeforeWrap']) {
  4843. $res= $res.$this->wrap($linktxt, $conf['wrap']).'</a>';
  4844. } else {
  4845. $res= $this->wrap($res.$linktxt.'</a>', $conf['wrap']);
  4846. }
  4847. $textstr.=$res.$parts[1];
  4848. } else {
  4849. $textstr.='mailto:'.$textpieces[$i];
  4850. }
  4851. }
  4852. return $textstr;
  4853. }
  4854. /**
  4855. * Creates and returns a TypoScript "imgResource".
  4856. * The value ($file) can either be a file reference (TypoScript resource) or the string "GIFBUILDER". In the first case a current image is returned, possibly scaled down or otherwise processed. In the latter case a GIFBUILDER image is returned; This means an image is made by TYPO3 from layers of elements as GIFBUILDER defines.
  4857. * In the function IMG_RESOURCE() this function is called like $this->getImgResource($conf['file'],$conf['file.']);
  4858. *
  4859. * @param string A "imgResource" TypoScript data type. Either a TypoScript file resource or the string GIFBUILDER. See description above.
  4860. * @param array TypoScript properties for the imgResource type
  4861. * @return array Returns info-array. info[origFile] = original file.
  4862. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=315&cHash=63b593a934
  4863. * @see IMG_RESOURCE(), cImage(), tslib_gifBuilder
  4864. */
  4865. function getImgResource($file,$fileArray) {
  4866. if (is_array($fileArray)) {
  4867. switch($file) {
  4868. case 'GIFBUILDER':
  4869. $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
  4870. $gifCreator->init();
  4871. $theImage='';
  4872. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
  4873. $gifCreator->start($fileArray,$this->data);
  4874. $theImage = $gifCreator->gifBuild();
  4875. }
  4876. $imageResource = $gifCreator->getImageDimensions($theImage);
  4877. break;
  4878. default:
  4879. if ($fileArray['import.']) {
  4880. $ifile = $this->stdWrap('',$fileArray['import.']);
  4881. if ($ifile) {$file = $fileArray['import'].$ifile;}
  4882. }
  4883. $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file);
  4884. if ($theImage) {
  4885. $fileArray['width']= $this->stdWrap($fileArray['width'],$fileArray['width.']);
  4886. $fileArray['height']= $this->stdWrap($fileArray['height'],$fileArray['height.']);
  4887. $fileArray['ext']= $this->stdWrap($fileArray['ext'],$fileArray['ext.']);
  4888. $fileArray['maxW']= intval($this->stdWrap($fileArray['maxW'],$fileArray['maxW.']));
  4889. $fileArray['maxH']= intval($this->stdWrap($fileArray['maxH'],$fileArray['maxH.']));
  4890. $fileArray['minW']= intval($this->stdWrap($fileArray['minW'],$fileArray['minW.']));
  4891. $fileArray['minH']= intval($this->stdWrap($fileArray['minH'],$fileArray['minH.']));
  4892. $maskArray= $fileArray['m.'];
  4893. $maskImages=array();
  4894. 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!
  4895. $maskImages['m_mask'] = $this->getImgResource($maskArray['mask'],$maskArray['mask.']);
  4896. $maskImages['m_bgImg'] = $this->getImgResource($maskArray['bgImg'],$maskArray['bgImg.']);
  4897. $maskImages['m_bottomImg'] = $this->getImgResource($maskArray['bottomImg'],$maskArray['bottomImg.']);
  4898. $maskImages['m_bottomImg_mask'] = $this->getImgResource($maskArray['bottomImg_mask'],$maskArray['bottomImg_mask.']);
  4899. }
  4900. $hash = t3lib_div::shortMD5($theImage.serialize($fileArray).serialize($maskImages));
  4901. if (!isset($GLOBALS['TSFE']->tmpl->fileCache[$hash])) {
  4902. $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
  4903. $gifCreator->init();
  4904. if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
  4905. $filename = basename($theImage);
  4906. // remove extension
  4907. $filename = substr($filename, 0, strrpos($filename, '.'));
  4908. // strip everything non-ascii
  4909. $filename = preg_replace('/[^A-Za-z0-9_-]/', '', trim($filename));
  4910. $gifCreator->filenamePrefix = substr($filename, 0, intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix'])) . '_';
  4911. unset($filename);
  4912. }
  4913. if ($fileArray['sample']) {
  4914. $gifCreator->scalecmd = '-sample';
  4915. $GLOBALS['TT']->setTSlogMessage('Sample option: Images are scaled with -sample.');
  4916. }
  4917. if ($fileArray['alternativeTempPath'] && t3lib_div::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['allowedTempPaths'],$fileArray['alternativeTempPath'])) {
  4918. $gifCreator->tempPath = $fileArray['alternativeTempPath'];
  4919. $GLOBALS['TT']->setTSlogMessage('Set alternativeTempPath: '.$fileArray['alternativeTempPath']);
  4920. }
  4921. if (!trim($fileArray['ext'])){$fileArray['ext']='web';}
  4922. $options = Array();
  4923. if ($fileArray['maxW']) {$options['maxW']=$fileArray['maxW'];}
  4924. if ($fileArray['maxH']) {$options['maxH']=$fileArray['maxH'];}
  4925. if ($fileArray['minW']) {$options['minW']=$fileArray['minW'];}
  4926. if ($fileArray['minH']) {$options['minH']=$fileArray['minH'];}
  4927. // checks to see if m (the mask array) is defined
  4928. if (is_array($maskArray) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
  4929. // Filename:
  4930. $fI = t3lib_div::split_fileref($theImage);
  4931. $imgExt = (strtolower($fI['fileext'])==$gifCreator->gifExtension ? $gifCreator->gifExtension : 'jpg');
  4932. $dest = $gifCreator->tempPath.$hash.'.'.$imgExt;
  4933. if (!file_exists($dest)) { // Generate!
  4934. $m_mask= $maskImages['m_mask'];
  4935. $m_bgImg = $maskImages['m_bgImg'];
  4936. if ($m_mask && $m_bgImg) {
  4937. $negate = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_negate_mask'] ? ' -negate' : '';
  4938. $temp_ext='png';
  4939. if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_gif']) { // If ImageMagick version 5+
  4940. $temp_ext=$gifCreator->gifExtension;
  4941. }
  4942. $tempFileInfo = $gifCreator->imageMagickConvert($theImage,$temp_ext,$fileArray['width'],$fileArray['height'],$fileArray['params'],$fileArray['frame'],$options);
  4943. if (is_array($tempFileInfo)) {
  4944. $m_bottomImg = $maskImages['m_bottomImg'];
  4945. if ($m_bottomImg) {
  4946. $m_bottomImg_mask = $maskImages['m_bottomImg_mask'];
  4947. }
  4948. // Scaling: ****
  4949. $tempScale=array();
  4950. $command = '-geometry '.$tempFileInfo[0].'x'.$tempFileInfo[1].'!';
  4951. $command = $this->modifyImageMagickStripProfileParameters($command, $fileArray);
  4952. $tmpStr = $gifCreator->randomName();
  4953. // m_mask
  4954. $tempScale['m_mask']=$tmpStr.'_mask.'.$temp_ext;
  4955. $gifCreator->imageMagickExec($m_mask[3],$tempScale['m_mask'],$command.$negate);
  4956. // m_bgImg
  4957. $tempScale['m_bgImg']=$tmpStr.'_bgImg.'.trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']);
  4958. $gifCreator->imageMagickExec($m_bgImg[3],$tempScale['m_bgImg'],$command);
  4959. // m_bottomImg / m_bottomImg_mask
  4960. if ($m_bottomImg && $m_bottomImg_mask) {
  4961. $tempScale['m_bottomImg']=$tmpStr.'_bottomImg.'.$temp_ext;
  4962. $gifCreator->imageMagickExec($m_bottomImg[3],$tempScale['m_bottomImg'],$command);
  4963. $tempScale['m_bottomImg_mask']=$tmpStr.'_bottomImg_mask.'.$temp_ext;
  4964. $gifCreator->imageMagickExec($m_bottomImg_mask[3],$tempScale['m_bottomImg_mask'],$command.$negate);
  4965. // BEGIN combining:
  4966. // The image onto the background
  4967. $gifCreator->combineExec($tempScale['m_bgImg'],$tempScale['m_bottomImg'],$tempScale['m_bottomImg_mask'],$tempScale['m_bgImg']);
  4968. }
  4969. // The image onto the background
  4970. $gifCreator->combineExec($tempScale['m_bgImg'],$tempFileInfo[3],$tempScale['m_mask'],$dest);
  4971. // Unlink the temp-images...
  4972. foreach ($tempScale as $file) {
  4973. if (@is_file($file)) {
  4974. unlink($file);
  4975. }
  4976. }
  4977. // t3lib_div::print_array($GLOBALS['TSFE']->tmpl->fileCache[$hash]);
  4978. }
  4979. }
  4980. }
  4981. // Finish off
  4982. if (($fileArray['reduceColors'] || ($imgExt=='png' && !$gifCreator->png_truecolor)) && is_file($dest)) {
  4983. $reduced = $gifCreator->IMreduceColors($dest, t3lib_div::intInRange($fileArray['reduceColors'], 256, $gifCreator->truecolorColors, 256));
  4984. if (is_file($reduced)) {
  4985. unlink($dest);
  4986. rename($reduced, $dest);
  4987. }
  4988. }
  4989. $GLOBALS['TSFE']->tmpl->fileCache[$hash]= $gifCreator->getImageDimensions($dest);
  4990. } else { // Normal situation:
  4991. $fileArray['params'] = $this->modifyImageMagickStripProfileParameters($fileArray['params'], $fileArray);
  4992. $GLOBALS['TSFE']->tmpl->fileCache[$hash]= $gifCreator->imageMagickConvert($theImage,$fileArray['ext'],$fileArray['width'],$fileArray['height'],$fileArray['params'],$fileArray['frame'],$options);
  4993. if (($fileArray['reduceColors'] || ($imgExt=='png' && !$gifCreator->png_truecolor)) && is_file($GLOBALS['TSFE']->tmpl->fileCache[$hash][3])) {
  4994. $reduced = $gifCreator->IMreduceColors($GLOBALS['TSFE']->tmpl->fileCache[$hash][3], t3lib_div::intInRange($fileArray['reduceColors'], 256, $gifCreator->truecolorColors, 256));
  4995. if (is_file($reduced)) {
  4996. unlink($GLOBALS['TSFE']->tmpl->fileCache[$hash][3]);
  4997. rename($reduced, $GLOBALS['TSFE']->tmpl->fileCache[$hash][3]);
  4998. }
  4999. }
  5000. }
  5001. $GLOBALS['TSFE']->tmpl->fileCache[$hash]['origFile'] = $theImage;
  5002. $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.
  5003. $GLOBALS['TSFE']->tmpl->fileCache[$hash]['fileCacheHash'] = $hash;
  5004. }
  5005. $imageResource = $GLOBALS['TSFE']->tmpl->fileCache[$hash];
  5006. }
  5007. break;
  5008. }
  5009. }
  5010. $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file);
  5011. // If image was processed by GIFBUILDER:
  5012. // ($imageResource indicates that it was processed the regular way)
  5013. if (!isset($imageResource) && $theImage) {
  5014. $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
  5015. /* @var $gifCreator tslib_gifbuilder */
  5016. $gifCreator->init();
  5017. $info= $gifCreator->imageMagickConvert($theImage,'WEB','','','','','');
  5018. $info['origFile'] = $theImage;
  5019. $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.
  5020. $imageResource = $info;
  5021. }
  5022. // Hook 'getImgResource': Post-processing of image resources
  5023. if (isset($imageResource)) {
  5024. foreach($this->getGetImgResourceHookObjects() as $hookObject) {
  5025. $imageResource = $hookObject->getImgResourcePostProcess($file, (array)$fileArray, $imageResource, $this);
  5026. }
  5027. }
  5028. return $imageResource;
  5029. }
  5030. /**
  5031. * Modifies the parameters for ImageMagick for stripping of profile information.
  5032. *
  5033. * @param string $parameters: The parameters to be modified (if required)
  5034. * @param array $configuration: The TypoScript configuration of [IMAGE].file
  5035. * @param string The modified parameters
  5036. */
  5037. protected function modifyImageMagickStripProfileParameters($parameters, array $configuration) {
  5038. // Strips profile information of image to save some space:
  5039. if (isset($configuration['stripProfile'])) {
  5040. if ($configuration['stripProfile']) {
  5041. $parameters = $gfxConf['im_stripProfileCommand'] . $parameters;
  5042. } else {
  5043. $parameters.= '###SkipStripProfile###';
  5044. }
  5045. }
  5046. return $parameters;
  5047. }
  5048. /***********************************************
  5049. *
  5050. * Data retrieval etc.
  5051. *
  5052. ***********************************************/
  5053. /**
  5054. * 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.
  5055. *
  5056. * @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)
  5057. * @return string
  5058. */
  5059. function getFieldVal($field) {
  5060. if (!strstr($field,'//')) {
  5061. return $this->data[trim($field)];
  5062. } else {
  5063. $sections = t3lib_div::trimExplode('//',$field,1);
  5064. foreach ($sections as $k) {
  5065. if (strcmp($this->data[$k],'')) return $this->data[$k];
  5066. }
  5067. }
  5068. }
  5069. /**
  5070. * 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.
  5071. *
  5072. * @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)
  5073. * @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.
  5074. * @return string The value fetched
  5075. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=282&cHash=831a95115d
  5076. * @see getFieldVal()
  5077. */
  5078. function getData($string,$fieldArray) {
  5079. global $TYPO3_CONF_VARS;
  5080. if (!is_array($fieldArray)) {
  5081. $fieldArray=$GLOBALS['TSFE']->page;
  5082. }
  5083. $retVal = '';
  5084. $sections = explode('//',$string);
  5085. while (!$retVal AND list($secKey, $secVal)=each($sections)) {
  5086. $parts = explode(':',$secVal,2);
  5087. $key = trim($parts[1]);
  5088. if ((string)$key!='') {
  5089. $type = strtolower(trim($parts[0]));
  5090. switch($type) {
  5091. case 'gpvar':
  5092. t3lib_div::deprecationLog('Using gpvar in TypoScript getText is deprecated since TYPO3 4.3 - Use gp instead of gpvar.');
  5093. // Fall Through
  5094. case 'gp':
  5095. // Merge GET and POST and get $key out of the merged array
  5096. $retVal = $this->getGlobal(
  5097. $key,
  5098. t3lib_div::array_merge_recursive_overrule(t3lib_div::_GET(), t3lib_div::_POST())
  5099. );
  5100. break;
  5101. case 'tsfe':
  5102. $retVal = $this->getGlobal ('TSFE|' . $key);
  5103. break;
  5104. case 'getenv':
  5105. $retVal = getenv($key);
  5106. break;
  5107. case 'getindpenv':
  5108. $retVal = t3lib_div::getIndpEnv($key);
  5109. break;
  5110. case 'field':
  5111. $retVal = $fieldArray[$key];
  5112. break;
  5113. case 'parameters':
  5114. $retVal = $this->parameters[$key];
  5115. break;
  5116. case 'register':
  5117. $retVal = $GLOBALS['TSFE']->register[$key];
  5118. break;
  5119. case 'global':
  5120. $retVal = $this->getGlobal($key);
  5121. break;
  5122. case 'leveltitle':
  5123. $nkey = $this->getKey($key,$GLOBALS['TSFE']->tmpl->rootLine);
  5124. $retVal = $this->rootLineValue($nkey,'title',stristr($key,'slide'));
  5125. break;
  5126. case 'levelmedia':
  5127. $nkey = $this->getKey($key,$GLOBALS['TSFE']->tmpl->rootLine);
  5128. $retVal = $this->rootLineValue($nkey,'media',stristr($key,'slide'));
  5129. break;
  5130. case 'leveluid':
  5131. $nkey = $this->getKey($key,$GLOBALS['TSFE']->tmpl->rootLine);
  5132. $retVal = $this->rootLineValue($nkey,'uid',stristr($key,'slide'));
  5133. break;
  5134. case 'levelfield':
  5135. $keyP = t3lib_div::trimExplode(',',$key);
  5136. $nkey = $this->getKey($keyP[0],$GLOBALS['TSFE']->tmpl->rootLine);
  5137. $retVal = $this->rootLineValue($nkey,$keyP[1],strtolower($keyP[2])=='slide');
  5138. break;
  5139. case 'fullrootline':
  5140. $keyP = t3lib_div::trimExplode(',',$key);
  5141. $fullKey = intval($keyP[0])-count($GLOBALS['TSFE']->tmpl->rootLine)+count($GLOBALS['TSFE']->rootLine);
  5142. if ($fullKey>=0) {
  5143. $retVal = $this->rootLineValue($fullKey,$keyP[1],stristr($keyP[2],'slide'),$GLOBALS['TSFE']->rootLine);
  5144. }
  5145. break;
  5146. case 'date':
  5147. if (!$key) {$key = 'd/m Y';}
  5148. $retVal = date($key, $GLOBALS['EXEC_TIME']);
  5149. break;
  5150. case 'page':
  5151. $retVal = $GLOBALS['TSFE']->page[$key];
  5152. break;
  5153. case 'current':
  5154. $retVal = $this->data[$this->currentValKey];
  5155. break;
  5156. case 'level':
  5157. $retVal = count($GLOBALS['TSFE']->tmpl->rootLine)-1;
  5158. break;
  5159. case 'db':
  5160. $selectParts = t3lib_div::trimExplode(':',$key);
  5161. $db_rec = $GLOBALS['TSFE']->sys_page->getRawRecord($selectParts[0],$selectParts[1]);
  5162. if (is_array($db_rec) && $selectParts[2]) {$retVal = $db_rec[$selectParts[2]];}
  5163. break;
  5164. case 'lll':
  5165. $retVal = $GLOBALS['TSFE']->sL('LLL:'.$key);
  5166. break;
  5167. case 'path':
  5168. $retVal = $GLOBALS['TSFE']->tmpl->getFileName($key);
  5169. break;
  5170. case 'cobj':
  5171. switch((string)$key) {
  5172. case 'parentRecordNumber':
  5173. $retVal = $this->parentRecordNumber;
  5174. break;
  5175. }
  5176. break;
  5177. case 'debug':
  5178. switch((string)$key) {
  5179. case 'rootLine':
  5180. $retVal = t3lib_div::view_array($GLOBALS['TSFE']->tmpl->rootLine);
  5181. break;
  5182. case 'fullRootLine':
  5183. $retVal = t3lib_div::view_array($GLOBALS['TSFE']->rootLine);
  5184. break;
  5185. case 'data':
  5186. $retVal = t3lib_div::view_array($this->data);
  5187. break;
  5188. }
  5189. break;
  5190. }
  5191. }
  5192. if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'])) {
  5193. foreach($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'] as $classData) {
  5194. $hookObject = t3lib_div::getUserObj($classData);
  5195. if(!($hookObject instanceof tslib_content_getDataHook)) {
  5196. throw new UnexpectedValueException('$hookObject must implement interface tslib_content_getDataHook', 1195044480);
  5197. }
  5198. $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $this);
  5199. }
  5200. }
  5201. }
  5202. return $retVal;
  5203. }
  5204. /**
  5205. * Returns a value from the current rootline (site) from $GLOBALS['TSFE']->tmpl->rootLine;
  5206. *
  5207. * @param string Which level in the root line
  5208. * @param string The field in the rootline record to return (a field from the pages table)
  5209. * @param boolean If set, then we will traverse through the rootline from outer level towards the root level until the value found is true
  5210. * @param mixed If you supply an array for this it will be used as an alternative root line array
  5211. * @return string The value from the field of the rootline.
  5212. * @access private
  5213. * @see getData()
  5214. */
  5215. function rootLineValue($key,$field,$slideBack=0,$altRootLine='') {
  5216. $rootLine = is_array($altRootLine) ? $altRootLine : $GLOBALS['TSFE']->tmpl->rootLine;
  5217. if (!$slideBack) {
  5218. return $rootLine[$key][$field];
  5219. } else {
  5220. for ($a=$key;$a>=0;$a--) {
  5221. $val = $rootLine[$a][$field];
  5222. if ($val) {return $val;}
  5223. }
  5224. }
  5225. }
  5226. /**
  5227. * Return global variable where the input string $var defines array keys separated by "|"
  5228. * Example: $var = "HTTP_SERVER_VARS | something" will return the value $GLOBALS['HTTP_SERVER_VARS']['something'] value
  5229. *
  5230. * @param string Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back.
  5231. * @param array Alternative array than $GLOBAL to get variables from.
  5232. * @return mixed Whatever value. If none, then blank string.
  5233. * @see getData()
  5234. */
  5235. function getGlobal($keyString, $source = NULL) {
  5236. $keys = explode('|', $keyString);
  5237. $numberOfLevels = count($keys);
  5238. $rootKey = trim($keys[0]);
  5239. $value = isset($source) ? $source[$rootKey] : $GLOBALS[$rootKey];
  5240. for ($i = 1; $i < $numberOfLevels && isset($value); $i++) {
  5241. $currentKey = trim($keys[$i]);
  5242. if (is_object($value)) {
  5243. $value = $value->$currentKey;
  5244. } elseif (is_array($value)) {
  5245. $value = $value[$currentKey];
  5246. } else {
  5247. $value = '';
  5248. break;
  5249. }
  5250. }
  5251. if (!is_scalar($value)) {
  5252. $value = '';
  5253. }
  5254. return $value;
  5255. }
  5256. /**
  5257. * 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).
  5258. * Example: entrylevel = -1 means that entryLevel ends up pointing at the outermost-level, -2 means the level before the outermost...
  5259. *
  5260. * @param integer The integer to transform
  5261. * @param array Array in which the key should be found.
  5262. * @return integer The processed integer key value.
  5263. * @access private
  5264. * @see getData()
  5265. */
  5266. function getKey($key,$arr) {
  5267. $key = intval($key);
  5268. if (is_array($arr)) {
  5269. if ($key < 0) {
  5270. $key = count($arr)+$key;
  5271. }
  5272. if ($key < 0) {
  5273. $key=0;
  5274. }
  5275. }
  5276. return $key;
  5277. }
  5278. /**
  5279. * Looks up the incoming value in the defined TCA configuration
  5280. * Works only with TCA-type 'select' and options defined in 'items'
  5281. *
  5282. * @param mixed Comma-separated list of values to look up
  5283. * @param array TS-configuration array, see TSref for details
  5284. * @return string String of translated values, seperated by $delimiter. If no matches were found, the input value is simply returned.
  5285. * @todo It would be nice it this function basically looked up any type of value, db-relations etc.
  5286. */
  5287. function TCAlookup($inputValue,$conf) {
  5288. global $TCA;
  5289. $table = $conf['table'];
  5290. $field = $conf['field'];
  5291. $delimiter = $conf['delimiter']?$conf['delimiter']:' ,';
  5292. $GLOBALS['TSFE']->includeTCA();
  5293. if (is_array($TCA[$table]) && is_array($TCA[$table]['columns'][$field]) && is_array($TCA[$table]['columns'][$field]['config']['items'])) {
  5294. $values = t3lib_div::trimExplode(',',$inputValue);
  5295. $output = array();
  5296. foreach ($values as $value) {
  5297. // Traverse the items-array...
  5298. foreach ($TCA[$table]['columns'][$field]['config']['items'] as $item) {
  5299. // ... and return the first found label where the value was equal to $key
  5300. if (!strcmp($item[1],trim($value))) {
  5301. $output[] = $GLOBALS['TSFE']->sL($item[0]);
  5302. }
  5303. }
  5304. }
  5305. $returnValue = implode($delimiter,$output);
  5306. } else {
  5307. $returnValue = $inputValue;
  5308. }
  5309. return $returnValue;
  5310. }
  5311. /***********************************************
  5312. *
  5313. * Link functions (typolink)
  5314. *
  5315. ***********************************************/
  5316. /**
  5317. * Implements the "typolink" property of stdWrap (and others)
  5318. * 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.
  5319. * 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.
  5320. * 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.
  5321. * For many more details on the parameters and how they are intepreted, please see the link to TSref below.
  5322. *
  5323. * @param string The string (text) to link
  5324. * @param array TypoScript configuration (see link below)
  5325. * @return string A link-wrapped string.
  5326. * @see stdWrap(), tslib_pibase::pi_linkTP()
  5327. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=321&cHash=59bd727a5e
  5328. */
  5329. function typoLink($linktxt, $conf) {
  5330. $LD = array();
  5331. $finalTagParts = array();
  5332. $finalTagParts['aTagParams'] = $this->getATagParams($conf);
  5333. $link_param = trim($this->stdWrap($conf['parameter'],$conf['parameter.']));
  5334. $sectionMark = trim($this->stdWrap($conf['section'],$conf['section.']));
  5335. $sectionMark = $sectionMark ? (t3lib_div::testInt($sectionMark)?'#c':'#').$sectionMark : '';
  5336. $initP = '?id='.$GLOBALS['TSFE']->id.'&type='.$GLOBALS['TSFE']->type;
  5337. $this->lastTypoLinkUrl = '';
  5338. $this->lastTypoLinkTarget = '';
  5339. if ($link_param) {
  5340. $enableLinksAcrossDomains = $GLOBALS['TSFE']->config['config']['typolinkEnableLinksAcrossDomains'];
  5341. $link_paramA = t3lib_div::unQuoteFilenames($link_param,true);
  5342. // Check for link-handler keyword:
  5343. list($linkHandlerKeyword,$linkHandlerValue) = explode(':',trim($link_paramA[0]),2);
  5344. if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword] && strcmp($linkHandlerValue, '')) {
  5345. $linkHandlerObj = t3lib_div::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]);
  5346. if(method_exists($linkHandlerObj, 'main')) {
  5347. return $linkHandlerObj->main($linktxt, $conf, $linkHandlerKeyword, $linkHandlerValue, $link_param, $this);
  5348. }
  5349. }
  5350. $link_param = trim($link_paramA[0]); // Link parameter value
  5351. $linkClass = trim($link_paramA[2]); // Link class
  5352. if ($linkClass=='-') $linkClass = ''; // The '-' character means 'no class'. Necessary in order to specify a title as fourth parameter without setting the target or class!
  5353. $forceTarget = trim($link_paramA[1]); // Target value
  5354. $forceTitle = trim($link_paramA[3]); // Title value
  5355. if ($forceTarget=='-') $forceTarget = ''; // The '-' character means 'no target'. Necessary in order to specify a class as third parameter without setting the target!
  5356. // Check, if the target is coded as a JS open window link:
  5357. $JSwindowParts = array();
  5358. $JSwindowParams = '';
  5359. $onClick = '';
  5360. if ($forceTarget && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/',$forceTarget,$JSwindowParts)) {
  5361. // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
  5362. $JSwindow_tempParamsArr = t3lib_div::trimExplode(',',strtolower($conf['JSwindow_params'].','.$JSwindowParts[4]),1);
  5363. $JSwindow_paramsArr=array();
  5364. foreach($JSwindow_tempParamsArr as $JSv) {
  5365. list($JSp,$JSv) = explode('=',$JSv);
  5366. $JSwindow_paramsArr[$JSp]=$JSp.'='.$JSv;
  5367. }
  5368. // Add width/height:
  5369. $JSwindow_paramsArr['width']='width='.$JSwindowParts[1];
  5370. $JSwindow_paramsArr['height']='height='.$JSwindowParts[2];
  5371. // Imploding into string:
  5372. $JSwindowParams = implode(',',$JSwindow_paramsArr);
  5373. $forceTarget = ''; // Resetting the target since we will use onClick.
  5374. }
  5375. // Internal target:
  5376. $target = isset($conf['target']) ? $conf['target'] : $GLOBALS['TSFE']->intTarget;
  5377. if ($conf['target.']) {$target=$this->stdWrap($target, $conf['target.']);}
  5378. // Title tag
  5379. $title = $conf['title'];
  5380. if ($conf['title.']) {$title=$this->stdWrap($title, $conf['title.']);}
  5381. // Parse URL:
  5382. $pU = parse_url($link_param);
  5383. // Detecting kind of link:
  5384. if(strstr($link_param,'@') && (!$pU['scheme'] || $pU['scheme']=='mailto')) { // If it's a mail address:
  5385. $link_param = preg_replace('/^mailto:/i','',$link_param);
  5386. list($this->lastTypoLinkUrl,$linktxt) = $this->getMailTo($link_param,$linktxt,$initP);
  5387. $finalTagParts['url']=$this->lastTypoLinkUrl;
  5388. $finalTagParts['TYPE']='mailto';
  5389. } else {
  5390. $isLocalFile=0;
  5391. $fileChar=intval(strpos($link_param, '/'));
  5392. $urlChar=intval(strpos($link_param, '.'));
  5393. // Firsts, test if $link_param is numeric and page with such id exists. If yes, do not attempt to link to file
  5394. if (!t3lib_div::testInt($link_param) || count($GLOBALS['TSFE']->sys_page->getPage_noCheck($link_param)) == 0) {
  5395. // 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.
  5396. list($rootFileDat) = explode('?',rawurldecode($link_param));
  5397. $containsSlash = strstr($rootFileDat,'/');
  5398. $rFD_fI = pathinfo($rootFileDat);
  5399. if (trim($rootFileDat) && !$containsSlash && (@is_file(PATH_site.$rootFileDat) || t3lib_div::inList('php,html,htm',strtolower($rFD_fI['extension'])))) {
  5400. $isLocalFile = 1;
  5401. } elseif ($containsSlash) {
  5402. $isLocalFile = 2; // Adding this so realurl directories are linked right (non-existing).
  5403. }
  5404. }
  5405. if($pU['scheme'] || ($isLocalFile!=1 && $urlChar && (!$containsSlash || $urlChar<$fileChar))) { // url (external): If doubleSlash or if a '.' comes before a '/'.
  5406. $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
  5407. if ($conf['extTarget.']) {$target = $this->stdWrap($target, $conf['extTarget.']);}
  5408. if ($forceTarget) {$target=$forceTarget;}
  5409. if ($linktxt=='') $linktxt = $link_param;
  5410. if (!$pU['scheme']) {$scheme='http://';} else {$scheme='';}
  5411. if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
  5412. $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix.$GLOBALS['TSFE']->config['mainScript'].$initP.'&jumpurl='.rawurlencode($scheme.$link_param).$GLOBALS['TSFE']->getMethodUrlIdToken;
  5413. } else {
  5414. $this->lastTypoLinkUrl = $scheme.$link_param;
  5415. }
  5416. $this->lastTypoLinkTarget = $target;
  5417. $finalTagParts['url']=$this->lastTypoLinkUrl;
  5418. $finalTagParts['targetParams'] = $target ? ' target="'.$target.'"' : '';
  5419. $finalTagParts['TYPE']='url';
  5420. $finalTagParts['aTagParams'].=$this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']);
  5421. } elseif ($containsSlash || $isLocalFile) { // file (internal)
  5422. $splitLinkParam = explode('?', $link_param);
  5423. if (file_exists(rawurldecode($splitLinkParam[0])) || $isLocalFile) {
  5424. if ($linktxt=='') $linktxt = rawurldecode($link_param);
  5425. if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
  5426. $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix.$GLOBALS['TSFE']->config['mainScript'].$initP.'&jumpurl='.rawurlencode($link_param).$GLOBALS['TSFE']->getMethodUrlIdToken;
  5427. } else {
  5428. $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix.$link_param;
  5429. }
  5430. $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
  5431. $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $GLOBALS['TSFE']->fileTarget;
  5432. if ($conf['fileTarget.']) {$target = $this->stdWrap($target, $conf['fileTarget.']);}
  5433. if ($forceTarget) {$target=$forceTarget;}
  5434. $this->lastTypoLinkTarget = $target;
  5435. $finalTagParts['url'] = $this->lastTypoLinkUrl;
  5436. $finalTagParts['targetParams'] = $target ? ' target="'.$target.'"' : '';
  5437. $finalTagParts['TYPE'] = 'file';
  5438. $finalTagParts['aTagParams'].=$this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']);
  5439. } else {
  5440. $GLOBALS['TT']->setTSlogMessage("typolink(): File '".$splitLinkParam[0]."' did not exist, so '".$linktxt."' was not linked.",1);
  5441. return $linktxt;
  5442. }
  5443. } else { // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to definition in $TCA!)
  5444. if ($conf['no_cache.']) $conf['no_cache']=$this->stdWrap($conf['no_cache'], $conf['no_cache.']);
  5445. // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/parameters triplet
  5446. $pairParts = t3lib_div::trimExplode(',', $link_param, TRUE);
  5447. $link_param = $pairParts[0];
  5448. $link_params_parts = explode('#', $link_param);
  5449. $link_param = trim($link_params_parts[0]); // Link-data del
  5450. if (!strcmp($link_param,'')) {$link_param=$GLOBALS['TSFE']->id;} // If no id or alias is given
  5451. if ($link_params_parts[1] && !$sectionMark) {
  5452. $sectionMark = trim($link_params_parts[1]);
  5453. $sectionMark = (t3lib_div::testInt($sectionMark)?'#c':'#').$sectionMark;
  5454. }
  5455. unset($theTypeP);
  5456. if (count($pairParts)>1) {
  5457. $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0; // Overruling 'type'
  5458. $conf['additionalParams'].= isset($pairParts[2]) ? $pairParts[2] : '';
  5459. }
  5460. // Checking if the id-parameter is an alias.
  5461. if (!t3lib_div::testInt($link_param)) {
  5462. $link_param = $GLOBALS['TSFE']->sys_page->getPageIdFromAlias($link_param);
  5463. }
  5464. // Link to page even if access is missing?
  5465. if (strlen($conf['linkAccessRestrictedPages'])) {
  5466. $disableGroupAccessCheck = ($conf['linkAccessRestrictedPages'] ? TRUE : FALSE);
  5467. } else {
  5468. $disableGroupAccessCheck = ($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] ? TRUE : FALSE);
  5469. }
  5470. // Looking up the page record to verify its existence:
  5471. $page = $GLOBALS['TSFE']->sys_page->getPage($link_param,$disableGroupAccessCheck);
  5472. if (count($page)) {
  5473. // MointPoints, look for closest MPvar:
  5474. $MPvarAcc = array();
  5475. if (!$GLOBALS['TSFE']->config['config']['MP_disableTypolinkClosestMPvalue']) {
  5476. $temp_MP = $this->getClosestMPvalueForPage($page['uid'],TRUE);
  5477. if ($temp_MP) $MPvarAcc['closest'] = $temp_MP;
  5478. }
  5479. // Look for overlay Mount Point:
  5480. $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($page['uid'], $page);
  5481. if (is_array($mount_info) && $mount_info['overlay']) {
  5482. $page = $GLOBALS['TSFE']->sys_page->getPage($mount_info['mount_pid'],$disableGroupAccessCheck);
  5483. if (!count($page)) {
  5484. $GLOBALS['TT']->setTSlogMessage("typolink(): Mount point '".$mount_info['mount_pid']."' was not available, so '".$linktxt."' was not linked.",1);
  5485. return $linktxt;
  5486. }
  5487. $MPvarAcc['re-map'] = $mount_info['MPvar'];
  5488. }
  5489. // Setting title if blank value to link:
  5490. if ($linktxt=='') $linktxt = $page['title'];
  5491. // Query Params:
  5492. $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : '';
  5493. $addQueryParams .= trim($this->stdWrap($conf['additionalParams'],$conf['additionalParams.']));
  5494. if ($addQueryParams == '&' || substr($addQueryParams, 0, 1) != '&') {
  5495. $addQueryParams = '';
  5496. }
  5497. if ($conf['useCacheHash']) {
  5498. // Mind the order below! See http://bugs.typo3.org/view.php?id=5117
  5499. $params = $GLOBALS['TSFE']->linkVars . $addQueryParams;
  5500. if (trim($params, '& ') != '') {
  5501. $addQueryParams .= '&cHash=' . t3lib_div::generateCHash($params);
  5502. }
  5503. unset($params);
  5504. }
  5505. $targetDomain = '';
  5506. $currentDomain = t3lib_div::getIndpEnv('HTTP_HOST');
  5507. // Mount pages are always local and never link to another domain
  5508. if (count($MPvarAcc)) {
  5509. // Add "&MP" var:
  5510. $addQueryParams.= '&MP='.rawurlencode(implode(',',$MPvarAcc));
  5511. }
  5512. elseif (strpos($addQueryParams, '&MP=') === false && $GLOBALS['TSFE']->config['config']['typolinkCheckRootline']) {
  5513. // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from
  5514. // menu. Mount points always work in the content of the current domain and we must not change
  5515. // domain if MP variables exist.
  5516. // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
  5517. // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
  5518. // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
  5519. if ($enableLinksAcrossDomains && $page['doktype'] == 4 && $page['shortcut_mode'] == 0) {
  5520. $page2 = $page; // Save in case of broken destination or endless loop
  5521. $maxLoopCount = 20; // Same as in RealURL, seems enough
  5522. while ($maxLoopCount && is_array($page) && $page['doktype'] == 4 && $page['shortcut_mode'] == 0) {
  5523. $page = $GLOBALS['TSFE']->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck);
  5524. $maxLoopCount--;
  5525. }
  5526. if (count($page) == 0 || $maxLoopCount == 0) {
  5527. // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop)
  5528. $page = $page2;
  5529. }
  5530. }
  5531. // Find all domain records in the rootline of the target page
  5532. $targetPageRootline = $GLOBALS['TSFE']->sys_page->getRootLine($page['uid']);
  5533. $foundDomains = array();
  5534. $firstFoundDomains = array();
  5535. $firstFoundForcedDomains = array();
  5536. $targetPageRootlinePids = array();
  5537. foreach ($targetPageRootline as $data) {
  5538. $targetPageRootlinePids[] = intval($data['uid']);
  5539. }
  5540. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  5541. 'pid, domainName, forced',
  5542. 'sys_domain',
  5543. 'pid IN (' . implode(',', $targetPageRootlinePids) . ') ' .
  5544. ' AND redirectTo=\'\' ' . $this->enableFields('sys_domain'),
  5545. '',
  5546. 'sorting ASC'
  5547. );
  5548. // TODO maybe it makes sense to hold all sys_domain records in a cache to save additional DB querys on each typolink
  5549. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  5550. $foundDomains[] = preg_replace('/\/$/', '', $row['domainName']);
  5551. if (!isset($firstFoundDomains[$row['pid']])) {
  5552. $firstFoundDomains[$row['pid']] = preg_replace('/\/$/', '', $row['domainName']);
  5553. }
  5554. if ($row['forced'] && !isset($firstFoundForcedDomains[$row['pid']])) {
  5555. $firstFoundForcedDomains[$row['pid']] = preg_replace('/\/$/', '', $row['domainName']);
  5556. }
  5557. }
  5558. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  5559. // Set targetDomain to first found domain record if the target page cannot be reached within the current domain
  5560. if (count($foundDomains) > 0
  5561. && (!in_array($currentDomain, $foundDomains) || count($firstFoundForcedDomains) > 0)) {
  5562. foreach ($targetPageRootlinePids as $pid) {
  5563. // Always use the 'forced' domain if we found one
  5564. if (isset($firstFoundForcedDomains[$pid])) {
  5565. $targetDomain = $firstFoundForcedDomains[$pid];
  5566. break;
  5567. }
  5568. // Use the first found domain record
  5569. if ($targetDomain === '' && isset($firstFoundDomains[$pid])) {
  5570. $targetDomain = $firstFoundDomains[$pid];
  5571. }
  5572. }
  5573. // Do not prepend the domain if its the current hostname
  5574. if ($targetDomain === $currentDomain) {
  5575. $targetDomain = '';
  5576. }
  5577. }
  5578. }
  5579. $absoluteUrlScheme = 'http';
  5580. // URL shall be absolute:
  5581. if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl']) {
  5582. // If no domain records are defined, use current domain:
  5583. if ($targetDomain === '') {
  5584. $targetDomain = $currentDomain;
  5585. }
  5586. // Override scheme:
  5587. if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
  5588. $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
  5589. }
  5590. }
  5591. // If target page has a different domain and the current domain's linking scheme (e.g. simulateStaticDocuments/RealURL/...) should not be used
  5592. if (strlen($targetDomain) && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
  5593. $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
  5594. if ($conf['extTarget.']) {
  5595. $target = $this->stdWrap($target, $conf['extTarget.']);
  5596. }
  5597. if ($forceTarget) {
  5598. $target = $forceTarget;
  5599. }
  5600. $LD['target'] = $target;
  5601. $this->lastTypoLinkUrl = $this->URLqMark($absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'], $addQueryParams) . $sectionMark;
  5602. } else { // Internal link or current domain's linking scheme should be used
  5603. if ($forceTarget) {
  5604. $target = $forceTarget;
  5605. }
  5606. $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $conf['no_cache'], '', '', $addQueryParams, $theTypeP, $targetDomain);
  5607. if (strlen($targetDomain)) {
  5608. // We will add domain only if URL does not have it already.
  5609. if ($enableLinksAcrossDomains) {
  5610. // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
  5611. // to the current web site. If we have domain here it means we link across
  5612. // domains. absRefPrefix can contain domain name, which will screw up
  5613. // the link to the external domain.
  5614. $prefixLength = strlen($GLOBALS['TSFE']->config['config']['absRefPrefix']);
  5615. if (substr($LD['totalURL'], 0, $prefixLength) == $GLOBALS['TSFE']->config['config']['absRefPrefix']) {
  5616. $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
  5617. }
  5618. }
  5619. $urlParts = parse_url($LD['totalURL']);
  5620. if ($urlParts['host'] == '') {
  5621. $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . ($LD['totalURL']{0} == '/' ? '' : '/') . $LD['totalURL'];
  5622. }
  5623. }
  5624. $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'],'').$sectionMark;
  5625. }
  5626. $this->lastTypoLinkTarget = $LD['target'];
  5627. $targetPart = $LD['target'] ? ' target="'.$LD['target'].'"' : '';
  5628. // 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.
  5629. if ($sectionMark && !$GLOBALS['TSFE']->config['config']['baseURL'] &&
  5630. $page['uid'] == $GLOBALS['TSFE']->id && !trim($addQueryParams) &&
  5631. !($conf['addQueryString'] && $conf['addQueryString.'])) {
  5632. list(,$URLparams) = explode('?',$this->lastTypoLinkUrl);
  5633. list($URLparams) = explode('#',$URLparams);
  5634. parse_str ($URLparams.$LD['orig_type'], $URLparamsArray);
  5635. if (intval($URLparamsArray['type'])==$GLOBALS['TSFE']->type) { // type nums must match as well as page ids
  5636. unset($URLparamsArray['id']);
  5637. unset($URLparamsArray['type']);
  5638. if (!count($URLparamsArray)) { // If there are no parameters left.... set the new url.
  5639. $this->lastTypoLinkUrl = $sectionMark;
  5640. }
  5641. }
  5642. }
  5643. // If link is to a access restricted page which should be redirected, then find new URL:
  5644. if ($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] &&
  5645. $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages']!=='NONE' &&
  5646. !$GLOBALS['TSFE']->checkPageGroupAccess($page)) {
  5647. $thePage = $GLOBALS['TSFE']->sys_page->getPage($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages']);
  5648. $addParams = $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages_addParams'];
  5649. $addParams = str_replace('###RETURN_URL###',rawurlencode($this->lastTypoLinkUrl),$addParams);
  5650. $addParams = str_replace('###PAGE_ID###',$page['uid'],$addParams);
  5651. $this->lastTypoLinkUrl = $this->getTypoLink_URL(
  5652. $thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''),
  5653. $addParams,
  5654. $target
  5655. );
  5656. $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
  5657. $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
  5658. $LD = $this->lastTypoLinkLD;
  5659. }
  5660. // Rendering the tag.
  5661. $finalTagParts['url']=$this->lastTypoLinkUrl;
  5662. $finalTagParts['targetParams']=$targetPart;
  5663. $finalTagParts['TYPE']='page';
  5664. } else {
  5665. $GLOBALS['TT']->setTSlogMessage("typolink(): Page id '".$link_param."' was not found, so '".$linktxt."' was not linked.",1);
  5666. return $linktxt;
  5667. }
  5668. }
  5669. }
  5670. $this->lastTypoLinkLD = $LD;
  5671. if ($forceTitle) {
  5672. $title=$forceTitle;
  5673. }
  5674. if ($JSwindowParams) {
  5675. // Create TARGET-attribute only if the right doctype is used
  5676. if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
  5677. $target = ' target="FEopenLink"';
  5678. } else {
  5679. $target = '';
  5680. }
  5681. $onClick="vHWin=window.open('".$GLOBALS['TSFE']->baseUrlWrap($finalTagParts['url'])."','FEopenLink','".$JSwindowParams."');vHWin.focus();return false;";
  5682. $res = '<a href="'.htmlspecialchars($finalTagParts['url']).'"'. $target .' onclick="'.htmlspecialchars($onClick).'"'.($title?' title="'.$title.'"':'').($linkClass?' class="'.$linkClass.'"':'').$finalTagParts['aTagParams'].'>';
  5683. } else {
  5684. if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' && $finalTagParts['TYPE'] === 'mailto') {
  5685. $res = '<a href="'.$finalTagParts['url'].'"'.($title?' title="'.$title.'"':'').$finalTagParts['targetParams'].($linkClass?' class="'.$linkClass.'"':'').$finalTagParts['aTagParams'].'>';
  5686. } else {
  5687. $res = '<a href="'.htmlspecialchars($finalTagParts['url']).'"'.($title?' title="'.$title.'"':'').$finalTagParts['targetParams'].($linkClass?' class="'.$linkClass.'"':'').$finalTagParts['aTagParams'].'>';
  5688. }
  5689. }
  5690. // Call user function:
  5691. if ($conf['userFunc']) {
  5692. $finalTagParts['TAG']=$res;
  5693. $res = $this->callUserFunction($conf['userFunc'],$conf['userFunc.'],$finalTagParts);
  5694. }
  5695. // Hook: Call post processing function for link rendering:
  5696. if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) {
  5697. $_params = array(
  5698. 'conf' => &$conf,
  5699. 'linktxt' => &$linktxt,
  5700. 'finalTag' => &$res,
  5701. 'finalTagParts' => &$finalTagParts,
  5702. );
  5703. foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) {
  5704. t3lib_div::callUserFunction($_funcRef, $_params, $this);
  5705. }
  5706. }
  5707. // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
  5708. if ($conf['returnLast']) {
  5709. switch($conf['returnLast']) {
  5710. case 'url':
  5711. return $this->lastTypoLinkUrl;
  5712. break;
  5713. case 'target':
  5714. return $this->lastTypoLinkTarget;
  5715. break;
  5716. }
  5717. }
  5718. if ($conf['ATagBeforeWrap']) {
  5719. return $res.$this->wrap($linktxt, $conf['wrap']).'</a>';
  5720. } else {
  5721. return $this->wrap($res.$linktxt.'</a>', $conf['wrap']);
  5722. }
  5723. } else {
  5724. return $linktxt;
  5725. }
  5726. }
  5727. /**
  5728. * Forces a given URL to be absolute.
  5729. *
  5730. * @param string $url The URL to be forced to be absolute
  5731. * @param array $configuration TypoScript configuration of typolink
  5732. * @return string The absolute URL
  5733. */
  5734. protected function forceAbsoluteUrl($url, array $configuration) {
  5735. if (!empty($url) && isset($configuration['forceAbsoluteUrl']) && $configuration['forceAbsoluteUrl']) {
  5736. if (preg_match('#^(?:([a-z]+)(://))?([^/]*)(.*)$#', $url, $matches)) {
  5737. $urlParts = array(
  5738. 'scheme' => $matches[1],
  5739. 'delimiter' => '://',
  5740. 'host' => $matches[3],
  5741. 'path' => $matches[4],
  5742. );
  5743. // Set scheme and host if not yet part of the URL:
  5744. if (empty($urlParts['host'])) {
  5745. $urlParts['scheme'] = 'http';
  5746. $urlParts['host'] = t3lib_div::getIndpEnv('HTTP_HOST');
  5747. $isUrlModified = TRUE;
  5748. }
  5749. // Override scheme:
  5750. $forceAbsoluteUrl =& $configuration['forceAbsoluteUrl.']['scheme'];
  5751. if (!empty($forceAbsoluteUrl) && $urlParts['scheme'] !== $forceAbsoluteUrl) {
  5752. $urlParts['scheme'] = $forceAbsoluteUrl;
  5753. $isUrlModified = TRUE;
  5754. }
  5755. // Recreate the absolute URL:
  5756. if ($isUrlModified) {
  5757. $url = implode('', $urlParts);
  5758. }
  5759. }
  5760. }
  5761. return $url;
  5762. }
  5763. /**
  5764. * Based on the input "TypoLink" TypoScript configuration this will return the generated URL
  5765. *
  5766. * @param array TypoScript properties for "typolink"
  5767. * @return string The URL of the link-tag that typolink() would by itself return
  5768. * @see typoLink()
  5769. */
  5770. function typoLink_URL($conf) {
  5771. $this->typolink('|',$conf);
  5772. return $this->lastTypoLinkUrl;
  5773. }
  5774. /**
  5775. * Returns a linked string made from typoLink parameters.
  5776. *
  5777. * 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.
  5778. * Optionally you can supply $urlParameters which is an array with key/value pairs that are rawurlencoded and appended to the resulting url.
  5779. *
  5780. * @param string Text string being wrapped by the link.
  5781. * @param string Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file.
  5782. * @param array An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
  5783. * @param string Specific target set, if any. (Default is using the current)
  5784. * @return string The wrapped $label-text string
  5785. * @see getTypoLink_URL()
  5786. */
  5787. function getTypoLink($label,$params,$urlParameters=array(),$target='') {
  5788. $conf=array();
  5789. $conf['parameter'] = $params;
  5790. if ($target) {
  5791. $conf['target']=$target;
  5792. $conf['extTarget']=$target;
  5793. $conf['fileTarget']=$target;
  5794. }
  5795. if (is_array($urlParameters)) {
  5796. if (count($urlParameters)) {
  5797. $conf['additionalParams'].= t3lib_div::implodeArrayForUrl('',$urlParameters);
  5798. }
  5799. } else {
  5800. $conf['additionalParams'].=$urlParameters;
  5801. }
  5802. $out = $this->typolink($label,$conf);
  5803. return $out;
  5804. }
  5805. /**
  5806. * Returns the URL of a "typolink" create from the input parameter string, url-parameters and target
  5807. *
  5808. * @param string Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file.
  5809. * @param array An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
  5810. * @param string Specific target set, if any. (Default is using the current)
  5811. * @return string The URL
  5812. * @see getTypoLink()
  5813. */
  5814. function getTypoLink_URL($params,$urlParameters=array(),$target='') {
  5815. $this->getTypoLink('',$params,$urlParameters,$target);
  5816. return $this->lastTypoLinkUrl;
  5817. }
  5818. /**
  5819. * Generates a typolink and returns the two link tags - start and stop - in an array
  5820. *
  5821. * @param array "typolink" TypoScript properties
  5822. * @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
  5823. * @see typolink()
  5824. */
  5825. function typolinkWrap($conf) {
  5826. $k=md5(microtime());
  5827. return explode($k,$this->typolink($k,$conf));
  5828. }
  5829. /**
  5830. * Returns the current page URL
  5831. *
  5832. * @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.
  5833. * @param integer An alternative ID to the current id ($GLOBALS['TSFE']->id)
  5834. * @return string The URL
  5835. * @see getTypoLink_URL()
  5836. */
  5837. function currentPageUrl($urlParameters=array(),$id=0) {
  5838. return $this->getTypoLink_URL($id?$id:$GLOBALS['TSFE']->id,$urlParameters,$GLOBALS['TSFE']->sPre);
  5839. }
  5840. /**
  5841. * Returns the &MP variable value for a page id.
  5842. * 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.
  5843. *
  5844. * @param integer page id
  5845. * @param boolean If true, the MPvalue is returned raw. Normally it is encoded as &MP=... variable
  5846. * @return string MP value, prefixed with &MP= (depending on $raw)
  5847. * @see typolink()
  5848. */
  5849. function getClosestMPvalueForPage($pageId, $raw=FALSE) {
  5850. // MointPoints:
  5851. if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $GLOBALS['TSFE']->MP) {
  5852. if (!strcmp($GLOBALS['TSFE']->id, $pageId)) { // same page as current.
  5853. $MP = $GLOBALS['TSFE']->MP;
  5854. } else { // ... otherwise find closest meeting point:
  5855. $tCR_rootline = $GLOBALS['TSFE']->sys_page->getRootLine($pageId, '', TRUE); // Gets rootline of linked-to page
  5856. $inverseTmplRootline = array_reverse($GLOBALS['TSFE']->tmpl->rootLine);
  5857. $rl_mpArray = array();
  5858. $startMPaccu = FALSE;
  5859. // Traverse root line of link uid and inside of that the REAL root line of current position.
  5860. foreach($tCR_rootline as $tCR_data) {
  5861. foreach($inverseTmplRootline as $rlKey => $invTmplRLRec) {
  5862. // Force accumulating when in overlay mode: Links to this page have to stay within the current branch
  5863. if ($invTmplRLRec['_MOUNT_OL'] && ($tCR_data['uid']==$invTmplRLRec['uid'])) {
  5864. $startMPaccu = TRUE;
  5865. }
  5866. // Accumulate MP data:
  5867. if ($startMPaccu && $invTmplRLRec['_MP_PARAM']) {
  5868. $rl_mpArray[] = $invTmplRLRec['_MP_PARAM'];
  5869. }
  5870. // If two PIDs matches and this is NOT the site root, start accumulation of MP data (on the next level):
  5871. // (The check for site root is done so links to branches outsite the site but sharing the site roots PID is NOT detected as within the branch!)
  5872. if ($tCR_data['pid']==$invTmplRLRec['pid'] && count($inverseTmplRootline)!=$rlKey+1) {
  5873. $startMPaccu = TRUE;
  5874. }
  5875. }
  5876. if ($startMPaccu) break; // Good enough...
  5877. }
  5878. if (count($rl_mpArray)) {
  5879. $MP = implode(',', array_reverse($rl_mpArray));
  5880. }
  5881. }
  5882. }
  5883. return !$raw ? ($MP ? '&MP='.rawurlencode($MP) : '') : $MP;
  5884. }
  5885. /**
  5886. * Creates a href attibute for given $mailAddress.
  5887. * The function uses spamProtectEmailAddresses and Jumpurl functionality for encoding the mailto statement.
  5888. * If spamProtectEmailAddresses is disabled, it'll just return a string like "mailto:user@example.tld".
  5889. *
  5890. * @param string Email address
  5891. * @param string Link text, default will be the email address.
  5892. * @param string Initial link parameters, only used if Jumpurl functionality is enabled. Example: ?id=5&type=0
  5893. * @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.
  5894. */
  5895. function getMailTo($mailAddress,$linktxt,$initP='?') {
  5896. if(!strcmp($linktxt,'')) { $linktxt = $mailAddress; }
  5897. $mailToUrl = 'mailto:'.$mailAddress;
  5898. if (!$GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $GLOBALS['TSFE']->config['config']['jumpurl_mailto_disable']) {
  5899. if ($GLOBALS['TSFE']->spamProtectEmailAddresses) {
  5900. if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii') {
  5901. $mailToUrl = $GLOBALS['TSFE']->encryptEmail($mailToUrl);
  5902. } else {
  5903. $mailToUrl = "javascript:linkTo_UnCryptMailto('".$GLOBALS['TSFE']->encryptEmail($mailToUrl)."');";
  5904. }
  5905. if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']) {
  5906. $atLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']);
  5907. }
  5908. $spamProtectedMailAddress = str_replace('@', ($atLabel ? $atLabel : '(at)'), $mailAddress);
  5909. if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']) {
  5910. $lastDotLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']);
  5911. $lastDotLabel = $lastDotLabel ? $lastDotLabel : '(dot)';
  5912. $spamProtectedMailAddress = preg_replace('/\.([^\.]+)$/', $lastDotLabel.'$1', $spamProtectedMailAddress);
  5913. }
  5914. $linktxt = str_ireplace($mailAddress, $spamProtectedMailAddress, $linktxt);
  5915. }
  5916. } else {
  5917. $mailToUrl = $GLOBALS['TSFE']->absRefPrefix.$GLOBALS['TSFE']->config['mainScript'].$initP.'&jumpurl='.rawurlencode($mailToUrl).$GLOBALS['TSFE']->getMethodUrlIdToken;
  5918. }
  5919. return array($mailToUrl,$linktxt);
  5920. }
  5921. /**
  5922. * Gets the query arguments and assembles them for URLs.
  5923. * Arguments may be removed or set, depending on configuration.
  5924. *
  5925. * @param string Configuration
  5926. * @param array Multidimensional key/value pairs that overrule incoming query arguments
  5927. * @param boolean If set, key/value pairs not in the query but the overrule array will be set
  5928. * @return string The URL query part (starting with a &)
  5929. */
  5930. public function getQueryArguments($conf, $overruleQueryArguments=array(), $forceOverruleArguments = FALSE) {
  5931. switch ((string)$conf['method']) {
  5932. case 'GET':
  5933. $currentQueryArray = t3lib_div::_GET();
  5934. break;
  5935. case 'POST':
  5936. $currentQueryArray = t3lib_div::_POST();
  5937. break;
  5938. case 'GET,POST':
  5939. $currentQueryArray = array_merge(t3lib_div::_GET(), t3lib_div::_POST());
  5940. break;
  5941. case 'POST,GET':
  5942. $currentQueryArray = array_merge(t3lib_div::_POST(), t3lib_div::_GET());
  5943. break;
  5944. default:
  5945. $currentQueryArray = t3lib_div::explodeUrl2Array(t3lib_div::getIndpEnv('QUERY_STRING'), TRUE);
  5946. }
  5947. if ($conf['exclude']) {
  5948. $exclude = str_replace(',', '&', $conf['exclude']);
  5949. $exclude = t3lib_div::explodeUrl2Array($exclude, TRUE);
  5950. // never repeat id
  5951. $exclude['id'] = 0;
  5952. $newQueryArray = t3lib_div::arrayDiffAssocRecursive($currentQueryArray, $exclude);
  5953. } else {
  5954. $newQueryArray = $currentQueryArray;
  5955. }
  5956. if ($forceOverruleArguments) {
  5957. $newQueryArray = t3lib_div::array_merge_recursive_overrule($newQueryArray, $overruleQueryArguments);
  5958. } else {
  5959. $newQueryArray = t3lib_div::array_merge_recursive_overrule($newQueryArray, $overruleQueryArguments, TRUE);
  5960. }
  5961. return t3lib_div::implodeArrayForUrl('', $newQueryArray);
  5962. }
  5963. /***********************************************
  5964. *
  5965. * Miscellaneous functions, stand alone
  5966. *
  5967. ***********************************************/
  5968. /**
  5969. * Wrapping a string.
  5970. * Implements the TypoScript "wrap" property.
  5971. * Example: $content = "HELLO WORLD" and $wrap = "<strong> | </strong>", result: "<strong>HELLO WORLD</strong>"
  5972. *
  5973. * @param string The content to wrap
  5974. * @param string The wrap value, eg. "<strong> | </strong>"
  5975. * @param string The char used to split the wrapping value, default is "|"
  5976. * @return string Wrapped input string
  5977. * @see noTrimWrap()
  5978. */
  5979. function wrap($content,$wrap,$char='|') {
  5980. if ($wrap) {
  5981. $wrapArr = explode($char, $wrap);
  5982. return trim($wrapArr[0]).$content.trim($wrapArr[1]);
  5983. } else return $content;
  5984. }
  5985. /**
  5986. * Wrapping a string, preserving whitespace in wrap value.
  5987. * Notice that the wrap value uses part 1/2 to wrap (and not 0/1 which wrap() does)
  5988. *
  5989. * @param string The content to wrap, eg. "HELLO WORLD"
  5990. * @param string The wrap value, eg. " | <strong> | </strong>"
  5991. * @return string Wrapped input string, eg. " <strong> HELLO WORD </strong>"
  5992. * @see wrap()
  5993. */
  5994. function noTrimWrap($content,$wrap) {
  5995. if ($wrap) {
  5996. $wrapArr = explode('|', $wrap);
  5997. return $wrapArr[1].$content.$wrapArr[2];
  5998. } else return $content;
  5999. }
  6000. /**
  6001. * 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.
  6002. *
  6003. * @param string The content to add space above/below to.
  6004. * @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)
  6005. * @param array Configuration from TypoScript
  6006. * @return string Wrapped string
  6007. */
  6008. function wrapSpace($content, $wrap, array $conf = NULL) {
  6009. if (trim($wrap)) {
  6010. $wrapArray = explode('|',$wrap);
  6011. $wrapBefore = intval($wrapArray[0]);
  6012. $wrapAfter = intval($wrapArray[1]);
  6013. $useDivTag = (isset($conf['useDiv']) && $conf['useDiv']);
  6014. if ($wrapBefore) {
  6015. if($useDivTag) {
  6016. $content = '<div class="content-spacer spacer-before" style="height:' . $wrapBefore . 'px;"></div>' . $content;
  6017. } else {
  6018. $content = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="1" height="' . $wrapBefore . '"' . $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />' . $content;
  6019. }
  6020. }
  6021. if ($wrapAfter) {
  6022. if($useDivTag) {
  6023. $content.= '<div class="content-spacer spacer-after" style="height:' . $wrapAfter . 'px;"></div>';
  6024. } else {
  6025. $content.= '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="1" height="' . $wrapAfter . '"' . $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />';
  6026. }
  6027. }
  6028. }
  6029. return $content;
  6030. }
  6031. /**
  6032. * Calling a user function/class-method
  6033. * Notice: For classes the instantiated object will have the internal variable, $cObj, set to be a *reference* to $this (the parent/calling object).
  6034. *
  6035. * @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.
  6036. * @param array The TypoScript configuration to pass the function
  6037. * @param string The content string to pass the function
  6038. * @return string The return content from the function call. Should probably be a string.
  6039. * @see USER(), stdWrap(), typoLink(), _parseFunc()
  6040. */
  6041. function callUserFunction($funcName,$conf,$content) {
  6042. $pre = $GLOBALS['TSFE']->TYPO3_CONF_VARS['FE']['userFuncClassPrefix'];
  6043. if ($pre &&
  6044. !t3lib_div::isFirstPartOfStr(trim($funcName),$pre) &&
  6045. !t3lib_div::isFirstPartOfStr(trim($funcName),'tx_')
  6046. ) {
  6047. $GLOBALS['TT']->setTSlogMessage('Function "'.$funcName.'" was not prepended with "'.$pre.'"',3);
  6048. return $content;
  6049. }
  6050. // Split parts
  6051. $parts = explode('->',$funcName);
  6052. if (count($parts)==2) { // Class
  6053. // Check whether class is available and try to reload includeLibs if possible:
  6054. if ($this->isClassAvailable($parts[0], $conf)) {
  6055. $classObj = t3lib_div::makeInstance($parts[0]);
  6056. if (is_object($classObj) && method_exists($classObj, $parts[1])) {
  6057. $classObj->cObj = $this;
  6058. $content = call_user_func_array(array($classObj, $parts[1]), array($content, $conf));
  6059. } else {
  6060. $GLOBALS['TT']->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', 3);
  6061. }
  6062. } else {
  6063. $GLOBALS['TT']->setTSlogMessage('Class "' . $parts[0] . '" did not exist', 3);
  6064. }
  6065. } else { // Function
  6066. if (function_exists($funcName)) {
  6067. $content = call_user_func($funcName, $content, $conf);
  6068. } else {
  6069. $GLOBALS['TT']->setTSlogMessage('Function "'.$funcName.'" did not exist',3);
  6070. }
  6071. }
  6072. return $content;
  6073. }
  6074. /**
  6075. * Parses a set of text lines with "[parameters] = [values]" into an array with parameters as keys containing the value
  6076. * If lines are empty or begins with "/" or "#" then they are ignored.
  6077. *
  6078. * @param string Text which the parameters
  6079. * @return array Array with the parameters as key/value pairs
  6080. */
  6081. function processParams($params) {
  6082. $paramArr=array();
  6083. $lines=t3lib_div::trimExplode(LF,$params,1);
  6084. foreach($lines as $val) {
  6085. $pair = explode('=',$val,2);
  6086. if (!t3lib_div::inList('#,/',substr(trim($pair[0]),0,1))) {
  6087. $paramArr[trim($pair[0])] = trim($pair[1]);
  6088. }
  6089. }
  6090. return $paramArr;
  6091. }
  6092. /**
  6093. * Cleans up a string of keywords. Keywords at splitted by "," (comma) ";" (semi colon) and linebreak
  6094. *
  6095. * @param string String of keywords
  6096. * @return string Cleaned up string, keywords will be separated by a comma only.
  6097. */
  6098. function keywords($content) {
  6099. $listArr = preg_split('/[,;' . LF . ']/', $content);
  6100. foreach ($listArr as $k => $v) {
  6101. $listArr[$k]=trim($v);
  6102. }
  6103. return implode(',',$listArr);
  6104. }
  6105. /**
  6106. * Changing character case of a string, converting typically used western charset characters as well.
  6107. *
  6108. * @param string The string to change case for.
  6109. * @param string The direction; either "upper" or "lower"
  6110. * @return string
  6111. * @see HTMLcaseshift()
  6112. */
  6113. function caseshift($theValue, $case) {
  6114. $case = strtolower($case);
  6115. switch($case) {
  6116. case 'upper':
  6117. $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset,$theValue,'toUpper');
  6118. #$theValue = strtoupper($theValue);
  6119. #$theValue = strtr($theValue, $this->caseConvStrings[0], $this->caseConvStrings[1]);
  6120. break;
  6121. case 'lower':
  6122. $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset,$theValue,'toLower');
  6123. #$theValue = strtolower($theValue);
  6124. #$theValue = strtr($theValue, $this->caseConvStrings[1], $this->caseConvStrings[0]);
  6125. break;
  6126. }
  6127. return $theValue;
  6128. }
  6129. /**
  6130. * Shifts the case of characters outside of HTML tags in the input string
  6131. *
  6132. * @param string The string to change case for.
  6133. * @param string The direction; either "upper" or "lower"
  6134. * @return string
  6135. * @see caseshift()
  6136. */
  6137. function HTMLcaseshift($theValue, $case) {
  6138. $inside = 0;
  6139. $newVal = '';
  6140. $pointer = 0;
  6141. $totalLen = strlen($theValue);
  6142. do {
  6143. if (!$inside) {
  6144. $len = strcspn(substr($theValue,$pointer),'<');
  6145. $newVal.= $this->caseshift(substr($theValue,$pointer,$len),$case);
  6146. $inside = 1;
  6147. } else {
  6148. $len = strcspn(substr($theValue,$pointer),'>')+1;
  6149. $newVal.= substr($theValue,$pointer,$len);
  6150. $inside = 0;
  6151. }
  6152. $pointer+=$len;
  6153. } while($pointer<$totalLen);
  6154. return $newVal;
  6155. }
  6156. /**
  6157. * Formats a number to GB, Mb or Kb or just bytes
  6158. *
  6159. * @param integer Number of bytes to format.
  6160. * @param string Labels for bytes, kilo, mega and giga separated by vertical bar (|) and possibly encapsulated in "". Eg: " | K| M| G" (which is the default value)
  6161. * @return string
  6162. * @see t3lib_div::formatSize(), stdWrap()
  6163. * @deprecated since TYPO3 3.6 - Use t3lib_div::formatSize() instead
  6164. */
  6165. function bytes($sizeInBytes,$labels) {
  6166. t3lib_div::logDeprecatedFunction();
  6167. return t3lib_div::formatSize($sizeInBytes,$labels);
  6168. }
  6169. /**
  6170. * Returns the 'age' of the tstamp $seconds
  6171. *
  6172. * @param integer Seconds to return age for. Example: "70" => "1 min", "3601" => "1 hrs"
  6173. * @param string $labels are the labels of the individual units. Defaults to : ' min| hrs| days| yrs'
  6174. * @return string The formatted string
  6175. */
  6176. function calcAge($seconds,$labels) {
  6177. if (t3lib_div::testInt($labels)) {
  6178. $labels = ' min| hrs| days| yrs';
  6179. } else {
  6180. $labels=str_replace('"','',$labels);
  6181. }
  6182. $labelArr = explode('|',$labels);
  6183. $absSeconds = abs($seconds);
  6184. if ($absSeconds<3600) {
  6185. $seconds = round ($seconds/60).$labelArr[0];
  6186. } elseif ($absSeconds<24*3600) {
  6187. $seconds = round ($seconds/3600).$labelArr[1];
  6188. } elseif ($absSeconds<365*24*3600) {
  6189. $seconds = round ($seconds/(24*3600)).$labelArr[2];
  6190. } else {
  6191. $seconds = round ($seconds/(365*24*3600)).$labelArr[3];
  6192. }
  6193. return $seconds;
  6194. }
  6195. /**
  6196. * Sending a notification email using $GLOBALS['TSFE']->plainMailEncoded()
  6197. *
  6198. * @param string The message content. If blank, no email is sent.
  6199. * @param string Comma list of recipient email addresses
  6200. * @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.
  6201. * @param string "From" email address
  6202. * @param string Optional "From" name
  6203. * @param string Optional "Reply-To" header email address.
  6204. * @return boolean Returns true if sent
  6205. */
  6206. function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName='', $replyTo='') {
  6207. // Sends order emails:
  6208. $headers=array();
  6209. if ($email_from) {$headers[]='From: '.$email_fromName.' <'.$email_from.'>';}
  6210. if ($replyTo) {$headers[]='Reply-To: '.$replyTo;}
  6211. $recipients=implode(',',t3lib_div::trimExplode(',',$recipients,1));
  6212. $emailContent = trim($msg);
  6213. if ($emailContent) {
  6214. $parts = explode(LF, $emailContent, 2); // First line is subject
  6215. $subject=trim($parts[0]);
  6216. $plain_message=trim($parts[1]);
  6217. if ($recipients) $GLOBALS['TSFE']->plainMailEncoded($recipients, $subject, $plain_message, implode(LF,$headers));
  6218. if ($cc) $GLOBALS['TSFE']->plainMailEncoded($cc, $subject, $plain_message, implode(LF,$headers));
  6219. return true;
  6220. }
  6221. }
  6222. /**
  6223. * Checks if $url has a '?' in it and if not, a '?' is inserted between $url and $params, which are anyway concatenated and returned
  6224. *
  6225. * @param string Input URL
  6226. * @param string URL parameters
  6227. * @return string
  6228. */
  6229. function URLqMark($url,$params) {
  6230. if ($params && !strstr($url,'?')) {
  6231. return $url.'?'.$params;
  6232. } else {
  6233. return $url.$params;
  6234. }
  6235. }
  6236. /**
  6237. * Checking syntax of input email address
  6238. *
  6239. * @param string Input string to evaluate
  6240. * @return boolean Returns true if the $email address (input string) is valid; Has a "@", domain name with at least one period and only allowed a-z characters.
  6241. * @see t3lib_div::validEmail()
  6242. * @deprecated since TYPO3 3.6 - Use t3lib_div::validEmail() instead
  6243. */
  6244. function checkEmail($email) {
  6245. t3lib_div::logDeprecatedFunction();
  6246. return t3lib_div::validEmail($email);
  6247. }
  6248. /**
  6249. * Clears TypoScript properties listed in $propList from the input TypoScript array.
  6250. *
  6251. * @param array TypoScript array of values/properties
  6252. * @param string List of properties to clear both value/properties for. Eg. "myprop,another_property"
  6253. * @return array The TypoScript array
  6254. * @see gifBuilderTextBox()
  6255. */
  6256. function clearTSProperties($TSArr,$propList) {
  6257. $list = explode(',',$propList);
  6258. foreach ($list as $prop) {
  6259. $prop = trim($prop);
  6260. unset($TSArr[$prop]);
  6261. unset($TSArr[$prop.'.']);
  6262. }
  6263. return $TSArr;
  6264. }
  6265. /**
  6266. * Resolves a TypoScript reference value to the full set of properties BUT overridden with any local properties set.
  6267. * So the reference is resolved but overlaid with local TypoScript properties of the reference value.
  6268. *
  6269. * @param array The TypoScript array
  6270. * @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.
  6271. * @return array The modified TypoScript array
  6272. * @see user_plaintext::typolist(),user_plaintext::typohead()
  6273. */
  6274. function mergeTSRef($confArr,$prop) {
  6275. if (substr($confArr[$prop],0,1)=='<') {
  6276. $key = trim(substr($confArr[$prop],1));
  6277. $cF = t3lib_div::makeInstance('t3lib_TSparser');
  6278. // $name and $conf is loaded with the referenced values.
  6279. $old_conf=$confArr[$prop.'.'];
  6280. list($name, $conf) = $cF->getVal($key,$GLOBALS['TSFE']->tmpl->setup);
  6281. if (is_array($old_conf) && count($old_conf)) {
  6282. $conf = $this->joinTSarrays($conf,$old_conf);
  6283. }
  6284. $confArr[$prop.'.']=$conf;
  6285. }
  6286. return $confArr;
  6287. }
  6288. /**
  6289. * Merges two TypoScript propery array, overlaing the $old_conf onto the $conf array
  6290. *
  6291. * @param array TypoScript property array, the "base"
  6292. * @param array TypoScript property array, the "overlay"
  6293. * @return array The resulting array
  6294. * @see mergeTSRef(), tx_tstemplatestyler_modfunc1::joinTSarrays()
  6295. */
  6296. function joinTSarrays($conf,$old_conf) {
  6297. if (is_array($old_conf)) {
  6298. foreach ($old_conf as $key => $val) {
  6299. if (is_array($val)) {
  6300. $conf[$key] = $this->joinTSarrays($conf[$key],$val);
  6301. } else {
  6302. $conf[$key] = $val;
  6303. }
  6304. }
  6305. }
  6306. return $conf;
  6307. }
  6308. /**
  6309. * 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
  6310. *
  6311. * @param array TypoScript properties for Gifbuilder - TEXT GIFBUILDER objects are added to this array and returned.
  6312. * @param array TypoScript properties for this function
  6313. * @param string The text string to write onto the GIFBUILDER file
  6314. * @return array The modified $gifbuilderConf array
  6315. * @see media/scripts/postit.inc
  6316. */
  6317. function gifBuilderTextBox($gifbuilderConf, $conf, $text) {
  6318. $chars = intval($conf['chars']) ? intval($conf['chars']) : 20;
  6319. $lineDist = intval($conf['lineDist']) ? intval($conf['lineDist']) : 20;
  6320. $Valign = strtolower(trim($conf['Valign']));
  6321. $tmplObjNumber = intval($conf['tmplObjNumber']);
  6322. $maxLines = intval($conf['maxLines']);
  6323. if ($tmplObjNumber && $gifbuilderConf[$tmplObjNumber]=='TEXT') {
  6324. $textArr = $this->linebreaks($text,$chars,$maxLines);
  6325. $angle = intval($gifbuilderConf[$tmplObjNumber.'.']['angle']);
  6326. foreach ($textArr as $c => $textChunk) {
  6327. $index = $tmplObjNumber+1+($c*2);
  6328. // Workarea
  6329. $gifbuilderConf = $this->clearTSProperties($gifbuilderConf,$index);
  6330. $rad_angle = 2*pi()/360*$angle;
  6331. $x_d = sin($rad_angle)*$lineDist;
  6332. $y_d = cos($rad_angle)*$lineDist;
  6333. $diff_x_d=0;
  6334. $diff_y_d=0;
  6335. if ($Valign=='center') {
  6336. $diff_x_d = $x_d*count($textArr);
  6337. $diff_x_d = $diff_x_d/2;
  6338. $diff_y_d = $y_d*count($textArr);
  6339. $diff_y_d = $diff_y_d/2;
  6340. }
  6341. $x_d = round($x_d*$c - $diff_x_d);
  6342. $y_d = round($y_d*$c - $diff_y_d);
  6343. $gifbuilderConf[$index] = 'WORKAREA';
  6344. $gifbuilderConf[$index.'.']['set'] = $x_d.','.$y_d;
  6345. // Text
  6346. $index++;
  6347. $gifbuilderConf = $this->clearTSProperties($gifbuilderConf,$index);
  6348. $gifbuilderConf[$index] = 'TEXT';
  6349. $gifbuilderConf[$index.'.'] = $this->clearTSProperties($gifbuilderConf[$tmplObjNumber.'.'],'text');
  6350. $gifbuilderConf[$index.'.']['text'] = $textChunk;
  6351. }
  6352. $gifbuilderConf = $this->clearTSProperties($gifbuilderConf,$tmplObjNumber);
  6353. }
  6354. return $gifbuilderConf;
  6355. }
  6356. /**
  6357. * Splits a text string into lines and returns an array with these lines but a max number of lines.
  6358. *
  6359. * @param string The string to break
  6360. * @param integer Max number of characters per line.
  6361. * @param integer Max number of lines in all.
  6362. * @return array Array with lines.
  6363. * @access private
  6364. * @see gifBuilderTextBox()
  6365. */
  6366. function linebreaks($string,$chars,$maxLines=0) {
  6367. $lines = explode(LF,$string);
  6368. $lineArr=Array();
  6369. $c=0;
  6370. foreach ($lines as $paragraph) {
  6371. $words = explode(' ',$paragraph);
  6372. foreach ($words as $word) {
  6373. if (strlen($lineArr[$c].$word)>$chars) {
  6374. $c++;
  6375. }
  6376. if (!$maxLines || $c<$maxLines) {
  6377. $lineArr[$c].= $word.' ';
  6378. }
  6379. }
  6380. $c++;
  6381. }
  6382. return $lineArr;
  6383. }
  6384. /**
  6385. * 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'])
  6386. * 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.
  6387. *
  6388. * @param array Data array which values to load into the form fields from $formName (only field names found in $fieldList)
  6389. * @param string The form name
  6390. * @param string A prefix for the data array
  6391. * @param string The list of fields which are loaded
  6392. * @return string
  6393. * @access private
  6394. * @see user_feAdmin::displayCreateScreen()
  6395. */
  6396. function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList) {
  6397. $JSPart='';
  6398. $updateValues=t3lib_div::trimExplode(',',$fieldList);
  6399. foreach ($updateValues as $fKey) {
  6400. $value = $dataArray[$fKey];
  6401. if (is_array($value)) {
  6402. foreach ($value as $Nvalue) {
  6403. $JSPart.="
  6404. updateForm('".$formName."','".$arrPrefix."[".$fKey."][]',".t3lib_div::quoteJSvalue($Nvalue, true).");";
  6405. }
  6406. } else {
  6407. $JSPart.="
  6408. updateForm('".$formName."','".$arrPrefix."[".$fKey."]',".t3lib_div::quoteJSvalue($value, true).");";
  6409. }
  6410. }
  6411. $JSPart='<script type="text/javascript">
  6412. /*<![CDATA[*/ '.$JSPart.'
  6413. /*]]>*/
  6414. </script>
  6415. ';
  6416. $GLOBALS['TSFE']->additionalHeaderData['JSincludeFormupdate'] =
  6417. '<script type="text/javascript" src="'
  6418. . t3lib_div::createVersionNumberedFilename($GLOBALS['TSFE']->absRefPrefix
  6419. . 't3lib/jsfunc.updateform.js')
  6420. . '"></script>';
  6421. return $JSPart;
  6422. }
  6423. /**
  6424. * Includes resources if the config property 'includeLibs' is set.
  6425. *
  6426. * @param array $config: TypoScript configuration
  6427. * @return boolean Whether a configuration for including libs was found and processed
  6428. */
  6429. protected function includeLibs(array $config) {
  6430. $librariesIncluded = false;
  6431. if (isset($config['includeLibs']) && $config['includeLibs']) {
  6432. $libraries = t3lib_div::trimExplode(',', $config['includeLibs'], true);
  6433. $GLOBALS['TSFE']->includeLibraries($libraries);
  6434. $librariesIncluded = true;
  6435. }
  6436. return $librariesIncluded;
  6437. }
  6438. /**
  6439. * Checks whether a PHP class is available. If the check fails, the method tries to
  6440. * determine the correct includeLibs to make the class available automatically.
  6441. *
  6442. * TypoScript example that can cause this:
  6443. * | plugin.tx_myext_pi1 = USER
  6444. * | plugin.tx_myext_pi1 {
  6445. * | includeLibs = EXT:myext/pi1/class.tx_myext_pi1.php
  6446. * | userFunc = tx_myext_pi1->main
  6447. * | }
  6448. * | 10 = USER
  6449. * | 10.userFunc = tx_myext_pi1->renderHeader
  6450. *
  6451. * @param string $className: The name of the PHP class to be checked
  6452. * @param array $config: TypoScript configuration (naturally of a USER or COA cObject)
  6453. * @return boolean Whether the class is available
  6454. * @link http://bugs.typo3.org/view.php?id=9654
  6455. * @TODO This method was introduced in TYPO3 4.3 and can be removed if the autoload was integrated
  6456. */
  6457. protected function isClassAvailable($className, array $config = NULL) {
  6458. if (class_exists($className)) {
  6459. return true;
  6460. } elseif ($config) {
  6461. $pluginConfiguration =& $GLOBALS['TSFE']->tmpl->setup['plugin.'][$className . '.'];
  6462. if (isset($pluginConfiguration['includeLibs']) && $pluginConfiguration['includeLibs']) {
  6463. $config['includeLibs'] = $pluginConfiguration['includeLibs'];
  6464. return $this->includeLibs($config);
  6465. }
  6466. }
  6467. return false;
  6468. }
  6469. /***********************************************
  6470. *
  6471. * Database functions, making of queries
  6472. *
  6473. ***********************************************/
  6474. /**
  6475. * Returns an UPDATE/DELETE sql query which will "delete" the record.
  6476. * 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.
  6477. *
  6478. * @param string The table name, should be in $TCA
  6479. * @param integer The UID of the record from $table which we are going to delete
  6480. * @param boolean If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!!
  6481. * @return string The query, ready to execute unless $doExec was true in which case the return value is false.
  6482. * @see DBgetUpdate(), DBgetInsert(), user_feAdmin
  6483. */
  6484. function DBgetDelete($table, $uid, $doExec=FALSE) {
  6485. if (intval($uid)) {
  6486. if ($GLOBALS['TCA'][$table]['ctrl']['delete']) {
  6487. if ($doExec) {
  6488. return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), array($GLOBALS['TCA'][$table]['ctrl']['delete'] => 1));
  6489. } else {
  6490. return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid='.intval($uid), array($GLOBALS['TCA'][$table]['ctrl']['delete'] => 1));
  6491. }
  6492. } else {
  6493. if ($doExec) {
  6494. return $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid='.intval($uid));
  6495. } else {
  6496. return $GLOBALS['TYPO3_DB']->DELETEquery($table, 'uid='.intval($uid));
  6497. }
  6498. }
  6499. }
  6500. }
  6501. /**
  6502. * Returns an UPDATE sql query.
  6503. * If a "tstamp" field is configured for the $table tablename in $TCA then that field is automatically updated to the current time.
  6504. * 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.
  6505. * NOTICE: From TYPO3 3.6.0 this function ALWAYS adds slashes to values inserted in the query.
  6506. *
  6507. * @param string The table name, should be in $TCA
  6508. * @param integer The UID of the record from $table which we are going to update
  6509. * @param array The data array where key/value pairs are fieldnames/values for the record to update.
  6510. * @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!!
  6511. * @param boolean If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!!
  6512. * @return string The query, ready to execute unless $doExec was true in which case the return value is false.
  6513. * @see DBgetInsert(), DBgetDelete(), user_feAdmin
  6514. */
  6515. function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec=FALSE) {
  6516. unset($dataArr['uid']); // uid can never be set
  6517. $uid=intval($uid);
  6518. if ($uid) {
  6519. $fieldList = implode(',',t3lib_div::trimExplode(',',$fieldList,1));
  6520. $updateFields=array();
  6521. foreach($dataArr as $f => $v) {
  6522. if (t3lib_div::inList($fieldList,$f)) {
  6523. $updateFields[$f] = $v;
  6524. }
  6525. }
  6526. if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
  6527. $updateFields[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME'];
  6528. }
  6529. if (count($updateFields)) {
  6530. if ($doExec) {
  6531. return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
  6532. } else {
  6533. return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid='.intval($uid), $updateFields);
  6534. }
  6535. }
  6536. }
  6537. }
  6538. /**
  6539. * Returns an INSERT sql query which automatically added "system-fields" according to $TCA
  6540. * 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.
  6541. * The "pid" field is overridden by the input $pid value if >= 0 (zero). "uid" can never be set as a field
  6542. * NOTICE: From TYPO3 3.6.0 this function ALWAYS adds slashes to values inserted in the query.
  6543. *
  6544. * @param string The table name, should be in $TCA
  6545. * @param integer The PID value for the record to insert
  6546. * @param array The data array where key/value pairs are fieldnames/values for the record to insert
  6547. * @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!!
  6548. * @param boolean If set, the query is executed. IT'S HIGHLY RECOMMENDED TO USE THIS FLAG to execute the query directly!!!
  6549. * @return string The query, ready to execute unless $doExec was true in which case the return value is false.
  6550. * @see DBgetUpdate(), DBgetDelete(), user_feAdmin
  6551. */
  6552. function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec=FALSE) {
  6553. $extraList='pid';
  6554. if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
  6555. $field = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
  6556. $dataArr[$field] = $GLOBALS['EXEC_TIME'];
  6557. $extraList .= ',' . $field;
  6558. }
  6559. if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
  6560. $field=$GLOBALS['TCA'][$table]['ctrl']['crdate'];
  6561. $dataArr[$field] = $GLOBALS['EXEC_TIME'];
  6562. $extraList .= ',' . $field;
  6563. }
  6564. if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {$field=$GLOBALS['TCA'][$table]['ctrl']['cruser_id']; $dataArr[$field]=0; $extraList.=','.$field;}
  6565. if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {$field=$GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']; $dataArr[$field]=intval($GLOBALS['TSFE']->fe_user->user['uid']); $extraList.=','.$field;}
  6566. if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {$field=$GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']; list($dataArr[$field])=explode(',',$GLOBALS['TSFE']->fe_user->user['usergroup']); $dataArr[$field]=intval($dataArr[$field]); $extraList.=','.$field;}
  6567. unset($dataArr['uid']); // uid can never be set
  6568. if ($pid>=0) { $dataArr['pid'] = $pid; } // Set pid < 0 and the dataarr-pid will be used!
  6569. $fieldList = implode(',',t3lib_div::trimExplode(',',$fieldList.','.$extraList,1));
  6570. $insertFields = array();
  6571. foreach($dataArr as $f => $v) {
  6572. if (t3lib_div::inList($fieldList,$f)) {
  6573. $insertFields[$f] = $v;
  6574. }
  6575. }
  6576. if ($doExec) {
  6577. return $GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $insertFields);
  6578. } else {
  6579. return $GLOBALS['TYPO3_DB']->INSERTquery($table, $insertFields);
  6580. }
  6581. }
  6582. /**
  6583. * Checks if a frontend user is allowed to edit a certain record
  6584. *
  6585. * @param string The table name, found in $TCA
  6586. * @param array The record data array for the record in question
  6587. * @param array The array of the fe_user which is evaluated, typ. $GLOBALS['TSFE']->fe_user->user
  6588. * @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.
  6589. * @param boolean True, if the fe_user may edit his own fe_user record.
  6590. * @return boolean
  6591. * @see user_feAdmin
  6592. */
  6593. function DBmayFEUserEdit($table,$row, $feUserRow, $allowedGroups='',$feEditSelf=0) {
  6594. $groupList = $allowedGroups ? implode(',',array_intersect(t3lib_div::trimExplode(',',$feUserRow['usergroup'],1),t3lib_div::trimExplode(',',$allowedGroups,1))) : $feUserRow['usergroup'];
  6595. $ok=0;
  6596. // points to the field that allows further editing from frontend if not set. If set the record is locked.
  6597. if (!$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] || !$row[$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']]) {
  6598. // points to the field (integer) that holds the fe_users-id of the creator fe_user
  6599. if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
  6600. $rowFEUser = intval($row[$GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']]);
  6601. if ($rowFEUser && $rowFEUser==$feUserRow['uid']) {
  6602. $ok=1;
  6603. }
  6604. }
  6605. // If $feEditSelf is set, fe_users may always edit them selves...
  6606. if ($feEditSelf && $table=='fe_users' && !strcmp($feUserRow['uid'],$row['uid'])) {
  6607. $ok=1;
  6608. }
  6609. // points to the field (integer) that holds the fe_group-id of the creator fe_user's first group
  6610. if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
  6611. $rowFEUser = intval($row[$GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']]);
  6612. if ($rowFEUser) {
  6613. if (t3lib_div::inList($groupList, $rowFEUser)) {
  6614. $ok=1;
  6615. }
  6616. }
  6617. }
  6618. }
  6619. return $ok;
  6620. }
  6621. /**
  6622. * Returns part of a where clause for selecting records from the input table name which the user may edit.
  6623. * Conceptually close to the function DBmayFEUserEdit(); It does the same thing but not for a single record, rather for a select query selecting all records which the user HAS access to.
  6624. *
  6625. * @param string The table name
  6626. * @param array The array of the fe_user which is evaluated, typ. $GLOBALS['TSFE']->fe_user->user
  6627. * @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.
  6628. * @param boolean True, if the fe_user may edit his own fe_user record.
  6629. * @return string The where clause part. ALWAYS returns a string. If no access at all, then " AND 1=0"
  6630. * @see DBmayFEUserEdit(), user_feAdmin::displayEditScreen()
  6631. */
  6632. function DBmayFEUserEditSelect($table,$feUserRow,$allowedGroups='',$feEditSelf=0) {
  6633. // Returns where-definition that selects user-editable records.
  6634. $groupList = $allowedGroups ? implode(',',array_intersect(t3lib_div::trimExplode(',',$feUserRow['usergroup'],1),t3lib_div::trimExplode(',',$allowedGroups,1))) : $feUserRow['usergroup'];
  6635. $OR_arr=array();
  6636. // points to the field (integer) that holds the fe_users-id of the creator fe_user
  6637. if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
  6638. $OR_arr[]=$GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id'].'='.$feUserRow['uid'];
  6639. }
  6640. // points to the field (integer) that holds the fe_group-id of the creator fe_user's first group
  6641. if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
  6642. $values = t3lib_div::intExplode(',',$groupList);
  6643. foreach ($values as $theGroupUid) {
  6644. if ($theGroupUid) {$OR_arr[]=$GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id'].'='.$theGroupUid;}
  6645. }
  6646. }
  6647. // If $feEditSelf is set, fe_users may always edit them selves...
  6648. if ($feEditSelf && $table=='fe_users') {
  6649. $OR_arr[]='uid='.intval($feUserRow['uid']);
  6650. }
  6651. $whereDef=' AND 1=0';
  6652. if (count($OR_arr)) {
  6653. $whereDef=' AND ('.implode(' OR ',$OR_arr).')';
  6654. if ($GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']) {
  6655. $whereDef.=' AND '.$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'].'=0';
  6656. }
  6657. }
  6658. return $whereDef;
  6659. }
  6660. /**
  6661. * Returns a part of a WHERE clause which will filter out records with start/end times or hidden/fe_groups fields set to values that should de-select them according to the current time, preview settings or user login. Definitely a frontend function.
  6662. * THIS IS A VERY IMPORTANT FUNCTION: Basically you must add the output from this function for EVERY select query you create for selecting records of tables in your own applications - thus they will always be filtered according to the "enablefields" configured in TCA
  6663. * Simply calls t3lib_pageSelect::enableFields() BUT will send the show_hidden flag along! This means this function will work in conjunction with the preview facilities of the frontend engine/Admin Panel.
  6664. *
  6665. * @param string The table for which to get the where clause
  6666. * @param boolean If set, then you want NOT to filter out hidden records. Otherwise hidden record are filtered based on the current preview settings.
  6667. * @return string The part of the where clause on the form " AND [fieldname]=0 AND ...". Eg. " AND hidden=0 AND starttime < 123345567"
  6668. * @see t3lib_pageSelect::enableFields()
  6669. */
  6670. function enableFields($table,$show_hidden=0) {
  6671. return $GLOBALS['TSFE']->sys_page->enableFields($table,$show_hidden?$show_hidden:($table=='pages' ? $GLOBALS['TSFE']->showHiddenPage : $GLOBALS['TSFE']->showHiddenRecords));
  6672. }
  6673. /**
  6674. * Generates a list of Page-uid's from $id. List does not include $id itself
  6675. * (unless the id specified is negative in which case it does!)
  6676. * The only pages WHICH PREVENTS DECENDING in a branch are
  6677. * - deleted pages,
  6678. * - pages in a recycler (doktype = 255) or of the Backend User Section (doktpe = 6) type
  6679. * - pages that has the extendToSubpages set, WHERE start/endtime, hidden
  6680. * and fe_users would hide the records.
  6681. * Apart from that, pages with enable-fields excluding them, will also be
  6682. * removed. HOWEVER $dontCheckEnableFields set will allow
  6683. * enableFields-excluded pages to be included anyway - including
  6684. * extendToSubpages sections!
  6685. * Mount Pages are also descended but notice that these ID numbers are not
  6686. * useful for links unless the correct MPvar is set.
  6687. *
  6688. * @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!
  6689. * @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...)
  6690. * @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'
  6691. * @param boolean See function description
  6692. * @param string Additional fields to select. Syntax: ",[fieldname],[fieldname],..."
  6693. * @param string Additional where clauses. Syntax: " AND [fieldname]=[value] AND ..."
  6694. * @param array Array of IDs from previous recursions. In order to prevent infinite loops with mount pages.
  6695. * @param integer Internal: Zero for the first recursion, incremented for each recursive call.
  6696. * @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.
  6697. * @see tslib_fe::checkEnableFields(), tslib_fe::checkPagerecordForIncludeSection()
  6698. */
  6699. public function getTreeList($id, $depth, $begin = 0, $dontCheckEnableFields = false, $addSelectFields = '', $moreWhereClauses = '', array $prevId_array = array(), $recursionLevel = 0) {
  6700. // Init vars:
  6701. $allFields = 'uid,hidden,starttime,endtime,fe_group,extendToSubpages,doktype,php_tree_stop,mount_pid,mount_pid_ol,t3ver_state'.$addSelectFields;
  6702. $depth = intval($depth);
  6703. $begin = intval($begin);
  6704. $id = intval($id);
  6705. $theList = '';
  6706. $addId = 0;
  6707. $requestHash = '';
  6708. if ($id) {
  6709. // First level, check id (second level, this is done BEFORE the recursive call)
  6710. if (!$recursionLevel) {
  6711. // check tree list cache
  6712. // first, create the hash for this request - not sure yet whether we need all these parameters though
  6713. $parameters = array(
  6714. $id,
  6715. $depth,
  6716. $begin,
  6717. $dontCheckEnableFields,
  6718. $addSelectFields,
  6719. $moreWhereClauses,
  6720. $prevId_array,
  6721. $GLOBALS['TSFE']->gr_list
  6722. );
  6723. $requestHash = md5(serialize($parameters));
  6724. list($cacheEntry) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
  6725. 'treelist',
  6726. 'cache_treelist',
  6727. 'md5hash = \'' . $requestHash . '\' AND ( expires > ' . $GLOBALS['EXEC_TIME'] . ' OR expires = 0 )'
  6728. );
  6729. if (is_array($cacheEntry)) {
  6730. // cache hit
  6731. return $cacheEntry['treelist'];
  6732. }
  6733. // If Id less than zero it means we should add the real id to list:
  6734. if ($id < 0) {
  6735. $addId = $id = abs($id);
  6736. }
  6737. // Check start page:
  6738. if ($GLOBALS['TSFE']->sys_page->getRawRecord('pages', $id, 'uid')) {
  6739. // Find mount point if any:
  6740. $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($id);
  6741. if (is_array($mount_info)) {
  6742. $id = $mount_info['mount_pid'];
  6743. // In Overlay mode, use the mounted page uid as added ID!:
  6744. if ($addId && $mount_info['overlay']) {
  6745. $addId = $id;
  6746. }
  6747. }
  6748. } else {
  6749. return ''; // Return blank if the start page was NOT found at all!
  6750. }
  6751. }
  6752. // Add this ID to the array of IDs
  6753. if ($begin <= 0) {
  6754. $prevId_array[] = $id;
  6755. }
  6756. // Select sublevel:
  6757. if ($depth > 0) {
  6758. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  6759. $allFields,
  6760. 'pages',
  6761. 'pid = '.intval($id).' AND deleted = 0 '.$moreWhereClauses,
  6762. '',
  6763. 'sorting'
  6764. );
  6765. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  6766. $GLOBALS['TSFE']->sys_page->versionOL('pages', $row);
  6767. if ($row['doktype'] == 255 || $row['doktype'] == 6 || $row['t3ver_state'] > 0) {
  6768. // Doing this after the overlay to make sure changes
  6769. // in the overlay are respected.
  6770. // However, we do not process pages below of and
  6771. // including of type recycler and BE user section
  6772. continue;
  6773. }
  6774. // Find mount point if any:
  6775. $next_id = $row['uid'];
  6776. $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($next_id, $row);
  6777. // Overlay mode:
  6778. if (is_array($mount_info) && $mount_info['overlay']) {
  6779. $next_id = $mount_info['mount_pid'];
  6780. $res2 = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  6781. $allFields,
  6782. 'pages',
  6783. 'uid = '.intval($next_id).' AND deleted = 0 '.$moreWhereClauses,
  6784. '' ,
  6785. 'sorting'
  6786. );
  6787. $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res2);
  6788. $GLOBALS['TYPO3_DB']->sql_free_result($res2);
  6789. $GLOBALS['TSFE']->sys_page->versionOL('pages', $row);
  6790. if ($row['doktype'] == 255 || $row['doktype'] == 6 || $row['t3ver_state'] > 0) {
  6791. // Doing this after the overlay to make sure
  6792. // changes in the overlay are respected.
  6793. // see above
  6794. continue;
  6795. }
  6796. }
  6797. // Add record:
  6798. if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkPagerecordForIncludeSection($row)) {
  6799. // Add ID to list:
  6800. if ($begin <= 0) {
  6801. if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkEnableFields($row)) {
  6802. $theList.= $next_id.',';
  6803. }
  6804. }
  6805. // Next level:
  6806. if ($depth > 1 && !$row['php_tree_stop']) {
  6807. // Normal mode:
  6808. if (is_array($mount_info) && !$mount_info['overlay']) {
  6809. $next_id = $mount_info['mount_pid'];
  6810. }
  6811. // Call recursively, if the id is not in prevID_array:
  6812. if (!in_array($next_id, $prevId_array)) {
  6813. $theList.= tslib_cObj::getTreeList($next_id, $depth-1, $begin-1, $dontCheckEnableFields, $addSelectFields, $moreWhereClauses, $prevId_array, $recursionLevel+1);
  6814. }
  6815. }
  6816. }
  6817. }
  6818. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  6819. }
  6820. // If first run, check if the ID should be returned:
  6821. if (!$recursionLevel) {
  6822. if ($addId) {
  6823. if ($begin > 0) {
  6824. $theList.= 0;
  6825. } else {
  6826. $theList.= $addId;
  6827. }
  6828. }
  6829. $GLOBALS['TYPO3_DB']->exec_INSERTquery(
  6830. 'cache_treelist',
  6831. array(
  6832. 'md5hash' => $requestHash,
  6833. 'pid' => $id,
  6834. 'treelist' => $theList,
  6835. 'tstamp' => $GLOBALS['EXEC_TIME'],
  6836. )
  6837. );
  6838. }
  6839. }
  6840. // Return list:
  6841. return $theList;
  6842. }
  6843. /**
  6844. * Returns a part for a WHERE clause (without preceeding operator) which will select records based on the presence of a certain string in a string-list inside the record.
  6845. * Example: If you have a record with a field, "usergroup" and that field might contain a list like "1,2,3" (with no spaces between the values) then you can select all records having eg. "2" in this list by calling this function. This is regardless of whether the number "2" is in the start, end or middle of the list - or the only value at all.
  6846. *
  6847. * @param string The field name to look in
  6848. * @param string The value to look for.
  6849. * @return string
  6850. * @deprecated since TYPO3 3.6 - Use $GLOBALS['TYPO3_DB']->listQuery() directly!
  6851. */
  6852. function whereSelectFromList($field,$value) {
  6853. return $GLOBALS['TYPO3_DB']->listQuery($field,$value,'');
  6854. }
  6855. /**
  6856. * 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"
  6857. *
  6858. * @param string List of fields to select
  6859. * @param string The local table
  6860. * @param string The join-table; The "uid_local" field of this table will be matched with $local_table's "uid" field.
  6861. * @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
  6862. * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
  6863. * @param string Optional GROUP BY field(s), if none, supply blank string.
  6864. * @param string Optional ORDER BY field(s), if none, supply blank string.
  6865. * @param string Optional LIMIT value ([begin,]max), if none, supply blank string.
  6866. * @return pointer SQL result pointer
  6867. * @see mm_query_uidList()
  6868. */
  6869. function exec_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='') {
  6870. return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  6871. $select,
  6872. $local_table.','.$mm_table.($foreign_table?','.$foreign_table:''),
  6873. $local_table.'.uid='.$mm_table.'.uid_local'.($foreign_table?' AND '.$foreign_table.'.uid='.$mm_table.'.uid_foreign':'').
  6874. $whereClause, // whereClauseMightContainGroupOrderBy
  6875. $groupBy,
  6876. $orderBy,
  6877. $limit
  6878. );
  6879. }
  6880. /**
  6881. * 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"
  6882. * 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.
  6883. *
  6884. * @param string List of fields to select
  6885. * @param string List of UID integers, eg. "1,2,3,456"
  6886. * @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
  6887. * @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.
  6888. * @param string Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
  6889. * @param string Optional GROUP BY field(s), if none, supply blank string.
  6890. * @param string Optional ORDER BY field(s), if none, supply blank string.
  6891. * @param string Optional LIMIT value ([begin,]max), if none, supply blank string.
  6892. * @return pointer SQL result pointer
  6893. * @see mm_query()
  6894. */
  6895. function exec_mm_query_uidList($select,$local_table_uidlist,$mm_table,$foreign_table='',$whereClause='',$groupBy='',$orderBy='',$limit='') {
  6896. return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  6897. $select,
  6898. $mm_table.($foreign_table?','.$foreign_table:''),
  6899. $mm_table.'.uid_local IN ('.$local_table_uidlist.')'.($foreign_table?' AND '.$foreign_table.'.uid='.$mm_table.'.uid_foreign':'').
  6900. $whereClause, // whereClauseMightContainGroupOrderBy
  6901. $groupBy,
  6902. $orderBy,
  6903. $limit
  6904. );
  6905. }
  6906. /**
  6907. * Generates a search where clause based on the input search words (AND operation - all search words must be found in record.)
  6908. * 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%")'
  6909. *
  6910. * @param string The search words. These will be separated by space and comma.
  6911. * @param string The fields to search in
  6912. * @param string The table name you search in (recommended for DBAL compliance. Will be prepended field names as well)
  6913. * @return string The WHERE clause.
  6914. */
  6915. function searchWhere($sw,$searchFieldList,$searchTable='') {
  6916. global $TYPO3_DB;
  6917. $prefixTableName = $searchTable ? $searchTable.'.' : '';
  6918. $where = '';
  6919. if ($sw) {
  6920. $searchFields = explode(',',$searchFieldList);
  6921. $kw = preg_split('/[ ,]/', $sw);
  6922. foreach ($kw as $val) {
  6923. $val = trim($val);
  6924. $where_p = array();
  6925. if (strlen($val)>=2) {
  6926. $val = $TYPO3_DB->escapeStrForLike($TYPO3_DB->quoteStr($val,$searchTable),$searchTable);
  6927. foreach ($searchFields as $field) {
  6928. $where_p[] = $prefixTableName.$field.' LIKE \'%'.$val.'%\'';
  6929. }
  6930. }
  6931. if (count($where_p)) {
  6932. $where.=' AND ('.implode(' OR ',$where_p).')';
  6933. }
  6934. }
  6935. }
  6936. return $where;
  6937. }
  6938. /**
  6939. * Executes a SELECT query for records from $table and with conditions based on the configuration in the $conf array
  6940. * This function is preferred over ->getQuery() if you just need to create and then execute a query.
  6941. *
  6942. * @param string The table name
  6943. * @param array The TypoScript configuration properties
  6944. * @return mixed A SQL result pointer
  6945. * @see getQuery()
  6946. */
  6947. function exec_getQuery($table, $conf) {
  6948. $queryParts = $this->getQuery($table, $conf, TRUE);
  6949. return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
  6950. }
  6951. /**
  6952. * Creates and returns a SELECT query for records from $table and with conditions based on the configuration in the $conf array
  6953. * Implements the "select" function in TypoScript
  6954. *
  6955. * @param string See ->exec_getQuery()
  6956. * @param array See ->exec_getQuery()
  6957. * @param boolean If set, the function will return the query not as a string but array with the various parts. RECOMMENDED!
  6958. * @return mixed A SELECT query if $returnQueryArray is false, otherwise the SELECT query in an array as parts.
  6959. * @access private
  6960. * @see CONTENT(), numRows()
  6961. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=318&cHash=a98cb4e7e6
  6962. */
  6963. function getQuery($table, $conf, $returnQueryArray=FALSE) {
  6964. // Handle PDO-style named parameter markers first
  6965. $queryMarkers = $this->getQueryMarkers($table, $conf);
  6966. // replace the markers in the non-stdWrap properties
  6967. foreach ($queryMarkers as $marker => $markerValue) {
  6968. $properties = array('uidInList', 'selectFields', 'where', 'max',
  6969. 'begin', 'groupBy', 'orderBy', 'join', 'leftjoin', 'rightjoin');
  6970. foreach ($properties as $property) {
  6971. if ($conf[$property]) {
  6972. $conf[$property] = str_replace('###' . $marker . '###',
  6973. $markerValue,
  6974. $conf[$property]);
  6975. }
  6976. }
  6977. }
  6978. // Construct WHERE clause:
  6979. $conf['pidInList'] = trim($this->stdWrap($conf['pidInList'],$conf['pidInList.']));
  6980. // Handle recursive function for the pidInList
  6981. if (isset($conf['recursive'])) {
  6982. $conf['recursive'] = intval($conf['recursive']);
  6983. if ($conf['recursive'] > 0) {
  6984. foreach (explode(',', $conf['pidInList']) as $value) {
  6985. if ($value === 'this') {
  6986. $value = $GLOBALS['TSFE']->id;
  6987. }
  6988. $pidList .= $value . ',' . $this->getTreeList($value, $conf['recursive']);
  6989. }
  6990. $conf['pidInList'] = trim($pidList, ',');
  6991. }
  6992. }
  6993. if (!strcmp($conf['pidInList'],'')) {
  6994. $conf['pidInList'] = 'this';
  6995. }
  6996. $queryParts = $this->getWhere($table,$conf,TRUE);
  6997. // Fields:
  6998. $queryParts['SELECT'] = $conf['selectFields'] ? $conf['selectFields'] : '*';
  6999. // Setting LIMIT:
  7000. if ($conf['max'] || $conf['begin']) {
  7001. $error=0;
  7002. // Finding the total number of records, if used:
  7003. if (strstr(strtolower($conf['begin'].$conf['max']),'total')) {
  7004. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, $queryParts['WHERE'], $queryParts['GROUPBY']);
  7005. if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
  7006. $GLOBALS['TT']->setTSlogMessage($error);
  7007. } else {
  7008. $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
  7009. $conf['max'] = str_ireplace('total', $row[0], $conf['max']);
  7010. $conf['begin'] = str_ireplace('total', $row[0], $conf['begin']);
  7011. }
  7012. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  7013. }
  7014. if (!$error) {
  7015. $conf['begin'] = t3lib_div::intInRange(ceil($this->calc($conf['begin'])),0);
  7016. $conf['max'] = t3lib_div::intInRange(ceil($this->calc($conf['max'])),0);
  7017. if ($conf['begin'] && !$conf['max']) {
  7018. $conf['max'] = 100000;
  7019. }
  7020. if ($conf['begin'] && $conf['max']) {
  7021. $queryParts['LIMIT'] = $conf['begin'].','.$conf['max'];
  7022. } elseif (!$conf['begin'] && $conf['max']) {
  7023. $queryParts['LIMIT'] = $conf['max'];
  7024. }
  7025. }
  7026. }
  7027. if (!$error) {
  7028. // Setting up tablejoins:
  7029. $joinPart='';
  7030. if ($conf['join']) {
  7031. $joinPart = 'JOIN ' .trim($conf['join']);
  7032. } elseif ($conf['leftjoin']) {
  7033. $joinPart = 'LEFT OUTER JOIN ' .trim($conf['leftjoin']);
  7034. } elseif ($conf['rightjoin']) {
  7035. $joinPart = 'RIGHT OUTER JOIN ' .trim($conf['rightjoin']);
  7036. }
  7037. // Compile and return query:
  7038. $queryParts['FROM'] = trim($table.' '.$joinPart);
  7039. // replace the markers in the queryParts to handle stdWrap
  7040. // enabled properties
  7041. foreach ($queryMarkers as $marker => $markerValue) {
  7042. foreach ($queryParts as $queryPartKey => &$queryPartValue) {
  7043. $queryPartValue = str_replace('###' . $marker . '###',
  7044. $markerValue,
  7045. $queryPartValue);
  7046. }
  7047. }
  7048. $query = $GLOBALS['TYPO3_DB']->SELECTquery(
  7049. $queryParts['SELECT'],
  7050. $queryParts['FROM'],
  7051. $queryParts['WHERE'],
  7052. $queryParts['GROUPBY'],
  7053. $queryParts['ORDERBY'],
  7054. $queryParts['LIMIT']
  7055. );
  7056. return $returnQueryArray ? $queryParts : $query;
  7057. }
  7058. }
  7059. /**
  7060. * Helper function for getQuery(), creating the WHERE clause of the SELECT query
  7061. *
  7062. * @param string The table name
  7063. * @param array The TypoScript configuration properties
  7064. * @param boolean If set, the function will return the query not as a string but array with the various parts. RECOMMENDED!
  7065. * @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.
  7066. * @access private
  7067. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=318&cHash=a98cb4e7e6
  7068. * @see getQuery()
  7069. */
  7070. function getWhere($table,$conf, $returnQueryArray=FALSE) {
  7071. global $TCA;
  7072. // Init:
  7073. $query = '';
  7074. $pid_uid_flag=0;
  7075. $queryParts = array(
  7076. 'SELECT' => '',
  7077. 'FROM' => '',
  7078. 'WHERE' => '',
  7079. 'GROUPBY' => '',
  7080. 'ORDERBY' => '',
  7081. 'LIMIT' => ''
  7082. );
  7083. if (trim($conf['uidInList'])) {
  7084. $listArr = t3lib_div::intExplode(',',str_replace('this',$GLOBALS['TSFE']->contentPid,$conf['uidInList']));
  7085. if (count($listArr)==1) {
  7086. $query.=' AND '.$table.'.uid='.intval($listArr[0]);
  7087. } else {
  7088. $query.=' AND '.$table.'.uid IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($listArr)).')';
  7089. }
  7090. $pid_uid_flag++;
  7091. }
  7092. // static_* tables are allowed to be fetched from root page
  7093. if (substr($table,0,7)=='static_') {
  7094. $pid_uid_flag++;
  7095. }
  7096. if (trim($conf['pidInList'])) {
  7097. $listArr = t3lib_div::intExplode(',',str_replace('this',$GLOBALS['TSFE']->contentPid,$conf['pidInList']));
  7098. // removes all pages which are not visible for the user!
  7099. $listArr = $this->checkPidArray($listArr);
  7100. if (count($listArr)) {
  7101. $query.=' AND '.$table.'.pid IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($listArr)).')';
  7102. $pid_uid_flag++;
  7103. } else {
  7104. $pid_uid_flag=0; // If not uid and not pid then uid is set to 0 - which results in nothing!!
  7105. }
  7106. }
  7107. if (!$pid_uid_flag) { // If not uid and not pid then uid is set to 0 - which results in nothing!!
  7108. $query.=' AND '.$table.'.uid=0';
  7109. }
  7110. if ($where = trim($conf['where'])) {
  7111. $query.=' AND '.$where;
  7112. }
  7113. if ($conf['languageField']) {
  7114. if ($GLOBALS['TSFE']->sys_language_contentOL && $TCA[$table] && $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField']) {
  7115. // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will OVERLAY the records with localized versions!
  7116. $sys_language_content = '0,-1';
  7117. } else {
  7118. $sys_language_content = intval($GLOBALS['TSFE']->sys_language_content);
  7119. }
  7120. $query.=' AND '.$conf['languageField'].' IN ('.$sys_language_content.')';
  7121. }
  7122. $andWhere = trim($this->stdWrap($conf['andWhere'],$conf['andWhere.']));
  7123. if ($andWhere) {
  7124. $query.=' AND '.$andWhere;
  7125. }
  7126. // enablefields
  7127. if ($table=='pages') {
  7128. $query.=' '.$GLOBALS['TSFE']->sys_page->where_hid_del.
  7129. $GLOBALS['TSFE']->sys_page->where_groupAccess;
  7130. } else {
  7131. $query.=$this->enableFields($table);
  7132. }
  7133. // MAKE WHERE:
  7134. if ($query) {
  7135. $queryParts['WHERE'] = trim(substr($query,4)); // Stripping of " AND"...
  7136. $query = 'WHERE '.$queryParts['WHERE'];
  7137. }
  7138. // GROUP BY
  7139. if (trim($conf['groupBy'])) {
  7140. $queryParts['GROUPBY'] = trim($conf['groupBy']);
  7141. $query.=' GROUP BY '.$queryParts['GROUPBY'];
  7142. }
  7143. // ORDER BY
  7144. if (trim($conf['orderBy'])) {
  7145. $queryParts['ORDERBY'] = trim($conf['orderBy']);
  7146. $query.=' ORDER BY '.$queryParts['ORDERBY'];
  7147. }
  7148. // Return result:
  7149. return $returnQueryArray ? $queryParts : $query;
  7150. }
  7151. /**
  7152. * 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)
  7153. *
  7154. * @param array Array of Page UID numbers for select and for which pages with enablefields and bad doktypes should be removed.
  7155. * @return array Returns the array of remaining page UID numbers
  7156. * @access private
  7157. * @see getWhere(),checkPid()
  7158. */
  7159. function checkPidArray($listArr) {
  7160. $outArr = Array();
  7161. if (is_array($listArr) && count($listArr)) {
  7162. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'uid IN ('.implode(',',$listArr).')'.$this->enableFields('pages').' AND doktype NOT IN ('.$this->checkPid_badDoktypeList.')');
  7163. if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
  7164. $GLOBALS['TT']->setTSlogMessage($error.': '.$query,3);
  7165. } else {
  7166. while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  7167. $outArr[] = $row['uid'];
  7168. }
  7169. }
  7170. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  7171. }
  7172. return $outArr;
  7173. }
  7174. /**
  7175. * Checks if a page UID is available due to enableFields() AND the list of bad doktype numbers ($this->checkPid_badDoktypeList)
  7176. *
  7177. * @param integer Page UID to test
  7178. * @return boolean True if OK
  7179. * @access private
  7180. * @see getWhere(), checkPidArray()
  7181. */
  7182. function checkPid($uid) {
  7183. $uid = intval($uid);
  7184. if (!isset($this->checkPid_cache[$uid])) {
  7185. $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
  7186. 'uid',
  7187. 'pages',
  7188. 'uid=' . intval($uid) .
  7189. $this->enableFields('pages') .
  7190. ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')'
  7191. );
  7192. $this->checkPid_cache[$uid] = (bool)$count;
  7193. }
  7194. return $this->checkPid_cache[$uid];
  7195. }
  7196. /**
  7197. * Builds list of marker values for handling PDO-like parameter markers in select parts.
  7198. * 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.
  7199. *
  7200. * @param string $table Table to select records from
  7201. * @param array $conf Select part of CONTENT definition
  7202. * @return array List of values to replace markers with
  7203. * @access private
  7204. * @see getQuery()
  7205. */
  7206. function getQueryMarkers($table, $conf) {
  7207. // parse markers and prepare their values
  7208. $markerValues = array();
  7209. if (is_array($conf['markers.'])) {
  7210. foreach($conf['markers.'] as $dottedMarker => $dummy) {
  7211. $marker = rtrim($dottedMarker, '.');
  7212. if ($dottedMarker == $marker . '.') {
  7213. // parse definition
  7214. $tempValue = $this->stdWrap(
  7215. $conf['markers.'][$dottedMarker]['value'],
  7216. $conf['markers.'][$dottedMarker]
  7217. );
  7218. // quote/escape if needed
  7219. if (is_numeric($tempValue)) {
  7220. if ((int)$tempValue == $tempValue) {
  7221. // handle integer
  7222. $markerValues[$marker] = intval($tempValue);
  7223. } else {
  7224. // handle float
  7225. $markerValues[$marker] = floatval($tempValue);
  7226. }
  7227. } elseif (is_null($tempValue)) {
  7228. // it represents NULL
  7229. $markerValues[$marker] = 'NULL';
  7230. } elseif ($conf['markers.'][$dottedMarker]['commaSeparatedList'] == 1) {
  7231. // see if it is really a comma separated list of values
  7232. $explodeValues = t3lib_div::trimExplode(',', $tempValue);
  7233. if (count($explodeValues) > 1) {
  7234. // handle each element of list separately
  7235. $tempArray = array();
  7236. foreach ($explodeValues as $listValue) {
  7237. if (is_numeric($listValue)) {
  7238. if ((int)$listValue == $listValue) {
  7239. $tempArray[] = intval($listValue);
  7240. } else {
  7241. $tempArray[] = floatval($listValue);
  7242. }
  7243. } else {
  7244. // if quoted, remove quotes before
  7245. // escaping.
  7246. if (preg_match('/^\'([^\']*)\'$/',
  7247. $listValue,
  7248. $matches)) {
  7249. $listValue = $matches[1];
  7250. } elseif (preg_match('/^\"([^\"]*)\"$/',
  7251. $listValue,
  7252. $matches)) {
  7253. $listValue = $matches[1];
  7254. }
  7255. $tempArray[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($listValue, $table);
  7256. }
  7257. }
  7258. $markerValues[$marker] = implode(',', $tempArray);
  7259. } else {
  7260. // handle remaining values as string
  7261. $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table);
  7262. }
  7263. } else {
  7264. // handle remaining values as string
  7265. $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table);
  7266. }
  7267. }
  7268. }
  7269. }
  7270. return $markerValues;
  7271. }
  7272. /***********************************************
  7273. *
  7274. * Frontend editing functions
  7275. *
  7276. ***********************************************/
  7277. /**
  7278. * 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.
  7279. * With the "edit panel" the user will see buttons with links to editing, moving, hiding, deleting the element
  7280. * This function is used for the cObject EDITPANEL and the stdWrap property ".editPanel"
  7281. *
  7282. * @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.
  7283. * @param array TypoScript configuration properties for the editPanel
  7284. * @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"
  7285. * @param array Alternative data array to use. Default is $this->data
  7286. * @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.
  7287. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=375&cHash=7d8915d508
  7288. */
  7289. function editPanel($content, $conf, $currentRecord='', $dataArr=array()) {
  7290. if($GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit)) {
  7291. if(!$currentRecord) {
  7292. $currentRecord = $this->currentRecord;
  7293. }
  7294. if (!count($dataArr)) {
  7295. $dataArr = $this->data;
  7296. }
  7297. // Delegate rendering of the edit panel to the t3lib_frontendedit class.
  7298. $content = $GLOBALS['BE_USER']->frontendEdit->displayEditPanel($content, $conf, $currentRecord, $dataArr);
  7299. }
  7300. return $content;
  7301. }
  7302. /**
  7303. * 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.
  7304. * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well).
  7305. *
  7306. * @param string The content to which the edit icons should be appended
  7307. * @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
  7308. * @param array TypoScript properties for configuring the edit icons.
  7309. * @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"
  7310. * @param array Alternative data array to use. Default is $this->data
  7311. * @param string Additional URL parameters for the link pointing to alt_doc.php
  7312. * @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.
  7313. */
  7314. function editIcons($content, $params, $conf=array(), $currentRecord='', $dataArr=array(), $addUrlParamStr='') {
  7315. if($GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit)) {
  7316. if(!$currentRecord) {
  7317. $currentRecord = $this->currentRecord;
  7318. }
  7319. if (!count($dataArr)) {
  7320. $dataArr = $this->data;
  7321. }
  7322. // Delegate rendering of the edit panel to the t3lib_frontendedit class.
  7323. $content = $GLOBALS['BE_USER']->frontendEdit->displayEditIcons($content, $params, $conf, $currentRecord, $dataArr, $addURLParamStr);
  7324. }
  7325. return $content;
  7326. }
  7327. /**
  7328. * Returns true if the input table/row would be hidden in the frontend (according nto the current time and simulate user group)
  7329. *
  7330. * @param string The table name
  7331. * @param array The data record
  7332. * @return boolean
  7333. * @access private
  7334. * @see editPanelPreviewBorder()
  7335. */
  7336. function isDisabled($table,$row) {
  7337. global $TCA;
  7338. if (
  7339. ($TCA[$table]['ctrl']['enablecolumns']['disabled'] && $row[$TCA[$table]['ctrl']['enablecolumns']['disabled']]) ||
  7340. ($TCA[$table]['ctrl']['enablecolumns']['fe_group'] && $GLOBALS['TSFE']->simUserGroup && $row[$TCA[$table]['ctrl']['enablecolumns']['fe_group']]==$GLOBALS['TSFE']->simUserGroup) ||
  7341. ($TCA[$table]['ctrl']['enablecolumns']['starttime'] && $row[$TCA[$table]['ctrl']['enablecolumns']['starttime']] > $GLOBALS['EXEC_TIME']) ||
  7342. ($TCA[$table]['ctrl']['enablecolumns']['endtime'] && $row[$TCA[$table]['ctrl']['enablecolumns']['endtime']] && $row[$TCA[$table]['ctrl']['enablecolumns']['endtime']] < $GLOBALS['EXEC_TIME'])
  7343. ) return true;
  7344. }
  7345. }
  7346. /**
  7347. * Rendering of framesets
  7348. *
  7349. * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
  7350. * @package TYPO3
  7351. * @subpackage tslib
  7352. */
  7353. class tslib_frameset {
  7354. /**
  7355. * Generates a frameset based on input configuration in a TypoScript array.
  7356. *
  7357. * @param array The TypoScript properties of the PAGE object property "frameSet.". See link.
  7358. * @return string A <frameset> tag.
  7359. * @see TSpagegen::renderContentWithHeader()
  7360. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=343&cHash=41ca925386
  7361. */
  7362. function make($setup) {
  7363. $content = '';
  7364. if (is_array($setup)) {
  7365. $sKeyArray=t3lib_TStemplate::sortedKeyList($setup);
  7366. foreach ($sKeyArray as $theKey) {
  7367. $theValue=$setup[$theKey];
  7368. if (intval($theKey) && $conf=$setup[$theKey.'.']) {
  7369. switch($theValue) {
  7370. case 'FRAME':
  7371. $typeNum = intval($GLOBALS['TSFE']->tmpl->setup[$conf['obj'].'.']['typeNum']);
  7372. if (!$conf['src'] && !$typeNum) {
  7373. $typeNum = -1;
  7374. }
  7375. $content.='<frame'.$this->frameParams($conf,$typeNum).' />'.LF;
  7376. break;
  7377. case 'FRAMESET':
  7378. $frameset = t3lib_div::makeInstance('tslib_frameset');
  7379. $content.=$frameset->make($conf).LF;
  7380. break;
  7381. }
  7382. }
  7383. }
  7384. return '<frameset'.$this->framesetParams($setup).'>'.LF.$content.'</frameset>';
  7385. }
  7386. }
  7387. /**
  7388. * Creates the attributes for a <frame> tag based on a $conf array and the type number
  7389. *
  7390. * @param array Configuration for the parameter generation for the FRAME set. See link
  7391. * @param integer The typenumber to use for the link.
  7392. * @return string String with attributes for the frame-tag. With a prefixed space character.
  7393. * @access private
  7394. * @link http://typo3.org/documentation/document-library/references/doc_core_tsref/current/view/7/9/
  7395. * @see make(), t3lib_TStemplate::linkData()
  7396. */
  7397. function frameParams($setup, $typeNum) {
  7398. $paramStr = '';
  7399. $name = $setup['obj'];
  7400. if ($setup['src'] || $setup['src.']) {
  7401. $src = $setup['src'];
  7402. if (is_array($setup['src.'])) {
  7403. $src = $GLOBALS['TSFE']->cObj->stdWrap($src, $setup['src.']);
  7404. }
  7405. $paramStr.=' src="'.htmlspecialchars($src).'"';
  7406. } else {
  7407. $LD = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page,'',$GLOBALS['TSFE']->no_cache,'','',($setup['options']?'&'.$setup['options']:'').$GLOBALS['TSFE']->cObj->getClosestMPvalueForPage($GLOBALS['TSFE']->page['uid']), intval($typeNum));
  7408. $finalURL = $LD['totalURL'];
  7409. $paramStr.=' src="'.htmlspecialchars($finalURL).'"';
  7410. }
  7411. if ($setup['name']) {$paramStr.=' name="'.$setup['name'].'"';} else {$paramStr.=' name="'.$name.'"';}
  7412. if ($setup['params']) {$paramStr.=' '.$setup['params'];}
  7413. return $paramStr;
  7414. }
  7415. /**
  7416. * Creates the attributes for a <frameset> tag based on a conf array ($setup)
  7417. *
  7418. * @param array The setup array (TypoScript properties)
  7419. * @return string Attributes with preceeding space.
  7420. * @access private
  7421. * @see make()
  7422. */
  7423. function framesetParams($setup) {
  7424. $paramStr = '';
  7425. if ($setup['cols']) { $paramStr.=' cols="'.$setup['cols'].'"'; }
  7426. if ($setup['rows']) { $paramStr.=' rows="'.$setup['rows'].'"'; }
  7427. if ($setup['params']) { $paramStr.=' '.$setup['params']; }
  7428. return $paramStr;
  7429. }
  7430. }
  7431. /**
  7432. * Rendering of tables for offset
  7433. *
  7434. * @see tslib_cObj::OTABLE(), tslib_cObj::stdWrap()
  7435. * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
  7436. * @package TYPO3
  7437. * @subpackage tslib
  7438. */
  7439. class tslib_tableOffset {
  7440. var $tableParams = 'border="0" cellspacing="0" cellpadding="0"';
  7441. var $default_tableParams = 'border="0" cellspacing="0" cellpadding="0"';
  7442. var $tdParams = ' width="99%" valign="top"';
  7443. /**
  7444. * Wrapping the input content string in a table which will space it out from top/left/right/bottom
  7445. *
  7446. * @param string The HTML content string
  7447. * @param string List of offset parameters; x,y,r,b,w,h
  7448. * @return string The HTML content string being wrapped in a <table> offsetting the content as the $offset parameters defined
  7449. */
  7450. function start($content,$offset) {
  7451. $valPairs = t3lib_div::intExplode(',',$offset.',,,,,');
  7452. if ($valPairs[0] || $valPairs[1] || $valPairs[2] || $valPairs[3] || $valPairs[4] || $valPairs[5]) {
  7453. // If width is defined AND there has been no change to the default table params, then extend them to a tablewidth of 1
  7454. if ($valPairs[4] && $this->default_tableParams==$this->tableParams) {$this->tableParams.=' width="1"';}
  7455. // Init:
  7456. $this->begin = LF.'<table '.$this->tableParams.'>';
  7457. $this->end = '</table>';
  7458. $rows=array();
  7459. $widthImg = '';
  7460. $heightImg = '';
  7461. // If width is required, set so bottom column will display for sure
  7462. if ($valPairs[4]) {
  7463. if (!$valPairs[3]) $valPairs[3]=1;
  7464. $widthImg='<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$valPairs[4].'" height="1" alt="" title="" />';
  7465. }
  7466. // If height is required, set so right column will display for sure
  7467. if ($valPairs[5]) {
  7468. if (!$valPairs[2]) $valPairs[2]=1;
  7469. $valPairs[2]=1; $heightImg='<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$valPairs[5].'" alt="" title="" />';
  7470. }
  7471. // First row:
  7472. if ($valPairs[1]) { // top
  7473. $rows[1].= '<tr>';
  7474. $rows[1].= '<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.($valPairs[0]?$valPairs[0]:1).'" height="'.$valPairs[1].'" alt="" title="" /></td>';
  7475. if ($valPairs[0]) $rows[1].= '<td></td>';
  7476. if ($valPairs[2]) $rows[1].= '<td></td>';
  7477. $rows[1].= '</tr>';
  7478. }
  7479. // Middle row:
  7480. $rows[2].= '<tr>';
  7481. if ($valPairs[0]) {$rows[2].= $valPairs[1] ? '<td></td>' : '<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$valPairs[0].'" height="1" alt="" title="" /></td>';}
  7482. $rows[2].= '<td'.$this->tdParams.'>'.$content.'</td>';
  7483. if ($valPairs[2]) {$rows[2].= $valPairs[3] ? '<td>'.$heightImg.'</td>' : '<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$valPairs[2].'" height="'.($valPairs[5]?$valPairs[5]:1).'" alt="" title="" /></td>';}
  7484. $rows[2].= '</tr>';
  7485. // Bottom row:
  7486. if ($valPairs[3]) { // bottom
  7487. $rows[3].= '<tr>';
  7488. if ($valPairs[0]) $rows[3].= '<td></td>';
  7489. if ($valPairs[2]) $rows[3].= '<td>'.$widthImg.'</td>';
  7490. $rows[3].= '<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.($valPairs[2]?$valPairs[2]:($valPairs[4]?$valPairs[4]:1)).'" height="'.$valPairs[3].'" alt="" title="" /></td>';
  7491. $rows[3].= '</tr>';
  7492. }
  7493. return $this->begin.implode('',$rows).$this->end;
  7494. } else return $content;
  7495. }
  7496. }
  7497. /**
  7498. * Rendering of tables for content positioning
  7499. *
  7500. * @see tslib_cObj::CTABLE()
  7501. * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
  7502. * @package TYPO3
  7503. * @subpackage tslib
  7504. */
  7505. class tslib_controlTable {
  7506. var $offX = 0; // offset, x
  7507. var $offY = 0; // offset, y
  7508. var $tm = ''; // top menu
  7509. var $lm = ''; // left menu
  7510. var $rm = ''; // right menu
  7511. var $bm = ''; // bottom menu
  7512. var $content = ''; // content
  7513. var $tmTDparams = 'valign="top"'; // top menu TDparams
  7514. var $lmTDparams = 'valign="top"'; // left menu TDparams
  7515. var $rmTDparams = 'valign="top"'; // right menu TDparams
  7516. var $bmTDparams = 'valign="top"'; // bottom menu TDparams
  7517. var $contentTDparams = 'valign="top"'; // content TDparams
  7518. var $cMl = 1; // content margin, left
  7519. var $cMr = 1; // content margin, right
  7520. var $cMt = 0; // content margin, top
  7521. var $cMb = 1; // content margin, bottom
  7522. var $contentW = 0; // Places a little gif-spacer in the bottom of the content frame
  7523. var $tableParams = 'border="0" cellspacing="0" cellpadding="0"';
  7524. /**
  7525. * Wrapping internal vars ->tm, ->lm, ->rm, ->bm and ->content in a table where each content part is stored in a cell.
  7526. * The two arguments to this function defines some offsets and margins to use in the arrangement of the content in the table.
  7527. *
  7528. * @param string List of offset parameters; x,y
  7529. * @param string List of margin parameters; left, top, right, bottom
  7530. * @return string The content strings wrapped in a <table> as the parameters defined
  7531. * @see tslib_cObj::CTABLE()
  7532. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=359&cHash=2e0065b4e7
  7533. */
  7534. function start($offset,$cMargins) {
  7535. $offArr = t3lib_div::intExplode(',',$offset);
  7536. $cMargArr = t3lib_div::intExplode(',',$cMargins);
  7537. $cols = 0;
  7538. $rows = 0;
  7539. if ($this->lm) $cols++;
  7540. if ($this->rm) $cols++;
  7541. if ($cMargArr[0]) $cols++;
  7542. if ($cMargArr[2]) $cols++;
  7543. if ($cMargArr[1]||$cMargArr[3]||$this->tm||$this->bm||$this->content||$this->contentW) $cols++;
  7544. if ($cMargArr[1]) $rows++;
  7545. if ($cMargArr[3]) $rows++;
  7546. if ($this->tm) $rows++;
  7547. if ($this->bm) $rows++;
  7548. if ($this->content) $rows++;
  7549. if ($this->contentW) $rows++;
  7550. if (!$rows && $cols) $rows=1; // If there are no rows in the middle but still som columns...
  7551. if ($rows&&$cols) {
  7552. $res = LF.'<table '.$this->tableParams.'>';
  7553. // top offset:
  7554. if ($offArr[1]) {
  7555. $xoff = $offArr[0] ? 1 : 0;
  7556. if ($cols+$xoff > 1) {$colspan =' colspan="'.($cols+$xoff).'"';}
  7557. $res.= '<tr><td'.$colspan.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$offArr[1].'" alt="" title="" /></td></tr>';
  7558. }
  7559. // The rows:
  7560. if ($rows>1) {$rowspan =' rowspan="'.($rows).'"';}
  7561. $res.= '<tr>';
  7562. if ($offArr[0]) { $res.='<td'.$rowspan.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" height="1" width="'.$offArr[0].'" alt="" title="" /></td>'; }
  7563. if ($this->lm) { $res.='<td'.$rowspan.' '.$this->lmTDparams.'>'.$this->lm.'</td>'; }
  7564. if ($cMargArr[0]) { $res.='<td'.$rowspan.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" height="1" width="'.$cMargArr[0].'" alt="" title="" /></td>'; }
  7565. // content...
  7566. $middle=Array();
  7567. if ($this->tm) { $middle[]='<td '.$this->tmTDparams.'>'.$this->tm.'</td>';}
  7568. if ($cMargArr[1]) { $middle[]='<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$cMargArr[1].'" alt="" title="" /></td>';}
  7569. if ($this->content) { $middle[]='<td '.$this->contentTDparams.'>'.$this->content.'</td>';}
  7570. if ($cMargArr[3]) { $middle[]='<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$cMargArr[3].'" alt="" title="" /></td>';}
  7571. if ($this->bm) { $middle[]='<td '.$this->bmTDparams.'>'.$this->bm.'</td>';}
  7572. if ($this->contentW) { $middle[]='<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" height="1" width="'.$this->contentW.'" alt="" title="" /></td>';}
  7573. if (isset($middle[0])) {$res.=$middle[0];}
  7574. // Left of content
  7575. if ($cMargArr[2]) { $res.='<td'.$rowspan.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" height="1" width="'.$cMargArr[2].'" alt="" title="" /></td>'; }
  7576. if ($this->rm) { $res.='<td'.$rowspan.' '.$this->rmTDparams.'>'.$this->rm.'</td>'; }
  7577. $res.= '</tr>';
  7578. // More than the two rows
  7579. $mCount = count($middle);
  7580. for($a=1;$a<$mCount;$a++) {
  7581. $res.='<tr>'.$middle[$a].'</tr>';
  7582. }
  7583. $res.='</table>';
  7584. return $res;
  7585. }
  7586. }
  7587. }
  7588. if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php']) {
  7589. include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_content.php']);
  7590. }
  7591. ?>