<?php
/*
* This is a modified PDO class which serves the user back-end database.
* This allows us to use a highly optimized PostGresql for packet capture and
* a more transactional database for backend/account management.
*/

class PDOMysqlConnection
{

    private static $_singletonInstance = null;
    private $_db;
    private $_config;

    public function __construct()
    {
        $this->_config = getBootstrapConfig();
    }

    /**
     * Connect to the database.
     */
    private function createConnection()
    {
        if (isset($this->_config) && is_array($this->_config)) {
            $persistent =
              (isset($this->_config['use_persistent_db_connections'])
                && $this->_config['use_persistent_db_connections'] == '1' ? true : false);

            if (!isset($this->_config['username'])) {
                $this->_config['username'] = get_current_user();
            }

            try {
                $this->_db = new PDO(
                    sprintf(
                        'mysql:dbname=%s;host=%s;port=%s;user=%s;password=%s',
                        $this->_config['database'],
                        $this->_config['host'],
                        $this->_config['port'],
                        $this->_config['username'],
                        $this->_config['password']
                    ), null, null,
                    array(
                        PDO::ATTR_PERSISTENT => $persistent,
                        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
                    )
                );
            } catch (PDOException $e) {
                echo $e;
                throw new Exception("Failed to connect to backend database.");
            }
        } else {
            throw new Exception("Failed to parse database ini file.");
        }
    }

    /**
     * Returnes a PDO db connection
     *
     * @return PDO
     */
    private function getConnection()
    {
        if($this->_db === null) {
            $this->createConnection();
        }

        return $this->_db;
    }

    /**
     * Executes an SQL statement, returning a result set as a PDOStatement object
     *
     * @param  string $sql
     * @return PDOStatement
     */
    public function query($sql)
    {
        return $this->getConnection()->query($sql);
    }

    /**
     * Prepares a statement for execution and returns a statement object
     *
     * @param  string $sql
     * @return PDOStatement
     */
    public function prepare($sql)
    {
        return $this->getConnection()->prepare($sql);
    }

    /**
     * Prepares a statement for execution and execute the prepared statement. Returnes the statment object
     *
     * @param  string $sql
     * @param  array  $arguments
     * @return PDOStatement
     */
    public function prepareAndExec($sql, array $arguments = array())
    {
        $statement = $this->prepare($sql);
        $statement->execute($arguments);
        return $statement;
    }

    /**
     * Initiates a transaction. Turns off autocommit mode. Returns TRUE on success or FALSE on failure.
     *
     * @return boolean
     */
    public function beginTransaction()
    {
        $this->getConnection()->beginTransaction();
    }

    /**
     * Commits a transaction. Returns TRUE on success or FALSE on failure.
     *
     * @return boolean
     */
    public function commit()
    {
        $this->getConnection()->commit();
    }

    /**
     * Rolls back the current transaction (that was started by beginTransaction). Returns TRUE on success or FALSE on failure.
     *
     * @return boolean
     */
    public function rollBack()
    {
        $this->getConnection()->rollBack();
    }

    /**
     * Get the ID of the last inserted record.
     *
     * @return int
     */
    public function lastInsertId()
    {
        return $this->getConnection()->lastInsertId();
    }

    /**
     * Returnes an initiated PDOConnection
     *
     * @return PDOMysqlConnection
     */
    public static function getInstance()
    {
        if (self::$_singletonInstance === null) {
            self::$_singletonInstance = new PDOMysqlConnection();
        }

        return self::$_singletonInstance;
    }
}
