php8
[web.mtrack] / MTrack / DB.php
1 <?php
2
3 require_once 'MTrack/Interface/DBExtension.php';
4 require_once 'MTrack/Config.php';
5
6 class MTrackDB {
7   static $db = null;
8   static $extensions = array();
9   static $queries = 0;
10   static $query_strings = array();
11
12   static function registerExtension(IMTrackDBExtension $ext) {
13     self::$extensions[] = $ext;
14   }
15
16   // given a unix timestamp, return a value timestamp string
17   // suitable for use with the database
18     static function unixtime($unix) 
19     {
20         list($unix) = explode('.', $unix, 2);
21         if ($unix == 0) {
22           return null;
23         }
24         if ($unix < 10) {
25           throw new Exception("unix time $unix is too small\n");
26         }
27         $d = date_create("@$unix", new DateTimeZone('UTC'));
28         // 2008-12-22T05:42:42.285445Z
29         if (!is_object($d)) {
30           throw new Exception("failed to create date for time $unix");
31         }
32         return $d->format('Y-m-d\TH:i:s.u\Z');
33     }
34
35     static function get() 
36     {
37       
38         if (self::$db != null) {
39             return self::$db;
40         }
41         
42         
43         $dsn = MTrackConfig::get('core', 'dsn');
44         $user = MTrackConfig::get('core', 'dsnuser');
45         $pass = MTrackConfig::get('core', 'dsnpassword');
46         if ($dsn === null) {
47             $dsn = 'sqlite:' . MTrackConfig::get('core', 'dblocation');
48         }
49         $db = new PDO($dsn, $user, $pass);
50         $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
51         self::$db = $db;
52
53         if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'sqlite') {
54             
55             $db->sqliteCreateAggregate('mtrack_group_concat',
56                 array('MTrackDB', 'group_concat_step'),
57                 array('MTrackDB', 'group_concat_final'));
58
59             $db->sqliteCreateFunction('mtrack_cleanup_attachments',
60                 array('MTrackAttachment', 'attachment_row_deleted'));
61         }
62
63         foreach (self::$extensions as $ext) {
64             $ext->onHandleCreated($db);
65         }
66     
67         return self::$db;
68     } 
69
70   static function lastInsertId($tablename, $keyfield) {
71     if (!strlen($tablename) || !strlen($keyfield)) {
72       throw new Exception("missing tablename or keyfield");
73     }
74     if (self::$db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'pgsql') {
75       return self::$db->lastInsertId($tablename . '_' . $keyfield . '_seq');
76     } else {
77       return self::$db->lastInsertId();
78     }
79   }
80
81   
82   // bit like stored procs in SQLITE..
83   static function group_concat_step($context, $rownum, $value)
84   {
85     if (!is_array($context)) {
86       $context = array();
87     }
88     $context[] = $value;
89     return $context;
90   }
91   static function group_concat_final($context, $rownum)
92   {
93     if ($context === null) {
94       return null;
95     }
96     asort($context);
97     return join(", ", $context);
98   }
99
100   static function esc($str) // escape..
101   {
102     return "'" . str_replace("'", "''", $str) . "'";
103   }
104
105   /* issue a query, passing optional parameters */
106   static function q($sql) {
107         self::$queries++;
108         if (isset(self::$query_strings[$sql])) {
109           self::$query_strings[$sql]++;
110         } else {
111           self::$query_strings[$sql] = 1;
112         }
113         $params = func_get_args();
114         array_shift($params);
115         $db = self::get();
116     #      echo "<br>SQL: $sql\n";
117     #      var_dump($params);
118     #echo "<br>";
119         try {
120           if (count($params)) {
121             $q = $db->prepare($sql);
122             $q->execute($params);
123           } else {
124             $q = $db->query($sql);
125           }
126         } catch (Exception $e) {
127           echo $e->getMessage();
128           throw $e;
129         }
130         return $q;
131       }
132 }