<?php
namespace daicuo;

class Upload
{
   /**
     * @var string 错误信息
     */
    private static $error = '';

    /*构造函数
    public function __construct($options = [])
    {
     
    }*/
    
    /**
     * 获取错误信息（支持多语言）
     * @return string
     */
    public function getError()
    {
        return self::$error;
    }
    
    /**
     * 批量上传附件
     * @param array $data 写入数据（一维数组） 
     * @param string|array $relation 关联表 
     * @return null|obj 成功时返回obj
     */
    public static function save_all($files=[])
    {
        if(!$files){
            return ['code'=>0,'msg'=>lang('mustIn'),'data'=>'','item'=>''];
        }
        //附件转为数组
        if(!is_array($files)){
            $files = [$files];
        }
        //循环处理上传
        $item = [];
        foreach($files as $key=>$file){
            $item[$key] = self::save($file);
        }
        //返回单个附件
        if( count($item) < 2 ){
            if($item[0]['error']){
                return ['code'=>0,'msg'=>$item[0]['error'],'data'=>$item[0],'item'=>''];
            }else{
                return ['code'=>1,'msg'=>'','data'=>$item[0],'item'=>''];
            }
        }
        //返回多个附件
        return ['code'=>1,'msg'=>'','data'=>'','item'=>$item];
    }
    
    /**
     * 批量删除附件
     * @param array $data 写入数据（一维数组） 
     * @param string|array $relation 关联表 
     * @return null|obj 成功时返回obj
     */
    public static function delete_all($attachments=[])
    {
        if(!$attachments){
            return ['code'=>0,'msg'=>lang('mustIn'),'data'=>''];
        }
        if(is_string($attachments)){
            $attachments = explode(',',$attachments);
        }
        //循环处理上传
        $datas = [];
        foreach($attachments as $key=>$attachment){
            $datas[$attachment] = self::delete($attachment);
        }
        return ['code'=>1,'msg'=>'','datas'=>$datas];
    }
    
    /**
     * 保存一个文件
     * @param obj $file 表单file对象 
     * @return array|false
     */
    public static function save($file='')
    {
        //不是TP的file对象直接退出
        if(!is_object($file)){
            self::$error = lang('mustIn');
            return false;
        }
        //钩子传参定义
        $params = array();
        $params['file']   = $file;//表单file对象
        $params['upload'] = false;//TP上传对象（SplFileObject）
        $params['result'] = false;//返回结果
        unset($file);
        //预埋钩子
        \think\Hook::listen('upload_save_before', $params);
        //添加数据
        if( false == $params['result'] ){
            //验证规则
            $validate = array();
            if( config('common.upload_max_size') ){
                $validate['size'] = self::byte(config('common.upload_max_size'));
            }
            if( config('common.upload_file_ext') ){
                $validate['ext'] = config('common.upload_file_ext');
            }
            if( config('common.upload_mime_type') ){
                $validate['type'] = config('common.upload_mime_type');
            }
            //保存路径
            //$uploadDir = ROOT_PATH.ltrim(config('common.upload_path'), '/');
            $uploadDir = './'.trim(config('common.upload_path'), '/');
            //保存文件名
            $saveName = self::buildSaveName($params['file']);
            //保存文件（移动到服务器的上传目录）
            $params['upload'] = $params['file']->rule(config('common.upload_save_rule'))->validate($validate)->move($uploadDir, $saveName, true);
            //保存失败
            if(!$params['upload']){
                $params['result']['error']      = $params['file']->getError();
            }else{
                $params['result']['error']      = '';
                $params['result']['item']       = [];//文件列表
                $params['result']['attachment'] = str_replace("\\",'/',$params['upload']->getSaveName());//文件保存路径
                $params['result']['url']        = DcUrlAttachment($params['result']['attachment']);//文件访问链接（带处理接口）
                $params['result']['file_path']  = self::filePathUrl($params['result']['attachment']);//文件真实访问路径
                $params['result']['file_name']  = $params['upload']->getFilename();//文件保存名
                $params['result']['old_name']   = $params['upload']->getInfo('name');//文件原始名
                $params['result']['ext']        = $params['upload']->getExtension();//文件后缀
                $params['result']['type']       = $params['upload']->getInfo('type');
                $params['result']['size']       = $params['upload']->getInfo('size');
                $params['result']['slug']       = $params["upload"]->hash('md5');
                //缩略图与水印
                if(substr($params['result']['type'],0,'5') == 'image'){
                    $params['result']['thumb']  = self::thumb($params['result']['attachment']);//缩略图真实路径
                    $params['result']['water']  = self::water($params['result']['attachment']);//水印图真实路径
                }
                //保存的文件列表（不包括上传目录）
                array_push($params['result']['item'], $params['result']['attachment']);
                if($params['result']['thumb']){
                    array_push($params['result']['item'],self::filePathSuffix($params['result']['attachment'],'thumb'));
                }
                if($params['result']['water']){
                    array_push($params['result']['item'],self::filePathSuffix($params['result']['attachment'],'water'));
                }
            }
        }
        //预埋钩子
        \think\Hook::listen('upload_save_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 删除一个文件
     * @param string $attachment 文件保存路径
     * @param string $mimeType 文件类型
     * @return array
     */
    public function delete($attachment='', $mimeType='')
    {
        //钩子传参定义
        $params = array();
        $params['mimeType']   = $mimeType;//文件类型
        $params['attachment'] = $attachment;//删除原始文件
        $params['item']       = [];//删除文件列表
        $params['result']     = [];//删除结果列表
        //预埋钩子
        \think\Hook::listen('upload_delete_before', $params);
        //删除本地附件
        if( !$params['result'] ){
            //定义删除文件列表
            array_push($params['item'], $params['attachment']);
            //删除图像处理
            if(substr($params['mimeType'],0,5) == 'image'){
                //缩略图
                array_push($params['item'],self::filePathSuffix($params['attachment'],'thumb'));
                //水印图
                array_push($params['item'],self::filePathSuffix($params['attachment'],'water'));
            }
            //本地删除
            foreach($params['item'] as $key=>$value){
                array_push($params['result'],@unlink('./'.trim(config('common.upload_path'),'/').'/'.$value));
            }
        }
        //预埋钩子
        \think\Hook::listen('upload_delete_after', $params);
        //返回结果
        return $params['result'];
    }
    
    /**
     * 生成缩略图
     * @param string $filePath 需要处理的图片地址
     * @param int $type 生成缩略图类型（1|2|3|4|5|6）
     * @param int $width 最大宽度
     * @param int $height 最大高度
     * @return bool|string 真实访问地址与false
     */
    public static function thumb($filePath='')
    {
        if($filePath && config('common.upload_thumb_type') && config('common.upload_thumb_width') && config('common.upload_thumb_height')){
            //小图文件名
            $saveName = self::filePathSuffix($filePath);
            //上传目录
            $uploadDir = './'.trim(config('common.upload_path'), '/').'/';
            //判断原始文件
            if(!file_exists($uploadDir.$filePath)){
                return false;
            }
            //裁减图片
            $image    = \think\Image::open($uploadDir.$filePath);
            $image->thumb(config('common.upload_thumb_width'), config('common.upload_thumb_height'), config('common.upload_thumb_type'))->save($uploadDir.$saveName);
            //真实访问路径
            return self::filePathUrl($saveName);
        }
        return false;
    }
    
    /**
     * 添加水印
     * @param string $filePath 需要处理的图片地址
     * @return bool|string 真实访问地址与false
     */
    public static function water($filePath='')
    {
        //水印伴置(0|1|2|3|4|5|6|7|8|9|10)
        if(!config('common.upload_water_locate')){
            return false;
        }
        //图片水印或文字水印
        if(!config('common.upload_water_logo') && !config('common.upload_water_text')){
            return false;
        }
        //水印文件名
        $saveName = self::filePathSuffix($filePath,'water');
        //上传目录
        $uploadDir = './'.trim(config('common.upload_path'), '/').'/';
        //判断原始文件
        if(!file_exists($uploadDir.$filePath)){
            return false;
        }
        //水印位置
        if(config('common.upload_water_locate') == 10){
            $locate = rand(1,9);
        }else{
            $locate = config('common.upload_water_locate');
        }
        //优先图片水印
        if(config('common.upload_water_logo')){
            //水印图片检查
            if(!file_exists('./'.config('common.upload_water_logo'))){
                return false;
            }
            $image = \think\Image::open($uploadDir.$filePath);
            $image->water('./'.config('common.upload_water_logo'), $locate, config('common.upload_water_light'))->save($uploadDir.$saveName);
            //真实路径
            return self::filePathUrl($saveName);
        }
        //文字水印
        if(!file_exists(ROOT_PATH.config('common.upload_water_font'))){
            return false;
        }
        $image = \think\Image::open($uploadDir.$filePath);
        $image->text(config('common.upload_water_text'), ROOT_PATH.config('common.upload_water_font'), config('common.upload_water_size'), config('common.upload_water_color'), $locate, config('common.upload_water_offset'), config('common.upload_water_angle'))->save($uploadDir.$saveName);
        //真实路径
        return self::filePathUrl($saveName);
    }
    
    /**
     * 按原文件名生成带后缀的保存路径
     * @param array $data 写入数据（一维数组） 
     * @param string $max_size 待转化的字符，如:10mb
     * @return string
     */
    public static function filePathSuffix($filePath='', $suffix='thumb')
    {
        $file = pathinfo($filePath);
        return $file['dirname'].'/'.$file['filename'].'_'.$suffix.'.'.$file['extension'];
    }
    
    /**
     * 返回文件的本地真实访问地址
     * @param string $attachment 文件保存路径(20210201/test.png)
     * @return string
     */
    public static function filePathUrl($attachment='')
    {
        return rtrim(config('common.upload_cdn'),'/').DcRoot().trim(config('common.upload_path'),'/').'/'.$attachment;
    }
    
    /**
     * 缩略图开关
     * @return bool
     */
    public static function isThumb()
    {
        if(config('common.upload_thumb_type') && config('common.upload_thumb_width') && config('common.upload_thumb_height')){
            return true;
        }
        return false;
    }
    
    /**
     * 水印开关
     * @return bool
     */
    public static function isWater()
    {
        //水印伴置(0|1|2|3|4|5|6|7|8|9|10)
        if(!config('common.upload_water_locate')){
            return false;
        }
        //图片水印或文字水印
        if(!config('common.upload_water_logo') && !config('common.upload_water_text')){
            return false;
        }
        //
        return true;
    }
    
    /**
     * 转换字节
     * @param array $data 写入数据（一维数组） 
     * @param string $max_size 待转化的字符，如:10mb
     * @return int 字节数
     */
    private static function byte($max_size)
    {
        $max_size = strtolower($max_size);
        preg_match('/([0-9\.]+)(\w+)/', $max_size, $matches);
        $size = $matches ? $matches[1] : $max_size;
        $type = $matches ? strtolower($matches[2]) : 'b';
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        return (int)($size * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0));
    }
    
    /**
     * 自否自动生成文件名
     * @param obj $file TP的文件类
     * @return bool|string true为自动生成,字符串为自定义文件名
     */
    private static function buildSaveName($file)
    {
        //包含/时为自定义文件名
        if($file && count(explode('/',config('common.upload_save_rule'))) > 1){
            $filename = $file->getInfo('name');
            $md5 = md5_file($file->getInfo('tmp_name'));
            $replaceArr = [
                '{year}'     => date("Y"),
                '{mon}'      => date("m"),
                '{day}'      => date("d"),
                '{hour}'     => date("H"),
                '{min}'      => date("i"),
                '{sec}'      => date("s"),
                '{filename}' => substr($filename, 0, 100),
                '{filemd5}'  => $md5,
            ];
            return str_replace(array_keys($replaceArr), array_values($replaceArr), config('common.upload_save_rule'));
        }
        //自动生成条件
        return true;
    }
    
    /**
     * 析构方法，用于关闭文件资源
    public function __destruct(){
        
    }
    */
}