$registeredLinkHandlers */ if ($registeredLinkHandlers !== []) { foreach ($registeredLinkHandlers as $type => $handlerClassName) { if (!isset($this->handlers[$type]) || !is_object($this->handlers[$type])) { $handler = GeneralUtility::makeInstance($handlerClassName); if ($handler instanceof LinkHandlingInterface) { $this->handlers[$type] = $handler; } } } } } /** * Part of the typolink construction functionality, called by typoLink() * Used to resolve "legacy"-based typolinks and URNs. * * Tries to get the type of the link from the link parameter * could be * - "mailto" an email address * - "url" external URL * - "file" a local file (checked AFTER getPublicUrl() is called) * - "page" a page (integer) * * Does NOT check if the page exists or the file exists. * * @param string $linkParameter could be "fileadmin/myfile.jpg", "info@typo3.org", "13" or "http://www.typo3.org" */ public function resolve(string $linkParameter): array { try { // Check if the new syntax with "t3://" is used return $this->resolveByStringRepresentation($linkParameter); } catch (UnknownUrnException $e) { $legacyLinkNotationConverter = GeneralUtility::makeInstance(LegacyLinkNotationConverter::class); return $legacyLinkNotationConverter->resolve($linkParameter); } } /** * Returns an array with data interpretation of the link target, something like t3://page?uid=23. * * @throws Exception\UnknownLinkHandlerException * @throws Exception\UnknownUrnException */ public function resolveByStringRepresentation(string $urn): array { $result = []; $resolveException = null; try { // linking to any t3:// syntax if (stripos($urn, 't3://') === 0) { // lets parse the urn $urnParsed = parse_url($urn); $type = $urnParsed['host']; if (isset($urnParsed['query'])) { parse_str(htmlspecialchars_decode($urnParsed['query']), $data); } else { $data = []; } $fragment = $urnParsed['fragment'] ?? null; if (isset($this->handlers[$type])) { $result = $this->handlers[$type]->resolveHandlerData($data); $result['type'] = $type; } else { $resolveException = new UnknownLinkHandlerException('LinkHandler for ' . $type . ' was not registered', 1460581769); } // this was historically named "section" if ($fragment) { $result['fragment'] = $fragment; } } elseif (($this->handlers[self::TYPE_URL] ?? false) && PathUtility::hasProtocolAndScheme($urn)) { $result = $this->handlers[self::TYPE_URL]->resolveHandlerData(['url' => $urn]); $result['type'] = self::TYPE_URL; } elseif (($this->handlers[self::TYPE_EMAIL] ?? false) && str_starts_with(strtolower($urn), 'mailto:')) { $result = $this->handlers[self::TYPE_EMAIL]->resolveHandlerData(['email' => $urn]); $result['type'] = self::TYPE_EMAIL; } elseif (($this->handlers[self::TYPE_TELEPHONE] ?? false) && str_starts_with(strtolower($urn), 'tel:')) { $result = $this->handlers[self::TYPE_TELEPHONE]->resolveHandlerData(['telephone' => $urn]); $result['type'] = self::TYPE_TELEPHONE; } } finally { $result = $this->eventDispatcher->dispatch( new AfterLinkResolvedByStringRepresentationEvent( result: $result, urn: $urn, resolveException: $resolveException ) )->getResult(); if (empty($result['type'])) { // In case no link type could be resolved and UnknownLinkHandlerException // has been added before, throw the exception now to inform calling components. if ($resolveException === null) { // Use the general UnknownUrnException in case neither a defined // handler nor an event listener could resolve the given URN. $resolveException = new UnknownUrnException('No valid URN to resolve found', 1457177667); } throw $resolveException; } } // @todo If resolved result (linkDetails) are later used to build an uri using LinkBuilder->build(), it's needed // to have the original $linkParameter in the result array. Otherwise, places may break like e.g. the // DatabaseRecordLinkBuilder. Can we safely set this here directly and avoiding calls before build like // "$linkDetails['typoLinkParameter'] = $redirectTarget;" - e.g. like in the ext:redirects // TYPO3\CMS\Redirects\Service\RedirectService::resolveLinkDetailsFromLinkTarget() and other places. return $result; } /** * Returns a string interpretation of the link target, something like * * - t3://page?uid=23&my=value#cool * - https://www.typo3.org/ * - t3://file?uid=13 * - t3://folder?storage=2&identifier=/my/folder/ * - mailto:mac@safe.com * * @param array $parameters * @throws Exception\UnknownLinkHandlerException */ public function asString(array $parameters): string { $linkHandler = $this->handlers[$parameters['type']] ?? null; if ($linkHandler !== null) { return $this->handlers[$parameters['type']]->asString($parameters); } if (isset($parameters['url']) && !empty($parameters['url'])) { // This usually happens for tel: or other types where a URL is available and the // legacy link service could resolve at least something return $parameters['url']; } throw new UnknownLinkHandlerException('No valid handlers found for type: ' . $parameters['type'], 1460629247); } }