1<?php 2 3use dokuwiki\plugin\sql2wiki\Csv; 4 5/** 6 * DokuWiki Plugin sql2wiki (Syntax Component) 7 * 8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 9 * @author Szymon Olewniczak <it@rid.pl> 10 */ 11class syntax_plugin_sql2wiki_query extends \dokuwiki\Extension\SyntaxPlugin 12{ 13 /** @inheritDoc */ 14 public function getType() 15 { 16 return 'protected'; 17 } 18 19 /** @inheritDoc */ 20 public function getPType() 21 { 22 return 'block'; 23 } 24 25 /** @inheritDoc */ 26 public function getSort() 27 { 28 return 0; 29 } 30 31 /** @inheritDoc */ 32 public function connectTo($mode) 33 { 34 $this->Lexer->addSpecialPattern('<sql2wiki.*?>.*?</sql2wiki>',$mode,'plugin_sql2wiki_query'); 35 } 36 37 /** @inheritDoc */ 38 public function handle($match, $state, $pos, Doku_Handler $handler) 39 { 40 libxml_use_internal_errors(true); 41 $xml = simplexml_load_string($match); 42 if ($xml === false) { 43 msg('Syntax: "'.hsc($match) . '" is not valid xml', -1); 44 return null; 45 } 46 $attributes = []; 47 foreach($xml[0]->attributes() as $a => $b) { 48 $attributes[$a] = (string) $b; 49 } 50 if (!isset($attributes['db']) || !isset($attributes['query'])) { 51 msg('"db" and "query" attributes are required.', -1); 52 return null; 53 } 54 55 // we use substr instead of simplexml to get the raw content 56 $content_start = strpos($match, '>') + 1; 57 $tag_value = substr($match, $content_start, -strlen('</sql2wiki>')); 58 59 $parsers = []; 60 $needle = 'parser_'; 61 foreach ($attributes as $name => $value) { 62 $length = strlen($needle); 63 if (substr($name, 0, $length) === $needle) { 64 list($_, $col) = explode('_', $name); 65 if (preg_match('/([[:alpha:]]+)\((.*)\)/', $value, $matches)) { 66 $class = $matches[1]; 67 $config = json_decode($matches[2], true); 68 $parsers[$col] = ['class' => $class, 'config' => $config]; 69 } else { 70 $parsers[$col] = ['class' => $value, 'config' => null]; 71 } 72 } 73 } 74 75 $args = []; 76 if (isset($attributes['args'])) { 77 $args = array_map('trim', explode(',', $attributes['args'])); 78 } 79 80 $start = $pos + strpos($match, '>'); // closing char of the opening tag 81 $end = $pos + strlen($match) - strlen('</sql2wiki>') - 1; 82 $data = [ 83 'db' => $attributes['db'], 84 'query_name' => $attributes['query'], 85 'parsers' => $parsers, 86 'args' => $args, 87 'value' => $tag_value, 88 'start' => $start, 89 'end' => $end, 90 'pos' => $pos, 91 'match' => $match 92 ]; 93 return $data; 94 } 95 96 /** @inheritDoc */ 97 public function render($mode, Doku_Renderer $renderer, $data) 98 { 99 if ($data === null) return false; 100 101 if ($mode == 'metadata') { 102 if (!isset($renderer->meta['plugin_sql2wiki'])) { 103 $renderer->meta['plugin_sql2wiki'] = []; 104 } 105 $renderer->meta['plugin_sql2wiki'][] = $data; 106 return true; 107 } 108 if ($mode == 'xhtml') { 109 $result = Csv::csv2arr($data['value']); 110 111 if (count($result) == 0) { 112 $renderer->p_open(); 113 $renderer->cdata($this->getLang('none')); 114 $renderer->p_close(); 115 return true; 116 } 117 118 // check if we use any parsers 119 $parsers = $data['parsers']; 120 if (count($parsers) > 0) { 121 $class_name = '\dokuwiki\plugin\struct\meta\Column'; 122 if (!class_exists($class_name)) { 123 msg('Install struct plugin to use parsers', -1); 124 return false; 125 } 126 $parser_types = $class_name::allTypes(); 127 } 128 129 $renderer->table_open(); 130 $renderer->tablethead_open(); 131 $renderer->tablerow_open(); 132 $headers = array_shift($result); 133 foreach ($headers as $header) { 134 $renderer->tableheader_open(); 135 $renderer->cdata($header); 136 $renderer->tableheader_close(); 137 } 138 $renderer->tablerow_close(); 139 $renderer->tablethead_close(); 140 141 $renderer->tabletbody_open(); 142 foreach ($result as $row) { 143 $renderer->tablerow_open(); 144 $tds = array_values($row); 145 foreach ($tds as $i => $td) { 146 if ($td === null) $td = '␀'; 147 if (isset($parsers[$i])) { 148 $parser_class = $parsers[$i]['class']; 149 $parser_config = $parsers[$i]['config']; 150 if (!isset($parser_types[$parser_class])) { 151 msg('Unknown parser: ' . $parser_class, -1); 152 $renderer->tablecell_open(); 153 $renderer->cdata($td); 154 $renderer->tablecell_close(); 155 } else { 156 /** @var \dokuwiki\plugin\struct\types\AbstractBaseType $parser */ 157 $parser = new $parser_types[$parser_class]($parser_config); 158 $renderer->tablecell_open(); 159 $parser->renderValue($td, $renderer, $mode); 160 $renderer->tablecell_close(); 161 } 162 } else { 163 $renderer->tablecell_open(); 164 $renderer->cdata($td); 165 $renderer->tablecell_close(); 166 } 167 } 168 $renderer->tablerow_close(); 169 } 170 $renderer->tabletbody_close(); 171 $renderer->table_close(); 172 return true; 173 } 174 return false; 175 } 176} 177 178