<?php
/**
 * Class object model
 */
class objectMod extends mod{
	public $subs = []; //子类
	function __construct(){
		$e = require(mvc::$cfg['ROOT'].'mod/element/object.php');
		parent::__construct($e);
    }
	/**
	 * Method 列表数据
	 * @param string $where 查询sql条件
	 * @param int $page 页码(从1开始)
	 * @param int $pagesize 分页大小
	 * @param string $sidx 排序字段(单个)
	 * @param string $sord 排序方式 asc|desc
	 * @param string $orderby 排序sql(可多个)[优先]
	 * @param string $isfull 是否显示全路径名称,及全路径keyword
	 * @return array 数据集
	 */
	public function list($parentId,$where='',$page=0,$pagesize=0,$sidx='',$sord='asc',$orderby='',$isfull=0){
		if($isfull==1){
			$sql = "SELECT * FROM (
				SELECT *
					,getObjectFullName(o.o_id) subjectText
					,getObjectKeyword(o.o_id) subjectKeyword
				 %s FROM `object` o
			) T_ WHERE 1 = 1";
		}else{
			$sql = "SELECT * FROM (SELECT *,(SELECT o_name FROM `object` WHERE o_id = o.o_parent_id) o_parent %s FROM `object` o) T_ WHERE 1 = 1";
		}
		$extsql = '';
		$checkBoxCols = [];
		$selectAndRadioCols = [];
		if($parentId>0 && $isfull==0){ //扩展字段内容
			$tpl_extsql = "(SELECT 
			      CASE
			        WHEN oev_type = 'varchar' 
			        THEN oev_varchar 
			        WHEN oev_type = 'int' 
			        THEN oev_int 
			        WHEN oev_type = 'decimal' 
			        THEN FORMAT(oev_decimal,oev_precision) 
			        WHEN oev_type = 'text' 
			        THEN oev_text 
			        WHEN oev_type = 'date' 
			        THEN oev_date 
			      END 
			    FROM
			      `object_ext_val` 
			    WHERE oev_o_id = o.o_id AND oev_oe_id = %s) oe_%s";
			if($rootRow = $this->getRootRowByChildren($parentId)){
				$arr = [];
				foreach($rootRow['ext'] as $v){
					if($v['oe_editor'] == 'checkbox') 
						$checkBoxCols[] = 'oe_'.$v['oe_id']; 
					else if($v['oe_editor'] == 'select' || $v['oe_editor'] == 'radio' || $v['oe_editor'] == 'not')
						$selectAndRadioCols[] = 'oe_'.$v['oe_id']; 
					$arr[] = sprintf($tpl_extsql,$v['oe_id'],$v['oe_id']);
				}
				if($arr){
					$extsql = implode(',',$arr);
					$sql = sprintf($sql,','.$extsql);
				}
			}

		}
		$sql = sprintf($sql,$extsql);
		if(trim($where)!='') {
			if(strtolower(substr(trim($where),0,3))!=='and') $where = ' AND ' . $where;
			$sql .= $where;
		}
		if($sidx=='' && $orderby=="") $orderby =  $this->e['order']; //默认排序
		if($orderby!=''){
			$sql.= sprintf(' ORDER BY %s', $orderby);
		}else if($sidx!=''){
			$sql.= sprintf(' ORDER BY %s %s',$sidx,$sord);
		}
		if($page>0 && $pagesize>0){
			$pages = $this->dbRead->PageLimit($sql,$page,$pagesize);
			$sql .= $pages['limit'];
		}else if($page<=0 && $pagesize>0){
			$sql .= ' limit 0,'.$pagesize;
		}
		$rows = $this->dbRead->Table($sql);
		if($checkBoxCols || $selectAndRadioCols){ //附表值，显示处理
			foreach($rows as $k=>$row){
				foreach($row as $k2=>$v){
					if(in_array($k2, $checkBoxCols)){
						$rows[$k][$k2] = $this->extCheckboxText($v);
					}else if(in_array($k2, $selectAndRadioCols)){
						if($v!='' && is_numeric($v))
							$rows[$k][$k2] = $this->extSelectAndRadioText($v);
					}
				}
			}
		}
		$footerData=[];
		$data = [
			'page'=> $pages['page'],
			'total'=> $pages['total'],
			'records' => $pages['records'],
			"userdata"=> $footerData,
			'rows' => $rows
		];
		return $data;
	}
	/**
	 * Method 找根节点
	 * @param [int|array] $value 可接收ID与Row数组
	 */
	function getRootRowByChildren($value){
		if(is_array($value)){
			$childrenRow = $value;
		}else{
			$childrenRow = $this->getRowByKey('*',$value);
		}
		$sql = sprintf("SELECT * FROM object WHERE o_lft<=%s AND o_rgt >=%s AND o_root = 1 LIMIT 0,1", $childrenRow['o_lft'], $childrenRow['o_rgt']);
		if($rootRow = $this->dbRead->Row($sql))
			$rootRow['ext']	= $this->getExt($rootRow['o_id']);	
		return $rootRow;
	}
	/**
	 * Method 得到节点扩展参数配置
	 * @param [int] $o_id
	 */
	function getExt($o_id){
		$sql = sprintf("SELECT * FROM object_ext WHERE oe_o_id = %s ORDER BY oe_sort,oe_id", $o_id);
		return $this->dbRead->Table($sql);
	}
	/**
	 * Method 获取节点扩展参数值
	 * @param [int] $o_id
	 * @param [int] $oe_id
	 */
	function getExtval($o_id,$oe_id){
		$sql = sprintf("SELECT * FROM object_ext_val WHERE oev_o_id=%s and oev_oe_id=%s LIMIT 1", $o_id,$oe_id);
		$result = '';
		if($row = $this->dbRead->Row($sql)){
			$result = $this->extValue($row);
		}
		return $result;
	}
	/**
	 * Method 得到节点扩展参数列表
	 * @param [int] $o_id
	 */
	function getExtvalList($o_id){
		$sql = sprintf("SELECT * FROM object_ext_val WHERE oev_o_id = %s", $o_id);
		$table = $this->dbRead->Table($sql);
		$data = [];
		foreach($table as $row){
			$data[$row['oev_oe_id']] = $this->formartExtRow($row);
		}
		return $data;
	}
	/**
	 * Method 格式化扩展记录
	 * @param [array] $row
	 */
	function formartExtRow($row){
		$field = 'oev_'.$row['oev_type'];
		$value = $row[$field];
		$editor = $row['oev_editor'];
		$text = '';
		if($row['oev_type']=='decimal' && $value!='' && $row['oev_precision']){
			$value = number_format($value, $row['oev_precision']);
		}else if($editor=='select' || $editor=='radio'){
			$text  = $this->extSelectAndRadioText($value);
		}else if($editor=='checkbox'){
			$value = json_decode($value);
			$text  = $this->extCheckboxText($value);
		}
		if($text=='') $text = $value;
		$data['value'] = $value;
		$data['text'] = $text;
		return $data;
	}
	/**
	 * Method 将扩展记录的SelectAndRadio值，转成显示文本
	 * @param [string] $value
	 */
	function extSelectAndRadioText($value){
		$result = $value;
		if(!empty($value)){
			$result = $this->getOne('o_name',sprintf("o_id = %s",$value));
		}
		
		return $result;
	}
	/**
	 * Method 将扩展记录的checkbox值，转成显示文本
	 * @param [json|array] $value
	 */
	function extCheckboxText($value){
		$result = '';
		if(!is_array($value)) $value = json_decode($value);
		if(!empty($value)){
			$ids = implode(',',$value);
			$extvalRows = $this->getTable('o_name',sprintf("o_id in(%s)",$ids));
			$result = implode(',', array_column($extvalRows,'o_name'));
		}
		
		return $result;
	}
	/**
	 * Method 通过附表ID与附表基表中的编码o_code，找附表的o_id值
	 * @param [int] $sche_id 附表ID
	 * @param [int] $text
	 */
	function getIdByCode($sche_id,$code){
		$row = $this->getRowByKey('*',$sche_id);
		if($row){
			$sql = sprintf("SELECT o_id FROM object WHERE o_lft>%s AND o_rgt<%s AND o_code = '%s' limit 1", 
				$row['o_lft'], 
				$row['o_rgt'],
				$code);
			$result = $this->dbRead->One($sql);
		}
		if(empty($result)) $result = '0';
		return $result;
	}
	/**
	 * Method 通过附表ID与附表基表中的文本o_name，找附表的o_id值
	 * @param [int] $sche_id 附表ID
	 * @param [int] $text
	 */
	function getIdByText($sche_id,$text,$isLike){
        $text = trim($text);
		$row = $this->getRowByKey('*',$sche_id);
		if($row){
            if($isLike){
                $sql = sprintf("SELECT o_id FROM object WHERE o_lft>%s AND o_rgt<%s AND o_name like '%%%s%%' limit 1", 
                    $row['o_lft'], 
                    $row['o_rgt'],
                    $text);
                $result = $this->dbRead->Table($sql);
        		if(empty($result)){
                    $result = [0];
                }else{
                    $result = array_column($result,'o_id');
                    //$result = array_values($result);
                }
            }else{
                $sql = sprintf("SELECT o_id FROM object WHERE o_lft>%s AND o_rgt<%s AND o_name = '%s' limit 1", 
                    $row['o_lft'], 
                    $row['o_rgt'],
                    $text);
                $result = $this->dbRead->One($sql);
        		if(empty($result)) $result = '0';
            }
		}
		return $result;
	}
	/**列表
	 * Method 保存扩展信息
	 * @param [int|array] $exts 扩展数据数组
	 * @param [int] $o_id
	 */
	function setExt($table,$exts,$o_id){
		$rootRow = $this->getRootRowByChildren($o_id);
		if(!$rootRow) 
			return false;
		$rootExt = [];
		foreach($rootRow['ext'] as $k=>$v){
			$rootExt[$v['oe_id']] = $v;
		}
		//$this->addRow(['a'=>1]);
		foreach($exts as $oe_id=>$value){
			$oe_type = $rootExt[$oe_id]['oe_type'];
			$oe_editor = $rootExt[$oe_id]['oe_editor'];
			$oe_precision = $rootExt[$oe_id]['oe_precision'];
			if(is_array($value)) $value = json_encode($value);
			$data = [
				'oev_o_id' => $o_id,
				'oev_oe_id' => $oe_id,
				'oev_type' => $oe_type,
				'oev_editor' => $oe_editor,
				'oev_precision' => $oe_precision,
				'oev_'.$oe_type => $value
			];
			$where = sprintf('oev_o_id=%s AND oev_oe_id=%s',$o_id, $oe_id);
			if(!$this->replaceRowSelectTable($table,$data,$where))
				return false;
		}
		return ture;
	}
	/**得到子类扩展类
	 * @param [int] $id
	 */
	function getSub($id){
		if(!isset($this->subs[$id])){
			$class = 'id'.$id;
			$file = mvc::$cfg['ROOT'].'mod/object_ext/'.$class.'.php';
			if(file_exists($file)){
				require_once($file);
				$this->subs[$id] = new $class();
			}
		}else{
			$this->subs[$id] = null;
		}
		return $this->subs[$id];
	}
	/**得到子类扩展类
	 * @param [int] $id
	 */
	function callSub($id,$func,&$params){
		$sub = $this->getSub($id);
		if($sub!=null && method_exists( $sub, $func)){
			$sub->$func($params);
			//call_user_func_array ( array ( $sub, $func ), $params );
			return true;
		}
		return false;
	}
	/**
	 * Method 通过名称与父节点取一行数据
	 */
	function getRowByName($root,$name,$parentId=0){
		$rootRow = $this->getRowByKey('*',$root);
		$where = sprintf(" o_lft>=%s AND o_rgt<=%s AND o_name='%s'",$rootRow['o_lft'],$rootRow['o_rgt'],$name);
		if($parentId) $where.= sprintf(" AND o_parent_id=%s",$parentId);
		return $this->getRow('*',$where);
	}
	/**
	 * Method 通过多级名称取一行记录
	 */
	function getRowByFullName($root,$name){
		$arr = explode('_',$name);
		$rootRow = $this->getRowByKey('*',$root);
		$where = "";
		if(count($arr)>1){ //要判断父节点名称
			$parentRow = $this->getRowByName($root,$arr[0]);
			return $this->getRowByName($root,$arr[1],$parentRow['o_id']);
		}else{
			return $this->getRowByName($root,$name);
		}
	}
	/**
	 * 通过名称与父ID找Oid
	 * @param int $parent_id 父ID
	 * @param string $name 名称
	 * @return int 
	 */
	public function getOidByName($parent_id, $name){
		return $this->getOneSelectTable('object','o_id',"o_parent_id=".$parent_id." AND o_name='".$name."'");
	}
}

