9b9444b7fcc7ad7bbdb128e1b86ba0e38ab71f4b
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / LinkHandling / LinkService.php
1 <?php
2 declare (strict_types = 1);
3 namespace TYPO3\CMS\Core\LinkHandling;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\SingletonInterface;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Class LinkService, responsible to find what kind of resource (type) is used
23 * to link to (email, external url, file, page etc)
24 * with the possibility to get a system-wide understandable "urn" to identify
25 * what type it actually is, based on the scheme or prefix.
26 */
27 class LinkService implements SingletonInterface
28 {
29
30 const TYPE_PAGE = 'page';
31 const TYPE_URL = 'url';
32 const TYPE_EMAIL = 'email';
33 const TYPE_FILE = 'file';
34 const TYPE_FOLDER = 'folder';
35 const TYPE_UNKNOWN = 'unknown';
36
37 /**
38 * All registered LinkHandlers
39 *
40 * @var LinkHandlingInterface[]
41 */
42 protected $handlers;
43
44 /**
45 * LinkService constructor initializes the registered handlers.
46 */
47 public function __construct()
48 {
49 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['linkHandler'])) {
50 foreach ($GLOBALS['TYPO3_CONF_VARS']['SYS']['linkHandler'] as $type => $handler) {
51 if (!is_object($this->handlers[$type])) {
52 $this->handlers[$type] = GeneralUtility::makeInstance($handler);
53 }
54 }
55 }
56 }
57
58 /**
59 * Part of the typolink construction functionality, called by typoLink()
60 * Used to resolve "legacy"-based typolinks and URNs.
61 *
62 * Tries to get the type of the link from the link parameter
63 * could be
64 * - "mailto" an email address
65 * - "url" external URL
66 * - "file" a local file (checked AFTER getPublicUrl() is called)
67 * - "page" a page (integer or alias)
68 *
69 * Does NOT check if the page exists or the file exists.
70 *
71 * @param string $linkParameter could be "fileadmin/myfile.jpg", "info@typo3.org", "13" or "http://www.typo3.org"
72 * @return array
73 */
74 public function resolve(string $linkParameter): array
75 {
76 try {
77 // Check if the new syntax with "t3://" is used
78 return $this->resolveByStringRepresentation($linkParameter);
79 } catch (\InvalidArgumentException $e) {
80 $legacyLinkNotationConverter = GeneralUtility::makeInstance(LegacyLinkNotationConverter::class);
81 return $legacyLinkNotationConverter->resolve($linkParameter);
82 }
83 }
84
85 /**
86 * Returns a array with data interpretation of the link target, something like t3:blabla.
87 *
88 * @param string $urn
89 * @return array
90 */
91 public function resolveByStringRepresentation(string $urn): array
92 {
93 // linking to any t3:// syntax
94 if (stripos($urn, 't3://') === 0) {
95 // lets parse the urn
96 $urnParsed = parse_url($urn);
97 $type = $urnParsed['host'];
98 if (isset($urnParsed['query'])) {
99 parse_str($urnParsed['query'], $data);
100 } else {
101 $data = [];
102 }
103 $fragment = $urnParsed['fragment'] ?? null;
104
105 if (is_object($this->handlers[$type])) {
106 $result = $this->handlers[$type]->resolveHandlerData($data);
107 $result['type'] = $type;
108 } else {
109 throw new \InvalidArgumentException('LinkHandler for ' . $type . ' was not registered', 1460581769);
110 }
111 // this was historically named "section"
112 if ($fragment) {
113 $result['fragment'] = $fragment;
114 }
115 } elseif (stripos($urn, '://') && $this->handlers[self::TYPE_URL]) {
116 $result = $this->handlers[self::TYPE_URL]->resolveHandlerData(['url' => $urn]);
117 $result['type'] = self::TYPE_URL;
118 } elseif (stripos($urn, 'mailto:') === 0 && $this->handlers[self::TYPE_EMAIL]) {
119 $result = $this->handlers[self::TYPE_EMAIL]->resolveHandlerData(['email' => $urn]);
120 $result['type'] = self::TYPE_EMAIL;
121 } else {
122 throw new \InvalidArgumentException('No valid URN to resolve found', 1457177667);
123 }
124
125 return $result;
126 }
127
128 /**
129 * Returns a string interpretation of the link target, something like
130 *
131 * - t3://page?uid=23&my=value#cool
132 * - https://www.typo3.org/
133 * - t3://file?uid=13
134 * - t3://folder?storage=2&identifier=/my/folder/
135 * - mailto:mac@safe.com
136 *
137 * @param array $parameters
138 * @return string
139 * @throws \InvalidArgumentException
140 */
141 public function asString(array $parameters): string
142 {
143 if (is_object($this->handlers[$parameters['type']])) {
144 return $this->handlers[$parameters['type']]->asString($parameters);
145 }
146 throw new \InvalidArgumentException('No valid handlers found for type: ' . $parameters['type'], 1460629247);
147 }
148 }