]> git.mxchange.org Git - friendica.git/blobdiff - include/dba.php
profile redir - goto correct profile page even if contact blocked, you just can't...
[friendica.git] / include / dba.php
index 782c279d5d0ec78815240acf9ad5ee7abaf8a07c..1421a703dc730ad1a7eb803e30c632ff0d17937c 100644 (file)
 <?php
 
+require_once('include/datetime.php');
+
 /**
  *
  * MySQL database class
  *
  * For debugging, insert 'dbg(1);' anywhere in the program flow.
  * dbg(0); will turn it off. Logging is performed at LOGGER_DATA level.
- * When logging, all binary info is converted to text and html entities are escaped so that 
- * the debugging stream is safe to view within both terminals and web pages.
+ * When logging, all binary info is converted to
+ * text and html entities are escaped so that
+ * the debugging stream is safe to view
+ * within both terminals and web pages.
  *
  */
-if(! class_exists('dba')) { 
-class dba {
-
-       private $debug = 0;
-       private $db;
-       public  $mysqli = true;
-       public  $connected = false;
-       public  $error = false;
-
-       function __construct($server,$user,$pass,$db,$install = false) {
-
-               $server = trim($server);
-               $user = trim($user);
-               $pass = trim($pass);
-               $db = trim($db);
-
-               if (!(strlen($server) && strlen($user))){
-                       $this->connected = false;
-                       $this->db = null;
-                       return;                 
-               }
+
+if(! class_exists('dba')) {
+
+       class dba {
+
+               private $debug = 0;
+               private $db;
+               private $exceptions; 
                
-               if($install) {
-                       if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
-                               if(! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
-                                       $this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
-                                       $this->connected = false;
-                                       $this->db = null;
-                                       return;
+               public  $mysqli = true;
+               public  $connected = false;
+               public  $error = false;
+
+               function __construct($server,$user,$pass,$db,$install = false) {
+
+                       $server = trim($server);
+                       $user = trim($user);
+                       $pass = trim($pass);
+                       $db = trim($db);
+
+                       //we need both, server and username, so fail if one is missing
+                       if (!(strlen($server) && strlen($user))){
+                               $this->connected = false;
+                               $this->db = null;
+                               throw new InvalidArgumentException(t("Server name of user name are missing. "));
+                       }
+
+                       //when we are installing
+                       if($install) {
+                               if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
+                                       if(! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
+                                               $this->connected = false;
+                                               $this->db = null;
+                                               throw new InvalidArgumentException( t('Cannot locate DNS info for database server \'%s\''), $server);
+                                       }
                                }
                        }
-               }
 
-               if(class_exists('mysqli')) {
-                       $this->db = @new mysqli($server,$user,$pass,$db);
-                       if(! mysqli_connect_errno()) {
-                               $this->connected = true;
+                       if(class_exists('mysqli')) {
+                               $this->db = new mysqli($server,$user,$pass,$db);
+                               if(NULL === $this->db->connect_error) {
+                                       $this->connected = true;
+                               } else {
+                                       throw new RuntimeException($this->db->connect_error);
+                               }
+                       } else {
+                               $this->mysqli = false;
+                               $this->db = mysql_connect($server,$user,$pass);
+                               if($this->db && mysql_select_db($db,$this->db)) {
+                                       $this->connected = true;
+                               } else {
+                                       throw new RuntimeException(mysql_error());
+                               }
                        }
                }
-               else {
-                       $this->mysqli = false;
-                       $this->db = mysql_connect($server,$user,$pass);
-                       if($this->db && mysql_select_db($db,$this->db)) {
-                               $this->connected = true;
-                       }
+
+               public function excep($excep) {
+                       $this->exceptions=$excep; 
                }
-               if(! $this->connected) {
-                       $this->db = null;
-                       if(! $install)
-                               system_unavailable();
+               
+               public function getdb() {
+                       return $this->db;
                }
-       }
 
-       public function getdb() {
-               return $this->db;
-       }
+               public function q($sql) {
 
-       public function q($sql) {
-               
-               if((! $this->db) || (! $this->connected))
-                       return false;
-               
-               if($this->mysqli)
-                       $result = @$this->db->query($sql);
-               else
-                       $result = @mysql_query($sql,$this->db);
+                       if((! $this->db) || (! $this->connected)) {
+                               $this->throwOrLog(new RuntimeException(t("There is no db connection. ")));
+                               return;
+                       }
 
-               if($this->debug) {
+                       if($this->mysqli) {
+                               $result = $this->db->query($sql);
+                       } else {
+                               $result = mysql_query($sql,$this->db);
+                       }
 
-                       $mesg = '';
+                       //on debug mode or fail, the query is written to the log.
+                       //this won't work if logger can not read it's logging level
+                       //from the db.
+                       if($this->debug || FALSE === $result) {
+
+                               $mesg = '';
+
+                               if($result === false) {
+                                       $mesg = 'false '.$this->error();
+                               } elseif($result === true) {
+                                       $mesg = 'true';
+                               } else {
+                                       if($this->mysqli) {
+                                               $mesg = $result->num_rows . t(' results') . EOL;
+                                       } else {
+                                               $mesg = mysql_num_rows($result) . t(' results') . EOL;
+                                       }
+                               }
 
-                       if($this->mysqli) {
-                               if($this->db->errno)
-                                       logger('dba: ' . $this->db->error);
+                               $str =  'SQL = ' . printable($sql) . EOL . t('SQL returned ') . $mesg . EOL;
+
+
+                        // If dbfail.out exists, we will write any failed calls directly to it,
+                        // regardless of any logging that may or may nor be in effect.
+                        // These usually indicate SQL syntax errors that need to be resolved.
+                               if(file_exists('dbfail.out')) {\r
+                                       file_put_contents('dbfail.out', datetime_convert() . "\n" . $str . "\n", FILE_APPEND);
+                               }
+                               logger('dba: ' . $str );
+                               if(FALSE===$result) {
+                                       $this->throwOrLog(new RuntimeException('dba: ' . $str));
+                                       return; 
+                               }
                        }
-                       elseif(mysql_errno($this->db))
-                               logger('dba: ' . mysql_error($this->db));
-
-                       if($result === false)
-                               $mesg = 'false';
-                       elseif($result === true)
-                               $mesg = 'true';
-                       else {
-                               if($this->mysqli)
-                                       $mesg = $result->num_rows . ' results' . EOL;
-                       else
-                                       $mesg = mysql_num_rows($result) . ' results' . EOL;
+                               
+
+                       if($result === true) {
+                               return $result;
                        }
-    
-                       $str =  'SQL = ' . printable($sql) . EOL . 'SQL returned ' . $mesg . EOL;
 
-                       logger('dba: ' . $str );
-               }
-               else {
-
-                       /**
-                        * If dbfail.out exists, we will write any failed calls directly to it,
-                        * regardless of any logging that may or may nor be in effect.
-                        * These usually indicate SQL syntax errors that need to be resolved.
-                        */
-
-                       if($result === false) {
-                               logger('dba: ' . printable($sql) . ' returned false.');
-                               if(file_exists('dbfail.out'))
-                                       file_put_contents('dbfail.out', printable($sql) . ' returned false' . "\n", FILE_APPEND);
+                       $r = array();
+                       if($this->mysqli) {
+                               if($result->num_rows) {
+                                       while($x = $result->fetch_array(MYSQLI_ASSOC)) {
+                                               $r[] = $x;
+                                       }
+                                       $result->free_result();
+                               }
+                       } else {
+                               if(mysql_num_rows($result)) {
+                                       while($x = mysql_fetch_array($result, MYSQL_ASSOC)) {
+                                               $r[] = $x;
+                                       }
+                                       mysql_free_result($result);
+                               }
                        }
-               }
 
-               if(($result === true) || ($result === false))
-                       return $result;
 
-               $r = array();
-               if($this->mysqli) {
-                       if($result->num_rows) {
-                               while($x = $result->fetch_array(MYSQL_ASSOC))
-                                       $r[] = $x;
-                               $result->free_result();
+                       if($this->debug) {
+                               logger('dba: ' . printable(print_r($r, true)));
+                       }
+                       return($r);
+               }
+
+               private function error() {
+                       if($this->mysqli) {
+                               return $this->db->error;
+                       } else {
+                               return mysql_error($this->db);
                        }
                }
-               else {
-                       if(mysql_num_rows($result)) {
-                               while($x = mysql_fetch_array($result, MYSQL_ASSOC))
-                                       $r[] = $x;
-                               mysql_free_result($result);
+               
+               private function throwOrLog(Exception $ex) {
+                       if($this->exceptions) {
+                               throw $ex; 
+                       } else {
+                               logger('dba: '.$ex->getMessage()); 
                        }
                }
+               
+               /**
+                * starts a transaction. Transactions need to be finished with 
+                * commit() or rollback(). Please mind that the db table engine may
+                * not support this. 
+                */
+               public function beginTransaction() {\r
+                       if($this->mysqli) {\r
+                               return $this->db->autocommit(false);\r
+                       } else {\r
+                               //no transaction support in mysql module...
+                               mysql_query('SET AUTOCOMMIT = 0;', $db); \r
+                       }\r
+               }
+               
+               /**
+                * rollback a transaction. So, rollback anything that was done since the last call 
+                * to beginTransaction(). 
+                */
+               public function rollback() {\r
+                       if($this->mysqli) {\r
+                               return $this->db->rollback();\r
+                       } else {\r
+                               //no transaction support in mysql module...
+                               mysql_query('ROLLBACK;', $db);\r
+                       }
+                       $this->stopTransaction(); \r
+               }
 
-    
-               if($this->debug)
-                       logger('dba: ' . printable(print_r($r, true)), LOGGER_DATA);
-               return($r);
-       }
-
-       public function dbg($dbg) {
-               $this->debug = $dbg;
-       }
+               /**
+                * commit a transaction. So, write any query to the database. 
+                */
+               public function commit() {\r
+                       if($this->mysqli) {\r
+                               return $this->db->commit();\r
+                       } else {\r
+                               //no transaction support in mysql module...\r
+                               mysql_query('COMMIT;', $db);\r
+                       }\r
+                       $this->stopTransaction();\r
+               }
+               
+               private function stopTransaction() {\r
+                       if($this->mysqli) {\r
+                               return $this->db->autocommit(true);\r
+                       } else {\r
+                               //no transaction support in mysql module...\r
+                               mysql_query('SET AUTOCOMMIT = 1;', $db);\r
+                       }\r
+               }
+               
+               public function dbg($dbg) {
+                       $this->debug = $dbg;
+               }
 
-       public function escape($str) {
-               if($this->db && $this->connected) {
-                       if($this->mysqli)
-                               return @$this->db->real_escape_string($str);
-                       else
-                               return @mysql_real_escape_string($str,$this->db);
+               public function escape($str) {
+                       if($this->db && $this->connected) {
+                               if($this->mysqli) {
+                                       return $this->db->real_escape_string($str);
+                               } else {
+                                       return mysql_real_escape_string($str,$this->db);
+                               }
+                       }
                }
-       }
 
-       function __destruct() {
-               if ($this->db) 
-                       if($this->mysqli)
-                               $this->db->close();
-                       else
+               function __destruct() {
+                       if ($this->db) {
+                               if($this->mysqli) {
+                                       $this->db->close();
+                               }
+                       } else {
                                mysql_close($this->db);
+                       }
+               }
        }
-}}
+}
 
 if(! function_exists('printable')) {
-function printable($s) {
-       $s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s);
-       $s = str_replace("\x00",'.',$s);
-       if(x($_SERVER,'SERVER_NAME'))
-               $s = escape_tags($s);
-       return $s;
-}}
+       function printable($s) {
+               $s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s);
+               $s = str_replace("\x00",'.',$s);
+               if(x($_SERVER,'SERVER_NAME'))
+                       $s = escape_tags($s);
+               return $s;
+       }
+}
 
 // Procedural functions
-if(! function_exists('dbg')) { 
-function dbg($state) {
-       global $db;
-       if($db)
-       $db->dbg($state);
-}}
+if(! function_exists('dbg')) {
+       function dbg($state) {
+               global $db;
+               if($db)
+                       $db->dbg($state);
+       }
+}
 
-if(! function_exists('dbesc')) { 
-function dbesc($str) {
-       global $db;
-       if($db && $db->connected)
-               return($db->escape($str));
-       else
-               return(str_replace("'","\\'",$str));
-}}
+if(! function_exists('dbesc')) {
+       function dbesc($str) {
+               global $db;
+               if($db && $db->connected)
+                       return($db->escape($str));
+               else
+                       return(str_replace("'","\\'",$str));
+       }
+}
 
 
 
@@ -199,28 +283,31 @@ function dbesc($str) {
 // Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
 //                   'user', 1);
 
-if(! function_exists('q')) { 
-function q($sql) {
+if(! function_exists('q')) {
+       function q($sql) {
 
-       global $db;
-       $args = func_get_args();
-       unset($args[0]);
+               global $db;
+               $args = func_get_args();
+               unset($args[0]);
 
-       if($db && $db->connected) {
-               $ret = $db->q(vsprintf($sql,$args));
-               return $ret;
-       }
+               if($db && $db->connected) {
+                       $stmt = vsprintf($sql,$args);
+                       if($stmt === false)
+                               logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true));
+                       return $db->q($stmt);
+               }
 
-       /**
-        *
-        * This will happen occasionally trying to store the 
-        * session data after abnormal program termination 
-        *
-        */
-       logger('dba: no database: ' . print_r($args,true));
-       return false; 
+               /**
+                *
+                * This will happen occasionally trying to store the
+                * session data after abnormal program termination
+                *
+                */
+               logger('dba: no database: ' . print_r($args,true));
+               return false;
 
-}}
+       }
+}
 
 /**
  *
@@ -228,36 +315,39 @@ function q($sql) {
  *
  */
 
-if(! function_exists('dbq')) { 
-function dbq($sql) {
+if(! function_exists('dbq')) {
+       function dbq($sql) {
 
-       global $db;
-       if($db && $db->connected)
-               $ret = $db->q($sql);
-       else
-               $ret = false;
-       return $ret;
-}}
+               global $db;
+               if($db && $db->connected)
+                       $ret = $db->q($sql);
+               else
+                       $ret = false;
+               return $ret;
+       }
+}
 
 
-// Caller is responsible for ensuring that any integer arguments to 
+// Caller is responsible for ensuring that any integer arguments to
 // dbesc_array are actually integers and not malformed strings containing
-// SQL injection vectors. All integer array elements should be specifically 
-// cast to int to avoid trouble. 
+// SQL injection vectors. All integer array elements should be specifically
+// cast to int to avoid trouble.
 
 
 if(! function_exists('dbesc_array_cb')) {
-function dbesc_array_cb(&$item, $key) {
-       if(is_string($item))
-               $item = dbesc($item);
-}}
+       function dbesc_array_cb(&$item, $key) {
+               if(is_string($item))
+                       $item = dbesc($item);
+       }
+}
 
 
 if(! function_exists('dbesc_array')) {
-function dbesc_array(&$arr) {
-       if(is_array($arr) && count($arr)) {
-               array_walk($arr,'dbesc_array_cb');
+       function dbesc_array(&$arr) {
+               if(is_array($arr) && count($arr)) {
+                       array_walk($arr,'dbesc_array_cb');
+               }
        }
-}}             
+}