#!/usr/local/bin/php-7.3
<?php

define('INSTALL_PATH', getcwd() . '/' );

require_once INSTALL_PATH . 'program/include/clisetup.php';

// get arguments
$opts = rcube_utils::get_opt(array(
    'd' => 'dir',
    'p' => 'package',
));

if (empty($opts['dir'])) {
    rcube::raise_error("Database schema directory not specified (--dir).", false, true);
}
if (empty($opts['package'])) {
    rcube::raise_error("Database schema package name not specified (--package).", false, true);
}

// Check if directory exists
if (!file_exists($opts['dir'])) {
    rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}

$RC = rcube::get_instance();
$DB = rcube_db::factory($RC->config->get('db_dsnw'));

// Connect to database
$DB->db_connect('w');
if (!$DB->is_connected()) {
    rcube::raise_error("Error connecting to database: " . $DB->is_error(), false, true);
}

$opts['dir'] = rtrim($opts['dir'], DIRECTORY_SEPARATOR);
$file = $opts['dir'] . DIRECTORY_SEPARATOR . $DB->db_provider . '.initial.sql';
if (!file_exists($file)) {
    rcube::raise_error("No DDL file found for " . $DB->db_provider . " driver.", false, true);
}

$package = $opts['package'];
$error = false;

// read DDL file
if ($lines = file($file)) {
    $sql = '';
    foreach ($lines as $line) {
        if (preg_match('/^--/', $line) || trim($line) == '')
            continue;

        $sql .= $line . "\n";
        if (preg_match('/(;|^GO)$/', trim($line))) {
            @$DB->query(fix_table_names($sql));
            $sql = '';
            if ($error = $DB->is_error()) {
                break;
            }
        }
    }
}

if (!$error) {
    $version = date('Ymd00');
    $system_table = $DB->quote_identifier($DB->table_name('system'));
    $name_col = $DB->quote_identifier('name');
    $value_col = $DB->quote_identifier('value');
    $package_version = $package . '-version';

    $DB->query("SELECT * FROM $system_table WHERE $name_col=?",
        $package_version);

    if ($DB->fetch_assoc()) {
        $DB->query("UPDATE $system_table SET $value_col=? WHERE $name_col=?",
            $version, $package_version);
    }
    else {
        $DB->query("INSERT INTO $system_table ($name_col, $value_col) VALUES (?, ?)",
            $package_version, $version);
    }

    $error = $DB->is_error();
}

if ($error) {
    echo "[FAILED]\n";
    rcube::raise_error("Error in DDL schema $file: $error", false, true);
}
echo "[OK]\n";


function fix_table_names($sql)
{
    global $DB, $RC;

    $prefix = $RC->config->get('db_prefix');
    $engine = $DB->db_provider;

    if (empty($prefix)) {
        return $sql;
    }

    $tables    = array();
    $sequences = array();

    // find table names
    if (preg_match_all('/CREATE TABLE (\[dbo\]\.|IF NOT EXISTS )?[`"\[\]]*([^`"\[\] \r\n]+)/i', $sql, $matches)) {
        foreach ($matches[2] as $table) {
            $tables[$table] = $prefix . $table;
        }
    }
    // find sequence names
    if ($engine == 'postgres' && preg_match_all('/CREATE SEQUENCE (IF NOT EXISTS )?"?([^" \n\r]+)/i', $sql, $matches)) {
        foreach ($matches[2] as $sequence) {
            $sequences[$sequence] = $prefix . $sequence;
        }
    }

    // replace table names
    foreach ($tables as $table => $real_table) {
        $sql = preg_replace("/([^a-zA-Z0-9_])$table([^a-zA-Z0-9_])/", "\\1$real_table\\2", $sql);
    }
    // replace sequence names
    foreach ($sequences as $sequence => $real_sequence) {
        $sql = preg_replace("/([^a-zA-Z0-9_])$sequence([^a-zA-Z0-9_])/", "\\1$real_sequence\\2", $sql);
    }

    return $sql;
}

?>
