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