diff --git a/Library/Think/Auto.php b/Library/Org/auto.php similarity index 100% rename from Library/Think/Auto.php rename to Library/Org/auto.php diff --git a/Library/Think/Controller/Amf.php b/Library/Org/controller/Amf.php similarity index 100% rename from Library/Think/Controller/Amf.php rename to Library/Org/controller/Amf.php diff --git a/Library/Think/Controller/Phprpc.php b/Library/Org/controller/Phprpc.php similarity index 100% rename from Library/Think/Controller/Phprpc.php rename to Library/Org/controller/Phprpc.php diff --git a/Library/Think/Controller/Rest.php b/Library/Org/controller/Rest.php similarity index 100% rename from Library/Think/Controller/Rest.php rename to Library/Org/controller/Rest.php diff --git a/Library/Org/crypt.php b/Library/Org/crypt.php new file mode 100644 index 00000000..393b93e0 --- /dev/null +++ b/Library/Org/crypt.php @@ -0,0 +1,74 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +class Crypt { + /** + * 加密字符串 + * @access public + * @param string $str 字符串 + * @param string $key 加密key + * @return string + */ + static public function encrypt($data,$key,$expire=0){ + $key = md5($key); + $data = base64_encode($data); + $x = 0; + $len = strlen($data); + $l = strlen($key); + $char = ''; + for ($i = 0; $i< $len; $i++) { + if ($x == $l) $x = 0; + $char .=substr($key, $x, 1); + $x++; + } + $str = sprintf('%010d', $expire ? $expire + time() : 0); + for ($i=0; $i< $len; $i++) { + $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256); + } + return str_replace('=', '', base64_encode($str)); + } + + /** + * 解密字符串 + * @access public + * @param string $str 字符串 + * @param string $key 加密key + * @return string + */ + static public function decrypt($data,$key){ + $key = md5($key); + $x = 0; + $data = base64_decode($data); + $expire = substr($data,0,10); + $data = substr($data,10); + if($expire > 0 && $expire +// +---------------------------------------------------------------------- + +namespace Think; + +class Filter { + //html标签设置 + static public $htmlTags = [ + 'allow' => 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a', + 'ban' => 'html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml', + ]; + + static public function filter($data,$filter,$option=''){ + return filter_var($data,is_int($filter)?$filter:filter_id($filter),$option); + } + + static private function filter_input($type,$name,$filter,$options=''){ + return filter_input($type,$name,is_int($filter)?$filter:filter_id($filter),$option); + } + + static public function get($name,$filter,$option=''){ + return self::filter_input(INPUT_GET,$name,$filter,$option); + } + + static public function post($name,$filter,$option=''){ + return self::filter_input(INPUT_POST,$name,$filter,$option); + } + + static public function cookie($name,$filter,$option=''){ + return self::filter_input(INPUT_COOKIE,$name,$filter,$option); + } + + static public function server($name,$filter,$option=''){ + return self::filter_input(INPUT_SERVER,$name,$filter,$option); + } + + /** + * 处理字符串,以便可以正常进行搜索 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function forSearch($string) { + return str_replace( ['%','_'], ['\%','\_'], $string ); + } + + /** + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function forShow($string) { + return self::nl2Br( self::hsc($string) ); + } + + /** + * 处理纯文本数据,以便在textarea标签中显示 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function forTarea($string) { + return str_ireplace([''], ['<textarea>','</textarea>'], $string); + } + + /** + * 将数据中的单引号和双引号进行转义 + * @access public + * @param string $text 要处理的字符串 + * @return string + */ + static public function forTag($string) { + return str_replace(['"',"'"], ['"','''], $string); + } + + /** + * 把换行转换为
标签 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function nl2Br($string) { + return nl2Br($string); + } + + /** + * 如果 magic_quotes_gpc 为关闭状态,这个函数可以转义字符串 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static public function addSlashes($string) { + return addslashes($string); + } + + /** + * 用于在textbox表单中显示html代码 + * @access public + * @param string $string 要处理的字符串 + * @return string + */ + static function hsc($string) { + return preg_replace(["/&/i", "/ /i"], ['&', '&nbsp;'], htmlspecialchars($string, ENT_QUOTES)); + } + + /** + * 是hsc()方法的逆操作 + * @access public + * @param string $text 要处理的字符串 + * @return string + */ + static function undoHsc($text) { + return preg_replace(["/>/i", "/</i", "/"/i", "/'/i", '/&nbsp;/i'], [">", "<", "\"", "'", " "], $text); + } + + /** + * 输出安全的html,用于过滤危险代码 + * @access public + * @param string $text 要处理的字符串 + * @param mixed $allowTags 允许的标签列表,如 table|td|th|td + * @return string + */ + static public function safeHtml($text, $allowTags = null) { + $text = trim($text); + //完全过滤注释 + $text = preg_replace('//','',$text); + //完全过滤动态代码 + $text = preg_replace('/<\?|\?'.'>/','',$text); + //完全过滤js + $text = preg_replace('//','',$text); + + $text = str_replace('[','[',$text); + $text = str_replace(']',']',$text); + $text = str_replace('|','|',$text); + //过滤换行符 + $text = preg_replace('/\r?\n/','',$text); + //br + $text = preg_replace('//i','[br]',$text); + $text = preg_replace('/(\[br\]\s*){10,}/i','[br]',$text); + //过滤危险的属性,如:过滤on事件lang js + while(preg_match('/(<[^><]+)(lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){ + $text=str_replace($mat[0],$mat[1],$text); + } + while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){ + $text=str_replace($mat[0],$mat[1].$mat[3],$text); + } + if( empty($allowTags) ) { $allowTags = self::$htmlTags['allow']; } + //允许的HTML标签 + $text = preg_replace('/<('.$allowTags.')( [^><\[\]]*)>/i','[\1\2]',$text); + //过滤多余html + if ( empty($banTag) ) { $banTag = self::$htmlTags['ban']; } + $text = preg_replace('/<\/?('.$banTag.')[^><]*>/i','',$text); + //过滤合法的html标签 + while(preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i',$text,$mat)){ + $text=str_replace($mat[0],str_replace('>',']',str_replace('<','[',$mat[0])),$text); + } + //转换引号 + while(preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i',$text,$mat)){ + $text=str_replace($mat[0],$mat[1].'|'.$mat[3].'|'.$mat[4],$text); + } + //空属性转换 + $text = str_replace('\'\'','||',$text); + $text = str_replace('""','||',$text); + //过滤错误的单个引号 + while(preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i',$text,$mat)){ + $text=str_replace($mat[0],str_replace($mat[1],'',$mat[0]),$text); + } + //转换其它所有不合法的 < > + $text = str_replace('<','<',$text); + $text = str_replace('>','>',$text); + $text = str_replace('"','"',$text); + //反转换 + $text = str_replace('[','<',$text); + $text = str_replace(']','>',$text); + $text = str_replace('|','"',$text); + //过滤多余空格 + $text = str_replace(' ',' ',$text); + return $text; + } + + /** + * 删除html标签,得到纯文本。可以处理嵌套的标签 + * @access public + * @param string $string 要处理的html + * @return string + */ + static public function deleteHtmlTags($string) { + while(strstr($string, '>')) { + $currentBeg = strpos($string, '<'); + $currentEnd = strpos($string, '>'); + $tmpStringBeg = @substr($string, 0, $currentBeg); + $tmpStringEnd = @substr($string, $currentEnd + 1, strlen($string)); + $string = $tmpStringBeg.$tmpStringEnd; + } + return $string; + } + + /** + * 处理文本中的换行 + * @access public + * @param string $string 要处理的字符串 + * @param mixed $br 对换行的处理, + * false:去除换行;true:保留原样;string:替换成string + * @return string + */ + static public function nl2($string, $br = '
') { + if ($br == false) { + $string = preg_replace("/(\015\012)|(\015)|(\012)/", '', $string); + } elseif ($br != true){ + $string = preg_replace("/(\015\012)|(\015)|(\012)/", $br, $string); + } + return $string; + } +} diff --git a/Library/Org/image.php b/Library/Org/image.php new file mode 100644 index 00000000..3db9b3cc --- /dev/null +++ b/Library/Org/image.php @@ -0,0 +1,61 @@ + +// +---------------------------------------------------------------------- + +namespace Think; + +/* 缩略图相关常量定义 */ +define('THINKIMAGE_THUMB_SCALING', 1); //常量,标识缩略图等比例缩放类型 +define('THINKIMAGE_THUMB_FILLED', 2); //常量,标识缩略图缩放后填充类型 +define('THINKIMAGE_THUMB_CENTER', 3); //常量,标识缩略图居中裁剪类型 +define('THINKIMAGE_THUMB_NORTHWEST', 4); //常量,标识缩略图左上角裁剪类型 +define('THINKIMAGE_THUMB_SOUTHEAST', 5); //常量,标识缩略图右下角裁剪类型 +define('THINKIMAGE_THUMB_FIXED', 6); //常量,标识缩略图固定尺寸缩放类型 + +/* 水印相关常量定义 */ +define('THINKIMAGE_WATER_NORTHWEST', 1); //常量,标识左上角水印 +define('THINKIMAGE_WATER_NORTH', 2); //常量,标识上居中水印 +define('THINKIMAGE_WATER_NORTHEAST', 3); //常量,标识右上角水印 +define('THINKIMAGE_WATER_WEST', 4); //常量,标识左居中水印 +define('THINKIMAGE_WATER_CENTER', 5); //常量,标识居中水印 +define('THINKIMAGE_WATER_EAST', 6); //常量,标识右居中水印 +define('THINKIMAGE_WATER_SOUTHWEST', 7); //常量,标识左下角水印 +define('THINKIMAGE_WATER_SOUTH', 8); //常量,标识下居中水印 +define('THINKIMAGE_WATER_SOUTHEAST', 9); //常量,标识右下角水印 + +/** + * 图片处理驱动类,可配置图片处理库 + * 目前支持GD库和imagick + * @author 麦当苗儿 + */ +class Image { + /** + * 图片资源 + * @var resource + */ + private static $im; + + /** + * 初始化方法,用于实例化一个图片处理对象 + * @param string $type 要使用的类库,默认使用GD库 + */ + static public function init($type = 'Gd', $imgname = null){ + /* 引入处理库,实例化图片处理对象 */ + $class = '\\Think\\Image\\Driver\\'.ucwords($type); + self::$im = new $class($imgname); + return self::$im; + } + + // 调用驱动类的方法 + static public function __callStatic($method, $params){ + self::$im || self::init(); + return call_user_func_array([self::$im, $method], $params); + } +} diff --git a/Library/Org/image/Driver/Gd.php b/Library/Org/image/Driver/Gd.php new file mode 100644 index 00000000..34facecd --- /dev/null +++ b/Library/Org/image/Driver/Gd.php @@ -0,0 +1,549 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Image\Driver; + +class Gd{ + /** + * 图像资源对象 + * @var resource + */ + private $im; + private $gif; + /** + * 图像信息,包括width,height,type,mime,size + * @var array + */ + private $info; + + /** + * 构造方法,可用于打开一张图像 + * @param string $imgname 图像路径 + */ + public function __construct($imgname = null) { + $imgname && $this->open($imgname); + } + + /** + * 打开一张图像 + * @param string $imgname 图像路径 + */ + public function open($imgname){ + //检测图像文件 + if(!is_file($imgname)) throw new \Exception('不存在的图像文件'); + + //获取图像信息 + $info = getimagesize($imgname); + + //检测图像合法性 + if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){ + throw new \Exception('非法图像文件'); + } + + //设置图像信息 + $this->info = [ + 'width' => $info[0], + 'height' => $info[1], + 'type' => image_type_to_extension($info[2], false), + 'mime' => $info['mime'], + ]; + + //销毁已存在的图像 + empty($this->im) || imagedestroy($this->im); + + //打开图像 + if('gif' == $this->info['type']){ + $class = '\\Think\\Image\\Driver\\Gif'; + $this->gif = new $class($imgname); + $this->im = imagecreatefromstring($this->gif->image()); + } else { + $fun = "imagecreatefrom{$this->info['type']}"; + $this->im = $fun($imgname); + } + return $this; + } + + /** + * 保存图像 + * @param string $imgname 图像保存名称 + * @param string $type 图像类型 + * @param boolean $interlace 是否对JPEG类型图像设置隔行扫描 + */ + public function save($imgname, $type = null, $interlace = true){ + if(empty($this->im)) throw new \Exception('没有可以被保存的图像资源'); + + //自动获取图像类型 + if(is_null($type)){ + $type = $this->info['type']; + } else { + $type = strtolower($type); + } + + //JPEG图像设置隔行扫描 + if('jpeg' == $type || 'jpg' == $type){ + $type = 'jpeg'; + imageinterlace($this->im, $interlace); + } + + //保存图像 + if('gif' == $type && !empty($this->gif)){ + $this->gif->save($imgname); + } else { + $fun = "image{$type}"; + $fun($this->im, $imgname); + } + return $this; + } + + /** + * 返回图像宽度 + * @return integer 图像宽度 + */ + public function width(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['width']; + } + + /** + * 返回图像高度 + * @return integer 图像高度 + */ + public function height(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['height']; + } + + /** + * 返回图像类型 + * @return string 图像类型 + */ + public function type(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['type']; + } + + /** + * 返回图像MIME类型 + * @return string 图像MIME类型 + */ + public function mime(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['mime']; + } + + /** + * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度 + * @return array 图像尺寸 + */ + public function size(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return [$this->info['width'], $this->info['height']]; + } + + /** + * 裁剪图像 + * @param integer $w 裁剪区域宽度 + * @param integer $h 裁剪区域高度 + * @param integer $x 裁剪区域x坐标 + * @param integer $y 裁剪区域y坐标 + * @param integer $width 图像保存宽度 + * @param integer $height 图像保存高度 + */ + public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){ + if(empty($this->im)) throw new \Exception('没有可以被裁剪的图像资源'); + + //设置保存尺寸 + empty($width) && $width = $w; + empty($height) && $height = $h; + + do { + //创建新图像 + $img = imagecreatetruecolor($width, $height); + // 调整默认颜色 + $color = imagecolorallocate($img, 255, 255, 255); + imagefill($img, 0, 0, $color); + + //裁剪 + imagecopyresampled($img, $this->im, 0, 0, $x, $y, $width, $height, $w, $h); + imagedestroy($this->im); //销毁原图 + + //设置新图像 + $this->im = $img; + } while(!empty($this->gif) && $this->gifNext()); + + $this->info['width'] = $width; + $this->info['height'] = $height; + return $this; + } + + /** + * 生成缩略图 + * @param integer $width 缩略图最大宽度 + * @param integer $height 缩略图最大高度 + * @param integer $type 缩略图裁剪类型 + */ + public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){ + if(empty($this->im)) throw new \Exception('没有可以被缩略的图像资源'); + + //原图宽度和高度 + $w = $this->info['width']; + $h = $this->info['height']; + + /* 计算缩略图生成的必要参数 */ + switch ($type) { + /* 等比例缩放 */ + case THINKIMAGE_THUMB_SCALING: + //原图尺寸小于缩略图尺寸则不进行缩略 + if($w < $width && $h < $height) return; + + //计算缩放比例 + $scale = min($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $width = $w * $scale; + $height = $h * $scale; + break; + + /* 居中裁剪 */ + case THINKIMAGE_THUMB_CENTER: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = ($this->info['width'] - $w)/2; + $y = ($this->info['height'] - $h)/2; + break; + + /* 左上角裁剪 */ + case THINKIMAGE_THUMB_NORTHWEST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $w = $width/$scale; + $h = $height/$scale; + break; + + /* 右下角裁剪 */ + case THINKIMAGE_THUMB_SOUTHEAST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = $this->info['width'] - $w; + $y = $this->info['height'] - $h; + break; + + /* 填充 */ + case THINKIMAGE_THUMB_FILLED: + //计算缩放比例 + if($w < $width && $h < $height){ + $scale = 1; + } else { + $scale = min($width/$w, $height/$h); + } + + //设置缩略图的坐标及宽度和高度 + $neww = $w * $scale; + $newh = $h * $scale; + $posx = ($width - $w * $scale)/2; + $posy = ($height - $h * $scale)/2; + + do{ + //创建新图像 + $img = imagecreatetruecolor($width, $height); + // 调整默认颜色 + $color = imagecolorallocate($img, 255, 255, 255); + imagefill($img, 0, 0, $color); + + //裁剪 + imagecopyresampled($img, $this->im, $posx, $posy, $x, $y, $neww, $newh, $w, $h); + imagedestroy($this->im); //销毁原图 + $this->im = $img; + } while(!empty($this->gif) && $this->gifNext()); + + $this->info['width'] = $width; + $this->info['height'] = $height; + return $this; + + /* 固定 */ + case THINKIMAGE_THUMB_FIXED: + $x = $y = 0; + break; + + default: + throw new \Exception('不支持的缩略图裁剪类型'); + } + + /* 裁剪图像 */ + $this->crop($w, $h, $x, $y, $width, $height); + return $this; + } + + /** + * 添加水印 + * @param string $source 水印图片路径 + * @param integer $locate 水印位置 + * @param integer $alpha 水印透明度 + */ + public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被添加水印的图像资源'); + if(!is_file($source)) throw new \Exception('水印图像不存在'); + + //获取水印图像信息 + $info = getimagesize($source); + if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){ + throw new \Exception('非法水印文件'); + } + + //创建水印图像资源 + $fun = 'imagecreatefrom' . image_type_to_extension($info[2], false); + $water = $fun($source); + + //设定水印图像的混色模式 + imagealphablending($water, true); + + /* 设定水印位置 */ + switch ($locate) { + /* 右下角水印 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x = $this->info['width'] - $info[0]; + $y = $this->info['height'] - $info[1]; + break; + + /* 左下角水印 */ + case THINKIMAGE_WATER_SOUTHWEST: + $x = 0; + $y = $this->info['height'] - $info[1]; + break; + + /* 左上角水印 */ + case THINKIMAGE_WATER_NORTHWEST: + $x = $y = 0; + break; + + /* 右上角水印 */ + case THINKIMAGE_WATER_NORTHEAST: + $x = $this->info['width'] - $info[0]; + $y = 0; + break; + + /* 居中水印 */ + case THINKIMAGE_WATER_CENTER: + $x = ($this->info['width'] - $info[0])/2; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 下居中水印 */ + case THINKIMAGE_WATER_SOUTH: + $x = ($this->info['width'] - $info[0])/2; + $y = $this->info['height'] - $info[1]; + break; + + /* 右居中水印 */ + case THINKIMAGE_WATER_EAST: + $x = $this->info['width'] - $info[0]; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 上居中水印 */ + case THINKIMAGE_WATER_NORTH: + $x = ($this->info['width'] - $info[0])/2; + $y = 0; + break; + + /* 左居中水印 */ + case THINKIMAGE_WATER_WEST: + $x = 0; + $y = ($this->info['height'] - $info[1])/2; + break; + + default: + /* 自定义水印坐标 */ + if(is_array($locate)){ + list($x, $y) = $locate; + } else { + throw new \Exception('不支持的水印位置类型'); + } + } + + do{ + //添加水印 + $src = imagecreatetruecolor($info[0], $info[1]); + // 调整默认颜色 + $color = imagecolorallocate($src, 255, 255, 255); + imagefill($src, 0, 0, $color); + + imagecopy($src, $this->im, 0, 0, $x, $y, $info[0], $info[1]); + imagecopy($src, $water, 0, 0, 0, 0, $info[0], $info[1]); + imagecopymerge($this->im, $src, $x, $y, 0, 0, $info[0], $info[1], 100); + + //销毁零时图片资源 + imagedestroy($src); + } while(!empty($this->gif) && $this->gifNext()); + + //销毁水印资源 + imagedestroy($water); + return $this; + } + + /** + * 图像添加文字 + * @param string $text 添加的文字 + * @param string $font 字体路径 + * @param integer $size 字号 + * @param string $color 文字颜色 + * @param integer $locate 文字写入位置 + * @param integer $offset 文字相对当前位置的偏移量 + * @param integer $angle 文字倾斜角度 + */ + public function text($text, $font, $size, $color = '#00000000', + $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被写入文字的图像资源'); + if(!is_file($font)) throw new \Exception("不存在的字体文件:{$font}"); + + //获取文字信息 + $info = imagettfbbox($size, $angle, $font, $text); + $minx = min($info[0], $info[2], $info[4], $info[6]); + $maxx = max($info[0], $info[2], $info[4], $info[6]); + $miny = min($info[1], $info[3], $info[5], $info[7]); + $maxy = max($info[1], $info[3], $info[5], $info[7]); + + /* 计算文字初始坐标和尺寸 */ + $x = $minx; + $y = abs($miny); + $w = $maxx - $minx; + $h = $maxy - $miny; + + /* 设定文字位置 */ + switch ($locate) { + /* 右下角文字 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x += $this->info['width'] - $w; + $y += $this->info['height'] - $h; + break; + + /* 左下角文字 */ + case THINKIMAGE_WATER_SOUTHWEST: + $y += $this->info['height'] - $h; + break; + + /* 左上角文字 */ + case THINKIMAGE_WATER_NORTHWEST: + // 起始坐标即为左上角坐标,无需调整 + break; + + /* 右上角文字 */ + case THINKIMAGE_WATER_NORTHEAST: + $x += $this->info['width'] - $w; + break; + + /* 居中文字 */ + case THINKIMAGE_WATER_CENTER: + $x += ($this->info['width'] - $w)/2; + $y += ($this->info['height'] - $h)/2; + break; + + /* 下居中文字 */ + case THINKIMAGE_WATER_SOUTH: + $x += ($this->info['width'] - $w)/2; + $y += $this->info['height'] - $h; + break; + + /* 右居中文字 */ + case THINKIMAGE_WATER_EAST: + $x += $this->info['width'] - $w; + $y += ($this->info['height'] - $h)/2; + break; + + /* 上居中文字 */ + case THINKIMAGE_WATER_NORTH: + $x += ($this->info['width'] - $w)/2; + break; + + /* 左居中文字 */ + case THINKIMAGE_WATER_WEST: + $y += ($this->info['height'] - $h)/2; + break; + + default: + /* 自定义文字坐标 */ + if(is_array($locate)){ + list($posx, $posy) = $locate; + $x += $posx; + $y += $posy; + } else { + throw new \Exception('不支持的文字位置类型'); + } + } + + /* 设置偏移量 */ + if(is_array($offset)){ + $offset = array_map('intval', $offset); + list($ox, $oy) = $offset; + } else{ + $offset = intval($offset); + $ox = $oy = $offset; + } + + /* 设置颜色 */ + if(is_string($color) && 0 === strpos($color, '#')){ + $color = str_split(substr($color, 1), 2); + $color = array_map('hexdec', $color); + if(empty($color[3]) || $color[3] > 127){ + $color[3] = 0; + } + } elseif (!is_array($color)) { + throw new \Exception('错误的颜色值'); + } + + do{ + /* 写入文字 */ + $col = imagecolorallocatealpha($this->im, $color[0], $color[1], $color[2], $color[3]); + imagettftext($this->im, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text); + } while(!empty($this->gif) && $this->gifNext()); + return $this; + } + + /* 切换到GIF的下一帧并保存当前帧,内部使用 */ + private function gifNext(){ + ob_start(); + ob_implicit_flush(0); + imagegif($this->im); + $img = ob_get_clean(); + + $this->gif->image($img); + $next = $this->gif->nextImage(); + + if($next){ + $this->im = imagecreatefromstring($next); + return $next; + } else { + $this->im = imagecreatefromstring($this->gif->image()); + return false; + } + } + + /** + * 析构方法,用于销毁图像资源 + */ + public function __destruct() { + empty($this->im) || imagedestroy($this->im); + } +} diff --git a/Library/Org/image/Driver/Gif.php b/Library/Org/image/Driver/Gif.php new file mode 100644 index 00000000..f3f6b6bc --- /dev/null +++ b/Library/Org/image/Driver/Gif.php @@ -0,0 +1,570 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Image\Driver; + +class Gif{ + /** + * GIF帧列表 + * @var array + */ + private $frames = []; + + /** + * 每帧等待时间列表 + * @var array + */ + private $delays = []; + + /** + * 构造方法,用于解码GIF图片 + * @param string $src GIF图片数据 + * @param string $mod 图片数据类型 + */ + public function __construct($src = null, $mod = 'url') { + if(!is_null($src)){ + if('url' == $mod && is_file($src)){ + $src = file_get_contents($src); + } + + /* 解码GIF图片 */ + try{ + $de = new GIFDecoder($src); + $this->frames = $de->GIFGetFrames(); + $this->delays = $de->GIFGetDelays(); + } catch(Exception $e){ + throw new \Exception("解码GIF图片出错"); + } + } + } + + /** + * 设置或获取当前帧的数据 + * @param string $stream 二进制数据流 + * @return boolean 获取到的数据 + */ + public function image($stream = null){ + if(is_null($stream)){ + $current = current($this->frames); + return false === $current ? reset($this->frames) : $current; + } else { + $this->frames[key($this->frames)] = $stream; + } + } + + /** + * 将当前帧移动到下一帧 + * @return string 当前帧数据 + */ + public function nextImage(){ + return next($this->frames); + } + + /** + * 编码并保存当前GIF图片 + * @param string $gifname 图片名称 + */ + public function save($gifname){ + $gif = new GIFEncoder($this->frames, $this->delays, 0, 2, 0, 0, 0, 'bin'); + file_put_contents($gifname, $gif->GetAnimation()); + } + +} + + +/* +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: GIFEncoder Version 2.0 by László Zsidi, http://gifs.hu +:: +:: This class is a rewritten 'GifMerge.class.php' version. +:: +:: Modification: +:: - Simplified and easy code, +:: - Ultra fast encoding, +:: - Built-in errors, +:: - Stable working +:: +:: +:: Updated at 2007. 02. 13. '00.05.AM' +:: +:: +:: +:: Try on-line GIFBuilder Form demo based on GIFEncoder. +:: +:: http://gifs.hu/phpclasses/demos/GifBuilder/ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +*/ + +Class GIFEncoder { + var $GIF = "GIF89a"; /* GIF header 6 bytes */ + var $VER = "GIFEncoder V2.05"; /* Encoder version */ + + var $BUF = array ( ); + var $LOP = 0; + var $DIS = 2; + var $COL = -1; + var $IMG = -1; + + var $ERR = array ( + 'ERR00'=>"Does not supported function for only one image!", + 'ERR01'=>"Source is not a GIF image!", + 'ERR02'=>"Unintelligible flag ", + 'ERR03'=>"Does not make animation from animated GIF source", + ); + + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFEncoder... + :: + */ + function GIFEncoder ( + $GIF_src, $GIF_dly, $GIF_lop, $GIF_dis, + $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod + ) { + if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_tim ) ) { + printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] ); + exit ( 0 ); + } + $this->LOP = ( $GIF_lop > -1 ) ? $GIF_lop : 0; + $this->DIS = ( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2; + $this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ? + ( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1; + + for ( $i = 0; $i < count ( $GIF_src ); $i++ ) { + if ( strToLower ( $GIF_mod ) == "url" ) { + $this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) ); + } + else if ( strToLower ( $GIF_mod ) == "bin" ) { + $this->BUF [ ] = $GIF_src [ $i ]; + } + else { + printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod ); + exit ( 0 ); + } + if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) { + printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] ); + exit ( 0 ); + } + for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = true; $k; $j++ ) { + switch ( $this->BUF [ $i ] { $j } ) { + case "!": + if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) { + printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) ); + exit ( 0 ); + } + break; + case ";": + $k = FALSE; + break; + } + } + } + GIFEncoder::GIFAddHeader ( ); + for ( $i = 0; $i < count ( $this->BUF ); $i++ ) { + GIFEncoder::GIFAddFrames ( $i, $GIF_dly [ $i ] ); + } + GIFEncoder::GIFAddFooter ( ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddHeader... + :: + */ + function GIFAddHeader ( ) { + $cmap = 0; + + if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) { + $cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ); + + $this->GIF .= substr ( $this->BUF [ 0 ], 6, 7 ); + $this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap ); + $this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFEncoder::GIFWord ( $this->LOP ) . "\0"; + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddFrames... + :: + */ + function GIFAddFrames ( $i, $d ) { + + $Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); + + $Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1; + $Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end ); + + $Global_len = 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); + $Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); + + $Global_rgb = substr ( $this->BUF [ 0 ], 13, + 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ) ); + $Locals_rgb = substr ( $this->BUF [ $i ], 13, + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ); + + $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 0 ) . + chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0"; + + if ( $this->COL > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) { + for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) { + if ( + ord ( $Locals_rgb { 3 * $j + 0 } ) == ( ( $this->COL >> 16 ) & 0xFF ) && + ord ( $Locals_rgb { 3 * $j + 1 } ) == ( ( $this->COL >> 8 ) & 0xFF ) && + ord ( $Locals_rgb { 3 * $j + 2 } ) == ( ( $this->COL >> 0 ) & 0xFF ) + ) { + $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 1 ) . + chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . chr ( $j ) . "\x0"; + break; + } + } + } + switch ( $Locals_tmp { 0 } ) { + case "!": + $Locals_img = substr ( $Locals_tmp, 8, 10 ); + $Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 ); + break; + case ",": + $Locals_img = substr ( $Locals_tmp, 0, 10 ); + $Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 ); + break; + } + if ( ord ( $this->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) { + if ( $Global_len == $Locals_len ) { + if ( GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len ) ) { + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); + } + else { + $byte = ord ( $Locals_img { 9 } ); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); + $Locals_img { 9 } = chr ( $byte ); + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); + } + } + else { + $byte = ord ( $Locals_img { 9 } ); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); + $Locals_img { 9 } = chr ( $byte ); + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); + } + } + else { + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); + } + $this->IMG = 1; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddFooter... + :: + */ + function GIFAddFooter ( ) { + $this->GIF .= ";"; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFBlockCompare... + :: + */ + function GIFBlockCompare ( $GlobalBlock, $LocalBlock, $Len ) { + + for ( $i = 0; $i < $Len; $i++ ) { + if ( + $GlobalBlock { 3 * $i + 0 } != $LocalBlock { 3 * $i + 0 } || + $GlobalBlock { 3 * $i + 1 } != $LocalBlock { 3 * $i + 1 } || + $GlobalBlock { 3 * $i + 2 } != $LocalBlock { 3 * $i + 2 } + ) { + return ( 0 ); + } + } + + return ( 1 ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFWord... + :: + */ + function GIFWord ( $int ) { + + return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GetAnimation... + :: + */ + function GetAnimation ( ) { + return ( $this->GIF ); + } +} + + +/* +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: GIFDecoder Version 2.0 by László Zsidi, http://gifs.hu +:: +:: Created at 2007. 02. 01. '07.47.AM' +:: +:: +:: +:: +:: Try on-line GIFBuilder Form demo based on GIFDecoder. +:: +:: http://gifs.hu/phpclasses/demos/GifBuilder/ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +*/ + +Class GIFDecoder { + var $GIF_buffer = array ( ); + var $GIF_arrays = array ( ); + var $GIF_delays = array ( ); + var $GIF_stream = ""; + var $GIF_string = ""; + var $GIF_bfseek = 0; + + var $GIF_screen = array ( ); + var $GIF_global = array ( ); + var $GIF_sorted; + var $GIF_colorS; + var $GIF_colorC; + var $GIF_colorF; + + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFDecoder ( $GIF_pointer ) + :: + */ + function GIFDecoder ( $GIF_pointer ) { + $this->GIF_stream = $GIF_pointer; + + GIFDecoder::GIFGetByte ( 6 ); // GIF89a + GIFDecoder::GIFGetByte ( 7 ); // Logical Screen Descriptor + + $this->GIF_screen = $this->GIF_buffer; + $this->GIF_colorF = $this->GIF_buffer [ 4 ] & 0x80 ? 1 : 0; + $this->GIF_sorted = $this->GIF_buffer [ 4 ] & 0x08 ? 1 : 0; + $this->GIF_colorC = $this->GIF_buffer [ 4 ] & 0x07; + $this->GIF_colorS = 2 << $this->GIF_colorC; + + if ( $this->GIF_colorF == 1 ) { + GIFDecoder::GIFGetByte ( 3 * $this->GIF_colorS ); + $this->GIF_global = $this->GIF_buffer; + } + /* + * + * 05.06.2007. + * Made a little modification + * + * + - for ( $cycle = 1; $cycle; ) { + + if ( GIFDecoder::GIFGetByte ( 1 ) ) { + - switch ( $this->GIF_buffer [ 0 ] ) { + - case 0x21: + - GIFDecoder::GIFReadExtensions ( ); + - break; + - case 0x2C: + - GIFDecoder::GIFReadDescriptor ( ); + - break; + - case 0x3B: + - $cycle = 0; + - break; + - } + - } + + else { + + $cycle = 0; + + } + - } + */ + for ( $cycle = 1; $cycle; ) { + if ( GIFDecoder::GIFGetByte ( 1 ) ) { + switch ( $this->GIF_buffer [ 0 ] ) { + case 0x21: + GIFDecoder::GIFReadExtensions ( ); + break; + case 0x2C: + GIFDecoder::GIFReadDescriptor ( ); + break; + case 0x3B: + $cycle = 0; + break; + } + } + else { + $cycle = 0; + } + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFReadExtension ( ) + :: + */ + function GIFReadExtensions ( ) { + GIFDecoder::GIFGetByte ( 1 ); + for ( ; ; ) { + GIFDecoder::GIFGetByte ( 1 ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + GIFDecoder::GIFGetByte ( $u ); + /* + * 07.05.2007. + * Implemented a new line for a new function + * to determine the originaly delays between + * frames. + * + */ + if ( $u == 4 ) { + $this->GIF_delays [ ] = ( $this->GIF_buffer [ 1 ] | $this->GIF_buffer [ 2 ] << 8 ); + } + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFReadExtension ( ) + :: + */ + function GIFReadDescriptor ( ) { + $GIF_screen = array ( ); + + GIFDecoder::GIFGetByte ( 9 ); + $GIF_screen = $this->GIF_buffer; + $GIF_colorF = $this->GIF_buffer [ 8 ] & 0x80 ? 1 : 0; + if ( $GIF_colorF ) { + $GIF_code = $this->GIF_buffer [ 8 ] & 0x07; + $GIF_sort = $this->GIF_buffer [ 8 ] & 0x20 ? 1 : 0; + } + else { + $GIF_code = $this->GIF_colorC; + $GIF_sort = $this->GIF_sorted; + } + $GIF_size = 2 << $GIF_code; + $this->GIF_screen [ 4 ] &= 0x70; + $this->GIF_screen [ 4 ] |= 0x80; + $this->GIF_screen [ 4 ] |= $GIF_code; + if ( $GIF_sort ) { + $this->GIF_screen [ 4 ] |= 0x08; + } + $this->GIF_string = "GIF87a"; + GIFDecoder::GIFPutByte ( $this->GIF_screen ); + if ( $GIF_colorF == 1 ) { + GIFDecoder::GIFGetByte ( 3 * $GIF_size ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + } + else { + GIFDecoder::GIFPutByte ( $this->GIF_global ); + } + $this->GIF_string .= chr ( 0x2C ); + $GIF_screen [ 8 ] &= 0x40; + GIFDecoder::GIFPutByte ( $GIF_screen ); + GIFDecoder::GIFGetByte ( 1 ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + for ( ; ; ) { + GIFDecoder::GIFGetByte ( 1 ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + GIFDecoder::GIFGetByte ( $u ); + GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + } + $this->GIF_string .= chr ( 0x3B ); + /* + Add frames into $GIF_stream array... + */ + $this->GIF_arrays [ ] = $this->GIF_string; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetByte ( $len ) + :: + */ + + /* + * + * 05.06.2007. + * Made a little modification + * + * + - function GIFGetByte ( $len ) { + - $this->GIF_buffer = array ( ); + - + - for ( $i = 0; $i < $len; $i++ ) { + + if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) { + + return 0; + + } + - $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); + - } + + return 1; + - } + */ + function GIFGetByte ( $len ) { + $this->GIF_buffer = array ( ); + + for ( $i = 0; $i < $len; $i++ ) { + if ( $this->GIF_bfseek > strlen ( $this->GIF_stream ) ) { + return 0; + } + $this->GIF_buffer [ ] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); + } + return 1; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFPutByte ( $bytes ) + :: + */ + function GIFPutByte ( $bytes ) { + for ( $i = 0; $i < count ( $bytes ); $i++ ) { + $this->GIF_string .= chr ( $bytes [ $i ] ); + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: PUBLIC FUNCTIONS + :: + :: + :: GIFGetFrames ( ) + :: + */ + function GIFGetFrames ( ) { + return ( $this->GIF_arrays ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetDelays ( ) + :: + */ + function GIFGetDelays ( ) { + return ( $this->GIF_delays ); + } +} diff --git a/Library/Org/image/Driver/Imagick.php b/Library/Org/image/Driver/Imagick.php new file mode 100644 index 00000000..85d9b5ef --- /dev/null +++ b/Library/Org/image/Driver/Imagick.php @@ -0,0 +1,591 @@ + +// +---------------------------------------------------------------------- + +namespace Think\Image\Driver; + +class Imagick{ + /** + * 图像资源对象 + * @var resource + */ + private $im; + + /** + * 图像信息,包括width,height,type,mime,size + * @var array + */ + private $info; + + /** + * 构造方法,可用于打开一张图像 + * @param string $imgname 图像路径 + */ + public function __construct($imgname = null) { + if ( !extension_loaded('Imagick') ) { + E(L('_NOT_SUPPERT_').':Imagick'); + } + $imgname && $this->open($imgname); + } + + /** + * 打开一张图像 + * @param string $imgname 图像路径 + */ + public function open($imgname){ + //检测图像文件 + if(!is_file($imgname)) throw new \Exception('不存在的图像文件'); + + //销毁已存在的图像 + empty($this->im) || $this->im->destroy(); + + //载入图像 + $this->im = new \Imagick(realpath($imgname)); + + //设置图像信息 + $this->info = [ + 'width' => $this->im->getImageWidth(), + 'height' => $this->im->getImageHeight(), + 'type' => strtolower($this->im->getImageFormat()), + 'mime' => $this->im->getImageMimeType(), + ]; + } + + /** + * 保存图像 + * @param string $imgname 图像保存名称 + * @param string $type 图像类型 + * @param boolean $interlace 是否对JPEG类型图像设置隔行扫描 + */ + public function save($imgname, $type = null, $interlace = true){ + if(empty($this->im)) throw new \Exception('没有可以被保存的图像资源'); + + //设置图片类型 + if(is_null($type)){ + $type = $this->info['type']; + } else { + $type = strtolower($type); + $this->im->setImageFormat($type); + } + + //JPEG图像设置隔行扫描 + if('jpeg' == $type || 'jpg' == $type){ + $this->im->setImageInterlaceScheme(1); + } + + //去除图像配置信息 + $this->im->stripImage(); + + //保存图像 + $imgname = realpath(dirname($imgname)) . '/' . basename($imgname); //强制绝对路径 + if ('gif' == $type) { + $this->im->writeImages($imgname, true); + } else { + $this->im->writeImage($imgname); + } + } + + /** + * 返回图像宽度 + * @return integer 图像宽度 + */ + public function width(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['width']; + } + + /** + * 返回图像高度 + * @return integer 图像高度 + */ + public function height(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['height']; + } + + /** + * 返回图像类型 + * @return string 图像类型 + */ + public function type(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['type']; + } + + /** + * 返回图像MIME类型 + * @return string 图像MIME类型 + */ + public function mime(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return $this->info['mime']; + } + + /** + * 返回图像尺寸数组 0 - 图像宽度,1 - 图像高度 + * @return array 图像尺寸 + */ + public function size(){ + if(empty($this->im)) throw new \Exception('没有指定图像资源'); + return [$this->info['width'], $this->info['height']]; + } + + /** + * 裁剪图像 + * @param integer $w 裁剪区域宽度 + * @param integer $h 裁剪区域高度 + * @param integer $x 裁剪区域x坐标 + * @param integer $y 裁剪区域y坐标 + * @param integer $width 图像保存宽度 + * @param integer $height 图像保存高度 + */ + public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null){ + if(empty($this->im)) throw new \Exception('没有可以被裁剪的图像资源'); + + //设置保存尺寸 + empty($width) && $width = $w; + empty($height) && $height = $h; + + //裁剪图片 + if('gif' == $this->info['type']){ + $img = $this->im->coalesceImages(); + $this->im->destroy(); //销毁原图 + + //循环裁剪每一帧 + do { + $this->_crop($w, $h, $x, $y, $width, $height, $img); + } while ($img->nextImage()); + + //压缩图片 + $this->im = $img->deconstructImages(); + $img->destroy(); //销毁零时图片 + } else { + $this->_crop($w, $h, $x, $y, $width, $height); + } + } + + /* 裁剪图片,内部调用 */ + private function _crop($w, $h, $x, $y, $width, $height, $img = null){ + is_null($img) && $img = $this->im; + + //裁剪 + $info = $this->info; + if($x != 0 || $y != 0 || $w != $info['width'] || $h != $info['height']){ + $img->cropImage($w, $h, $x, $y); + $img->setImagePage($w, $h, 0, 0); //调整画布和图片一致 + } + + //调整大小 + if($w != $width || $h != $height){ + $img->scaleImage($width, $height); + } + + //设置缓存尺寸 + $this->info['width'] = $w; + $this->info['height'] = $h; + } + + /** + * 生成缩略图 + * @param integer $width 缩略图最大宽度 + * @param integer $height 缩略图最大高度 + * @param integer $type 缩略图裁剪类型 + */ + public function thumb($width, $height, $type = THINKIMAGE_THUMB_SCALE){ + if(empty($this->im)) throw new \Exception('没有可以被缩略的图像资源'); + + //原图宽度和高度 + $w = $this->info['width']; + $h = $this->info['height']; + + /* 计算缩略图生成的必要参数 */ + switch ($type) { + /* 等比例缩放 */ + case THINKIMAGE_THUMB_SCALING: + //原图尺寸小于缩略图尺寸则不进行缩略 + if($w < $width && $h < $height) return; + + //计算缩放比例 + $scale = min($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $width = $w * $scale; + $height = $h * $scale; + break; + + /* 居中裁剪 */ + case THINKIMAGE_THUMB_CENTER: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = ($this->info['width'] - $w)/2; + $y = ($this->info['height'] - $h)/2; + break; + + /* 左上角裁剪 */ + case THINKIMAGE_THUMB_NORTHWEST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $x = $y = 0; + $w = $width/$scale; + $h = $height/$scale; + break; + + /* 右下角裁剪 */ + case THINKIMAGE_THUMB_SOUTHEAST: + //计算缩放比例 + $scale = max($width/$w, $height/$h); + + //设置缩略图的坐标及宽度和高度 + $w = $width/$scale; + $h = $height/$scale; + $x = $this->info['width'] - $w; + $y = $this->info['height'] - $h; + break; + + /* 填充 */ + case THINKIMAGE_THUMB_FILLED: + //计算缩放比例 + if($w < $width && $h < $height){ + $scale = 1; + } else { + $scale = min($width/$w, $height/$h); + } + + //设置缩略图的坐标及宽度和高度 + $neww = $w * $scale; + $newh = $h * $scale; + $posx = ($width - $w * $scale)/2; + $posy = ($height - $h * $scale)/2; + + //创建一张新图像 + $newimg = new Imagick(); + $newimg->newImage($width, $height, 'white', $this->info['type']); + + + if('gif' == $this->info['type']){ + $imgs = $this->im->coalesceImages(); + $img = new Imagick(); + $this->im->destroy(); //销毁原图 + + //循环填充每一帧 + do { + //填充图像 + $image = $this->_fill($newimg, $posx, $posy, $neww, $newh, $imgs); + + $img->addImage($image); + $img->setImageDelay($imgs->getImageDelay()); + $img->setImagePage($width, $height, 0, 0); + + $image->destroy(); //销毁零时图片 + + } while ($imgs->nextImage()); + + //压缩图片 + $this->im->destroy(); + $this->im = $img->deconstructImages(); + $imgs->destroy(); //销毁零时图片 + $img->destroy(); //销毁零时图片 + + } else { + //填充图像 + $img = $this->_fill($newimg, $posx, $posy, $neww, $newh); + //销毁原图 + $this->im->destroy(); + $this->im = $img; + } + + //设置新图像属性 + $this->info['width'] = $width; + $this->info['height'] = $height; + return; + + /* 固定 */ + case THINKIMAGE_THUMB_FIXED: + $x = $y = 0; + break; + + default: + throw new \Exception('不支持的缩略图裁剪类型'); + } + + /* 裁剪图像 */ + $this->crop($w, $h, $x, $y, $width, $height); + } + + /* 填充指定图像,内部使用 */ + private function _fill($newimg, $posx, $posy, $neww, $newh, $img = null){ + is_null($img) && $img = $this->im; + + /* 将指定图片绘入空白图片 */ + $draw = new ImagickDraw(); + $draw->composite($img->getImageCompose(), $posx, $posy, $neww, $newh, $img); + $image = $newimg->clone(); + $image->drawImage($draw); + $draw->destroy(); + + return $image; + } + + /** + * 添加水印 + * @param string $source 水印图片路径 + * @param integer $locate 水印位置 + * @param integer $alpha 水印透明度 + */ + public function water($source, $locate = THINKIMAGE_WATER_SOUTHEAST){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被添加水印的图像资源'); + if(!is_file($source)) throw new \Exception('水印图像不存在'); + + //创建水印图像资源 + $water = new Imagick(realpath($source)); + $info = [$water->getImageWidth(), $water->getImageHeight()]; + + /* 设定水印位置 */ + switch ($locate) { + /* 右下角水印 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x = $this->info['width'] - $info[0]; + $y = $this->info['height'] - $info[1]; + break; + + /* 左下角水印 */ + case THINKIMAGE_WATER_SOUTHWEST: + $x = 0; + $y = $this->info['height'] - $info[1]; + break; + + /* 左上角水印 */ + case THINKIMAGE_WATER_NORTHWEST: + $x = $y = 0; + break; + + /* 右上角水印 */ + case THINKIMAGE_WATER_NORTHEAST: + $x = $this->info['width'] - $info[0]; + $y = 0; + break; + + /* 居中水印 */ + case THINKIMAGE_WATER_CENTER: + $x = ($this->info['width'] - $info[0])/2; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 下居中水印 */ + case THINKIMAGE_WATER_SOUTH: + $x = ($this->info['width'] - $info[0])/2; + $y = $this->info['height'] - $info[1]; + break; + + /* 右居中水印 */ + case THINKIMAGE_WATER_EAST: + $x = $this->info['width'] - $info[0]; + $y = ($this->info['height'] - $info[1])/2; + break; + + /* 上居中水印 */ + case THINKIMAGE_WATER_NORTH: + $x = ($this->info['width'] - $info[0])/2; + $y = 0; + break; + + /* 左居中水印 */ + case THINKIMAGE_WATER_WEST: + $x = 0; + $y = ($this->info['height'] - $info[1])/2; + break; + + default: + /* 自定义水印坐标 */ + if(is_array($locate)){ + list($x, $y) = $locate; + } else { + throw new \Exception('不支持的水印位置类型'); + } + } + + //创建绘图资源 + $draw = new ImagickDraw(); + $draw->composite($water->getImageCompose(), $x, $y, $info[0], $info[1], $water); + + if('gif' == $this->info['type']){ + $img = $this->im->coalesceImages(); + $this->im->destroy(); //销毁原图 + + do{ + //添加水印 + $img->drawImage($draw); + } while ($img->nextImage()); + + //压缩图片 + $this->im = $img->deconstructImages(); + $img->destroy(); //销毁零时图片 + + } else { + //添加水印 + $this->im->drawImage($draw); + } + + //销毁水印资源 + $draw->destroy(); + $water->destroy(); + } + + /** + * 图像添加文字 + * @param string $text 添加的文字 + * @param string $font 字体路径 + * @param integer $size 字号 + * @param string $color 文字颜色 + * @param integer $locate 文字写入位置 + * @param integer $offset 文字相对当前位置的偏移量 + * @param integer $angle 文字倾斜角度 + */ + public function text($text, $font, $size, $color = '#00000000', + $locate = THINKIMAGE_WATER_SOUTHEAST, $offset = 0, $angle = 0){ + //资源检测 + if(empty($this->im)) throw new \Exception('没有可以被写入文字的图像资源'); + if(!is_file($font)) throw new \Exception("不存在的字体文件:{$font}"); + + //获取颜色和透明度 + if(is_array($color)){ + $color = array_map('dechex', $color); + foreach ($color as &$value) { + $value = str_pad($value, 2, '0', STR_PAD_LEFT); + } + $color = '#' . implode('', $color); + } elseif(!is_string($color) || 0 !== strpos($color, '#')) { + throw new \Exception('错误的颜色值'); + } + $col = substr($color, 0, 7); + $alp = strlen($color) == 9 ? substr($color, -2) : 0; + + + //获取文字信息 + $draw = new ImagickDraw(); + $draw->setFont(realpath($font)); + $draw->setFontSize($size); + $draw->setFillColor($col); + $draw->setFillAlpha(1-hexdec($alp)/127); + $draw->setTextAntialias(true); + $draw->setStrokeAntialias(true); + + $metrics = $this->im->queryFontMetrics($draw, $text); + + /* 计算文字初始坐标和尺寸 */ + $x = 0; + $y = $metrics['ascender']; + $w = $metrics['textWidth']; + $h = $metrics['textHeight']; + + /* 设定文字位置 */ + switch ($locate) { + /* 右下角文字 */ + case THINKIMAGE_WATER_SOUTHEAST: + $x += $this->info['width'] - $w; + $y += $this->info['height'] - $h; + break; + + /* 左下角文字 */ + case THINKIMAGE_WATER_SOUTHWEST: + $y += $this->info['height'] - $h; + break; + + /* 左上角文字 */ + case THINKIMAGE_WATER_NORTHWEST: + // 起始坐标即为左上角坐标,无需调整 + break; + + /* 右上角文字 */ + case THINKIMAGE_WATER_NORTHEAST: + $x += $this->info['width'] - $w; + break; + + /* 居中文字 */ + case THINKIMAGE_WATER_CENTER: + $x += ($this->info['width'] - $w)/2; + $y += ($this->info['height'] - $h)/2; + break; + + /* 下居中文字 */ + case THINKIMAGE_WATER_SOUTH: + $x += ($this->info['width'] - $w)/2; + $y += $this->info['height'] - $h; + break; + + /* 右居中文字 */ + case THINKIMAGE_WATER_EAST: + $x += $this->info['width'] - $w; + $y += ($this->info['height'] - $h)/2; + break; + + /* 上居中文字 */ + case THINKIMAGE_WATER_NORTH: + $x += ($this->info['width'] - $w)/2; + break; + + /* 左居中文字 */ + case THINKIMAGE_WATER_WEST: + $y += ($this->info['height'] - $h)/2; + break; + + default: + /* 自定义文字坐标 */ + if(is_array($locate)){ + list($posx, $posy) = $locate; + $x += $posx; + $y += $posy; + } else { + throw new \Exception('不支持的文字位置类型'); + } + } + + /* 设置偏移量 */ + if(is_array($offset)){ + $offset = array_map('intval', $offset); + list($ox, $oy) = $offset; + } else{ + $offset = intval($offset); + $ox = $oy = $offset; + } + + /* 写入文字 */ + if('gif' == $this->info['type']){ + $img = $this->im->coalesceImages(); + $this->im->destroy(); //销毁原图 + do{ + $img->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text); + } while ($img->nextImage()); + + //压缩图片 + $this->im = $img->deconstructImages(); + $img->destroy(); //销毁零时图片 + + } else { + $this->im->annotateImage($draw, $x + $ox, $y + $oy, $angle, $text); + } + $draw->destroy(); + } + + /** + * 析构方法,用于销毁图像资源 + */ + public function __destruct() { + empty($this->im) || $this->im->destroy(); + } +} diff --git a/Library/Think/Oauth.php b/Library/Org/oauth.php similarity index 100% rename from Library/Think/Oauth.php rename to Library/Org/oauth.php diff --git a/Library/Think/Oauth/Driver.php b/Library/Org/oauth/Driver.php similarity index 100% rename from Library/Think/Oauth/Driver.php rename to Library/Org/oauth/Driver.php diff --git a/Library/Think/Oauth/Driver/Baidu.php b/Library/Org/oauth/Driver/Baidu.php similarity index 100% rename from Library/Think/Oauth/Driver/Baidu.php rename to Library/Org/oauth/Driver/Baidu.php diff --git a/Library/Think/Oauth/Driver/Diandian.php b/Library/Org/oauth/Driver/Diandian.php similarity index 100% rename from Library/Think/Oauth/Driver/Diandian.php rename to Library/Org/oauth/Driver/Diandian.php diff --git a/Library/Think/Oauth/Driver/Douban.php b/Library/Org/oauth/Driver/Douban.php similarity index 100% rename from Library/Think/Oauth/Driver/Douban.php rename to Library/Org/oauth/Driver/Douban.php diff --git a/Library/Think/Oauth/Driver/Github.php b/Library/Org/oauth/Driver/Github.php similarity index 100% rename from Library/Think/Oauth/Driver/Github.php rename to Library/Org/oauth/Driver/Github.php diff --git a/Library/Think/Oauth/Driver/Google.php b/Library/Org/oauth/Driver/Google.php similarity index 100% rename from Library/Think/Oauth/Driver/Google.php rename to Library/Org/oauth/Driver/Google.php diff --git a/Library/Think/Oauth/Driver/Kaixin.php b/Library/Org/oauth/Driver/Kaixin.php similarity index 100% rename from Library/Think/Oauth/Driver/Kaixin.php rename to Library/Org/oauth/Driver/Kaixin.php diff --git a/Library/Think/Oauth/Driver/Msn.php b/Library/Org/oauth/Driver/Msn.php similarity index 100% rename from Library/Think/Oauth/Driver/Msn.php rename to Library/Org/oauth/Driver/Msn.php diff --git a/Library/Think/Oauth/Driver/Qq.php b/Library/Org/oauth/Driver/Qq.php similarity index 100% rename from Library/Think/Oauth/Driver/Qq.php rename to Library/Org/oauth/Driver/Qq.php diff --git a/Library/Think/Oauth/Driver/Renren.php b/Library/Org/oauth/Driver/Renren.php similarity index 100% rename from Library/Think/Oauth/Driver/Renren.php rename to Library/Org/oauth/Driver/Renren.php diff --git a/Library/Think/Oauth/Driver/Sina.php b/Library/Org/oauth/Driver/Sina.php similarity index 100% rename from Library/Think/Oauth/Driver/Sina.php rename to Library/Org/oauth/Driver/Sina.php diff --git a/Library/Think/Oauth/Driver/Sohu.php b/Library/Org/oauth/Driver/Sohu.php similarity index 100% rename from Library/Think/Oauth/Driver/Sohu.php rename to Library/Org/oauth/Driver/Sohu.php diff --git a/Library/Think/Oauth/Driver/T163.php b/Library/Org/oauth/Driver/T163.php similarity index 100% rename from Library/Think/Oauth/Driver/T163.php rename to Library/Org/oauth/Driver/T163.php diff --git a/Library/Think/Oauth/Driver/Taobao.php b/Library/Org/oauth/Driver/Taobao.php similarity index 100% rename from Library/Think/Oauth/Driver/Taobao.php rename to Library/Org/oauth/Driver/Taobao.php diff --git a/Library/Think/Oauth/Driver/Tencent.php b/Library/Org/oauth/Driver/Tencent.php similarity index 100% rename from Library/Think/Oauth/Driver/Tencent.php rename to Library/Org/oauth/Driver/Tencent.php diff --git a/Library/Think/Oauth/Driver/X360.php b/Library/Org/oauth/Driver/X360.php similarity index 100% rename from Library/Think/Oauth/Driver/X360.php rename to Library/Org/oauth/Driver/X360.php diff --git a/Library/Think/Transform/Driver/Json.php b/Library/Org/transform/Driver/Json.php similarity index 100% rename from Library/Think/Transform/Driver/Json.php rename to Library/Org/transform/Driver/Json.php diff --git a/Library/Think/Transform/Driver/Xml.php b/Library/Org/transform/Driver/Xml.php similarity index 100% rename from Library/Think/Transform/Driver/Xml.php rename to Library/Org/transform/Driver/Xml.php diff --git a/Library/Think/Upload.php b/Library/Org/upload.php similarity index 100% rename from Library/Think/Upload.php rename to Library/Org/upload.php diff --git a/Library/Think/Validate.php b/Library/Org/validate.php similarity index 100% rename from Library/Think/Validate.php rename to Library/Org/validate.php diff --git a/Library/Think/App.php b/Library/Think/App.php index aef3db98..94105879 100644 --- a/Library/Think/App.php +++ b/Library/Think/App.php @@ -76,9 +76,9 @@ class App { // 执行操作 if(!preg_match('/^[A-Za-z](\/|\w)*$/',CONTROLLER_NAME)){ // 安全检测 $instance = false; - }elseif(isset($config['action_bind_class']) && $config['action_bind_class']){ + }elseif($config['action_bind_class']){ // 操作绑定到类:模块\Controller\控制器\操作 - $layer = $config['controller_layer']; + $layer = CONTROLLER_LAYER; if(is_dir(MODULE_PATH.$layer.'/'.CONTROLLER_NAME)){ $namespace = MODULE_NAME.'\\'.$layer.'\\'.CONTROLLER_NAME.'\\'; }else{ @@ -279,7 +279,7 @@ class App { static private function getModule($config){ $module = strtolower(isset($_GET[$config['var_module']]) ? $_GET[$config['var_module']] : $config['default_module']); - if(isset($config['url_module_map']) && $maps = $config['url_module_map']) { + if($maps = $config['url_module_map']) { if(isset($maps[$module])) { // 记录当前别名 define('MODULE_ALIAS',$module); @@ -290,6 +290,6 @@ class App { $module = ''; } } - return strip_tags(ucwords($module)); + return strip_tags($module); } } diff --git a/Library/Think/Create.php b/Library/Think/Create.php index 9073181e..72f98d0d 100644 --- a/Library/Think/Create.php +++ b/Library/Think/Create.php @@ -46,19 +46,19 @@ class Create { } foreach($file as $val){ switch($path) { - case 'Controller':// 控制器 + case 'controller':// 控制器 $filename = ucwords($val).$path; if(!is_file(APP_PATH.$module.'/'.$path.'/'.$filename.'.php')) { file_put_contents(APP_PATH.$module.'/'.$path.'/'.$filename.'.php'," -// +---------------------------------------------------------------------- - -namespace Think; - -class Tag { - - static private $tags = []; - - /** - * 动态添加行为扩展到某个标签 - * @param string $tag 标签名称 - * @param mixed $behavior 行为名称 - * @return void - */ - static public function add($tag,$behavior) { - if(is_array($behavior)) { - self::$tags[$tag] = array_merge(self::$tags[$tag],$behavior); - }else{ - self::$tags[$tag][] = $behavior; - } - } - - /** - * 批量导入行为 - * @param array $tags 标签行为 - * @return void - */ - static public function import($tags) { - self::$tags = array_merge(self::$tags,$tags); - } - - /** - * 监听标签的行为 - * @param string $tag 标签名称 - * @param mixed $params 传入参数 - * @return void - */ - static public function listen($tag, &$params=NULL) { - if(isset(self::$tags[$tag])) { - foreach (self::$tags[$tag] as $val) { - Debug::remark('behavior_start','time'); - $result = self::exec($val, $params); - Debug::remark('behavior_end','time'); - Log::record('Run '.$val.' Behavior [ RunTime:'.Debug::getUseTime('behavior_start','behavior_end').'s ]','INFO'); - if(false === $result) { - // 如果返回false 则中断行为执行 - return ; - } - } - } - return; - } - - /** - * 执行某个行为 - * @param string $name 行为名称 - * @param Mixed $params 传人的参数 - * @return void - */ - static public function exec($name, &$params=NULL) { - if($name instanceof \Closure) { - return $name($params); - } - if(false === strpos($name,'\\')) { - $class = '\\'.ucwords(MODULE_NAME).'\\Behavior\\'.$name; - }else{ - $class = $name; - } - if(class_exists($class)) { - $behavior = new $class(); - return $behavior->run($params); - } - return ; - } -} diff --git a/Library/Think/Template.php b/Library/Think/Template.php index 4465d90c..c9a7e679 100644 --- a/Library/Think/Template.php +++ b/Library/Think/Template.php @@ -439,7 +439,7 @@ class Template { protected function parseTagLib($tagLib,&$content,$hide=false) { $begin = $this->config['taglib_begin']; $end = $this->config['taglib_end']; - $className = '\\Think\\Template\\TagLib\\'.ucwords($tagLib); + $className = '\\Think\\Template\\Taglib\\'.ucwords($tagLib); $tLib = new $className($this); foreach ($tLib->getTags() as $name=>$val){ $tags = [$name]; diff --git a/Library/Think/Template/TagLib/Cx.php b/Library/Think/Template/TagLib/Cx.php index d97be139..fe52c0b0 100644 --- a/Library/Think/Template/TagLib/Cx.php +++ b/Library/Think/Template/TagLib/Cx.php @@ -9,8 +9,8 @@ // | Author: liu21st // +---------------------------------------------------------------------- -namespace Think\Template\TagLib; -use Think\Template\TagLib; +namespace Think\Template\Taglib; +use Think\Template\Taglib; /** * CX标签库解析类 @@ -19,7 +19,7 @@ use Think\Template\TagLib; * @subpackage Driver.Taglib * @author liu21st */ -class Cx extends TagLib { +class Cx extends Taglib { // 标签定义 protected $tags = [ diff --git a/Mode/common.php b/Mode/common.php index ca8c148e..3e02eefa 100644 --- a/Mode/common.php +++ b/Mode/common.php @@ -47,6 +47,8 @@ return [ 'caceh_path' => CACHE_PATH, 'session_prefix' => 'think', 'session_auto_start' => true, + 'action_bind_class' => false, + 'url_module_map' => [], /* 错误设置 */ 'error_message' => '页面错误!请稍后再试~',//错误显示信息,非调试模式有效 diff --git a/Mode/sae/convention.php b/Mode/sae/convention.php new file mode 100644 index 00000000..9101e436 --- /dev/null +++ b/Mode/sae/convention.php @@ -0,0 +1,39 @@ + +// +---------------------------------------------------------------------- + +/** + * SAE模式惯例配置文件 + * 该文件请不要修改,如果要覆盖惯例配置的值,可在应用配置文件中设定和惯例不符的配置项 + * 配置名称大小写任意,系统会统一转换成小写 + * 所有配置参数都可以在生效前动态改变 + */ +defined('THINK_PATH') or exit(); +$st = new SaeStorage(); +return array( + //SAE下固定mysql配置 + 'DB_TYPE' => 'mysql', // 数据库类型 + 'DB_DEPLOY_TYPE' => 1, + 'DB_RW_SEPARATE' => true, + 'DB_HOST' => SAE_MYSQL_HOST_M.','.SAE_MYSQL_HOST_S, // 服务器地址 + 'DB_NAME' => SAE_MYSQL_DB, // 数据库名 + 'DB_USER' => SAE_MYSQL_USER, // 用户名 + 'DB_PWD' => SAE_MYSQL_PASS, // 密码 + 'DB_PORT' => SAE_MYSQL_PORT, // 端口 + //更改模板替换变量,让普通能在所有平台下显示 + 'TMPL_PARSE_STRING' => array( + // __PUBLIC__/upload --> /Public/upload -->http://appname-public.stor.sinaapp.com/upload + '/Public/upload' => $st->getUrl('public','upload') + ), + 'LOG_TYPE' => 'Sae', + 'DATA_CACHE_TYPE' => 'Memcachesae', + 'CHECK_APP_DIR' => false, + 'FILE_UPLOAD_TYPE' => 'Sae', +); diff --git a/base.php b/base.php index aac0cab7..5a11f69b 100644 --- a/base.php +++ b/base.php @@ -16,22 +16,22 @@ define('MAGIC_QUOTES_GPC', false); define('THINK_VERSION', '4.0beta'); // 系统常量 defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__).'/'); -defined('LIB_PATH') or define('LIB_PATH', THINK_PATH.'Library/'); -defined('MODE_PATH') or define('MODE_PATH', THINK_PATH.'Mode/'); // 系统应用模式目录 -defined('TRAIT_PATH') or define('TRAIT_PATH', THINK_PATH.'Traits/'); -defined('CORE_PATH') or define('CORE_PATH', LIB_PATH.'Think/'); -defined('ORG_PATH') or define('ORG_PATH', LIB_PATH.'Org/'); +defined('LIB_PATH') or define('LIB_PATH', THINK_PATH.'library/'); +defined('MODE_PATH') or define('MODE_PATH', THINK_PATH.'mode/'); // 系统应用模式目录 +defined('TRAIT_PATH') or define('TRAIT_PATH', THINK_PATH.'traits/'); +defined('CORE_PATH') or define('CORE_PATH', LIB_PATH.'think/'); +defined('ORG_PATH') or define('ORG_PATH', LIB_PATH.'org/'); defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); -defined('RUNTIME_PATH') or define('RUNTIME_PATH', realpath(APP_PATH).'/Runtime/'); -defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH.'Data/'); -defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH.'Log/'); -defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH.'Cache/'); -defined('TEMP_PATH') or define('CACHE_PATH', RUNTIME_PATH.'Temp/'); -defined('VENDOR_PATH') or define('VENDOR_PATH', THINK_PATH.'Vendor/'); +defined('RUNTIME_PATH') or define('RUNTIME_PATH', realpath(APP_PATH).'/runtime/'); +defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH.'data/'); +defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH.'log/'); +defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH.'cache/'); +defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH.'temp/'); +defined('VENDOR_PATH') or define('VENDOR_PATH', THINK_PATH.'vendor/'); defined('EXT') or define('EXT', '.php'); -defined('MODEL_LAYER') or define('MODEL_LAYER', 'Model'); -defined('VIEW_LAYER') or define('VIEW_LAYER', 'View'); -defined('CONTROLLER_LAYER') or define('CONTROLLER_LAYER', 'Controller'); +defined('MODEL_LAYER') or define('MODEL_LAYER', 'model'); +defined('VIEW_LAYER') or define('VIEW_LAYER', 'view'); +defined('CONTROLLER_LAYER') or define('CONTROLLER_LAYER', 'controller'); defined('APP_DEBUG') or define('APP_DEBUG', false); // 是否调试模式 if(function_exists('saeAutoLoader')){// 自动识别SAE环境 @@ -238,7 +238,7 @@ function S($name,$value='',$options=null) { */ function parse_name($name, $type=0) { if ($type) { - return ucfirst(preg_replace("/_([a-zA-Z])/e", "strtoupper('\\1')", $name)); + return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match){ return strtoupper($match[1]);}, $name)); } else { return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); } diff --git a/start.php b/start.php index bd248de4..f75590ac 100644 --- a/start.php +++ b/start.php @@ -17,7 +17,7 @@ namespace Think; // 加载基础文件 require __DIR__.'/base.php'; -require CORE_PATH.'Loader.php'; +require CORE_PATH.'loader.php'; // 注册自动加载 Loader::register(); @@ -30,16 +30,16 @@ set_exception_handler(['Think\Error','appException']); // 加载模式定义文件 $mode = require MODE_PATH.APP_MODE.EXT; -// 加载模式配置文件 -if(isset($mode['config'])){ - is_array($mode['config']) ? Config::set($mode['config']) : Config::load($mode['config']); -} - // 加载模式别名定义 if(isset($mode['alias'])){ Loader::addMap(is_array($mode['alias']) ? $mode['alias'] : include $mode['alias']); } +// 加载模式配置文件 +if(isset($mode['config'])){ + is_array($mode['config']) ? Config::set($mode['config']) : Config::load($mode['config']); +} + // 加载模式行为定义 if(isset($mode['tags'])) { Hook::import(is_array($mode['tags']) ? $mode['tags'] : include $mode['tags']);