<?php
namespace app\api\controller;

use think\Cache;
use think\Config;
use think\Request;
use think\Response;
use think\Validate;
/**
 * 接口基类
 * @author liyuhang <523277027@qq.com>
 */
abstract class Base{
    protected $method; // 当前请求类型
    protected $type; // 当前资源类型
    // 输出类型
    protected $_btw    = [0, 0]; // 时间区间等
    protected $url = '';//分享地址
    protected $restMethodList = 'post,get';
    protected $restDefaultType = '';
    protected $header = []; //输出header数据
    protected $request = [];
    protected $accessToken = '';
    protected $p = 1; //分页页数
    protected $order = ""; //排序
    protected $row = 10; //默认分页数
    protected $user = []; //登录对象
    protected $uid = 0;
    protected $param = []; //post参数
    protected $map = [];//post处理过后的参数
    protected $allCount = 0; //数据总条数
    protected $token = ''; //token
    protected $allow_fun = [//登录不需要验证的方法
        'com'=>'*',
        'user'=>',login,'
    ];

    /**
     * 架构函数 取得模板对象实例
     * @access public
     */
    public function __construct(Request $request) {
        session_start();
        // 指定允许其他域名访问
        $http_origin = "*";
        if(isset($_SERVER['HTTP_ORIGIN'])){
            $http_origin = $_SERVER['HTTP_ORIGIN'];
        }
        header("Access-Control-Allow-Origin:".$http_origin);
        header('Access-Control-Allow-Methods:POST,GET'); //支持的http 动作
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization, token');  //响应头 请按照自己需求添加。
        if (strtolower($_SERVER['REQUEST_METHOD']) == 'options') {
            exit;
        }
        $this->request = $request;
        $referer = $this->request->server('referer');
        if ($referer && strpos($referer, 'www.*.com') > -1) {
            $this->response('系统检测到您的环境存在安全风险,拒绝了您的访问!', 503);
        }
        // 请求方式检测
        $this->method = strtolower($request->method());
        $this->param = $this->request->param();
        $this->map = $this->request->get();
        $this->_getdata();
        $this->validate();
        $this->authToken();
    }
    /**
     * @name:判断当前状态是否登录
     */
    private function authToken() {
        $ctr = strtolower($this->request->controller());
        $action = strtolower($this->request->action());
        if(isset($this->allow_fun[$ctr]) && (($this->allow_fun[$ctr] == '*') || strpos($this->allow_fun[$ctr], sprintf(',%s,', $action)) > -1)){
            return;
        }
        if (isset($this->param['token']) && !empty($this->param['token'])) {
            $this->accessToken = $this->param['token'];
        } else {
            $this->accessToken = $this->request->header('token');
        }
        if(!Cache::has($this->accessToken)){
            $this->response('请登录!', 202,[]);
        }
        //获取当前的session_id
        $cache = Cache::get($this->accessToken);
        if(!$cache){	//由于机器人没法登陆,需要跳过登陆验证
            $this->response('请登录!', 202,[]);
        }
        $this->user = $cache;
        if($cache){
            $this->uid = $this->user['id'];
        }
    }

    /**
     * 验证
     * @return
     */
    private function validate() {
        if (false === stripos($this->restMethodList, $this->method)) {
            // 请求方式非法 则用默认请求方法
            $this->response('请求方式非法', 415, '只允许' . $this->restMethodList);
        }
        $ctr = strtolower($this->request->controller());
        $action = strtolower($this->request->action());
        $config = Config::get('validate.'.$ctr.'_'.$action);
        if(isset($config) || !empty($config)){
            if(false === stripos($config['allow_method'], $this->method)){
                $this->response('请求方式错误',415,'只允许'.$config['allow_method']);
            }
        }
    }
    /**
     * post公共参数初始化
     */
    private function _getdata() {
        //获取兼容路由参数
        $getdata = array_merge($this->request->param(), $this->request->route());
        foreach ($getdata as $k => $v) {

            if(is_array($v)){
                continue;
            }
            switch ($k) {
                case "order":
                    strpos($v, "-") > -1 ? $v = str_replace("-", " ", $v) : $v = $v . " desc";
                    $this->order = $v;
                    break;
                case "p":
                    $this->p = $v;
                    break;
                case "row":
                    $this->row = $v;
                    break;
                case "name":
                    $this->map[$k] = ['like','%'.$v.'%'];
                    break;
                case "start":
                    $this->_btw[0]                             = $v;
                    $this->_btw[1]                             = date('Y-m-d H:i:s',time());
                    $this->map['created_time'] = ['between', $this->_btw];
                    break;
                case "end":
                    $this->_btw[1]                             = $v;
                    $this->map['created_time'] = ['between', $this->_btw];
                    break;
                case "debug":
                    defined("DEBUG") || define("DEBUG", $v);
                    break;
                case 'XDEBUG_SESSION_START':
                    break;
                default:
                    if (!empty($v)) {
                        $this->map[$k] = $v;
                    }
                    break;
            }
        }
    }

    /**
     * REST 调用
     * @access public
     * @param string $method 方法名
     * @return mixed
     * @throws Exception
     */
    public function _empty($method) {
        $this->response('非法操作=>' . $method, 404);
    }

    /**
     * 通用数据输出
     * @param  $msg
     * @param  $code
     * @param  $data
     * @param  $result_code
     * @param  $type
     * @return
     */
    protected function response($msg, $code = 200, $data = '', $result_code = null, $type = 'json') {
        $result_code === null && $result_code = $code;
        $result = [
            'code' => $result_code,
            'msg' => $msg,
            'data' => $this->_extents($data),
        ];
        $this->setHeader('X_End_Time', $this->request->time());
        $response = Response::create($result, $type)->code($code)->header($this->header);
        throw new \think\exception\HttpResponseException($response);
    }

    /**
     * post方法请求输出数据
     * @param  $data
     * @return
     */
    protected function result($list) {
        $data['data'] = $list;
        $data['page'] = $this->setPages();
        $this->response('success', 200, $data);

    }

    protected function _extents($data) {

        if (empty($data) || !is_array($data)) {
            return empty($data) ? is_array($data) ? [] : '' : $data;
        }
        foreach ($data as $k => $v) {
            if (is_array($v)) {
                $data[$k] = $this->_extents($v);
            } else {
                if (is_null($v)) {
                    $data[$k] = '';
                    continue;
                }
                switch ((string) $k) {
                    case 'file':
                        $data[$k . '_link'] = getFileUrl($v, 'file');
                        break;
                }
            }
        }
        return $data;
    }

    /**
     * 设置header
     * @param  $name
     * @param  $value
     * @return
     */
    protected function setHeader($name, $value) {
        if (is_array($name)) {
            $this->header = array_merge($this->header, $name);
        } else {
            $this->header[$name] = $value;
        }
        return $this;
    }

    /**
     * 请求头设置分页返回参数()
     */
    public function setPage() {

        $page_count = $this->allCount > $this->row ? ceil($this->allCount / $this->row) : 1;
        $this->setHeader('X-Pagination-Total-Count', $this->allCount); //总条数
        $this->setHeader('X-Pagination-Page-Count', $page_count); //总页数
        $this->setHeader('X-Pagination-Current-Page', $this->p); //当前页数
        $this->setHeader('X-Pagination-Per-Page', $this->row); //每页条数
    }

    /**
     * 直接返回设置分页返回参数()
     */
    protected function setPages() {
        $page_count = $this->allCount > $this->row ? ceil($this->allCount / $this->row) : 1;
        $this->header['Total-Count'] = $this->allCount; //总条数
        $this->header['Page-Count'] = $page_count; //总页数
        $this->header['Current-Page'] = $this->p; //当前页数
        $this->header['Per-Page'] = $this->row; //每页条数
        return $this->header;
    }

    //敏感词过滤
    protected function badword($content) {
        $str = str_replace(explode('|', config('sensitive_words')), '***', $content);
        return $str;
    }

}