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