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