<?php

namespace Qii\Driver;
use Qii\Autoloader\Psr4;
use Qii\Exceptions\InvalidParams;

/**
 * Class Base
 * @package Qii\Driver
 * 使用方法
 * class base extends \Qii\Driver\Model {
 *      public function __construct()
 *      {
 *          parent::__construct();
 *      }
 *      public function demo()
 *      {
 *           $this->db->fields("*")->join(array("leftJoin", array('table' => 'ad_site', 'alias' => 'b', 'on' => 'a.uid = b.uid')))->where(array('a.create_at:greater' => 1))->limit(10)->groupBy(array('a.uid', 'a.create_at'))->orderBy(array('a.uid' => 'desc'))->selectAll('user a');
 *           $this->db->where(array('uid' => 1))->set(array('create_at:plus' => time(), 'status' => 1))->update('user');
 *           $this->db->updateObject('user', array('create_at:plus' => time(), 'status' => 1), array('uid' => 1));
 *           $this->db->where(array('uid:greater' => 1))->delete('user');
 *           $this->db->deleteObject('user', array('uid' => 1));
 *           $this->db->where(array('uid:greater' => 1))->like("email like '%test@test.com%'")->selectAll('user');
 *           $this->db->where(array('uid:greater' => 1))->where("or")->like(array('email' => 'test@testcom'))->selectAll('user');
 *           $this->db->where(array('uid:greater' => 1, 'or', 'email:like' => 'test@test.com'))->selectAll('user');
 *           $this->db->where(array('uid:greater' => 1))->where("OR")->like(array('email' => 'test@test.com'))->selectAll('user');
 *           $this->db->where(array('name' => 'antsnet'))->exclude(array('email' => 'test@test.com', 'status' => 1))->selectAll('user');
 *           $this->db->where(array('name' => 'antsnet'))->or(array('email' => 'test@test.com', 'status' => 1))->selectAll('user');
 *           $this->db->or(array('email' => 'test@test.com', 'status' => 1))->selectAll('user');
 *           $this->db->join(array("leftJoin", array("table" => 'table', 'alias' => 'a', 'on' => 'a.id=b.id')));
 *           $this->db->join(" LEFT JOIN table c on c.id=a.id")->selectAll('use a');
 *           $this->db->where(array('email:unequal' => 'test@test.com'))->in(array('uid:in' => array('1,2,3'), 'status' => array(1)))->selectAll('user');
 *           $this->db->where(array(array('email:unequal' => 'test@test.com'), array('uid:in' => array('1,2,3'), 'status:in' => array(1))))->selectAll('user');
 *      }
 * }
 */
class Base
{
    const VERSION = '1.3';
    use TraitDatabase;
    use TraitCache;
    //query 方法
    protected $_query = array(
        "INSERT" => "INSERT INTO %s(%s) VALUES('%s')",
        "REPLACE" => "REPLACE %s (%s) VALUES('%s')",
        "SELECT" => "SELECT %s FROM %s %s",
        "UPDATE" => "UPDATE %s SET ",
        "DELETE" => "DELETE FROM %s %s",
        "WHERE" => " WHERE %s",
        "OR" => " `%s` = '%s' ",
        "ORDER" => " ORDER BY %s %s",
        "GROUP" => " GROUP BY %s",
        "LIMIT" => " LIMIT %d, %d"
    );
    //load类
    public $load;
    //cache类
    public $cache;
    //语言包
    public $language;
    //响应内容
    public $response;
    //执行的sql语句
    public $modelSQL = "";

    public $operateVal = array('or', 'and', 'like');//连接条件操作;
    public $operateTable = array('leftJoin', 'rightJoin', 'innerJoin');//链接表的操作
    public $faultTolerant = true;

    public $whereCondition = array();
    public $joinCondition = array();

    public $fields = "*";
    public $sets = array();
    protected $groupBy;
    protected $limit;
    protected $orderBy;

    protected $_modelAlias = array('updateRows' => 'update', 'selectRows' => 'selectAll', 'select' => 'selectRow', 'getOne' => 'selectOne', 'getRow' => 'selectRow', 'getAll' => 'selectAll', 'remove' => 'delete', 'deleteRows' => 'delete');


    public function __construct()
    {
        $this->language = Psr4::getInstance()->loadClass('Qii\Language\Loader');
        $this->load = Psr4::getInstance()->loadClass('\Qii\Autoloader\Loader');
        $this->response = new Response();
    }
    /**
     * 获取所有数据
     *
     * @param $table
     * @param null $where
     * @return mixed
     * @throws \Exception
     */
    public function selectAll($table, $where = null)
    {
        if(is_array($where) && count($where) > 0)
        {
            $this->where($where);
        }
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        return $this->getAll($sql);
    }
    /**
     * 返回resource资源
     * @param string $table 数据表名称
     */
    final function rs($table)
    {
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        return $this->setQuery($sql);
    }
    /**
     * 查询一行
     * @param $table
     * @param null $where
     * @return mixed
     * @throws \Exception
     */
    public function selectRow($table, $where = null)
    {
        if(is_array($where) && count($where) > 0)
        {
            $this->where($where);
        }
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        return $this->getRow($sql);
    }
    /**
     *
     * 查询一列
     * @param String $table
     */
    final function selectOne($table)
    {
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        return $this->getOne($sql);
    }

    /**
     * 插入数据
     * @param $table
     * @param $dataArray
     * @return int
     * @throws \Qii\Exceptions\InvalidFormat
     */
    final function insertObject($table, $dataArray)
    {
        if (empty($table)) {
            throw new InvalidParams(_i('%s is invalid', 'table'), __LINE__);
        }
        $replaceObj = $this->createInsertReplaceObj($dataArray);
        if(empty($replaceObj['fields']) || empty($replaceObj['values']))
        {
            throw new \Qii\Exceptions\Variable(_i('Invalid %s format', 'data'), __LINE__);
        }
        $this->modelSQL = $sql = "INSERT INTO " . $this->getTable($table) . "(`" . join("`, `", $replaceObj['fields']) . "`) VALUES('" . join("', '", $replaceObj['values']) . "')";
        $this->setQuery($sql);
        $this->setError();
        return $this->lastInsertId();
    }
    /**
     *
     * Replace Object
     * @param String $table
     * @param Array|Object $dataArray
     */
    final function replaceObject($table, $dataArray)
    {
        if (empty($table)) {
            throw new InvalidParams(_i('%s is invalid', 'table'), __LINE__);
        }
        $replaceObj = $this->createInsertReplaceObj($dataArray);
        if(empty($replaceObj['fields']) || empty($replaceObj['values']))
        {
            throw new \Qii\Exceptions\Variable(_i('Invalid %s format', 'data'), __LINE__);
        }
        $this->modelSQL = $sql = "REPLACE INTO " . $this->getTable($table) . "(`" . join("`, `", $replaceObj['fields']) . "`) VALUES('" . join("', '", $replaceObj['values']) . "')";
        $rs = $this->setQuery($sql);
        $this->setError();
        return $this->AffectedRows($rs);
    }

    /**
     * 创建插入或替换的内容
     *
     * @param $dataArray
     * @return array
     * @throws \Qii\Exceptions\InvalidFormat
     */
    protected function createInsertReplaceObj($dataArray)
    {
        if (sizeof($dataArray) > 0 || get_object_vars($dataArray) > 0) {
            $keys = array();
            $values = array();
            foreach ($dataArray AS $key => $value) {
                $keys[] = $key;
                if (is_array($value)) {
                    throw new \Qii\Exceptions\InvalidFormat(_i('Invalid %s format', $key), __LINE__);
                }
                $values[] = $this->setQuote($value);
            }
            return array('fields' => $keys, 'values' => $values);
        }
        return array('fields' => array(), 'values' => array());
    }
    /**
     * 更新表中指定数据 结合set、where等方法是用
     *
     * @param string $table
     * @return string
     * @throws \Exception
     */
    public function update($table)
    {
        if(!$table) {
            throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
        }
        $set = join(",", $this->sets);
        $this->sets = array();
        if(count($this->whereCondition) > 0 && $this->isOperator($this->whereCondition[0]))
        {
            array_shift($this->whereCondition);
        }
        $where = count($this->whereCondition) > 0 ? " WHERE ". join(" ", $this->whereCondition) : "";
        $this->whereCondition = array();

        $alias = $this->getTableAlias($table);
        $this->modelSQL = $sql = sprintf($this->_query['UPDATE'], $alias['name'] . $alias['alias']) . $set. $where;
        return $this->exec($sql);
    }
    /**
     * 更新表的数据，同时可以使用update方法达到同样的效果
     *
     * @param $table
     * @param $dataArray
     * @param array $where [key => $val]
     * @return string
     * @throws \Exception
     */
    final function updateObject($table, $dataArray, $where = array()){
        if(!$table) {
            throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
        }
        return $this->set($dataArray)->where($where)->update($table);
    }

    /**
     * 删除表中的数据，结合where方法使用
     *
     * @param string $table 表名
     * @return string
     * @throws \Exception
     */
    final function delete($table)
    {
        if(!$table) {
            throw new \Exception('未指定更新的表名', __LINE__);
        }
        $where = count($this->whereCondition) > 0 ? " WHERE ". join(" ", $this->whereCondition) : "";
        $this->whereCondition = array();

        $alias = $this->getTableAlias($table);
        $this->modelSQL = $sql = sprintf($this->_query['DELETE'], $alias['name'], $where);
        return $this->exec($sql);
    }

    /**
     * 删除表中数据
     *
     * @param string $table 表名
     * @param null $where
     * @return string
     * @throws \Exception
     */
    final function deleteObject($table, $where = null)
    {
        if(!$table) {
            throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);
        }
        return $this->where($where)->delete($table);
    }
    /**
     * like语句
     * @param mix $arr
     * @return $this
     */
    final function like($arr)
    {
        if(!is_array($arr)) {
            if(!empty($arr)) {
                $this->where($arr);
            }
            return $this;
        }
        foreach($arr as $key => $val) {
            $arr[$key .":like"] = $val;
            unset($arr[$key]);
        }
        $this->where($arr);
        return $this;
    }

    /**
     *
     * Limit函数，如果省略第二个参数则第一个为0，第二个参数值取第一个
     * @param int $limit
     * @param int $offset
     */
    final function limit($limit, $offset = 0)
    {
        $this->limit = null;
        if($limit === '' || $limit === null) {
            throw new InvalidParams(_i('%s is invalid', 'Limit'), __LINE__);
        }
        if ($limit !== '') {
            if (!$offset) {
                $this->limit = sprintf($this->_query["LIMIT"], 0, $limit);
            } else {
                $this->limit = sprintf($this->_query["LIMIT"], $limit, $offset);
            }
        }
        return $this;
    }

    /**
     * sql中的set条件
     *
     * @param array $set
     * @param null $res
     * @param string $defaultOperator
     * @return $this
     */
    final public function set($set, &$res = null, $defaultOperator = 'equal')
    {
        if(!is_array($set))
        {
            if(!empty($set))
            {
                $this->sets[] = $set;
            }
            return $this;
        }
        if(count($set) == 0) {
            return $this;
        }
        $operator = array("equal" => "%s`%s` = '%s'", "plus" => "%s`%s` = %s`%s`+%s", "minus" => "%s`%s` = %s`%s`-%s", "multiply" => "%s`%s` = %s`%s`*%s", "divide" => "%s`%s` = %s`%s`/%s");
        foreach($set as $key => $val)
        {
            $val = $this->setQuote($val);
            $alias = $this->getFieldAlias($key);
            $operate = $this->getFieldOperator($alias['name']);
            if($operate['operator'] == '') {
                $operate['operator'] = $defaultOperator;
            }
            if($operate['operator'] == 'equal') {
                $this->sets[] = sprintf($operator[$operate['operator']], $alias['alias'], $operate['field'], $val);
            }else{
                $this->sets[] = sprintf($operator[$operate['operator']], $alias['alias'], $operate['field'], $alias['alias'], $operate['field'], $val);
            }
        }

        return $this;
    }

    /**
     * set 字段加
     * @param $set
     * @return $this
     */
    public function upsetCounter($set)
    {
        if(!is_array($set))
        {
            if(!empty($set))
            {
                $this->sets[] = $set;
            }
            return $this;
        }
        if(count($set) == 0) {
            return $this;
        }
        foreach ($set as $key => $val) {
            if(substr($key, -5) == ':plus') {
                continue;
            }
            $set[$key . ":plus"] = $val;
            unset($set[$key]);
        }
        return $this->set($set);
    }

    /**
     * set 字段减
     * @param $set
     * @return $this
     */
    public function downsetCounter($set)
    {
        if(!is_array($set)) {
            if(!empty($set)) {
                $this->sets[] = $set;
            }
            return $this;
        }
        if(count($set) == 0) {
            return $this;
        }
        foreach ($set as $key => $val) {
            if(substr($key, -6) == ':minus') {
                continue;
            }
            $set[$key . ":minus"] = $val;
            unset($set[$key]);
        }
        return $this->set($set);
    }
    /**
     * where条件
     * @param $where where语句
     * @param null $res
     * @return $this
     */
    public function where($where, &$res = null)
    {
        if(!is_array($where)) {
            if(!empty($where))
            {
                if(!empty($this->whereCondition) && !$this->isOperator($where)) {
                    $this->whereCondition[] = "and";
                }
                if($this->isOperator($where)) {
                    $this->whereCondition[] = $where;
                }else{
                    $this->whereCondition[] = "(". $where . ")";
                }
            }
            return $this;
        }
        if(count($where) == 0) {
            return $this;
        }
        $slices = $this->groupContents($where);
        $this->handleCondition($slices, $res);
        return $this;
    }

    /**
     * OR 条件
     * @param $where
     * @param string $defaultOperater
     * @param null $res
     * @return $this
     * @throws \Exception
     */
    public function orTerms($where, $defaultOperater = 'or', &$res = null)
    {
        if(!is_array($where))
        {
            if($where != '') {
                if(!empty($this->whereCondition) && !$this->isOperator($where)) {
                    $this->whereCondition[] = $defaultOperater;
                }
                $this->whereCondition[] = "(". $where . ")";
            }
            return $this;
        }
        if(count($where) == 0) {
            return $this;
        }
        $this->handleCondition(array(array($defaultOperater, $where)), $res);
        return $this;
    }

    /**
     * in 条件
     * @param $where
     * @param $defaultOperater
     * @param $res
     * @return $this
     * @throws \Exception
     */
    public function in($where, $defaultOperater = 'or', &$res = null)
    {
        if(!is_array($where))
        {
            if($where != '') {
                if(!empty($this->whereCondition) && !$this->isOperator($where)) {
                    $this->whereCondition[] = $defaultOperater;
                }
                $this->whereCondition[] = "(". $where . ")";
            }
            return $this;
        }
        if(count($where) == 0) {
            return $this;
        }

        foreach ($where as $key => $val) {
            if(substr($key, - 3) == ':in') {
                continue;
            }
            $where[$key . ":in"] = $val;
            unset($where[$key]);
        }
        $this->handleCondition(array(array('and', $where)), $res);
        return $this;
    }

    /**
     * 不包含
     *
     * @param mix $where 条件
     * @return $this
     */
    public function exclude($where)
    {
        if(!is_array($where))
        {
            return $this->where($where);
        }
        if(count($where) == 0) {
            return $this;
        }
        foreach($where as $key => $value) {
            if($this->getFieldOperator($key)['operator'] == '') {
                $where[$key . ":unequal"] = $value;
                unset($where[$key]);
            }
        }
        return $this->where($where);
    }

    /**
     * join语句
     *
     * @param mix $val
     * @param reference $res 用于返回值
     * @return $this
     * @throws \Exception
     */
    public function join($val, &$res = null) {
        if(!is_array($val)) {
            if(!empty($val)) {
                $this->joinCondition[] = $val;
            }
            return $this;
        }
        if(count($val) == 0) {
            return $this;
        }
        $slices = $this->groupContents($val);
        $this->handleTableJoin($slices, 'leftJoin', $res);
        return $this;
    }

    /**
     * left join
     * @param $table
     * @param $on
     * @return $this
     * @throws \Exception
     */
    final function leftJoinObject($table, $on)
    {
        $alias = $this->getTableAlias($table);
        return $this->join(" LEFT JOIN ". $this->getTable($alias['name']) . " " . $alias['alias'] ."  ON ". $on);
    }

    /**
     * GROUP BY
     * @param mix $group
     * @return $this
     */
    public function groupBy($group)
    {
        if(!is_array($group))
        {
            if(!empty($group))
            {
                $this->groupBy = stristr($group, 'GROUP BY') === false?  "GROUP BY ". $group: $group;
            }
            return $this;
        }
        if(count($group) == 0) {
            return $this;
        }
        foreach($group as $index => $val)
        {
            $alias = $this->getFieldAlias($val);
            $group[$index] = $alias['alias'] . "`". $alias['name'] ."`";
        }
        $this->groupBy = " GROUP BY ". join(",", $group);
        return $this;
    }

    /**
     * Order by
     *
     * @param mix $order
     * @return $this
     * @throws \Exception
     */
    public function orderBy($order)
    {
        if(!is_array($order))
        {
            if(!empty($order)) {
                $this->orderBy = stristr($order, 'ORDER BY') === false ? "ORDER BY ". $order: $order;
            }
            return $this;
        }
        if(count($order) == 0) {
            return $this;
        }
        $allowSortOff = array('asc', 'desc');
        $orderBy = array();
        $i = 0;
        $countOrder = count($order);
        foreach($order as $key => $sort)
        {
            if(!in_array(strtolower($sort), $allowSortOff) && $countOrder == $i)
            {
                throw new InvalidParams(_i('%s is invalid', 'sort'), __LINE__);
            }
            $alias = $this->getFieldAlias($key);

            $orderBy[] = $alias['alias'] . "`". $alias['name'] ."` ". $sort;
            $i++;
        }
        $this->orderBy = " ORDER BY ". join(",", $orderBy);
        return $this;
    }

    /**
     * Order by sql
     *
     * @param string $orderBy
     * @return $this
     * @throws \Exception
     */
    public function orderByStr($orderBy)
    {
        return $this->orderBy($orderBy);
    }
    /**
     * 过滤值
     *
     * @param mix $word
     * @return array|string
     */
    final function setQuote($word)
    {
        if (ini_get("magic_quotes_gpc")) {
            return $word;
        }
        return is_array($word) ? array_map('addslashes', $word) : addslashes($word);
    }
    /**
     *
     * 查询的字段
     * @param String $fields
     */
    final function fields($fields = "*")
    {
        $this->fields = null;
        if (empty($fields)) $fields = "*";
        if (is_array($fields)) {
            if(count($fields) == 0) {
                $fields = '*';
            }else{
                foreach($fields as $key => $val)
                {
                    $alias = explode('.', $val);
                    if(count($alias) > 1)
                    {
                        $fields[$key] = $alias[0] . ".`".join(".", array_slice($alias, 1))."`";
                    }
                }
                $fields = join(',', $fields);
            }
        }
        $this->fields = $fields;
        return $this;
    }
    /**
     * 清空Data数据
     */
    final public function clearCondition()
    {
        $this->fields = '*';
        $this->whereCondition = array();
        $this->joinCondition = array();
        $this->groupBy = "";
        $this->orderBy = "";
        $this->limit = null;
        $this->sets = array();
    }

    /**
     * 获取错误码
     */
    final public function getCode()
    {
        return $this->response->getCode();
    }

    /**
     * 获取错误信息
     */
    final public function getMessage()
    {
        if ($this->response->isError()) {
            return $this->response->getMessage();
        }
    }

    /**
     * 返回response对象
     *
     * @return Bool
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * 转换字符创
     *
     * @param $str
     * @return array|string
     */
    final public function iconv($str)
    {
        if (is_array($str)) {
            return array_map(function ($n) {
                return toUtf8($n);
            }, $str);
        }
        return toUtf8($str);
    }

    /**
     * 执行Model过程中保存的相关信息
     *
     * @param String $option
     * @return Mix
     */
    final function querySQL($option = '')
    {
        $allow = array('_queryTimes', '_querySeconds', '_errorInfo', '_exeSQL');
        if (in_array($option, $allow)) {
            return $this->{$option};
        }
        return 0;
    }
    /**
     * 通过where\set\limit等方法自动生成SQL语句
     *
     * @param string $table 必填
     * @return string
     * @throws \Exception
     */
    public function createSelectSQL($table)
    {
        if(!$table) {
            throw new InvalidParams(_i('%s is invalid', '表名'), __LINE__);

        }
        $aliases = $this->getTableAlias($table);

        $fields = (trim($this->fields) != '') ? $this->fields : "*";
        //$this->fields = '*';

        if(count($this->whereCondition) > 0 && $this->isOperator($this->whereCondition[0])) {
            array_shift($this->whereCondition);
        }
        $where = count($this->whereCondition) > 0 ? " WHERE ". join(" ", $this->whereCondition) : "";
        //$this->whereCondition = array();

        $join = count($this->joinCondition) > 0 ? join("\n", $this->joinCondition) : "";
        //$this->joinCondition = array();

        $groupBy = " ". $this->groupBy;
        //$this->groupBy = "";

        $orderBy = " ". $this->orderBy;
        //$this->orderBy = "";

        $limit = $this->limit;
        //$this->limit = null;

        $sql = sprintf($this->_query['SELECT'], $fields, $aliases['name'], $aliases['alias']) . $join . $where . $groupBy . $orderBy . $limit;
        $this->clearCondition();
        return $sql;
    }
    /**
     * 获取操作符
     *
     * @param string $field 字段
     * @return array
     */
    protected function getFieldOperator($field)
    {
        $operator = explode(":", $field);
        if(count($operator) == 1) {
            return array('operator' => '', 'field' => $field);
        }
        $operate = array_pop($operator);
        $field = join(":", $operator);

        return array('operator' => $operate, 'field' => $field);
    }
    /**
     * 获取字段别名
     *
     * @param string $name
     * @param string $connector
     * @return array
     */
    protected function getFieldAlias($name, $connector = ".")
    {
        $aliases = explode('.', $name);
        if(count($aliases) == 1) {
            return array('alias' => '', 'name' => $name);
        }

        return array('alias' => $aliases[0] . $connector, 'name' => join(".", array_slice($aliases, 1)));
    }

    /**
     * 获取表的别名
     *
     * @param string $name 名字
     * @return array
     */
    protected function getTableAlias($name)
    {
        //去掉table前后的``符号
        $name = str_replace('`', '', $name);
        $aliases = explode(' ', $name);
        //检查表名中时候含数据库名，有数据表名的时候需要单独处理
        $hasDatabaseName = false;
        if(stristr($name, '.')) {
            $hasDatabaseName = true;
        }
        if(count($aliases) == 1) {
            if($hasDatabaseName) {
                $names = explode(".", $name);
                $name = $names[0] . ".`". $names[1] . "`";
            }else{
                $name = "`". $name ."`";
            }
            return array('alias' => '', 'name' => $name);
        }
        $res = array();
        $res['alias'] = array_pop($aliases);
        $res['name'] = join(" ", array_slice($aliases, -1));
        if($hasDatabaseName) {
            $names = explode(".", $res['name']);
            $res['name'] = $names[0] . ".`". $names[1] . "`";
        }else{
            $res['name'] = "`". $res['name'] ."`";
        }
        return $res;
    }
    /**
     * 把条件根据『链接字符串,『字段:值』』等内容分组
     *
     *
     * $whereGroup = array(
     *   ['id' => 1, 'name' => '名字'],
     *   'or',
     *   ['status' => 1, 'create_at:greater' => '22222'],//
     *   'or',//链接字段与字段之间的操作符
     *   'like',//使用在字段与值之间的操作符，可以省略
     *   'and',//字段1与字段2之间的操作符
     *   'or',//字段2与字段3之间的操作符
     *   '...',//字段n与字段n+1之间的操作符
     *   //字段n与字段n+1之间的操作符可以省略
     *   //子数组之间的操作符优先于上边的操作符
     *   ['email' => 'antsnet@163.com', "and", 'nickname' => 'antsnet'],
     *   ['uid' => 1],
     *   'and',
     *   ['name' => 'ss'],
     *   'and',
     *   'and',
     *   'update_at=1',
     *   );
     * @param $group
     * @return array [['or/and', 'like/equal/...', ['字段1' => '值1', '字段2' => '值2']],[...]]
     */
    protected function groupContents($group)
    {
        $slices = array();
        //如果是一维数组就直接操作值，不检查操作符
        if(count($group) == count($group, 1)) {
            $slices[] = array($group);
            return $slices;
        }
        $count = count($group);
        $tmpWhere = array();
        //最后一次是否是赋值
        $lastIsValue = null;
        $groupCount = count($group);
        foreach($group as $index => $val)
        {
            $isOperator = $this->isOperator($val);//如果是操作符，上一个不是操作符就清空tmpWhere，并放入slices
            $isValue = !$isOperator;
            /*if($isOperator) {
                $hasOperator = true;
            }*/
            if($lastIsValue && $isOperator)
            {
                $slices[] = $tmpWhere;
                $tmpWhere = array();
                $tmpWhere[] = $val;
            }
            else if($count - 1 == $index)
            {
                $tmpWhere[] = $val;
                $slices[] = $tmpWhere;
            }else {
                $tmpWhere[] = $val;
            }
            $lastIsValue = $isValue;
        }
        return $slices;
    }
    /**
     * 判断是否是操作符号
     *
     * @param $val 值
     * @return bool
     */
    protected function isOperator($val)
    {
        if(is_array($val)) {
            return false;
        }
        if(!is_array($val)) {
            $val = strtolower($val);
        }
        return in_array($val, $this->operateVal) || in_array($val, $this->operateTable);
    }

    /**
     * 是否是操作表
     *
     * @param mix $val 值
     * @return bool
     */
    protected function isOperateTable($val)
    {
        if(is_array($val)) {
            return false;
        }
        return in_array($val, $this->operateTable);
    }

    /**
     * where条件子句组合
     *
     * @param array $values ['字段1' => '值1', '字段2' => '值2', ...]
     * @param $defaultOperate 默认字句的链接方式
     *  ..... 额外的参数，用于字段与字段之间的连接
     * @return string
     * @throws \Exception
     */
    protected function handleSubCondition($values, $defaultOperate = 'equal')
    {
        $extraParams = array();
        if(func_num_args() > 2)
        {
            $extraParams = array_slice(func_get_args(), 2);
        }
        $where = array();
        $operator = array('equal' => "%s`%s` = '%s'",'in' => "%s`%s` in (%s)", 'unequal' => "%s`%s` != '%s'", 'greater' => "%s`%s` > '%s'", 'greaterEqual' => "%s`%s` >= '%s'", 'less' => "%s`%s` < '%s'", 'lessEqual' => "%s`%s` <= '%s'", 'like' => "%s`%s` like '%%%s%%'");
        $lastIsOperator = false;
        $lastIsValue = null;
        $i = 0;
        foreach($values as $key => $val)
        {
            $isOperator = $this->isOperator($val);//如果是操作符，上一个不是操作符就清空tmpWhere，并放入slices
            $isValue = !$isOperator;
            if($lastIsValue && $isOperator)//如果当前是操作符，上一个是值，就将操作符加入到条件中
            {
                $where[] = $val;
                $lastIsValue = $isValue;
                $lastIsOperator = $isOperator;
                continue;
            }
            //如果上一次是操作符，这次又是操作符，就是用当前的操作符，去掉上一个操作符
            if($lastIsOperator && $isOperator)
            {
                if(!$this->faultTolerant) throw new InvalidParams(_i('Unsupported operator'), __LINE__);
                array_pop($where);
                $where[] = $val;
                continue;
            }
            if($lastIsValue && $isValue)//需要添加操作符
            {
                $where[] = count($extraParams) > 0 && isset($extraParams[$i-1]) ? $extraParams[$i-1] : "and";
            }

            //$aliases = explode(".", $key);
            $aliases = $this->getFieldAlias($key);
            $alias = $aliases['alias'];
            $operate = $this->getFieldOperator($aliases['name']);
            $opt = $operate['operator'] ? $operate['operator'] : $defaultOperate;
            $name =  $operate['field'];
            if($opt == 'in' && is_array($val))
            {
                $where[] = sprintf($operator[$opt], $alias, $name, "'". join("','", $val) . "'");
            }else{
                $where[] = sprintf($operator[$opt], $alias, $name, $this->setQuote($val));
            }
            $lastIsValue = $isValue;
            $lastIsOperator = $isOperator;
            $i++;
        }

        return join(" ", $where);
    }

    /**
     * 处理table join
     * @param array $slices [['leftJoin', ['table' => '表名', 'alias' => 'a', 'on' => 'a.id = b.id']]]
     * @param string $defaultJoin
     * @param null $res
     * @return $this
     * @throws \Exception
     */
    protected function handleTableJoin($slices, $defaultJoin = 'leftJoin', &$res = null)
    {
        foreach ($slices as $v)
        {
            if(count($v) == 0) {
                throw new \Exception('连接表操作失败，格式:"leftJoin/rightJoin/innerJoin", ["table" => "表名", "alias" => "b", "on" => "a.id=b.id"]', __LINE__);
            }
            if(count($v) == 1 && !$this->isOperateTable($v[0]))
            {
                array_unshift($v, $defaultJoin);
            }
            $joinOperator = array(
                "leftJoin" => " LEFT JOIN %s ON %s",
                "rightJoin" => " RIGHT JOIN %s ON %s",
                "innerJoin" => " INNER JOIN %s ON %s"
            );
            if(!$this->isOperateTable($v[0]))
            {
                throw new \Exception('连接表操作失败，格式:"leftJoin/rightJoin/innerJoin", ["table" => "表名", "alias" => "b", "on" => "a.id=b.id"]', __LINE__);
            }

            $joinCondition = sprintf($joinOperator[$v[0]], $v[1]['table'] . ' '. $v[1]['alias'], $v[1]['on']);
            if(!empty($this->join) && is_array($this->join))
            {
                $this->joinCondition = array_merge($this->join, array($joinCondition));
            }
            else
            {
                $this->joinCondition[] = $joinCondition;
            }
            $res[] = $joinCondition;
        }
        unset($joinCondition);
        return $this;
    }

    /**
     * 处理 where 条件
     * @param array $condition
     * @param null $res
     * @return $this
     * @throws \Exception
     */
    protected function handleCondition($condition, &$res = null)
    {
        if(!is_array($condition))
        {
            return $this;
        }
        $count = count($condition);
        $whereCondition = array();
        for($i = 0; $i < $count; $i++)
        {
            $v = $condition[$i];
            //如果有两个及上的操作符
            //默认第一个为连接其他条件的操作符，第二个位字段和值之间的操作符, 从第三个开始即为字段与字段之间的连接符
            //最里层的字段与值之间的操作符优先级最高

            //例如 1: 'or/and','like','or', 'and', ['uid' => 1, 'name' => '名字', 'status' => 激活];
            //结果 1：or/and (uid like '%1%' or name like '%名字%' and status like '%激活%')

            //例如 2: 'or/and','like','or', 'and', ['uid' => 1, 'name' => '名字', 'status:equal' => 激活];
            //结果 2：or/and (uid like '%1%' or name like '%名字%' and status = '激活')

            $operateCondition = array();
            $values = array();
            $countCondition = count($v);
            $handleTable = false;
            for($j = 0; $j < $countCondition; $j++)
            {
                $handleTable = false;
                if($this->isOperateTable($v[$j]))
                {
                    /*
                    $operateCondition[] = $v[$j];
                    $joinTable[$v[$j]] = $this->handleTableJoin($v);
                    */
                    //如果是操作数据表就直接退出循环单独处理
                    $handleTable = true;
                    break;
                }
                if($this->isOperator($v[$j]))
                {
                    $operateCondition[] = $v[$j];
                    continue;
                }
                if(!$this->isOperator($v[$j]))
                {
                    if(!is_array($v[$j])) {
                        $whereCondition[] = $v[0];
                        $whereCondition[] = "(". $v[1] . ")";
                        break;
                    }
                    $values = is_array($v[$j]) ? array_merge($values, $v[$j]) : array_merge($values, array($v[$j]));
                }
            }
            if($handleTable)
            {
                continue;
            }
            if(count($operateCondition) > 0 && count($values) > 0)
            {
                $whereCondition[] = array_shift($operateCondition);
            }
            if(count($values) > 0) {
                if(count($operateCondition) > 0) {
                    array_unshift($operateCondition, $values);
                    $whereCondition[] = "(". call_user_func_array(array($this, 'handleSubCondition'), $operateCondition) .")";
                }else{
                    $whereCondition[] = "(". $this->handleSubCondition($values) .")";
                }
            }
        }
        if(!empty($this->whereCondition))
        {
            $lastCondition = $this->whereCondition[count($this->whereCondition) - 1];
            if(!$this->isOperator($whereCondition[0]) && !$this->isOperator($lastCondition)) {
                $this->whereCondition = array_merge($this->whereCondition, array('and'));
            }
            $this->whereCondition = array_merge($this->whereCondition, $whereCondition);
        }
        else
        {
            $this->whereCondition = $whereCondition;
        }
        $res = $whereCondition;
        unset($whereCondition);
        return $this;
    }

    /**
     * 如果不存在指定的方法则调用提示错误
     *
     * @param String $name
     * @param Mix $args
     * @return Mix
     */
    public function __call($method, $argvs)
    {
        if (isset($this->_modelAlias[$method])) {
            if (method_exists($this, $this->_modelAlias[$method])) {
                return call_user_func_array(array($this, $this->_modelAlias[$method]), $argvs);
            }
            \Qii::setError(false, __LINE__, 1506, 'Alias ' . get_called_class() . '->' . $method . '()');
        }
        \Qii::setError(false, __LINE__, 1506, get_called_class() . '->' . $method . '()');
    }
}