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