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