<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Narrow database adapter used by the ported append-only VeriFactu journal.
 * It intentionally exposes only the methods required by this plugin.
 */
final class DdvWpDb
{
    private static $instance;
    public $Insert_ID = 0;

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public static function prefix()
    {
        global $wpdb;
        return (string) $wpdb->prefix;
    }

    public static function table($name)
    {
        $name = (string) $name;
        $prefix = self::prefix();
        return strpos($name, $prefix) === 0 ? $name : $prefix . $name;
    }

    public static function escape($value)
    {
        global $wpdb;
        if (method_exists($wpdb, '_real_escape')) {
            return $wpdb->_real_escape((string) $value);
        }
        return esc_sql((string) $value);
    }

    public static function quoteIdentifier($identifier)
    {
        return preg_replace('/[^A-Za-z0-9_]/', '', (string) $identifier);
    }

    public function Insert_ID()
    {
        global $wpdb;
        return (int) $wpdb->insert_id;
    }

    public function execute($sql)
    {
        global $wpdb;
        return $wpdb->query((string) $sql) !== false;
    }

    public function executeS($sql)
    {
        global $wpdb;
        $rows = $wpdb->get_results((string) $sql, ARRAY_A);
        return is_array($rows) ? $rows : array();
    }

    public function getRow($sql)
    {
        global $wpdb;
        $row = $wpdb->get_row((string) $sql, ARRAY_A);
        return is_array($row) ? $row : false;
    }

    public function getValue($sql)
    {
        global $wpdb;
        return $wpdb->get_var((string) $sql);
    }

    public function insert($table, array $data, ...$ignored)
    {
        global $wpdb;
        unset($ignored);
        $result = $wpdb->insert(self::table($table), $data);
        if ($result === false) {
            return false;
        }
        $this->Insert_ID = (int) $wpdb->insert_id;
        return true;
    }

    public function update($table, array $data, $where = '', ...$ignored)
    {
        global $wpdb;
        unset($ignored);
        $table = self::table($table);
        if (is_array($where)) {
            return $wpdb->update($table, $data, $where) !== false;
        }
        $sets = array();
        foreach ($data as $field => $value) {
            $field = self::quoteIdentifier($field);
            if ($value === null) {
                $sets[] = '`' . $field . '` = NULL';
            } elseif (is_int($value) || is_float($value)) {
                $sets[] = '`' . $field . '` = ' . (0 + $value);
            } else {
                $sets[] = '`' . $field . "` = '" . self::escape((string) $value) . "'";
            }
        }
        if (empty($sets)) {
            return true;
        }
        $sql = 'UPDATE `' . self::quoteIdentifier($table) . '` SET ' . implode(', ', $sets);
        if (trim((string) $where) !== '') {
            $sql .= ' WHERE ' . preg_replace('/^\s*WHERE\s+/i', '', (string) $where);
        }
        return $wpdb->query($sql) !== false;
    }

    public function delete($table, $where = '', ...$ignored)
    {
        global $wpdb;
        unset($ignored);
        $table = self::table($table);
        if (is_array($where)) {
            return $wpdb->delete($table, $where) !== false;
        }
        $sql = 'DELETE FROM `' . self::quoteIdentifier($table) . '`';
        if (trim((string) $where) !== '') {
            $sql .= ' WHERE ' . preg_replace('/^\s*WHERE\s+/i', '', (string) $where);
        }
        return $wpdb->query($sql) !== false;
    }
}
