TYPO3 CMS  TYPO3_8-7
LegacyLinkNotationConverter.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
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 
24 
32 {
33 
37  protected $resourceFactory;
38 
56  public function resolve(string $linkParameter): array
57  {
58  if (stripos(rawurldecode(trim($linkParameter)), 'phar://') === 0) {
59  throw new \RuntimeException(
60  'phar scheme not allowed as soft reference target',
61  1530030673
62  );
63  }
64 
65  $result = [];
66  // Parse URL scheme
67  $scheme = parse_url($linkParameter, PHP_URL_SCHEME);
68 
69  // Resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
70  if (stripos($linkParameter, 'file:') === 0) {
71  $result = $this->getFileOrFolderObjectFromMixedIdentifier(substr($linkParameter, 5));
72  } elseif (GeneralUtility::validEmail(parse_url($linkParameter, PHP_URL_PATH))) {
73  $result['type'] = LinkService::TYPE_EMAIL;
74  $result['email'] = $linkParameter;
75  } elseif (strpos($linkParameter, ':') !== false) {
76  // Check for link-handler keyword
77  list($linkHandlerKeyword, $linkHandlerValue) = explode(':', $linkParameter, 2);
78  $result['type'] = strtolower(trim($linkHandlerKeyword));
79  $result['url'] = $linkParameter;
80  $result['value'] = $linkHandlerValue;
81  if ($result['type'] === LinkService::TYPE_RECORD) {
82  list($a['identifier'], $tableAndUid) = explode(':', $linkHandlerValue, 2);
83  $tableAndUid = explode(':', $tableAndUid);
84  if (count($tableAndUid) > 1) {
85  $a['table'] = $tableAndUid[0];
86  $a['uid'] = $tableAndUid[1];
87  } else {
88  // this case can happen if there is the very old linkhandler syntax, which was only record:<table>:<uid>
89  $a['table'] = $a['identifier'];
90  $a['uid'] = $tableAndUid[0];
91  }
92  $result = array_merge($result, $a);
93  }
94  } else {
95  // special handling without a scheme
96  $isLocalFile = 0;
97  $fileChar = (int)strpos($linkParameter, '/');
98  $urlChar = (int)strpos($linkParameter, '.');
99 
100  $isIdOrAlias = MathUtility::canBeInterpretedAsInteger($linkParameter);
101  $matches = [];
102  // capture old RTE links relative to TYPO3_mainDir
103  if (preg_match('#../(?:index\\.php)?\\?id=([^&]+)#', $linkParameter, $matches)) {
104  $linkParameter = $matches[1];
105  $isIdOrAlias = true;
106  }
107  $containsSlash = false;
108  if (!$isIdOrAlias) {
109  // Detects if a file is found in site-root and if so it will be treated like a normal file.
110  list($rootFileDat) = explode('?', rawurldecode($linkParameter));
111  $containsSlash = strpos($rootFileDat, '/') !== false;
112  $pathInfo = pathinfo($rootFileDat);
113  $fileExtension = strtolower(($pathInfo['extension'] ?? ''));
114  if (!$containsSlash
115  && trim($rootFileDat)
116  && (
117  @is_file(PATH_site . $rootFileDat)
118  || $fileExtension === 'php'
119  || $fileExtension === 'html'
120  || $fileExtension === 'htm'
121  )
122  ) {
123  $isLocalFile = 1;
124  } elseif ($containsSlash) {
125  // Adding this so realurl directories are linked right (non-existing).
126  $isLocalFile = 2;
127  }
128  }
129 
130  // url (external): If doubleSlash or if a '.' comes before a '/'.
131  if (!$isIdOrAlias && $isLocalFile !== 1 && $urlChar && (!$containsSlash || $urlChar < $fileChar)) {
132  $result['type'] = LinkService::TYPE_URL;
133  if (!$scheme) {
134  $result['url'] = 'http://' . $linkParameter;
135  } else {
136  $result['url'] = $linkParameter;
137  }
138  // file (internal) or folder
139  } elseif ($containsSlash || $isLocalFile) {
140  $result = $this->getFileOrFolderObjectFromMixedIdentifier($linkParameter);
141  } else {
142  // Integer or alias (alias is without slashes or periods or commas, that is
143  // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
144  $result = $this->resolvePageRelatedParameters($linkParameter);
145  }
146  }
147 
148  return $result;
149  }
150 
158  protected function resolvePageRelatedParameters(string $data): array
159  {
160  $result = ['type' => LinkService::TYPE_PAGE];
161  if (strpos($data, '#') !== false) {
162  list($data, $result['fragment']) = explode('#', $data, 2);
163  }
164  // check for additional parameters
165  if (strpos($data, '?') !== false) {
166  list($data, $result['parameters']) = explode('?', $data, 2);
167  } elseif (strpos($data, '&') !== false) {
168  list($data, $result['parameters']) = explode('&', $data, 2);
169  }
170  if (empty($data)) {
171  $result['pageuid'] = 'current';
172  } elseif ($data[0] === '#') {
173  $result['pageuid'] = 'current';
174  $result['fragment'] = substr($data, 1);
175  } elseif (strpos($data, ',') !== false) {
176  $data = rtrim($data, ',');
177  list($result['pageuid'], $result['pagetype']) = explode(',', $data, 2);
178  } elseif (strpos($data, '/') !== false) {
179  $data = explode('/', trim($data, '/'));
180  $result['pageuid'] = array_shift($data);
181  foreach ($data as $k => $item) {
182  if ($data[$k] % 2 === 0 && !empty($data[$k + 1])) {
183  $result['page' . $data[$k]] = $data[$k + 1];
184  }
185  }
186  } else {
187  $result['pageuid'] = $data;
188  }
189 
190  // expect an alias
191  if (!MathUtility::canBeInterpretedAsInteger($result['pageuid']) && $result['pageuid'] !== 'current') {
192  $result['pagealias'] = $result['pageuid'];
193  unset($result['pageuid']);
194  }
195 
196  return $result;
197  }
198 
206  protected function getFileOrFolderObjectFromMixedIdentifier(string $mixedIdentifier): array
207  {
208  $result = [];
209  try {
210  $fileOrFolderObject = $this->getResourceFactory()->retrieveFileOrFolderObject($mixedIdentifier);
211  // Link to a folder or file
212  if ($fileOrFolderObject instanceof File) {
213  $result['type'] = LinkService::TYPE_FILE;
214  $result['file'] = $fileOrFolderObject;
215  } elseif ($fileOrFolderObject instanceof Folder) {
216  $result['type'] = LinkService::TYPE_FOLDER;
217  $result['folder'] = $fileOrFolderObject;
218  } else {
219  $result['type'] = LinkService::TYPE_UNKNOWN;
220  $result['file'] = $mixedIdentifier;
221  }
222  } catch (\RuntimeException $e) {
223  // Element wasn't found
224  $result['type'] = LinkService::TYPE_UNKNOWN;
225  $result['file'] = $mixedIdentifier;
226  } catch (ResourceDoesNotExistException $e) {
227  // Resource was not found
228  $result['type'] = LinkService::TYPE_UNKNOWN;
229  $result['file'] = $mixedIdentifier;
230  }
231 
232  return $result;
233  }
234 
240  protected function getResourceFactory(): ResourceFactory
241  {
242  if (!$this->resourceFactory) {
243  $this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
244  }
245  return $this->resourceFactory;
246  }
247 }
static makeInstance($className,... $constructorArguments)