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