<?php
/**************************************************************************
* This file is part of the WebIssues Server program
* Copyright (C) 2006 Michał Męciński
* Copyright (C) 2007-2009 WebIssues Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
**************************************************************************/

function wi_db_connect( $host, $database, $user, $password )
{
    global $db_link;

    $port = '';
    $socket = '';

    $parts = explode( ':', $host );
    if ( isset( $parts[ 1 ] ) ) {
        $host = $parts[ 0 ];
        if ( is_numeric( $parts[ 1 ] ) )
            $port = $parts[ 1 ];
        else
            $socket = $parts[ 1 ];
    }

    if ( $host == '' )
        $host = 'localhost';

    if ( $socket != '' )
        $db_link = mysqli_connect( $host, $user, $password, $database, null, $socket );
    else if ( $port != '' )
        $db_link = mysqli_connect( $host, $user, $password, $database, $port );
    else
        $db_link = mysqli_connect( $host, $user, $password, $database );

    if ( !$db_link )
        return false;

    $db_link->query( "SET NAMES 'utf8'" );

    return true;
}

function wi_db_escape_arg( $arg, $type, &$params )
{
    global $db_link;

    switch( $type ) {
        case 'd':
            return (int)$arg;
        case 's':
        case 'b':
            if ( strlen( $arg ) > 6000 ) {
                $params[] = $arg;
                return '?';
            }
            return "'" . $db_link->real_escape_string( $arg ) . "'";
    }
}

function wi_db_query( $query, $params )
{
    global $db_link;

    $log = wi_log_open( 'sql' );
    if ( $log )
        fwrite( $log, "> $query\n" );

    if ( empty( $params ) ) {
        $rs = $db_link->query( $query );

        if ( !$rs ) {
            $error = $db_link->error;
            trigger_error( 'mysqli::query(): ' . $error, E_USER_WARNING );
            if ( $log )
                fwrite( $log, "ERROR: $error\n" );
            return false;
        }

        if ( $rs !== true )
            $result = new WI_DB_Result( $rs );
        else
            $result = true;
    } else {
        $stmt = $db_link->prepare( $query );
        if ( !$stmt ) {
            $error = $db_link->error;
            trigger_error( 'mysqli::prepare(): ' . $error, E_USER_WARNING );
            if ( $log )
                fwrite( $log, "ERROR: $error\n" );
            return false;
        }

        $types = str_repeat( 's', count( $params ) );
        $args = array_merge( array( $stmt, $types ), $params );

        call_user_func_array( 'mysqli_stmt_bind_param', $args );

        if ( !$stmt->execute() ) {
            $error = $stmt->error;
            trigger_error( 'mysqli_stmt::execute(): ' . $error, E_USER_WARNING );
            if ( $log )
                fwrite( $log, "ERROR: $error\n" );
            return false;
        }

        $fields = $stmt->result_metadata();
        if ( $fields )
            $result = new WI_DB_Statement( $stmt, $fields );
        else
            $result = true;
    }

    if ( $log ) {
        if ( $result === true ) {
            $num = $db_link->affected_rows;
            fwrite( $log, "($num rows affected)\n" );
        } else {
            $num = $result->num_rows();
            fwrite( $log, "($num rows returned)\n" );
        }
    }

    return $result;
}

function wi_db_fetch_assoc( $rs )
{
    return $rs->fetch_assoc();
}

function wi_db_unescape_blob( $data )
{
    return $data;
}

function wi_db_insert_id( $table, $column )
{
    global $db_link;

    return $db_link->insert_id;
}

function wi_db_table_exists( $table )
{
    global $db_link;

    $query = "SHOW TABLES LIKE '$table'";
    $rs = $db_link->query( $query );
    return $rs->num_rows > 0;
}

class WI_DB_Result
{
    var $rs;

    function WI_DB_Result( $rs )
    {
        $this->rs = $rs;
    }

    function fetch_assoc()
    {
        if ( $row = $this->rs->fetch_assoc() )
            return $row;

        $this->rs->free_result();
        return NULL;
    }

    function num_rows()
    {
        return $this->rs->num_rows;
    }
}

class WI_DB_Statement
{
    var $stmt;
    var $result;

    function WI_DB_Statement( $stmt, $fields )
    {
        $this->stmt = $stmt;
        $this->result = array();

        $stmt->store_result();

        $args = array( $stmt );
        while( $field = $fields->fetch_field() )
            $args[] =& $this->result[ $field->name ];

        call_user_func_array( 'mysqli_stmt_bind_result', $args );

        $fields->free();
    }

    function fetch_assoc()
    {
        if ( $this->stmt->fetch() )
            return $this->result;

        $this->stmt->free_result();
        return NULL;
    }

    function num_rows()
    {
        return $this->stmt->num_rows;
    }
}
