1<?php 2 3/** 4 * DokuWiki Plugin dbquery (Syntax Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr <dokuwiki@cosmocode.de> 8 */ 9class syntax_plugin_dbquery_query extends DokuWiki_Syntax_Plugin 10{ 11 /** @inheritDoc */ 12 public function getType() 13 { 14 return 'substition'; 15 } 16 17 /** @inheritDoc */ 18 public function getPType() 19 { 20 return 'block'; 21 } 22 23 /** @inheritDoc */ 24 public function getSort() 25 { 26 return 135; 27 } 28 29 /** @inheritDoc */ 30 public function connectTo($mode) 31 { 32 $this->Lexer->addSpecialPattern('{{QUERY:\w+}}', $mode, 'plugin_dbquery_query'); 33 } 34 35 /** @inheritDoc */ 36 public function handle($match, $state, $pos, Doku_Handler $handler) 37 { 38 return ['name' => substr($match, 8, -2)]; 39 } 40 41 /** @inheritDoc */ 42 public function render($mode, Doku_Renderer $renderer, $data) 43 { 44 if ($mode !== 'xhtml') { 45 return false; 46 } 47 48 /** @var helper_plugin_dbquery $hlp */ 49 $hlp = plugin_load('helper', 'dbquery'); 50 try { 51 $qdata = $hlp->loadDataFromPage($data['name']); 52 $result = $hlp->executeQuery($qdata['codeblocks']['_']); 53 } catch (\Exception $e) { 54 msg(hsc($e->getMessage()), -1); 55 return true; 56 } 57 58 if (count($result) === 1 && isset($result[0]['status']) && isset($qdata['codeblocks'][$result[0]['status']])) { 59 $this->renderStatus($result, $qdata['codeblocks'][$result[0]['status']], $renderer); 60 } else { 61 if ($qdata['macros']['transpose']) { 62 $this->renderTransposedResultTable($result, $renderer); 63 } else { 64 $this->renderResultTable($result, $renderer); 65 } 66 } 67 68 return true; 69 } 70 71 /** 72 * Render given result via the given status HTML 73 * 74 * @param string[][] $result 75 * @param string $html 76 * @param Doku_Renderer $R 77 */ 78 public function renderStatus($result, $html, Doku_Renderer $R) 79 { 80 $value = isset($result[0]['result']) ? $result[0]['result'] : ''; 81 $html = str_replace(':result', hsc($value), $html); 82 $R->doc .= $html; 83 } 84 85 /** 86 * Render the given result as a table 87 * 88 * @param string[][] $result 89 * @param Doku_Renderer $R 90 */ 91 public function renderResultTable($result, Doku_Renderer $R) 92 { 93 global $lang; 94 95 if (!count($result)) { 96 $R->cdata($lang['nothingfound']); 97 return; 98 } 99 100 $R->table_open(); 101 $R->tablethead_open(); 102 $R->tablerow_open(); 103 foreach (array_keys($result[0]) as $header) { 104 $R->tableheader_open(); 105 $R->cdata($header); 106 $R->tableheader_close(); 107 } 108 $R->tablerow_close(); 109 $R->tablethead_close(); 110 111 $R->tabletbody_open(); 112 foreach ($result as $row) { 113 $R->tablerow_open(); 114 foreach ($row as $cell) { 115 $R->tablecell_open(); 116 $this->cellFormat($cell, $R); 117 $R->tablecell_close(); 118 } 119 $R->tablerow_close(); 120 } 121 $R->tabletbody_close(); 122 $R->table_close(); 123 } 124 125 /** 126 * Render the given result as a table, but turned 90 degrees 127 * 128 * @param string[][] $result 129 * @param Doku_Renderer $R 130 */ 131 public function renderTransposedResultTable($result, Doku_Renderer $R) 132 { 133 global $lang; 134 135 if (!count($result)) { 136 $R->cdata($lang['nothingfound']); 137 return; 138 } 139 140 $width = count($result[0]); 141 $height = count($result); 142 143 $R->table_open(); 144 for ($x = 0; $x < $width; $x++) { 145 $R->tablerow_open(); 146 $R->tableheader_open(); 147 $R->cdata(array_keys($result[0])[$x]); 148 $R->tableheader_close(); 149 150 for ($y = 0; $y < $height; $y++) { 151 $R->tablecell_open(); 152 $this->cellFormat(array_values($result[$y])[$x], $R); 153 $R->tablecell_close(); 154 } 155 $R->tablerow_close(); 156 } 157 $R->table_close(); 158 } 159 160 /** 161 * Pass the given cell content to the correct renderer call 162 * 163 * Detects a subset of the wiki link syntax 164 * 165 * @param string $content 166 * @param Doku_Renderer $R 167 * @return void 168 */ 169 protected function cellFormat($content, Doku_Renderer $R) 170 { 171 // external urls 172 if (preg_match('/^\[\[(https?:\/\/[^|\]]+)(|.*?)?]]$/', $content, $m)) { 173 $url = $m[1]; 174 $title = $m[2] ?? ''; 175 $title = trim($title,'|'); 176 $R->externallink($url, $title); 177 return; 178 } 179 180 // internal urls 181 if (preg_match('/^\[\[([^|\]]+)(|.*?)?]]$/', $content, $m)) { 182 $page = cleanID($m[1]); 183 $title = $m[2] ?? ''; 184 $title = trim($title,'|'); 185 $R->internallink($page, $title); 186 return; 187 } 188 189 $R->cdata($content); 190 } 191} 192 193