[BUGFIX] Caching framework: Reduce code duplication in db backend
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_softrefproc.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2003-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the Typo3 project. The Typo3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
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 * Soft Reference processing class
26 * "Soft References" are references to database elements, files, email addresses, URls etc.
27 * which are found in-text in content. The <link [page_id]> tag from typical bodytext fields
28 * are an example of this.
29 * This class contains generic parsers for the most well-known types
30 * which are default for most TYPO3 installations. Soft References can also be userdefined.
31 * The Soft Reference parsers are used by the system to find these references and process them accordingly in import/export actions and copy operations.
32 *
33 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 116: class t3lib_softrefproc
41 * 137: function findRef($table, $field, $uid, $content, $spKey, $spParams, $structurePath='')
42 * 213: function findRef_images($content, $spParams)
43 * 280: function findRef_typolink($content, $spParams)
44 * 317: function findRef_typolink_tag($content, $spParams)
45 * 352: function findRef_TStemplate($content, $spParams)
46 * 434: function findRef_TSconfig($content, $spParams)
47 * 457: function findRef_email($content, $spParams)
48 * 497: function findRef_url($content, $spParams)
49 * 539: function findRef_extension_fileref($content, $spParams)
50 *
51 * SECTION: Helper functions
52 * 591: function fileadminReferences($content, &$elements)
53 * 634: function getTypoLinkParts($typolinkValue)
54 * 718: function setTypoLinkPartsElement($tLP, &$elements, $content, $idx)
55 * 833: function getPageIdFromAlias($link_param)
56 * 845: function makeTokenID($index='')
57 *
58 * TOTAL FUNCTIONS: 14
59 * (This index is automatically created/updated by the extension "extdeveval")
60 *
61 */
62
63
64 /**
65 * Example of usage
66 * // Soft References:
67 * if ($conf['softref'] && strlen($value)) { // Check if a TCA configured field has softreferences defined (see TYPO3 Core API document)
68 * $softRefs = t3lib_BEfunc::explodeSoftRefParserList($conf['softref']); // Explode the list of softreferences/parameters
69 * foreach($softRefs as $spKey => $spParams) { // Traverse soft references
70 * $softRefObj = &t3lib_BEfunc::softRefParserObj($spKey); // create / get object
71 * if (is_object($softRefObj)) { // If there was an object returned...:
72 * $resultArray = $softRefObj->findRef($table, $field, $uid, $softRefValue, $spKey, $spParams); // Do processing
73 *
74 * Result Array:
75 * The Result array should contain two keys: "content" and "elements".
76 * "content" is a string containing the input content but possibly with tokens inside.
77 * Tokens are strings like {softref:[tokenID]} which is a placeholder for a value extracted by a softref parser
78 * For each token there MUST be an entry in the "elements" key which has a "subst" key defining the tokenID and the tokenValue. See below.
79 * "elements" is an array where the keys are insignificant, but the values are arrays with these keys:
80 * "matchString" => The value of the match. This is only for informational purposes to show what was found.
81 * "error" => An error message can be set here, like "file not found" etc.
82 * "subst" => array( // If this array is found there MUST be a token in the output content as well!
83 * "tokenID" => The tokenID string corresponding to the token in output content, {softref:[tokenID]}. This is typically an md5 hash of a string defining uniquely the position of the element.
84 * "tokenValue" => The value that the token substitutes in the text. Basically, if this value is inserted instead of the token the content should match what was inputted originally.
85 * "type" => file / db / string = the type of substitution. "file" means it is a relative file [automatically mapped], "db" means a database record reference [automatically mapped], "string" means it is manually modified string content (eg. an email address)
86 * "relFileName" => (for "file" type): Relative filename. May not necessarily exist. This could be noticed in the error key.
87 * "recordRef" => (for "db" type) : Reference to DB record on the form [table]:[uid]. May not necessarily exist.
88 * "title" => Title of element (for backend information)
89 * "description" => Description of element (for backend information)
90 * )
91 *
92 */
93
94
95 /**
96 * Class for processing of the default soft reference types for CMS:
97 *
98 * - 'substitute' : A full field value targeted for manual substitution (for import /export features)
99 * - 'notify' : Just report if a value is found, nothing more.
100 * - 'images' : HTML <img> tags for RTE images / images from fileadmin/
101 * - 'typolink' : references to page id or file, possibly with anchor/target, possibly commaseparated list.
102 * - 'typolink_tag' : As typolink, but searching for <link> tag to encapsulate it.
103 * - 'TSconfig' processing (filerefs? Domains? what do we know...)
104 * - 'TStemplate' : freetext references to "fileadmin/" files.
105 * - 'email' : Email highlight
106 * - 'url' : URL highlights (with a scheme)
107 *
108 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
109 * @package TYPO3
110 * @subpackage t3lib
111 */
112 class t3lib_softrefproc {
113
114 // external configuration
115 var $fileAdminDir = 'fileadmin';
116
117
118 // Internal:
119 var $tokenID_basePrefix = '';
120
121 /**
122 * Main function through which all processing happens
123 *
124 * @param string Database table name
125 * @param string Field name for which processing occurs
126 * @param integer UID of the record
127 * @param string The content/value of the field
128 * @param string The softlink parser key. This is only interesting if more than one parser is grouped in the same class. That is the case with this parser.
129 * @param array Parameters of the softlink parser. Basically this is the content inside optional []-brackets after the softref keys. Parameters are exploded by ";"
130 * @param string If running from inside a FlexForm structure, this is the path of the tag.
131 * @return array Result array on positive matches, see description above. Otherwise FALSE
132 */
133 function findRef($table, $field, $uid, $content, $spKey, $spParams, $structurePath = '') {
134
135 $retVal = FALSE;
136
137 $this->tokenID_basePrefix = $table . ':' . $uid . ':' . $field . ':' . $structurePath . ':' . $spKey;
138
139 switch ($spKey) {
140 case 'notify': // Simple notification
141 $resultArray = array(
142 'elements' => array(
143 array(
144 'matchString' => $content
145 )
146 )
147 );
148 $retVal = $resultArray;
149 break;
150 case 'substitute':
151 $tokenID = $this->makeTokenID();
152 $resultArray = array(
153 'content' => '{softref:' . $tokenID . '}',
154 'elements' => array(
155 array(
156 'matchString' => $content,
157 'subst' => array(
158 'type' => 'string',
159 'tokenID' => $tokenID,
160 'tokenValue' => $content
161 )
162 )
163 )
164 );
165 $retVal = $resultArray;
166 break;
167 case 'images':
168 $retVal = $this->findRef_images($content, $spParams);
169 break;
170 case 'typolink':
171 $retVal = $this->findRef_typolink($content, $spParams);
172 break;
173 case 'typolink_tag':
174 $retVal = $this->findRef_typolink_tag($content, $spParams);
175 break;
176 case 'ext_fileref':
177 $retVal = $this->findRef_extension_fileref($content, $spParams);
178 break;
179 case 'TStemplate':
180 $retVal = $this->findRef_TStemplate($content, $spParams);
181 break;
182 case 'TSconfig':
183 $retVal = $this->findRef_TSconfig($content, $spParams);
184 break;
185 case 'email':
186 $retVal = $this->findRef_email($content, $spParams);
187 break;
188 case 'url':
189 $retVal = $this->findRef_url($content, $spParams);
190 break;
191 default:
192 $retVal = FALSE;
193 break;
194 }
195
196 return $retVal;
197 }
198
199 /**
200 * Finding image tags in the content.
201 * All images that are not from external URLs will be returned with an info text
202 * Will only return files in fileadmin/ and files in uploads/ folders which are prefixed with "RTEmagic[C|P]_" for substitution
203 * Any "clear.gif" images are ignored.
204 *
205 * @param string The input content to analyse
206 * @param array Parameters set for the softref parser key in TCA/columns
207 * @return array Result array on positive matches, see description above. Otherwise FALSE
208 */
209 function findRef_images($content, $spParams) {
210
211 // Start HTML parser and split content by image tag:
212 $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
213 $splitContent = $htmlParser->splitTags('img', $content);
214 $elements = array();
215
216 // Traverse splitted parts:
217 foreach ($splitContent as $k => $v) {
218 if ($k % 2) {
219
220 // Get file reference:
221 $attribs = $htmlParser->get_tag_attributes($v);
222 $srcRef = t3lib_div::htmlspecialchars_decode($attribs[0]['src']);
223 $pI = pathinfo($srcRef);
224
225 // If it looks like a local image, continue. Otherwise ignore it.
226 $absPath = t3lib_div::getFileAbsFileName(PATH_site . $srcRef);
227 if (!$pI['scheme'] && !$pI['query'] && $absPath && $srcRef !== 'clear.gif') {
228
229 // Initialize the element entry with info text here:
230 $tokenID = $this->makeTokenID($k);
231 $elements[$k] = array();
232 $elements[$k]['matchString'] = $v;
233
234 // If the image seems to be from fileadmin/ folder or an RTE image, then proceed to set up substitution token:
235 if (t3lib_div::isFirstPartOfStr($srcRef, $this->fileAdminDir . '/') || (t3lib_div::isFirstPartOfStr($srcRef, 'uploads/') && preg_match('/^RTEmagicC_/', basename($srcRef)))) {
236 // Token and substitute value:
237 if (strstr($splitContent[$k], $attribs[0]['src'])) { // Make sure the value we work on is found and will get substituted in the content (Very important that the src-value is not DeHSC'ed)
238 $splitContent[$k] = str_replace($attribs[0]['src'], '{softref:' . $tokenID . '}', $splitContent[$k]); // Substitute value with token (this is not be an exact method if the value is in there twice, but we assume it will not)
239 $elements[$k]['subst'] = array(
240 'type' => 'file',
241 'relFileName' => $srcRef,
242 'tokenID' => $tokenID,
243 'tokenValue' => $attribs[0]['src'],
244 );
245 if (!@is_file($absPath)) { // Finally, notice if the file does not exist.
246 $elements[$k]['error'] = 'File does not exist!';
247 }
248 } else {
249 $elements[$k]['error'] = 'Could not substitute image source with token!';
250 }
251 }
252 }
253 }
254 }
255
256 // Return result:
257 if (count($elements)) {
258 $resultArray = array(
259 'content' => implode('', $splitContent),
260 'elements' => $elements
261 );
262
263 return $resultArray;
264 }
265 }
266
267 /**
268 * TypoLink value processing.
269 * Will process input value as a TypoLink value.
270 *
271 * @param string The input content to analyse
272 * @param array Parameters set for the softref parser key in TCA/columns. value "linkList" will split the string by comma before processing.
273 * @return array Result array on positive matches, see description above. Otherwise FALSE
274 * @see tslib_content::typolink(), getTypoLinkParts()
275 */
276 function findRef_typolink($content, $spParams) {
277
278 // First, split the input string by a comma if the "linkList" parameter is set.
279 // An example: the link field for images in content elements of type "textpic" or "image". This field CAN be configured to define a link per image, separated by comma.
280 if (is_array($spParams) && in_array('linkList', $spParams)) {
281 $linkElement = explode(',', $content); // Preserving whitespace on purpose.
282 } else {
283 $linkElement = array($content); // If only one element, just set in this array to make it easy below.
284 }
285
286 // Traverse the links now:
287 $elements = array();
288 foreach ($linkElement as $k => $typolinkValue) {
289 $tLP = $this->getTypoLinkParts($typolinkValue);
290 $linkElement[$k] = $this->setTypoLinkPartsElement($tLP, $elements, $typolinkValue, $k);
291 }
292
293 // Return output:
294 if (count($elements)) {
295 $resultArray = array(
296 'content' => implode(',', $linkElement),
297 'elements' => $elements
298 );
299
300 return $resultArray;
301 }
302 }
303
304 /**
305 * TypoLink tag processing.
306 * Will search for <link ...> tags in the content string and process any found.
307 *
308 * @param string The input content to analyse
309 * @param array Parameters set for the softref parser key in TCA/columns
310 * @return array Result array on positive matches, see description above. Otherwise FALSE
311 * @see tslib_content::typolink(), getTypoLinkParts()
312 */
313 function findRef_typolink_tag($content, $spParams) {
314
315 // Parse string for special TYPO3 <link> tag:
316 $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
317 $linkTags = $htmlParser->splitTags('link', $content);
318
319 // Traverse result:
320 $elements = array();
321 foreach ($linkTags as $k => $foundValue) {
322 if ($k % 2) {
323 $typolinkValue = preg_replace('/<LINK[[:space:]]+/i', '', substr($foundValue, 0, -1));
324 $tLP = $this->getTypoLinkParts($typolinkValue);
325 $linkTags[$k] = '<LINK ' . $this->setTypoLinkPartsElement($tLP, $elements, $typolinkValue, $k) . '>';
326 }
327 }
328
329 // Return output:
330 if (count($elements)) {
331 $resultArray = array(
332 'content' => implode('', $linkTags),
333 'elements' => $elements
334 );
335
336 return $resultArray;
337 }
338 }
339
340 /**
341 * Processing the content expected from a TypoScript template
342 * This content includes references to files in fileadmin/ folders and file references in HTML tags like <img src="">, <a href=""> and <form action="">
343 *
344 * @param string The input content to analyse
345 * @param array Parameters set for the softref parser key in TCA/columns
346 * @return array Result array on positive matches, see description above. Otherwise FALSE
347 */
348 function findRef_TStemplate($content, $spParams) {
349 $elements = array();
350
351 // First, try to find images and links:
352 $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
353 $splitContent = $htmlParser->splitTags('img,a,form', $content);
354
355 // Traverse splitted parts:
356 foreach ($splitContent as $k => $v) {
357 if ($k % 2) {
358
359 $attribs = $htmlParser->get_tag_attributes($v);
360
361 $attributeName = '';
362 switch ($htmlParser->getFirstTagName($v)) {
363 case 'img':
364 $attributeName = 'src';
365 break;
366 case 'a':
367 $attributeName = 'href';
368 break;
369 case 'form':
370 $attributeName = 'action';
371 break;
372 }
373
374 // Get file reference:
375 if (isset($attribs[0][$attributeName])) {
376 $srcRef = t3lib_div::htmlspecialchars_decode($attribs[0][$attributeName]);
377
378 // Set entry:
379 $tokenID = $this->makeTokenID($k);
380 $elements[$k] = array();
381 $elements[$k]['matchString'] = $v;
382
383 // OK, if it looks like a local file from fileadmin/, include it:
384 $pI = pathinfo($srcRef);
385 $absPath = t3lib_div::getFileAbsFileName(PATH_site . $srcRef);
386 if (t3lib_div::isFirstPartOfStr($srcRef, $this->fileAdminDir . '/') && !$pI['query'] && $absPath) {
387
388 // Token and substitute value:
389 if (strstr($splitContent[$k], $attribs[0][$attributeName])) { // Very important that the src-value is not DeHSC'ed
390 $splitContent[$k] = str_replace($attribs[0][$attributeName], '{softref:' . $tokenID . '}', $splitContent[$k]);
391 $elements[$k]['subst'] = array(
392 'type' => 'file',
393 'relFileName' => $srcRef,
394 'tokenID' => $tokenID,
395 'tokenValue' => $attribs[0][$attributeName],
396 );
397 if (!@is_file($absPath)) {
398 $elements[$k]['error'] = 'File does not exist!';
399 }
400 } else {
401 $elements[$k]['error'] = 'Could not substitute attribute (' . $attributeName . ') value with token!';
402 }
403 }
404 }
405 }
406 }
407 $content = implode('', $splitContent);
408
409 // Process free fileadmin/ references as well:
410 $content = $this->fileadminReferences($content, $elements);
411
412 // Return output:
413 if (count($elements)) {
414 $resultArray = array(
415 'content' => $content,
416 'elements' => $elements
417 );
418 return $resultArray;
419 }
420 }
421
422 /**
423 * Processes possible references inside of Page and User TSconfig fields.
424 * Currently this only includes file references to fileadmin/ but in fact there are currently no properties that supports such references.
425 *
426 * @param string The input content to analyse
427 * @param array Parameters set for the softref parser key in TCA/columns
428 * @return array Result array on positive matches, see description above. Otherwise FALSE
429 */
430 function findRef_TSconfig($content, $spParams) {
431 $elements = array();
432
433 // Process free fileadmin/ references from TSconfig
434 $content = $this->fileadminReferences($content, $elements);
435
436 // Return output:
437 if (count($elements)) {
438 $resultArray = array(
439 'content' => $content,
440 'elements' => $elements
441 );
442 return $resultArray;
443 }
444 }
445
446 /**
447 * Finding email addresses in content and making them substitutable.
448 *
449 * @param string The input content to analyse
450 * @param array Parameters set for the softref parser key in TCA/columns
451 * @return array Result array on positive matches, see description above. Otherwise FALSE
452 */
453 function findRef_email($content, $spParams) {
454 $resultArray = array();
455
456 // email:
457 $parts = preg_split("/([^[:alnum:]]+)([A-Za-z0-9\._-]+[@][A-Za-z0-9\._-]+[\.].[A-Za-z0-9]+)/", ' ' . $content . ' ', 10000, PREG_SPLIT_DELIM_CAPTURE);
458 foreach ($parts as $idx => $value) {
459 if ($idx % 3 == 2) {
460
461 $tokenID = $this->makeTokenID($idx);
462 $elements[$idx] = array();
463 $elements[$idx]['matchString'] = $value;
464
465 if (is_array($spParams) && in_array('subst', $spParams)) {
466 $parts[$idx] = '{softref:' . $tokenID . '}';
467 $elements[$idx]['subst'] = array(
468 'type' => 'string',
469 'tokenID' => $tokenID,
470 'tokenValue' => $value,
471 );
472 }
473 }
474 }
475
476 // Return output:
477 if (count($elements)) {
478 $resultArray = array(
479 'content' => substr(implode('', $parts), 1, -1),
480 'elements' => $elements
481 );
482 return $resultArray;
483 }
484 }
485
486 /**
487 * Finding URLs in content
488 *
489 * @param string The input content to analyse
490 * @param array Parameters set for the softref parser key in TCA/columns
491 * @return array Result array on positive matches, see description above. Otherwise FALSE
492 */
493 function findRef_url($content, $spParams) {
494 $resultArray = array();
495
496 // Fileadmin files:
497 $parts = preg_split("/([^[:alnum:]\"']+)((http|ftp):\/\/[^[:space:]\"'<>]*)([[:space:]])/", ' ' . $content . ' ', 10000, PREG_SPLIT_DELIM_CAPTURE);
498
499 foreach ($parts as $idx => $value) {
500 if ($idx % 5 == 3) {
501 unset($parts[$idx]);
502 }
503 if ($idx % 5 == 2) {
504
505 $tokenID = $this->makeTokenID($idx);
506 $elements[$idx] = array();
507 $elements[$idx]['matchString'] = $value;
508
509 if (is_array($spParams) && in_array('subst', $spParams)) {
510 $parts[$idx] = '{softref:' . $tokenID . '}';
511 $elements[$idx]['subst'] = array(
512 'type' => 'string',
513 'tokenID' => $tokenID,
514 'tokenValue' => $value,
515 );
516 }
517 }
518 }
519
520 // Return output:
521 if (count($elements)) {
522 $resultArray = array(
523 'content' => substr(implode('', $parts), 1, -1),
524 'elements' => $elements
525 );
526 return $resultArray;
527 }
528 }
529
530 /**
531 * Finding reference to files from extensions in content, but only to notify about their existence. No substitution
532 *
533 * @param string The input content to analyse
534 * @param array Parameters set for the softref parser key in TCA/columns
535 * @return array Result array on positive matches, see description above. Otherwise FALSE
536 */
537 function findRef_extension_fileref($content, $spParams) {
538 $resultArray = array();
539
540 // Fileadmin files:
541 $parts = preg_split("/([^[:alnum:]\"']+)(EXT:[[:alnum:]_]+\/[^[:space:]\"',]*)/", ' ' . $content . ' ', 10000, PREG_SPLIT_DELIM_CAPTURE);
542
543 foreach ($parts as $idx => $value) {
544 if ($idx % 3 == 2) {
545
546 $tokenID = $this->makeTokenID($idx);
547 $elements[$idx] = array();
548 $elements[$idx]['matchString'] = $value;
549 }
550 }
551
552 // Return output:
553 if (count($elements)) {
554 $resultArray = array(
555 'content' => substr(implode('', $parts), 1, -1),
556 'elements' => $elements
557 );
558 return $resultArray;
559 }
560 }
561
562
563 /*************************
564 *
565 * Helper functions
566 *
567 *************************/
568
569 /**
570 * Searches the content for a reference to a file in "fileadmin/".
571 * When a match is found it will get substituted with a token.
572 *
573 * @param string Input content to analyse
574 * @param array Element array to be modified with new entries. Passed by reference.
575 * @return string Output content, possibly with tokens inserted.
576 */
577 function fileadminReferences($content, &$elements) {
578
579 // Fileadmin files are found
580 $parts = preg_split("/([^[:alnum:]]+)(" . $this->fileAdminDir . "\/[^[:space:]\"'<>]*)/", ' ' . $content . ' ', 10000, PREG_SPLIT_DELIM_CAPTURE);
581
582 // Traverse files:
583 foreach ($parts as $idx => $value) {
584 if ($idx % 3 == 2) {
585
586 // when file is found, set up an entry for the element:
587 $tokenID = $this->makeTokenID('fileadminReferences:' . $idx);
588 $elements['fileadminReferences.' . $idx] = array();
589 $elements['fileadminReferences.' . $idx]['matchString'] = $value;
590 $elements['fileadminReferences.' . $idx]['subst'] = array(
591 'type' => 'file',
592 'relFileName' => $value,
593 'tokenID' => $tokenID,
594 'tokenValue' => $value,
595 );
596 $parts[$idx] = '{softref:' . $tokenID . '}';
597
598 // Check if the file actually exists:
599 $absPath = t3lib_div::getFileAbsFileName(PATH_site . $value);
600 if (!@is_file($absPath)) {
601 $elements['fileadminReferences.' . $idx]['error'] = 'File does not exist!';
602 }
603 }
604 }
605
606 // Implode the content again, removing prefixed and trailing white space:
607 return substr(implode('', $parts), 1, -1);
608 }
609
610 /**
611 * Analyse content as a TypoLink value and return an array with properties.
612 * TypoLinks format is: <link [typolink] [browser target] [css class]>. See tslib_content::typolink()
613 * The syntax of the [typolink] part is: [typolink] = [page id or alias][,[type value]][#[anchor, if integer = tt_content uid]]
614 * The extraction is based on how tslib_content::typolink() behaves.
615 *
616 * @param string TypoLink value.
617 * @return array Array with the properties of the input link specified. The key "LINK_TYPE" will reveal the type. If that is blank it could not be determined.
618 * @see tslib_content::typolink(), setTypoLinkPartsElement()
619 */
620 function getTypoLinkParts($typolinkValue) {
621 $finalTagParts = array();
622
623 // Split by space into link / target / class
624 list($link_param, $browserTarget, $cssClass) = t3lib_div::trimExplode(' ', $typolinkValue, 1);
625 if (strlen($browserTarget)) {
626 $finalTagParts['target'] = $browserTarget;
627 }
628 if (strlen($cssClass)) {
629 $finalTagParts['class'] = $cssClass;
630 }
631
632 // Parse URL:
633 $pU = @parse_url($link_param);
634
635 // Detecting the kind of reference:
636 if (strstr($link_param, '@') && !$pU['scheme']) { // If it's a mail address:
637 $link_param = preg_replace('/^mailto:/i', '', $link_param);
638
639 $finalTagParts['LINK_TYPE'] = 'mailto';
640 $finalTagParts['url'] = trim($link_param);
641 } else {
642 $isLocalFile = 0;
643 $fileChar = intval(strpos($link_param, '/'));
644 $urlChar = intval(strpos($link_param, '.'));
645
646 // Detects if a file is found in site-root (or is a 'virtual' simulateStaticDocument file!) and if so it will be treated like a normal file.
647 list($rootFileDat) = explode('?', rawurldecode($link_param));
648 $containsSlash = strstr($rootFileDat, '/');
649 $rFD_fI = pathinfo($rootFileDat);
650 if (trim($rootFileDat) && !$containsSlash && (@is_file(PATH_site . $rootFileDat) || t3lib_div::inList('php,html,htm', strtolower($rFD_fI['extension'])))) {
651 $isLocalFile = 1;
652 } elseif ($containsSlash) {
653 $isLocalFile = 2; // Adding this so realurl directories are linked right (non-existing).
654 }
655
656 if ($pU['scheme'] || ($isLocalFile != 1 && $urlChar && (!$containsSlash || $urlChar < $fileChar))) { // url (external): If doubleSlash or if a '.' comes before a '/'.
657 $finalTagParts['LINK_TYPE'] = 'url';
658 $finalTagParts['url'] = $link_param;
659 } elseif ($containsSlash || $isLocalFile) { // file (internal)
660 $splitLinkParam = explode('?', $link_param);
661 if (file_exists(rawurldecode($splitLinkParam[0])) || $isLocalFile) {
662 $finalTagParts['LINK_TYPE'] = 'file';
663 $finalTagParts['filepath'] = rawurldecode($splitLinkParam[0]);
664 $finalTagParts['query'] = $splitLinkParam[1];
665 }
666 } else {
667 // integer or alias (alias is without slashes or periods or commas, that is
668 // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
669
670 $finalTagParts['LINK_TYPE'] = 'page';
671
672 $link_params_parts = explode('#', $link_param);
673 $link_param = trim($link_params_parts[0]); // Link-data del
674
675 if (strlen($link_params_parts[1])) {
676 $finalTagParts['anchor'] = trim($link_params_parts[1]);
677 }
678
679 // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/? pair
680 $pairParts = t3lib_div::trimExplode(',', $link_param);
681 if (count($pairParts) > 1) {
682 $link_param = $pairParts[0];
683 $finalTagParts['type'] = $pairParts[1]; // Overruling 'type'
684 }
685
686 // Checking if the id-parameter is an alias.
687 if (strlen($link_param)) {
688 if (!t3lib_div::testInt($link_param)) {
689 $finalTagParts['alias'] = $link_param;
690 $link_param = $this->getPageIdFromAlias($link_param);
691 }
692
693 $finalTagParts['page_id'] = intval($link_param);
694 }
695 }
696 }
697
698 return $finalTagParts;
699 }
700
701 /**
702 * Recompile a TypoLink value from the array of properties made with getTypoLinkParts() into an elements array
703 *
704 * @param array TypoLink properties
705 * @param array Array of elements to be modified with substitution / information entries.
706 * @param string The content to process.
707 * @param integer Index value of the found element - user to make unique but stable tokenID
708 * @return string The input content, possibly containing tokens now according to the added substitution entries in $elements
709 * @see getTypoLinkParts()
710 */
711 function setTypoLinkPartsElement($tLP, &$elements, $content, $idx) {
712
713 // Initialize, set basic values. In any case a link will be shown
714 $tokenID = $this->makeTokenID('setTypoLinkPartsElement:' . $idx);
715 $elements[$tokenID . ':' . $idx] = array();
716 $elements[$tokenID . ':' . $idx]['matchString'] = $content;
717
718 // Based on link type, maybe do more:
719 switch ((string) $tLP['LINK_TYPE']) {
720 case 'mailto':
721 case 'url':
722 // Mail addresses and URLs can be substituted manually:
723 $elements[$tokenID . ':' . $idx]['subst'] = array(
724 'type' => 'string',
725 'tokenID' => $tokenID,
726 'tokenValue' => $tLP['url'],
727 );
728 // Output content will be the token instead:
729 $content = '{softref:' . $tokenID . '}';
730 break;
731 case 'file':
732 // Process files found in fileadmin directory:
733 if (!$tLP['query']) { // We will not process files which has a query added to it. That will look like a script we don't want to move.
734 if (t3lib_div::isFirstPartOfStr($tLP['filepath'], $this->fileAdminDir . '/')) { // File must be inside fileadmin/
735
736 // Set up the basic token and token value for the relative file:
737 $elements[$tokenID . ':' . $idx]['subst'] = array(
738 'type' => 'file',
739 'relFileName' => $tLP['filepath'],
740 'tokenID' => $tokenID,
741 'tokenValue' => $tLP['filepath'],
742 );
743
744 // Depending on whether the file exists or not we will set the
745 $absPath = t3lib_div::getFileAbsFileName(PATH_site . $tLP['filepath']);
746 if (!@is_file($absPath)) {
747 $elements[$tokenID . ':' . $idx]['error'] = 'File does not exist!';
748 }
749
750 // Output content will be the token instead
751 $content = '{softref:' . $tokenID . '}';
752 } else {
753 return $content;
754 }
755 } else {
756 return $content;
757 }
758 break;
759 case 'page':
760 // Rebuild page reference typolink part:
761 $content = '';
762
763 // Set page id:
764 if ($tLP['page_id']) {
765 $content .= '{softref:' . $tokenID . '}';
766 $elements[$tokenID . ':' . $idx]['subst'] = array(
767 'type' => 'db',
768 'recordRef' => 'pages:' . $tLP['page_id'],
769 'tokenID' => $tokenID,
770 'tokenValue' => $tLP['alias'] ? $tLP['alias'] : $tLP['page_id'], // Set page alias if that was used.
771 );
772 }
773
774 // Add type if applicable
775 if (strlen($tLP['type'])) {
776 $content .= ',' . $tLP['type'];
777 }
778
779 // Add anchor if applicable
780 if (strlen($tLP['anchor'])) {
781 if (t3lib_div::testInt($tLP['anchor'])) { // Anchor is assumed to point to a content elements:
782 // Initialize a new entry because we have a new relation:
783 $newTokenID = $this->makeTokenID('setTypoLinkPartsElement:anchor:' . $idx);
784 $elements[$newTokenID . ':' . $idx] = array();
785 $elements[$newTokenID . ':' . $idx]['matchString'] = 'Anchor Content Element: ' . $tLP['anchor'];
786
787 $content .= '#{softref:' . $newTokenID . '}';
788 $elements[$newTokenID . ':' . $idx]['subst'] = array(
789 'type' => 'db',
790 'recordRef' => 'tt_content:' . $tLP['anchor'],
791 'tokenID' => $newTokenID,
792 'tokenValue' => $tLP['anchor'],
793 );
794 } else { // Anchor is a hardcoded string
795 $content .= '#' . $tLP['type'];
796 }
797 }
798 break;
799 default:
800 {
801 $elements[$tokenID . ':' . $idx]['error'] = 'Couldn\t decide typolink mode.';
802 return $content;
803 }
804 break;
805 }
806
807 // Finally, for all entries that was rebuild with tokens, add target and class in the end:
808 if (strlen($content) && strlen($tLP['target'])) {
809 $content .= ' ' . $tLP['target'];
810 if (strlen($tLP['class'])) {
811 $content .= ' ' . $tLP['class'];
812 }
813 }
814
815 // Return rebuilt typolink value:
816 return $content;
817 }
818
819 /**
820 * Look up and return page uid for alias
821 *
822 * @param integer Page alias string value
823 * @return integer Page uid corresponding to alias value.
824 */
825 function getPageIdFromAlias($link_param) {
826 $pRec = t3lib_BEfunc::getRecordsByField('pages', 'alias', $link_param);
827
828 return $pRec[0]['uid'];
829 }
830
831 /**
832 * Make Token ID for input index.
833 *
834 * @param string suffix value.
835 * @return string Token ID
836 */
837 function makeTokenID($index = '') {
838 return md5($this->tokenID_basePrefix . ':' . $index);
839 }
840 }
841
842 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_softrefproc.php'])) {
843 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_softrefproc.php']);
844 }
845
846 ?>