xref: /dokuwiki/inc/Parsing/ParserMode/Externallink.php (revision 71096e46fcbfaeaa808667aba794e77fe2780169)
1<?php
2
3namespace dokuwiki\Parsing\ParserMode;
4
5use dokuwiki\Parsing\Handler;
6
7class Externallink extends AbstractMode
8{
9    protected $schemes = [];
10    protected $patterns = [];
11
12    /** @inheritdoc */
13    public function getSort()
14    {
15        return 330;
16    }
17
18    /** @inheritdoc */
19    public function preConnect()
20    {
21        if (count($this->patterns)) return;
22
23        $ltrs = '\w';
24        $gunk = '/\#~:.?+=&%@!\-\[\]';
25        $punc = '.:?\-;,';
26        $host = $ltrs . $punc;
27        $any  = $ltrs . $gunk . $punc;
28
29        $this->schemes = getSchemes();
30        foreach ($this->schemes as $scheme) {
31            $this->patterns[] = '\b(?i)' . $scheme . '(?-i)://[' . $any . ']+?(?=[' . $punc . ']*[^' . $any . '])';
32        }
33
34        $this->patterns[] = '(?<![/\\\\])\b(?i)www?(?-i)\.[' . $host . ']+?\.' .
35                            '[' . $host . ']+?[' . $any . ']+?(?=[' . $punc . ']*[^' . $any . '])';
36        $this->patterns[] = '(?<![/\\\\])\b(?i)ftp?(?-i)\.[' . $host . ']+?\.' .
37                            '[' . $host . ']+?[' . $any . ']+?(?=[' . $punc . ']*[^' . $any . '])';
38    }
39
40    /** @inheritdoc */
41    public function connectTo($mode)
42    {
43
44        foreach ($this->patterns as $pattern) {
45            $this->Lexer->addSpecialPattern($pattern, $mode, 'externallink');
46        }
47    }
48
49    /** @inheritdoc */
50    public function handle($match, $state, $pos, Handler $handler)
51    {
52        $url = $match;
53        $title = null;
54
55        // add protocol on simple short URLs
56        if (str_starts_with($url, 'ftp') && !str_starts_with($url, 'ftp://')) {
57            $title = $url;
58            $url = 'ftp://' . $url;
59        }
60        if (str_starts_with($url, 'www')) {
61            $title = $url;
62            $url = 'http://' . $url;
63        }
64
65        $handler->addCall('externallink', [$url, $title], $pos);
66        return true;
67    }
68
69    /**
70     * @return array
71     */
72    public function getPatterns()
73    {
74        return $this->patterns;
75    }
76}
77