PageRenderTime 40ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/ext/tt_news/pi/class.tx_ttnews.php

https://github.com/elhakim22003/TypoFlash
PHP | 3397 lines | 2322 code | 408 blank | 667 comment | 603 complexity | 66f5651fea5a2e86956d79600f52c27d MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 1999-2004 Kasper Skårhøj (kasper@typo3.com)
  6. * (c) 2004-2007 Rupert Germann (rupi@gmx.li)
  7. * All rights reserved
  8. *
  9. * This script is part of the TYPO3 project. The TYPO3 project is
  10. * free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * The GNU General Public License can be found at
  16. * http://www.gnu.org/copyleft/gpl.html.
  17. * A copy is found in the textfile GPL.txt and important notices to the license
  18. * from the author is found in LICENSE.txt distributed with these scripts.
  19. *
  20. *
  21. * This script is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * This copyright notice MUST APPEAR in all copies of the script!
  27. ***************************************************************/
  28. /**
  29. * class.tx_ttnews.php
  30. *
  31. * versatile news system for TYPO3.
  32. * $Id: class.tx_ttnews.php 8605 2008-03-15 20:03:19Z rupertgermann $
  33. *
  34. * TypoScript setup:
  35. * @See static/ts_new/setup.txt
  36. * @See tt_news Manual: http://typo3.org/documentation/document-library/extension-manuals/tt_news/current/
  37. * @See TSref: http://typo3.org/documentation/document-library/references/doc_core_tsref/current/
  38. *
  39. * @author Rupert Germann <rupi@gmx.li>
  40. * @co-author Ingo Renner <typo3@ingo-renner.com>
  41. */
  42. /**
  43. * [CLASS/FUNCTION INDEX of SCRIPT]
  44. *
  45. *
  46. *
  47. * 112: class tx_ttnews extends tslib_pibase
  48. * 143: function main_news($content, $conf)
  49. * 219: function init($conf)
  50. * 373: function newsArchiveMenu()
  51. * 523: function displaySingle()
  52. * 606: function displayVersionPreview ()
  53. * 659: function displayList($excludeUids = 0)
  54. * 1003: function getListContent($itemparts, $selectConf, $prefix_display)
  55. * 1172: function getSelectConf($where, $noPeriod = 0)
  56. * 1419: function generatePageArray()
  57. * 1440: function getItemMarkerArray ($row, $textRenderObj = 'displaySingle')
  58. * 1723: function insertPagebreaks($text,$firstPageWordCrop)
  59. * 1773: function makeMultiPageSView($bodytext,$lConf)
  60. * 1803: function makePageBrowser($showResultCount=1,$tableParams='',$pointerName='pointer')
  61. * 1885: function getCategories($uid, $getAll=false)
  62. * 1958: function getCategoryPath($categoryArray)
  63. * 2015: function getSubCategories($catlist, $cc = 0)
  64. * 2044: function displayCatMenu()
  65. * 2157: function getCatMenuContent($array_in,$lConf, $l=0)
  66. * 2209: function getSubCategoriesForMenu ($catlist, $fields, $addWhere, $cc = 0)
  67. * 2240: function getCatMarkerArray($markerArray, $row, $lConf)
  68. * 2380: function getImageMarkers($markerArray, $row, $lConf, $textRenderObj)
  69. * 2448: function getRelated($uid)
  70. * 2608: function userProcess($mConfKey, $passVar)
  71. * 2623: function spMarker($subpartMarker)
  72. * 2641: function searchWhere($sw)
  73. * 2652: function formatStr($str)
  74. * 2667: function getLayouts($templateCode, $alternatingLayouts, $marker)
  75. * 2685: function initLanguages ()
  76. * 2705: function initCategoryVars()
  77. * 2775: function checkRecords($recordlist)
  78. * 2807: function initTemplate()
  79. * 2832: function initPidList ()
  80. * 2857: function getXmlHeader()
  81. * 2958: function getW3cDate($datetime)
  82. * 2983: function main_xmlnewsfeed($content, $conf)
  83. * 2998: function getStoriesResult()
  84. * 3020: function cleanXML($str)
  85. * 3034: function convertDates()
  86. * 3073: function getHrDateSingle($tstamp)
  87. * 3086: function displayFEHelp()
  88. * 3107: function validateFields($fieldlist)
  89. * 3128: function getNewsSubpart($myTemplate, $myKey, $row = Array())
  90. *
  91. * SECTION: DB Functions
  92. * 3149: function exec_getQuery($table, $conf)
  93. * 3167: function getQuery($table, $conf, $returnQueryArray=FALSE)
  94. * 3249: function getWhere($table,$conf, $returnQueryArray=FALSE)
  95. *
  96. * TOTAL FUNCTIONS: 45
  97. * (This index is automatically created/updated by the extension "extdeveval")
  98. *
  99. */
  100. require_once(PATH_t3lib . 'class.t3lib_xml.php');
  101. require_once(PATH_t3lib . 'class.t3lib_htmlmail.php');
  102. require_once(PATH_tslib . 'class.tslib_pibase.php');
  103. require_once(t3lib_extMgm::extPath('tt_news') . 'class.tx_ttnews_catmenu.php');
  104. /**
  105. * Plugin 'news' for the 'tt_news' extension.
  106. *
  107. * @author Rupert Germann <rupi@gmx.li>
  108. * @package TYPO3
  109. * @subpackage tt_news
  110. */
  111. class tx_ttnews extends tslib_pibase {
  112. // Default plugin variables:
  113. var $prefixId = 'tx_ttnews'; // Same as class name
  114. var $scriptRelPath = 'pi/class.tx_ttnews.php'; // Path to this script relative to the extension dir.
  115. var $extKey = 'tt_news'; // The extension key.
  116. var $tt_news_uid; // the uid of the current news record in SINGLE view
  117. var $config; // the processed TypoScript configuration array
  118. var $langArr; // the languages found in the tt_news sysfolder
  119. var $sys_language_mode;
  120. var $alternatingLayouts;
  121. var $allowCaching;
  122. var $catExclusive;
  123. var $arcExclusive;
  124. var $searchFieldList = 'short,bodytext,author,keywords,links,imagecaption,title';
  125. var $theCode = '';
  126. var $rdfToc = '';
  127. var $versioningEnabled = false; // is the extension 'version' loaded
  128. var $vPrev = false; // do we display a versioning preview
  129. var $categories = array(); // Is initialized with the categories of the news system
  130. var $pageArray = array(); // Is initialized with an array of the pages in the pid-list
  131. /**
  132. * Main news function: calls the init_news() function and decides by the given CODEs which of the
  133. * functions to display news should by called.
  134. *
  135. * @param string $content : function output is added to this
  136. * @param array $conf : configuration array
  137. * @return string $content: complete content generated by the tt_news plugin
  138. */
  139. function main_news($content, $conf) {
  140. $this->local_cObj = t3lib_div::makeInstance('tslib_cObj'); // Local cObj.
  141. $this->init($conf);
  142. if ($this->conf['displayCurrentRecord']) {
  143. $this->config['code'] = $this->conf['defaultCode']?trim($this->conf['defaultCode']):'SINGLE';
  144. $this->tt_news_uid = $this->cObj->data['uid'];
  145. }
  146. // get codes and decide which function is used to process the content
  147. $codes = t3lib_div::trimExplode(',', $this->config['code']?$this->config['code']:$this->conf['defaultCode'], 1);
  148. if (!count($codes)) { // no code at all
  149. $codes = array();
  150. $noCode = true;
  151. }
  152. while (list(, $theCode) = each($codes)) {
  153. $theCode = (string)strtoupper(trim($theCode));
  154. $this->theCode = $theCode;
  155. switch ($theCode) {
  156. case 'SINGLE':
  157. $content .= $this->displaySingle();
  158. break;
  159. case 'VERSION_PREVIEW':
  160. $content .= $this->displayVersionPreview();
  161. break;
  162. case 'LATEST':
  163. case 'LIST':
  164. case 'SEARCH':
  165. case 'XML':
  166. $content .= $this->displayList();
  167. break;
  168. case 'AMENU':
  169. $content .= $this->newsArchiveMenu();
  170. break;
  171. case 'CATMENU':
  172. $content .= $this->displayCatMenu();
  173. break;
  174. default:
  175. // Adds hook for processing of extra codes
  176. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraCodesHook'])) {
  177. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraCodesHook'] as $_classRef) {
  178. $_procObj = & t3lib_div::getUserObj($_classRef);
  179. $content .= $_procObj->extraCodesProcessor($this);
  180. }
  181. } else {
  182. $langKey = strtoupper($GLOBALS['TSFE']->config['config']['language']);
  183. $helpTemplate = $this->cObj->fileResource('EXT:tt_news/pi/news_help.tmpl');
  184. // Get language version of the help-template
  185. $helpTemplate_lang = '';
  186. if ($langKey) {
  187. $helpTemplate_lang = $this->getNewsSubpart($helpTemplate, "###TEMPLATE_" . $langKey . '###');
  188. }
  189. $helpTemplate = $helpTemplate_lang ? $helpTemplate_lang :
  190. $this->getNewsSubpart($helpTemplate, '###TEMPLATE_DEFAULT###');
  191. // Markers and substitution:
  192. $markerArray['###CODE###'] = $this->theCode;
  193. $markerArray['###EXTPATH###'] = $GLOBALS['TYPO3_LOADED_EXT']['tt_news']['siteRelPath'];
  194. $content .= $this->displayFEHelp();
  195. }
  196. break;
  197. }
  198. }
  199. if($noCode) {
  200. $content .= $this->displayFEHelp();
  201. }
  202. return $content;
  203. }
  204. /**
  205. * Init Function: here all the needed configuration values are stored in class variables..
  206. *
  207. * @param array $conf : configuration array from TS
  208. * @return void
  209. */
  210. function init($conf) {
  211. $this->conf = $conf; //store configuration
  212. $this->pi_loadLL(); // Loading language-labels
  213. $this->pi_setPiVarDefaults(); // Set default piVars from TS
  214. $this->pi_initPIflexForm(); // Init FlexForm configuration for plugin
  215. $this->enableFields = $this->cObj->enableFields('tt_news');
  216. $this->tt_news_uid = intval($this->piVars['tt_news']); // Get the submitted uid of a news (if any)
  217. if (!isset($this->conf['compatVersion']) || !preg_match('/^\d+\.\d+\.\d+$/', $this->conf['compatVersion'])) {
  218. $this->conf['compatVersion'] = $this->getCurrentVersion();
  219. }
  220. if (t3lib_extMgm::isLoaded('version')) {
  221. $this->versioningEnabled = true;
  222. }
  223. // load available syslanguages
  224. $this->initLanguages();
  225. // sys_language_mode defines what to do if the requested translation is not found
  226. $this->sys_language_mode = $this->conf['sys_language_mode']?$this->conf['sys_language_mode'] : $GLOBALS['TSFE']->sys_language_mode;
  227. // "CODE" decides what is rendered: codes can be set by TS or FF with priority on FF
  228. $code = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'what_to_display', 'sDEF');
  229. $this->config['code'] = $code ? $code : $this->cObj->stdWrap($this->conf['code'], $this->conf['code.']);
  230. // initialize category vars
  231. $this->initCategoryVars();
  232. // get fieldnames from the tt_news db-table
  233. $this->fieldNames = array_keys($GLOBALS['TYPO3_DB']->admin_get_fields('tt_news'));
  234. if ($this->conf['searchFieldList']) {
  235. $searchFieldList = $this->validateFields($this->conf['searchFieldList']);
  236. if ($searchFieldList) {
  237. $this->searchFieldList = $searchFieldList;
  238. }
  239. }
  240. // Archive:
  241. $this->config['archiveMode'] = trim($this->conf['archiveMode']) ; // month, quarter or year listing in AMENU
  242. $this->config['archiveMode'] = $this->config['archiveMode']?$this->config['archiveMode']:'month';
  243. // arcExclusive : -1=only non-archived; 0=don't care; 1=only archived
  244. $arcExclusive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'archive', 'sDEF');
  245. $this->arcExclusive = $arcExclusive?$arcExclusive:$this->conf['archive'];
  246. $this->config['datetimeDaysToArchive'] = intval($this->conf['datetimeDaysToArchive']);
  247. $this->config['datetimeHoursToArchive'] = intval($this->conf['datetimeHoursToArchive']);
  248. $this->config['datetimeMinutesToArchive'] = intval($this->conf['datetimeMinutesToArchive']);
  249. if ($this->conf['useHRDates']) {
  250. $this->convertDates();
  251. }
  252. // list of pages where news records will be taken from
  253. if (!$this->conf['dontUsePidList']) {
  254. $this->initPidList();
  255. }
  256. // itemLinkTarget is only used for categoryLinkMode 3 (catselector) in framesets
  257. $this->config['itemLinkTarget'] = trim($this->conf['itemLinkTarget']);
  258. // id of the page where the search results should be displayed
  259. $this->config['searchPid'] = intval($this->conf['searchPid']);
  260. // pages in Single view will be divided by this token
  261. $this->config['pageBreakToken'] = trim($this->conf['pageBreakToken'])?trim($this->conf['pageBreakToken']):'<---newpage--->';
  262. $this->config['singleViewPointerName'] = trim($this->conf['singleViewPointerName'])?trim($this->conf['singleViewPointerName']):'sViewPointer';
  263. $maxWordsInSingleView = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'maxWordsInSingleView', 's_misc'));
  264. $maxWordsInSingleView = $maxWordsInSingleView?$maxWordsInSingleView:intval($this->conf['maxWordsInSingleView']);
  265. $this->config['maxWordsInSingleView'] = $maxWordsInSingleView?$maxWordsInSingleView:0;
  266. $this->config['useMultiPageSingleView'] = $maxWordsInSingleView>1?1:$this->conf['useMultiPageSingleView'];
  267. // pid of the page with the single view. the old var PIDitemDisplay is still processed if no other value is found
  268. $singlePid = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'PIDitemDisplay', 's_misc');
  269. $singlePid = $singlePid?$singlePid:intval($this->cObj->stdWrap($this->conf['singlePid'],$this->conf['singlePid.']));
  270. $this->config['singlePid'] = $singlePid ? $singlePid:intval($this->conf['PIDitemDisplay']);
  271. // pid to return to when leaving single view
  272. $backPid = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'backPid', 's_misc'));
  273. $backPid = $backPid?$backPid:intval($this->conf['backPid']);
  274. $backPid = $backPid?$backPid:intval($this->piVars['backPid']);
  275. $backPid = $backPid?$backPid:$GLOBALS['TSFE']->id ;
  276. $this->config['backPid'] = $backPid;
  277. // max items per page
  278. $FFlimit = t3lib_div::intInRange($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listLimit', 's_misc'), 0, 1000);
  279. $limit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['limit'],$this->conf['limit.']), 0, 1000);
  280. $limit = $limit?$limit: 50;
  281. $this->config['limit'] = $FFlimit?$FFlimit: $limit;
  282. $latestLimit = t3lib_div::intInRange($this->cObj->stdWrap($this->conf['latestLimit'],$this->conf['latestLimit.']), 0, 1000);
  283. $latestLimit = $latestLimit?$latestLimit:10;
  284. $this->config['latestLimit'] = $FFlimit?$FFlimit:$latestLimit;
  285. // orderBy and groupBy statements for the list Query
  286. $orderBy = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listOrderBy', 'sDEF');
  287. $orderByTS = trim($this->conf['listOrderBy']);
  288. $orderBy = $orderBy?$orderBy:$orderByTS;
  289. $this->config['orderBy'] = $orderBy;
  290. if ($orderBy) {
  291. $ascDesc = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'ascDesc', 'sDEF');
  292. $this->config['ascDesc'] = $ascDesc;
  293. if ($this->config['ascDesc']) {
  294. // remove ASC/DESC from 'orderBy' if it is already set from TS
  295. $this->config['orderBy'] = preg_replace('/( DESC| ASC)\b/i','',$this->config['orderBy']);
  296. }
  297. }
  298. $this->config['groupBy'] = trim($this->conf['listGroupBy']);
  299. // if this is set, the first image is handled as preview image, which is only shown in list view
  300. $fImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'firstImageIsPreview', 's_misc');
  301. $this->config['firstImageIsPreview'] = $fImgPreview?$fImgPreview : $this->conf['firstImageIsPreview'];
  302. $forcefImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'forceFirstImageIsPreview', 's_misc');
  303. $this->config['forceFirstImageIsPreview'] = $forcefImgPreview?$fImgPreview : $this->conf['forceFirstImageIsPreview'];
  304. // List start id
  305. $listStartId = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listStartId', 's_misc'));
  306. $this->config['listStartId'] = $listStartId?$listStartId:intval($this->conf['listStartId']);
  307. // supress pagebrowser
  308. $noPageBrowser = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'noPageBrowser', 's_misc');
  309. $this->config['noPageBrowser'] = $noPageBrowser?$noPageBrowser: $this->conf['noPageBrowser'];
  310. // image sizes given from FlexForms
  311. $this->config['FFimgH'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxHeight', 's_template'));
  312. $this->config['FFimgW'] = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxWidth', 's_template'));
  313. // Get number of alternative Layouts (loop layout in LATEST and LIST view) default is 2:
  314. $altLayouts = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'alternatingLayouts', 's_template'));
  315. $altLayouts = $altLayouts?$altLayouts:intval($this->conf['alternatingLayouts']);
  316. $this->alternatingLayouts = $altLayouts?$altLayouts:2;
  317. // Get cropping lenght
  318. $this->config['croppingLenght'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'croppingLenght', 's_template'));
  319. $this->initTemplate();
  320. // Configure caching
  321. $this->allowCaching = $this->conf['allowCaching']?1:0;
  322. if (!$this->allowCaching) {
  323. $GLOBALS['TSFE']->set_no_cache();
  324. }
  325. // get siteUrl for links in rss feeds. the 'dontInsert' option seems to be needed in some configurations depending on the baseUrl setting
  326. if (!$this->conf['displayXML.']['dontInsertSiteUrl']) {
  327. $this->config['siteUrl'] = t3lib_div::getIndpEnv('TYPO3_SITE_URL');
  328. }
  329. }
  330. /**
  331. * generates the News archive menu
  332. *
  333. * @return string html code of the archive menu
  334. */
  335. function newsArchiveMenu() {
  336. $this->arcExclusive = 1;
  337. $selectConf = $this->getSelectConf('', 1);
  338. // Finding maximum and minimum values:
  339. $selectConf['selectFields'] = 'max(tt_news.datetime) as maxval, min(tt_news.datetime) as minval';
  340. $res = $this->exec_getQuery('tt_news', $selectConf);
  341. $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
  342. if ($row['minval'] || $row['maxval']) {
  343. // if ($row['minval']) {
  344. $dateArr = array();
  345. $arcMode = $this->config['archiveMode'];
  346. $c = 0;
  347. do {
  348. switch ($arcMode) {
  349. case 'month':
  350. $theDate = mktime (0, 0, 0, date('m', $row['minval']) + $c, 1, date('Y', $row['minval']));
  351. break;
  352. case 'quarter':
  353. $theDate = mktime (0, 0, 0, floor(date('m', $row['minval']) / 3) + 1 + (3 * $c), 1, date('Y', $row['minval']));
  354. break;
  355. case 'year':
  356. $theDate = mktime (0, 0, 0, 1, 1, date('Y', $row['minval']) + $c);
  357. break;
  358. }
  359. $dateArr[] = $theDate;
  360. $c++;
  361. if ($c > 1000) break;
  362. }
  363. while ($theDate < $GLOBALS['SIM_EXEC_TIME']);
  364. reset($dateArr);
  365. $periodAccum = array();
  366. $selectConf2['where'] = $selectConf['where'];
  367. while (list($k, $v) = each($dateArr)) {
  368. if (!isset($dateArr[$k + 1])) {
  369. break;
  370. }
  371. $periodInfo = array();
  372. $periodInfo['start'] = $dateArr[$k];
  373. $periodInfo['stop'] = $dateArr[$k + 1]-1;
  374. $periodInfo['HRstart'] = date('d-m-Y', $periodInfo['start']);
  375. $periodInfo['HRstop'] = date('d-m-Y', $periodInfo['stop']);
  376. $periodInfo['quarter'] = floor(date('m', $dateArr[$k]) / 3) + 1;
  377. // execute a query to count the archive periods
  378. $selectConf['selectFields'] = 'count(distinct(tt_news.uid))';
  379. $selectConf['where'] = $selectConf2['where'] . ' AND tt_news.datetime>=' . $periodInfo['start'] . ' AND tt_news.datetime<' . $periodInfo['stop'];
  380. $res = $this->exec_getQuery('tt_news', $selectConf);
  381. $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
  382. $periodInfo['count'] = $row[0];
  383. if (!$this->conf['archiveMenuNoEmpty'] || $periodInfo['count']) {
  384. $periodAccum[] = $periodInfo;
  385. }
  386. }
  387. // get template subpart
  388. $t['total'] = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE###'));
  389. $t['item'] = $this->getLayouts($t['total'], $this->alternatingLayouts, 'MENUITEM');
  390. $cc = 0;
  391. $veryLocal_cObj = t3lib_div::makeInstance('tslib_cObj');
  392. // reverse amenu order if 'reverseAMenu' is given
  393. if ($this->conf['reverseAMenu']) {
  394. arsort($periodAccum);
  395. }
  396. $archiveLink = $this->conf['archiveTypoLink.']['parameter'];
  397. $this->conf['parent.']['addParams'] = $this->conf['archiveTypoLink.']['addParams'];
  398. reset($periodAccum);
  399. $itemsOutArr = array();
  400. while (list(, $pArr) = each($periodAccum)) {
  401. // Print Item Title
  402. $wrappedSubpartArray = array();
  403. if (!$this->conf['disableCategoriesInAmenuLinks']) {
  404. if ($this->config['catSelection'] && $this->config['amenuWithCatSelector']) {
  405. // use the catSelection from GPvars only if 'amenuWithCatSelector' is given.
  406. $amenuLinkCat = $this->config['catSelection'];
  407. } else {
  408. $amenuLinkCat = $this->catExclusive;
  409. }
  410. }
  411. if ($this->conf['useHRDates']) {
  412. $year = date('Y',$pArr['start']);
  413. $month = date('m',$pArr['start']);
  414. if ($arcMode == 'year') {
  415. $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id));
  416. } else {
  417. $archLinkArr = $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'year' => $year, 'month' => $month), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id));
  418. }
  419. $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $archLinkArr);
  420. } else {
  421. $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array('cat' => ($amenuLinkCat?$amenuLinkCat:null), 'pS' => $pArr['start'], 'pL' => ($pArr['stop'] - $pArr['start']), 'arc' => 1), $this->allowCaching, 1, ($archiveLink?$archiveLink:$GLOBALS['TSFE']->id)));
  422. }
  423. $markerArray = array();
  424. $veryLocal_cObj->start($pArr, '');
  425. $markerArray['###ARCHIVE_TITLE###'] = $veryLocal_cObj->cObjGetSingle($this->conf['archiveTitleCObject'], $this->conf['archiveTitleCObject.'], 'archiveTitle');
  426. $markerArray['###ARCHIVE_COUNT###'] = $pArr['count'];
  427. $markerArray['###ARCHIVE_ITEMS###'] = $this->pi_getLL('archiveItems');
  428. // fill the generated data to an array to pass it to a userfuction as a single variable
  429. $itemsOutArr[] = array('html' => $this->cObj->substituteMarkerArrayCached($t['item'][($cc % count($t['item']))], $markerArray, array(), $wrappedSubpartArray), 'data' => $pArr);
  430. $cc++;
  431. }
  432. // Pass to user defined function
  433. if ($this->conf['newsAmenuUserFunc']) {
  434. $itemsOutArr = $this->userProcess('newsAmenuUserFunc', $itemsOutArr);
  435. }
  436. foreach ($itemsOutArr as $itemHtml) {
  437. $tmpItemsArr[] = $itemHtml['html'];
  438. }
  439. if (is_array($tmpItemsArr)) {
  440. $itemsOut = implode('', $tmpItemsArr);
  441. }
  442. // Reset:
  443. $subpartArray = array();
  444. $wrappedSubpartArray = array();
  445. $markerArray = array();
  446. $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']);
  447. // Set content
  448. $subpartArray['###CONTENT###'] = $itemsOut;
  449. $content = $this->cObj->substituteMarkerArrayCached($t['total'], $markerArray, $subpartArray, $wrappedSubpartArray);
  450. } else {
  451. // if nothing is found in the archive display the TEMPLATE_ARCHIVE_NOITEMS message
  452. $markerArray['###ARCHIVE_HEADER###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveHeader'), $this->conf['archiveHeader_stdWrap.']);
  453. $markerArray['###ARCHIVE_EMPTY_MSG###'] = $this->local_cObj->stdWrap($this->pi_getLL('archiveEmptyMsg'), $this->conf['archiveEmptyMsg_stdWrap.']);
  454. $noItemsMsg = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_ARCHIVE_NOITEMS###'));
  455. $content = $this->cObj->substituteMarkerArrayCached($noItemsMsg, $markerArray);
  456. }
  457. return $content;
  458. }
  459. /**
  460. * Displays the "single view" of a news article. Is also used when displaying single news records with the "insert records" content element.
  461. *
  462. * @return string html-code for the "single view"
  463. */
  464. function displaySingle() {
  465. $singleWhere = 'tt_news.uid=' . intval($this->tt_news_uid);
  466. $singleWhere .= ' AND type NOT IN(1,2)' . $this->enableFields; // only real news -> type=0
  467. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  468. '*',
  469. 'tt_news',
  470. $singleWhere);
  471. $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
  472. // get the translated record if the content language is not the default language
  473. if ($GLOBALS['TSFE']->sys_language_content) {
  474. $OLmode = ($this->sys_language_mode == 'strict'?'hideNonTranslated':'');
  475. $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $OLmode);
  476. }
  477. if ($this->versioningEnabled) {
  478. // get workspaces Overlay
  479. $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$row);
  480. // fix pid for record from workspace
  481. $GLOBALS['TSFE']->sys_page->fixVersioningPid('tt_news',$row);
  482. }
  483. $GLOBALS['TSFE']->displayedNews[]=$row['uid'];
  484. if (is_array($row) && ($row['pid'] > 0 || $this->vPrev)) { // never display versions of a news record (having pid=-1) for normal website users
  485. // Get the subpart code
  486. if ($this->conf['displayCurrentRecord']) {
  487. $item = trim($this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE_RECORDINSERT###'), $row));
  488. }
  489. if (!$item) {
  490. $item = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SINGLE###'), $row);
  491. }
  492. // reset marker array
  493. $wrappedSubpartArray = array();
  494. // build the backToList link
  495. if ($this->conf['useHRDates']) {
  496. $pointerName = 'pointer';
  497. $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array(
  498. 'tt_news' => null,
  499. 'backPid' => null,
  500. $this->config['singleViewPointerName'] => null,
  501. 'pS' => null,
  502. 'pL' => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid']));
  503. } else {
  504. $wrappedSubpartArray['###LINK_ITEM###'] = explode('|', $this->pi_linkTP_keepPIvars('|', array(
  505. 'tt_news' => null,
  506. 'backPid' => null,
  507. $this->config['singleViewPointerName'] => null), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $this->config['backPid']));
  508. }
  509. // set the title of the single view page to the title of the news record
  510. if ($this->conf['substitutePagetitle']) {
  511. $GLOBALS['TSFE']->page['title'] = $row['title'];
  512. // set pagetitle for indexed search to news title
  513. $GLOBALS['TSFE']->indexedDocTitle = $row['title'];
  514. }
  515. if ($this->conf['displaySingle.']['catOrderBy']) {
  516. $this->config['catOrderBy'] = $this->conf['displaySingle.']['catOrderBy'];
  517. }
  518. $markerArray = $this->getItemMarkerArray($row, 'displaySingle');
  519. // Substitute
  520. $content = $this->cObj->substituteMarkerArrayCached($item, $markerArray, array(), $wrappedSubpartArray);
  521. } elseif ($this->sys_language_mode == 'strict' && $this->tt_news_uid && $GLOBALS['TSFE']->sys_language_content) { // not existing translation
  522. $noTranslMsg = $this->local_cObj->stdWrap($this->pi_getLL('noTranslMsg'), $this->conf['noNewsIdMsg_stdWrap.']);
  523. $content = $noTranslMsg;
  524. } elseif ($row['pid'] < 0) { // a non-public version of a record was requested
  525. $nonPlublicVersion = $this->local_cObj->stdWrap($this->pi_getLL('nonPlublicVersionMsg'), $this->conf['nonPlublicVersionMsg_stdWrap.']);
  526. $content = $nonPlublicVersion;
  527. } else { // if singleview is shown with no tt_news uid given from GETvars (&tx_ttnews[tt_news]=) an error message is displayed.
  528. $noNewsIdMsg = $this->local_cObj->stdWrap($this->pi_getLL('noNewsIdMsg'), $this->conf['noNewsIdMsg_stdWrap.']);
  529. $content = $noNewsIdMsg;
  530. }
  531. return $content;
  532. }
  533. /**
  534. * Displays the "versioning preview".
  535. * The functions checks:
  536. * - if the extension "version" is loaded
  537. * - if a BE_user is logged in
  538. * - the plausibility of the requested "version preview".
  539. * If this is all OK, "displaySingle()" is executed to display the "versioning preview".
  540. *
  541. * @return string html code for the "versioning preview"
  542. */
  543. function displayVersionPreview () {
  544. if ($this->versioningEnabled) {
  545. $vPrev = t3lib_div::_GP('ADMCMD_vPrev');
  546. if ($this->piVars['ADMCMD_vPrev']) {
  547. $piADMCMD = unserialize(rawurldecode($this->piVars['ADMCMD_vPrev']));
  548. }
  549. if ((is_array($vPrev) || is_array($piADMCMD)) && is_object($GLOBALS['BE_USER'])) { // check if ADMCMD_vPrev is set and if a BE_user is logged in. $this->piVars['ADMCMD_vPrev'] is needed for previewing a "single view with pagebrowser"
  550. if (!is_array($vPrev)) { $vPrev = $piADMCMD; }
  551. list($table,$t3ver_oid) = explode(':',key($vPrev));
  552. if ($table == 'tt_news') {
  553. if ($testrec = $this->pi_getRecord('tt_news', intval($vPrev[key($vPrev)]))) { // check if record exists before doing anything
  554. if ($testrec['t3ver_oid'] == intval($t3ver_oid) && $testrec['pid']==-1) { // check if requested t3ver_oid is the t3ver_oid of the requested tt_news record, and if the pid of the record is -1 (=non-plublic version)
  555. $GLOBALS['TSFE']->set_no_cache(); // version preview will never be cached
  556. // make version preview message with a link to the public version of hte record which is previewed
  557. $vPrevHeader = $this->local_cObj->stdWrap(
  558. $this->pi_getLL('versionPreviewMessage').
  559. $this->local_cObj->typolink(
  560. $this->local_cObj->stdWrap(
  561. $this->pi_getLL('versionPreviewMessageLinkToOriginal'),$this->conf['versionPreviewMessageLinkToOriginal_stdWrap.']
  562. ),
  563. array(
  564. 'parameter' => $this->config['singlePid'].' _blank',
  565. 'additionalParams' => '&tx_ttnews[tt_news]='.$t3ver_oid,
  566. 'no_cache' => 1
  567. )
  568. ),
  569. $this->conf['versionPreviewMessage_stdWrap.']
  570. );
  571. $this->tt_news_uid = intval($vPrev[key($vPrev)]);
  572. $this->piVars['tt_news'] = $this->tt_news_uid;
  573. $this->piVars['ADMCMD_vPrev'] = rawurlencode(serialize(array($table.':'.$t3ver_oid => $this->tt_news_uid)));
  574. $this->theCode = 'SINGLE';
  575. $this->vPrev = true;
  576. $content = $vPrevHeader.$this->displaySingle();
  577. } else { // error: t3ver_oid mismatch
  578. $GLOBALS['TT']->setTSlogMessage('tt_news: ERROR! The "t3ver_oid" of requested tt_news record and the "t3ver_oid" from GPvars doesn\'t match.');
  579. }
  580. }
  581. }
  582. }
  583. }
  584. return $content;
  585. }
  586. /**
  587. * Display LIST,LATEST or SEARCH
  588. * Things happen: determine the template-part to use, get the query parameters (add where if search was performed),
  589. * exec count query to get the number of results, check if a browsebox should be displayed,
  590. * get the general Markers for each item and fill the content array, check if a browsebox should be displayed
  591. *
  592. * @param string $excludeUids : commaseparated list of tt_news uids to exclude from display
  593. * @return string html-code for the plugin content
  594. */
  595. function displayList($excludeUids = 0) {
  596. $theCode = $this->theCode;
  597. $where = '';
  598. $content = '';
  599. switch ($theCode) {
  600. case 'LATEST':
  601. $prefix_display = 'displayLatest';
  602. $templateName = 'TEMPLATE_LATEST';
  603. if (!$this->conf['displayArchivedInLatest']) {
  604. // if this is set, latest will do the same as list
  605. $this->arcExclusive = -1; // Only latest, non archive news
  606. }
  607. $this->config['limit'] = $this->config['latestLimit'];
  608. break;
  609. case 'LIST':
  610. $prefix_display = 'displayList';
  611. $templateName = 'TEMPLATE_LIST';
  612. break;
  613. case 'SEARCH':
  614. $prefix_display = 'displayList';
  615. $templateName = 'TEMPLATE_LIST';
  616. // Make markers for the searchform
  617. $searchMarkers = array(
  618. '###FORM_URL###' => $this->pi_linkTP_keepPIvars_url(array('pointer' => null, 'cat' => null), 0, 1, $this->config['searchPid']),
  619. '###SWORDS###' => htmlspecialchars($this->piVars['swords']),
  620. '###SEARCH_BUTTON###' => $this->pi_getLL('searchButtonLabel'),
  621. );
  622. // Hook for any additional form fields
  623. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['additionalFormSearchFields'])) {
  624. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['additionalFormSearchFields'] as $_classRef) {
  625. $_procObj = & t3lib_div::getUserObj($_classRef);
  626. $searchMarkers = $_procObj->additionalFormSearchFields($this, $searchMarkers);
  627. }
  628. }
  629. // Add to content
  630. $searchSub = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SEARCH###'));
  631. $content .= $this->cObj->substituteMarkerArray($searchSub, $searchMarkers);
  632. unset($searchSub);
  633. unset($searchMarkers);
  634. // do the search and add the result to the $where string
  635. if ($this->piVars['swords']) {
  636. $where = $this->searchWhere(trim($this->piVars['swords']));
  637. $theCode = 'SEARCH';
  638. } else {
  639. $where = ($this->conf['emptySearchAtStart']?'AND 1=0':''); // display an empty list, if 'emptySearchAtStart' is set.
  640. }
  641. break;
  642. // xml news export
  643. case 'XML':
  644. $prefix_display = 'displayXML';
  645. // $this->arcExclusive = -1; // Only latest, non archive news
  646. $this->allowCaching = $this->conf['displayXML.']['xmlCaching'];
  647. $this->config['limit'] = $this->conf['displayXML.']['xmlLimit']?$this->conf['displayXML.']['xmlLimit']:
  648. $this->config['limit'];
  649. switch ($this->conf['displayXML.']['xmlFormat']) {
  650. case 'rss091':
  651. $templateName = 'TEMPLATE_RSS091';
  652. $this->templateCode = $this->cObj->fileResource($this->conf['displayXML.']['rss091_tmplFile']);
  653. break;
  654. case 'rss2':
  655. $templateName = 'TEMPLATE_RSS2';
  656. $this->templateCode = $this->cObj->fileResource($this->conf['displayXML.']['rss2_tmplFile']);
  657. break;
  658. case 'rdf':
  659. $templateName = 'TEMPLATE_RDF';
  660. $this->templateCode = $this->cObj->fileResource($this->conf['displayXML.']['rdf_tmplFile']);
  661. break;
  662. case 'atom03':
  663. $templateName = 'TEMPLATE_ATOM03';
  664. $this->templateCode = $this->cObj->fileResource($this->conf['displayXML.']['atom03_tmplFile']);
  665. break;
  666. case 'atom1':
  667. $templateName = 'TEMPLATE_ATOM1';
  668. $this->templateCode = $this->cObj->fileResource($this->conf['displayXML.']['atom1_tmplFile']);
  669. break;
  670. }
  671. break;
  672. }
  673. // process extra codes from $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']
  674. $userCodes = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['what_to_display'];
  675. if ($userCodes && !$prefix_display && !$templateName) {
  676. while (list(, $ucode) = each($userCodes)) {
  677. if ($theCode == $ucode[0]) {
  678. $prefix_display = 'displayList';
  679. $templateName = 'TEMPLATE_' . $ucode[0] ;
  680. }
  681. }
  682. }
  683. $noPeriod = 0; // used to call getSelectConf without a period lenght (pL) at the first archive page
  684. $pointerName = $this->pointerName = 'pointer';
  685. if (!$this->conf['emptyArchListAtStart']) {
  686. // if this is true, we're listing from the archive for the first time (no pS set), to prevent an empty list page we set the pS value to the archive start
  687. if (($this->arcExclusive > 0 && !$this->piVars['pS'] && $theCode != 'SEARCH')) {
  688. // set pS to time minus archive startdate
  689. if ($this->config['datetimeMinutesToArchive']) {
  690. $this->piVars['pS'] = ($GLOBALS['SIM_EXEC_TIME'] - ($this->config['datetimeMinutesToArchive'] * 60));
  691. } elseif ($this->config['datetimeHoursToArchive']) {
  692. $this->piVars['pS'] = ($GLOBALS['SIM_EXEC_TIME'] - ($this->config['datetimeHoursToArchive'] * 3600));
  693. } else {
  694. $this->piVars['pS'] = ($GLOBALS['SIM_EXEC_TIME'] - ($this->config['datetimeDaysToArchive'] * 86400));
  695. }
  696. }
  697. }
  698. if ($this->piVars['pS'] && !$this->piVars['pL']) {
  699. $noPeriod = 1; // override the period lenght checking in getSelectConf
  700. }
  701. // Allowed to show the listing? periodStart must be set, when listing from the archive.
  702. if (!($this->arcExclusive > -1 && !$this->piVars['pS'] && $theCode != 'SEARCH')) {
  703. if ($this->conf['displayCurrentRecord'] && $this->tt_news_uid) {
  704. $this->pid_list = $this->cObj->data['pid'];
  705. $where = 'AND tt_news.uid=' . $this->tt_news_uid;
  706. }
  707. if ($excludeUids) {
  708. $where = ' AND tt_news.uid NOT IN ('.$excludeUids.')';
  709. }
  710. // build parameter Array for List query
  711. $selectConf = $this->getSelectConf($where, $noPeriod);
  712. // performing query to count all news (we need to know it for browsing):
  713. $selectConf['selectFields'] = 'COUNT(DISTINCT(tt_news.uid))';
  714. $newsCount = 0;
  715. if (($res = $this->exec_getQuery('tt_news', $selectConf))) {
  716. list($newsCount) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
  717. $GLOBALS['TYPO3_DB']->sql_free_result($res);
  718. }
  719. // Only do something if the query result is not empty
  720. if ($newsCount > 0) {
  721. // Init Templateparts: $t['total'] is complete template subpart (TEMPLATE_LATEST f.e.)
  722. // $t['item'] is an array with the alternative subparts (NEWS, NEWS_1, NEWS_2 ...)
  723. $t = array();
  724. $t['total'] = $this->getNewsSubpart($this->templateCode, $this->spMarker('###' . $templateName . '###'));
  725. $t['item'] = $this->getLayouts($t['total'], $this->alternatingLayouts, 'NEWS');
  726. // build query for display:
  727. $selectConf['selectFields'] = 'DISTINCT(tt_news.uid),tt_news.*';
  728. if ($this->config['groupBy']) {
  729. $selectConf['groupBy'] = $this->config['groupBy'];
  730. }
  731. // else {
  732. // $selectConf['groupBy'] = 'tt_news.uid';
  733. // }
  734. if ($this->config['orderBy']) {
  735. if (strtoupper($this->config['orderBy']) == 'RANDOM') {
  736. $selectConf['orderBy'] = 'RAND()';
  737. } else {
  738. $selectConf['orderBy'] = $this->config['orderBy'] . ($this->config['ascDesc']?' ' . $this->config['ascDesc']:'');
  739. }
  740. } else {
  741. $selectConf['orderBy'] = 'datetime DESC';
  742. }
  743. // overwrite the groupBy value for categories
  744. if (!$this->catExclusive && $selectConf['groupBy'] == 'category') {
  745. $selectConf['leftjoin'] = 'tt_news_cat_mm ON tt_news.uid = tt_news_cat_mm.uid_local';
  746. $selectConf['groupBy'] = 'tt_news_cat_mm.uid_foreign';
  747. // $selectConf['selectFields'] = 'DISTINCT(tt_news.uid),tt_news.*';
  748. }
  749. // exclude the LATEST template from changing its content with the pagebrowser. This can be overridden by setting the conf var latestWithPagebrowser
  750. if ($theCode != 'LATEST' || $this->conf['latestWithPagebrowser']) {
  751. $selectConf['begin'] = $this->piVars[$pointerName] * $this->config['limit'];
  752. }
  753. if (!$this->conf['excludeAlreadyDisplayedNews']) {
  754. // exclude news-records shown in LATEST from the LIST template
  755. if ($theCode == 'LIST' && $this->conf['excludeLatestFromList'] && !$this->piVars[$pointerName] && !$this->piVars['cat']) {
  756. if ($this->config['latestLimit']) {
  757. $selectConf['begin'] += $this->config['latestLimit'];
  758. $newsCount -= $this->config['latestLimit'];
  759. } else {
  760. $selectConf['begin'] += $newsCount;
  761. // this will clean the display of LIST view when 'latestLimit' is unset because all the news have been shown in LATEST already
  762. }
  763. }
  764. // List start ID
  765. if (($theCode == 'LIST' || $theCode == 'LATEST') && $this->config['listStartId'] && !$this->piVars[$pointerName] && !$this->piVars['cat']) {
  766. $selectConf['begin'] = $this->config['listStartId'];
  767. }
  768. }
  769. // Reset:
  770. $subpartArray = array();
  771. $wrappedSubpartArray = array();
  772. $markerArray = array();
  773. // get the list of news items and fill them in the CONTENT subpart
  774. $subpartArray['###CONTENT###'] = $this->getListContent($t['item'], $selectConf, $prefix_display);
  775. $markerArray['###NEWS_CATEGORY_ROOTLINE###'] = '';
  776. if($this->conf['catRootline.']['showCatRootline'] && $this->piVars['cat'] && !strpos($this->piVars['cat'],',')) {
  777. $markerArray['###NEWS_CATEGORY_ROOTLINE###'] = $this->getCategoryPath(array(array('catid' => intval($this->piVars['cat']))));
  778. }
  779. if ($theCode == 'XML') {
  780. $markerArray = $this->getXmlHeader();
  781. $subpartArray['###HEADER###'] = $this->cObj->substituteMarkerArray($this->getNewsSubpart($t['total'], '###HEADER###'), $markerArray);
  782. if($this->conf['displayXML.']['xmlFormat']) {
  783. if(!empty($this->rdfToc)) {
  784. $markerArray['###NEWS_RDF_TOC###'] = '<rdf:Seq>'."\n".$this->rdfToc."\t\t\t".'</rdf:Seq>';
  785. } else {
  786. $markerArray['###NEWS_RDF_TOC###'] = '';
  787. }
  788. }
  789. $subpartArray['###HEADER###'] = $this->cObj->substituteMarkerArray($this->getNewsSubpart($t['total'], '###HEADER###'), $markerArray);
  790. }
  791. $markerArray['###GOTOARCHIVE###'] = $this->pi_getLL('goToArchive');
  792. $markerArray['###LATEST_HEADER###'] = $this->pi_getLL('latestHeader');
  793. $wrappedSubpartArray['###LINK_ARCHIVE###'] = $this->local_cObj->typolinkWrap($this->conf['archiveTypoLink.']);
  794. // unset pagebrowser markers
  795. $markerArray['###LINK_PREV###'] = '';
  796. $markerArray['###LINK_NEXT###'] = '';
  797. $markerArray['###BROWSE_LINKS###'] = '';
  798. // render a pagebrowser if needed
  799. if ($newsCount > $this->config['limit'] && !$this->config['noPageBrowser']) {
  800. // configure pagebrowser vars
  801. $this->internal['res_count'] = $newsCount;
  802. $this->internal['results_at_a_time'] = $this->config['limit'];
  803. $this->internal['maxPages'] = $this->conf['pageBrowser.']['maxPages'];
  804. if (!$this->conf['pageBrowser.']['showPBrowserText']) {
  805. $this->LOCAL_LANG[$this->LLkey]['pi_list_browseresults_page'] = '';
  806. }
  807. if ($this->conf['userPageBrowserFunc']) {
  808. $markerArray = $this->userProcess('userPageBrowserFunc', $markerArray);
  809. } else {
  810. if ($this->conf['usePiBasePagebrowser']) {
  811. $this->internal['pagefloat'] = $this->conf['pageBrowser.']['pagefloat'];
  812. $this->internal['showFirstLast'] = $this->conf['pageBrowser.']['showFirstLast'];
  813. $this->internal['showRange'] = $this->conf['pageBrowser.']['showRange'];
  814. $this->internal['dontLinkActivePage'] = $this->conf['pageBrowser.']['dontLinkActivePage'];
  815. $wrapArrFields = explode(',', 'disabledLinkWrap,inactiveLinkWrap,activeLinkWrap,browseLinksWrap,showResultsWrap,showResultsNumbersWrap,browseBoxWrap');
  816. $wrapArr = array();
  817. foreach($wrapArrFields as $key) {
  818. if ($this->conf['pageBrowser.'][$key]) {
  819. $wrapArr[$key] = $this->conf['pageBrowser.'][$key];
  820. }
  821. }
  822. if ($wrapArr['showResultsNumbersWrap'] && strpos($this->LOCAL_LANG[$this->LLkey]['pi_list_browseresults_displays'],'%s')) {
  823. // if the advanced pagebrowser is enabled and the "pi_list_browseresults_displays" label contains %s it will be replaced with the content of the label "pi_list_browseresults_displays_advanced"
  824. $this->LOCAL_LANG[$this->LLkey]['pi_list_browseresults_displays'] = $this->LOCAL_LANG[$this->LLkey]['pi_list_browseresults_displays_advanced'];
  825. }
  826. $this->pi_alwaysPrev = $this->conf['pageBrowser.']['alwaysPrev'];
  827. if ($this->conf['useHRDates']) {
  828. // prevent adding pS & pL to pagebrowser links if useHRDates is enabled
  829. $tmpPS = $this->piVars['pS'];
  830. unset($this->piVars['pS']);
  831. $tmpPL = $this->piVars['pL'];
  832. unset($this->piVars['pL']);
  833. }
  834. // if there is a GETvar in the URL that is not in this list, caching will be disabled for the pagebrowser links
  835. $this->pi_isOnlyFields = $pointerName.',tt_news,year,month,day,pS,pL,arc,cat';
  836. // pi_lowerThan limits the amount of cached pageversions for the list view. Caching will be disabled if one of the vars in $this->pi_isOnlyFields has a value greater than $this->pi_lowerThan
  837. // $this->pi_lowerThan = ceil($this->internal['res_count']/$this->internal['results_at_a_time']);
  838. $pi_isOnlyFieldsArr = explode(',',$this->pi_isOnlyFields);
  839. $highestVal = 0;
  840. foreach ($pi_isOnlyFieldsArr as $k => $v) {
  841. if ($this->piVars[$v] > $highestVal) {
  842. $highestVal = $this->piVars[$v];
  843. }
  844. }
  845. $this->pi_lowerThan = $highestVal+1;
  846. // render pagebrowser
  847. $markerArray['###BROWSE_LINKS###'] = $this->pi_list_browseresults($this->conf['pageBrowser.']['showResultCount'], $this->conf['pageBrowser.']['tableParams'],$wrapArr, $pointerName, $this->conf['pageBrowser.']['hscText']);
  848. if ($this->conf['useHRDates']) {
  849. // restore pS & pL
  850. if ($tmpPS) $this->piVars['pS'] = $tmpPS;
  851. if ($tmpPL) $this->piVars['pL'] = $tmpPL;
  852. }
  853. } else {
  854. $markerArray['###BROWSE_LINKS###'] = $this->makePageBrowser($this->conf['pageBrowser.']['showResultCount'], $this->conf['pageBrowser.']['tableParams'],$pointerName);
  855. }
  856. }
  857. }
  858. // Adds hook for processing of extra global markers
  859. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraGlobalMarkerHook'])) {
  860. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraGlobalMarkerHook'] as $_classRef) {
  861. $_procObj = & t3lib_div::getUserObj($_classRef);
  862. $markerArray = $_procObj->extraGlobalMarkerProcessor($this, $markerArray);
  863. }
  864. }
  865. $content .= $this->cObj->substituteMarkerArrayCached($t['total'], $markerArray, $subpartArray, $wrappedSubpartArray);
  866. } elseif (strpos($where,'1=0')) {
  867. // first view of the search page with the parameter 'emptySearchAtStart' set
  868. $markerArray['###SEARCH_EMPTY_MSG###'] = $this->local_cObj->stdWrap($this->pi_getLL('searchEmptyMsg'), $this->conf['searchEmptyMsg_stdWrap.']);
  869. $searchEmptyMsg = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SEARCH_EMPTY###'));
  870. $content .= $this->cObj->substituteMarkerArrayCached($searchEmptyMsg, $markerArray);
  871. } elseif ($this->piVars['swords']) {
  872. // no results
  873. $markerArray['###SEARCH_EMPTY_MSG###'] = $this->local_cObj->stdWrap($this->pi_getLL('noResultsMsg'), $this->conf['searchEmptyMsg_stdWrap.']);
  874. $searchEmptyMsg = $this->getNewsSubpart($this->templateCode, $this->spMarker('###TEMPLATE_SEARCH_EMPTY###'));
  875. $content .= $this->cObj->substituteMarkerArrayCached($searchEmptyMsg, $markerArray);
  876. } elseif ($theCode == 'XML') {
  877. // fill at least the template header
  878. // Init Templateparts: $t['total'] is complete template subpart (TEMPLATE_LATEST f.e.)
  879. $t = array();
  880. $t['total'] = $this->getNewsSubpart($this->templateCode, $this->spMarker('###' . $templateName . '###'));
  881. // Reset:
  882. $subpartArray = array();
  883. $wrappedSubpartArray = array();
  884. $markerArray = array();
  885. // header data
  886. $markerArray = $this->getXmlHeader();
  887. $subpartArray['###HEADER###'] = $this->cObj->substituteMarkerArray($this->getNewsSubpart($t['total'], '###HEADER###'), $markerArray);
  888. // substitute the xml declaration (it's not included in the subpart ###HEADER###)
  889. $t['total'] = $this->cObj->substituteMarkerArray($t['total'], array('###XML_DECLARATION###' => $markerArray['###XML_DECLARATION###']));
  890. $t['total'] = $this->cObj->substituteMarkerArray($t['total'], array('###SITE_LANG###' => $markerArray['###SITE_LANG###']));
  891. $t['total'] = $this->cObj->substituteSubpart($t['total'], '###HEADER###', $subpartArray['###HEADER###'], 0);
  892. $t['total'] = $this->cObj->substituteSubpart($t['total'], '###CONTENT###', '', 0);
  893. $content .= $t['total'];
  894. } elseif ($this->arcExclusive && $this->piVars['pS'] && $GLOBALS['TSFE']->sys_language_content) {
  895. // this matches if a user has switched languages within a archive period that contains no items in the desired language
  896. $content .= $this->local_cObj->stdWrap($this->pi_getLL('noNewsForArchPeriod', 'Sorry, there are no translated news-articles in this Archive period'), $this->conf['noNewsToListMsg_stdWrap.']);
  897. } else {
  898. $content .= $this->local_cObj->stdWrap($this->pi_getLL('noNewsToListMsg'), $this->conf['noNewsToListMsg_stdWrap.']);
  899. }
  900. }
  901. return $content;
  902. }
  903. /**
  904. * get the content for a news item NOT displayed as single item (List & Latest)
  905. *
  906. * @param array $itemparts : parts of the html template
  907. * @param array $selectConf : quety parameters in an array
  908. * @param string $prefix_display : the part of the TS-setup
  909. * @return string $itemsOut: itemlist as htmlcode
  910. */
  911. function getListContent($itemparts, $selectConf, $prefix_display) {
  912. $res = $this->exec_getQuery('tt_news', $selectConf); //get query for list contents
  913. $itemsOut = '';
  914. $itempartsCount = count($itemparts);
  915. $pTmp = $GLOBALS['TSFE']->ATagParams;
  916. $cc = 0;
  917. $token = md5(microtime());
  918. // Getting elements
  919. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  920. $GLOBALS['TSFE']->displayedNews[]=$row['uid'];
  921. $wrappedSubpartArray = array();
  922. $lConf = $this->conf[$prefix_display.'.'];
  923. $titleField = $lConf['linkTitleField']?$lConf['linkTitleField']:'';
  924. if ($GLOBALS['TSFE']->sys_language_content) {
  925. // prevent link targets from being changed in localized records
  926. $tmpPage = $row['page'];
  927. $tmpExtURL = $row['ext_url'];
  928. $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL, '');
  929. $row['page'] = $tmpPage;
  930. $row['ext_url'] = $tmpExtURL;
  931. }
  932. if ($this->versioningEnabled) {
  933. // get workspaces Overlay
  934. $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$row);
  935. }
  936. $GLOBALS['TSFE']->ATagParams = $pTmp.' title="'.$this->local_cObj->stdWrap(trim(htmlspecialchars($row[$titleField])), $lConf['linkTitleField.']).'"';
  937. if ($this->conf[$prefix_display.'.']['catOrderBy']) {
  938. $this->config['catOrderBy'] = $this->conf[$prefix_display.'.']['catOrderBy'];
  939. }
  940. $this->categories[$row['uid']] = $this->getCategories($row['uid']);
  941. if ($row['type'] == 1 || $row['type'] == 2) {
  942. // News type article or external url
  943. $this->local_cObj->setCurrentVal($row['type'] == 1 ? $row['page']:$row['ext_url']);
  944. $wrappedSubpartArray['###LINK_ITEM###'] = $this->local_cObj->typolinkWrap($this->conf['pageTypoLink.']);
  945. // fill the link string in a register to access it from TS
  946. $this->local_cObj->LOAD_REGISTER(array('newsMoreLink' => $this->local_cObj->typolink($this->pi_getLL('more'), $this->conf['pageTypoLink.'])), '');
  947. } else {
  948. // Overwrite the singlePid from config-array with a singlePid given from the first entry in $this->categories
  949. if ($this->conf['useSPidFromCategory'] && is_array($this->categories)) {
  950. $tmpcats = $this->categories;
  951. $catSPid = array_shift($tmpcats[$row['uid']]);
  952. }
  953. $singlePid = $catSPid['single_pid']?$catSPid['single_pid']:$this->config['singlePid'];
  954. if ($this->conf['useHRDates'] && !$this->conf['useHRDatesSingle']) {
  955. $piVarsArray = array(
  956. 'tt_news' => $row['uid'],
  957. 'backPid' => ($this->conf['dontUseBackPid']?null:$this->config['backPid']),
  958. 'year' => ($this->conf['dontUseBackPid']?null:($this->piVars['year']?$this->piVars['year']:null)),
  959. 'month' => ($this->conf['dontUseBackPid']?null:($this->piVars['month']?$this->piVars['month']:null)),
  960. 'pS' => null,
  961. 'pL' => null,
  962. 'arc' => null,
  963. );
  964. $wrappedSubpartArray['###LINK_ITEM###'] = explode($token, $this->pi_linkTP_keepPIvars($token, $piVarsArray, $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $singlePid));
  965. $this->local_cObj->LOAD_REGISTER(array('newsMoreLink' => $this->pi_linkTP_keepPIvars($this->pi_getLL('more'), $piVarsArray, $this->allowCaching,($this->conf['dontUseBackPid']?1:0), $singlePid)), '');
  966. } elseif ($this->conf['useHRDates'] && $this->conf['useHRDatesSingle']) {
  967. $tmpY = $this->piVars['year'];
  968. $tmpM = $this->piVars['month'];
  969. $tmpD = $this->piVars['day'];
  970. $this->getHrDateSingle($row['datetime']);
  971. $piVarsArray = array(
  972. 'tt_news' => $row['uid'],
  973. 'backPid' => ($this->conf['dontUseBackPid']?null:$this->config['backPid']),
  974. 'year' => $this->piVars['year'],
  975. 'month' => $this->piVars['month'],
  976. 'day' => ($this->piVars['day']?$this->piVars['day']:null),
  977. 'pS' => null,
  978. 'pL' => null,
  979. 'arc' => null,
  980. );
  981. $wrappedSubpartArray['###LINK_ITEM###'] = explode($token, $this->pi_linkTP_keepPIvars($token,$piVarsArray, $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $singlePid));
  982. // fill the link string in a register to access it from TS
  983. $this->local_cObj->LOAD_REGISTER(array('newsMoreLink' => $this->pi_linkTP_keepPIvars($this->pi_getLL('more'), $piVarsArray, $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $singlePid)), '');
  984. $this->piVars['year'] = $tmpY;
  985. $this->piVars['month'] = $tmpM;
  986. $this->piVars['day'] = $tmpD;
  987. } else {
  988. $wrappedSubpartArray['###LINK_ITEM###'] = explode($token, $this->pi_linkTP_keepPIvars($token, array('tt_news' => $row['uid'], 'backPid' => ($this->conf['dontUseBackPid']?null:$this->config['backPid'])), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $singlePid));
  989. // fill the link string in a register to access it from TS
  990. $this->local_cObj->LOAD_REGISTER(array('newsMoreLink' => $this->pi_linkTP_keepPIvars($this->pi_getLL('more'), array('tt_news' => $row['uid'], 'backPid' => ($this->conf['dontUseBackPid']?null:$this->config['backPid'])), $this->allowCaching, ($this->conf['dontUseBackPid']?1:0), $singlePid)), '');
  991. }
  992. }
  993. // reset ATagParams
  994. $GLOBALS['TSFE']->ATagParams = $pTmp;
  995. $markerArray = $this->getItemMarkerArray($row, $prefix_display);
  996. // XML
  997. if ($this->theCode == 'XML') {
  998. if ($row['type'] == 1 || $row['type'] == 2) {
  999. if ($row['type'] == 2) {
  1000. $exturl = trim(strpos($row['ext_url'],'http://')!==FALSE?$row['ext_url']:'http://'.$row['ext_url']);
  1001. $exturl = (strpos($exturl,' ')?substr($exturl, 0, strpos($exturl, ' ')):$exturl);
  1002. }
  1003. $rssUrl = ($row['type'] == 1 ? $this->config['siteUrl'] .$this->pi_getPageLink($row['page'], ''):$exturl);
  1004. } else {
  1005. if ($this->conf['useHRDates'] && !$this->conf['useHRDatesSingle']) {
  1006. $piVarsArray = array(
  1007. 'tt_news' => $row['uid'],
  1008. 'backPid' => ($this->conf['dontUseBackPid']?null:$this->config['backPid']),
  1009. 'year' => ($this->conf['dontUseBackPid']?null:($this->piVars['year']?$this->piVars['year']:null)),
  1010. 'month' => ($this->conf['dontUseBackPid']?null:($this->piVars['month']?$this->piVars['month']:null)),
  1011. 'pS' => null,
  1012. 'pL' => null,
  1013. 'arc' => null,
  1014. );
  1015. $rssUrl = $this->config['siteUrl'] . $this->pi_linkTP_keepPIvars_url($piVarsArray, $this->allowCaching, '', $singlePid);
  1016. } elseif ($this->conf['useHRDates'] && $this->conf['useHRDatesSingle']) {
  1017. $tmpY = $this->piVars['year'];
  1018. $tmpM = $this->piVars['month'];
  1019. $tmpD = $this->piVars['day'];
  1020. $this->getHrDateSingle($row['datetime']);
  1021. $piVarsArray = array(
  1022. 'tt_news' => $row['uid'],
  1023. 'backPid' => ($this->conf['dontUseBackPid']?null:$this->config['backPid']),
  1024. 'year' => $this->piVars['year'],
  1025. 'month' => $this->piVars['month'],
  1026. 'day' => ($this->piVars['day']?$this->piVars['day']:null),
  1027. 'pS' => null,
  1028. 'pL' => null,
  1029. 'arc' => null,
  1030. );
  1031. $rssUrl = $this->config['siteUrl'] . $this->pi_linkTP_keepPIvars_url($piVarsArray, $this->allowCaching, '', $singlePid);
  1032. } else {
  1033. $rssUrl = $this->config['siteUrl'] . $this->pi_linkTP_keepPIvars_url(array('tt_news' => $row['uid'], 'backPid' => null), $this->allowCaching, '', $singlePid);
  1034. }
  1035. }
  1036. // replace square brackets [] in links with their URLcodes and replace the &-sign with its ASCII code
  1037. $rssUrl = preg_replace(array('/\[/', '/\]/', '/&/'), array('%5B', '%5D', '&#38;') , $rssUrl);
  1038. $markerArray['###NEWS_LINK###'] = $rssUrl;
  1039. if($this->conf['displayXML.']['xmlFormat'] == 'rdf') {
  1040. $this->rdfToc .= "\t\t\t\t".'<rdf:li resource="'.$rssUrl.'" />'."\n";
  1041. }
  1042. }
  1043. $layoutNum = ($itempartsCount == 0 ? 0 : ($cc % $itempartsCount));
  1044. // Store the result of template parsing in the Var $itemsOut, use the alternating layouts
  1045. $itemsOut .= $this->cObj->substituteMarkerArrayCached($itemparts[$layoutNum], $markerArray, array(), $wrappedSubpartArray);
  1046. $cc++;
  1047. if ($cc == $this->config['limit']) {
  1048. break;
  1049. }
  1050. }
  1051. return $itemsOut;
  1052. }
  1053. /**
  1054. * build the selectconf (array of query-parameters) to get the news items from the db
  1055. *
  1056. * @param string $where : where-part of the query
  1057. * @param integer $noPeriod : if this value exists the listing starts with the given 'period start' (pS). If not the value period start needs also a value for 'period lenght' (pL) to display something.
  1058. * @return array the selectconf for the display of a news item
  1059. */
  1060. function getSelectConf($where, $noPeriod = 0) {
  1061. // Get news
  1062. $selectConf = Array();
  1063. $selectConf['pidInList'] = $this->pid_list;
  1064. $selectConf['where'] = '';
  1065. if ($this->sys_language_mode == 'strict' && $GLOBALS['TSFE']->sys_language_content) {
  1066. // sys_language_mode == 'strict': If a certain language is requested, select only news-records from the default language which have a translation. The translated articles will be overlayed later in the list or single function.
  1067. $tmpres = $this->exec_getQuery('tt_news', array(
  1068. 'selectFields' => 'tt_news.l18n_parent',
  1069. 'where' => 'tt_news.sys_language_uid = '.$GLOBALS['TSFE']->sys_language_content.$this->enableFields,
  1070. 'pidInList' => $this->pid_list));
  1071. $strictUids = array();
  1072. while ($tmprow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($tmpres)) {
  1073. $strictUids[] = $tmprow['l18n_parent'];
  1074. }
  1075. $strStrictUids = implode(',', $strictUids);
  1076. $selectConf['where'] .= '(tt_news.uid IN (' . ($strStrictUids?$strStrictUids:0) . ') OR tt_news.sys_language_uid=-1)'; // sys_language_uid=-1 = [all languages]
  1077. } else {
  1078. // sys_language_mode != 'strict': If a certain language is requested, select only news-records in the default language. The translated articles (if they exist) will be overlayed later in the list or single function.
  1079. $selectConf['where'] .= 'tt_news.sys_language_uid IN (0,-1)';
  1080. }
  1081. if ($this->conf['showNewsWithoutDefaultTranslation']) {
  1082. $selectConf['where'] = '('.$selectConf['where'].' OR (tt_news.sys_language_uid='.$GLOBALS['TSFE']->sys_language_content.' AND NOT tt_news.l18n_parent))';
  1083. }
  1084. $selectConf['where'] = '1=1 AND ' . ($this->theCode == 'LATEST'?'':($where?'1=1 '.$where.' AND ':'')).$selectConf['where'];
  1085. if ($this->arcExclusive > 0) {
  1086. if ($this->piVars['arc']) {
  1087. // allow overriding of the arcExclusive parameter from GET vars
  1088. $this->arcExclusive = intval($this->piVars['arc']);
  1089. }
  1090. // select news from a certain period
  1091. if (!$noPeriod && intval($this->piVars['pS'])) {
  1092. $selectConf['where'] .= ' AND tt_news.datetime>=' . intval($this->piVars['pS']);
  1093. if (intval($this->piVars['pL'])) {
  1094. $pL = intval($this->piVars['pL']);
  1095. //selecting news for a certain day only
  1096. if(intval($this->piVars['day'])) {
  1097. $pL = 86400; // = 24h, as pS always starts at the beginning of a day (00:00:00)
  1098. }
  1099. $selectConf['where'] .= ' AND tt_news.datetime<' . (intval($this->piVars['pS']) + $pL);
  1100. }
  1101. }
  1102. }
  1103. if ($this->arcExclusive) {
  1104. if ($this->conf['enableArchiveDate'] && $this->config['datetimeDaysToArchive'] && $this->arcExclusive > 0) {
  1105. $theTime = $GLOBALS['SIM_EXEC_TIME'] - intval($this->config['datetimeDaysToArchive']) * 3600 * 24;
  1106. if (version_compare($this->conf['compatVersion'], '2.5.0') <= 0) {
  1107. $selectConf['where'] .= ' AND (tt_news.archivedate<'.$GLOBALS['SIM_EXEC_TIME'].' OR tt_news.datetime<'.$theTime.')';
  1108. }
  1109. else {
  1110. $selectConf['where'] .= ' AND ((tt_news.archivedate > 0 AND tt_news.archivedate<'.$GLOBALS['SIM_EXEC_TIME'].') OR tt_news.datetime<'.$theTime.')';
  1111. }
  1112. } else {
  1113. if ($this->conf['enableArchiveDate']) {
  1114. if ($this->arcExclusive < 0) {
  1115. // show archived
  1116. $selectConf['where'] .= ' AND (tt_news.archivedate=0 OR tt_news.archivedate>' . $GLOBALS['SIM_EXEC_TIME'] . ')';
  1117. } elseif ($this->arcExclusive > 0) {
  1118. if (version_compare($this->conf['compatVersion'], '2.5.0') <= 0) {
  1119. $selectConf['where'] .= ' AND tt_news.archivedate<' . $GLOBALS['SIM_EXEC_TIME'];
  1120. }
  1121. else {
  1122. $selectConf['where'] .= ' AND tt_news.archivedate>0 AND tt_news.archivedate<' . $GLOBALS['SIM_EXEC_TIME'];
  1123. }
  1124. }
  1125. }
  1126. if ($this->config['datetimeMinutesToArchive'] || $this->config['datetimeHoursToArchive'] || $this->config['datetimeDaysToArchive']) {
  1127. if ($this->config['datetimeMinutesToArchive']) {
  1128. $theTime = $GLOBALS['SIM_EXEC_TIME'] - intval($this->config['datetimeMinutesToArchive']) * 60;
  1129. }
  1130. elseif ($this->config['datetimeHoursToArchive']) {
  1131. $theTime = $GLOBALS['SIM_EXEC_TIME'] - intval($this->config['datetimeHoursToArchive']) * 3600;
  1132. }
  1133. else {
  1134. $theTime = $GLOBALS['SIM_EXEC_TIME'] - intval($this->config['datetimeDaysToArchive']) * 86400;
  1135. }
  1136. if ($this->arcExclusive < 0) {
  1137. $selectConf['where'] .= ' AND (tt_news.datetime=0 OR tt_news.datetime>' . $theTime . ')';
  1138. } elseif ($this->arcExclusive > 0) {
  1139. $selectConf['where'] .= ' AND tt_news.datetime<' . $theTime;
  1140. }
  1141. }
  1142. }
  1143. }
  1144. // exclude LATEST and AMENU from changing their contents with the catmenu. This can be overridden by setting the TSvars 'latestWithCatSelector' or 'amenuWithCatSelector'
  1145. if ($this->config['catSelection'] && (
  1146. ($this->theCode == 'LATEST' && $this->conf['latestWithCatSelector']) ||
  1147. ($this->theCode == 'AMENU' && $this->conf['amenuWithCatSelector']) ||
  1148. ($this->theCode == 'LIST' || $this->theCode == 'SEARCH' || $this->theCode == 'XML'))) {
  1149. // force 'select categories' mode if cat is given in GPvars
  1150. $this->config['categoryMode'] = 1;
  1151. // override category selection from other news content-elements with selection from catmenu (GPvars)
  1152. $this->catExclusive = $this->config['catSelection'];
  1153. }
  1154. if ($this->catExclusive) {
  1155. // select newsitems by their categories
  1156. if ($this->config['categoryMode'] == 1 || $this->config['categoryMode'] == 2) {
  1157. // show items with selected categories
  1158. $tmpCatExclusive = ($this->config['categoryMode'] == 2 && !$this->conf['ignoreUseSubcategoriesForAndSelection'] ? $this->actuallySelectedCategories : $this->catExclusive);
  1159. $selectConf['leftjoin'] = 'tt_news_cat_mm ON tt_news.uid = tt_news_cat_mm.uid_local';
  1160. $selectConf['where'] .= ' AND (IFNULL(tt_news_cat_mm.uid_foreign,0) IN (' . ($tmpCatExclusive ? $tmpCatExclusive : 0) . '))';
  1161. }
  1162. // de-select newsitems by their categories
  1163. if (($this->config['categoryMode'] == -1 || $this->config['categoryMode'] == -2)) {
  1164. // do not show items with selected categories
  1165. $selectConf['leftjoin'] = 'tt_news_cat_mm ON tt_news.uid = tt_news_cat_mm.uid_local';
  1166. $selectConf['where'] .= ' AND (IFNULL(tt_news_cat_mm.uid_foreign,0) NOT IN (' . ($this->catExclusive?$this->catExclusive:0) . '))';
  1167. $selectConf['where'] .= ' AND (tt_news_cat_mm.uid_foreign)'; // filter out not categoized records
  1168. }
  1169. } elseif ($this->config['categoryMode']) {
  1170. // special case: if $this->catExclusive is not set but $this->config['categoryMode'] -> show only non-categized records
  1171. $selectConf['leftjoin'] = 'tt_news_cat_mm ON tt_news.uid = tt_news_cat_mm.uid_local';
  1172. $selectConf['where'] .= ' AND (IFNULL(tt_news_cat_mm.uid_foreign,'.$GLOBALS['TYPO3_DB']->fullQuoteStr('nocat', 'tt_news').') ' . ($this->config['categoryMode'] > 0?'':'!') . '='.$GLOBALS['TYPO3_DB']->fullQuoteStr('nocat', 'tt_news').')';
  1173. }
  1174. // if categoryMode is 'show items AND' it's required to check if the records in the result do actually have the same number of categories as in $this->catExclusive
  1175. if ($this->catExclusive && $this->config['categoryMode'] == 2) {
  1176. $tmpCatExclusive = $this->catExclusive /*$this->actuallySelectedCategories*/;
  1177. $res = $this->exec_getQuery('tt_news', $selectConf);
  1178. $results = array();
  1179. $resultsCount = array();
  1180. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1181. $results[] = $row['uid'];
  1182. if (in_array($row['uid'], $results)) {
  1183. $resultsCount[$row['uid']]++;
  1184. }
  1185. }
  1186. $catCount = count(explode(',',$tmpCatExclusive));
  1187. $cleanedResultsCount = array();
  1188. foreach ($resultsCount as $uid => $hits) {
  1189. if ($hits == $catCount) {
  1190. $cleanedResultsCount[] = $uid;
  1191. }
  1192. }
  1193. $matchlist = implode(',',$cleanedResultsCount);
  1194. if ($matchlist) {
  1195. $selectConf['where'] .= ' AND tt_news.uid IN ('.$matchlist.')';
  1196. } else {
  1197. $selectConf['where'] .= ' AND tt_news.uid IN (0)';
  1198. }
  1199. }
  1200. // if categoryMode is 'don't show items OR' we check if each found record does not have any of the deselected categories assigned
  1201. if ($this->catExclusive && $this->config['categoryMode'] == -2) {
  1202. $res = $this->exec_getQuery('tt_news', $selectConf);
  1203. $results = array();
  1204. $resultsCount = array();
  1205. while (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
  1206. $results[$row['uid']] = $row['uid'];
  1207. }
  1208. array_unique($results);
  1209. foreach ($results as $uid) {
  1210. $currentCats = $this->getCategories($uid);
  1211. foreach (array_keys($currentCats) as $catid) {
  1212. if (t3lib_div::inList($this->catExclusive,$catid)) {
  1213. unset($results[$uid]);
  1214. break; // break after one deselected category was found
  1215. }
  1216. }
  1217. }
  1218. $matchlist = implode(',',$results);
  1219. if ($matchlist) {
  1220. $selectConf['where'] .= ' AND tt_news.uid IN ('.$matchlist.')';
  1221. } else {
  1222. $selectConf['where'] .= ' AND tt_news.uid IN (0)';
  1223. }
  1224. }
  1225. // filter Workspaces preview.
  1226. // Since "enablefields" is ignored in workspace previews it's required to filter out news manually which are not visible in the live version AND the selected workspace.
  1227. if ($GLOBALS['TSFE']->sys_page->versioningPreview) {
  1228. // execute the complete query
  1229. $wsSelectconf = $selectConf;
  1230. $wsSelectconf['selectFields'] = 'uid,pid,tstamp,crdate,deleted,hidden,fe_group,sys_language_uid,l18n_parent,l18n_diffsource,t3ver_oid,t3ver_id,t3ver_label,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_count,t3ver_tstamp,t3_origuid';
  1231. $wsRes = $this->exec_getQuery('tt_news', $wsSelectconf);
  1232. $removeUids = array();
  1233. while ($wsRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($wsRes)) {
  1234. $orgUid = $wsRow['uid'];
  1235. $GLOBALS['TSFE']->sys_page->versionOL('tt_news',$wsRow);
  1236. if (!$wsRow['uid']) { // if versionOL returns nothing the record is not visible in the selected Workspace
  1237. $removeUids[] = $orgUid;
  1238. }
  1239. }
  1240. $removeUidList = implode(',',array_unique($removeUids));
  1241. // add list of not visible uids to the whereclause
  1242. if ($removeUidList) {
  1243. $selectConf['where'] .= ' AND tt_news.uid NOT IN ('.$removeUidList.')';
  1244. }
  1245. }
  1246. if ($this->conf['excludeAlreadyDisplayedNews']) {
  1247. if (!is_array($GLOBALS['TSFE']->displayedNews)) {
  1248. $GLOBALS['TSFE']->displayedNews = array();
  1249. } else {
  1250. $excludeUids = implode(',',$GLOBALS['TSFE']->displayedNews);
  1251. if ($excludeUids) {
  1252. $selectConf['where'] .= ' AND tt_news.uid NOT IN ('.$GLOBALS['TYPO3_DB']->cleanIntList($excludeUids).')';
  1253. }
  1254. }
  1255. }
  1256. // function Hook for processing the selectConf array
  1257. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['selectConfHook'])) {
  1258. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['selectConfHook'] as $_classRef) {
  1259. $_procObj = & t3lib_div::getUserObj($_classRef);
  1260. $selectConf = $_procObj->processSelectConfHook($this, $selectConf);
  1261. }
  1262. }
  1263. // debug($this->config['categoryMode'],'categoryMode');
  1264. // debug($this->catExclusive,'$this->catExclusive');
  1265. // debug($selectConf,'select_conf');
  1266. return $selectConf;
  1267. }
  1268. /**
  1269. * Generates an array, $this->pageArray of the pagerecords from $this->pid_list
  1270. *
  1271. * @return void
  1272. */
  1273. function generatePageArray() {
  1274. // Get pages
  1275. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1276. 'title,uid,author,author_email',
  1277. 'pages',
  1278. 'uid IN (' . $this->pid_list . ')');
  1279. $this->pageArray = array();
  1280. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1281. $this->pageArray[$row['uid']] = $row;
  1282. }
  1283. }
  1284. /**
  1285. * Fills in the markerArray with data for a news item
  1286. *
  1287. * @param array $row : result row for a news item
  1288. * @param array $textRenderObj : conf vars for the current template
  1289. * @return array $markerArray: filled marker array
  1290. */
  1291. function getItemMarkerArray ($row, $textRenderObj = 'displaySingle') {
  1292. // get config for current template part:
  1293. $lConf = $this->conf[$textRenderObj . '.'];
  1294. $this->local_cObj->start($row, 'tt_news');
  1295. $markerArray = array();
  1296. // get image markers
  1297. $markerArray = $this->getImageMarkers($markerArray, $row, $lConf, $textRenderObj);
  1298. // find categories for the current record
  1299. if (!is_array($this->categories[$row['uid']])) {
  1300. $this->categories[$row['uid']] = $this->getCategories($row['uid']);
  1301. }
  1302. $markerArray['###NEWS_CATEGORY_ROOTLINE###'] = '';
  1303. if ($this->conf['catRootline.']['showCatRootline']/* && $textRenderObj == 'displaySingle'*/) {
  1304. $markerArray['###NEWS_CATEGORY_ROOTLINE###'] = $this->getCategoryPath($this->categories[$row['uid']]);
  1305. }
  1306. // get markers and links for categories
  1307. $markerArray = $this->getCatMarkerArray($markerArray, $row, $lConf);
  1308. $markerArray['###NEWS_UID###'] = $row['uid'];
  1309. // show language label and/or flag
  1310. $markerArray['###NEWS_LANGUAGE###'] = '';
  1311. if ($this->conf['showLangLabels']) {
  1312. $L_uid = $row['sys_language_uid'];
  1313. $markerArray['###NEWS_LANGUAGE###'] = $this->langArr[$L_uid]['title'];
  1314. }
  1315. if ($this->langArr[$L_uid]['flag'] && $this->conf['showFlags']) {
  1316. $fImgFile = ($this->conf['flagPath']?$this->conf['flagPath']:'media/uploads/flag_') . $this->langArr[$L_uid]['flag'];
  1317. $fImgConf = $this->conf['flagImage.'];
  1318. $fImgConf['file'] = $fImgFile;
  1319. $flagImg = $this->local_cObj->IMAGE($fImgConf);
  1320. // debug ($fImgConf);
  1321. $markerArray['###NEWS_LANGUAGE###'] .= $flagImg;
  1322. }
  1323. $markerArray['###NEWS_TITLE###'] = $this->local_cObj->stdWrap($row['title'], $lConf['title_stdWrap.']);
  1324. $newsAuthor = $this->local_cObj->stdWrap($row['author']?$this->local_cObj->stdWrap($this->pi_getLL('preAuthor'), $lConf['preAuthor_stdWrap.']).$row['author']:'', $lConf['author_stdWrap.']);
  1325. $markerArray['###NEWS_AUTHOR###'] = $this->formatStr($newsAuthor);
  1326. $markerArray['###NEWS_EMAIL###'] = $this->local_cObj->stdWrap($row['author_email'], $lConf['email_stdWrap.']);
  1327. $markerArray['###NEWS_DATE###'] = $this->local_cObj->stdWrap($row['datetime'], $lConf['date_stdWrap.']);
  1328. $markerArray['###NEWS_TIME###'] = $this->local_cObj->stdWrap($row['datetime'], $lConf['time_stdWrap.']);
  1329. $markerArray['###NEWS_AGE###'] = $this->local_cObj->stdWrap($row['datetime'], $lConf['age_stdWrap.']);
  1330. $markerArray['###TEXT_NEWS_AGE###'] = $this->local_cObj->stdWrap($this->pi_getLL('textNewsAge'), $lConf['textNewsAge_stdWrap.']);
  1331. if ($this->config['croppingLenght']) {
  1332. $lConf['subheader_stdWrap.']['crop'] = $this->config['croppingLenght'];
  1333. }
  1334. $markerArray['###NEWS_SUBHEADER###'] = '';
  1335. if (!$this->piVars[$this->config['singleViewPointerName']] || $this->conf['subheaderOnAllSViewPages']) {
  1336. $markerArray['###NEWS_SUBHEADER###'] = $this->formatStr($this->local_cObj->stdWrap($row['short'], $lConf['subheader_stdWrap.']));
  1337. }
  1338. $markerArray['###NEWS_KEYWORDS###'] = $this->local_cObj->stdWrap($row['keywords'], $lConf['keywords_stdWrap.']);
  1339. if (!$this->piVars[$this->config['singleViewPointerName']]) {
  1340. if ($textRenderObj == 'displaySingle') {
  1341. // load the keywords the register 'newsKeywords' to access it from TS
  1342. $this->local_cObj->LOAD_REGISTER(array(
  1343. 'newsKeywords' => $row['keywords'],
  1344. 'newsSubheader' => $row['short']
  1345. ), '');
  1346. }
  1347. }
  1348. if ($textRenderObj == 'displaySingle' && !$row['no_auto_pb'] && $this->config['maxWordsInSingleView']>1) {
  1349. $row['bodytext'] = $this->insertPagebreaks($row['bodytext'],count(t3lib_div::trimExplode(' ',$row['short'],1)));
  1350. }
  1351. if (strpos($row['bodytext'],$this->config['pageBreakToken'])) {
  1352. if ($this->config['useMultiPageSingleView'] && $textRenderObj == 'displaySingle') {
  1353. $tmp = $this->makeMultiPageSView($row['bodytext'],$lConf);
  1354. $newscontent = $tmp[0];
  1355. $sViewPagebrowser = $tmp[1];
  1356. } else {
  1357. $newscontent = $this->formatStr($this->local_cObj->stdWrap(preg_replace('/'.$this->config['pageBreakToken'].'/','',$row['bodytext']), $lConf['content_stdWrap.']));
  1358. }
  1359. } else {
  1360. $newscontent = $this->formatStr($this->local_cObj->stdWrap($row['bodytext'], $lConf['content_stdWrap.']));
  1361. }
  1362. if ($this->conf['appendSViewPBtoContent']) {
  1363. $newscontent = $newscontent.$sViewPagebrowser;
  1364. $sViewPagebrowser = '';
  1365. }
  1366. $markerArray['###NEWS_CONTENT###'] = $newscontent;
  1367. $markerArray['###NEWS_SINGLE_PAGEBROWSER###'] = $sViewPagebrowser;
  1368. $markerArray['###MORE###'] = $this->pi_getLL('more');
  1369. // get title (or its language overlay) of the page where the backLink points to (this is done only in single view)
  1370. if ($this->config['backPid'] && $textRenderObj == 'displaySingle') {
  1371. if ($GLOBALS['TSFE']->sys_language_content) {
  1372. $p_res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1373. '*',
  1374. 'pages_language_overlay',
  1375. '1=1 AND pid=' . $this->config['backPid'] . ' AND sys_language_uid=' . $GLOBALS['TSFE']->sys_language_content);
  1376. $backP = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($p_res);
  1377. } else {
  1378. $backP = $this->pi_getRecord('pages', $this->config['backPid']);
  1379. }
  1380. }
  1381. // generate the string for the backLink. By setting the conf-parameter 'hscBackLink',
  1382. // you can switch whether the string is parsed through htmlspecialchars() or not.
  1383. $markerArray['###BACK_TO_LIST###'] = sprintf($this->pi_getLL('backToList', '', $this->conf['hscBackLink']), $backP['title']);
  1384. // get related news
  1385. if ($textRenderObj == 'displaySingle' || $this->conf['alwaysShowRelated']) {
  1386. $relatedNews = $this->getRelated($row['uid']);
  1387. }
  1388. $markerArray['###TEXT_RELATED###'] = '';
  1389. $markerArray['###NEWS_RELATED###'] = '';
  1390. if ($relatedNews) {
  1391. $rel_stdWrap = t3lib_div::trimExplode('|', $this->conf['related_stdWrap.']['wrap']);
  1392. $markerArray['###TEXT_RELATED###'] = $rel_stdWrap[0].$this->local_cObj->stdWrap($this->pi_getLL('textRelated'), $this->conf['relatedHeader_stdWrap.']);
  1393. $markerArray['###NEWS_RELATED###'] = $relatedNews.$rel_stdWrap[1];
  1394. }
  1395. // Links
  1396. $markerArray['###TEXT_LINKS###'] = '';
  1397. $markerArray['###NEWS_LINKS###'] = '';
  1398. if ($row['links']) {
  1399. $links_stdWrap = t3lib_div::trimExplode('|', $lConf['links_stdWrap.']['wrap']);
  1400. $newsLinks = $this->local_cObj->stdWrap($this->formatStr($row['links']), $lConf['linksItem_stdWrap.']);
  1401. $markerArray['###TEXT_LINKS###'] = $links_stdWrap[0].$this->local_cObj->stdWrap($this->pi_getLL('textLinks'), $lConf['linksHeader_stdWrap.']);
  1402. $markerArray['###NEWS_LINKS###'] = $newsLinks.$links_stdWrap[1];
  1403. }
  1404. // filelinks
  1405. $markerArray['###TEXT_FILES###'] = '';
  1406. $markerArray['###FILE_LINK###'] = '';
  1407. $markerArray['###NEWS_RSS2_ENCLOSURES###'] = '';
  1408. if ($row['news_files']) {
  1409. $files_stdWrap = t3lib_div::trimExplode('|', $this->conf['newsFiles_stdWrap.']['wrap']);
  1410. $markerArray['###TEXT_FILES###'] = $files_stdWrap[0].$this->local_cObj->stdWrap($this->pi_getLL('textFiles'), $this->conf['newsFilesHeader_stdWrap.']);
  1411. $fileArr = explode(',', $row['news_files']);
  1412. $files = '';
  1413. $rss2Enclousres = '';
  1414. while (list(, $val) = each($fileArr)) {
  1415. // fills the marker ###FILE_LINK### with the links to the atached files
  1416. $filelinks .= $this->local_cObj->filelink($val, $this->conf['newsFiles.']) ;
  1417. // <enclosure> support for RSS 2.0
  1418. if($this->theCode == 'XML') {
  1419. $path = trim($this->conf['newsFiles.']['path']);
  1420. $theFile = $path.$val;
  1421. if (@is_file($theFile)) {
  1422. $fileURL = $this->config['siteUrl'].$theFile;
  1423. $fileSize = filesize($theFile);
  1424. $fileMimeType = t3lib_htmlmail::getMimeType($fileURL);
  1425. $rss2Enclousres .= '<enclosure url="'.$fileURL.'" ';
  1426. $rss2Enclousres .= 'length ="'.$fileSize.'" ';
  1427. $rss2Enclousres .= 'type="'.$fileMimeType.'" />'."\n\t\t\t";
  1428. }
  1429. }
  1430. }
  1431. $markerArray['###FILE_LINK###'] = $filelinks.$files_stdWrap[1];
  1432. $markerArray['###NEWS_RSS2_ENCLOSURES###'] = trim($rss2Enclousres);
  1433. }
  1434. // show news with the same categories in SINGLE view
  1435. if ($textRenderObj == 'displaySingle' && $this->conf['showRelatedNewsByCategory'] && count($this->categories[$row['uid']])) {
  1436. // save some variables which are used to build the backLonk to the list view
  1437. $tmpcatExclusive = $this->catExclusive;
  1438. $tmpcode = $this->theCode;
  1439. $tmpBrowsePage = $this->piVars['pointer'];
  1440. unset($this->piVars['pointer']);
  1441. $tmpPS = $this->piVars['pS'];
  1442. unset($this->piVars['pS']);
  1443. $tmpPL = $this->piVars['pL'];
  1444. unset($this->piVars['pL']);
  1445. if(is_array($this->categories[$row['uid']])) {
  1446. $this->catExclusive = implode(array_keys($this->categories[$row['uid']]),',');
  1447. }
  1448. $this->config['categoryMode'] = 1;
  1449. $this->theCode = 'LIST';
  1450. $relNewsByCat = trim($this->displayList($row['uid']));
  1451. // restore variables
  1452. $this->theCode = $tmpcode;
  1453. $this->catExclusive = $tmpcatExclusive;
  1454. $this->piVars['pointer'] = $tmpBrowsePage;
  1455. $this->piVars['pS'] = $tmpPS;
  1456. $this->piVars['pL'] = $tmpPL;
  1457. }
  1458. $markerArray['###NEWS_RELATEDBYCATEGORY###'] = '';
  1459. $markerArray['###TEXT_RELATEDBYCATEGORY###'] = '';
  1460. if ($this->conf['showRelatedNewsByCategory'] && $relNewsByCat) {
  1461. $cat_rel_stdWrap = t3lib_div::trimExplode('|', $this->conf['relatedByCategory_stdWrap.']['wrap']);
  1462. $markerArray['###TEXT_RELATEDBYCATEGORY###'] = $cat_rel_stdWrap[0].$this->local_cObj->stdWrap($this->pi_getLL('textRelatedByCategory'), $this->conf['relatedByCategoryHeader_stdWrap.']);
  1463. $markerArray['###NEWS_RELATEDBYCATEGORY###'] = $relNewsByCat.$cat_rel_stdWrap[1];
  1464. }
  1465. // the both markers: ###ADDINFO_WRAP_B### and ###ADDINFO_WRAP_E### are only inserted, if there are any files, related news or links
  1466. $markerArray['###ADDINFO_WRAP_B###'] = '';
  1467. $markerArray['###ADDINFO_WRAP_E###'] = '';
  1468. if ($relatedNews || $row['links'] || $row['news_files'] || $relNewsByCat) {
  1469. $addInfo_stdWrap = t3lib_div::trimExplode('|', $lConf['addInfo_stdWrap.']['wrap']);
  1470. $markerArray['###ADDINFO_WRAP_B###'] = $addInfo_stdWrap[0];
  1471. $markerArray['###ADDINFO_WRAP_E###'] = $addInfo_stdWrap[1];
  1472. }
  1473. // Page fields:
  1474. $markerArray['###PAGE_UID###'] = $row['pid'];
  1475. $markerArray['###PAGE_TITLE###'] = $this->pageArray[$row['pid']]['title'];
  1476. $markerArray['###PAGE_AUTHOR###'] = $this->local_cObj->stdWrap($this->pageArray[$row['pid']]['author'], $lConf['author_stdWrap.']);
  1477. $markerArray['###PAGE_AUTHOR_EMAIL###'] = $this->local_cObj->stdWrap($this->pageArray[$row['pid']]['author_email'], $lConf['email_stdWrap.']);
  1478. // XML
  1479. if ($this->theCode == 'XML') {
  1480. $markerArray['###NEWS_TITLE###'] = $this->cleanXML($this->local_cObj->stdWrap($row['title'], $lConf['title_stdWrap.']));
  1481. $markerArray['###NEWS_AUTHOR###'] = $row['author_email']?'<author>'.$row['author_email'].'</author>':'';
  1482. if($this->conf['displayXML.']['xmlFormat'] == 'atom03' ||
  1483. $this->conf['displayXML.']['xmlFormat'] == 'atom1') {
  1484. $markerArray['###NEWS_AUTHOR###'] = $row['author'];
  1485. }
  1486. if($this->conf['displayXML.']['xmlFormat'] == 'rss2' ||
  1487. $this->conf['displayXML.']['xmlFormat'] == 'rss091') {
  1488. $markerArray['###NEWS_SUBHEADER###'] = $this->cleanXML($this->local_cObj->stdWrap($row['short'], $lConf['subheader_stdWrap.']));
  1489. } elseif ($this->conf['displayXML.']['xmlFormat'] == 'atom03' ||
  1490. $this->conf['displayXML.']['xmlFormat'] == 'atom1') {
  1491. //html doesn't need to be striped off in atom feeds
  1492. $lConf['subheader_stdWrap.']['stripHtml'] = 0;
  1493. $markerArray['###NEWS_SUBHEADER###'] = $this->local_cObj->stdWrap($row['short'], $lConf['subheader_stdWrap.']);
  1494. //just removing some whitespace to ease atom feed building
  1495. $markerArray['###NEWS_SUBHEADER###'] = str_replace('\n', '', $markerArray['###NEWS_SUBHEADER###']);
  1496. $markerArray['###NEWS_SUBHEADER###'] = str_replace('\r', '', $markerArray['###NEWS_SUBHEADER###']);
  1497. }
  1498. if($this->conf['displayXML.']['xmlFormat'] == 'rss2' ||
  1499. $this->conf['displayXML.']['xmlFormat'] == 'rss091') {
  1500. $markerArray['###NEWS_DATE###'] = date('D, d M Y H:i:s O', $row['datetime']);
  1501. } elseif ($this->conf['displayXML.']['xmlFormat'] == 'atom03' ||
  1502. $this->conf['displayXML.']['xmlFormat'] == 'atom1') {
  1503. $markerArray['###NEWS_DATE###'] = $this->getW3cDate($row['datetime']);
  1504. }
  1505. //dates for atom03
  1506. $markerArray['###NEWS_CREATED###'] = $this->getW3cDate($row['crdate']);
  1507. $markerArray['###NEWS_MODIFIED###'] = $this->getW3cDate($row['tstamp']);
  1508. if($this->conf['displayXML.']['xmlFormat'] == 'atom03' && !empty($this->conf['displayXML.']['xmlLang'])) {
  1509. $markerArray['###SITE_LANG###'] = ' xml:lang="'.$this->conf['displayXML.']['xmlLang'].'"';
  1510. }
  1511. $markerArray['###NEWS_ATOM_ENTRY_ID###'] = 'tag:'.substr($this->config['siteUrl'], 11, -1).','.date('Y', $row['crdate']).':article'.$row['uid'];
  1512. $markerArray['###SITE_LINK###'] = $this->config['siteUrl'];
  1513. }
  1514. // Adds hook for processing of extra item markers
  1515. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraItemMarkerHook'])) {
  1516. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['extraItemMarkerHook'] as $_classRef) {
  1517. $_procObj = & t3lib_div::getUserObj($_classRef);
  1518. $markerArray = $_procObj->extraItemMarkerProcessor($markerArray, $row, $lConf, $this);
  1519. }
  1520. }
  1521. // Pass to user defined function
  1522. if ($this->conf['itemMarkerArrayFunc']) {
  1523. $markerArray = $this->userProcess('itemMarkerArrayFunc', $markerArray);
  1524. }
  1525. return $markerArray;
  1526. }
  1527. /**
  1528. * inserts pagebreaks after a certain amount of words
  1529. *
  1530. * @param string text which can contain manully inserted 'pageBreakTokens'
  1531. * @param integer amount of words in the subheader (short). The lenght of the first page will be reduced by that amount of words added to the value of $this->conf['cropWordsFromFirstPage'].
  1532. * @return string the processed text
  1533. */
  1534. function insertPagebreaks($text,$firstPageWordCrop) {
  1535. $paragraphs = explode(chr(10), $text); // get paragraphs
  1536. $wtmp = array();
  1537. $firstPageCrop = $firstPageWordCrop+intval($this->conf['cropWordsFromFirstPage']);
  1538. $cc = 0; // wordcount
  1539. $isfirst = true; // first paragraph
  1540. while (list($k,$p) = each ($paragraphs)) {
  1541. $words = explode(' ', $p); // get words
  1542. $pArr = array();
  1543. $break = false;
  1544. foreach ($words as $w) {
  1545. #if (trim($w)=='&nbsp;') debug ($w);
  1546. if (strpos($w,$this->config['pageBreakToken'])) { // manually inserted pagebreaks
  1547. $cc = 0;
  1548. $pArr[] = $w;
  1549. $isfirst = false;
  1550. } elseif ($cc >= t3lib_div::intInRange($this->config['maxWordsInSingleView']-($isfirst && !$this->conf['subheaderOnAllSViewPages'] ? $firstPageCrop:0),0,$this->config['maxWordsInSingleView'])) {
  1551. if (trim($paragraphs[$k+1])=='&nbsp;') unset($paragraphs[$k+1]);
  1552. if (!$this->conf['useParagraphAsPagebreak'] && substr($w,-1)=='.') { // break at dot
  1553. $pArr[] = $w.$this->config['pageBreakToken'];
  1554. } else { // break at paragraph
  1555. $break = true;
  1556. $pArr[] = $w;
  1557. #$pArr[] = '<b> '.$cc.' </b>';
  1558. }
  1559. $cc = 0;
  1560. $isfirst = false;
  1561. } else {
  1562. $pArr[] = $w;
  1563. }
  1564. $cc++;
  1565. }
  1566. if ($break) { // add break at end of current paragraph
  1567. array_push ($pArr, $this->config['pageBreakToken']);
  1568. }
  1569. $wtmp[] = implode($pArr,' ');
  1570. }
  1571. $processedText = implode($wtmp,chr(10));
  1572. return $processedText;
  1573. }
  1574. /**
  1575. * divides the bodytext field of a news single view to pages and returns the part of the bodytext
  1576. * that is choosen by piVars[$pointerName]
  1577. *
  1578. * @param string the text with 'pageBreakTokens' in it
  1579. * @param array config array for the single view
  1580. * @return string the current bodytext part wrapped with stdWrap
  1581. */
  1582. function makeMultiPageSView($bodytext,$lConf) {
  1583. $pointerName=$this->config['singleViewPointerName'];
  1584. $pagenum = $this->piVars[$pointerName]?$this->piVars[$pointerName]:0;
  1585. $textArr = t3lib_div::trimExplode($this->config['pageBreakToken'],$bodytext,1);
  1586. $pagecount = count($textArr);
  1587. // render a pagebrowser for the single view
  1588. if ($pagecount > 1) {
  1589. // configure pagebrowser vars
  1590. $this->internal['res_count'] = $pagecount;
  1591. $this->internal['results_at_a_time'] = 1;
  1592. $this->internal['maxPages'] = $this->conf['pageBrowser.']['maxPages'];
  1593. if (!$this->conf['pageBrowser.']['showPBrowserText']) {
  1594. $this->LOCAL_LANG[$this->LLkey]['pi_list_browseresults_page'] = '';
  1595. }
  1596. $pagebrowser = $this->makePageBrowser(0, $this->conf['pageBrowser.']['tableParams'],$pointerName);
  1597. }
  1598. return array($this->formatStr($this->local_cObj->stdWrap($textArr[$pagenum], $lConf['content_stdWrap.'])),$pagebrowser);
  1599. }
  1600. /**
  1601. * this is a copy of the function pi_list_browseresults from class.tslib_piBase.php
  1602. * Returns a results browser. This means a bar of page numbers plus a "previous" and "next" link. For each entry in the bar the piVars "$pointerName" will be pointing to the "result page" to show.
  1603. * Using $this->piVars['$pointerName'] as pointer to the page to display
  1604. * Using $this->internal['res_count'], $this->internal['results_at_a_time'] and $this->internal['maxPages'] for count number, how many results to show and the max number of pages to include in the browse bar.
  1605. *
  1606. * @param boolean If set (default) the text "Displaying results..." will be show, otherwise not.
  1607. * @param string Attributes for the table tag which is wrapped around the table cells containing the browse links
  1608. * @param string varname for the pointer
  1609. * @return string Output HTML, wrapped in <div>-tags with a class attribute
  1610. */
  1611. function makePageBrowser($showResultCount=1,$tableParams='',$pointerName='pointer') {
  1612. if ($this->conf['useHRDates']) {
  1613. $tmpPS = $this->piVars['pS'];
  1614. unset($this->piVars['pS']);
  1615. $tmpPL = $this->piVars['pL'];
  1616. unset($this->piVars['pL']);
  1617. }
  1618. // Initializing variables:
  1619. $pointer=$this->piVars[$pointerName];
  1620. $count=$this->internal['res_count'];
  1621. $results_at_a_time = t3lib_div::intInRange($this->internal['results_at_a_time'],1,1000);
  1622. $maxPages = t3lib_div::intInRange($this->internal['maxPages'],1,100);
  1623. $max = t3lib_div::intInRange(ceil($count/$results_at_a_time),1,$maxPages);
  1624. $pointer=intval($pointer);
  1625. $links=array();
  1626. // Make browse-table/links:
  1627. if ($this->pi_alwaysPrev>=0) {
  1628. if ($pointer>0) {
  1629. $links[]='
  1630. <td nowrap="nowrap"><p>'.$this->pi_linkTP_keepPIvars($this->pi_getLL('pi_list_browseresults_prev','< Previous'),array($pointerName=>($pointer-1?$pointer-1:'')),$this->allowCaching).'</p></td>';
  1631. } elseif ($this->pi_alwaysPrev) {
  1632. $links[]='
  1633. <td nowrap="nowrap"><p>'.$this->pi_getLL('pi_list_browseresults_prev','< Previous').'</p></td>';
  1634. }
  1635. }
  1636. for($a=0;$a<$max;$a++) {
  1637. $links[]='
  1638. <td'.($pointer==$a?$this->pi_classParam('browsebox-SCell'):'').' nowrap="nowrap"><p>'.
  1639. $this->pi_linkTP_keepPIvars(trim($this->pi_getLL('pi_list_browseresults_page','Page').' '.($a+1)),array($pointerName=>($a?$a:'')),$this->allowCaching).
  1640. '</p></td>';
  1641. }
  1642. if ($pointer<ceil($count/$results_at_a_time)-1) {
  1643. $links[]='
  1644. <td nowrap="nowrap"><p>'.
  1645. $this->pi_linkTP_keepPIvars($this->pi_getLL('pi_list_browseresults_next','Next >'),array($pointerName=>$pointer+1),$this->allowCaching).
  1646. '</p></td>';
  1647. }
  1648. $pR1 = $pointer*$results_at_a_time+1;
  1649. $pR2 = $pointer*$results_at_a_time+$results_at_a_time;
  1650. $sTables = '
  1651. <!--
  1652. List browsing box:
  1653. -->
  1654. <div'.$this->pi_classParam('browsebox').'>'.
  1655. ($showResultCount ? '
  1656. <p>'.
  1657. ($this->internal['res_count'] ?
  1658. sprintf(
  1659. str_replace('###SPAN_BEGIN###','<span'.$this->pi_classParam('browsebox-strong').'>',$this->pi_getLL('pi_list_browseresults_displays','Displaying results ###SPAN_BEGIN###%s to %s</span> out of ###SPAN_BEGIN###%s</span>')),
  1660. $this->internal['res_count'] > 0 ? $pR1 : 0,
  1661. min(array($this->internal['res_count'],$pR2)),
  1662. $this->internal['res_count']
  1663. ) :
  1664. $this->pi_getLL('pi_list_browseresults_noResults','Sorry, no items were found.')).'</p>':''
  1665. ).'
  1666. <'.trim('table '.$tableParams).'>
  1667. <tr>
  1668. '.implode('',$links).'
  1669. </tr>
  1670. </table>
  1671. </div>';
  1672. if ($this->conf['useHRDates']) {
  1673. if ($tmpPS) $this->piVars['pS'] = $tmpPS;
  1674. if ($tmpPL) $this->piVars['pL'] = $tmpPL;
  1675. }
  1676. return $sTables;
  1677. }
  1678. /**
  1679. * gets categories and subcategories for a news record
  1680. *
  1681. * @param integer $uid : uid of the current news record
  1682. * @param [type] $getAll: ...
  1683. * @return array $categories: array of found categories
  1684. */
  1685. function getCategories($uid, $getAll=false) {
  1686. if (!$this->config['catOrderBy'] || $this->config['catOrderBy'] == 'sorting') {
  1687. $mmCatOrderBy = 'mmsorting';
  1688. } else {
  1689. $mmCatOrderBy = $this->config['catOrderBy'];
  1690. }
  1691. $res = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query (
  1692. 'tt_news_cat.*,tt_news_cat_mm.sorting AS mmsorting',
  1693. 'tt_news',
  1694. 'tt_news_cat_mm',
  1695. 'tt_news_cat',
  1696. ' AND tt_news_cat_mm.uid_local='.($uid?$uid:0).$this->SPaddWhere.($getAll?' AND tt_news_cat.deleted=0':$this->enableCatFields),
  1697. '',
  1698. $mmCatOrderBy);
  1699. $categories = array();
  1700. $maincat = 0;
  1701. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1702. $maincat .= ','.$row['uid'];
  1703. $row = array($row);
  1704. if ($this->conf['displaySubCategories'] && $this->config['useSubCategories']) {
  1705. $subCategories = array();
  1706. $subcats = implode(',', array_unique(explode(',', $this->getSubCategories($row[0]['uid']))));
  1707. $subres = $GLOBALS['TYPO3_DB']->exec_SELECTquery (
  1708. 'tt_news_cat.*',
  1709. 'tt_news_cat',
  1710. 'tt_news_cat.uid IN ('.($subcats?$subcats:0).')'.$this->SPaddWhere.$this->enableCatFields,
  1711. '',
  1712. 'tt_news_cat.'.$this->config['catOrderBy']);
  1713. while ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($subres)) {
  1714. $subCategories[] = $subrow;
  1715. }
  1716. $row = array_merge($row, $subCategories);
  1717. }
  1718. while (list (, $val) = each ($row)) {
  1719. $catTitle = '';
  1720. if ($GLOBALS['TSFE']->sys_language_content) {
  1721. // find translations of category titles
  1722. $catTitleArr = t3lib_div::trimExplode('|', $val['title_lang_ol']);
  1723. $catTitle = $catTitleArr[($GLOBALS['TSFE']->sys_language_content-1)];
  1724. }
  1725. $catTitle = $catTitle?$catTitle:$val['title'];
  1726. $categories[$val['uid']] = array(
  1727. 'title' => $catTitle,
  1728. 'image' => $val['image'],
  1729. 'shortcut' => $val['shortcut'],
  1730. 'shortcut_target' => $val['shortcut_target'],
  1731. 'single_pid' => $val['single_pid'],
  1732. 'catid' => $val['uid'],
  1733. 'parent_category' => (!t3lib_div::inList($maincat,$val['uid']) && $this->conf['displaySubCategories']?$val['parent_category']:''),
  1734. 'sorting' => $val['sorting'],
  1735. 'mmsorting' => $val['mmsorting'],
  1736. );
  1737. }
  1738. }
  1739. return $categories;
  1740. }
  1741. /**
  1742. * displays a category rootline by extending either the first category of a record or the category
  1743. * which is selected by piVars by their parent categories until a category with parent 0 is reached.
  1744. *
  1745. * @param array $categoryArray: list of categories which will be extended by subcategories
  1746. * @return string the category rootline
  1747. */
  1748. function getCategoryPath($categoryArray) {
  1749. if (is_array($categoryArray)) {
  1750. $pTmp = $GLOBALS['TSFE']->ATagParams;
  1751. $lConf = $this->conf['catRootline.'];
  1752. $mainCategory = array_shift($categoryArray);
  1753. $uid = $mainCategory['catid'];
  1754. $loopCheck = 100;
  1755. $theRowArray = array();
  1756. $output = array();
  1757. while ($uid!=0 && $loopCheck>0) {
  1758. $loopCheck--;
  1759. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1760. '*',
  1761. 'tt_news_cat',
  1762. 'uid='.intval($uid).$this->SPaddWhere.$this->enableCatFields);
  1763. if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1764. $uid = $row['parent_category'];
  1765. $theRowArray[] = $row;
  1766. } else {
  1767. break;
  1768. }
  1769. }
  1770. if (is_array($theRowArray)) {
  1771. krsort($theRowArray);
  1772. while(list($key,$val)=each($theRowArray)) {
  1773. if ($lConf['linkTitles']) {
  1774. $GLOBALS['TSFE']->ATagParams = ($pTmp?$pTmp.' ':'').'title="'.$val['title'].'"';
  1775. $output[] = $this->local_cObj->stdWrap($this->pi_linkToPage($val['title'], $val['shortcut'], $val['shortcut_target']), $lConf['title_stdWrap.']);
  1776. } else {
  1777. $output[] = $this->local_cObj->stdWrap($val['title'], $lConf['title_stdWrap.']);
  1778. }
  1779. }
  1780. }
  1781. $catRootline = implode($lConf['divider'],$output);
  1782. if ($catRootline) {
  1783. $catRootline = $this->local_cObj->stdWrap($catRootline, $lConf['catRootline_stdWrap.']);
  1784. }
  1785. $GLOBALS['TSFE']->ATagParams = $pTmp;
  1786. return $catRootline;
  1787. }
  1788. }
  1789. /**
  1790. * extends a given list of categories by their subcategories
  1791. *
  1792. * @param string $catlist: list of categories which will be extended by subcategories
  1793. * @param integer $cc: counter to detect recursion in nested categories
  1794. * @return string extended $catlist
  1795. */
  1796. function getSubCategories($catlist, $cc = 0) {
  1797. $pcatArr = array();
  1798. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1799. 'uid',
  1800. 'tt_news_cat',
  1801. 'tt_news_cat.parent_category IN ('.$catlist.')'.$this->SPaddWhere.$this->enableCatFields);
  1802. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1803. $cc++;
  1804. if ($cc > 1000) {
  1805. $GLOBALS['TT']->setTSlogMessage('tt_news: one or more recursive categories where found');
  1806. return implode(',', $pcatArr);
  1807. }
  1808. $subcats = $this->getSubCategories($row['uid'], $cc);
  1809. $subcats = $subcats?','.$subcats:'';
  1810. $pcatArr[] = $row['uid'].$subcats;
  1811. }
  1812. $catlist = implode(',', $pcatArr);
  1813. return $catlist;
  1814. }
  1815. /**
  1816. * Displays a hirarchical menu from tt_news categories
  1817. *
  1818. * @return string html for the category menu
  1819. */
  1820. function displayCatMenu() {
  1821. $lConf = $this->conf['displayCatMenu.'];
  1822. $mode = $lConf['mode']?$lConf['mode']:'tree';
  1823. $dontStartFromRootRecord = false;
  1824. if ($lConf['catOrderBy']) {
  1825. $this->config['catOrderBy'] = $lConf['catOrderBy'];
  1826. }
  1827. if ($this->catExclusive) {
  1828. $catlistWhere = ' AND tt_news_cat.uid'.($this->config['categoryMode'] < 0?' NOT':'').' IN ('.$this->catExclusive.')';
  1829. } else {
  1830. if ($lConf['excludeList']) {
  1831. $catlistWhere = ' AND tt_news_cat.uid NOT IN ('.implode(t3lib_div::intExplode(',',$lConf['excludeList']),',').')';
  1832. }
  1833. if($lConf['includeList']) {
  1834. $catlistWhere .= ' AND tt_news_cat.uid IN ('.implode(t3lib_div::intExplode(',',$lConf['includeList']),',').')';
  1835. }
  1836. }
  1837. if ($lConf['includeList'] || $this->catExclusive) {
  1838. // MOUNTS (in tree mode) must only contain the main/parent categories. Therefore it is required to filter out the subcategories from $this->catExclusive or $lConf['includeList']
  1839. $categoryMounts = ($this->catExclusive?$this->catExclusive:$lConf['includeList']);
  1840. $tmpres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1841. 'uid,parent_category',
  1842. 'tt_news_cat',
  1843. 'tt_news_cat.uid IN ('.$categoryMounts.')'.$this->SPaddWhere.$this->enableCatFields,
  1844. '',
  1845. 'tt_news_cat.'.$this->config['catOrderBy']);
  1846. $cleanedCategoryMounts = array();
  1847. if ($tmpres) {
  1848. while (($tmprow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($tmpres))) {
  1849. if (!t3lib_div::inList($categoryMounts,$tmprow['parent_category'])) {
  1850. $dontStartFromRootRecord = true;
  1851. $cleanedCategoryMounts[] = $tmprow['uid'];
  1852. }
  1853. }
  1854. }
  1855. }
  1856. switch ($mode) {
  1857. case 'nestedWraps';
  1858. $fields = '*';
  1859. $lConf = $this->conf['displayCatMenu.'];
  1860. if ($dontStartFromRootRecord) {
  1861. $addCatlistWhere = 'tt_news_cat.uid IN ('.implode(',',$cleanedCategoryMounts).')';
  1862. }
  1863. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1864. $fields,
  1865. 'tt_news_cat',
  1866. ($dontStartFromRootRecord?$addCatlistWhere:'tt_news_cat.parent_category=0').$this->SPaddWhere. $this->enableCatFields.$catlistWhere,
  1867. '',
  1868. 'tt_news_cat.'.$this->config['catOrderBy']);
  1869. $cArr = array();
  1870. $cArr[] = $this->local_cObj->stdWrap($this->pi_getLL('catmenuHeader','Select a category:'),$lConf['catmenuHeader_stdWrap.']);
  1871. while (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
  1872. $cArr[] = $row;
  1873. $subcats = $this->getSubCategoriesForMenu($row['uid'],$fields,$catlistWhere);
  1874. if (count($subcats)) {
  1875. $cArr[] = $subcats;
  1876. }
  1877. }
  1878. $content = $this->getCatMenuContent($cArr,$lConf);
  1879. break;
  1880. case 'tree':
  1881. $treeViewObj = t3lib_div::makeInstance('tx_ttnews_catmenu');
  1882. $treeViewObj->table = 'tt_news_cat';
  1883. $treeViewObj->init($this->SPaddWhere.$this->enableCatFields.$catlistWhere, $this->config['catOrderBy']);
  1884. $treeViewObj->backPath = TYPO3_mainDir;
  1885. $treeViewObj->parentField = 'parent_category';
  1886. $treeViewObj->expandAll = 1;
  1887. $treeViewObj->expandFirst = 1;
  1888. $treeViewObj->fieldArray = array('uid','title','title_lang_ol','description','image'); // those fields will be filled to the array $treeViewObj->tree
  1889. $treeViewObj->ext_IconMode = '1'; // no context menu on icons
  1890. $treeViewObj->title = $this->pi_getLL('catmenuHeader','Select a category:');
  1891. if ($dontStartFromRootRecord) {
  1892. $treeViewObj->MOUNTS = $cleanedCategoryMounts;
  1893. }
  1894. $treeViewObj->getTree(0);
  1895. $treeViewObj->tt_news_obj = &$this;
  1896. $content = $treeViewObj->getBrowsableTree();
  1897. break;
  1898. default:
  1899. // hook for user catmenu
  1900. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['userDisplayCatmenuHook'])) {
  1901. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['userDisplayCatmenuHook'] as $_classRef) {
  1902. $_procObj = & t3lib_div::getUserObj($_classRef);
  1903. $content = $_procObj->userDisplayCatmenu($lConf, $this);
  1904. }
  1905. }
  1906. break;
  1907. }
  1908. return $this->local_cObj->stdWrap($content, $lConf['catmenu_stdWrap.']);
  1909. }
  1910. /**
  1911. * This function calls itself recursively to convert the nested category array to HTML
  1912. *
  1913. * @param array $array_in: the nested categories
  1914. * @param array $lConf: TS configuration
  1915. * @param integer $l: level counter
  1916. * @return string HTML for the category menu
  1917. */
  1918. function getCatMenuContent($array_in,$lConf, $l=0) {
  1919. $titlefield = 'title';
  1920. if (is_array($array_in)) {
  1921. $result = '';
  1922. while (list($key,$val)=each($array_in)) {
  1923. if ($key == $titlefield||is_array($array_in[$key])) {
  1924. if ($l) {
  1925. $catmenuLevel_stdWrap = explode('|||',$this->local_cObj->stdWrap('|||',$lConf['catmenuLevel'.$l.'_stdWrap.']));
  1926. $result.= $catmenuLevel_stdWrap[0];
  1927. }
  1928. if (is_array($array_in[$key])) {
  1929. $result.=$this->getCatMenuContent($array_in[$key],$lConf,$l+1);
  1930. } elseif ($key == $titlefield) {
  1931. if ($GLOBALS['TSFE']->sys_language_content && $array_in['uid']) {
  1932. // get translations of category titles
  1933. $catTitleArr = t3lib_div::trimExplode('|', $array_in['title_lang_ol']);
  1934. $syslang = $GLOBALS['TSFE']->sys_language_content-1;
  1935. $val = $catTitleArr[$syslang]?$catTitleArr[$syslang]:$val;
  1936. }
  1937. // if (!$title) $title = $val;
  1938. $catSelLinkParams = ($this->conf['catSelectorTargetPid']?($this->config['itemLinkTarget']?$this->conf['catSelectorTargetPid'].' '.$this->config['itemLinkTarget']:$this->conf['catSelectorTargetPid']):$GLOBALS['TSFE']->id);
  1939. $pTmp = $GLOBALS['TSFE']->ATagParams;
  1940. if ($this->conf['displayCatMenu.']['insertDescrAsTitle']) {
  1941. $GLOBALS['TSFE']->ATagParams = ($pTmp?$pTmp.' ':'').'title="'.$array_in['description'].'"';
  1942. }
  1943. if ($array_in['uid']) {
  1944. if ($this->piVars['cat']==$array_in['uid']) {
  1945. $result.= $this->local_cObj->stdWrap($this->pi_linkTP_keepPIvars($val, array('cat' => $array_in['uid']), $this->allowCaching, 1, $catSelLinkParams),$lConf['catmenuItem_ACT_stdWrap.']);
  1946. } else {
  1947. $result.= $this->local_cObj->stdWrap($this->pi_linkTP_keepPIvars($val, array('cat' => $array_in['uid']), $this->allowCaching, 1, $catSelLinkParams),$lConf['catmenuItem_NO_stdWrap.']);
  1948. }
  1949. } else {
  1950. $result.= $this->pi_linkTP_keepPIvars($val, array(), $this->allowCaching, 1, $catSelLinkParams);
  1951. }
  1952. $GLOBALS['TSFE']->ATagParams = $pTmp;
  1953. }
  1954. if ($l) { $result.= $catmenuLevel_stdWrap[1]; }
  1955. }
  1956. }
  1957. }
  1958. return $result;
  1959. }
  1960. /**
  1961. * extends a given list of categories by their subcategories. This function returns a nested array with subcategories (the function getSubCategories() return only a commaseparated list of category UIDs)
  1962. *
  1963. * @param string $catlist: list of categories which will be extended by subcategories
  1964. * @param string $fields: list of fields for the query
  1965. * @param integer $cc: counter to detect recursion in nested categories
  1966. * @param [type] $cc: ...
  1967. * @return array all categories in a nested array
  1968. */
  1969. function getSubCategoriesForMenu ($catlist, $fields, $addWhere, $cc = 0) {
  1970. $pcatArr = array();
  1971. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  1972. $fields,
  1973. 'tt_news_cat',
  1974. 'tt_news_cat.parent_category IN ('.$catlist.')'.$this->SPaddWhere.$this->enableCatFields,
  1975. '',
  1976. 'tt_news_cat.'.$this->config['catOrderBy']);
  1977. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  1978. $cc++;
  1979. if ($cc > 10000) {
  1980. $GLOBALS['TT']->setTSlogMessage('tt_news: one or more recursive categories where found');
  1981. return $pcatArr;
  1982. }
  1983. $subcats = $this->getSubCategoriesForMenu($row['uid'], $fields, $addWhere, $cc);
  1984. $pcatArr[] = is_array($subcats)?array_merge($row,$subcats):'';
  1985. }
  1986. return $pcatArr;
  1987. }
  1988. /**
  1989. * Fills in the Category markerArray with data
  1990. *
  1991. * @param array $markerArray : partly filled marker array
  1992. * @param array $row : result row for a news item
  1993. * @param array $lConf : configuration for the current templatepart
  1994. * @return array $markerArray: filled markerarray
  1995. */
  1996. function getCatMarkerArray($markerArray, $row, $lConf) {
  1997. // clear the category text and image markers if the news item has no categories
  1998. $markerArray['###NEWS_CATEGORY_IMAGE###'] = '';
  1999. $markerArray['###NEWS_CATEGORY###'] = '';
  2000. $markerArray['###TEXT_CAT###'] = '';
  2001. $markerArray['###TEXT_CAT_LATEST###'] = '';
  2002. $markerArray['###CATWRAP_B###'] = '';
  2003. $markerArray['###CATWRAP_E###'] = '';
  2004. $pTmp = $GLOBALS['TSFE']->ATagParams;
  2005. if (count($this->categories[$row['uid']]) && ($this->config['catImageMode'] || $this->config['catTextMode'])) {
  2006. // wrap for all categories
  2007. $cat_stdWrap = t3lib_div::trimExplode('|', $lConf['category_stdWrap.']['wrap']);
  2008. $markerArray['###CATWRAP_B###'] = $cat_stdWrap[0];
  2009. $markerArray['###CATWRAP_E###'] = $cat_stdWrap[1];
  2010. $markerArray['###TEXT_CAT###'] = $this->pi_getLL('textCat');
  2011. $markerArray['###TEXT_CAT_LATEST###'] = $this->pi_getLL('textCatLatest');
  2012. $news_category = array();
  2013. $theCatImgCode = '';
  2014. $theCatImgCodeArray = array();
  2015. $catTextLenght = 0;
  2016. $wroteRegister = false;
  2017. foreach ($this->categories[$row['uid']] as $key => $val) {
  2018. // find categories, wrap them with links and collect them in the array $news_category.
  2019. $catTitle = htmlspecialchars($this->categories[$row['uid']][$key]['title']);
  2020. $GLOBALS['TSFE']->ATagParams = $pTmp.' title="'.$catTitle.'"';
  2021. if ($this->config['catTextMode'] == 0) {
  2022. $markerArray['###NEWS_CATEGORY###'] = '';
  2023. } elseif ($this->config['catTextMode'] == 1) {
  2024. // display but don't link
  2025. $news_category[] = $this->local_cObj->stdWrap($catTitle, $lConf[($this->categories[$row['uid']][$key]['parent_category'] > 0?'subCategoryTitleItem_stdWrap.':'categoryTitleItem_stdWrap.')]);
  2026. } elseif ($this->config['catTextMode'] == 2) {
  2027. // link to category shortcut
  2028. $news_category[] = $this->local_cObj->stdWrap($this->pi_linkToPage($catTitle, $this->categories[$row['uid']][$key]['shortcut'], $this->categories[$row['uid']][$key]['shortcut_target']), $lConf[($this->categories[$row['uid']][$key]['parent_category'] > 0?'subCategoryTitleItem_stdWrap.':'categoryTitleItem_stdWrap.')]);
  2029. } elseif ($this->config['catTextMode'] == 3) {
  2030. // act as category selector
  2031. $catSelLinkParams = ($this->conf['catSelectorTargetPid']?($this->config['itemLinkTarget']?$this->conf['catSelectorTargetPid'].' '.$this->config['itemLinkTarget']:$this->conf['catSelectorTargetPid']):$GLOBALS['TSFE']->id);
  2032. if ($this->conf['useHRDates']) {
  2033. $news_category[] = $this->local_cObj->stdWrap($this->pi_linkTP_keepPIvars($catTitle, array(
  2034. 'cat' => $this->categories[$row['uid']][$key]['catid'],
  2035. 'year' => ($this->piVars['year']?$this->piVars['year']:null),
  2036. 'month' => ($this->piVars['month']?$this->piVars['month']:null), 'backPid' => null, $this->pointerName => null), $this->allowCaching, 0, $catSelLinkParams), $lConf[($this->categories[$row['uid']][$key]['parent_category'] > 0?'subCategoryTitleItem_stdWrap.':'categoryTitleItem_stdWrap.')]);
  2037. } else {
  2038. $news_category[] = $this->local_cObj->stdWrap($this->pi_linkTP_keepPIvars($catTitle, array('cat' => $this->categories[$row['uid']][$key]['catid'], 'backPid' => null, $this->pointerName => null), $this->allowCaching, 0, $catSelLinkParams), $lConf[($this->categories[$row['uid']][$key]['parent_category'] > 0?'subCategoryTitleItem_stdWrap.':'categoryTitleItem_stdWrap.')]);
  2039. }
  2040. }
  2041. $catTextLenght += strlen($catTitle);
  2042. if ($this->config['catImageMode'] == 0 or empty($this->categories[$row['uid']][$key]['image'])) {
  2043. $markerArray['###NEWS_CATEGORY_IMAGE###'] = '';
  2044. } else {
  2045. $catPicConf = array();
  2046. $catPicConf['image.']['file'] = 'uploads/pics/' . $this->categories[$row['uid']][$key]['image'];
  2047. $catPicConf['image.']['file.']['maxW'] = intval($this->config['catImageMaxWidth']);
  2048. $catPicConf['image.']['file.']['maxH'] = intval($this->config['catImageMaxHeight']);
  2049. $catPicConf['image.']['stdWrap.']['spaceAfter'] = 0;
  2050. // clear the imagewrap to prevent category image from beeing wrapped in a table
  2051. $lConf['imageWrapIfAny'] = '';
  2052. if ($this->config['catImageMode'] != 1) {
  2053. if ($this->config['catImageMode'] == 2) {
  2054. // link to category shortcut
  2055. $sCpageId = $this->categories[$row['uid']][$key]['shortcut'];
  2056. $sCpage = $this->pi_getRecord('pages', $sCpageId); // get the title of the shortcut page
  2057. $catPicConf['image.']['altText'] = $sCpage['title']?$this->pi_getLL('altTextCatShortcut') . $sCpage['title']:
  2058. '';
  2059. $catPicConf['image.']['stdWrap.']['innerWrap'] = $this->pi_linkToPage('|', $this->categories[$row['uid']][$key]['shortcut'], $this->config['itemLinkTarget']);
  2060. }
  2061. if ($this->config['catImageMode'] == 3) {
  2062. // act as category selector
  2063. $catSelLinkParams = ($this->conf['catSelectorTargetPid']?($this->config['itemLinkTarget']?$this->conf['catSelectorTargetPid'].' '.$this->config['itemLinkTarget']:$this->conf['catSelectorTargetPid']):$GLOBALS['TSFE']->id);
  2064. $catPicConf['image.']['altText'] = $this->pi_getLL('altTextCatSelector') . $catTitle;
  2065. if ($this->conf['useHRDates']) {
  2066. $catPicConf['image.']['stdWrap.']['innerWrap'] = $this->pi_linkTP_keepPIvars('|', array(
  2067. 'cat' => $this->categories[$row['uid']][$key]['catid'],
  2068. 'year' => ($this->piVars['year']?$this->piVars['year']:null),
  2069. 'month' => ($this->piVars['month']?$this->piVars['month']:null), 'backPid' => null, $this->pointerName => null), $this->allowCaching, 0, $catSelLinkParams);
  2070. } else {
  2071. $catPicConf['image.']['stdWrap.']['innerWrap'] = $this->pi_linkTP_keepPIvars('|', array('cat' => $this->categories[$row['uid']][$key]['catid'], 'backPid' => null, $this->pointerName => null), $this->allowCaching, 0, $catSelLinkParams);
  2072. }
  2073. }
  2074. } else {
  2075. $catPicConf['image.']['altText'] = $this->categories[$row['uid']][$key]['title'];
  2076. }
  2077. // add linked category image to output array
  2078. $theCatImgCodeArray[] = $this->local_cObj->stdWrap($this->local_cObj->IMAGE($catPicConf['image.']), $lConf[($this->categories[$row['uid']][$key]['parent_category'] > 0?'subCategoryImgItem_stdWrap.':'categoryImgItem_stdWrap.')]);
  2079. }
  2080. if (!$wroteRegister) {
  2081. // Load the uid of the first assigned category to the register 'newsCategoryUid'
  2082. $this->local_cObj->LOAD_REGISTER(array('newsCategoryUid' => $this->categories[$row['uid']][$key]['catid']), '');
  2083. $wroteRegister = true;
  2084. }
  2085. }
  2086. if ($this->config['catTextMode'] != 0) {
  2087. $categoryDivider = $this->local_cObj->stdWrap($this->conf['categoryDivider'], $this->conf['categoryDivider_stdWrap.']);
  2088. $news_category = implode($categoryDivider, array_slice($news_category, 0, intval($this->config['maxCatTexts'])));
  2089. if ($this->config['catTextLength']) {
  2090. // crop the complete category titles if 'catTextLength' value is given
  2091. $markerArray['###NEWS_CATEGORY###'] = (strlen($news_category) < intval($this->config['catTextLength'])?$news_category:substr($news_category, 0, intval($this->config['catTextLength'])) . '...');
  2092. } else {
  2093. $markerArray['###NEWS_CATEGORY###'] = $this->local_cObj->stdWrap($news_category, $lConf['categoryTitles_stdWrap.']);
  2094. }
  2095. }
  2096. if ($this->config['catImageMode'] != 0) {
  2097. $theCatImgCode = implode('', array_slice($theCatImgCodeArray, 0, intval($this->config['maxCatImages']))); // downsize the image array to the 'maxCatImages' value
  2098. $markerArray['###NEWS_CATEGORY_IMAGE###'] = $this->local_cObj->stdWrap($theCatImgCode, $lConf['categoryImages_stdWrap.']);
  2099. }
  2100. // XML
  2101. if ($this->theCode == 'XML') {
  2102. $newsCategories = explode(', ', $news_category);
  2103. $xmlCategories = '';
  2104. foreach($newsCategories as $xmlCategory) {
  2105. $xmlCategories .= '<category>'.$this->local_cObj->stdWrap($xmlCategory, $lConf['categoryTitles_stdWrap.']).'</category>'."\n\t\t\t";
  2106. }
  2107. $markerArray['###NEWS_CATEGORY###'] = $xmlCategories;
  2108. }
  2109. }
  2110. $GLOBALS['TSFE']->ATagParams = $pTmp;
  2111. return $markerArray;
  2112. }
  2113. /**
  2114. * Fills the image markers with data. if a userfunction is given in "imageMarkerFunc",
  2115. * the marker Array is processed by this function.
  2116. *
  2117. * @param array $markerArray : partly filled marker array
  2118. * @param array $row : result row for a news item
  2119. * @param array $lConf : configuration for the current templatepart
  2120. * @param string $textRenderObj : name of the template subpart
  2121. * @return array $markerArray: filled markerarray
  2122. */
  2123. function getImageMarkers($markerArray, $row, $lConf, $textRenderObj) {
  2124. // overwrite image sizes from TS with the values from the content-element if they exist.
  2125. if ($this->config['FFimgH'] || $this->config['FFimgW']) {
  2126. $lConf['image.']['file.']['maxW'] = $this->config['FFimgW'];
  2127. $lConf['image.']['file.']['maxH'] = $this->config['FFimgH'];
  2128. }
  2129. if ($this->conf['imageMarkerFunc']) {
  2130. $markerArray = $this->userProcess('imageMarkerFunc', array($markerArray, $lConf));
  2131. } else {
  2132. $imageNum = isset($lConf['imageCount']) ? $lConf['imageCount']:1;
  2133. $imageNum = t3lib_div::intInRange($imageNum, 0, 100);
  2134. $theImgCode = '';
  2135. $imgs = t3lib_div::trimExplode(',', $row['image'], 1);
  2136. $imgsCaptions = explode(chr(10), $row['imagecaption']);
  2137. $imgsAltTexts = explode(chr(10), $row['imagealttext']);
  2138. $imgsTitleTexts = explode(chr(10), $row['imagetitletext']);
  2139. reset($imgs);
  2140. $cc = 0;
  2141. // remove first img from the image array in single view if the TSvar firstImageIsPreview is set
  2142. if (( (count($imgs) > 1 && $this->config['firstImageIsPreview'])
  2143. ||
  2144. (count($imgs) >= 1 && $this->config['forceFirstImageIsPreview'])
  2145. ) && $textRenderObj == 'displaySingle') {
  2146. array_shift($imgs);
  2147. array_shift($imgsCaptions);
  2148. array_shift($imgsAltTexts);
  2149. array_shift($imgsTitleTexts);
  2150. }
  2151. // get img array parts for single view pages
  2152. if ($this->piVars[$this->config['singleViewPointerName']]) {
  2153. $spage = $this->piVars[$this->config['singleViewPointerName']];
  2154. $astart = $imageNum*$spage;
  2155. $imgs = array_slice($imgs,$astart,$imageNum);
  2156. $imgsCaptions = array_slice($imgsCaptions,$astart,$imageNum);
  2157. $imgsAltTexts = array_slice($imgsAltTexts,$astart,$imageNum);
  2158. $imgsTitleTexts = array_slice($imgsTitleTexts,$astart,$imageNum);
  2159. }
  2160. while (list(, $val) = each($imgs)) {
  2161. if ($cc == $imageNum) break;
  2162. if ($val) {
  2163. $lConf['image.']['altText'] = $imgsAltTexts[$cc];
  2164. $lConf['image.']['titleText'] = $imgsTitleTexts[$cc];
  2165. $lConf['image.']['file'] = 'uploads/pics/' . $val;
  2166. }
  2167. $theImgCode .= $this->local_cObj->IMAGE($lConf['image.']) . $this->local_cObj->stdWrap($imgsCaptions[$cc], $lConf['caption_stdWrap.']);
  2168. $cc++;
  2169. }
  2170. $markerArray['###NEWS_IMAGE###'] = '';
  2171. if ($cc) {
  2172. $markerArray['###NEWS_IMAGE###'] = $this->local_cObj->wrap(trim($theImgCode), $lConf['imageWrapIfAny']);
  2173. } else {
  2174. $markerArray['###NEWS_IMAGE###'] = $this->local_cObj->stdWrap($markerArray['###NEWS_IMAGE###'],$lConf['image.']['noImage_stdWrap.']);
  2175. }
  2176. }
  2177. return $markerArray;
  2178. }
  2179. /**
  2180. * Find related news records and pages, add links to them and wrap them with stdWraps from TS.
  2181. *
  2182. * @param integer $uid of the current news record
  2183. * @return string html code for the related news list
  2184. */
  2185. function getRelated($uid) {
  2186. $lConf = $this->conf['getRelatedCObject.'];
  2187. // find visible categories and their singlePids
  2188. $catres = $GLOBALS['TYPO3_DB']->exec_SELECTquery (
  2189. 'tt_news_cat.uid,tt_news_cat.single_pid',
  2190. 'tt_news_cat',
  2191. '1=1'.$this->SPaddWhere.$this->enableCatFields);
  2192. $catTemp = array();
  2193. $sPidByCat = array();
  2194. while ($catrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($catres)) {
  2195. $sPidByCat[$catrow['uid']] = $catrow['single_pid'];
  2196. $catTemp[] = $catrow['uid'];
  2197. }
  2198. if ($this->conf['checkCategoriesOfRelatedNews']) {
  2199. $visibleCategories = implode($catTemp,',');
  2200. }
  2201. if ($this->conf['usePagesRelations']) {
  2202. $relPages = array();
  2203. $pres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  2204. 'uid,title,tstamp,description,subtitle,M.tablenames',
  2205. 'pages,tt_news_related_mm AS M',
  2206. 'pages.uid=M.uid_foreign AND M.uid_local=' . $uid . ' AND M.tablenames='.$GLOBALS['TYPO3_DB']->fullQuoteStr('pages', 'tt_news_related_mm').$this->cObj->enableFields('pages'),
  2207. '', 'title');
  2208. while ($prow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($pres)) {
  2209. if ($GLOBALS['TSFE']->sys_language_content) {
  2210. $prow = $GLOBALS['TSFE']->sys_page->getPageOverlay($prow, $GLOBALS['TSFE']->sys_language_content);
  2211. }
  2212. $relPages[] = array(
  2213. 'title' => $prow['title'],
  2214. 'datetime' => $prow['tstamp'],
  2215. 'archivedate' => 0,
  2216. 'type' => 1,
  2217. 'page' => $prow['uid'],
  2218. 'short' => $prow['subtitle']?$prow['subtitle']:$prow['description'],
  2219. 'tablenames' => $prow['tablenames']
  2220. );
  2221. }
  2222. }
  2223. $select_fields = 'DISTINCT uid, pid, title, short, datetime, archivedate, type, page, ext_url, sys_language_uid, l18n_parent, M.tablenames';
  2224. $where = 'tt_news.uid=M.uid_foreign AND M.uid_local=' . $uid . ' AND M.tablenames!='.$GLOBALS['TYPO3_DB']->fullQuoteStr('pages', 'tt_news_related_mm');
  2225. if ($lConf['groupBy']) {
  2226. $groupBy = trim($lConf['groupBy']);
  2227. }
  2228. if ($lConf['orderBy']) {
  2229. $orderBy = trim($lConf['orderBy']);
  2230. }
  2231. if ($this->conf['useBidirectionalRelations']) {
  2232. $where = '(('.$where.') OR (tt_news.uid=M.uid_local AND M.uid_foreign=' . $uid .' AND M.tablenames!='.$GLOBALS['TYPO3_DB']->fullQuoteStr('pages', 'tt_news_related_mm').'))';
  2233. }
  2234. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  2235. $select_fields,
  2236. 'tt_news,tt_news_related_mm AS M',
  2237. $where . $this->enableFields,
  2238. $groupBy,
  2239. $orderBy);
  2240. if ($res) {
  2241. $relrows = array();
  2242. while ($relrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
  2243. $currentCats = array();
  2244. if ($this->conf['checkCategoriesOfRelatedNews'] || $this->conf['useSPidFromCategory']) {
  2245. $currentCats = $this->getCategories($relrow['uid'],true);
  2246. }
  2247. if ($this->conf['checkCategoriesOfRelatedNews']) {
  2248. if (count($currentCats)) { // record has categories
  2249. foreach ($currentCats as $cUid) {
  2250. if (t3lib_div::inList($visibleCategories,$cUid['catid'])) { // if the record has at least one visible category assigned it will be shown
  2251. $relrows[$relrow['uid']] = $relrow;
  2252. }
  2253. }
  2254. } else { // record has NO categories
  2255. $relrows[$relrow['uid']] = $relrow;
  2256. }
  2257. } else {
  2258. $relrows[$relrow['uid']] = $relrow;
  2259. }
  2260. // check if there's a single pid for the first category of a news record and add 'sPidByCat' to the $relrows array.
  2261. if ($this->conf['useSPidFromCategory'] && count($currentCats) && $relrows[$relrow['uid']]) {
  2262. $firstcat = array_shift($currentCats);
  2263. if ($firstcat['catid'] && $sPidByCat[$firstcat['catid']]) {
  2264. $relrows[$relrow['uid']]['sPidByCat'] = $sPidByCat[$firstcat['catid']];
  2265. }
  2266. }
  2267. }
  2268. if (is_array($relPages[0]) && $this->conf['usePagesRelations']) {
  2269. $relrows = array_merge_recursive($relPages,$relrows);
  2270. }
  2271. $veryLocal_cObj = t3lib_div::makeInstance('tslib_cObj'); // Local cObj.
  2272. $lines = array();
  2273. foreach($relrows as $k => $row) {
  2274. if ($GLOBALS['TSFE']->sys_language_content && $row['tablenames']!='pages') {
  2275. $OLmode = ($this->sys_language_mode == 'strict' ? 'hideNonTranslated' : '');
  2276. $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_news', $row, $GLOBALS['TSFE']->sys_language_content, $OLmode);
  2277. if (!is_array($row)) continue;
  2278. }
  2279. $veryLocal_cObj->start($row, 'tt_news');
  2280. if ($row['type']!=1 && $row['type']!=2) { // only normal news
  2281. $queryString = explode('&', t3lib_div::implodeArrayForUrl('', t3lib_div::_GET())) ;
  2282. if ($queryString) {
  2283. while (list(, $val) = each($queryString)) {
  2284. $tmp = explode('=', $val);
  2285. $paramArray[$tmp[0]] = $val;
  2286. }
  2287. $excludeList = 'id,cHash,tx_ttnews[tt_news],tx_ttnews[backPid],L,tx_ttnews['.$this->config['singleViewPointerName'].']';
  2288. while (list($key, $val) = each($paramArray)) {
  2289. if (!$val || ($excludeList && t3lib_div::inList($excludeList, $key))) {
  2290. unset($paramArray[$key]);
  2291. }
  2292. }
  2293. $paramArray['tx_ttnews[tt_news]'] = 'tx_ttnews[tt_news]=' . $row['uid'];
  2294. if (!$this->conf['dontUseBackPid']) {
  2295. $paramArray['tx_ttnews[backPid]'] = 'tx_ttnews[backPid]=' . $this->config['backPid'];
  2296. }
  2297. $newsAddParams = '&' . implode($paramArray, '&');
  2298. // debug ($newsAddParams);
  2299. }
  2300. // load the parameter string into the register 'newsAddParams' to access it from TS
  2301. $veryLocal_cObj->LOAD_REGISTER(array('newsAddParams' => $newsAddParams), '');
  2302. $catSPid = false;
  2303. if ($row['sPidByCat'] && $this->conf['useSPidFromCategory']) {
  2304. $catSPid = $row['sPidByCat'];
  2305. }
  2306. $sPid = ($catSPid?$catSPid:$this->config['singlePid']);
  2307. $veryLocal_cObj->LOAD_REGISTER(array('newsSinglePid' => $sPid), '');
  2308. if (!$this->conf['getRelatedCObject.']['10.']['default.']['10.']['typolink.']['parameter'] || $catSPid) {
  2309. $this->conf['getRelatedCObject.']['10.']['default.']['10.']['typolink.']['parameter'] = $sPid;
  2310. }
  2311. }
  2312. $lines[] = $veryLocal_cObj->cObjGetSingle($this->conf['getRelatedCObject'], $this->conf['getRelatedCObject.'], 'getRelated');
  2313. }
  2314. return implode('', $lines);
  2315. }
  2316. }
  2317. /**
  2318. * Calls user function defined in TypoScript
  2319. *
  2320. * @param integer $mConfKey : if this value is empty the var $mConfKey is not processed
  2321. * @param mixed $passVar : this var is processed in the user function
  2322. * @return mixed the processed $passVar
  2323. */
  2324. function userProcess($mConfKey, $passVar) {
  2325. if ($this->conf[$mConfKey]) {
  2326. $funcConf = $this->conf[$mConfKey . '.'];
  2327. $funcConf['parentObj'] = & $this;
  2328. $passVar = $GLOBALS['TSFE']->cObj->callUserFunction($this->conf[$mConfKey], $funcConf, $passVar);
  2329. }
  2330. return $passVar;
  2331. }
  2332. /**
  2333. * returns the subpart name. if 'altMainMarkers.' are given this name is used instead of the default marker-name.
  2334. *
  2335. * @param string $subpartMarker : name of the subpart to be substituted
  2336. * @return string new name of the template subpart
  2337. */
  2338. function spMarker($subpartMarker) {
  2339. $sPBody = substr($subpartMarker, 3, -3);
  2340. $altSPM = '';
  2341. if (isset($this->conf['altMainMarkers.'])) {
  2342. $altSPM = trim($this->cObj->stdWrap($this->conf['altMainMarkers.'][$sPBody], $this->conf['altMainMarkers.'][$sPBody . '.']));
  2343. $GLOBALS['TT']->setTSlogMessage('Using alternative subpart marker for \'' . $subpartMarker . '\': ' . $altSPM, 1);
  2344. }
  2345. return $altSPM?$altSPM:
  2346. $subpartMarker;
  2347. }
  2348. /**
  2349. * Generates a search where clause.
  2350. *
  2351. * @param string $sw: searchword(s)
  2352. * @return string querypart
  2353. */
  2354. function searchWhere($sw) {
  2355. $where = $this->cObj->searchWhere($sw, $this->searchFieldList, 'tt_news');
  2356. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['searchWhere'])) {
  2357. foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['tt_news']['searchWhere'] as $_classRef) {
  2358. $_procObj = & t3lib_div::getUserObj($_classRef);
  2359. $where = $_procObj->searchWhere($this, $sw, $where);
  2360. }
  2361. }
  2362. return $where;
  2363. }
  2364. /**
  2365. * Format string with general_stdWrap from configuration
  2366. *
  2367. * @param string $string to wrap
  2368. * @return string wrapped string
  2369. */
  2370. function formatStr($str) {
  2371. if (is_array($this->conf['general_stdWrap.'])) {
  2372. $str = $this->local_cObj->stdWrap($str, $this->conf['general_stdWrap.']);
  2373. }
  2374. return $str;
  2375. }
  2376. /**
  2377. * Returns alternating layouts
  2378. *
  2379. * @param string $html code of the template subpart
  2380. * @param integer $number of alternatingLayouts
  2381. * @param string $name of the content-markers in this template-subpart
  2382. * @return array html code for alternating content markers
  2383. */
  2384. function getLayouts($templateCode, $alternatingLayouts, $marker) {
  2385. $out = array();
  2386. for($a = 0; $a < $alternatingLayouts; $a++) {
  2387. $m = '###' . $marker . ($a?'_' . $a:'') . '###';
  2388. if (strstr($templateCode, $m)) {
  2389. $out[] = $GLOBALS['TSFE']->cObj->getSubpart($templateCode, $m);
  2390. } else {
  2391. break;
  2392. }
  2393. }
  2394. return $out;
  2395. }
  2396. /**
  2397. * fills the internal array '$this->langArr' with the available syslanguages
  2398. *
  2399. * @return void
  2400. */
  2401. function initLanguages () {
  2402. $lres = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  2403. '*',
  2404. 'sys_language',
  2405. '1=1' . $this->cObj->enableFields('sys_language'));
  2406. $this->langArr = array();
  2407. while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($lres)) {
  2408. $this->langArr[$row['uid']] = $row;
  2409. }
  2410. }
  2411. /**
  2412. * initialize category related vars and add subcategories to the category selection
  2413. *
  2414. * @return void
  2415. */
  2416. function initCategoryVars() {
  2417. $confArr = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['tt_news']);
  2418. if ($confArr['useStoragePid']) {
  2419. $storagePid = $GLOBALS['TSFE']->getStorageSiterootPids();
  2420. $this->SPaddWhere = ' AND tt_news_cat.pid IN (' . $storagePid['_STORAGE_PID'] . ')';
  2421. }
  2422. if ($this->conf['catExcludeList']) {
  2423. $this->SPaddWhere .= ' AND tt_news_cat.uid NOT IN ('.$this->conf['catExcludeList'].')';
  2424. }
  2425. $this->enableCatFields = $this->cObj->enableFields('tt_news_cat');
  2426. $useSubCategories = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'useSubCategories', 'sDEF');
  2427. $this->config['useSubCategories'] = (strcmp($useSubCategories,'') ? $useSubCategories : $this->conf['useSubCategories']);
  2428. // global ordering for categories, Can be overwritten later by catOrderBy for a certain content element
  2429. $catOrderBy = trim($this->conf['catOrderBy']);
  2430. $this->config['catOrderBy'] = $catOrderBy?$catOrderBy:'sorting';
  2431. // categoryModes are: 0=display all categories, 1=display selected categories, -1=display deselected categories
  2432. $categoryMode = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'categoryMode', 'sDEF');
  2433. $this->config['categoryMode'] = $categoryMode ? $categoryMode: intval($this->conf['categoryMode']);
  2434. // catselection holds only the uids of the categories selected by GETvars
  2435. if ($this->piVars['cat']) {
  2436. // catselection holds only the uids of the categories selected by GETvars
  2437. $this->config['catSelection'] = $this->checkRecords($this->piVars['cat']);
  2438. if ($this->config['useSubCategories'] && $this->config['catSelection']) {
  2439. // get subcategories for selection from getVars
  2440. $subcats = $this->getSubCategories($this->config['catSelection']);
  2441. $this->config['catSelection'] = implode(',', array_unique(explode(',', $this->config['catSelection'].($subcats?','.$subcats:''))));
  2442. }
  2443. }
  2444. $catExclusive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'categorySelection', 'sDEF');
  2445. $catExclusive = $catExclusive?$catExclusive:trim($this->cObj->stdWrap($this->conf['categorySelection'], $this->conf['categorySelection.']));
  2446. $this->catExclusive = $this->config['categoryMode']?$catExclusive:0; // ignore cat selection if categoryMode isn't set
  2447. $this->catExclusive = $this->checkRecords($this->catExclusive);
  2448. // store the actually selected categories because we need them for the comparison in categoryMode 2 and -2
  2449. $this->actuallySelectedCategories = $this->catExclusive;
  2450. // get subcategories
  2451. if ($this->config['useSubCategories'] && $this->catExclusive) {
  2452. $subcats = $this->getSubCategories($this->catExclusive);
  2453. $this->catExclusive = implode(',', array_unique(explode(',', $this->catExclusive.($subcats?','.$subcats:''))));
  2454. }
  2455. // get more category fields from FF or TS
  2456. $fields = explode(',', 'catImageMode,catTextMode,catImageMaxWidth,catImageMaxHeight,maxCatImages,catTextLength,maxCatTexts');
  2457. foreach($fields as $key) {
  2458. $value = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], $key, 's_category');
  2459. $this->config[$key] = (is_numeric($value)?$value:$this->conf[$key]);
  2460. }
  2461. }
  2462. /**
  2463. * Checks the visibility of a list of category-records
  2464. *
  2465. * @param string $recordlist: comma seperated list of category uids
  2466. * @return string $clearedlist: the cleared list
  2467. */
  2468. function checkRecords($recordlist) {
  2469. if ($recordlist) {
  2470. $temp = t3lib_div::trimExplode(',', $recordlist,1);
  2471. // debug($temp);
  2472. $newtemp = array();
  2473. while (list(, $val) = each($temp)) {
  2474. if ($val === '0') $this->nocat = true;
  2475. $val = intval($val);
  2476. if ($val) {
  2477. $test = $GLOBALS['TSFE']->sys_page->checkRecord('tt_news_cat',$val,1); // test, if the record is visible
  2478. if ($test) {
  2479. $newtemp[] = $val;
  2480. }
  2481. }
  2482. }
  2483. reset($newtemp);
  2484. if (!count($newtemp)){
  2485. // select category 'null' if no visible category was found
  2486. $newtemp[] = 'null';
  2487. }
  2488. $clearedlist = implode(',', $newtemp);
  2489. return $clearedlist;
  2490. }
  2491. }
  2492. /**
  2493. * read the template file, fill in global wraps and markers and write the result
  2494. * to '$this->templateCode'
  2495. *
  2496. * @return void
  2497. */
  2498. function initTemplate() {
  2499. // read template-file and fill and substitute the Global Markers
  2500. $templateflex_file = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'template_file', 's_template');
  2501. if ($templateflex_file) {
  2502. if (false === strpos($templateflex_file, '/')) {
  2503. $templateflex_file = 'uploads/tx_ttnews/' . $templateflex_file;
  2504. }
  2505. $this->templateCode = $this->cObj->fileResource($templateflex_file);
  2506. }
  2507. else {
  2508. $this->templateCode = $this->cObj->fileResource($this->conf['templateFile']);
  2509. }
  2510. $splitMark = md5(microtime(true));
  2511. $globalMarkerArray = array();
  2512. list($globalMarkerArray['###GW1B###'], $globalMarkerArray['###GW1E###']) = explode($splitMark, $this->cObj->stdWrap($splitMark, $this->conf['wrap1.']));
  2513. list($globalMarkerArray['###GW2B###'], $globalMarkerArray['###GW2E###']) = explode($splitMark, $this->cObj->stdWrap($splitMark, $this->conf['wrap2.']));
  2514. list($globalMarkerArray['###GW3B###'], $globalMarkerArray['###GW3E###']) = explode($splitMark, $this->cObj->stdWrap($splitMark, $this->conf['wrap3.']));
  2515. $globalMarkerArray['###GC1###'] = $this->cObj->stdWrap($this->conf['color1'], $this->conf['color1.']);
  2516. $globalMarkerArray['###GC2###'] = $this->cObj->stdWrap($this->conf['color2'], $this->conf['color2.']);
  2517. $globalMarkerArray['###GC3###'] = $this->cObj->stdWrap($this->conf['color3'], $this->conf['color3.']);
  2518. $globalMarkerArray['###GC4###'] = $this->cObj->stdWrap($this->conf['color4'], $this->conf['color4.']);
  2519. $this->templateCode = $this->cObj->substituteMarkerArray($this->templateCode, $globalMarkerArray);
  2520. }
  2521. /**
  2522. * extends the pid_list given from $conf or FF recursively by the pids of the subpages
  2523. * generates an array from the pagetitles of those pages
  2524. *
  2525. * @return void
  2526. */
  2527. function initPidList () {
  2528. // pid_list is the pid/list of pids from where to fetch the news items.
  2529. $pid_list = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'pages', 'sDEF');
  2530. $pid_list = $pid_list?$pid_list:
  2531. trim($this->cObj->stdWrap($this->conf['pid_list'], $this->conf['pid_list.']));
  2532. $pid_list = $pid_list ? implode(t3lib_div::intExplode(',', $pid_list), ','):
  2533. $GLOBALS['TSFE']->id;
  2534. $recursive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'recursive', 'sDEF');
  2535. $recursive = is_numeric($recursive)?$recursive:
  2536. $this->cObj->stdWrap($this->conf['recursive'], $this->conf['recursive.']);
  2537. // extend the pid_list by recursive levels
  2538. $this->pid_list = $this->pi_getPidList($pid_list, $recursive);
  2539. $this->pid_list = $this->pid_list?$this->pid_list:0;
  2540. // generate array of page titles
  2541. $this->generatePageArray();
  2542. }
  2543. /**
  2544. * builds the XML header (array of markers to substitute)
  2545. *
  2546. * @return array the filled XML header markers
  2547. */
  2548. function getXmlHeader() {
  2549. $markerArray = array();
  2550. $markerArray['###SITE_TITLE###'] = $this->conf['displayXML.']['xmlTitle'];
  2551. $markerArray['###SITE_LINK###'] = $this->config['siteUrl'];
  2552. $markerArray['###SITE_DESCRIPTION###'] = $this->conf['displayXML.']['xmlDesc'];
  2553. if(!empty($markerArray['###SITE_DESCRIPTION###'])) {
  2554. if($this->conf['displayXML.']['xmlFormat'] == 'atom03') {
  2555. $markerArray['###SITE_DESCRIPTION###'] = '<tagline>'.$markerArray['###SITE_DESCRIPTION###'].'</tagline>';
  2556. } elseif($this->conf['displayXML.']['xmlFormat'] == 'atom1') {
  2557. $markerArray['###SITE_DESCRIPTION###'] = '<subtitle>'.$markerArray['###SITE_DESCRIPTION###'].'</subtitle>';
  2558. }
  2559. }
  2560. $markerArray['###SITE_LANG###'] = $this->conf['displayXML.']['xmlLang'];
  2561. if($this->conf['displayXML.']['xmlFormat'] == 'rss2') {
  2562. $markerArray['###SITE_LANG###'] = '<language>'.$markerArray['###SITE_LANG###'].'</language>';
  2563. } elseif($this->conf['displayXML.']['xmlFormat'] == 'atom03') {
  2564. $markerArray['###SITE_LANG###'] = ' xml:lang="'.$markerArray['###SITE_LANG###'].'"';
  2565. }
  2566. if(empty($this->conf['displayXML.']['xmlLang'])) {
  2567. $markerArray['###SITE_LANG###'] = '';
  2568. }
  2569. $markerArray['###IMG###'] = t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST') . '/' . $this->conf['displayXML.']['xmlIcon'];
  2570. $imgFile = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/' . $this->conf['displayXML.']['xmlIcon'];
  2571. $imgSize = is_file($imgFile)?getimagesize($imgFile):
  2572. '';
  2573. $markerArray['###IMG_W###'] = $imgSize[0];
  2574. $markerArray['###IMG_H###'] = $imgSize[1];
  2575. $markerArray['###NEWS_WEBMASTER###'] = $this->conf['displayXML.']['xmlWebMaster'];
  2576. $markerArray['###NEWS_MANAGINGEDITOR###'] = $this->conf['displayXML.']['xmlManagingEditor'];
  2577. $selectConf = Array();
  2578. $selectConf['pidInList'] = $this->pid_list;
  2579. // select only normal news (type=0) for the RSS feed. You can override this with other types with the TS-var 'xmlNewsTypes'
  2580. $selectConf['selectFields'] = 'max(datetime) as maxval';
  2581. $res = $this->exec_getQuery('tt_news', $selectConf);
  2582. $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
  2583. // optional tags
  2584. if ($this->conf['displayXML.']['xmlLastBuildDate']) {
  2585. $markerArray['###NEWS_LASTBUILD###'] = '<lastBuildDate>' . date('D, d M Y H:i:s O', $row['maxval']) . '</lastBuildDate>';
  2586. } else {
  2587. $markerArray['###NEWS_LASTBUILD###'] = '';
  2588. }
  2589. if($this->conf['displayXML.']['xmlFormat'] == 'atom03' ||
  2590. $this->conf['displayXML.']['xmlFormat'] == 'atom1') {
  2591. $markerArray['###NEWS_LASTBUILD###'] = $this->getW3cDate($row['maxval']);
  2592. }
  2593. if ($this->conf['displayXML.']['xmlWebMaster']) {
  2594. $markerArray['###NEWS_WEBMASTER###'] = '<webMaster>' . $this->conf['displayXML.']['xmlWebMaster'] . '</webMaster>';
  2595. } else {
  2596. $markerArray['###NEWS_WEBMASTER###'] = '';
  2597. }
  2598. if ($this->conf['displayXML.']['xmlManagingEditor']) {
  2599. $markerArray['###NEWS_MANAGINGEDITOR###'] = '<managingEditor>' . $this->conf['displayXML.']['xmlManagingEditor'] . '</managingEditor>';
  2600. } else {
  2601. $markerArray['###NEWS_MANAGINGEDITOR###'] = '';
  2602. }
  2603. if ($this->conf['displayXML.']['xmlCopyright']) {
  2604. if($this->conf['displayXML.']['xmlFormat'] == 'atom1') {
  2605. $markerArray['###NEWS_COPYRIGHT###'] = '<rights>' . $this->conf['displayXML.']['xmlCopyright'] . '</rights>';
  2606. } else {
  2607. $markerArray['###NEWS_COPYRIGHT###'] = '<copyright>' . $this->conf['displayXML.']['xmlCopyright'] . '</copyright>';
  2608. }
  2609. } else {
  2610. $markerArray['###NEWS_COPYRIGHT###'] = '';
  2611. }
  2612. $charset = ($GLOBALS['TSFE']->metaCharset?$GLOBALS['TSFE']->metaCharset:'iso-8859-1');
  2613. if ($this->conf['displayXML.']['xmlDeclaration']) {
  2614. $markerArray['###XML_DECLARATION###'] = trim($this->conf['displayXML.']['xmlDeclaration']);
  2615. } else {
  2616. $markerArray['###XML_DECLARATION###'] = '<?xml version="1.0" encoding="'.$charset.'"?>';
  2617. }
  2618. // promoting TYPO3 in atom feeds, supress the subversion
  2619. $version = explode('.',($GLOBALS['TYPO3_VERSION']?$GLOBALS['TYPO3_VERSION']:$GLOBALS['TYPO_VERSION']));
  2620. unset($version[2]);
  2621. $markerArray['###TYPO3_VERSION###'] = implode($version,'.');
  2622. return $markerArray;
  2623. }
  2624. /**
  2625. * Generates the date format needed for Atom feeds
  2626. * see: http://www.w3.org/TR/NOTE-datetime (same as ISO 8601)
  2627. * in php5 it would be so easy: date('c', $row['datetime']);
  2628. *
  2629. * @param integer the datetime value to be converted to w3c format
  2630. * @return string datetime in w3c format
  2631. */
  2632. function getW3cDate($datetime) {
  2633. $offset = date('Z', $datetime) / 3600;
  2634. if($offset < 0) {
  2635. $offset *= -1;
  2636. if($offset < 10) {
  2637. $offset = '0'.$offset;
  2638. }
  2639. $offset = '-'.$offset;
  2640. } elseif ($offset == 0) {
  2641. $offset = '+00';
  2642. } elseif ($offset < 10) {
  2643. $offset = '+0'.$offset;
  2644. } else {
  2645. $offset = '+'.$offset;
  2646. }
  2647. return strftime('%Y-%m-%dT%H:%M:%S', $datetime).$offset.':00';
  2648. }
  2649. /**
  2650. * this the old [DEPRECIATED] function for XML news feed.
  2651. *
  2652. * @param string $content : ...
  2653. * @param array $conf : configuration array from TS
  2654. * @return string news content as xml string
  2655. */
  2656. function main_xmlnewsfeed($content, $conf) {
  2657. $className = t3lib_div::makeInstanceClassName('t3lib_xml');
  2658. $xmlObj = new $className('typo3_xmlnewsfeed');
  2659. $xmlObj->setRecFields('tt_news', 'title,datetime'); // More fields here...
  2660. $xmlObj->renderHeader();
  2661. $xmlObj->renderRecords('tt_news', $this->getStoriesResult());
  2662. $xmlObj->renderFooter();
  2663. return $xmlObj->getResult();
  2664. }
  2665. /**
  2666. * returns the db-result for the news-item displayed by the xmlnewsfeed function
  2667. *
  2668. * @return pointer MySQL select result pointer / DBAL object
  2669. */
  2670. function getStoriesResult() {
  2671. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
  2672. '*',
  2673. 'tt_news',
  2674. 'pid=' . intval($GLOBALS['TSFE']->id) . $this->cObj->enableFields('tt_news'),
  2675. '',
  2676. 'datetime DESC');
  2677. return $res;
  2678. }
  2679. /**
  2680. * cleans the content for rss feeds. removes '&nbsp;' and '?;' (dont't know if the scond one matters in real-life).
  2681. * The rest of the cleaning/character-conversion is done by the stdWrap functions htmlspecialchars,stripHtml and csconv.
  2682. * For details see http://typo3.org/documentation/document-library/doc_core_tsref/stdWrap/
  2683. *
  2684. * @param string $str: input string to clean
  2685. * @return string the cleaned string
  2686. */
  2687. function cleanXML($str) {
  2688. $cleanedStr = preg_replace(
  2689. array('/&nbsp;/', '/&;/', '/</', '/>/'),
  2690. array(' ', '&amp;;', '&lt;', '&gt;'),
  2691. $str);
  2692. return $cleanedStr;
  2693. }
  2694. /**
  2695. * Converts the piVars 'pS' and 'pL' to a human readable format which will be filled to
  2696. * the piVars 'year' and 'month'.
  2697. *
  2698. * @return void
  2699. */
  2700. function convertDates() {
  2701. //readable archivedates
  2702. if ($this->piVars['year'] || $this->piVars['month']) {
  2703. $this->arcExclusive = 1;
  2704. }
  2705. if (!$this->piVars['year'] && $this->piVars['pS']) {
  2706. $this->piVars['year'] = date('Y',$this->piVars['pS']);
  2707. }
  2708. if (!$this->piVars['month'] && $this->piVars['pS']) {
  2709. $this->piVars['month'] = date('m',$this->piVars['pS']);
  2710. }
  2711. if (!$this->piVars['day'] && $this->piVars['pS']) {
  2712. $this->piVars['day'] = date('j',$this->piVars['pS']);
  2713. }
  2714. if ($this->piVars['year'] || $this->piVars['month'] || $this->piVars['day']) {
  2715. $mon = ($this->piVars['month'] ? $this->piVars['month'] : 1);
  2716. $day = ($this->piVars['day'] ? $this->piVars['day'] : 1);
  2717. $this->piVars['pS'] = mktime (0, 0, 0, $mon, $day, $this->piVars['year']);
  2718. switch ($this->config['archiveMode']) {
  2719. case 'month':
  2720. $this->piVars['pL'] = mktime (0, 0, 0, $mon+1, 1, $this->piVars['year'])-$this->piVars['pS']-1;
  2721. break;
  2722. case 'quarter':
  2723. $this->piVars['pL'] = mktime (0, 0, 0, $mon+3, 1, $this->piVars['year'])-$this->piVars['pS']-1;
  2724. break;
  2725. case 'year':
  2726. $this->piVars['pL'] = mktime (0, 0, 0, 1, 1, $this->piVars['year']+1)-$this->piVars['pS']-1;
  2727. unset($this->piVars['month']);
  2728. break;
  2729. }
  2730. }
  2731. }
  2732. /**
  2733. * converts the datetime of a record into variables you can use in realurl
  2734. *
  2735. * @param integer the timestamp to convert into a HR date
  2736. * @return void
  2737. */
  2738. function getHrDateSingle($tstamp) {
  2739. $this->piVars['year'] = date('Y',$tstamp);
  2740. $this->piVars['month'] = date('m',$tstamp);
  2741. if (!$this->conf['useHRDatesSingleWithoutDay']) {
  2742. $this->piVars['day'] = date('d',$tstamp);
  2743. }
  2744. }
  2745. /**
  2746. * returns a help message wich will be displayed on the website when no "code" is given or when the given "code" doesn't exist.
  2747. *
  2748. * @return string HTML code for the help message
  2749. */
  2750. function displayFEHelp() {
  2751. $langKey = strtoupper($GLOBALS['TSFE']->config['config']['language']);
  2752. $helpTemplate = $this->cObj->fileResource('EXT:tt_news/pi/news_help.tmpl');
  2753. // Get language version of the help-template
  2754. $helpTemplate_lang = '';
  2755. if ($langKey) {
  2756. $helpTemplate_lang = $this->getNewsSubpart($helpTemplate, "###TEMPLATE_" . $langKey . '###');
  2757. }
  2758. $helpTemplate = $helpTemplate_lang ? $helpTemplate_lang : $this->getNewsSubpart($helpTemplate, '###TEMPLATE_DEFAULT###');
  2759. // Markers and substitution:
  2760. $markerArray['###CODE###'] = $this->theCode?$this->theCode:'no CODE given!';
  2761. $markerArray['###EXTPATH###'] = $GLOBALS['TYPO3_LOADED_EXT']['tt_news']['siteRelPath'];
  2762. return $this->cObj->substituteMarkerArray($helpTemplate, $markerArray);
  2763. }
  2764. /**
  2765. * checks for each field of a list of items if it exists in the tt_news table ($this->fieldNames) and returns the validated fields
  2766. *
  2767. * @param string $fieldlist: a list of fields to ckeck
  2768. * @return string the list of validated fields
  2769. */
  2770. function validateFields($fieldlist) {
  2771. $checkedFields = array();
  2772. $fArr = t3lib_div::trimExplode(',',$fieldlist,1);
  2773. while (list(,$fN) = each($fArr)) {
  2774. if (in_array($fN,$this->fieldNames)) {
  2775. $checkedFields[] = $fN;
  2776. }
  2777. }
  2778. $checkedFieldlist = implode($checkedFields,',');
  2779. return $checkedFieldlist;
  2780. }
  2781. /**
  2782. * Returns a subpart from the input content stream.
  2783. * Enables pre-/post-processing of templates/templatefiles
  2784. *
  2785. * @param string $Content stream, typically HTML template content.
  2786. * @param string $Marker string, typically on the form "###...###"
  2787. * @param array $Optional: the active row of data - if available
  2788. * @return string The subpart found, if found.
  2789. */
  2790. function getNewsSubpart($myTemplate, $myKey, $row = Array()) {
  2791. return ($this->cObj->getSubpart($myTemplate, $myKey));
  2792. }
  2793. /*********************************************
  2794. *
  2795. * DB Functions
  2796. * The following functions are copied from class tslib_content to make it possible to get a query without 'pidInList'
  2797. *
  2798. **********************************************/
  2799. /**
  2800. * Executes a SELECT query for records from $table and with conditions based on the configuration in the $conf array
  2801. * This function is preferred over ->getQuery() if you just need to create and then execute a query.
  2802. *
  2803. * @param string The table name
  2804. * @param array The TypoScript configuration properties
  2805. * @return mixed A SQL result pointer
  2806. * @see getQuery()
  2807. */
  2808. function exec_getQuery($table, $conf) {
  2809. $queryParts = $this->getQuery($table, $conf, TRUE);
  2810. // debug($queryParts,'$queryParts');
  2811. return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
  2812. }
  2813. /**
  2814. * Creates and returns a SELECT query for records from $table and with conditions based on the configuration in the $conf array
  2815. * Implements the "select" function in TypoScript
  2816. *
  2817. * @param string See ->exec_getQuery()
  2818. * @param array See ->exec_getQuery()
  2819. * @param boolean If set, the function will return the query not as a string but array with the various parts. RECOMMENDED!
  2820. * @return mixed A SELECT query if $returnQueryArray is false, otherwise the SELECT query in an array as parts.
  2821. * @access private
  2822. * @see CONTENT(), numRows()
  2823. */
  2824. function getQuery($table, $conf, $returnQueryArray=FALSE) {
  2825. // Construct WHERE clause:
  2826. if (!$this->conf['dontUsePidList']) {
  2827. $conf['pidInList'] = trim($this->cObj->stdWrap($conf['pidInList'],$conf['pidInList.']));
  2828. if (!strcmp($conf['pidInList'],'')) {
  2829. $conf['pidInList'] = 'this';
  2830. }
  2831. }
  2832. $queryParts = $this->getWhere($table,$conf,TRUE);
  2833. // Fields:
  2834. $queryParts['SELECT'] = $conf['selectFields'] ? $conf['selectFields'] : '*';
  2835. // Setting LIMIT:
  2836. if ($conf['max'] || $conf['begin']) {
  2837. $error=0;
  2838. // Finding the total number of records, if used:
  2839. if (strstr(strtolower($conf['begin'].$conf['max']),'total')) {
  2840. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', $table, $queryParts['WHERE'], $queryParts['GROUPBY']);
  2841. if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
  2842. $GLOBALS['TT']->setTSlogMessage($error);
  2843. } else {
  2844. $total = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
  2845. $conf['max'] = eregi_replace('total', (string)$total, $conf['max']);
  2846. $conf['begin'] = eregi_replace('total', (string)$total, $conf['begin']);
  2847. }
  2848. }
  2849. if (!$error) {
  2850. $conf['begin'] = t3lib_div::intInRange(ceil($this->cObj->calc($conf['begin'])),0);
  2851. $conf['max'] = t3lib_div::intInRange(ceil($this->cObj->calc($conf['max'])),0);
  2852. if ($conf['begin'] && !$conf['max']) {
  2853. $conf['max'] = 100000;
  2854. }
  2855. if ($conf['begin'] && $conf['max']) {
  2856. $queryParts['LIMIT'] = $conf['begin'].','.$conf['max'];
  2857. } elseif (!$conf['begin'] && $conf['max']) {
  2858. $queryParts['LIMIT'] = $conf['max'];
  2859. }
  2860. }
  2861. }
  2862. if (!$error) {
  2863. // Setting up tablejoins:
  2864. $joinPart='';
  2865. if ($conf['join']) {
  2866. $joinPart = 'JOIN ' .trim($conf['join']);
  2867. } elseif ($conf['leftjoin']) {
  2868. $joinPart = 'LEFT OUTER JOIN ' .trim($conf['leftjoin']);
  2869. } elseif ($conf['rightjoin']) {
  2870. $joinPart = 'RIGHT OUTER JOIN ' .trim($conf['rightjoin']);
  2871. }
  2872. // Compile and return query:
  2873. $queryParts['FROM'] = trim($table.' '.$joinPart);
  2874. $query = $GLOBALS['TYPO3_DB']->SELECTquery(
  2875. $queryParts['SELECT'],
  2876. $queryParts['FROM'],
  2877. $queryParts['WHERE'],
  2878. $queryParts['GROUPBY'],
  2879. $queryParts['ORDERBY'],
  2880. $queryParts['LIMIT']
  2881. );
  2882. return $returnQueryArray ? $queryParts : $query;
  2883. }
  2884. }
  2885. /**
  2886. * Helper function for getQuery(), creating the WHERE clause of the SELECT query
  2887. *
  2888. * @param string The table name
  2889. * @param array The TypoScript configuration properties
  2890. * @param boolean If set, the function will return the query not as a string but array with the various parts. RECOMMENDED!
  2891. * @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.
  2892. * @access private
  2893. * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=318&cHash=a98cb4e7e6
  2894. * @see getQuery()
  2895. */
  2896. function getWhere($table,$conf, $returnQueryArray=FALSE) {
  2897. global $TCA;
  2898. // Init:
  2899. $query = '';
  2900. $pid_uid_flag=0;
  2901. $queryParts = array(
  2902. 'SELECT' => '',
  2903. 'FROM' => '',
  2904. 'WHERE' => '',
  2905. 'GROUPBY' => '',
  2906. 'ORDERBY' => '',
  2907. 'LIMIT' => ''
  2908. );
  2909. if (trim($conf['uidInList'])) {
  2910. $listArr = t3lib_div::intExplode(',',str_replace('this',$GLOBALS['TSFE']->contentPid,$conf['uidInList'])); // str_replace instead of ereg_replace 020800
  2911. if (count($listArr)==1) {
  2912. $query.=' AND '.$table.'.uid='.intval($listArr[0]);
  2913. } else {
  2914. $query.=' AND '.$table.'.uid IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($listArr)).')';
  2915. }
  2916. $pid_uid_flag++;
  2917. }
  2918. if (trim($conf['pidInList'])) {
  2919. $listArr = t3lib_div::intExplode(',',str_replace('this',$GLOBALS['TSFE']->contentPid,$conf['pidInList'])); // str_replace instead of ereg_replace 020800
  2920. // removes all pages which are not visible for the user!
  2921. $listArr = $this->cObj->checkPidArray($listArr);
  2922. if (count($listArr)) {
  2923. $query.=' AND '.$table.'.pid IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($listArr)).')';
  2924. $pid_uid_flag++;
  2925. } else {
  2926. $pid_uid_flag=0; // If not uid and not pid then uid is set to 0 - which results in nothing!!
  2927. }
  2928. }
  2929. // if (!$pid_uid_flag) { // If not uid and not pid then uid is set to 0 - which results in nothing!!
  2930. // $query.=' AND '.$table.'.uid=0';
  2931. // }
  2932. if ($where = trim($conf['where'])) {
  2933. $query.=' AND '.$where;
  2934. }
  2935. if ($conf['languageField']) {
  2936. if ($GLOBALS['TSFE']->sys_language_contentOL && $TCA[$table] && $TCA[$table]['ctrl']['languageField'] && $TCA[$table]['ctrl']['transOrigPointerField']) {
  2937. // 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!
  2938. $sys_language_content = '0,-1';
  2939. } else {
  2940. $sys_language_content = intval($GLOBALS['TSFE']->sys_language_content);
  2941. }
  2942. $query.=' AND '.$conf['languageField'].' IN ('.$sys_language_content.')';
  2943. }
  2944. $andWhere = trim($this->cObj->stdWrap($conf['andWhere'],$conf['andWhere.']));
  2945. if ($andWhere) {
  2946. $query.=' AND '.$andWhere;
  2947. }
  2948. // enablefields
  2949. if ($table=='pages') {
  2950. $query.=' '.$GLOBALS['TSFE']->sys_page->where_hid_del.
  2951. $GLOBALS['TSFE']->sys_page->where_groupAccess;
  2952. } else {
  2953. $query.=$this->cObj->enableFields($table);
  2954. }
  2955. // MAKE WHERE:
  2956. if ($query) {
  2957. $queryParts['WHERE'] = trim(substr($query,4)); // Stripping of " AND"...
  2958. $query = 'WHERE '.$queryParts['WHERE'];
  2959. }
  2960. // GROUP BY
  2961. if (trim($conf['groupBy'])) {
  2962. $queryParts['GROUPBY'] = trim($conf['groupBy']);
  2963. $query.=' GROUP BY '.$queryParts['GROUPBY'];
  2964. }
  2965. // ORDER BY
  2966. if (trim($conf['orderBy'])) {
  2967. $queryParts['ORDERBY'] = trim($conf['orderBy']);
  2968. $query.=' ORDER BY '.$queryParts['ORDERBY'];
  2969. }
  2970. // Return result:
  2971. return $returnQueryArray ? $queryParts : $query;
  2972. }
  2973. /**
  2974. * Obtains current extension version (for use with compatVersion)
  2975. *
  2976. * @return string Extension version (for example, '2.5.1')
  2977. */
  2978. function getCurrentVersion() {
  2979. $_EXTKEY = $this->extKey;
  2980. require_once(t3lib_extMgm::extPath($this->extKey, 'ext_emconf.php'));
  2981. return $EM_CONF[$_EXTKEY]['version'];
  2982. }
  2983. }
  2984. if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/tt_news/pi/class.tx_ttnews.php']) {
  2985. include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/tt_news/pi/class.tx_ttnews.php']);
  2986. }
  2987. ?>