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