<?php
// +----------------------------------------------------------------------
// | 后台父类控制器
// +----------------------------------------------------------------------
// | Copyright (c) 2018 https://blog.junphp.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 小黄牛 <1731223728@qq.com>
// +----------------------------------------------------------------------

namespace app\controller\SuperClass;
use app\controller\SuperClass\Reception;

class Admin extends Reception
{
    /**
     * 登录信息
    */
    protected $admin = [];
    // 菜单实例
    protected $menu  = null;
    // 默认的公共控制器方法
    protected $public_menu = [
        '/admin/login',
        '/admin/login/send',
        '/admin/login/out',
        '/admin',
    ];

    public function __construct() {
        // 开关模板布局
        $array = explode(\x\Config::run()->get('route.suffix'), \x\Request::route());
        $url = strtolower($array[0]);
        
        $admin = \x\Session::get('admin');
        if ($admin) {
            $Db = new \x\Db();
            $this->admin = $Db->name('auth_admin')->where('id', $admin['id'])->find();
            $Db->return();
            $this->assign('admin', $this->admin);
            
            # 获取列表
            $this->get_menu();
    
            # 验证访问权限
            $res = $this->vif_menu($url);
            if ($res !== true) return $res;
    
            # 将控制器实例返回到模板，方便进行验证
            $this->assign('auth', $this);
        }
    }

    // 验证访问权限
	private function vif_menu($url){
		$status = false;
		# 验证菜单权限
		foreach ($this->public_menu as $v) {
			if ($v == $url) {
				$status = true;
                break;
			}
        }
        
        // 访问不通过，直接调用404
		if (!$status) {
            if (\x\Request::is_post()) {
                return $this->returnJson('01', '你无该操作权限！');
            }    
            return $this->fetch('你无该操作权限！');
        }

        return true;
    }

    // 单独验证菜单权限
	public function vif($route){
		$route = strtolower( $route );
        $status     = false;

		# 验证
		foreach ($this->public_menu as $v) {
			if ($v == $route) {
				$status = true;
                break;
			}
		}
		return $status;
    }
    
    // 获取对应的权限菜单
    protected function get_menu(){
        if ($this->menu != null) return $this->menu;
        $field = 'id, pid, name, display, controller, action, icon';

        $where = [];
        $where[] = ['status', '=', 1];
        $list2 = [];
        $Db = new \x\Db();
        # 超级管理员
        if ($this->admin['role'] == 0) {
            $list1 = $Db->name('auth_menu')->where($where)->field($field)->order('sort DESC')->select();
        }else{
            # 取出角色下的权限菜单
            $role_menu = $Db->name('auth_role')->where('id', $this->admin['role'])->value('menu_list');
            if (!$role_menu) $role_menu = 0;
            $list1 = $Db->name('auth_menu')->where($where)->whereIn('id', $role_menu)->field($field)->order('sort DESC')->select();
            # 取出管理员的独立权限
            $admin_menu = $Db->name('auth_admin_menu')->where('admin', $this->admin['id'])->value('menu_list');
            if ($admin_menu) {
                $list2 = $Db->name('auth_menu')->where($where)->whereIn('id', $admin_menu)->whereNotIn('id', $role_menu)->field($field)->order('sort DESC')->select();
            }
            # 不是超级管理员还得单独拿公共权限
            $where[] = ['public', '=', 1];
            $list3 = $Db->name('auth_menu')->where($where)->field($field)->select();
            foreach ($list3 as $v) {
                $this->menu[] = $v;
                $url = '/admin/'.$v['controller'];
                if ($v['action']) $url .= '/'.$v['action'];
                $this->public_menu[] = $url;
            }
        }
        # 植入权限列表
        foreach ($list1 as $v) {
            $this->menu[] = $v;
            $url = '/admin/'.$v['controller'];
            if ($v['action']) $url .= '/'.$v['action'];
            $this->public_menu[] = $url;
        }
        foreach ($list2 as $v) {
            $this->menu[] = $v;
            $url = '/admin/'.$v['controller'];
            if ($v['action']) $url .= '/'.$v['action'];
            $this->public_menu[] = $url;
        }
        $Db->return();

        return $this->menu;
    }

    // 用于后台递归生成权限菜单
    protected function menu_make($cate='', $name = 'children', $pid = 0) {
        $arr = [];
        foreach ($cate as $v) {
            if ($v['pid'] == $pid) {
                if ($v['display'] == 1) {
                    $v[$name] = $this->menu_make($cate, $name, $v['id']);
                    $v['num'] = count($v[$name]);
                    $arr[] = $v;
                } 
            }
        }
        return $arr;
    }

    // 用于后台生成地区菜单
    protected function menuFor($cate, $name = 'children', $pid = 0, $array = []) {
        $arr = [];

        foreach ($cate as $k=>$v) {
            if (in_array($v['id'], $array)) {
                $v['checked'] = true;
                $v['open'] = true;
            } else {
                $v['open'] = false;
            }
            if ($v['pid'] == $pid) {
                unset($cate[$k]);
                $v[$name] = $this->menuFor($cate, $name, $v['id'], $array);
                $v['num'] = count($v[$name]);
                $arr[] = $v;
            }
        }
        return $arr;
    }

    // 用于后台输出LIST菜单给Layui
    protected function _list($code, $msg, $count, $list=[]) {
        $json = json_encode([
            'code' => "$code",
            'msg' => $msg,
            'count' => $count,
            'data' => $list
        ], JSON_UNESCAPED_UNICODE);

        $this->fetch($json);
        // 返回false，是为了兼容各种where判断中断操作
        return false;
    }

    /**
     * 输出Json到页面
     * @todo 无
     * @author 小黄牛
     * @version v1.1.5 + 2020.07.14
     * @deprecated 暂不启用
     * @global 无
     * @param string $code
     * @param string $msg
     * @param array $data
     * @return void
    */
    public function returnJson($code, $msg='Success', $data=[]) {
        $admin = \x\Session::get('admin');
        if ($admin) {
            if (\x\Request::is_post()) {
                $json = json_encode(\x\Request::post(), JSON_UNESCAPED_UNICODE);
            } else {
                $json = json_encode(\x\Request::get(), JSON_UNESCAPED_UNICODE);
            }
            $Db = new \x\Db();
            $Db->name('auth_admin_action')->insert([
                'admin' => $admin['id'],
                'url' => \x\Request::url(),
                'ip' => \x\Request::ip(),
                'msg' => $msg,
                'param' => $json,
                'create_time' => time(),
            ]);
            $Db->return();
        }
        $json = json_encode([
            'code' => "{$code}",
            'msg' => $msg,
            'data' => $data,
        ], JSON_UNESCAPED_UNICODE);
        $this->fetch($json);
        // 返回false，是为了兼容各种where判断中断操作
        return false;
    }
    
    /*
     * 判断地区编码是否存在，从属性关系是否错误
     * @todo 无
     * @author 小黄牛
     * @version v1.2.1 + 2019.04.02
     * @deprecated 暂不弃用
     * @global 无
     * @param Db $Db 数据实例
     * @param int $vif_code 需要验证的地区编码
     * @param int $pid_code 父级地区编码
     * @param int $msg_code 日志编码
     * @param int $in_code 原先的地区编码
     * @return void
    */
    protected function vif_code($Db, $vif_code, $pid_code, $msg_code, $in_code=null) {
        if ($vif_code != $in_code) {
            $res1 = $Db->name('region')->where('code', $vif_code)->value('id');
            $res2 = $Db->name('area')->where('code', $vif_code)->value('id');

            if ($res1 || $res2) {
                return $this->returnJson('01', '地区编码已存在！');
            }
        }

        if (!preg_match("/^[1-9][0-9]*$/", $vif_code)) {
            return $this->returnJson('01', '地区编码必须为整数类型！');
        }

        if (mb_strlen($vif_code, 'utf8') != 6) {
            return $this->returnJson('01', '地区编码长度错误，正确为6位数字！');
        }
        
        # 判断从属性，为父级前2位
        if (!empty($pid_code)) {
            $left  = substr($vif_code, 0, 2);  
            $right = substr($pid_code, 0, 2); 
            if ($left != $right) {
                return $this->returnJson('01', '地区编码与父级地区编码从属关系错误！');
            }
        }

        return true;
    }
}