1<?php 2 3/** 4 * Database wrapper 5 * @package framework 6 * @subpackage db 7 */ 8 9/** 10 * DB interface for the framework and modules 11 */ 12class Hm_DB { 13 14 /* DB connection handlers */ 15 static public $dbh = array(); 16 17 /* required DB configuration params */ 18 static private $required_config = array('db_user', 'db_pass', 'db_name', 'db_host', 'db_driver'); 19 20 /* DB config */ 21 static private $config; 22 23 /** 24 * Load DB configuration from the site config 25 * @param object $site_config site config 26 * @return void 27 */ 28 static private function parse_config($site_config) { 29 self::$config = array('db_driver' => $site_config->get('db_driver', false), 30 'db_host' => $site_config->get('db_host', false), 31 'db_name' => $site_config->get('db_name', false), 32 'db_user' => $site_config->get('db_user', false), 33 'db_pass' => $site_config->get('db_pass', false), 34 'db_socket' => $site_config->get('db_socket', false), 35 'db_conn_type' => $site_config->get('db_connection_type', 'host'), 36 ); 37 foreach (self::$required_config as $v) { 38 if (!self::$config[$v]) { 39 Hm_Debug::add(sprintf('Missing configuration setting for %s', $v)); 40 } 41 } 42 } 43 44 /** 45 * Return a unique key for a DB connection 46 * @return string md5 of the DB settings 47 */ 48 static private function db_key() { 49 return md5(self::$config['db_driver']. 50 self::$config['db_host']. 51 self::$config['db_name']. 52 self::$config['db_user']. 53 self::$config['db_pass']. 54 self::$config['db_conn_type']. 55 self::$config['db_socket'] 56 ); 57 } 58 59 /** 60 * Build a DSN to connect to the db with 61 * @return string 62 */ 63 static public function build_dsn() { 64 if (self::$config['db_driver'] == 'sqlite') { 65 return sprintf('%s:%s', self::$config['db_driver'], self::$config['db_socket']); 66 } 67 if (self::$config['db_conn_type'] == 'socket') { 68 return sprintf('%s:unix_socket=%s;dbname=%s', self::$config['db_driver'], self::$config['db_socket'], self::$config['db_name']); 69 } 70 else { 71 return sprintf('%s:host=%s;dbname=%s', self::$config['db_driver'], self::$config['db_host'], self::$config['db_name']); 72 } 73 } 74 75 /** 76 * @param object|false $dbh PDO connection object 77 * @param string $sql sql with placeholders to execute 78 * @param array $args values to insert into the sql 79 * @param bool $type optional type of sql query 80 * @param bool $all optional flag to return multiple rows 81 * @return boolean|integer|array 82 */ 83 static public function execute($dbh, $sql, $args, $type=false, $all=false) { 84 if (!$dbh) { 85 return false; 86 } 87 if (!$type) { 88 $type = self::execute_type($sql); 89 } 90 $sql = $dbh->prepare($sql); 91 if (!$sql || !$sql->execute($args)) { 92 return false; 93 } 94 if ($type == 'modify' || $type == 'insert') { 95 return $sql->rowCount(); 96 } 97 if ($all) { 98 return $sql->fetchAll(PDO::FETCH_ASSOC); 99 } 100 return $sql->fetch(PDO::FETCH_ASSOC); 101 } 102 103 /** 104 * @param string $sql query string 105 * @return string 106 */ 107 static private function execute_type($sql) { 108 switch(substr($sql, 0, 1)) { 109 case 'd': 110 case 'u': 111 case 'i': 112 return 'modify'; 113 case 's': 114 default: 115 return 'select'; 116 } 117 } 118 119 /** 120 * Connect to a DB server 121 * @param object $site_config site settings 122 * @return object|false database connection on success 123 */ 124 static public function connect($site_config) { 125 self::parse_config($site_config); 126 $key = self::db_key(); 127 128 if (array_key_exists($key, self::$dbh) && self::$dbh[$key]) { 129 return self::$dbh[$key]; 130 } 131 $dsn = self::build_dsn(); 132 try { 133 self::$dbh[$key] = new PDO($dsn, self::$config['db_user'], self::$config['db_pass']); 134 self::$dbh[$key]->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 135 Hm_Debug::add(sprintf('Connecting to dsn: %s', $dsn)); 136 return self::$dbh[$key]; 137 } 138 catch (Exception $oops) { 139 Hm_Debug::add($oops->getMessage()); 140 self::$dbh[$key] = false; 141 return false; 142 } 143 } 144} 145