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