1<?php
2
3use dokuwiki\Extension\SyntaxPlugin;
4
5/**
6 * DokuWiki Plugin networkgraph (Syntax Component)
7 *
8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
9 * @author Feralheart <dokuwiki@feralheart.dev>
10 */
11class syntax_plugin_networkgraph_renderer extends SyntaxPlugin
12{
13    /** @inheritDoc */
14    public function getType()
15    {
16        return 'substition';
17    }
18
19    /** @inheritDoc */
20    public function getPType()
21    {
22        return 'normal';
23    }
24
25    /** @inheritDoc */
26    public function getSort()
27    {
28        return 361;
29    }
30
31    /** @inheritDoc */
32    public function connectTo($mode)
33    {
34        $this->Lexer->addSpecialPattern('~~NETWORKGRAPH(?:\|[a-zA-Z0-9\:\-\#\;\=]+)?~~', $mode, 'plugin_networkgraph_renderer');
35    }
36
37    /** @inheritDoc */
38    public function handle($match, $state, $pos, Doku_Handler $handler)
39    {
40        $params = '';
41        $cleanMatch = trim($match, '~');
42        if (strpos($cleanMatch, '|') !== false) {
43            $paramsString = substr($cleanMatch, strpos($cleanMatch, '|') + 1);
44
45            if (strpos($paramsString, '=') !== false) {
46                list($key, $value) = explode('=', $paramsString, 2);
47                $key = trim($key);
48                $value = trim($value);
49
50                if ($key === 'colors') {
51                    $params = $value;
52                }
53            } else {
54                $params = $paramsString;
55            }
56        }
57
58        $colorMap = $this->parseColorMap($params);
59
60        return ['colors' => $colorMap];
61    }
62
63    /** @inheritDoc */
64    public function render($mode, Doku_Renderer $renderer, $data)
65    {
66        if ($mode !== 'xhtml') {
67            return false;
68        }
69
70        $colorMap       = $data['colors'] ?? [];
71        $randomNumber   = rand(0, getrandmax());
72        $graphId        = "networkgraph_" . $randomNumber;
73        $file           = metaFN('networkgraph_data', '.json');
74        $json           = file_exists($file) ? file_get_contents($file) : json_encode(['nodes' => [], 'links' => []]);
75        $renderer->info['cache'] = false;
76        $renderer->doc .= "<div id='" . $graphId . "' class='networkgraph' style='width:100%; height:600px; border:1px solid #ddd;'></div>";
77        $renderer->doc .= "<script>
78            (function() {
79                const graph = " . $json . ";
80                const colorMap = " . json_encode($colorMap) . ";
81                renderGraph('" . $graphId . "', graph, colorMap);
82            })();
83        </script>";
84
85        return true;
86    }
87
88    private function parseColorMap($param) {
89        $colorMap = [];
90
91        if (!$param) return $colorMap;
92
93        $entries = explode(';', $param);
94
95        foreach ($entries as $entry) {
96            if (strpos($entry, '-') === false) continue;
97
98            list($ns, $color) = explode('-', $entry, 2);
99
100            $color = trim($color);
101
102            if (preg_match('/^#?[0-9a-fA-F]{6}$/', $color)) {
103                $color = ltrim($color, '#');
104                $colorMap[trim($ns)] = '#' . strtolower($color);
105            }
106        }
107
108        return $colorMap;
109    }
110}
111