<?php
/** Database driver; Techbase Solutions xCRUD v.1.7.28; 01/2025 */
class Xcrud_db
{
    private static $_instance = array();
    private $connect;
    public $result;
    private $dbhost;
    private $dbuser;
    private $dbpass;
    private $dbname;
    private $dbencoding;
    private $magic_quotes;

    public static function get_instance($params = false)
    {
        if (is_array($params))
        {
            list($dbuser, $dbpass, $dbname, $dbhost, $dbencoding) = $params;
            $instance_name = sha1($dbuser . $dbpass . $dbname . $dbhost . $dbencoding);
        }
        else
        {
            $instance_name = 'db_instance_default';
        }
        if (!isset(self::$_instance[$instance_name]) or null === self::$_instance[$instance_name])
        {
            if (!is_array($params))
            {
                $dbuser = Xcrud_config::$dbuser;
                $dbpass = Xcrud_config::$dbpass;
                $dbname = Xcrud_config::$dbname;
                $dbhost = Xcrud_config::$dbhost;
                $dbencoding = Xcrud_config::$dbencoding;
            }
            self::$_instance[$instance_name] = new self($dbuser, $dbpass, $dbname, $dbhost, $dbencoding);
        }
        return self::$_instance[$instance_name];
    }

    private function __construct($dbuser, $dbpass, $dbname, $dbhost, $dbencoding)
    {
        $dsn = "pgsql:host=$dbhost;dbname=$dbname";
        if ($dbencoding)
        {
            $dsn .= ";options='--client_encoding=$dbencoding'";
        }

        try {
            // Use PDO to connect to the PostgreSQL database
            $this->connect = new PDO($dsn, $dbuser, $dbpass);
            // Set the error mode to exceptions
            $this->connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            $this->error('Connection error: ' . $e->getMessage());
        }
    }

    public function query($query = '')
    {
        try {
            $this->result = $this->connect->query($query);
            return $this->result->rowCount();
        } catch (PDOException $e) {
            $this->error('Query error: ' . $e->getMessage() . '<pre>' . $query . '</pre>');
        }
    }

    public function insert_id()
    {
        return $this->connect->lastInsertId();
    }

    public function result()
    {
        $out = array();
        if ($this->result)
        {
            while ($row = $this->result->fetch(PDO::FETCH_ASSOC))
            {
                $out[] = $row;
            }
        }
        return $out;
    }

    public function row()
    {
        return $this->result->fetch(PDO::FETCH_ASSOC);
    }

    public function escape($val, $not_qu = false, $type = false, $null = false, $bit = false)
    {
        // PDO automatically escapes inputs when using prepared statements,
        // but here we still sanitize the values before using them in SQL
        if ($type)
        {
            switch ($type)
            {
                case 'bool':
                    return $val ? 'TRUE' : ($null ? 'NULL' : 'FALSE');
                    break;
                case 'int':
                    $val = preg_replace('/[^0-9\-]/', '', $val);
                    if ($val === '')
                    {
                        return $null ? 'NULL' : 0;
                    }
                    return $val;
                    break;
                case 'float':
                    if ($val === '')
                    {
                        return $null ? 'NULL' : 0;
                    }
                    return $val;  // PDO handles float escaping automatically
                    break;
                default:
                    if (trim($val) == '')
                    {
                        return $null ? 'NULL' : '\'\'';
                    }
                    return $val;  // PDO handles string escaping automatically
            }
        }

        if (is_array($val)){
            if ($not_qu)
                return $val;
            return $val;
        }

        if ($not_qu)
            return $val;  // In prepared statements, PDO escapes automatically
        return '\'' . $val . '\'';
    }

    public function escape_like($val, $pattern = array('%', '%'))
    {
        if (is_int($val))
            return '\'' . $pattern[0] . (int)$val . $pattern[1] . '\'';
        if ($val == '')
        {
            return '\'\'';
        }
        else
        {
            return '\'' . $pattern[0] . $val . $pattern[1] . '\'';
        }
    }

    private function error($text = 'Error!')
    {
        exit('<div class="xcrud-error" style="position:relative;line-height:1.25;padding:15px;color:#BA0303;margin:10px;border:1px solid #BA0303;border-radius:4px;font-family:Arial,sans-serif;background:#FFB5B5;box-shadow:inset 0 0 80px #E58989;">
            <span style="position:absolute;font-size:10px;bottom:3px;right:5px;">xCRUD</span>' . $text . '</div>');
    }
}
