1<?php
2/**
3 * DokuWiki Plugin randomtable (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Oscar Merida <oscar@oscarm.org>
7 */
8class syntax_plugin_randomtables_source  extends \dokuwiki\Extension\SyntaxPlugin
9{
10    /** @inheritDoc */
11    public function getType(): string
12    {
13        return 'protected';
14    }
15
16    /** @inheritDoc */
17    public function getPType(): string
18    {
19        return 'block';
20    }
21
22    /** @inheritDoc */
23    public function getSort(): int
24    {
25        return 200;
26    }
27
28    /** @inheritDoc */
29    public function connectTo($mode): void
30    {
31        $this->Lexer->addEntryPattern('\<RANDOMTABLE\s+[A-Za-z0-9_]+>', $mode, 'plugin_randomtables_source');
32    }
33
34    /** @inheritDoc */
35    public function postConnect(): void
36    {
37        $this->Lexer->addExitPattern('</RANDOMTABLE>', 'plugin_randomtables_source');
38    }
39
40    /** @inheritDoc */
41    public function handle($match, $state, $pos, Doku_Handler $handler): array
42    {
43		static $tableID;
44
45     	switch ($state) {
46			case DOKU_LEXER_ENTER:
47				preg_match('/\s([A-Za-z0-9_]+)\>$/', $match, $parts);
48				$tableID[] = $parts[1];
49
50				return [$state, $match, $parts[1]];
51
52			case DOKU_LEXER_UNMATCHED:
53				$match = preg_split("/(\r|\n|\r\n)/m", $match);
54
55				$match = $this->parseLines($match);
56
57				if (!$_GET['do']) {
58					$data = [
59						'lines' => $match,
60						'id' => array_pop($tableID),
61					];
62					trigger_event('randomtables_save', $data);
63				}
64
65				return [$state, $match];
66
67			case DOKU_LEXER_EXIT:
68				return [$state, ''];
69
70		}
71        return [];
72    }
73
74    /** @inheritDoc */
75    public function render($mode, Doku_Renderer $renderer, $data): bool
76    {
77        if ($mode !== 'xhtml') {
78            return false;
79        }
80
81        [$state, $match] = $data;
82
83		switch ($state) {
84			case DOKU_LEXER_ENTER:
85				$id = $data[2];
86				$renderer->doc .= '<div class="randomtable-well"><button class="randomtable" data-src="' . $id . '" data-target="results-'
87					           . $id . '">Roll</button><div id="results-' . $id .'" class="results"></div></div>' . PHP_EOL;
88				$renderer->doc .= '<table id="' . $id.'" class="inline table table-striped table-condensed randomtable">' . PHP_EOL;
89				$renderer->doc .='<thead><tr><th>Range</th><th>Result</th></tr></thead>' . PHP_EOL;
90				break;
91
92			case DOKU_LEXER_UNMATCHED:
93
94				foreach ($match as $line) {
95					[$min, $max, $txt] = $line;
96
97					$range = ($min === $max) ? $min : $min . '-' . $max;
98
99					$renderer->doc .= '<tr>'
100						. '<td>' . $range . '</td>'
101						. '<td>' . $renderer->_xmlEntities($txt) .'</td>'
102						. '</tr>' . PHP_EOL;
103				}
104
105				break;
106
107			case DOKU_LEXER_EXIT:
108				$renderer->doc .= "</table>" . PHP_EOL;
109				break;
110		}
111
112        return true;
113    }
114
115	private function parseLines(array $match): array
116	{
117		$match = array_filter($match);
118
119		$match = array_map(function($line) use (&$count) {
120			if (preg_match('/^(\d+)\.*(?:[ -])+(\d+)\.*\s*(.+)$/', $line, $subm)) {
121				$count = (int) $subm[2];
122				return [(int) $subm[1], (int) $subm[2], $subm[3]];
123			}
124
125			if (preg_match('/^(\d+)\.*\s+(.+)$/', $line, $subm)) {
126				$count = (int) $subm[1];
127				return [(int) $subm[1], (int) $subm[1], $subm[2]];
128			}
129
130			$count++;
131			return [$count, $count,  $line];
132
133
134		}, $match);
135
136		return $match;
137	}
138}
139