Add insertInto and update as special methods
[infodrom.org/service.infodrom.org] / class / database.class.php
1 <?php
2
3 class Database {
4   private $db;
5   private $error_log = false;
6   private $error_mail = false;
7   private $lastInsertTable = null;
8
9   public function __construct($driver, $host, $dbname, $user, $passwd)
10   {
11     $this->db = new PDO(sprintf('%s:host=%s;dbname=%s', $driver, $host, $dbname), $user, $passwd);
12
13     #    $this->db->query("SET NAMES 'utf8'"); 
14     #    $this->db->query("SET CHARACTER SET 'utf8'");
15     #    $this->db->query("SET collation_connection = 'utf8_general_ci'");
16     #    $this->db->query("SET lc_time_names = 'de_DE'");
17   }
18
19   public function enableErrorLog()
20   {
21     $this->error_log = true;
22   }
23
24   public function disableErrorLog()
25   {
26     $this->error_log = false;
27   }
28
29   public function setErrorMail($address)
30   {
31     $this->error_mail = $address;
32   }
33
34   private function logQuery($sql)
35   {
36     if ($this->error_log) error_log(trim(str_replace("\n", ' ', $sql)));
37   }
38
39   private function handleError($sth, $sql, $data=false)
40   {
41     if (!$this->error_log) error_log(trim(str_replace("\n", ' ', $sql)));
42     $arr = $this->db->errorInfo();
43     foreach (explode("\n", $arr[2]) as $line)
44       error_log($line);
45
46     if ($this->error_mail && defined('MAIL_FROM') && defined('MAIL_FROM_NAME')) {
47       $mail = new Mail();
48       $mail->env_from(MAIL_FROM);
49       $mail->set('From', mb_encode_mimeheader(utf8_decode(sprintf("%s <%s>", MAIL_FROM_NAME, MAIL_FROM)),'latin1'));
50       $mail->set('To', $this->error_mail);
51       $mail->set('Subject', 'SQL Error in ' . $_SERVER['REQUEST_URI']);
52
53       $body = sprintf("http://%s%s%s\nReferer: %s\nUser: %s\n\n%s\n\nError Number %d\n%s\n\n",
54                       $_SERVER['SERVER_NAME'],
55                       $_SERVER['SERVER_PORT'] != 80 ? ':'.$_SERVER['SERVER_PORT'] : '',
56                       $_SERVER['REQUEST_URI'],
57                       $_SERVER['HTTP_REFERER'],
58                       $_SESSION['sys']['login'],
59                       trim($sql),
60                       $arr[1],
61                       $arr[2]);
62
63       ob_start();
64       debug_print_backtrace();
65       $body .= ob_get_contents()."\n";
66       ob_end_clean();
67
68       if (count($_POST)) $body .= 'POST: ' . var_export($_POST,true)."\n";
69       if (count($_GET)) $body .= 'GET: ' . var_export($_GET,true)."\n";
70       if (count($_SESSION)) $body .= 'SESSION: ' . var_export($_SESSION,true)."\n";
71       if ($data) $body .= 'data: ' . var_export($data,true)."\n";
72
73       $mail->send($body);
74     }
75     return $sth;
76   }
77
78   public function errorInfo()
79   {
80     return $this->db->errorInfo();
81   }
82
83   public function quote($string)
84   {
85     if (is_null($string)) return 'NULL';
86     if (strtolower($string) == 'now()' || strtolower($string) == 'current_timestamp') return 'now()';
87     return $this->db->quote($string);
88   }
89
90   public function lastInsertId()
91   {
92     if (DBDRIVER == 'pgsql')
93       return $this->db->lastInsertId($this->lastInsertTable.'_id_seq');
94     else
95       return $this->db->lastInsertId();
96   }
97
98   private function query($sql)
99   {
100     $this->logQuery($sql);
101     $sth = $this->db->query($sql);
102
103     if ($sth === false) return $this->handleError($sth,$sql);
104
105     if (preg_match('/INSERT\s+INTO\s+(\S+)\s+/i', $sql, $matches))
106       $this->lastInsertTable = $matches[1];
107
108     return $sth;
109   }
110
111   public function execute($sql)
112   {
113     return $this->query($sql) !== false;
114   }
115
116   public function fetchValue($sql)
117   {
118     $sth = $this->query($sql);
119     if ($sth === false) return false;
120     $ret = $sth->fetch(PDO::FETCH_BOTH);
121     if ($ret === false) return false;
122     return $ret[0];
123   }
124
125   public function fetchAssoc($sql)
126   {
127     $sth = $this->query($sql);
128     if ($sth === false) return false;
129     return $sth->fetch(PDO::FETCH_ASSOC);
130   }
131
132   public function fetchObject($sql)
133   {
134     $sth = $this->query($sql);
135     if ($sth === false) return false;
136     return $sth->fetchObject();
137   }
138
139   public function fetchAssocList($sql)
140   {
141     $result = array();
142     $sth = $this->query($sql);
143     if ($sth === false) return $result;
144     while ($row = $sth->fetch(PDO::FETCH_ASSOC))
145       $result[] = $row;
146     return $result;
147   }
148
149   public function fetchObjectList($sql)
150   {
151     $result = array();
152     $sth = $this->query($sql);
153     if ($sth === false) return $result;
154     while ($row = $sth->fetchObject())
155       $result[] = $row;
156     return $result;
157   }
158
159   private function executeBind($sql, $data)
160   {
161     $sth = $this->db->prepare($sql);
162     if ($sth === false) return $this->handleError($sth,$sql);
163
164     foreach ($data as $key => $value) {
165       if(is_int($value))
166         $param = PDO::PARAM_INT;
167       elseif(is_bool($value))
168         $param = PDO::PARAM_BOOL;
169       elseif(is_null($value))
170         $param = PDO::PARAM_NULL;
171       elseif(is_string($value))
172         $param = PDO::PARAM_STR;
173       else
174         $param = FALSE;
175
176       $sth->bindValue(':'.$key, $value, $param);
177     }
178
179     $ok = $sth->execute();
180     if ($ok === false) return $this->handleError($sth,$sql,$data);
181
182     if (preg_match('/INSERT\s+INTO\s+(\S+)\s+/i', $sql, $matches))
183       $this->lastInsertTable = $matches[1];
184
185     return $ok;
186   }
187
188   public function insertInto($table, $data)
189   {
190     if (!is_array($data)) throw Exception('insertInto called without data array');
191
192     $columns = array();
193     foreach ($data as $k => $v) {
194       $columns[] = $k;
195       $values[] = ':' . $k;
196     }
197
198     $sql = sprintf("INSERT INTO %s (%s)\n    VALUES (%s)",
199                    $table,
200                    implode(',', $columns),
201                    implode(',', $values));
202     return $this->executeBind($sql, $data);
203   }
204
205   public function update($table, $data, $condition)
206   {
207     if (!is_array($data)) throw Exception('update called without data array');
208     if (empty($condition)) throw Exception('update called without condition');
209
210     $set = array();
211     foreach ($data as $k => $v)
212       $set[] = $k.'=:'.$k;
213
214     $sql = sprintf("UPDATE %s SET %s\n    WHERE %s",
215                    $table,
216                    implode(',', $set),
217                    $condition);
218     return $this->executeBind($sql, $data);
219   }
220
221 }
222
223 ?>