<?php
namespace KIF;

/**
 * @name 单文件上传类
 * @desc 本控件主要对文件上传过程的监控,需要时可自动创建目标目录的上层目录。文件保存的路径和命名规则不在控件内设置。
 * @author lishuming@kimiss.com
 * 使用方法
 * $objUpload = new \KIF\Upload($custom_config);
 * $objUpload->execute();
 * 
 * @param array 自定义配置参数
 * $custom_config = array(
 * 		'save_path'	=> '/tmp/dir/', (必填)文件保存路径
 * 		'save_filename'	=> 'name', (选填)保存文件名。不需要添加文件后缀。留空时使用原名
 * 		'file_type'	=> '', (必填)上传文件类型
 * 		'field'	=> 'myFile', (必填)客户端文件上传控件名,input 中的表单名
 * 		...
 * );
 */

use KIF\Data\ResultWrapper;

class Upload {
	
	/**
	 * 上传文件控件配置
	 * @var array
	 */
	private $config = array();
	
	/**
	 * 上传文件控件默认配置
	 * @var array
	 */
	private $default_config = array(
		'save_path'		=> '',		//文件保存目录路径。格式:/tmp/dir/
		'save_filename'	=> null,		//保存文件名。默认为空时使用原名
		'file_type'		=> '', //上传文件的类型。可选项有:image,flash,media,file
		'allow_ext_arr'	=> array(	//定义允许上传文件的扩展名
			'image'		=> array('gif', 'jpg', 'jpeg', 'png', 'bmp'),
			'flash'		=> array('swf', 'flv'),
			'media'		=> array('swf', 'flv', 'mp3', 'wav', 'wma', 'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb'),
			'file'		=> array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2'),
		),
		'max_size'		=> 1000000,	//允许上传最大文件的大小 (单位字节)
		'field'			=> '',		//客户端文件上传控件名,input 中的表单名
		'dchmod'		=> 0777,	//新创建的目录权限设置
		'fchmod'		=> 0777,	//新创建的文件权限设置
	);
	
	public function __construct(/*自定义配置*/$custom_config = array()) {
		if (!empty($custom_config)) {
			$this->config = array_merge($this->default_config, $custom_config);
		} else {
			$this->config = $this->default_config;
		}
	}
	
	public function execute() {
		if (!$this->config['save_path']) {
			return ResultWrapper::fail('请设置文件保存路径。');
		}
		$save_path = rtrim($this->config['save_path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
		
		if (!$this->config['file_type']) {
			return ResultWrapper::fail('请设置上传文件类型。');
		}
		$file_type = $this->config['file_type'];
		
		if (!$this->config['field']) {
			return ResultWrapper::fail('请设置客户端文件上传控件名。');
		}
		$field = $this->config['field'];
		
		$ext_arr = $this->config['allow_ext_arr'];
		
		$max_size = $this->config['max_size'];
		
		if (empty($_FILES)) {
			return ResultWrapper::fail('没有需要上传的文件。');
		}
		
		#保存文件名
		if (!$this->config['save_filename']) {
			$save_filename = $_FILES[$field]['name'];
		}
		$save_filename = $this->config['save_filename'];
		
		#原文件名
		$file_name = $_FILES[$field]['name'];
		
		#检查文件名
		if (!$file_name) {
			return ResultWrapper::fail('请选择上传文件。');
		}
		
		#服务器上临时文件名
		$tmp_name = $_FILES[$field]['tmp_name'];
		
		#文件大小
		$file_size = $_FILES[$field]['size'];
		
		#检查是否已上传
		if (@is_uploaded_file($tmp_name) === false) {
			return ResultWrapper::fail("临时文件可能不是上传文件。");
		}
		
		#检查文件大小
		if ($file_size > $max_size) {
			return ResultWrapper::fail("上传文件大小超过限制。");
		}
		
		#获得文件扩展名
		$file_ext = $this->getExtension($file_name);
		#检查扩展名
		if (in_array($file_ext, $ext_arr[$file_type]) === false) {
			return ResultWrapper::fail("上传文件扩展名是不允许的扩展名。");
		}
		
		#检查目录
		if (@is_dir($save_path) === false) {
			#创建目录
			if (!mkdir($save_path, intval($this->config['dchmod']), true)) {
				return ResultWrapper::fail("创建目录失败:{$save_path}");
			}
		}
		
		#检查目录写权限
		if (@is_writable($save_path) === false) {
			return ResultWrapper::fail("上传目录没有写权限。");
		}
		
		#移动文件
		$file_path = $save_path . $save_filename . '.' . $file_ext;
		if (move_uploaded_file($tmp_name, $file_path) === false) {
			return ResultWrapper::fail("上传文件失败。");
		}
		
		@chmod($file_path, intval($this->config['fchmod']));
		
		return ResultWrapper::success(array(
			'file_path'	=> $file_path,
		));
	}
	
	/**
	 * 获取文件扩展名
	 * @param string $filename
	 * @return string
	 */
	static public function getExtension($filename) {
		$temp_arr = explode(".", $filename);
		$file_ext = array_pop($temp_arr);
		$file_ext = trim($file_ext);
		return strtolower($file_ext);
	}
	
}