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