<?php

/**
 * examples:
 * 
 * $rows = $db->queryFetchAll('select ..');
 * 
 */

class Database {
    
    public 
$pdo;
    private 
$transactionRunning false;
    public 
$lastSql;
    
    public function 
init($dbHost$dbUSer$dbPw$dbName) {
        try {
            
#$dsn = 'mysql:host='.$dbHost.';dbname='.$dbName;
            
$dsn 'mysql:host='.$dbHost.';dbname='.$dbName.';charset=utf8';
            
# (prior to PHP 5.3.6 would need: $dbh->exec("set names utf8"); instead)

            
$this->pdo = new PDO($dsn$dbUSer$dbPw);
            
$this->pdo->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
        } catch (
PDOException $e) {
            
$bt debug_backtrace(); $backtraceFlat '['.__CLASS__.'::'.__FUNCTION__.' / line '.__LINE__.' ] [caller: '.$bt[0]['file'].' / line '.$bt[0]['line'].']';
            
Errors::log('database connection failed: '.$e->getMessage().' '.$backtraceFlat);
        }

        
# NO_ZERO_DATE became default with mysql 5.6 (strict).
        # remove NO_ZERO_DATE from sql_mode to allow date values of 0000-00-00, for example when
        # creating a customer without / with empty customerAddress maintenanceDate (converted to
        # 0000-00-00 in customerAddressModel). Otherwise customer creation fails with an error
        # message.
        
$rows $this->queryFetchAll("SELECT @@sql_mode as sql_mode;");
        
$sql_mode $rows[0]->sql_mode;
        
$sql_mode str_replace("NO_ZERO_DATE"""$sql_mode);
        
$this->query("SET SESSION sql_mode = " $this->quote($sql_mode) . ";");
    }
    
    public function 
quote($val) {
        return 
$this->pdo->quote($val);
    }
    
    public function 
quoteArray($array) {
        foreach (
$array as &$elem) {
            
$elem $this->pdo->quote($elem);
        }
        unset(
$elem);
        return 
$array;
    }
    
    
/**
     * @param string $sql the sql statement
     * @param bool $catchExceptions default is true. set to false to handle exception yourself
     * @return PDOStatement
     */
    
public function query($sql$catchExceptions=true) {
        global 
$db;
        
$this->lastSql $sql;
        if (!
$catchExceptions) {
            return 
$this->pdo->query($sql);
        } else {
            try {
                return 
$this->pdo->query($sql);
            } catch (
PDOException $e) {
                
$bt debug_backtrace(); $backtraceFlat '['.__CLASS__.'::'.__FUNCTION__.' / line '.__LINE__.' ] [caller: '.$bt[0]['file'].' / line '.$bt[0]['line'].']';
                
Errors::log('sql query failed: '.$e->getMessage().' '.$backtraceFlat);
                if (
DEBUG_SQL) { Errors::log('sql: '.$db->lastSql.' '); }
            }
        }
    }
    
    
/** always returns array (empty if no results). on error returns empty array and throws exception. 
     */
    
public function queryFetchAll($sql) {
        global 
$db;
        
$rows = array();
        
        
$result null;
        try {
            
$result $this->pdo->query($sql);
        } catch (
PDOException $e) {
            
$bt debug_backtrace(); $backtraceFlat '['.__CLASS__.'::'.__FUNCTION__.' / line '.__LINE__.' ] [caller: '.$bt[0]['file'].' / line '.$bt[0]['line'].']';
            
Errors::log('sql query failed: '.$e->getMessage().' '.$backtraceFlat);
            if (
DEBUG_SQL) { Errors::log('sql: '.$db->lastSql.' '); }
        }
        
        if (
$result) {
            if (
$result->rowCount()>0) {
                
$rows $result->fetchAll(PDO::FETCH_OBJ);
            }
            
$result->closeCursor();
        }
        
        return 
$rows;
    }
    
    public function 
lastInsertId() {
        return 
$this->pdo->lastInsertId();
    }
    
    
    
    public function 
isTransactionRunning() {
        return 
$this->transactionRunning;
    }
    
    public function 
beginTransaction() {
        
$this->transactionRunning true;
        return 
$this->pdo->beginTransaction();
    }
    
    public function 
commit() {
        
$this->transactionRunning false;
        return 
$this->pdo->commit();
    }
    
    public function 
rollBack() {
        
$this->transactionRunning false;
        return 
$this->pdo->rollBack();
    }
    
}