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