Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
72.22% covered (success)
72.22%
13 / 18
CRAP
83.33% covered (success)
83.33%
115 / 138
Db
0.00% covered (danger)
0.00%
0 / 1
72.22% covered (success)
72.22%
13 / 18
107.89
83.33% covered (success)
83.33%
115 / 138
 connect
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 mysqlConnect
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 pdoConnect
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 pgsqlConnect
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 sqlsrvConnect
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 sqliteConnect
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 check
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
11 / 11
 install
0.00% covered (danger)
0.00%
0 / 1
26.27
77.14% covered (success)
77.14%
27 / 35
 getAvailableAdapters
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
9 / 9
 isAvailable
100.00% covered (success)
100.00%
1 / 1
9
100.00% covered (success)
100.00%
24 / 24
 hasDb
0.00% covered (danger)
0.00%
0 / 1
38.87
42.86% covered (warning)
42.86%
6 / 14
 setDb
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
10 / 10
 addClassToTable
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 hasClassToTable
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setDefaultDb
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getDb
0.00% covered (danger)
0.00%
0 / 1
19.10
73.68% covered (success)
73.68%
14 / 19
 db
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getAll
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
<?php
/**
 * Pop PHP Framework (http://www.popphp.org/)
 *
 * @link       https://github.com/popphp/popphp-framework
 * @author     Nick Sagona, III <dev@nolainteractive.com>
 * @copyright  Copyright (c) 2009-2018 NOLA Interactive, LLC. (http://www.nolainteractive.com)
 * @license    http://www.popphp.org/license     New BSD License
 */
/**
 * @namespace
 */
namespace Pop\Db;
/**
 * Db class
 *
 * @category   Pop
 * @package    Pop\Db
 * @author     Nick Sagona, III <dev@nolainteractive.com>
 * @copyright  Copyright (c) 2009-2018 NOLA Interactive, LLC. (http://www.nolainteractive.com)
 * @license    http://www.popphp.org/license     New BSD License
 * @version    4.3.0
 */
class Db
{
    /**
     * Database connection(s)
     * @var array
     */
    protected static $db = ['default' => null];
    /**
     * Database connection class to table relationship
     * @var array
     */
    protected static $classToTable = [];
    /**
     * Method to connect to a database and return the database adapter object
     *
     * @param  string $adapter
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return Adapter\AbstractAdapter
     */
    public static function connect($adapter, array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        $class = $prefix . ucfirst(strtolower($adapter));
        if (!class_exists($class)) {
            throw new Exception('Error: The database adapter ' . $class . ' does not exist.');
        }
        return new $class($options);
    }
    /**
     * Method to connect to a MySQL database and return the MySQL database adapter object
     *
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return Adapter\Mysql
     */
    public static function mysqlConnect(array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        return self::connect('mysql', $options, $prefix);
    }
    /**
     * Method to connect to a PDO database and return the PDO database adapter object
     *
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return Adapter\Pdo
     */
    public static function pdoConnect(array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        return self::connect('pdo', $options, $prefix);
    }
    /**
     * Method to connect to a PostgreSQL database and return the PostgreSQL database adapter object
     *
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return Adapter\Pgsql
     */
    public static function pgsqlConnect(array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        return self::connect('pgsql', $options, $prefix);
    }
    /**
     * Method to connect to a SQL Server database and return the SQL Server database adapter object
     *
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return Adapter\Sqlsrv
     */
    public static function sqlsrvConnect(array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        return self::connect('sqlsrv', $options, $prefix);
    }
    /**
     * Method to connect to a SQLite database and return the SQLite database adapter object
     *
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return Adapter\Sqlite
     */
    public static function sqliteConnect(array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        return self::connect('sqlite', $options, $prefix);
    }
    /**
     * Check the database connection
     *
     * @param  string $adapter
     * @param  array  $options
     * @param  string $prefix
     * @return mixed
     */
    public static function check($adapter, array $options, $prefix = '\Pop\Db\Adapter\\')
    {
        $result = null;
        $class  = $prefix . ucfirst(strtolower($adapter));
        $error  = ini_get('error_reporting');
        error_reporting(E_ERROR);
        try {
            if (!class_exists($class)) {
                $result = 'Error: The database adapter ' . $class . ' does not exist.';
            } else {
                $db = new $class($options);
            }
        } catch (\Exception $e) {
            $result = $e->getMessage();
        }
        error_reporting($error);
        return $result;
    }
    /**
     * Install a database schema
     *
     * @param  string $sql
     * @param  mixed $adapter
     * @param  array  $options
     * @param  string $prefix
     * @throws Exception
     * @return void
     */
    public static function install($sql, $adapter, array $options = [], $prefix = '\Pop\Db\Adapter\\')
    {
        if (is_string($adapter)) {
            $adapter = ucfirst(strtolower($adapter));
            $class   = $prefix . $adapter;
            if (!class_exists($class)) {
                throw new Exception('Error: The database adapter ' . $class . ' does not exist.');
            }
            // If Sqlite
            if (($adapter == 'Sqlite') || (($adapter == 'Pdo') && isset($options['type'])) && (strtolower($options['type']) == 'sqlite')) {
                if (!file_exists($options['database'])) {
                    touch($options['database']);
                    chmod($options['database'], 0777);
                }
                if (!file_exists($options['database'])) {
                    throw new Exception('Error: Could not create the database file.');
                }
            }
            $db = new $class($options);
        } else {
            $db = $adapter;
        }
        $lines = (file_exists($sql)) ? file($sql) : explode("\n", $sql);
        // Remove comments, execute queries
        if (count($lines) > 0) {
            $insideComment = false;
            foreach ($lines as $i => $line) {
                if ($insideComment) {
                    if (substr($line, 0, 2) == '*/') {
                        $insideComment = false;
                    }
                    unset($lines[$i]);
                } else {
                    if ((substr($line, 0, 1) == '-') || (substr($line, 0, 1) == '#')) {
                        unset($lines[$i]);
                    } else if (substr($line, 0, 2) == '/*') {
                        $insideComment = true;
                        unset($lines[$i]);
                    }
                }
            }
            $sqlString  = trim(implode('', $lines));
            $newLine    = (strpos($sqlString, ";\r\n") !== false) ? ";\r\n" : ";\n";
            $statements = explode($newLine, $sqlString);
            foreach ($statements as $statement) {
                if (!empty($statement)) {
                    if (isset($options['prefix'])) {
                        $statement = str_replace('[{prefix}]', $options['prefix'], trim($statement));
                    }
                    $db->query($statement);
                }
            }
        }
    }
    /**
     * Get the available database adapters
     *
     * @return array
     */
    public static function getAvailableAdapters()
    {
        $pdoDrivers = (class_exists('Pdo', false)) ? \PDO::getAvailableDrivers() : [];
        return [
            'mysqli' => (class_exists('mysqli', false)),
            'pdo'    => [
                'mysql'  => (in_array('mysql', $pdoDrivers)),
                'pgsql'  => (in_array('pgsql', $pdoDrivers)),
                'sqlite' => (in_array('sqlite', $pdoDrivers)),
                'sqlsrv' => (in_array('sqlsrv', $pdoDrivers))
            ],
            'pgsql'  => (function_exists('pg_connect')),
            'sqlite' => (class_exists('Sqlite3', false)),
            'sqlsrv' => (function_exists('sqlsrv_connect'))
        ];
    }
    /**
     * Determine if a database adapter is available
     *
     * @param  string $adapter
     * @return boolean
     */
    public static function isAvailable($adapter)
    {
        $adapter = strtolower($adapter);
        $result  = false;
        $type    = null;
        $pdoDrivers = (class_exists('Pdo', false)) ? \PDO::getAvailableDrivers() : [];
        if (strpos($adapter, 'pdo_') !== false) {
            $type    = substr($adapter, 4);
            $adapter = 'pdo';
        }
        switch ($adapter) {
            case 'mysql':
            case 'mysqli':
                $result = (class_exists('mysqli', false));
                break;
            case 'pdo':
                $result = (in_array($type, $pdoDrivers));
                break;
            case 'pgsql':
                $result = (function_exists('pg_connect'));
                break;
            case 'sqlite':
                $result = (class_exists('Sqlite3', false));
                break;
            case 'sqlsrv':
                $result = (function_exists('sqlsrv_connect'));
                break;
        }
        return $result;
    }
    /**
     * Check for a DB adapter
     *
     * @param  string $class
     * @return boolean
     */
    public static function hasDb($class = null)
    {
        $result = false;
        if ((null !== $class) && isset(self::$db[$class])) {
            $result = true;
        } else if (null !== $class) {
            foreach (self::$db as $prefix => $adapter) {
                if (substr($class, 0, strlen($prefix)) == $prefix) {
                    $result = true;
                }
            }
        }
        if ((!$result) && (null !== $class) && in_array($class, self::$classToTable)) {
            $class = array_search($class, self::$classToTable);
            if (isset(self::$db[$class])) {
                $result = true;
            }
        }
        if ((!$result) && isset(self::$db['default'])) {
            $result = true;
        }
        return $result;
    }
    /**
     * Set DB adapter
     *
     * @param  Adapter\AbstractAdapter $db
     * @param  string                  $class
     * @param  string                  $prefix
     * @param  boolean                 $isDefault
     * @return void
     */
    public static function setDb(Adapter\AbstractAdapter $db, $class = null, $prefix = null, $isDefault = false)
    {
        if (null !== $prefix) {
            self::$db[$prefix] = $db;
        }
        if (null !== $class) {
            self::$db[$class] = $db;
            $record = new $class();
            if ($record instanceof Record) {
                self::$classToTable[$class] = $record->getFullTable();
            }
        }
        if ($isDefault) {
            self::$db['default'] = $db;
        }
    }
    /**
     * Add class-to-table relationship
     *
     * @param  string $class
     * @param  string $table
     * @return void
     */
    public static function addClassToTable($class, $table)
    {
        self::$classToTable[$class] = $table;
    }
    /**
     * Check if class-to-table relationship exists
     *
     * @param  string $class
     * @return boolean
     */
    public static function hasClassToTable($class)
    {
        return isset(self::$classToTable[$class]);
    }
    /**
     * Set DB adapter
     *
     * @param  Adapter\AbstractAdapter $db
     * @param  string                  $class
     * @param  string                  $prefix
     * @return void
     */
    public static function setDefaultDb(Adapter\AbstractAdapter $db, $class = null, $prefix = null)
    {
        self::setDb($db, $class, $prefix, true);
    }
    /**
     * Get DB adapter
     *
     * @param  string $class
     * @throws Exception
     * @return Adapter\AbstractAdapter
     */
    public static function getDb($class = null)
    {
        $dbAdapter = null;
        // Check for database adapter assigned to a full class name
        if ((null !== $class) && isset(self::$db[$class])) {
            $dbAdapter = self::$db[$class];
        // Check for database adapter assigned to a namespace
        } else if (null !== $class) {
            foreach (self::$db as $prefix => $adapter) {
                if (substr($class, 0, strlen($prefix)) == $prefix) {
                    $dbAdapter = $adapter;
                }
            }
        }
        // Check if class is actual table name
        if ((null === $dbAdapter) && (null !== $class) && in_array($class, self::$classToTable)) {
            $class = array_search($class, self::$classToTable);
            // Direct match
            if (isset(self::$db[$class])) {
                $dbAdapter = self::$db[$class];
            // Check prefixes
            } else {
                foreach (self::$db as $prefix => $adapter) {
                    if (substr($class, 0, strlen($prefix)) == $prefix) {
                        $dbAdapter = $adapter;
                    }
                }
            }
        }
        if ((null === $dbAdapter) && isset(self::$db['default'])) {
            $dbAdapter = self::$db['default'];
        }
        if (null === $dbAdapter) {
            throw new Exception('No database adapter was found.');
        }
        return $dbAdapter;
    }
    /**
     * Get DB adapter (alias)
     *
     * @param  string $class
     * @return Adapter\AbstractAdapter
     */
    public static function db($class = null)
    {
        return self::getDb($class);
    }
    /**
     * Get all DB adapters
     *
     * @return array
     */
    public static function getAll()
    {
        return self::$db;
    }
}