1<?php 2 3/** 4 * DokuWiki Plugin dbquery (Helper Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr <dokuwiki@cosmocode.de> 8 */ 9class helper_plugin_dbquery extends dokuwiki\Extension\Plugin 10{ 11 12 /** 13 * @param string $name Page name of the query 14 * @return array 15 * @throws \Exception 16 */ 17 public function loadCodeBlocksFromPage($name) 18 { 19 20 $name = cleanID($name); 21 $id = $this->getConf('namespace') . ':' . $name; 22 if (!page_exists($id)) throw new \Exception("No query named '$name' found"); 23 24 $doc = p_cached_output(wikiFN($id), 'dbquery'); 25 26 return json_decode($doc, true); 27 } 28 29 /** 30 * Opens a database connection, executes the query and returns the result 31 * 32 * @param string $query 33 * @return array 34 * @throws \PDOException 35 * @todo should we keep the DB connection around for subsequent queries? 36 * @todo should we allow SELECT queries only for additional security? 37 */ 38 public function executeQuery($query) 39 { 40 41 $opts = [ 42 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // always fetch as array 43 PDO::ATTR_EMULATE_PREPARES => true, // emulating prepares allows us to reuse param names 44 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // we want exceptions, not error codes 45 ]; 46 $pdo = new PDO( 47 $this->getConf('dsn'), 48 $this->getConf('user'), 49 conf_decodeString($this->getConf('pass')), 50 $opts 51 ); 52 53 $params = $this->gatherVariables(); 54 $sth = $this->prepareStatement($pdo, $query, $params); 55 $sth->execute(); 56 $data = $sth->fetchAll(PDO::FETCH_ASSOC); 57 $sth->closeCursor(); 58 59 return $data; 60 } 61 62 /** 63 * Generate a prepared statement with bound parameters 64 * 65 * @param PDO $pdo 66 * @param string $sql 67 * @param string[] $parameters 68 * @return PDOStatement 69 */ 70 public function prepareStatement(\PDO $pdo, $sql, $parameters) 71 { 72 $sth = $pdo->prepare($sql); 73 74 foreach ($parameters as $key => $val) { 75 if (is_array($val)) continue; 76 if (is_object($val)) continue; 77 if (strpos($sql, $key) === false) continue; // skip if parameter is missing 78 79 if (is_int($val)) { 80 $sth->bindValue($key, $val, PDO::PARAM_INT); 81 } else { 82 $sth->bindValue($key, $val); 83 } 84 } 85 86 return $sth; 87 } 88 89 /** 90 * Get the standard replacement variables 91 * 92 * @return array 93 */ 94 public function gatherVariables() 95 { 96 global $USERINFO; 97 global $INFO; 98 global $INPUT; 99 100 // add leading colon 101 $id = ':' . $INFO['id']; 102 return [ 103 ':user' => $INPUT->server->str('REMOTE_USER'), 104 ':mail' => $USERINFO['mail'] ?: '', 105 ':groups' => $USERINFO['grps'] ? join(',', $USERINFO['grps']) : '', //FIXME escaping correct??? 106 ':id' => $id, 107 ':page' => noNS($id), 108 ':ns' => getNS($id), //FIXME check that leading colon exists 109 ]; 110 } 111} 112