<?php
/**
 * Класс модели данных
 *
 * @copyright 
 * @link 
 * @package Majestic
 * @subpackage DB
 * @since 
 * @version SVN: $Id$
 * @filesource $URL$
 */
abstract class Model
{
    private $handler;

    protected $table = false;
    protected $primary_key = 'id';

    function __construct()
    {
        $this->handler = DBConnector::getConnect(Env::getParam('db_settings'));
    }

    /**
    * Выполняет запрос и возвращает сырой результат
    *
    * @param string $sql
    * @return resource
    */
    function exec($sql)
    {
        $time = microtime(true);
        $res = mysqli_query($this->handler, $sql);
        if (mysqli_errno($this->handler)) {
            throw new MJException("<b>Query Error:</b>\n".$sql."\n<b>Error:</b>\n".mysqli_error($this->handler), 1);
        }

        if (DEBUG_ENABLE) {
            DBConnector::$queries[] = $sql.'; ('.round((microtime(true)-$time)*1000, 1).'ms)';
        }

        return $res;
    }

    /**
    * Выполняет запрос и возвращает объект результата
    *
    * @param string $sql
    * @return object
    */
    function query($sql)
    {
        $res = $this->exec($sql);

        switch (strtolower(substr($sql, 0, 6))) {
            case 'select':
                return new ModelSelectResult($res);
            case 'insert':
                return new ModelInsertResult($this->handler);
            default:
                return new ModelChangeResult($this->handler);
        }
    }

    /**
    * Экранирует строку
    *
    * @param string $data - строка для экранирования
    * @return string
    */
    function escape($data)
    {
        return mysqli_real_escape_string($this->handler, $data);
    }

//////////////////////////
    function update($id, $data)
    {
        $sql = '';
        foreach ($data as $key => $val) {
            $sql .= $key."='".$this->escape($val)."', ";
        }
        return $this->query('UPDATE '.$this->table.' SET '.rtrim($sql, ', ').' WHERE '.$this->primary_key.'='.(int) $id);
    }

    function insert($data, $postfix = '')
    {
        $sql = '';
        foreach ($data as $key => $val) {
            $sql .= $key.'="'.$this->escape($val).'", ';
        }
        return $this->query('INSERT '.$this->table.' SET '.rtrim($sql, ', ').' '.$postfix);
    }

    function delete($id)
    {
        return $this->query('DELETE FROM '.$this->table.' WHERE '.$this->primary_key.'='.(int) $id);
    }

    function get($id)
    {
        return $this->query('SELECT * FROM '.$this->table.' WHERE '.$this->primary_key.'='.(int) $id);
    }

    function getList($limit = false, $sort = 'ASC')
    {
        return $this->query('SELECT * FROM '.$this->table.' ORDER BY '.$this->primary_key.' '.($sort == 'ASC' ? 'ASC' : 'DESC').($limit === false ? ' LIMIT '.(int) $limit : ''));
    }
}

class ModelResult
{
    function __call($name, $args)
    {
        throw new MJException('Call undeclared method "'.$name.'" in "'.get_class($this).'" class', -1);
    }
}

class ModelSelectResult extends ModelResult
{
    public $result;

    function __construct($res)
    {
        $this->result  = $res;
    }

    function fetch()
    {
        return mysqli_fetch_object($this->result);
    }

    function fetchField($field, $default = false)
    {
        $row = $this->fetch();
        return isset($row->$field) ? $row->$field : $default;
    }

    function fetchAll($key = false)
    {
        $array = array();
        if ($key) {
            while ($row = mysqli_fetch_object($this->result)) {
                $array[$row->$key] = $row;
            }
        } else {
            while ($row = mysqli_fetch_object($this->result)) {
                $array[] = $row;
            }
        }
        return $array;
    }

    function count()
    {
        return mysqli_num_rows($this->result);
    }

    function free()
    {
        mysqli_free_result($this->result);
    }

    function __destruct() {
        $this->free();
    }
}

class ModelChangeResult extends ModelResult
{
    public $affected;

    function __construct($resource)
    {
        $this->affected = mysqli_affected_rows($resource);
    }

    function count()
    {
        return $this->affected;
    }
}

class ModelInsertResult extends ModelResult
{
    public $id;

    function __construct($resource)
    {
        $this->id = mysqli_insert_id($resource);
    }

    function getId()
    {
        return $this->id;
    }
}
?>