1c64c1748SAndreas Gohr<?php 2c64c1748SAndreas Gohr 39730265cSAndreas Gohruse dokuwiki\Extension\SyntaxPlugin; 49730265cSAndreas Gohr 5c64c1748SAndreas Gohr/** 6c64c1748SAndreas Gohr * DokuWiki Plugin dbquery (Syntax Component) 7c64c1748SAndreas Gohr * 8c64c1748SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 9c64c1748SAndreas Gohr * @author Andreas Gohr <dokuwiki@cosmocode.de> 10c64c1748SAndreas Gohr */ 119730265cSAndreas Gohrclass syntax_plugin_dbquery_query extends SyntaxPlugin 12c64c1748SAndreas Gohr{ 13c64c1748SAndreas Gohr /** @inheritDoc */ 14c64c1748SAndreas Gohr public function getType() 15c64c1748SAndreas Gohr { 16c64c1748SAndreas Gohr return 'substition'; 17c64c1748SAndreas Gohr } 18c64c1748SAndreas Gohr 19c64c1748SAndreas Gohr /** @inheritDoc */ 20c64c1748SAndreas Gohr public function getPType() 21c64c1748SAndreas Gohr { 22c64c1748SAndreas Gohr return 'block'; 23c64c1748SAndreas Gohr } 24c64c1748SAndreas Gohr 25c64c1748SAndreas Gohr /** @inheritDoc */ 26c64c1748SAndreas Gohr public function getSort() 27c64c1748SAndreas Gohr { 28c64c1748SAndreas Gohr return 135; 29c64c1748SAndreas Gohr } 30c64c1748SAndreas Gohr 31c64c1748SAndreas Gohr /** @inheritDoc */ 32c64c1748SAndreas Gohr public function connectTo($mode) 33c64c1748SAndreas Gohr { 34c64c1748SAndreas Gohr $this->Lexer->addSpecialPattern('{{QUERY:\w+}}', $mode, 'plugin_dbquery_query'); 35c64c1748SAndreas Gohr } 36c64c1748SAndreas Gohr 37c64c1748SAndreas Gohr /** @inheritDoc */ 38c64c1748SAndreas Gohr public function handle($match, $state, $pos, Doku_Handler $handler) 39c64c1748SAndreas Gohr { 40c64c1748SAndreas Gohr return ['name' => substr($match, 8, -2)]; 41c64c1748SAndreas Gohr } 42c64c1748SAndreas Gohr 43c64c1748SAndreas Gohr /** @inheritDoc */ 44c64c1748SAndreas Gohr public function render($mode, Doku_Renderer $renderer, $data) 45c64c1748SAndreas Gohr { 46c64c1748SAndreas Gohr if ($mode !== 'xhtml') { 47c64c1748SAndreas Gohr return false; 48c64c1748SAndreas Gohr } 49c64c1748SAndreas Gohr 50c64c1748SAndreas Gohr /** @var helper_plugin_dbquery $hlp */ 51c64c1748SAndreas Gohr $hlp = plugin_load('helper', 'dbquery'); 52c64c1748SAndreas Gohr try { 53c64c1748SAndreas Gohr $qdata = $hlp->loadDataFromPage($data['name']); 543113520cSAndreas Gohr $result = $hlp->executeQuery($qdata['codeblocks']['_'], $qdata['macros']['dsn'] ?? null); 55c64c1748SAndreas Gohr } catch (\Exception $e) { 56c64c1748SAndreas Gohr msg(hsc($e->getMessage()), -1); 57c64c1748SAndreas Gohr return true; 58c64c1748SAndreas Gohr } 59c64c1748SAndreas Gohr 60c64c1748SAndreas Gohr if (count($result) === 1 && isset($result[0]['status']) && isset($qdata['codeblocks'][$result[0]['status']])) { 61c64c1748SAndreas Gohr $this->renderStatus($result, $qdata['codeblocks'][$result[0]['status']], $renderer); 629730265cSAndreas Gohr } elseif ($qdata['macros']['transpose']) { 63c64c1748SAndreas Gohr $this->renderTransposedResultTable($result, $renderer); 64c64c1748SAndreas Gohr } else { 65c64c1748SAndreas Gohr $this->renderResultTable($result, $renderer); 66c64c1748SAndreas Gohr } 67c64c1748SAndreas Gohr 68c64c1748SAndreas Gohr return true; 69c64c1748SAndreas Gohr } 70c64c1748SAndreas Gohr 71c64c1748SAndreas Gohr /** 72c64c1748SAndreas Gohr * Render given result via the given status HTML 73c64c1748SAndreas Gohr * 74c64c1748SAndreas Gohr * @param string[][] $result 75c64c1748SAndreas Gohr * @param string $html 76c64c1748SAndreas Gohr * @param Doku_Renderer $R 77c64c1748SAndreas Gohr */ 78c64c1748SAndreas Gohr public function renderStatus($result, $html, Doku_Renderer $R) 79c64c1748SAndreas Gohr { 809730265cSAndreas Gohr $value = $result[0]['result'] ?? ''; 81c64c1748SAndreas Gohr $html = str_replace(':result', hsc($value), $html); 82c64c1748SAndreas Gohr $R->doc .= $html; 83c64c1748SAndreas Gohr } 84c64c1748SAndreas Gohr 85c64c1748SAndreas Gohr /** 86c64c1748SAndreas Gohr * Render the given result as a table 87c64c1748SAndreas Gohr * 88c64c1748SAndreas Gohr * @param string[][] $result 89c64c1748SAndreas Gohr * @param Doku_Renderer $R 90c64c1748SAndreas Gohr */ 91c64c1748SAndreas Gohr public function renderResultTable($result, Doku_Renderer $R) 92c64c1748SAndreas Gohr { 93c64c1748SAndreas Gohr global $lang; 94c64c1748SAndreas Gohr 95c64c1748SAndreas Gohr if (!count($result)) { 96c64c1748SAndreas Gohr $R->cdata($lang['nothingfound']); 97c64c1748SAndreas Gohr return; 98c64c1748SAndreas Gohr } 99c64c1748SAndreas Gohr 100c64c1748SAndreas Gohr $R->table_open(); 10104ef7616SAndreas Gohr $R->tablethead_open(); 102c64c1748SAndreas Gohr $R->tablerow_open(); 103c64c1748SAndreas Gohr foreach (array_keys($result[0]) as $header) { 104*19d0a884SAndreas Gohr $header = preg_replace('/_wiki$/', ' ', $header); // remove _wiki type suffix 105c64c1748SAndreas Gohr $R->tableheader_open(); 106c64c1748SAndreas Gohr $R->cdata($header); 107c64c1748SAndreas Gohr $R->tableheader_close(); 108c64c1748SAndreas Gohr } 109c64c1748SAndreas Gohr $R->tablerow_close(); 11004ef7616SAndreas Gohr $R->tablethead_close(); 111c64c1748SAndreas Gohr 11204ef7616SAndreas Gohr $R->tabletbody_open(); 113c64c1748SAndreas Gohr foreach ($result as $row) { 114c64c1748SAndreas Gohr $R->tablerow_open(); 115*19d0a884SAndreas Gohr foreach ($row as $col => $cell) { 116c64c1748SAndreas Gohr $R->tablecell_open(); 117*19d0a884SAndreas Gohr $this->cellFormat($cell, $R, $col); 118c64c1748SAndreas Gohr $R->tablecell_close(); 119c64c1748SAndreas Gohr } 120c64c1748SAndreas Gohr $R->tablerow_close(); 121c64c1748SAndreas Gohr } 12204ef7616SAndreas Gohr $R->tabletbody_close(); 123c64c1748SAndreas Gohr $R->table_close(); 124c64c1748SAndreas Gohr } 125c64c1748SAndreas Gohr 126c64c1748SAndreas Gohr /** 127c64c1748SAndreas Gohr * Render the given result as a table, but turned 90 degrees 128c64c1748SAndreas Gohr * 129c64c1748SAndreas Gohr * @param string[][] $result 130c64c1748SAndreas Gohr * @param Doku_Renderer $R 131c64c1748SAndreas Gohr */ 132c64c1748SAndreas Gohr public function renderTransposedResultTable($result, Doku_Renderer $R) 133c64c1748SAndreas Gohr { 134c64c1748SAndreas Gohr global $lang; 135c64c1748SAndreas Gohr 136c64c1748SAndreas Gohr if (!count($result)) { 137c64c1748SAndreas Gohr $R->cdata($lang['nothingfound']); 138c64c1748SAndreas Gohr return; 139c64c1748SAndreas Gohr } 140c64c1748SAndreas Gohr 141c64c1748SAndreas Gohr $width = count($result[0]); 142c64c1748SAndreas Gohr $height = count($result); 143c64c1748SAndreas Gohr 144c64c1748SAndreas Gohr $R->table_open(); 145c64c1748SAndreas Gohr for ($x = 0; $x < $width; $x++) { 146*19d0a884SAndreas Gohr $col = array_keys($result[0])[$x]; 147*19d0a884SAndreas Gohr $header = preg_replace('/_wiki$/', ' ', $col); // remove _wiki type suffix 148*19d0a884SAndreas Gohr 149c64c1748SAndreas Gohr $R->tablerow_open(); 150c64c1748SAndreas Gohr $R->tableheader_open(); 151*19d0a884SAndreas Gohr $R->cdata($header); 152c64c1748SAndreas Gohr $R->tableheader_close(); 153c64c1748SAndreas Gohr 154c64c1748SAndreas Gohr for ($y = 0; $y < $height; $y++) { 155c64c1748SAndreas Gohr $R->tablecell_open(); 156*19d0a884SAndreas Gohr $this->cellFormat(array_values($result[$y])[$x], $R, $col); 157c64c1748SAndreas Gohr $R->tablecell_close(); 158c64c1748SAndreas Gohr } 159c64c1748SAndreas Gohr $R->tablerow_close(); 160c64c1748SAndreas Gohr } 161c64c1748SAndreas Gohr $R->table_close(); 162c64c1748SAndreas Gohr } 163c64c1748SAndreas Gohr 1641b7b5e66SAndreas Gohr /** 1651b7b5e66SAndreas Gohr * Pass the given cell content to the correct renderer call 1661b7b5e66SAndreas Gohr * 1671b7b5e66SAndreas Gohr * Detects a subset of the wiki link syntax 1681b7b5e66SAndreas Gohr * 1691b7b5e66SAndreas Gohr * @param string $content 1701b7b5e66SAndreas Gohr * @param Doku_Renderer $R 171*19d0a884SAndreas Gohr * @param string $name Name of the selected column 1721b7b5e66SAndreas Gohr * @return void 1731b7b5e66SAndreas Gohr */ 174*19d0a884SAndreas Gohr protected function cellFormat($content, Doku_Renderer $R, $name) 1751b7b5e66SAndreas Gohr { 176*19d0a884SAndreas Gohr if(trim($content) === '') { 177*19d0a884SAndreas Gohr return; 178*19d0a884SAndreas Gohr } 179*19d0a884SAndreas Gohr 180*19d0a884SAndreas Gohr // parse wiki syntax 181*19d0a884SAndreas Gohr if(str_ends_with($name, '_wiki')) { 182*19d0a884SAndreas Gohr $this->renderInject($R, $content); 183*19d0a884SAndreas Gohr return; 184*19d0a884SAndreas Gohr } 185*19d0a884SAndreas Gohr 1861b7b5e66SAndreas Gohr // external urls 1871b7b5e66SAndreas Gohr if (preg_match('/^\[\[(https?:\/\/[^|\]]+)(|.*?)?]]$/', $content, $m)) { 1881b7b5e66SAndreas Gohr $url = $m[1]; 1891b7b5e66SAndreas Gohr $title = $m[2] ?? ''; 1901b7b5e66SAndreas Gohr $title = trim($title, '|'); 1911b7b5e66SAndreas Gohr $R->externallink($url, $title); 1921b7b5e66SAndreas Gohr return; 1931b7b5e66SAndreas Gohr } 1941b7b5e66SAndreas Gohr 1951b7b5e66SAndreas Gohr // internal urls 1961b7b5e66SAndreas Gohr if (preg_match('/^\[\[([^|\]]+)(|.*?)?]]$/', $content, $m)) { 1971b7b5e66SAndreas Gohr $page = cleanID($m[1]); 1981b7b5e66SAndreas Gohr $title = $m[2] ?? ''; 1991b7b5e66SAndreas Gohr $title = trim($title, '|'); 2001b7b5e66SAndreas Gohr $R->internallink($page, $title); 2011b7b5e66SAndreas Gohr return; 2021b7b5e66SAndreas Gohr } 2031b7b5e66SAndreas Gohr 2041b7b5e66SAndreas Gohr $R->cdata($content); 2051b7b5e66SAndreas Gohr } 206*19d0a884SAndreas Gohr 207*19d0a884SAndreas Gohr /** 208*19d0a884SAndreas Gohr * Injects the given syntax into the current renderer 209*19d0a884SAndreas Gohr * 210*19d0a884SAndreas Gohr * @param Doku_Renderer $R 211*19d0a884SAndreas Gohr * @param string $syntax 212*19d0a884SAndreas Gohr * @return void 213*19d0a884SAndreas Gohr */ 214*19d0a884SAndreas Gohr protected function renderInject(Doku_Renderer $R, $syntax) 215*19d0a884SAndreas Gohr { 216*19d0a884SAndreas Gohr $instructions = p_get_instructions($syntax); 217*19d0a884SAndreas Gohr foreach ($instructions as $instruction) { 218*19d0a884SAndreas Gohr // not these 219*19d0a884SAndreas Gohr if(in_array($instruction[0], ['document_start', 'document_end'])) { 220*19d0a884SAndreas Gohr continue; 221*19d0a884SAndreas Gohr } 222*19d0a884SAndreas Gohr 223*19d0a884SAndreas Gohr // no headers 224*19d0a884SAndreas Gohr if($instruction[0] === 'header') { 225*19d0a884SAndreas Gohr $R->p_open(); 226*19d0a884SAndreas Gohr $R->strong_open(); 227*19d0a884SAndreas Gohr $R->cdata($instruction[1][0]); 228*19d0a884SAndreas Gohr $R->strong_close(); 229*19d0a884SAndreas Gohr $R->p_close(); 230*19d0a884SAndreas Gohr continue; 231*19d0a884SAndreas Gohr } 232*19d0a884SAndreas Gohr 233*19d0a884SAndreas Gohr call_user_func_array([$R, $instruction[0]], $instruction[1]); 234*19d0a884SAndreas Gohr } 235*19d0a884SAndreas Gohr } 236c64c1748SAndreas Gohr} 237