fixed rotation: for some reason 90 and 270 degrees had to be switched
[phpfspot.git] / phpfspot_db.php
1 <?php
2
3 /***************************************************************************
4  *
5  * phpfspot, presents your F-Spot photo collection in Web browsers.
6  *
7  * Copyright (c) by Andreas Unterkircher
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  ***************************************************************************/
24
25 /**
26  * PHPFSPOT_DB class
27  *
28  * @package phpfspot
29  */
30 class PHPFSPOT_DB {
31
32    private $db;
33    private $db_path;
34    private $parent;
35    private $is_connected;
36    private $last_error;
37    private $last_query;
38
39    /**
40     * PHPFSPOT_DB class constructor
41     *
42     * This constructor initially connect to the database.
43     */
44    public function __construct($parent, $db_path)
45    {
46       global $phpfspot;
47
48       $this->parent = $phpfspot;
49       $this->db_path = $db_path;
50
51       /* We are starting disconnected */
52       $this->setConnStatus(false);
53
54       /* Connect to database */
55       $this->db_connect();
56
57    } // __construct()
58          
59    /**
60     * PHPFSPOT_DB class deconstructor
61     *
62     * This destructor will close the current database connection.
63     */ 
64    public function __destruct()
65    {
66       $this->db_disconnect();
67
68    } // _destruct()
69
70    /**
71     * PHPFSPOT_DB database connect
72     *
73     * This function will connect to the database
74     */
75    private function db_connect()
76    {
77       switch($this->parent->cfg->db_access) {
78          case 'native':
79             if(($this->db = sqlite3_open($this->db_path)) === false) {
80                $this->throwError("Unable to connect to database:" . $this->getLastError());
81                $this->setConnStatus(false);
82             }
83             else {
84                sqlite3_create_function($this->db, 'basename', 1, 'basename');
85                $this->setConnStatus(true);
86             }
87             break;
88          case 'pdo':
89             try {
90                $this->db =  new PDO("sqlite:".$this->db_path);
91                $this->setConnStatus(true);
92             }
93             catch (Exception $e) {
94                $this->throwError("Unable to connect to database:" . $e->getMessage());
95                $this->setConnStatus(false);
96             }
97             break;
98
99       }
100
101    } // db_connect()
102
103    /**
104     * PHPFSPOT_DB database disconnect
105     *
106     * This function will disconnected an established database connection.
107     */
108    private function db_disconnect()
109    {
110       switch($this->parent->cfg->db_access) {
111          case 'native':
112             if($this->getConnStatus())
113                sqlite3_close($this->db);
114             break;
115          case 'pdo':
116             $this->db = NULL;
117             break;
118       }
119
120    } // db_disconnect()
121
122    /**
123     * PHPFSPOT_DB database query
124     *
125     * This function will execute a SQL query and return the result as
126     * object.
127     */
128    public function db_query($query = "")
129    {
130       if(!$this->getConnStatus())
131          return false;
132    
133       $this->last_query = $query;
134
135       switch($this->parent->cfg->db_access) {
136          case 'native':
137             if(($result = sqlite3_query($this->db, $query)) === false)
138                $this->ThrowError($this->getLastError());
139             break;
140          case 'pdo':
141             try{
142                $result = $this->db->query($query);
143                return $result;
144             }
145             catch (Exception $e) {
146                $this->ThrowError($e->getMessage());
147                $result= NULL;
148             }
149             break;
150
151       }
152
153       return $result;
154
155    } // db_query()
156
157    /**
158     * PHPFSPOT_DB database query & execute
159     *
160     * This function will execute a SQL query and return nothing.
161     */
162    public function db_exec($query = "")
163    {
164       if(!$this->getConnStatus())
165          return false;
166
167       $this->last_query = $query;
168
169       switch($this->parent->cfg->db_access) {
170          case 'native':
171             if(($result = sqlite3_exec($this->db, $query)) === false) {
172                $this->ThrowError($this->getLastError());
173                return false;
174             }
175             break;
176          case 'pdo':
177             try {
178                $result = $this->db->query($query);
179             }
180             catch (Exception $e){
181                $this->ThrowError($e->getLMessage());
182                return false;
183             }
184             break;
185       }
186
187       return true;
188
189    } // db_exec()
190
191    public function db_fetch_object($resource)
192    {
193       switch($this->parent->cfg->db_access) {
194          case 'native':
195             return sqlite3_fetch_array($resource);
196          case 'pdo':
197             return $resource->fetch();
198       }
199
200    } // db_fetch_object
201
202    /**
203     * PHPFSPOT_DB fetch ONE row
204     *
205     * This function will execute the given but only return the
206     * first result.
207     */
208    public function db_fetchSingleRow($query = "") 
209    {
210       if(!$this->getConnStatus())
211          return false;
212
213       $result = $this->db_query($query);
214       switch($this->parent->cfg->db_access) {
215          case 'native':
216             $row = $this->db_fetch_object($result);
217             break;
218          case 'pdo':
219             $row = $result->fetch();
220             break;
221       }
222       return $row;
223       
224    } // db_fetchSingleRow()
225
226    /**
227     * PHPFSPOT_DB number of affected rows
228     *
229     * This functions returns the number of affected rows but the
230     * given SQL query.
231     */
232    public function db_getNumRows($query = "")
233    {
234       /* Execute query */
235       $result = $this->db_query($query);
236
237       /* Errors? */
238       if(PEAR::isError($result)) 
239          $this->throwError($result->getMessage());
240
241       return $result->numRows();
242
243    } // db_getNumRows()
244
245    /**
246     * PHPFSPOT_DB check table exists
247     *
248     * This function checks if the given table exists in the
249     * database
250     * @param string, table name
251     * @return true if table found otherwise false
252     */
253    public function db_check_table_exists($table_name = "")
254    {
255       if(!$this->getConnStatus())
256          return false;
257
258       $result = $this->db_query("SELECT name FROM sqlite_master WHERE type='table'");
259       switch($this->parent->cfg->db_access) {
260          case 'native':
261             while($table = $this->db_fetch_object($result)) {
262                if($table['name'] == $table_name)
263                   return true;
264             }
265             break;
266          case 'pdo':
267             foreach($result as $table ){
268                if($table['NAME'] == $table_name)
269                   return true;
270             }
271             break;
272        }
273
274       return false;
275          
276    } // db_check_table_exists()
277
278    /**
279     * PHPFSPOT_DB check column exist
280     *
281     * This function checks if the given column exists within
282     * the specified table.
283     */
284    public function db_check_column_exists($table_name, $column)
285    {
286       if(!$this->getConnStatus())
287          return false;
288
289       $result = $this->db_query("
290          SELECT sql
291          FROM
292             (SELECT * FROM sqlite_master UNION ALL
293              SELECT * FROM sqlite_temp_master)
294          WHERE
295             tbl_name LIKE '". $table_name ."'
296          AND type!='meta'
297          AND sql NOT NULL
298          AND name NOT LIKE 'sqlite_%'
299          ORDER BY substr(type,2,1), name
300       ");
301
302       while($row = $this->db_fetch_object($result)) {
303          /* CREATE TABLE xx ( col1 int, col2 bool, col3 ...) */
304          if(strstr($row['sql'], " ". $column ." ") !== false)
305                return true;
306       }
307
308       return false;
309
310    } // db_check_column_exists()
311
312    /**
313     * PHPFSPOT_DB get connection status
314     *
315     * This function checks the internal state variable if already
316     * connected to database.
317     */
318    private function setConnStatus($status)
319    {
320       $this->is_connected = $status;
321       
322    } // setConnStatus()
323
324    /**
325     * PHPFSPOT_DB set connection status
326     * This function sets the internal state variable to indicate
327     * current database connection status.
328     */
329    private function getConnStatus()
330    {
331       return $this->is_connected;
332
333    } // getConnStatus()
334
335    /**
336     * PHPFSPOT_DB throw error
337     *
338     * This function shows up error messages and afterwards through exceptions.
339     */
340    private function ThrowError($string)
341    {
342       if(!defined('DB_NOERROR'))  {
343          print "Error during query: ". $this->last_query ."<br /><br />\n";
344          print "<br /><br />". $string ."<br /><br />\n";
345          try {
346             throw new Exception;
347          }
348          catch(Exectpion $e) {
349          }
350       }
351
352       $this->last_error = $string;
353          
354    } // ThrowError()
355
356    private function getLastError()
357    {
358       switch($this->parent->cfg->db_access) {
359          case 'native':
360             return sqlite3_error($this->db);
361          case 'pdo':
362             return "". $this->db->errorInfo();
363       }
364
365    } // getLastError()
366
367    /**
368     * start transaction
369     *
370     * this will start a transaction on ACID-supporting database
371     * systems.
372     *
373     * @return bool
374     */
375    public function db_start_transaction()
376    {
377       if(!$this->getConnStatus())
378          return false;
379
380       $result = $this->db_exec("BEGIN");
381
382       /* Errors? */
383       if(PEAR::isError($result))
384          $this->throwError($result->getMessage() .' - '. $result->getUserInfo());
385
386       return true;
387
388    } // db_start_transaction()
389
390    /**
391     * commit transaction
392     *
393     * this will commit an ongoing transaction on ACID-supporting
394     * database systems
395     *
396     * @return bool
397     */
398    public function db_commit_transaction()
399    {
400       if(!$this->getConnStatus())
401          return false;
402
403       $result = $this->db_exec("COMMIT");
404
405       /* Errors? */
406       if(PEAR::isError($result))
407          $this->throwError($result->getMessage() .' - '. $result->getUserInfo());
408
409       return true;
410
411    } // db_commit_transaction()
412
413    /**
414     * rollback transaction()
415     *
416     * this function aborts a on going transaction
417     *
418     * @return bool
419     */
420    public function db_rollback_transaction()
421    {
422       if(!$this->getConnStatus())
423          return false;
424
425       $result = $this->db_exec("ROLLBACK");
426
427       /* Errors? */
428       if(PEAR::isError($result))
429          $this->throwError($result->getMessage() .' - '. $result->getUserInfo());
430
431       return true;
432
433    } // db_rollback_transaction()
434
435 } // PHPFSPOT_DB
436
437 ?>