xref: /dokuwiki/inc/Parsing/Helpers/Link.php (revision b73ece99c18919754d993a1d1f5cb27140555705)
1<?php
2
3namespace dokuwiki\Parsing\Helpers;
4
5use dokuwiki\MailUtils;
6
7/**
8 * Pure helper for classifying link targets.
9 *
10 * Side-effect-free: returns data and leaves handler emission to the
11 * caller. Shared by DokuWiki's Internallink mode and GfmLink.
12 */
13class Link
14{
15    /**
16     * Classify a link target and return the handler call that would emit it.
17     *
18     * Classification order: interwiki prefix, then Windows share, then
19     * protocol scheme, then email, then local anchor, then internal page
20     * as the default. The order is load-bearing — e.g. a URL with an
21     * interwiki prefix that also matches an email pattern is still
22     * dispatched as interwiki.
23     *
24     * @param string $url raw link target
25     * @param string|array|null $label display label, or null; for
26     *     Internallink this may be a parsed media array
27     * @return array{0: string, 1: array} tuple of [handler call name, args]
28     *     — caller invokes $handler->addCall($name, $args, $pos)
29     */
30    public static function classify(string $url, $label): array
31    {
32        if (link_isinterwiki($url)) {
33            $iw = sexplode('>', $url, 2, '');
34            return ['interwikilink', [$url, $label, strtolower($iw[0]), $iw[1]]];
35        }
36        if (preg_match('/^\\\\\\\\[^\\\\]+?\\\\/u', $url)) {
37            return ['windowssharelink', [$url, $label]];
38        }
39        if (preg_match('#^([a-z0-9\-\.+]+?)://#i', $url)) {
40            return ['externallink', [$url, $label]];
41        }
42        if (preg_match('<' . MailUtils::PREG_PATTERN_VALID_EMAIL . '>', $url)) {
43            return ['emaillink', [$url, $label]];
44        }
45        if (preg_match('!^#.+!', $url)) {
46            return ['locallink', [substr($url, 1), $label]];
47        }
48        return ['internallink', [$url, $label]];
49    }
50}
51