1<?php
2
3use dokuwiki\Extension\SyntaxPlugin;
4use dokuwiki\Utf8\Sort;
5
6/**
7 * DokuWiki Plugin linklist (Syntax Component)
8 *
9 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
10 * @author Andreas Gohr <dokuwiki@cosmocode.de>
11 */
12class syntax_plugin_linklist extends SyntaxPlugin
13{
14    /** @inheritDoc */
15    public function getType()
16    {
17        return 'substition';
18    }
19
20    /** @inheritDoc */
21    public function getPType()
22    {
23        return 'block';
24    }
25
26    /** @inheritDoc */
27    public function getSort()
28    {
29        return 155;
30    }
31
32    /** @inheritDoc */
33    public function connectTo($mode)
34    {
35        $this->Lexer->addSpecialPattern('\{\{linklist[^\}]*?\}\}', $mode, 'plugin_linklist');
36    }
37
38
39    /** @inheritDoc */
40    public function handle($match, $state, $pos, Doku_Handler $handler)
41    {
42        $match = substr($match, 11, -2);
43        $params = explode(' ', $match);
44        $id = array_shift($params);
45        $params = array_map('trim', $params);
46
47        $type = 'internal';
48        if (in_array('backlinks', $params)) {
49            $type = 'backlinks';
50        } elseif (in_array('external', $params)) {
51            $type = 'external';
52        } elseif (in_array('interwiki', $params)) {
53            $type = 'interwiki';
54        }
55
56
57        $data = [
58            'id' => $id,
59            'type' => $type,
60        ];
61
62        return $data;
63    }
64
65    /** @inheritDoc */
66    public function render($mode, Doku_Renderer $renderer, $data)
67    {
68        if ($mode == 'linklist') return false;
69        if ($mode == 'metadata') return false;
70
71        global $INFO;
72
73        if (!$data['id']) $data['id'] = $INFO['id'];
74        if (!page_exists($data['id'])) return true;
75        if (auth_quickaclcheck($data['id']) < AUTH_READ) return true;
76
77        switch ($data['type']) {
78            case 'backlinks':
79                // backlinks from the index
80                $links = ft_backlinks($data['id'], true);
81                $links = array_map(fn($link) => [$link, helper_plugin_linklist::getTitle($link)], $links);
82                break;
83            case 'internal':
84            case 'external':
85            case 'interwiki':
86                // all other links from our own renderer
87                $results = p_cached_output(wikiFN($data['id']), 'linklist');
88                $results = json_decode($results, true, JSON_THROW_ON_ERROR);
89                $links = $results[$data['type']];
90        }
91
92
93        $links = array_filter($links, fn($item) => !isHiddenPage($item));
94        if (!$links) return true;
95        usort($links, [$this, 'sortByTitle']);
96
97        $renderer->listu_open();
98        foreach ($links as $params) {
99            $renderer->listitem_open(1);
100            $renderer->listcontent_open();
101            switch ($data['type']) {
102                case 'backlinks':
103                case 'internal':
104                    $renderer->internallink($params[0], $params[1]);
105                    break;
106                case 'external':
107                    $renderer->externallink($params[0], $params[1]);
108                    break;
109                case 'interwiki':
110                    $renderer->interwikilink($params[0], $params[1], $params[2], $params[3]);
111                    break;
112            }
113            $renderer->listcontent_close();
114            $renderer->listitem_close();
115        }
116        $renderer->listu_close();
117
118
119        return true;
120    }
121
122    /**
123     * Sort the links by title
124     *
125     * Titles are the second parameter in the array
126     *
127     * @param array $a
128     * @param array $b
129     * @return int
130     */
131    public function sortByTitle($a, $b)
132    {
133        return Sort::strcmp($a[1], $b[1]);
134    }
135}
136