cff3eadf997e893bc30851e56b3a30cb4cca5eb9
[TYPO3CMS/Extensions/contagged.git] / class.tx_contagged.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 * (c) 2007 Jochen Rau <j.rau@web.de>
5 * All rights reserved
6 * This script is part of the TYPO3 project. The TYPO3 project is
7 * free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 * The GNU General Public License can be found at
12 * http://www.gnu.org/copyleft/gpl.html.
13 * This script is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 * This copyright notice MUST APPEAR in all copies of the script!
18 ***************************************************************/
19
20 require_once (PATH_tslib . 'class.tslib_pibase.php');
21 require_once (PATH_t3lib . 'class.t3lib_parsehtml.php');
22 require_once (t3lib_extMgm::extPath('contagged') . 'model/class.tx_contagged_model_terms.php');
23
24 /**
25 * The main class to parse,tag and replace specific terms of the content.
26 *
27 * @author Jochen Rau <j.rau@web.de>
28 * @package TYPO3
29 * @subpackage tx_contagged
30 */
31 class tx_contagged extends tslib_pibase {
32
33 var $prefixId = 'tx_contagged';
34
35 var $scriptRelPath = 'class.tx_contagged.php'; // path to this script relative to the extension dir
36 var $extKey = 'contagged'; // the extension key
37 var $conf; // the TypoScript configuration array
38 var $typolinkConf;
39
40 /**
41 * The main method. It instantly delegates the process to the parse function.
42 *
43 * @param string $content: The content
44 * @param array $conf: The configuration array
45 * @return string The parsed and tagged content that is displayed on the website
46 */
47 public function main($content, $conf = NULL) {
48 return $this->parse($content, $conf);
49 }
50
51 /**
52 * This method is to parse, tag and link specific terms in the given content.
53 *
54 * @param string $content: The content
55 * @param array $conf: The configuration array
56 * @return string The parsed and tagged content that is displayed on the website
57 */
58 public function parse($content, $conf) {
59 if (!is_array($conf)) {
60 $conf = array();
61 }
62 $this->conf = t3lib_div::array_merge_recursive_overrule($GLOBALS['TSFE']->tmpl->setup['plugin.'][$this->prefixId . '.'], $conf);
63 $this->pi_setPiVarDefaults();
64 if (!is_object($this->cObj)) {
65 $this->cObj = t3lib_div::makeInstance('tslib_cObj');
66 $this->cObj->setCurrentVal($GLOBALS['TSFE']->id);
67 }
68
69 $this->typolinkConf = is_array($this->conf['typolink.']) ? $this->conf['typolink.'] : array();
70 if (!empty($this->typolinkConf['additionalParams'])) {
71 $this->typolinkConf['additionalParams'] = $this->cObj->stdWrap($typolinkConf['additionalParams'], $typolinkConf['additionalParams.']);
72 unset($this->typolinkConf['additionalParams.']);
73 }
74 $this->typolinkConf['useCacheHash'] = 1;
75
76 // exit if the content should be skipped
77 if ($this->isContentToSkip()) {
78 return $content;
79 }
80
81 // get an array of all type configurations
82 $this->typesArray = $this->conf['types.'];
83
84 // get the model (an associated array of terms)
85 $model = t3lib_div::makeInstance('tx_contagged_model_terms', $this);
86 $this->termsArray = $model->findAllTerms();
87
88 $excludeTerms = explode(',', $this->conf['excludeTerms']);
89 $sortedTerms = array();
90 foreach ($this->termsArray as $termKey => $termArray) {
91 if ($this->conf['autoExcludeTerms'] == 1 && in_array($termArray['term_main'], $excludeTerms)) {
92 continue;
93 }
94 $sortedTerms[] = array('term' => $termArray['term_main'], 'key' => $termKey);
95 if (is_array($termArray['term_alt'])) {
96 foreach ($termArray['term_alt'] as $term) {
97 if ($this->conf['autoExcludeTerms'] == 1 && in_array($term, $excludeTerms)) {
98 continue;
99 }
100 $sortedTerms[] = array('term' => $term, 'key' => $termKey);
101 }
102 }
103 }
104
105 // sort the array descending by length of the value, so the longest term will match
106 usort($sortedTerms, array($this, 'sortTermsByDescendingLength'));
107
108 // get a comma separated list of all tags which should be omitted
109 $tagsToOmitt = $this->getTagsToOmitt();
110
111 // TODO split recursively
112 $parseObj = t3lib_div::makeInstance('t3lib_parsehtml');
113 $splittedContent = $parseObj->splitIntoBlock($tagsToOmitt, $content);
114 foreach ((array)$splittedContent as $intKey => $HTMLvalue) {
115 if (!($intKey % 2)) {
116 $positionsArray = array();
117 foreach ($sortedTerms as $termAndKey) {
118 if (empty($termAndKey['term'])) {
119 continue;
120 }
121 $this->getPositions($splittedContent[$intKey], $positionsArray, $termAndKey['term'], $termAndKey['key']);
122 }
123 ksort($positionsArray);
124 $splittedContent[$intKey] = $this->doReplace($splittedContent[$intKey], $positionsArray);
125 }
126 }
127 $parsedContent = implode('', $splittedContent);
128
129 // update the keywords (field "tx_contagged_keywords" in table "page")
130 if ($this->conf['updateKeywords'] > 0) {
131 $this->updatePageKeywords();
132 }
133 $this->addJavaScript();
134
135 return $parsedContent;
136 }
137
138 /**
139 * Utility method to sort array items according to the (string) length of their "term" item
140 *
141 * Note: the sorting is descending
142 *
143 * @param array $a
144 * @param array $b
145 * @return integer +1 if term from a is shorter than b, -1 for the contrary, 0 in case of equality
146 */
147 public function sortTermsByDescendingLength($a, $b) {
148 // Calculate length correctly by relying on t3lib_cs
149 $aTermLength = $GLOBALS['TSFE']->csConvObj->strlen($GLOBALS['TSFE']->renderCharset, $a['term']);
150 $bTermLength = $GLOBALS['TSFE']->csConvObj->strlen($GLOBALS['TSFE']->renderCharset, $b['term']);
151 if ($aTermLength == $bTermLength) {
152 return 0;
153 } else {
154 return ($aTermLength < $bTermLength) ? +1 : -1;
155 }
156 }
157
158 function getPositions($content, &$positionsArray, $term, $termKey) {
159 $termArray = $this->termsArray[$termKey];
160 $typeConfigArray = $this->typesArray[$termArray['term_type'] . '.'];
161 if ($typeConfigArray['termIsRegEx'] > 0) {
162 $regEx = $termArray['term_main'] . $this->conf['modifier'];
163 } else {
164 $term = $this->cObj->stdWrap($term, $typeConfigArray['termStdWrap.']);
165 if (strstr($this->conf['modifier'], 'u') !== FALSE) {
166 $regEx = '/(?<=\P{L}|^)' . preg_quote($term, '/') . '(?=\P{L}|$)/' . $this->conf['modifier'];
167 } else {
168 $regEx = '/(?<=\W|^)' . preg_quote($term, '/') . '(?=\W|$)/' . $this->conf['modifier'];
169 }
170 }
171 preg_match_all($regEx, $content, $matchesArray, PREG_OFFSET_CAPTURE);
172 $matchesArray = $matchesArray[0]; // only take the full pattern matches of the regEx
173
174 // determine the maximum of recurrences of the same term to be tagged
175 $maxRecurrences = (!empty($this->conf['maxRecurrences'])) ? min($this->conf['maxRecurrences'], count($matchesArray)) : count($matchesArray);
176 $step = $maxRecurrences != 0 ? ceil(count($matchesArray) / $maxRecurrences) : 1;
177 for ($i = 0; $i < count($matchesArray); $i = $i + $step) {
178 if (!empty($this->conf['maxRecurrencesPerPage'])
179 && $GLOBALS['contagged']['occurences'][$termKey] > (int)$this->conf['maxRecurrencesPerPage']
180 ) {
181 break;
182 }
183 $preContent = substr($content, 0, $matchesArray[$i][1]);
184 $postContent = substr($content, strlen($matchesArray[$i][0]) + $matchesArray[$i][1]);
185
186 // Flag: $inTag=true if we are inside a tag < here we are >
187 $inTag = FALSE;
188 if (preg_match('/<[^<>]*$/' . $this->conf['modifier'], $preContent) > 0 && preg_match('/^[^<>]*>/' . $this->conf['modifier'], $postContent) > 0) {
189 $inTag = TRUE;
190 }
191 if (!$inTag) {
192 // support for joined words (with a dashes)
193 $preMatch = '';
194 $postMatch = '';
195 if ($this->checkLocalGlobal($typeConfigArray, 'checkPreAndPostMatches') > 0) {
196 if (strstr($this->conf['modifier'], 'u') !== FALSE) {
197 preg_match('/(?<=\P{L})\p{L}*-$/' . $this->conf['modifier'], $preContent, $preMatch);
198 preg_match('/^-\p{L}*(?=\P{L})/' . $this->conf['modifier'], $postContent, $postMatch);
199 } else {
200 preg_match('/(?<=\W)\w*-$/' . $this->conf['modifier'], $preContent, $preMatch);
201 preg_match('/^-\w*(?=\W)/' . $this->conf['modifier'], $postContent, $postMatch);
202 }
203 }
204 $matchedTerm = $preMatch[0] . $matchesArray[$i][0] . $postMatch[0];
205 $matchStart = $matchesArray[$i][1] - strlen($preMatch[0]);
206 $matchEnd = $matchStart + strlen($matchedTerm);
207
208 // check for nested matches
209 $isNested = FALSE;
210 $checkArray = $positionsArray;
211 foreach ($checkArray as $start => $value) {
212 $length = strlen($value['matchedTerm']);
213 $end = $start + $length;
214 if ((($matchStart >= $start) && ($matchStart < $end)) || (($matchEnd > $start) && ($matchEnd <= $end))) {
215 $isNested = TRUE;
216 }
217 }
218 if (!$isNested) {
219 $positionsArray[$matchStart] = array(
220 'termKey' => $termKey,
221 'matchedTerm' => $matchedTerm,
222 'preMatch' => $preMatch[0],
223 'postMatch' => $postMatch[0]
224 );
225 $GLOBALS['contagged']['occurences'][$termKey]++;
226 }
227 }
228 }
229 }
230
231 function doReplace($content, $positionsArray) {
232 $posStart = 0;
233 $newContent = '';
234 if ($positionsArray) {
235 foreach ($positionsArray as $matchStart => $matchArray) {
236 $matchLength = strlen($matchArray['matchedTerm']);
237 $termKey = $matchArray['termKey'];
238 $replacement = $this->getReplacement($termKey, $matchArray['matchedTerm'], $matchArray['preMatch'], $matchArray['postMatch']);
239 $replacementLength = strlen($replacement);
240 $newContent = $newContent . substr($content, $posStart, $matchStart - $posStart) . $replacement;
241 $posStart = $matchStart + $matchLength;
242 }
243 $newContent = $newContent . substr($content, $posStart);
244 } else {
245 $newContent = $content;
246 }
247
248 return $newContent;
249 }
250
251 /**
252 * Do something with the matched term (replace, stdWrap, link, tag)
253 *
254 * @param int $termKey: the internal "uid" of the term (not related to the database uid)
255 * @param string $matchedTerm: The matched term including pre and post matches
256 * @return string The replaced, linked and tagged term
257 * @author Jochen Rau
258 */
259 function getReplacement($termKey, $matchedTerm, $preMatch, $postMatch) {
260 $termArray = $this->termsArray[$termKey];
261 $typeConfigArray = $this->typesArray[$termArray['term_type'] . '.'];
262 // register the term array
263 $this->registerFields($typeConfigArray, $termKey);
264
265 // build the tag enclosing the term
266 if (!empty($typeConfigArray['tag'])) {
267 // get the attributes
268 $langAttribute = $this->getLangAttribute($typeConfigArray, $termArray);
269 $titleAttribute = $this->getTitleAttribute($typeConfigArray, $termArray);
270 $cssClassAttribute = $this->getCssClassAttribute($typeConfigArray, $termArray);
271 // concatenate the tag
272 $before = '<' . $typeConfigArray['tag'] . $titleAttribute . $cssClassAttribute . $langAttribute . '>';
273 $after = '</' . $typeConfigArray['tag'] . '>';
274 }
275
276 // replace matched term
277 if ($this->checkLocalGlobal($typeConfigArray, 'replaceTerm') && $termArray['term_replace']) {
278 // if the first letter of the matched term is upper case
279 // make the first letter of the replacing term also upper case
280 // (\p{Lu} stands for "unicode letter uppercase")
281 $GLOBALS['TSFE']->register['contagged_matchedTerm'] = $termArray['term_replace'];
282 $this->updateIndex($termKey, $termArray['term_replace']);
283 if (preg_match('/^\p{Lu}/u', $matchedTerm) > 0 && ($this->checkLocalGlobal($typeConfigArray, 'respectCase') > 0)) {
284 $matchedTerm = $preMatch . ucfirst($termArray['term_replace']) . $postMatch;
285 // TODO ucfirst is not UTF8 safe; it depends on the locale settings (they could be ASCII)
286 } else {
287 $matchedTerm = $preMatch . $termArray['term_replace'] . $postMatch;
288 }
289 } else {
290 $GLOBALS['TSFE']->register['contagged_matchedTerm'] = $matchedTerm;
291 $this->updateIndex($termKey, $termArray['term']);
292 }
293
294 // call stdWrap to handle the matched term via TS BEFORE it is wraped with a-tags
295 if ($typeConfigArray['preStdWrap.']) {
296 $matchedTerm = $this->cObj->stdWrap($matchedTerm, $typeConfigArray['preStdWrap.']);
297 }
298
299 $matchedTerm = $this->linkMatchedTerm($matchedTerm, $typeConfigArray, $termKey);
300
301 // call stdWrap to handle the matched term via TS AFTER it was wrapped with a-tags
302 if ($typeConfigArray['postStdWrap.'] or $typeConfigArray['stdWrap.']) {
303 $matchedTerm = $this->cObj->stdWrap($matchedTerm, $typeConfigArray['postStdWrap.']);
304 $matchedTerm = $this->cObj->stdWrap($matchedTerm, $typeConfigArray['stdWrap.']); // for compatibility with < v0.0.5
305 }
306
307 if (!empty($typeConfigArray['tag'])) {
308 $matchedTerm = $before . $matchedTerm . $after;
309 }
310
311 // TODO Edit Icons
312 $editIconsConf = array(
313 'styleAttribute' => '',
314 );
315 $matchedTerm = $this->cObj->editIcons($matchedTerm, 'tx_contagged_terms:sys_language_uid,hidden,starttime,endtime,fe_group,term_main,term_alt,term_type,term_lang,term_replace,desc_short,desc_long,image,dam_images,imagecaption,imagealt,imagetitle,related,link,exclude', $editIconsConf, 'tx_contagged_terms:' . $termArray['uid'], NULL, '&defVals[tx_contagged_terms][desc_short]=TEST');
316
317 return $matchedTerm;
318 }
319
320 function updateIndex($termKey, $matchedTerm) {
321 $currentRecord = t3lib_div::trimExplode(':', $this->cObj->currentRecord);
322 $GLOBALS['T3_VAR']['ext']['contagged']['index'][$GLOBALS['TSFE']->id][$termKey] = array(
323 'matchedTerm' => $matchedTerm,
324 'source' => $this->termsArray[$termKey]['source'],
325 'uid' => $this->termsArray[$termKey]['uid'],
326 'currentRecordSource' => $currentRecord[0],
327 'currentRecordUid' => $currentRecord[1],
328 'currentPid' => $GLOBALS['TSFE']->id
329 );
330 }
331
332 /**
333 * Some content tagged by configured tags could be prevented from beeing parsed.
334 * This function collects all the tags which should be considered.
335 *
336 * @return string Comma separated list of tags
337 */
338 function getTagsToOmitt() {
339 $tagArray = array();
340
341 // if there are tags to exclude: add them to the list
342 if ($this->conf['excludeTags']) {
343 $tagArray = t3lib_div::trimExplode(',', $this->conf['excludeTags'], 1);
344 }
345
346 // if configured: add tags used by the term definitions
347 if ($this->conf['autoExcludeTags'] > 0) {
348 ;
349 foreach ($this->conf['types.'] as $key => $type) {
350 if (!empty($type['tag']) && !in_array($type['tag'], $tagArray)) {
351 $tagArray[] = $type['tag'];
352 }
353 }
354 }
355
356 $tagList = implode(',', $tagArray);
357
358 return $tagList;
359 }
360
361 function updatePageKeywords() {
362 $terms = array();
363 if (is_array($GLOBALS['T3_VAR']['ext']['contagged']['index'][$GLOBALS['TSFE']->id])) {
364 foreach ($GLOBALS['T3_VAR']['ext']['contagged']['index'][$GLOBALS['TSFE']->id] as $termKey => $indexArray) {
365 $terms[] = $indexArray['matchedTerm'];
366 }
367 }
368 $termsList = implode(',', $terms);
369 $res = $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
370 'pages', // TABLE ...
371 'uid=' . $GLOBALS['TSFE']->id, // WHERE ...
372 array($this->prefixId . '_keywords' => $termsList)
373 );
374 }
375
376 /**
377 * Register the fields in $GLOBALS['TSFE] to be used in the TS Setup
378 *
379 * @param array $typeConfigArray: Configuration array of the term
380 * @param array $this->termsArray: Array of terms
381 * @param int $termKey: Internal key of the term
382 */
383 function registerFields($typeConfigArray, $termKey) {
384 if ($typeConfigArray['stripBlockTags'] > 0) {
385 $this->termsArray[$termKey]['desc_short_inline'] = $this->stripBlockTags($this->termsArray[$termKey]['desc_short']);
386 $text = $this->cObj->parseFunc($this->termsArray[$termKey]['desc_long'], array(), '< lib.parseFunc_RTE');
387 $this->termsArray[$termKey]['desc_long_inline'] = $this->stripBlockTags($text);
388 }
389
390 $GLOBALS['TSFE']->register['contagged_key'] = $termKey;
391
392 // register all fields to be handled by the TS Setup
393 foreach ($this->termsArray[$termKey] as $label => $value) {
394 $GLOBALS['TSFE']->register['contagged_' . $label] = $value;
395 }
396 }
397
398 /**
399 * Wrap the matched term in a link tag - as configured
400 *
401 * @param string $matchedTerm
402 * @param string $typeConfigArray
403 * @param string $this->termsArray
404 * @param string $termKey
405 * @return void
406 * @author Jochen Rau
407 */
408 function linkMatchedTerm($matchedTerm, $typeConfigArray, $termKey) {
409 $termArray = $this->termsArray[$termKey];
410
411 // check conditions if the term should be linked to a list page
412 $makeLink = $this->checkLocalGlobal($typeConfigArray, 'linkToListPage');
413 if ($termArray['exclude'] > 0) {
414 $makeLink = false;
415 }
416 if ($termArray['link']) {
417 $makeLink = true;
418 }
419
420 // link the matched term to the front-end list page
421 if ($makeLink) {
422 unset($typolinkConf);
423 $typolinkConf = $this->typolinkConf;
424 if (!empty($typeConfigArray['typolink.'])) {
425 $typolinkConf = t3lib_div::array_merge_recursive_overrule($typolinkConf, $typeConfigArray['typolink.']);
426 }
427 if ($termArray['link']) {
428 $typolinkConf['parameter'] = $termArray['link'];
429 $typolinkConf['additionalParams'] = $termArray['link.']['additionalParams'];
430 } else {
431 if ($typeConfigArray['listPages']) {
432 $typolinkConf['parameter'] = array_shift(t3lib_div::trimExplode(',', $typeConfigArray['listPages'], 1));
433 } else {
434 $typolinkConf['parameter'] = array_shift(t3lib_div::trimExplode(',', $this->conf['listPages'], 1));
435 }
436 $GLOBALS['TSFE']->register['contagged_list_page'] = $typolinkConf['parameter'];
437 $additionalParams['source'] = $termArray['source'];
438 $additionalParams['uid'] = $termArray['uid'];
439 if ($this->checkLocalGlobal($typeConfigArray, 'addBackLink')) {
440 $additionalParams['backPid'] = $GLOBALS['TSFE']->id;
441 }
442 $typolinkConf['additionalParams'] = t3lib_div::implodeArrayForUrl('tx_contagged', $additionalParams, '', 1);
443 }
444 $GLOBALS['TSFE']->register['contagged_link_url'] = $this->cObj->typoLink_URL($typolinkConf);
445 $matchedTerm = $this->cObj->typolink($matchedTerm, $typolinkConf);
446 }
447
448 return $matchedTerm;
449 }
450
451 /**
452 * Overwrite global settings with settings of the type configuration.
453 *
454 * @param string $typeConfigArray
455 * @param string $attributeName
456 * @return void
457 * @author Jochen Rau
458 */
459 function checkLocalGlobal($typeConfigArray, $attributeName) {
460 if (isset($typeConfigArray[$attributeName])) {
461 $addAttribute = ($typeConfigArray[$attributeName] > 0) ? true : false;
462 } else {
463 $addAttribute = ($this->conf[$attributeName] > 0) ? true : false;
464 }
465
466 return $addAttribute;
467 }
468
469 /**
470 * If the language of the term is undefined, or the page language is the same as language of the term,
471 * then the lang attribute will not be shown.
472 * If the terms language is defined and different from the page language, then the language attribute is added.
473 *
474 * @param string $typeConfigArray
475 * @param string $termArray
476 * @return void
477 * @author Jochen Rau
478 */
479 function getLangAttribute($typeConfigArray, $termArray) {
480 // get page language
481 if ($GLOBALS['TSFE']->config['config']['language']) {
482 $pageLanguage = $GLOBALS['TSFE']->config['config']['language'];
483 } else {
484 $pageLanguage = substr($GLOBALS['TSFE']->config['config']['htmlTag_langKey'], 0, 2);
485 }
486 // build language attribute if the page language is different from the terms language
487 if ($this->checkLocalGlobal($typeConfigArray, 'addLangAttribute') && !empty($termArray['term_lang']) && ($pageLanguage != $termArray['term_lang'])) {
488 $langAttribute = ' lang="' . $termArray['term_lang'] . '"';
489 $langAttribute .= ' xml:lang="' . $termArray['term_lang'] . '"';
490 }
491
492 return $langAttribute;
493 }
494
495 /**
496 * Renders the title attribute of the tag.
497 *
498 * @param string $typeConfigArray
499 * @param string $termArray
500 * @return void
501 * @author Jochen Rau
502 */
503 function getTitleAttribute($typeConfigArray, $termArray) {
504 if ($this->checkLocalGlobal($typeConfigArray, 'addTitleAttribute') && !empty($termArray['desc_short'])) {
505 $titleAttribute = ' title="' . $termArray['desc_short'] . '"';
506 }
507
508 return $titleAttribute;
509 }
510
511 /**
512 * Renders the class attribute of the tag.
513 *
514 * @param [type] $typeConfigArray: ...
515 * @param [type] $termArray: ...
516 * @return [type] ...
517 */
518 function getCssClassAttribute($typeConfigArray, $termArray) {
519 if ($this->checkLocalGlobal($typeConfigArray, 'addCssClassAttribute')) {
520 if ($typeConfigArray['cssClass']) {
521 $cssClassAttribute = $this->pi_classParam($typeConfigArray['cssClass']);
522 } else {
523 $cssClassAttribute = $this->pi_classParam($termArray['term_type']);
524 }
525 }
526
527 return $cssClassAttribute;
528 }
529
530 /**
531 * Test, if the current page should be skipped
532 *
533 * @return boolean True if the page should be skipped
534 */
535 function isContentToSkip() {
536 $result = true; // true, if the page should be skipped
537 $currentPageUid = $GLOBALS['TSFE']->id;
538
539 // get rootline of the current page
540 $rootline = $GLOBALS['TSFE']->sys_page->getRootline($currentPageUid);
541 // build an array of uids of pages the rootline
542 for ($i = count($rootline) - 1; $i >= 0; $i--) {
543 $pageUidsInRootline[] = $rootline["$i"]['uid'];
544 }
545 // check if the root page is in the rootline of the current page
546 $includeRootPagesUids = t3lib_div::trimExplode(',', $this->conf['includeRootPages'], 1);
547 foreach ($includeRootPagesUids as $includeRootPageUid) {
548 if (t3lib_div::inArray((array)$pageUidsInRootline, $includeRootPageUid)) {
549 $result = false;
550 }
551 }
552 $excludeRootPagesUids = t3lib_div::trimExplode(',', $this->conf['excludeRootPages'], 1);
553 foreach ($excludeRootPagesUids as $excludeRootPageUid) {
554 if (t3lib_div::inArray((array)$pageUidsInRootline, $excludeRootPageUid)) {
555 $result = true;
556 }
557 }
558 if (t3lib_div::inList($this->conf['includePages'], $currentPageUid)) {
559 $result = false;
560 }
561 if (t3lib_div::inList($this->conf['excludePages'], $currentPageUid)) {
562 $result = true;
563 }
564 if ($GLOBALS['TSFE']->page['tx_contagged_dont_parse'] == 1) {
565 $result = true;
566 }
567 if (!empty($this->cObj)) {
568 if ($this->cObj->getFieldVal('tx_contagged_dont_parse') == 1) {
569 $result = true;
570 }
571 }
572
573 return $result;
574 }
575
576 /**
577 * Replaces block elements with inline versions (if possible)
578 *
579 * @param string $text
580 * @return string The reformatted text
581 */
582 protected function stripBlockTags($text) {
583 $blockElements = 'address|blockquote|center|del|dir|div|dl|fieldset|form|h[1-6]|hr|ins|isindex|menu|noframes|noscript|ol|p|pre|table|ul|center|dir|isindex|menu|noframes';
584 $text = preg_replace('%' . $this->getOpeningTag('li|dd') . '%xs', '&nbsp;&nbsp;*&nbsp;', $text);
585 $text = preg_replace('%' . $this->getClosingTag('li|dt') . '%xs', '<br />', $text);
586 $text = preg_replace('%' . $this->getClosingTag('ol|ul|dl') . '%xs', '', $text);
587 $text = preg_replace('%' . $this->getOpeningTag($blockElements) . '%xs', '', $text);
588 $text = preg_replace('%' . $this->getClosingTag($blockElements) . '%xs', '<br />', $text);
589 $text = preg_replace('%' . $this->getOpeningTag('br') . '{2,2}%xs', '<br />', $text);
590 return $text;
591 }
592
593 /**
594 * Returns an opening tag of the allowed elements.
595 *
596 * @param string $allowedElements The allowed elements ("a|b|c")
597 * @return void
598 */
599 protected function getOpeningTag($allowedElements) {
600 $tag = "
601 (
602 <(?:" . $allowedElements . ") # opening tag ('<tag') or closing tag ('</tag')
603 (?:
604 (?:
605 \s+\w+ # EITHER spaces, followed by word characters (attribute names)
606 (?:
607 \s*=?\s* # equals
608 (?>
609 \".*?\" # attribute values in double-quotes
610 |
611 '.*?' # attribute values in single-quotes
612 |
613 [^'\">\s]+ # plain attribute values
614 )
615 )?
616 )+\s*
617 | # OR only spaces
618 \s*
619 )
620 /?> # closing the tag with '>' or '/>'
621 )";
622 return $tag;
623 }
624
625 /**
626 * Returns a closing tag of the allowed elements.
627 *
628 * @param string $allowedElements The allowed elements ("a|b|c")
629 * @return void
630 */
631 protected function getClosingTag($allowedElements) {
632 $tag = "
633 (
634 </(?:" . $allowedElements . ") # opening tag ('<tag') or closing tag ('</tag')
635 (?:
636 (?:
637 \s+\w+ # EITHER spaces, followed by word characters (attribute names)
638 (?:
639 \s*=?\s* # equals
640 (?>
641 \".*?\" # attribute values in double-quotes
642 |
643 '.*?' # attribute values in single-quotes
644 |
645 [^'\">\s]+ # plain attribute values
646 )
647 )?
648 )+\s*
649 | # OR only spaces
650 \s*
651 )
652 > # closing the tag with '>' or '/>'
653 )";
654 return $tag;
655 }
656
657 /**
658 * Adds the qTip plugin script (jQuery). You can call this function in you TS setup if necessary.
659 *
660 * @return void
661 */
662 protected function addJavaScript() {
663 $extensionConfiguration = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['contagged']);
664 $javaScriptPathAndFilename = $extensionConfiguration['javaScriptPathAndFilename'];
665 if (is_string($javaScriptPathAndFilename) && $javaScriptPathAndFilename !== '') {
666 $GLOBALS['TSFE']->additionalHeaderData['contagged'] .= '<script src="' . $javaScriptPathAndFilename . '" type="text/javascript"></script>';
667 }
668 }
669 }
670
671 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/contagged/class.tx_contagged.php']) {
672 include_once ($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/contagged/class.tx_contagged.php']);
673 }
674 ?>