<?php
namespace common\components;
require 'qiniuSDK/autoload.php';
use yii;
use common\components\CHelper;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use Qiniu\Storage\BucketManager;
use Qiniu\Processing\ImageUrlBuilder;
class Upload
{
    public $fileSaveName;
    private $instance;
    private $uploadInfo;
    private $error=0;
    private $save_pre_url = '';
    private $config = array(
        'allowExts'=>array(),
        'allowTypes'=>array(),
        'maxSize'=>'',
        'saveFolder'=>'',
        'nameRule'=>'',
        'type'=>'image',
    );
    public function __get($name){
        if(isset($this->config[$name])) {
            return $this->config[$name];
        }
        return null;
    }

    public function __set($name,$value){
        if(isset($this->config[$name])) {
            $this->config[$name]    =   $value;
        }
    }

    public function __isset($name){
        return isset($this->config[$name]);
    }
    public function __construct($instance=null,$config=array()){
        $this->instance = $instance;
        $this->uploadInfo = $this->object2array($this->instance);
        $this->config = array_merge($this->config,$config);
        $this->config['maxSize'] = $this->config['maxSize']?$this->config['maxSize']:Yii::$app->params['upload_file_max']*1024*1024;
        if($this->config['saveFolder']){
            $this->config['saveFolder'] = UPLOAD_PATH.$this->config['saveFolder'].'/';
        }
        if(!$this->config['allowExts']){
            $this->config['allowExts'] = $this->getAllowExts($this->config['type']);
        }
    }
    private function getAllowExts($type){
        switch($type){
            case 'image':
                return array('bmp','png','gif','jpeg','jpg');
                break;
            case 'file':
                return array('doc','docx','xls','xlsx','ppt','htm','html','txt','zip','rar','gz','bz2');
                break;
            case 'flash':
                return array('swf','flv');
                break;
            default:
                return array('bmp','png','gif','jpeg','jpg');
                break;
        }
    }
    private function object2array($object){
        if(is_object($object)){
            foreach ($object as $key => $value) {
                $array[$key] = $value;
            }
        }else{
            $array = $object;
        }
        return $array;
    }
    /**
     * 检查上传的文件
     * @access private
     * @param array $file 文件信息
     * @return boolean
     */
    private function check($file) {
        if($file['error']!== 0) {
            //文件上传失败
            //捕获错误代码
            $this->error($file['error']);
            return false;
        }
        //文件上传成功，进行自定义规则检查
        //检查文件大小
        if(!$this->checkSize($file['size'])) {
            $this->error = '上传文件大小不符！';
            return false;
        }

        //检查文件Mime类型
        if(!$this->checkType($file['type'])) {
            $this->error = '上传文件MIME类型不允许！';
            return false;
        }
        //检查文件类型
        if(!$this->checkExt($this->getExt($file['name']))) {
            $this->error ='上传文件类型不允许';
            return false;
        }
        //检查是否合法上传
        if(!$this->checkUpload($file['tempName'])) {
            $this->error = '非法上传文件！';
            return false;
        }
        return true;
    }
    /**
     * 获取错误代码信息
     * @access public
     * @param string $errorNo  错误号码
     * @return void
     */
    protected function error($errorNo) {
         switch($errorNo) {
            case 1:
                $this->error = '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值';
                break;
            case 2:
                $this->error = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值';
                break;
            case 3:
                $this->error = '文件只有部分被上传';
                break;
            case 4:
                $this->error = '没有文件被上传';
                break;
            case 6:
                $this->error = '找不到临时文件夹';
                break;
            case 7:
                $this->error = '文件写入失败';
                break;
            default:
                $this->error = '未知上传错误！';
        }
        return ;
    }
    /**
     * 检查上传的文件类型是否合法
     * @access private
     * @param string $type 数据
     * @return boolean
     */
    private function checkType($type) {
        if(!empty($this->allowTypes))
            return in_array(strtolower($type),$this->allowTypes);
        return true;
    }


    /**
     * 检查上传的文件后缀是否合法
     * @access private
     * @param string $ext 后缀名
     * @return boolean
     */
    private function checkExt($ext) {
        if(!empty($this->allowExts))
            return in_array(strtolower($ext),$this->allowExts,true);
        return true;
    }

    /**
     * 检查文件大小是否合法
     * @access private
     * @param integer $size 数据
     * @return boolean
     */
    private function checkSize($size) {
        return !($size > $this->maxSize) || (-1 == $this->maxSize);
    }

    /**
     * 检查文件是否非法提交
     * @access private
     * @param string $filename 文件名
     * @return boolean
     */
    private function checkUpload($filename) {
        return is_uploaded_file($filename);
    }

    /**
     * 取得上传文件的后缀
     * @access private
     * @param string $filename 文件名
     * @return boolean
     */
    private function getExt($filename) {
        $pathinfo = pathinfo($filename);
        return $pathinfo['extension'];
    }

    /**
     * 取得上传文件的信息
     * @access public
     * @return array
     */
    public function getUploadFileInfo() {
        return $this->uploadFileInfo;
    }

    /**
     * 取得最后一次错误信息
     * @access public
     * @return string
     */
    public function getError() {
        return $this->error;
    }
    public function upload(){
        if(!$this->check($this->uploadInfo)){
            return false;
        }
        if(Yii::$app->params['qiniu_open']){
            $this->save_pre_url = 'http://'.Yii::$app->params['qiniu_domain'].'/';
            $this->fileSaveName = rand(1,10000).time().'.'.$this->getExt($this->uploadInfo['name']);
        }else{
            $url = date('Y/m/d').'/';
            if(!$this->nameRule){
                $this->fileSaveName = $url.rand(1,10000).time().'.'.$this->getExt($this->uploadInfo['name']);
            }else{
                $this->fileSaveName = $this->nameRule;
            }
            //创建路径
            $this->saveFolder && CHelper::mkdirs($this->saveFolder.$url);
        }
        return $this->save_pre_url.$this->fileSaveName;
    }
    public function save(){
        if(Yii::$app->params['qiniu_open']){
            $this->saveByQiniu();
        }else{
            $this->instance->saveAs($this->saveFolder.$this->fileSaveName);
        }
    }
    private function initQiniu(){
        $accessKey = Yii::$app->params['qiniu_accessKey'];
        $secretKey = Yii::$app->params['qiniu_secretKey'];
        // 构建鉴权对象
        $auth = new Auth($accessKey, $secretKey);
        return $auth;
    }
    private function saveByQiniu(){
        $auth = $this->initQiniu();
        // 要上传的空间
        $bucket = Yii::$app->params['qiniu_bucket'];
        // 生成上传 Token
        $token = $auth->uploadToken($bucket);
        // 要上传文件的本地路径
        $filePath = $this->uploadInfo['tempName'];
        // 上传到七牛后保存的文件名
        $key = $this->fileSaveName;
        // 初始化 UploadManager 对象并进行文件的上传。
        $uploadMgr = new UploadManager();
        // 调用 UploadManager 的 putFile 方法进行文件的上传。
        list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
        if ($err !== null) {
            $this->error = $err;
            return false;
        } else {
            return true;
        }
    }
    public function delete($file,$folder=''){
        if(false===strpos($file,"http://")){
            @unlink(UPLOAD_PATH.$folder.'/'.$file);
        }else{
            $this->deleteByQiniu($file);
        }
        return true;
    }
    private function deleteByQiniu($file){
        $auth = $this->initQiniu();
        $file = str_replace('http://'.Yii::$app->params['qiniu_domain'].'/','',$file);
        //初始化BucketManager
        $bucketMgr = new BucketManager($auth);
        $err = $bucketMgr->delete(Yii::$app->params['qiniu_bucket'], $file);
        if ($err !== null) {
            $this->error = $err;
            return false;
        } else {
            return true;
        }
    }
}
