* ADD Page browser (pi_base)
[TYPO3CMS/Extensions/contagged.git] / pi1 / class.tx_contagged_pi1.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2007 Jochen Rau <j.rau@web.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 require_once (PATH_tslib . 'class.tslib_pibase.php');
26 require_once (t3lib_extMgm::extPath('contagged') . 'model/class.tx_contagged_model_terms.php');
27 require_once (t3lib_extMgm::extPath('contagged') . 'model/class.tx_contagged_model_mapper.php');
28
29 /**
30 * contagged list plugin
31 *
32 * @author Jochen Rau <j.rau@web.de>
33 * @package TYPO3
34 * @subpackage tx_contagged_pi1
35 */
36 class tx_contagged_pi1 extends tslib_pibase {
37 var $prefixId = 'tx_contagged_pi1'; // same as class name
38 var $scriptRelPath = 'pi1/class.tx_contagged_pi1.php'; // path to this script relative to the extension dir
39 var $extKey = 'contagged'; // the extension key
40 var $templateFile = 'EXT:contagged/pi1/contagged.tmpl';
41 var $conf; // the TypoScript configuration array
42 var $templateCode; // template file
43 var $local_cObj;
44 var $typolinkConf;
45 var $backPid; // pid of the last visited page (from piVars)
46 var $indexChar; // char of the given index the user has clicked on (from piVars)
47
48
49 /**
50 * main method of the contagged list plugin
51 *
52 * @param string $content: The content of the cObj
53 * @param array $conf: The configuration
54 * @return string a single or list view of terms
55 */
56 function main($content) {
57 $this->local_cObj = t3lib_div::makeInstance('tslib_cObj');
58 $this->local_cObj->setCurrentVal($GLOBALS['TSFE']->id);
59 $this->pi_loadLL();
60 $this->conf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_contagged.'];
61 $this->templateCode = $this->cObj->fileResource($this->conf['templateFile']?$this->conf['templateFile']:$this->templateFile);
62 $this->typolinkConf = $this->conf['typolink.'];
63 $this->typolinkConf['parameter.']['current'] = 1;
64 $this->typolinkConf['additionalParams'] = $this->cObj->stdWrap($typolinkConf['additionalParams'], $typolinkConf['additionalParams.']);
65 unset($this->typolinkConf['additionalParams.']);
66 $this->backPid = $this->piVars['backPid'] ? intval($this->piVars['backPid']) : NULL;
67 $this->pointer = $this->piVars['pointer'] ? intval($this->piVars['pointer']) : NULL;
68 $this->indexChar = $this->piVars['index'] ? urldecode($this->piVars['index']) : NULL;
69 if ( !is_null($this->piVars['key']) ) {
70 $termKey = intval($this->piVars['key']);
71 }
72 $sword = $this->piVars['sword'] ? urldecode($this->piVars['sword']) : NULL;
73
74 // get an array of all type configurations
75 $this->typesArray = $this->conf['types.'];
76
77 $this->mapper = new tx_contagged_model_mapper($this);
78
79 // get the model (an associated array of terms)
80 $this->model = new tx_contagged_model_terms($this);
81 $this->termsArray = $this->model->findAllTermsToBeListed($GLOBALS['TSFE']->id);
82
83 // setup the page browser
84 $this->internal['res_count'] = count($this->termsArray);
85 $this->internal['results_at_a_time'] = $this->conf['pagebrowser.']['results_at_a_time'] ? intval($this->conf['pagebrowser.']['results_at_a_time']) : 20;
86 $this->internal['maxPages'] = $this->conf['pagebrowser.']['maxPages'] ? intval($this->conf['pagebrowser.']['maxPages']) : 3;
87 $this->internal['dontLinkActivePage'] = $this->conf['pagebrowser.']['dontLinkActivePage'] ? (boolean)$this->conf['pagebrowser.']['dontLinkActivePage'] : TRUE;
88 $this->internal['showFirstLast'] = $this->conf['pagebrowser.']['showFirstLast'] ? (boolean)$this->conf['pagebrowser.']['showFirstLast'] : FALSE;
89 $this->internal['pagefloat'] = 'center';
90
91 if ( is_null($termKey) && is_null($sword) ) {
92 $content .= $this->renderList();
93 } elseif ( is_null($termKey) && !is_null($sword) ) {
94 $content .= $this->renderListBySword($sword);
95 } elseif ( !is_null($termKey) ) {
96 $content .= $this->renderSingleItemByKey($termKey);
97 }
98
99 // TODO hook "newRenderFunctionName"
100
101 $content = $this->removeUnfilledMarker($content);
102
103 return $this->pi_wrapInBaseClass($content);
104 }
105
106 /**
107 * Renders the list of terms
108 *
109 * @return $string The list as HTML
110 */
111 function renderList() {
112 $subparts = $this->getSubparts('LIST');
113 $this->renderLinks($markerArray,$wrappedSubpartArray);
114 $this->renderIndex($markerArray);
115 if (empty($this->indexChar)) {
116 $this->renderPageBrowser($markerArray);
117 $terms = array_slice($this->termsArray, ($this->pointer * $this->internal['results_at_a_time']), $this->internal['results_at_a_time'], TRUE);
118 } else {
119 $terms = $this->termsArray;
120 }
121 foreach ( $terms as $termKey => $termArray ) {
122 if ( $this->indexChar==NULL || $termArray['indexChar']==$this->indexChar ) {
123 $this->renderSingleItem($termKey,$markerArray,$wrappedSubpartArray);
124 $subpartArray['###LIST###'] .= $this->cObj->substituteMarkerArrayCached($subparts['item'],$markerArray,$subpartArray,$wrappedSubpartArray);
125 }
126 }
127 $content = $this->cObj->substituteMarkerArrayCached($subparts['template_list'],$markerArray,$subpartArray,$wrappedSubpartArray);
128
129 return $content;
130 }
131
132 function renderListBySword($sword) {
133 $subparts = $this->getSubparts('LIST');
134 $this->renderLinks($markerArray,$wrappedSubpartArray);
135 $this->renderIndex($markerArray);
136 foreach ( $this->termsArray as $termKey => $termArray ) {
137 $fieldsToSearch = t3lib_div::trimExplode(',',$this->conf['fieldsToSearch'] );
138 foreach ($fieldsToSearch as $field) {
139 // TODO make arrays searchable
140 $swordMatched = preg_match('/'.preg_quote($sword,'/').'/Uui',$termArray[$field]) ? TRUE : FALSE;
141 }
142 if ( $swordMatched ) {
143 $this->renderSingleItem($termKey,$markerArray,$wrappedSubpartArray);
144 $subpartArray['###LIST###'] .= $this->cObj->substituteMarkerArrayCached($subparts['item'],$markerArray,$subpartArray,$wrappedSubpartArray);
145 }
146 }
147 // TODO Display warning if result is empty
148 // if (!$content) {
149 // $subpartArray['###LIST###'] = "No items.";
150 // }
151 $content = $this->cObj->substituteMarkerArrayCached($subparts['template_list'],$markerArray,$subpartArray,$wrappedSubpartArray);
152
153 return $content;
154 }
155
156 function renderSingleItemByKey($termKey) {
157 $subparts = $this->getSubparts('SINGLE');
158 $this->renderLinks($markerArray,$wrappedSubpartArray);
159 $this->renderIndex($markerArray);
160 $this->renderSingleItem($termKey,$markerArray,$wrappedSubpartArray);
161 $subpartArray['###LIST###'] = $this->cObj->substituteMarkerArrayCached($subparts['item'],$markerArray,$subpartArray,$wrappedSubpartArray);
162 $content = $this->cObj->substituteMarkerArrayCached($subparts['template_list'],$markerArray,$subpartArray,$wrappedSubpartArray);
163
164 return $content;
165 }
166
167 // TODO hook "newRenderFunction"
168
169 function getSubparts($templateName='LIST') {
170 $subparts['template_list'] = $this->cObj->getSubpart($this->templateCode,'###TEMPLATE_' . $templateName . '###');
171 $subparts['item'] = $this->cObj->getSubpart($subparts['template_list'],'###ITEM###');
172
173 return $subparts;
174 }
175
176 function renderLinks(&$markerArray,&$wrappedSubpartArray) {
177 // make "back to..." link
178 if ($this->backPid) {
179 if($this->conf['addBackLinkDescription']>0) {
180 $backPage = $this->pi_getRecord('pages', $this->backPid);
181 $markerArray['###BACK_TO###'] = $this->pi_getLL('backToPage') . " \"" . $backPage['title'] . "\"";
182 } else {
183 $markerArray['###BACK_TO###'] = $this->pi_getLL('back');
184 }
185 } else {
186 $markerArray['###BACK_TO###'] = '';
187 }
188 unset($typolinkConf);
189 $typolinkConf['parameter'] = $this->backPid;
190 $wrappedSubpartArray['###LINK_BACK_TO###'] = $this->local_cObj->typolinkWrap($typolinkConf);
191
192 // make "link to all entries"
193 $markerArray['###INDEX_ALL###'] = $this->pi_linkTP($this->pi_getLL('all'));
194
195 // make "to list ..." link
196 unset($typolinkConf);
197 $markerArray['###TO_LIST###'] = $this->pi_getLL('toList');
198 $typolinkConf = $this->typolinkConf;
199 $typolinkConf['parameter.']['wrap'] = "|,".$GLOBALS['TSFE']->type;
200 $wrappedSubpartArray['###LINK_TO_LIST###'] = $this->local_cObj->typolinkWrap($typolinkConf);
201 }
202
203 function renderSingleItem ($termKey,&$markerArray,&$wrappedSubpartArray) {
204 $termArray = $this->termsArray[$termKey];
205 $typeConfigArray = $this->conf['types.'][$termArray['term_type'] . '.'];
206
207 // TODO Add a search box
208 // $markerArray['###SEARCHBOX###'] = $this->pi_list_searchBox();
209 $markerArray['###SEARCHBOX###'] = '';
210
211 $markerArray['###TERM_TYPE###'] = $typeConfigArray['label'];
212 $markerArray['###TERM###'] = $this->cObj->editIcons($termArray['term'],'tx_contagged_terms:term_main,term_alt,term_type,term_lang,term_replace,desc_short,desc_long,link,exclude',$editIconsConf,'tx_contagged_terms:'.$termArray['uid']);
213 $markerArray['###TERM_MAIN###'] = $termArray['term_main'];
214 $markerArray['###TERM_ALT###'] = $termArray['term_alt']?implode(', ',$termArray['term_alt']):$this->pi_getLL('na');
215 $markerArray['###TERM_REPLACE###'] = $termArray['term_replace']?$termArray['term_replace']:$this->pi_getLL('na');
216 $markerArray['###DESC_SHORT###'] = $termArray['desc_short']?$termArray['desc_short']:$this->pi_getLL('na');
217 $markerArray['###DESC_LONG###'] = $termArray['desc_long']?$termArray['desc_long']:$this->pi_getLL('na');
218 $markerArray['###IMAGES###'] = $this->getImages($termArray);
219 $markerArray['###RELATED###'] = $this->getRelated($termArray);
220 $markerArray['###TERM_LANG###'] = $this->pi_getLL('lang.'.$termArray['term_lang'])?$this->pi_getLL('lang.'.$termArray['term_lang']):$this->pi_getLL('na');
221
222 $labelWrap['noTrimWrap'] = $typeConfigArray['labelWrap1']?$typeConfigArray['labelWrap1']:$this->conf['labelWrap1'];
223 $markerArray['###TERM_TYPE_LABEL###'] = $markerArray['###TERM_TYPE###']?$this->local_cObj->stdWrap($this->pi_getLL('term_type'),$labelWrap):'';
224 $markerArray['###TERM_LABEL###'] = $this->local_cObj->stdWrap($this->pi_getLL('term'),$labelWrap);
225 $markerArray['###TERM_MAIN_LABEL###'] = $this->local_cObj->stdWrap($this->pi_getLL('term_main'),$labelWrap);
226 $markerArray['###TERM_ALT_LABEL###'] = $markerArray['###TERM_ALT###']?$this->local_cObj->stdWrap($this->pi_getLL('term_alt'),$labelWrap):'';
227 $markerArray['###TERM_REPLACE_LABEL###'] = $markerArray['###TERM_REPLACE###']?$this->local_cObj->stdWrap($this->pi_getLL('term_replace'),$labelWrap):'';
228 $markerArray['###DESC_SHORT_LABEL###'] = $markerArray['###DESC_SHORT###']?$this->local_cObj->stdWrap($this->pi_getLL('desc_short'),$labelWrap):'';
229 $markerArray['###DESC_LONG_LABEL###'] = $markerArray['###DESC_LONG###']?$this->local_cObj->stdWrap($this->pi_getLL('desc_long'),$labelWrap):'';
230 $markerArray['###RELATED_LABEL###'] = $markerArray['###RELATED###']?$this->local_cObj->stdWrap($this->pi_getLL('related'),$labelWrap):'';
231 $markerArray['###IMAGES_LABEL###'] = $markerArray['###IMAGES###']?$this->local_cObj->stdWrap($this->pi_getLL('images'),$labelWrap):'';
232 $markerArray['###TERM_LANG_LABEL###'] = $markerArray['###TERM_LANG###']?$this->local_cObj->stdWrap($this->pi_getLL('term_lang'),$labelWrap):'';
233
234 // make "more..." link
235 $markerArray['###DETAILS###'] = $this->pi_getLL('details');
236 unset($typolinkConf);
237 $typolinkConf = $this->typolinkConf;
238 $typolinkConf['additionalParams'] .= '&' . $this->prefixId . '[key]=' . $termKey;
239 $typolinkConf['parameter.']['wrap'] = "|,".$GLOBALS['TSFE']->type;
240 $wrappedSubpartArray['###LINK_DETAILS###'] = $this->local_cObj->typolinkWrap($typolinkConf);
241 }
242
243 function getRelated($term) {
244 $relatedCode = '';
245 if (is_array($term['related'])) {
246 foreach ($term['related'] as $termReference) {
247 $result = $this->model->findTermByUid($termReference['sourceName'], $termReference['uid']);
248 $key = key($result);
249 if (array_key_exists($key, $this->termsArray)) {
250 $relatedTerm = current($result);
251 $typolinkConf = $this->typolinkConf;
252 $typolinkConf['additionalParams'] .= '&' . $this->prefixId . '[key]=' . $key;
253 $typolinkConf['parameter.']['wrap'] = "|,".$GLOBALS['TSFE']->type;
254 $relatedCode .= '<div>' . $this->local_cObj->typoLink($relatedTerm['term'], $typolinkConf) . '</div>';
255 }
256 }
257 return $this->local_cObj->wrap(trim($relatedCode), $this->conf['related.']['wrapIfAny']);
258 } else {
259 return NULL;
260 }
261 }
262
263 function getImages($termArray) {
264 if (!empty($termArray['image'])) {
265 $imagesConf = $this->conf['images.']['single.'];
266 $images = t3lib_div::trimExplode(',', $termArray['image'], 1);
267 $imagesCaption = t3lib_div::trimExplode(chr(10), $termArray['imagecaption']);
268 $imagesAltText = t3lib_div::trimExplode(chr(10), $termArray['imagealt']);
269 $imagesTitleText = t3lib_div::trimExplode(chr(10), $termArray['imagetitle']);
270 $imagesCode = '';
271 foreach ($images as $key => $image) {
272 $imagesConf['image.']['altText'] = $imagesAltText[$key];
273 $imagesConf['image.']['titleText'] = $imagesTitleText[$key];
274 $imagesConf['image.']['file'] = 'uploads/pics/' . $image;
275 $imagesCode .= $this->local_cObj->IMAGE($imagesConf['image.']) . $this->local_cObj->stdWrap($imagesCaption[$key], $this->conf['images.']['caption.']['stdWrap.']);
276 }
277 return $this->local_cObj->wrap(trim($imagesCode), $this->conf['images.']['wrapIfAny']);
278 } else {
279 return NULL;
280 }
281 }
282
283 function renderIndex(&$markerArray) {
284 $subparts = array();
285 $subparts['template_index'] = $this->cObj->getSubpart($this->templateCode,'###TEMPLATE_INDEX###');
286 $subparts['item'] = $this->cObj->getSubpart($subparts['template_index'],'###ITEM###');
287
288 $indexArray = $this->getIndexArray();
289
290 // wrap index chars and add a class attribute if there is a selected index char.
291 foreach ($indexArray as $indexChar => $link) {
292 $cssClass = '';
293 if ($this->piVars['index']==$indexChar) {
294 $cssClass = " class='tx-contagged-act'";
295 }
296 if ($link) {
297 $markerArray['###SINGLE_CHAR###'] = '<span' . $cssClass . '>' . $link . '</span>';
298 } elseif ($this->conf['showOnlyMatchedIndexChars']==0) {
299 $markerArray['###SINGLE_CHAR###'] = '<span' . $cssClass . '>' . $indexChar . '</span>';
300 } else {
301 $markerArray['###SINGLE_CHAR###'] = '';
302 }
303 $subpartArray['###INDEX_CONTENT###'] .= $this->cObj->substituteMarkerArrayCached($subparts['item'], $markerArray);
304 }
305 $markerArray['###INDEX###'] = $this->cObj->substituteMarkerArrayCached($subparts['template_index'], $markerArray, $subpartArray);
306 }
307
308 function getIndexArray() {
309 // Get localized index chars.
310 foreach (t3lib_div::trimExplode(',', $this->pi_getLL('indexChars')) as $key => $value) {
311 $subCharArray = t3lib_div::trimExplode('|', $value);
312 $indexArray[$subCharArray[0]] = NULL;
313 foreach($subCharArray as $subChar) {
314 $reverseIndexArray[$subChar] = $subCharArray[0];
315 }
316 }
317
318 // The configuered subchars like Ö will be linked as O (see documentation and file "locallang.xml").
319 unset($typolinkConf);
320 $typolinkConf = $this->typolinkConf;
321 foreach ($this->termsArray as $termKey => $termArray) {
322 if ( $termArray['exclude']!=1 && $this->conf['types.'][$termArray['term_type'].'.']['dontListTerms']!=1 && in_array($GLOBALS['TSFE']->id,$termArray['listPages']) ) {
323 $sortField = $this->model->getSortField($termArray);
324 // debug($sortField);
325 foreach ($reverseIndexArray as $subChar => $indexChar) {
326 // debug(preg_quote($subChar),$termArray['term']);
327 // debug(preg_match('/^'.preg_quote($subChar).'/ui',$termArray['term']));
328 if ( preg_match('/^'.preg_quote($subChar).'/' . $this->conf['modifier'],$termArray[$sortField])>0 ) {
329 $typolinkConf['additionalParams'] = '&' . $this->prefixId . '[index]=' . $indexChar;
330 $indexArray[$indexChar] = $this->local_cObj->typolink($indexChar, $typolinkConf);
331 $this->termsArray[$termKey]['indexChar'] = $indexChar;
332 }
333 }
334 // If the term matches no given index char, crate one if desired and add it to the index
335 if ( $this->termsArray[$termKey]['indexChar']=='' && $this->conf['autoAddIndexChars']==1 ) {
336 // get the first char of the term (UTF8)
337 // TODO: Make the RegEx configurable to make ZIP-Codes possible
338 preg_match('/^./' . $this->conf['modifier'],$termArray[$sortField],$match);
339 $newIndexChar = $match[0];
340 $indexArray[$newIndexChar] = NULL;
341 $typolinkConf['additionalParams'] .= '&' . $this->prefixId . '[index]=' . urlencode($newIndexChar);
342 $indexArray[$newIndexChar] = $this->local_cObj->typolink($newIndexChar, $typolinkConf);
343 $this->termsArray[$termKey]['indexChar'] = $newIndexChar;
344 }
345 }
346 }
347
348 // TODO Sorting of the index (UTF8)
349 ksort($indexArray,SORT_LOCALE_STRING);
350
351 return $indexArray;
352 }
353
354 function renderPageBrowser(&$markerArray) {
355 if ($this->internal['res_count'] > $this->internal['results_at_a_time']) {
356 $showResultCount = $this->conf['pagebrowser.']['showResultCount'] ? (boolean)$this->conf['pagebrowser.']['showResultCount'] : FALSE;
357 $markerArray['###PAGEBROWSER###'] = $this->pi_list_browseresults($showResultCount);
358 } else {
359 $markerArray['###PAGEBROWSER###'] = '';
360 }
361 }
362
363 protected function removeUnfilledMarker($content) {
364 return preg_replace('/###.*?###/', '', $content);
365 }
366
367 }
368
369
370 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/contagged/pi1/class.tx_contagged_pi1.php']) {
371 include_once ($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/contagged/pi1/class.tx_contagged_pi1.php']);
372 }
373 ?>