From 1df472b73e38ff782cba8fafce288573d984fa4c Mon Sep 17 00:00:00 2001 From: thinkphp Date: Thu, 22 Jan 2015 09:28:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/Org/README.md | 1 - Library/Org/auto.php | 59 - Library/Org/controller/Amf.php | 29 - Library/Org/controller/Phprpc.php | 34 - Library/Org/controller/Rest.php | 215 --- Library/Org/crypt.php | 74 - Library/Org/filter.php | 222 --- Library/Org/image.php | 61 - Library/Org/image/Driver/Gd.php | 549 ------- Library/Org/image/Driver/Gif.php | 570 ------- Library/Org/image/Driver/Imagick.php | 591 ------- Library/Org/oauth.php | 71 - Library/Org/oauth/Driver.php | 233 --- Library/Org/oauth/Driver/Baidu.php | 93 -- Library/Org/oauth/Driver/Diandian.php | 93 -- Library/Org/oauth/Driver/Douban.php | 91 -- Library/Org/oauth/Driver/Github.php | 93 -- Library/Org/oauth/Driver/Google.php | 99 -- Library/Org/oauth/Driver/Kaixin.php | 94 -- Library/Org/oauth/Driver/Msn.php | 100 -- Library/Org/oauth/Driver/Qq.php | 102 -- Library/Org/oauth/Driver/Renren.php | 116 -- Library/Org/oauth/Driver/Sina.php | 93 -- Library/Org/oauth/Driver/Sohu.php | 93 -- Library/Org/oauth/Driver/T163.php | 95 -- Library/Org/oauth/Driver/Taobao.php | 97 -- Library/Org/oauth/Driver/Tencent.php | 98 -- Library/Org/oauth/Driver/X360.php | 93 -- Library/Org/transform/Driver/Json.php | 22 - Library/Org/transform/Driver/Xml.php | 119 -- Library/Org/upload.php | 514 ------- Library/Org/validate.php | 189 --- Library/Think/App.php | 295 ---- Library/Think/Behavior/ContentReplace.php | 65 - Library/Think/Behavior/LocationTemplate.php | 48 - Library/Think/Behavior/ReadHtmlCache.php | 122 -- Library/Think/Behavior/ShowPageTrace.php | 90 -- Library/Think/Behavior/TokenBuild.php | 61 - Library/Think/Cache.php | 38 - Library/Think/Cache/Driver/Apc.php | 101 -- Library/Think/Cache/Driver/Db.php | 146 -- Library/Think/Cache/Driver/Eaccelerator.php | 101 -- Library/Think/Cache/Driver/File.php | 184 --- Library/Think/Cache/Driver/Memcache.php | 113 -- Library/Think/Cache/Driver/Redis.php | 116 -- Library/Think/Cache/Driver/Secache.php | 722 --------- Library/Think/Cache/Driver/Simple.php | 99 -- Library/Think/Cache/Driver/Sqlite.php | 119 -- Library/Think/Cache/Driver/Wincache.php | 103 -- Library/Think/Cache/Driver/Xcache.php | 106 -- Library/Think/Config.php | 92 -- Library/Think/Config/Driver/Ini.php | 22 - Library/Think/Config/Driver/Xml.php | 29 - Library/Think/Controller.php | 192 --- Library/Think/Cookie.php | 138 -- Library/Think/Create.php | 102 -- Library/Think/Db.php | 97 -- Library/Think/Db/Driver.php | 1037 ------------- Library/Think/Db/Driver/Mongo.php | 735 --------- Library/Think/Db/Driver/Mysql.php | 92 -- Library/Think/Db/Driver/Oracle.php | 153 -- Library/Think/Db/Driver/Pgsql.php | 91 -- Library/Think/Db/Driver/Sqlite.php | 98 -- Library/Think/Db/Driver/Sqlsrv.php | 164 -- Library/Think/Db/Lite.php | 449 ------ Library/Think/Debug.php | 114 -- Library/Think/Error.php | 128 -- Library/Think/Exception.php | 16 - Library/Think/Hook.php | 86 -- Library/Think/Input.php | 174 --- Library/Think/Lang.php | 54 - Library/Think/Loader.php | 234 --- Library/Think/Log.php | 84 - Library/Think/Log/Driver/File.php | 43 - Library/Think/Model.php | 1026 ------------- Library/Think/Model/ExtendModel.php | 18 - Library/Think/Model/MongoModel.php | 274 ---- Library/Think/Model/RelationModel.php | 16 - Library/Think/Model/ViewModel.php | 16 - Library/Think/Parser.php | 32 - Library/Think/Parser/Driver/Markdown.php | 1534 ------------------- Library/Think/Parser/Driver/Ubb.php | 290 ---- Library/Think/Route.php | 452 ------ Library/Think/Seesion/Driver.php | 22 - Library/Think/Session.php | 200 --- Library/Think/Storage.php | 40 - Library/Think/Storage/Driver/File.php | 125 -- Library/Think/Storage/Driver/Sae.php | 194 --- Library/Think/Template.php | 743 --------- Library/Think/Template/Driver/File.php | 48 - Library/Think/Template/TagLib.php | 248 --- Library/Think/Template/TagLib/Cx.php | 614 -------- Library/Think/Transform.php | 81 - Library/Think/Url.php | 151 -- Library/Think/View.php | 261 ---- Library/Think/View/Driver/Think.php | 28 - Mode/common.php | 106 -- Mode/sae.php | 56 - Mode/sae/convention.php | 39 - Tpl/default_index.tpl | 8 - Tpl/dispatch_jump.tpl | 44 - Tpl/page_trace.tpl | 67 - Tpl/think_exception.tpl | 53 - Traits/Think/Model/Auto.php | 363 ----- Traits/Think/Model/Extend.php | 261 ---- Traits/Think/Model/Query.php | 92 -- Traits/Think/Model/Relation.php | 346 ----- Traits/Think/Model/View.php | 239 --- base.php | 245 --- start.php | 49 - 110 files changed, 20437 deletions(-) delete mode 100644 Library/Org/README.md delete mode 100644 Library/Org/auto.php delete mode 100644 Library/Org/controller/Amf.php delete mode 100644 Library/Org/controller/Phprpc.php delete mode 100644 Library/Org/controller/Rest.php delete mode 100644 Library/Org/crypt.php delete mode 100644 Library/Org/filter.php delete mode 100644 Library/Org/image.php delete mode 100644 Library/Org/image/Driver/Gd.php delete mode 100644 Library/Org/image/Driver/Gif.php delete mode 100644 Library/Org/image/Driver/Imagick.php delete mode 100644 Library/Org/oauth.php delete mode 100644 Library/Org/oauth/Driver.php delete mode 100644 Library/Org/oauth/Driver/Baidu.php delete mode 100644 Library/Org/oauth/Driver/Diandian.php delete mode 100644 Library/Org/oauth/Driver/Douban.php delete mode 100644 Library/Org/oauth/Driver/Github.php delete mode 100644 Library/Org/oauth/Driver/Google.php delete mode 100644 Library/Org/oauth/Driver/Kaixin.php delete mode 100644 Library/Org/oauth/Driver/Msn.php delete mode 100644 Library/Org/oauth/Driver/Qq.php delete mode 100644 Library/Org/oauth/Driver/Renren.php delete mode 100644 Library/Org/oauth/Driver/Sina.php delete mode 100644 Library/Org/oauth/Driver/Sohu.php delete mode 100644 Library/Org/oauth/Driver/T163.php delete mode 100644 Library/Org/oauth/Driver/Taobao.php delete mode 100644 Library/Org/oauth/Driver/Tencent.php delete mode 100644 Library/Org/oauth/Driver/X360.php delete mode 100644 Library/Org/transform/Driver/Json.php delete mode 100644 Library/Org/transform/Driver/Xml.php delete mode 100644 Library/Org/upload.php delete mode 100644 Library/Org/validate.php delete mode 100644 Library/Think/App.php delete mode 100644 Library/Think/Behavior/ContentReplace.php delete mode 100644 Library/Think/Behavior/LocationTemplate.php delete mode 100644 Library/Think/Behavior/ReadHtmlCache.php delete mode 100644 Library/Think/Behavior/ShowPageTrace.php delete mode 100644 Library/Think/Behavior/TokenBuild.php delete mode 100644 Library/Think/Cache.php delete mode 100644 Library/Think/Cache/Driver/Apc.php delete mode 100644 Library/Think/Cache/Driver/Db.php delete mode 100644 Library/Think/Cache/Driver/Eaccelerator.php delete mode 100644 Library/Think/Cache/Driver/File.php delete mode 100644 Library/Think/Cache/Driver/Memcache.php delete mode 100644 Library/Think/Cache/Driver/Redis.php delete mode 100644 Library/Think/Cache/Driver/Secache.php delete mode 100644 Library/Think/Cache/Driver/Simple.php delete mode 100644 Library/Think/Cache/Driver/Sqlite.php delete mode 100644 Library/Think/Cache/Driver/Wincache.php delete mode 100644 Library/Think/Cache/Driver/Xcache.php delete mode 100644 Library/Think/Config.php delete mode 100644 Library/Think/Config/Driver/Ini.php delete mode 100644 Library/Think/Config/Driver/Xml.php delete mode 100644 Library/Think/Controller.php delete mode 100644 Library/Think/Cookie.php delete mode 100644 Library/Think/Create.php delete mode 100644 Library/Think/Db.php delete mode 100644 Library/Think/Db/Driver.php delete mode 100644 Library/Think/Db/Driver/Mongo.php delete mode 100644 Library/Think/Db/Driver/Mysql.php delete mode 100644 Library/Think/Db/Driver/Oracle.php delete mode 100644 Library/Think/Db/Driver/Pgsql.php delete mode 100644 Library/Think/Db/Driver/Sqlite.php delete mode 100644 Library/Think/Db/Driver/Sqlsrv.php delete mode 100644 Library/Think/Db/Lite.php delete mode 100644 Library/Think/Debug.php delete mode 100644 Library/Think/Error.php delete mode 100644 Library/Think/Exception.php delete mode 100644 Library/Think/Hook.php delete mode 100644 Library/Think/Input.php delete mode 100644 Library/Think/Lang.php delete mode 100644 Library/Think/Loader.php delete mode 100644 Library/Think/Log.php delete mode 100644 Library/Think/Log/Driver/File.php delete mode 100644 Library/Think/Model.php delete mode 100644 Library/Think/Model/ExtendModel.php delete mode 100644 Library/Think/Model/MongoModel.php delete mode 100644 Library/Think/Model/RelationModel.php delete mode 100644 Library/Think/Model/ViewModel.php delete mode 100644 Library/Think/Parser.php delete mode 100644 Library/Think/Parser/Driver/Markdown.php delete mode 100644 Library/Think/Parser/Driver/Ubb.php delete mode 100644 Library/Think/Route.php delete mode 100644 Library/Think/Seesion/Driver.php delete mode 100644 Library/Think/Session.php delete mode 100644 Library/Think/Storage.php delete mode 100644 Library/Think/Storage/Driver/File.php delete mode 100644 Library/Think/Storage/Driver/Sae.php delete mode 100644 Library/Think/Template.php delete mode 100644 Library/Think/Template/Driver/File.php delete mode 100644 Library/Think/Template/TagLib.php delete mode 100644 Library/Think/Template/TagLib/Cx.php delete mode 100644 Library/Think/Transform.php delete mode 100644 Library/Think/Url.php delete mode 100644 Library/Think/View.php delete mode 100644 Library/Think/View/Driver/Think.php delete mode 100644 Mode/common.php delete mode 100644 Mode/sae.php delete mode 100644 Mode/sae/convention.php delete mode 100644 Tpl/default_index.tpl delete mode 100644 Tpl/dispatch_jump.tpl delete mode 100644 Tpl/page_trace.tpl delete mode 100644 Tpl/think_exception.tpl delete mode 100644 Traits/Think/Model/Auto.php delete mode 100644 Traits/Think/Model/Extend.php delete mode 100644 Traits/Think/Model/Query.php delete mode 100644 Traits/Think/Model/Relation.php delete mode 100644 Traits/Think/Model/View.php delete mode 100644 base.php delete mode 100644 start.php diff --git a/Library/Org/README.md b/Library/Org/README.md deleted file mode 100644 index 6f940733..00000000 --- a/Library/Org/README.md +++ /dev/null @@ -1 +0,0 @@ -Org命名空间目录 diff --git a/Library/Org/auto.php b/Library/Org/auto.php deleted file mode 100644 index 50de171a..00000000 --- a/Library/Org/auto.php +++ /dev/null @@ -1,59 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Auto { - - protected $auto = []; - - public function rule($rule){ - $this->auto = $rule; - return $this; - } - - /** - * 自动表单处理 - * @access public - * @param array $data 创建数据 - * @return mixed - */ - public function operate($data) { - // 自动填充 - if($this->auto) { - foreach ($this->auto as $auto){ - // 填充因子定义格式 - // array('field','填充内容','附加规则',[额外参数]) - switch(trim($auto[2])) { - case 'callback': // 使用回调方法 - $args = isset($auto[3])?(array)$auto[3]:[]; - if(isset($data[$auto[0]])) { - array_unshift($args,$data[$auto[0]]); - } - $data[$auto[0]] = call_user_func_array($auto[1], $args); - break; - case 'field': // 用其它字段的值进行填充 - $data[$auto[0]] = $data[$auto[1]]; - break; - case 'ignore': // 为空忽略 - if(''===$data[$auto[0]]) - unset($data[$auto[0]]); - break; - case 'string': - default: // 默认作为字符串填充 - $data[$auto[0]] = $auto[1]; - } - if(false === $data[$auto[0]] ) unset($data[$auto[0]]); - } - } - return $data; - } -} diff --git a/Library/Org/controller/Amf.php b/Library/Org/controller/Amf.php deleted file mode 100644 index b4b9a6e8..00000000 --- a/Library/Org/controller/Amf.php +++ /dev/null @@ -1,29 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Controller; -abstract class Amf { - - /** - * PHPRpc控制器架构函数 - * @access public - */ - public function __construct() { - //导入类库 - Think\Loader::import('Vendor.Zend.Amf.Server'); - //实例化AMF - $server = new \Zend_Amf_Server(); - $server -> setClass($this); - echo $server -> handle(); - return ; - } - -} diff --git a/Library/Org/controller/Phprpc.php b/Library/Org/controller/Phprpc.php deleted file mode 100644 index f4274e06..00000000 --- a/Library/Org/controller/Phprpc.php +++ /dev/null @@ -1,34 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Controller; - -abstract class Phprpc { - /** - * PHPRpc控制器架构函数 - * @access public - */ - public function __construct() { - //导入类库 - Think\Loader::import('Vendor.phpRPC.phprpc_server'); - //实例化phprpc - $server = new \PHPRPC_Server(); - $server->add($this); - if(APP_DEBUG) { - $server->setDebugMode(true); - } - $server->setEnableGZIP(true); - $server->start(); - //C('PHPRPC_COMMENT',$server->comment()); - echo $server->comment(); - } - -} diff --git a/Library/Org/controller/Rest.php b/Library/Org/controller/Rest.php deleted file mode 100644 index 00d07d5c..00000000 --- a/Library/Org/controller/Rest.php +++ /dev/null @@ -1,215 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Controller; - -abstract class Rest { - - protected $_method = ''; // 当前请求类型 - protected $_type = ''; // 当前资源类型 - // 输出类型 - protected $restMethodList = 'get|post|put|delete'; - protected $restDefaultMethod = 'get'; - protected $restTypeList = 'html|xml|json|rss'; - protected $restDefaultType = 'html'; - protected $restOutputType = [ // REST允许输出的资源类型列表 - 'xml' => 'application/xml', - 'json' => 'application/json', - 'html' => 'text/html', - ]; - - /** - * 架构函数 取得模板对象实例 - * @access public - */ - public function __construct() { - // 资源类型检测 - if(''==__EXT__) { // 自动检测资源类型 - $this->_type = $this->getAcceptType(); - }elseif(!preg_match('/\('.$this->restTypeList.')$/i',__EXT__)) { - // 资源类型非法 则用默认资源类型访问 - $this->_type = $this->restDefaultType; - }else{ - $this->_type = __EXT__; - } - // 请求方式检测 - $method = strtolower($_SERVER['REQUEST_METHOD']); - if(false === stripos($this->restMethodList,$method)) { - // 请求方式非法 则用默认请求方法 - $method = $this->restDefaultMethod; - } - $this->_method = $method; - } - - /** - * REST 调用 - * @access public - * @param string $method 方法名 - * @param array $args 参数 - * @return mixed - */ - public function _empty($method,$args) { - if(method_exists($this,$method.'_'.$this->_method.'_'.$this->_type)) { // RESTFul方法支持 - $fun = $method.'_'.$this->_method.'_'.$this->_type; - }elseif($this->_method == $this->restDefaultMethod && method_exists($this,$method.'_'.$this->_type) ){ - $fun = $method.'_'.$this->_type; - }elseif($this->_type == $this->restDefaultType && method_exists($this,$method.'_'.$this->_method) ){ - $fun = $method.'_'.$this->_method; - } - if(isset($fun)) { - $this->$fun(); - }else{ - // 抛出异常 - E(L('_ERROR_ACTION_:').ACTION_NAME); - } - } - - /** - * 设置页面输出的CONTENT_TYPE和编码 - * @access public - * @param string $type content_type 类型对应的扩展名 - * @param string $charset 页面输出编码 - * @return void - */ - public function setContentType($type, $charset='utf-8'){ - if(headers_sent()) return; - $type = strtolower($type); - if(isset($this->restOutputType[$type])) //过滤content_type - header('Content-Type: '.$this->restOutputType[$type].'; charset='.$charset); - } - - /** - * 输出返回数据 - * @access protected - * @param mixed $data 要返回的数据 - * @param String $type 返回类型 JSON XML - * @param integer $code HTTP状态 - * @return void - */ - protected function response($data,$type='',$code=200) { - $this->sendHttpStatus($code); - exit($this->encodeData($data,strtolower($type))); - } - - /** - * 编码数据 - * @access protected - * @param mixed $data 要返回的数据 - * @param String $type 返回类型 JSON XML - * @return void - */ - protected function encodeData($data,$type='') { - if(empty($data)) return ''; - if('json' == $type) { - // 返回JSON数据格式到客户端 包含状态信息 - $data = json_encode($data); - }elseif('xml' == $type){ - // 返回xml格式数据 - $data = xml_encode($data); - }elseif('php'==$type){ - $data = serialize($data); - }// 默认直接输出 - $this->setContentType($type); - header('Content-Length: ' . strlen($data)); - return $data; - } - - // 发送Http状态信息 - protected function sendHttpStatus($status) { - static $_status = [ - // Informational 1xx - 100 => 'Continue', - 101 => 'Switching Protocols', - // Success 2xx - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - // Redirection 3xx - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Moved Temporarily ', // 1.1 - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - // 306 is deprecated but reserved - 307 => 'Temporary Redirect', - // Client Error 4xx - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Request Entity Too Large', - 414 => 'Request-URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Requested Range Not Satisfiable', - 417 => 'Expectation Failed', - // Server Error 5xx - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 509 => 'Bandwidth Limit Exceeded' - ]; - if(isset($_status[$code])) { - header('HTTP/1.1 '.$code.' '.$_status[$code]); - // 确保FastCGI模式下正常 - header('Status:'.$code.' '.$_status[$code]); - } - } - - /** - * 获取当前请求的Accept头信息 - * @return string - */ - protected function getAcceptType(){ - $type = [ - 'html' => 'text/html,application/xhtml+xml,*/*', - 'xml' => 'application/xml,text/xml,application/x-xml', - 'json' => 'application/json,text/x-json,application/jsonrequest,text/json', - 'js' => 'text/javascript,application/javascript,application/x-javascript', - 'css' => 'text/css', - 'rss' => 'application/rss+xml', - 'yaml' => 'application/x-yaml,text/yaml', - 'atom' => 'application/atom+xml', - 'pdf' => 'application/pdf', - 'text' => 'text/plain', - 'png' => 'image/png', - 'jpg' => 'image/jpg,image/jpeg,image/pjpeg', - 'gif' => 'image/gif', - 'csv' => 'text/csv' - ]; - - foreach($type as $key=>$val){ - $array = explode(',',$val); - foreach($array as $k=>$v){ - if(stristr($_SERVER['HTTP_ACCEPT'], $v)) { - return $key; - } - } - } - return false; - } -} diff --git a/Library/Org/crypt.php b/Library/Org/crypt.php deleted file mode 100644 index 393b93e0..00000000 --- a/Library/Org/crypt.php +++ /dev/null @@ -1,74 +0,0 @@ - -// +---------------------------------------------------------------------- - -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 deleted file mode 100644 index 3db9b3cc..00000000 --- a/Library/Org/image.php +++ /dev/null @@ -1,61 +0,0 @@ - -// +---------------------------------------------------------------------- - -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 deleted file mode 100644 index 34facecd..00000000 --- a/Library/Org/image/Driver/Gd.php +++ /dev/null @@ -1,549 +0,0 @@ - -// +---------------------------------------------------------------------- - -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 deleted file mode 100644 index f3f6b6bc..00000000 --- a/Library/Org/image/Driver/Gif.php +++ /dev/null @@ -1,570 +0,0 @@ - -// +---------------------------------------------------------------------- - -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 deleted file mode 100644 index 85d9b5ef..00000000 --- a/Library/Org/image/Driver/Imagick.php +++ /dev/null @@ -1,591 +0,0 @@ - -// +---------------------------------------------------------------------- - -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/Org/oauth.php b/Library/Org/oauth.php deleted file mode 100644 index 1a42de6c..00000000 --- a/Library/Org/oauth.php +++ /dev/null @@ -1,71 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -// oauth登录接口 -// -// Oauth::connect('qq',['app_key'=>'','app_secret'=>'','callback'=>'','authorize'=>'']); // 链接QQ登录 -// Oauth::login(); // 跳转到授权登录页面 或者 Oauth::login($callbackUrl); -// Oauth::call('api','params'); // 调用API接口 -// -class Oauth { - - /** - * 操作句柄 - * @var object - * @access protected - */ - static protected $handler = null; - - /** - * 连接oauth - * @access public - * @param string $type Oauth类型 - * @param array $options 配置数组 - * @return object - */ - static public function connect($type,$options=[]) { - $class = 'Think\\Oauth\\Driver\\'.ucwords($type); - self::$handler = new $class($options); - return self::$handler; - } - - // 跳转到授权登录页面 - static public function login($callback=''){ - self::$handler->login($callback); - } - - // 获取access_token - static public function getAccessToken($code){ - self::$handler->getAccessToken($code); - } - - // 设置保存过的token信息 - static public function setToken($token){ - self::$handler->setToken($token); - } - - // 获取oauth用户信息 - static public function getOauthInfo(){ - return self::$handler->getOauthInfo(); - } - - // 获取openid信息 - static public function getOpenId(){ - return self::$handler->getOpenId(); - } - - // 调用oauth接口API - static public function call($api,$param='',$method='GET'){ - return self::$handler->call($api,$param,$method); - } -} diff --git a/Library/Org/oauth/Driver.php b/Library/Org/oauth/Driver.php deleted file mode 100644 index cfb8938f..00000000 --- a/Library/Org/oauth/Driver.php +++ /dev/null @@ -1,233 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth; -abstract class Driver { - - /** - * oauth版本 - * @var string - */ - protected $version = '2.0'; - - /** - * 申请应用时分配的app_key - * @var string - */ - protected $appKey = ''; - - /** - * 申请应用时分配的 app_secret - * @var string - */ - protected $appSecret = ''; - - /** - * 授权类型 response_type 目前只能为code - * @var string - */ - protected $responseType = 'code'; - - /** - * grant_type 目前只能为 authorization_code - * @var string - */ - protected $grantType = 'authorization_code'; - - /** - * 获取request_code请求的URL - * @var string - */ - protected $getRequestCodeURL = ''; - - /** - * 获取access_token请求的URL - * @var string - */ - protected $getAccessTokenURL = ''; - - /** - * API根路径 - * @var string - */ - protected $apiBase = ''; - - /** - * 授权后获取到的TOKEN信息 - * @var array - */ - protected $token = null; - - /** - * 回调页面URL 可以通过配置文件配置 - * @var string - */ - protected $callback = ''; - - /** - * 构造方法,配置应用信息 - * @param array $config - */ - public function __construct($config = []){ - $this->appKey = $config['app_key']; - $this->appSecret = $config['app_secret']; - $this->authorize = isset($config['authorize']) ? $config['authorize'] : ''; - $this->callback = isset($config['callback']) ? $config['callback'] : ''; - } - - // 跳转到授权登录页面 - public function login($callback = ''){ - if($callback) { - $this->callback = $callback; - } - //跳转到授权页面 - header('Location: ' . $this->getRequestCodeURL()); - exit; - } - - /** - * 请求code - */ - public function getRequestCodeURL(){ - //Oauth 标准参数 - $params = array( - 'client_id' => $this->appKey, - 'redirect_uri' => $this->callback, - 'response_type' => $this->responseType, - ); - - //获取额外参数 - if($this->authorize){ - parse_str($this->authorize, $_param); - if(is_array($_param)){ - $params = array_merge($params, $_param); - } else { - throw new \Exception('AUTHORIZE配置不正确!'); - } - } - return $this->getRequestCodeURL . '?' . http_build_query($params); - } - - /** - * 获取access_token - * @param string $code 授权登录成功后得到的code信息 - */ - public function getAccessToken($code){ - $params = array( - 'client_id' => $this->appKey, - 'client_secret' => $this->appSecret, - 'grant_type' => $this->grantType, - 'redirect_uri' => $this->callback, - 'code' => $code, - ); - // 获取token信息 - $data = $this->http($this->getAccessTokenURL, $params, 'POST'); - // 解析token - $this->token = $this->parseToken($data); - return $this->token; - } - - /** - * 设置access_token - * @param string $token - */ - public function setToken($token){ - $this->token = $token; - } - - /** - * 合并默认参数和额外参数 - * @param array $params 默认参数 - * @param array/string $param 额外参数 - * @return array: - */ - protected function param($params, $param){ - if(is_string($param)) - parse_str($param, $param); - return array_merge($params, $param); - } - - /** - * 获取指定API请求的URL - * @param string $api API名称 - * @param string $fix api后缀 - * @return string 请求的完整URL - */ - protected function url($api, $fix = ''){ - return $this->apiBase . $api . $fix; - } - - /** - * 发送HTTP请求方法,目前只支持CURL发送请求 - * @param string $url 请求URL - * @param array $params 请求参数 - * @param string $method 请求方法GET/POST - * @return array $data 响应数据 - */ - protected function http($url, $params, $method = 'GET', $header = [], $multi = false){ - $opts = array( - CURLOPT_TIMEOUT => 30, - CURLOPT_RETURNTRANSFER => 1, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - CURLOPT_HTTPHEADER => $header - ); - - /* 根据请求类型设置特定参数 */ - switch(strtoupper($method)){ - case 'GET': - $opts[CURLOPT_URL] = $url . '?' . http_build_query($params); - break; - case 'POST': - //判断是否传输文件 -+ $params = $multi ? $params : http_build_query($params); - $opts[CURLOPT_URL] = $url; - $opts[CURLOPT_POST] = 1; - $opts[CURLOPT_POSTFIELDS] = $params; - break; - default: - throw new \Exception('不支持的请求方式!'); - } - - /* 初始化并执行curl请求 */ - $ch = curl_init(); - curl_setopt_array($ch, $opts); - $data = curl_exec($ch); - $error = curl_error($ch); - curl_close($ch); - if($error) throw new \Exception('请求发生错误:' . $error); - return $data; - } - - /** - * 抽象方法,在SNSSDK中实现 - * 组装接口调用参数 并调用接口 - */ - abstract protected function call($api, $param = '', $method = 'GET', $multi = false); - - /** - * 抽象方法,在SNSSDK中实现 - * 解析access_token方法请求后的返回值 - */ - abstract protected function parseToken($result); - - /** - * 抽象方法,在SNSSDK中实现 - * 获取当前授权用户的SNS标识 - */ - abstract public function getOpenId(); - - /** - * 抽象方法 - * 获取当前授权用户的用户信息 - */ - abstract public function getOauthInfo(); -} diff --git a/Library/Org/oauth/Driver/Baidu.php b/Library/Org/oauth/Driver/Baidu.php deleted file mode 100644 index 09328f0d..00000000 --- a/Library/Org/oauth/Driver/Baidu.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Baidu extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://openapi.baidu.com/oauth/2.0/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://openapi.baidu.com/oauth/2.0/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://openapi.baidu.com/rest/2.0/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 百度API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 百度调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $this->openid(); - return $data; - } else - throw new \Exception("获取百度ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - $data = $this->call('passport/users/getLoggedInUser'); - return !empty($data['uid'])?$data['uid']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('passport/users/getLoggedInUser'); - - if(!empty($data['uid'])){ - $userInfo['type'] = 'BAIDU'; - $userInfo['name'] = $data['uid']; - $userInfo['nick'] = $data['uname']; - $userInfo['avatar'] = "http://tb.himg.baidu.com/sys/portrait/item/{$data['portrait']}"; - return $userInfo; - } else { - throw new \Exception("获取百度用户信息失败:{$data['error_msg']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Diandian.php b/Library/Org/oauth/Driver/Diandian.php deleted file mode 100644 index d070da0f..00000000 --- a/Library/Org/oauth/Driver/Diandian.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Diandian extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.diandian.com/oauth/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.diandian.com/oauth/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.diandian.com/v1/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 点点网API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 点点网调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['token_type'] && $data['uid']){ - $data['openid'] = $data['uid']; - unset($data['uid']); - return $data; - } else - throw new \Exception("获取点点网ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user/info'); - - if(!empty($data['meta']['status']) && $data['meta']['status'] == 200){ - $userInfo['type'] = 'DIANDIAN'; - $userInfo['name'] = $data['response']['name']; - $userInfo['nick'] = $data['response']['name']; - $userInfo['avatar'] = "https://api.diandian.com/v1/blog/{$data['response']['blogs'][0]['blogUuid']}/avatar/144"; - return $userInfo; - } else { - E("获取点点用户信息失败:{$data}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Douban.php b/Library/Org/oauth/Driver/Douban.php deleted file mode 100644 index d7962507..00000000 --- a/Library/Org/oauth/Driver/Douban.php +++ /dev/null @@ -1,91 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Douban extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://www.douban.com/service/auth2/auth'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://www.douban.com/service/auth2/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.douban.com/v2/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 豆瓣调用公共参数 */ - $params = []; - $header = array("Authorization: Bearer {$this->token['access_token']}"); - $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['douban_user_id']){ - $data['openid'] = $data['douban_user_id']; - unset($data['douban_user_id']); - return $data; - } else - throw new \Exception("获取豆瓣ACCESS_TOKEN出错:{$data['msg']}"); - } - - /** - * 获取当前授权应用的openid - * @return string|null - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user/~me'); - - if(empty($data['code'])){ - $userInfo['type'] = 'DOUBAN'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['avatar']; - return $userInfo; - } else { - E("获取豆瓣用户信息失败:{$data['msg']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Github.php b/Library/Org/oauth/Driver/Github.php deleted file mode 100644 index bca8d3b8..00000000 --- a/Library/Org/oauth/Driver/Github.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Github extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://github.com/login/oauth/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://github.com/login/oauth/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.github.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* Github 调用公共参数 */ - $params = []; - $header = array("Authorization: bearer {$this->token['access_token']}"); - - $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - parse_str($result, $data); - if($data['access_token'] && $data['token_type']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new \Exception("获取 Github ACCESS_TOKEN出错:未知错误"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('user'); - return !empty($data['id'])?$data['id']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user'); - - if(empty($data['code'])){ - $userInfo['type'] = 'GITHUB'; - $userInfo['name'] = $data['login']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['avatar_url']; - return $userInfo; - } else { - E("获取Github用户信息失败:{$data}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Google.php b/Library/Org/oauth/Driver/Google.php deleted file mode 100644 index 5a9ceac0..00000000 --- a/Library/Org/oauth/Driver/Google.php +++ /dev/null @@ -1,99 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Google extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://accounts.google.com/o/oauth2/auth'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://accounts.google.com/o/oauth2/token'; - - /** - * 获取request_code的额外参数 URL查询字符串格式 - * @var srting - */ - protected $authorize = 'scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://www.googleapis.com/oauth2/v1/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* Google 调用公共参数 */ - $params = []; - $header = array("Authorization: Bearer {$this->token['access_token']}"); - - $data = $this->http($this->url($api), $this->param($params, $param), $method, $header); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['token_type'] && $data['expires_in']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new \Exception("获取 Google ACCESS_TOKEN出错:未知错误"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('userinfo'); - return !empty($data['id'])?$data['id']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('userinfo'); - - if(!empty($data['id'])){ - $userInfo['type'] = 'GOOGLE'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['picture']; - return $userInfo; - } else { - E("获取Google用户信息失败:{$data}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Kaixin.php b/Library/Org/oauth/Driver/Kaixin.php deleted file mode 100644 index 026b5b04..00000000 --- a/Library/Org/oauth/Driver/Kaixin.php +++ /dev/null @@ -1,94 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Kaixin extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'http://api.kaixin001.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.kaixin001.com/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.kaixin001.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 开心网API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 开心网调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new \Exception("获取开心网ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('users/me'); - return !empty($data['uid'])?$data['uid']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users/me'); - - if(!empty($data['uid'])){ - $userInfo['type'] = 'KAIXIN'; - $userInfo['name'] = $data['uid']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['logo50']; - return $userInfo; - } else { - E("获取开心网用户信息失败:{$data['error']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Msn.php b/Library/Org/oauth/Driver/Msn.php deleted file mode 100644 index 30ec22e7..00000000 --- a/Library/Org/oauth/Driver/Msn.php +++ /dev/null @@ -1,100 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Msn extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://login.live.com/oauth20_authorize.srf'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://login.live.com/oauth20_token.srf'; - - /** - * 获取request_code的额外参数 URL查询字符串格式 - * @var srting - */ - protected $authorize = 'scope=wl.basic wl.offline_access wl.signin wl.emails wl.photos'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://apis.live.net/v5.0/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* MSN 调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['token_type'] && $data['expires_in']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new \Exception("获取 MSN ACCESS_TOKEN出错:未知错误"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('me'); - return !empty($data['id'])?$data['id']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('me'); - - if(!empty($data['id'])){ - $userInfo['type'] = 'MSN'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = '微软暂未提供头像URL,请通过 me/picture 接口下载'; - return $userInfo; - } else { - E("获取msn用户信息失败:{$data}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Qq.php b/Library/Org/oauth/Driver/Qq.php deleted file mode 100644 index 339564e1..00000000 --- a/Library/Org/oauth/Driver/Qq.php +++ /dev/null @@ -1,102 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Qq extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://graph.qq.com/oauth2.0/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://graph.qq.com/oauth2.0/token'; - - /** - * 获取request_code的额外参数,可在配置中修改 URL查询字符串格式 - * @var srting - */ - protected $authorize = 'scope=get_user_info,add_share'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://graph.qq.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 腾讯QQ调用公共参数 */ - $params = array( - 'oauth_consumer_key' => $this->AppKey, - 'access_token' => $this->token['access_token'], - 'openid' => $this->openid(), - 'format' => 'json' - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - parse_str($result, $data); - if($data['access_token'] && $data['expires_in']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new \Exception("获取腾讯QQ ACCESS_TOKEN 出错:{$result}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - if($data['access_token']){ - $data = $this->http($this->url('oauth2.0/me'), array('access_token' => $data['access_token'])); - $data = json_decode(trim(substr($data, 9), " );\n"), true); - if(isset($data['openid'])) - return $data['openid']; - } - return null; - } - - public function getOauthInfo(){ - $data = $this->call('user/get_user_info'); - - if($data['ret'] == 0){ - $userInfo['type'] = 'QQ'; - $userInfo['name'] = $data['nickname']; - $userInfo['nick'] = $data['nickname']; - $userInfo['avatar'] = $data['figureurl_2']; - return $userInfo; - } else { - E("获取腾讯QQ用户信息失败:{$data['msg']}"); - } - } -} diff --git a/Library/Org/oauth/Driver/Renren.php b/Library/Org/oauth/Driver/Renren.php deleted file mode 100644 index bdb31520..00000000 --- a/Library/Org/oauth/Driver/Renren.php +++ /dev/null @@ -1,116 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Renren extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://graph.renren.com/oauth/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://graph.renren.com/oauth/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'http://api.renren.com/restserver.do'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'POST'){ - /* 人人网调用公共参数 */ - $params = array( - 'method' => $api, - 'access_token' => $this->token['access_token'], - 'v' => '1.0', - 'format' => 'json', - ); - - $data = $this->http($this->url(''), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 合并默认参数和额外参数 - * @param array $params 默认参数 - * @param array/string $param 额外参数 - * @return array: - */ - protected function param($params, $param){ - $params = parent::param($params, $param); - - /* 签名 */ - ksort($params); - $param = []; - foreach ($params as $key => $value){ - $param[] = "{$key}={$value}"; - } - $sign = implode('', $param).$this->AppSecret; - $params['sig'] = md5($sign); - - return $params; - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['user']['id']){ - $data['openid'] = $data['user']['id']; - unset($data['user']); - return $data; - } else - throw new \Exception("获取人人网ACCESS_TOKEN出错:{$data['error_description']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users.getInfo'); - - if(!isset($data['error_code'])){ - $userInfo['type'] = 'RENREN'; - $userInfo['name'] = $data[0]['name']; - $userInfo['nick'] = $data[0]['name']; - $userInfo['avatar'] = $data[0]['headurl']; - return $userInfo; - } else { - E("获取人人网用户信息失败:{$data['error_msg']}"); - } - } -} diff --git a/Library/Org/oauth/Driver/Sina.php b/Library/Org/oauth/Driver/Sina.php deleted file mode 100644 index f58c1fca..00000000 --- a/Library/Org/oauth/Driver/Sina.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Sina extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.weibo.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.weibo.com/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.weibo.com/2/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET', $multi = false){ - /* 新浪微博调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method, $multi); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['remind_in'] && $data['uid']){ - $data['openid'] = $data['uid']; - unset($data['uid']); - return $data; - } else - throw new \Exception("获取新浪微博ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users.getInfo'); - - if(!isset($data['error_code'])){ - $userInfo['type'] = 'RENREN'; - $userInfo['name'] = $data[0]['name']; - $userInfo['nick'] = $data[0]['name']; - $userInfo['avatar'] = $data[0]['headurl']; - return $userInfo; - } else { - E("获取人人网用户信息失败:{$data['error_msg']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Sohu.php b/Library/Org/oauth/Driver/Sohu.php deleted file mode 100644 index 35827484..00000000 --- a/Library/Org/oauth/Driver/Sohu.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Sohu extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.sohu.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.sohu.com/oauth2/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.sohu.com/rest/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 搜狐API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 搜狐调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token'] && $data['open_id']){ - $data['openid'] = $data['open_id']; - unset($data['open_id']); - return $data; - } else - throw new \Exception("获取搜狐ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('i/prv/1/user/get-basic-info'); - - if('success' == $data['message'] && !empty($data['data'])){ - $userInfo['type'] = 'SOHU'; - $userInfo['name'] = $data['data']['open_id']; - $userInfo['nick'] = $data['data']['nick']; - $userInfo['avatar'] = $data['data']['icon']; - return $userInfo; - } else { - E("获取搜狐用户信息失败:{$data['message']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/T163.php b/Library/Org/oauth/Driver/T163.php deleted file mode 100644 index bc5cc86c..00000000 --- a/Library/Org/oauth/Driver/T163.php +++ /dev/null @@ -1,95 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class T163 extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://api.t.163.com/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://api.t.163.com/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://api.t.163.com/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 新浪微博调用公共参数 */ - $params = array( - 'oauth_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['uid'] && $data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $data['uid']; - unset($data['uid']); - return $data; - } else - throw new \Exception("获取网易微博ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - - $data = $this->call('users/show'); - return !empty($data['id'])?$data['id']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users/show'); - - if($data['error_code'] == 0){ - $userInfo['type'] = 'T163'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['screen_name']; - $userInfo['avatar'] = str_replace('w=48&h=48', 'w=180&h=180', $data['profile_image_url']); - return $userInfo; - } else { - E("获取网易微博用户信息失败:{$data['error']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Taobao.php b/Library/Org/oauth/Driver/Taobao.php deleted file mode 100644 index b765f771..00000000 --- a/Library/Org/oauth/Driver/Taobao.php +++ /dev/null @@ -1,97 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Taobao extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://oauth.taobao.com/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://oauth.taobao.com/token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://eco.taobao.com/router/rest'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 淘宝网调用公共参数 */ - $params = array( - 'method' => $api, - 'access_token' => $this->token['access_token'], - 'format' => 'json', - 'v' => '2.0', - ); - $data = $this->http($this->url(''), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['taobao_user_id']){ - $data['openid'] = $data['taobao_user_id']; - unset($data['taobao_user_id']); - return $data; - } else - throw new \Exception("获取淘宝网ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $fields = 'user_id,nick,sex,buyer_credit,avatar,has_shop,vip_info'; - $data = $this->call('taobao.user.buyer.get', "fields={$fields}"); - - if(!empty($data['user_buyer_get_response']['user'])){ - $user = $data['user_buyer_get_response']['user']; - $userInfo['type'] = 'TAOBAO'; - $userInfo['name'] = $user['user_id']; - $userInfo['nick'] = $user['nick']; - $userInfo['avatar'] = $user['avatar']; - return $userInfo; - } else { - E("获取淘宝网用户信息失败:{$data['error_response']['msg']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/Tencent.php b/Library/Org/oauth/Driver/Tencent.php deleted file mode 100644 index 030dd5dc..00000000 --- a/Library/Org/oauth/Driver/Tencent.php +++ /dev/null @@ -1,98 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class Tencent extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://open.t.qq.com/cgi-bin/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://open.t.qq.com/cgi-bin/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://open.t.qq.com/api/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 微博API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET', $multi = false){ - /* 腾讯微博调用公共参数 */ - $params = array( - 'oauth_consumer_key' => $this->AppKey, - 'access_token' => $this->token['access_token'], - 'openid' => $this->openid(), - 'clientip' => get_client_ip(), - 'oauth_version' => '2.a', - 'scope' => 'all', - 'format' => 'json' - ); - - $data = $this->http($this->url($api), $this->param($params, $param), $method, $multi); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - parse_str($result, $data); - $data = array_merge($data, ['openid' => $_GET['openid'], 'openkey' => $_GET['openkey']]); - if($data['access_token'] && $data['expires_in'] && $data['openid']) - return $data; - else - throw new \Exception("获取腾讯微博 ACCESS_TOKEN 出错:{$result}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - return null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('users.getInfo'); - - if(!isset($data['error_code'])){ - $userInfo['type'] = 'RENREN'; - $userInfo['name'] = $data[0]['name']; - $userInfo['nick'] = $data[0]['name']; - $userInfo['avatar'] = $data[0]['headurl']; - return $userInfo; - } else { - E("获取人人网用户信息失败:{$data['error_msg']}"); - } - } - -} diff --git a/Library/Org/oauth/Driver/X360.php b/Library/Org/oauth/Driver/X360.php deleted file mode 100644 index 28ac1ccb..00000000 --- a/Library/Org/oauth/Driver/X360.php +++ /dev/null @@ -1,93 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Oauth\Driver; -use Think\Oauth\Driver; - -class X360 extends Driver{ - /** - * 获取requestCode的api接口 - * @var string - */ - protected $getRequestCodeURL = 'https://openapi.360.cn/oauth2/authorize'; - - /** - * 获取access_token的api接口 - * @var string - */ - protected $getAccessTokenURL = 'https://openapi.360.cn/oauth2/access_token'; - - /** - * API根路径 - * @var string - */ - protected $apiBase = 'https://openapi.360.cn/'; - - /** - * 组装接口调用参数 并调用接口 - * @param string $api 360开放平台API - * @param string $param 调用API的额外参数 - * @param string $method HTTP请求方法 默认为GET - * @return json - */ - public function call($api, $param = '', $method = 'GET'){ - /* 360开放平台调用公共参数 */ - $params = array( - 'access_token' => $this->token['access_token'], - ); - - $data = $this->http($this->url($api, '.json'), $this->param($params, $param), $method); - return json_decode($data, true); - } - - /** - * 解析access_token方法请求后的返回值 - * @param string $result 获取access_token的方法的返回值 - */ - protected function parseToken($result){ - $data = json_decode($result, true); - if($data['access_token'] && $data['expires_in'] && $data['refresh_token']){ - $data['openid'] = $this->getOpenId(); - return $data; - } else - throw new \Exception("获取360开放平台ACCESS_TOKEN出错:{$data['error']}"); - } - - /** - * 获取当前授权应用的openid - * @return string - */ - public function getOpenId(){ - if(!empty($this->token['openid'])) - return $this->token['openid']; - $data = $this->call('user/me'); - return !empty($data['id'])?$data['id']:null; - } - - /** - * 获取当前登录的用户信息 - * @return array - */ - public function getOauthInfo(){ - $data = $this->call('user/me'); - - if($data['error_code'] == 0){ - $userInfo['type'] = 'X360'; - $userInfo['name'] = $data['name']; - $userInfo['nick'] = $data['name']; - $userInfo['avatar'] = $data['avatar']; - return $userInfo; - } else { - E("获取360用户信息失败:{$data['error']}"); - } - } - -} diff --git a/Library/Org/transform/Driver/Json.php b/Library/Org/transform/Driver/Json.php deleted file mode 100644 index 6a4f0b84..00000000 --- a/Library/Org/transform/Driver/Json.php +++ /dev/null @@ -1,22 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Transform\Driver; - -class Json{ - public function encode($data){ - return json_encode($data); - } - - public function decode($data, $assoc = true){ - return json_decode($data, $assoc); - } -} \ No newline at end of file diff --git a/Library/Org/transform/Driver/Xml.php b/Library/Org/transform/Driver/Xml.php deleted file mode 100644 index 0e0d20f7..00000000 --- a/Library/Org/transform/Driver/Xml.php +++ /dev/null @@ -1,119 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Transform\Driver; - -class Xml{ - /** - * XML数据默认配置项 - * @var array - */ - private $config = [ - 'root_name' => 'think', //根节点名称 - 'root_attr' => [], //根节点属性 - 'item_name' => 'item', //数字节点转换的名称 - 'item_key' => 'id', //数字节点转换的属性名 - ]; - - /** - * 编码XML数据 - * @param mixed $data 被编码的数据 - * @param array $config 数据配置项 - * @return string 编码后的XML数据 - */ - public function encode($data, array $config = []) { - //初始化配置 - $config = array_merge($this->config, $config); - - //创建XML对象 - $xml = new \SimpleXMLElement("<{$config['root_name']}>"); - self::data2xml($xml, $data, $config['item_name'], $config['item_key']); - return $xml->asXML(); - } - - /** - * 解码XML数据 - * @param string $str XML字符串 - * @param boolean $assoc 是否转换为数组 - * @param array $config 数据配置项 - * @return string 解码后的XML数据 - */ - public function decode($str, $assoc = true, array $config = []){ - //初始化配置 - $config = array_merge($this->config, $config); - - //创建XML对象 - $xml = new \SimpleXMLElement($str); - if($assoc){ - self::xml2data($xml, $data, $config['item_name'], $config['item_key']); - return $data; - } - - return $xml; - } - - /** - * 数据XML编码 - * @static - * @access public - * @param mixed $data 数据 - * @param string $item 数字索引时的节点名称 - * @param string $id 数字索引key转换为的属性名 - * @return string - */ - static public function data2xml(SimpleXMLElement $xml, $data, $item = 'item', $id = 'id') { - foreach ($data as $key => $value) { - //指定默认的数字key - if(is_numeric($key)){ - $id && $val = $key; - $key = $item; - } - - //添加子元素 - if(is_array($value) || is_object($value)){ - $child = $xml->addChild($key); - self::data2xml($child, $value, $item, $id); - } else { - $child = $xml->addChild($key, $value); - } - - //记录原来的key - isset($val) && $child->addAttribute($id, $val); - } - } - - /** - * 数据XML解码 - * @static - * @access public - * @param SimpleXMLElement $xml xml对象 - * @param array $data 解码后的数据 - * @param string $item 数字索引时的节点名称 - * @param string $id 数字索引key转换为的属性名 - */ - static public function xml2data(SimpleXMLElement $xml, &$data, $item = 'item', $id = 'id'){ - foreach ($xml->children() as $items) { - $key = $items->getName(); - $attr = $items->attributes(); - if($key == $item && isset($attr[$id])){ - $key = strval($attr[$id]); - } - - if($items->count()){ - self::xml2data($items, $val); - } else { - $val = strval($items); - } - - $data[$key] = $val; - } - } -} diff --git a/Library/Org/upload.php b/Library/Org/upload.php deleted file mode 100644 index 31941de7..00000000 --- a/Library/Org/upload.php +++ /dev/null @@ -1,514 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Upload { - protected $config = [ - 'max_size' => -1, // 上传文件的最大值 - 'support_multi' => true, // 是否支持多文件上传 - 'allow_exts' => [], // 允许上传的文件后缀 留空不作后缀检查 - 'allow_types' => [], // 允许上传的文件类型 留空不做检查 - 'thumb' => false, // 使用对上传图片进行缩略图处理 - 'thumb_max_width' => '',// 缩略图最大宽度 - 'thumb_max_height' => '',// 缩略图最大高度 - 'thumb_prefix' => 'thumb_',// 缩略图前缀 - 'thumb_suffix' => '', - 'thumb_path' => '',// 缩略图保存路径 - 'thumb_file' => '',// 缩略图文件名 - 'thumb_ext' => '',// 缩略图扩展名 - 'thumb_remove_origin' => false,// 是否移除原图 - 'zip_images' => false,// 压缩图片文件上传 - 'auto_sub' => false,// 启用子目录保存文件 - 'sub_type' => 'hash',// 子目录创建方式 可以使用hash date custom - 'sub_dir' => '', // 子目录名称 subType为custom方式后有效 - 'date_format' => 'Ymd', - 'hash_level' => 1, // hash的目录层次 - 'save_path' => '',// 上传文件保存路径 - 'auto_check' => true, // 是否自动检查附件 - 'upload_replace' => false,// 存在同名是否覆盖 - 'save_rule' => 'uniqid',// 上传文件命名规则 - 'hash_type' => 'md5_file',// 上传文件Hash规则函数名 - ]; - - // 错误信息 - private $error = ''; - // 上传成功的文件信息 - private $uploadFileInfo ; - - 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]); - } - - /** - * 架构函数 - * @access public - * @param array $config 上传参数 - */ - public function __construct($config=[]) { - if(is_array($config)) { - $this->config = array_merge($this->config,$config); - } - } - - /** - * 上传一个文件 - * @access protected - * @param mixed $name 数据 - * @param string $value 数据表名 - * @return string - */ - protected function save($file) { - $filename = $file['save_path'].$file['savename']; - if(!$this->upload_replace && is_file($filename)) { - // 不覆盖同名文件 - $this->error = '文件已经存在!'.$filename; - return false; - } - // 如果是图像文件 检测文件格式 - if( in_array(strtolower($file['extension']),['gif','jpg','jpeg','bmp','png','swf'])) { - $info = getimagesize($file['tmp_name']); - if(false === $info || ('gif' == strtolower($file['extension']) && empty($info['bits']))){ - $this->error = '非法图像文件'; - return false; - } - } - if(!move_uploaded_file($file['tmp_name'], $this->autoCharset($filename,'utf-8','gbk'))) { - $this->error = '文件上传保存错误!'; - return false; - } - if($this->thumb && in_array(strtolower($file['extension']),['gif','jpg','jpeg','bmp','png'])) { - $image = getimagesize($filename); - if(false !== $image) { - //是图像文件生成缩略图 - $thumbWidth = explode(',',$this->thumb_max_width); - $thumbHeight = explode(',',$this->thumb_max_height); - $thumb_prefix = explode(',',$this->thumb_prefix); - $thumb_suffix = explode(',',$this->thumb_suffix); - $thumb_file = explode(',',$this->thumb_file); - $thumb_path = $this->thumb_path?$this->thumb_path:dirname($filename).'/'; - $thumb_ext = $this->thumb_ext ? $this->thumb_ext : $file['extension']; //自定义缩略图扩展名 - // 生成图像缩略图 - for($i=0,$len=count($thumbWidth); $i<$len; $i++) { - if(!empty($thumb_file[$i])) { - $thumbname = $thumb_file[$i]; - }else{ - $prefix = isset($thumb_prefix[$i])?$thumb_prefix[$i]:$thumb_prefix[0]; - $suffix = isset($thumb_suffix[$i])?$thumb_suffix[$i]:$thumb_suffix[0]; - $thumbname = $prefix.basename($filename,'.'.$file['extension']).$suffix; - } - Image::thumb($filename,$thumb_path.$thumbname.'.'.$thumb_ext,'',$thumbWidth[$i],$thumbHeight[$i],true); - } - if($this->thumb_remove_origin) { - // 生成缩略图之后删除原图 - unlink($filename); - } - } - } - if($this->zipImags) { - // TODO 对图片压缩包在线解压 - - } - return true; - } - - /** - * 上传所有文件 - * @access public - * @param string $savePath 上传文件保存路径 - * @return string - */ - public function upload($savePath ='') { - //如果不指定保存文件名,则由系统默认 - if(empty($savePath)) - $savePath = $this->save_path; - // 检查上传目录 - if(!is_dir($savePath)) { - // 检查目录是否编码后的 - if(is_dir(base64_decode($savePath))) { - $savePath = base64_decode($savePath); - }else{ - // 尝试创建目录 - if(!mkdir($savePath)){ - $this->error = '上传目录'.$savePath.'不存在'; - return false; - } - } - }else { - if(!is_writeable($savePath)) { - $this->error = '上传目录'.$savePath.'不可写'; - return false; - } - } - $fileInfo = []; - $isUpload = false; - - // 获取上传的文件信息 - // 对$_FILES数组信息处理 - $files = $this->dealFiles($_FILES); - foreach($files as $key => $file) { - //过滤无效的上传 - if(!empty($file['name'])) { - //登记上传文件的扩展信息 - if(!isset($file['key'])) $file['key'] = $key; - $file['extension'] = $this->getExt($file['name']); - $file['savepath'] = $savePath; - $file['savename'] = $this->getSaveName($file); - - // 自动检查附件 - if($this->auto_check) { - if(!$this->check($file)) - return false; - } - - //保存上传文件 - if(!$this->save($file)) return false; - if(function_exists($this->hash_type)) { - $fun = $this->hash_type; - $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk')); - } - //上传成功后保存文件信息,供其他地方调用 - unset($file['tmp_name'],$file['error']); - $fileInfo[] = $file; - $isUpload = true; - } - } - if($isUpload) { - $this->uploadFileInfo = $fileInfo; - return true; - }else { - $this->error = '没有选择上传文件'; - return false; - } - } - - /** - * 上传单个上传字段中的文件 支持多附件 - * @access public - * @param array $file 上传文件信息 - * @param string $savePath 上传文件保存路径 - * @return string - */ - public function uploadOne($file,$savePath=''){ - //如果不指定保存文件名,则由系统默认 - if(empty($savePath)) - $savePath = $this->save_path; - // 检查上传目录 - if(!is_dir($savePath)) { - // 尝试创建目录 - if(!mkdir($savePath,0777,true)){ - $this->error = '上传目录'.$savePath.'不存在'; - return false; - } - }else { - if(!is_writeable($savePath)) { - $this->error = '上传目录'.$savePath.'不可写'; - return false; - } - } - //过滤无效的上传 - if(!empty($file['name'])) { - $fileArray = []; - if(is_array($file['name'])) { - $keys = array_keys($file); - $count = count($file['name']); - for ($i=0; $i<$count; $i++) { - foreach ($keys as $key) - $fileArray[$i][$key] = $file[$key][$i]; - } - }else{ - $fileArray[] = $file; - } - $info = []; - foreach ($fileArray as $key=>$file){ - //登记上传文件的扩展信息 - $file['extension'] = $this->getExt($file['name']); - $file['savepath'] = $savePath; - $file['savename'] = $this->getSaveName($file); - // 自动检查附件 - if($this->auto_check) { - if(!$this->check($file)) - return false; - } - //保存上传文件 - if(!$this->save($file)) return false; - if(function_exists($this->hash_type)) { - $fun = $this->hash_type; - $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk')); - } - unset($file['tmp_name'],$file['error']); - $info[] = $file; - } - // 返回上传的文件信息 - return $info; - }else { - $this->error = '没有选择上传文件'; - return false; - } - } - - /** - * 转换上传文件数组变量为正确的方式 - * @access protected - * @param array $files 上传的文件变量 - * @return array - */ - protected function dealFiles($files) { - $fileArray = []; - $n = 0; - foreach ($files as $key=>$file){ - if(is_array($file['name'])) { - $keys = array_keys($file); - $count = count($file['name']); - for ($i=0; $i<$count; $i++) { - $fileArray[$n]['key'] = $key; - foreach ($keys as $_key){ - $fileArray[$n][$_key] = $file[$_key][$i]; - } - $n++; - } - }else{ - $fileArray[$key] = $file; - } - } - return $fileArray; - } - - /** - * 获取错误代码信息 - * @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 protected - * @param string $filename 数据 - * @return string - */ - protected function getSaveName($filename) { - $rule = $this->save_rule; - if(empty($rule)) {//没有定义命名规则,则保持文件名不变 - $saveName = $filename['name']; - }else { - if(function_exists($rule)) { - //使用函数生成一个唯一文件标识号 - $saveName = $rule().".".$filename['extension']; - }else { - //使用给定的文件名作为标识号 - $saveName = $rule.".".$filename['extension']; - } - } - if($this->auto_sub) { - // 使用子目录保存文件 - $filename['savename'] = $saveName; - $saveName = $this->getSubName($filename).$saveName; - } - return $saveName; - } - - /** - * 获取子目录的名称 - * @access protected - * @param array $file 上传的文件信息 - * @return string - */ - protected function getSubName($file) { - switch($this->sub_type) { - case 'custom': - $dir = $this->sub_dir; - break; - case 'date': - $dir = date($this->date_format,time()).'/'; - break; - case 'hash': - default: - $name = md5($file['savename']); - $dir = ''; - for($i=0;$i<$this->hash_level;$i++) { - $dir .= $name{$i}.'/'; - } - break; - } - if(!is_dir($file['savepath'].$dir)) { - mkdir($file['savepath'].$dir,0777,true); - } - return $dir; - } - - /** - * 检查上传的文件 - * @access protected - * @param array $file 文件信息 - * @return boolean - */ - protected 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($file['extension'])) { - $this->error ='上传文件类型不允许'; - return false; - } - - //检查是否合法上传 - if(!$this->checkUpload($file['tmp_name'])) { - $this->error = '非法上传文件!'; - return false; - } - return true; - } - - // 自动转换字符集 支持数组转换 - protected function autoCharset($fContents, $from='gbk', $to='utf-8') { - $from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from; - $to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to; - if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) { - //如果编码相同或者非字符串标量则不转换 - return $fContents; - } - if (function_exists('mb_convert_encoding')) { - return mb_convert_encoding($fContents, $to, $from); - } elseif (function_exists('iconv')) { - return iconv($from, $to, $fContents); - } else { - return $fContents; - } - } - - /** - * 检查上传的文件类型是否合法 - * @access protected - * @param string $type 数据 - * @return boolean - */ - protected function checkType($type) { - if(!empty($this->allow_types)) - return in_array(strtolower($type),$this->allow_types); - return true; - } - - - /** - * 检查上传的文件后缀是否合法 - * @access protected - * @param string $ext 后缀名 - * @return boolean - */ - protected function checkExt($ext) { - if(!empty($this->allow_exts)) - return in_array(strtolower($ext),$this->allow_exts,true); - return true; - } - - /** - * 检查文件大小是否合法 - * @access protected - * @param integer $size 数据 - * @return boolean - */ - protected function checkSize($size) { - return !($size > $this->max_size) || (-1 == $this->max_size); - } - - /** - * 检查文件是否非法提交 - * @access protected - * @param string $filename 文件名 - * @return boolean - */ - protected function checkUpload($filename) { - return is_uploaded_file($filename); - } - - /** - * 取得上传文件的后缀 - * @access protected - * @param string $filename 文件名 - * @return boolean - */ - protected function getExt($filename) { - return pathinfo($filename,PATHINFO_EXTENSION); - } - - /** - * 取得上传文件的信息 - * @access public - * @return array - */ - public function getUploadFileInfo() { - return $this->uploadFileInfo; - } - - /** - * 取得最后一次错误信息 - * @access public - * @return string - */ - public function getErrorMsg() { - return $this->error; - } -} diff --git a/Library/Org/validate.php b/Library/Org/validate.php deleted file mode 100644 index 8c92c3bf..00000000 --- a/Library/Org/validate.php +++ /dev/null @@ -1,189 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Validate { - - protected $validate = []; // 自动验证定义 - // 是否批处理验证 - protected $patchValidate = false; - protected $error = ''; - - public function rule($rule){ - $this->validate = $rule; - return $this; - } - - public function getError(){ - return $this->error; - } - - /** - * 自动表单验证 - * @access protected - * @param array $data 创建数据 - * @param string $type 创建类型 - * @return boolean - */ - public function valid($data,$rule=[]) { - $validate = $rule?$rule:$this->validate; - // 属性验证 - if($validate) { // 如果设置了数据自动验证则进行数据验证 - if($this->patchValidate) { // 重置验证错误信息 - $this->error = []; - } - foreach($validate as $key=>$val) { - // 验证因子定义格式 - // array(field,rule,message,condition,type,params) - // 判断是否需要执行验证 - if(0==strpos($val[2],'{%') && strpos($val[2],'}')) - // 支持提示信息的多语言 使用 {%语言定义} 方式 - $val[2] = L(substr($val[2],2,-1)); - $val[3] = isset($val[3])?$val[3]:0; - $val[4] = isset($val[4])?$val[4]:'regex'; - // 判断验证条件 - if( 1 == $val[3] || (2 == $val[3] && '' != trim($data[$val[0]])) || (0 == $val[3] && isset($data[$val[0]])) ) { - if(false === $this->_validationField($data,$val)) - return false; - } - } - // 批量验证的时候最后返回错误 - if(!empty($this->error)) return false; - } - return true; - } - - /** - * 验证表单字段 支持批量验证 - * 如果批量验证返回错误的数组信息 - * @access protected - * @param array $data 创建数据 - * @param array $val 验证因子 - * @return boolean - */ - protected function _validationField($data,$val) { - if(false === $this->_validationFieldItem($data,$val)){ - if($this->patchValidate) { - $this->error[$val[0]] = $val[2]; - }else{ - $this->error = $val[2]; - return false; - } - } - return ; - } - - /** - * 根据验证因子验证字段 - * @access protected - * @param array $data 创建数据 - * @param array $val 验证因子 - * @return boolean - */ - protected function _validationFieldItem($data,$val) { - switch(strtolower(trim($val[4]))) { - case 'callback':// 调用方法进行验证 - $args = isset($val[5])?(array)$val[5]:[]; - if(is_string($val[0]) && strpos($val[0], ',')) - $val[0] = explode(',', $val[0]); - if(is_array($val[0])){ - // 支持多个字段验证 - foreach($val[0] as $field) - $_data[$field] = $data[$field]; - array_unshift($args, $_data); - }else{ - array_unshift($args, $data[$val[0]]); - } - return call_user_func_array($val[1], $args); - case 'confirm': // 验证两个字段是否相同 - return $data[$val[0]] == $data[$val[1]]; - default: // 检查附加规则 - return $this->check($data[$val[0]],$val[1],$val[4]); - } - } - - /** - * 验证数据 支持 in between equal length regex expire ip_allow ip_deny - * @access public - * @param string $value 验证数据 - * @param mixed $rule 验证表达式 - * @param string $type 验证方式 默认为正则验证 - * @return boolean - */ - public function check($value,$rule,$type='regex'){ - $type = strtolower(trim($type)); - switch($type) { - case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组 - case 'notin': - $range = is_array($rule)? $rule : explode(',',$rule); - return $type == 'in' ? in_array($value ,$range) : !in_array($value ,$range); - case 'between': // 验证是否在某个范围 - case 'notbetween': // 验证是否不在某个范围 - if (is_array($rule)){ - $min = $rule[0]; - $max = $rule[1]; - }else{ - list($min,$max) = explode(',',$rule); - } - return $type == 'between' ? $value>=$min && $value<=$max : $value<$min || $value>$max; - case 'equal': // 验证是否等于某个值 - case 'notequal': // 验证是否等于某个值 - return $type == 'equal' ? $value == $rule : $value != $rule; - case 'length': // 验证长度 - $length = mb_strlen($value,'utf-8'); // 当前数据长度 - if(strpos($rule,',')) { // 长度区间 - list($min,$max) = explode(',',$rule); - return $length >= $min && $length <= $max; - }else{// 指定长度 - return $length == $rule; - } - case 'expire': - list($start,$end) = explode(',',$rule); - if(!is_numeric($start)) $start = strtotime($start); - if(!is_numeric($end)) $end = strtotime($end); - return NOW_TIME >= $start && NOW_TIME <= $end; - case 'ip_allow': // IP 操作许可验证 - return in_array($_SERVER['REMOTE_ADDR'],explode(',',$rule)); - case 'ip_deny': // IP 操作禁止验证 - return !in_array($_SERVER['REMOTE_ADDR'],explode(',',$rule)); - case 'regex': - default: // 默认使用正则验证 可以使用验证类中定义的验证名称 - // 检查附加规则 - return $this->regex($value,$rule); - } - } - - /** - * 使用正则验证数据 - * @access public - * @param string $value 要验证的数据 - * @param string $rule 验证规则 - * @return boolean - */ - public function regex($value,$rule) { - $validate = [ - 'require' => '/.+/', - 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', - 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', - 'currency' => '/^\d+(\.\d+)?$/', - 'number' => '/^\d+$/', - 'zip' => '/^\d{6}$/', - 'integer' => '/^[-\+]?\d+$/', - 'double' => '/^[-\+]?\d+(\.\d+)?$/', - 'english' => '/^[A-Za-z]+$/', - ]; - // 检查是否有内置的正则表达式 - if(isset($validate[strtolower($rule)])) - $rule = $validate[strtolower($rule)]; - return preg_match($rule,$value)===1; - } -} diff --git a/Library/Think/App.php b/Library/Think/App.php deleted file mode 100644 index c5e13c48..00000000 --- a/Library/Think/App.php +++ /dev/null @@ -1,295 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; -use Think\Exception; - -/** - * App 应用管理 - * @author liu21st - */ -class App { - - /** - * 执行应用程序 - * @access public - * @return void - */ - static public function run($config) { - - // 日志初始化 - Log::init(['type'=>$config['log_type'],'log_path'=> $config['log_path']]); - - // 缓存初始化 - Cache::connect(['type'=>$config['cache_type'],'temp'=> $config['cache_path']]); - - // 加载框架底层语言包 - is_file(THINK_PATH.'Lang/'.strtolower(Config::get('default_lang')).EXT) && Lang::set(include THINK_PATH.'Lang/'.strtolower(Config::get('default_lang')).EXT); - - // 启动session - if(!IS_CLI) { - Session::init(['prefix'=>$config['session_prefix'],'auto_start'=>$config['session_auto_start']]); - } - if(is_file(APP_PATH.'build.php')) { // 自动化创建脚本 - Create::build(include APP_PATH.'build.php'); - } - // 监听app_init - Hook::listen('app_init'); - - define('COMMON_PATH', APP_PATH . $config['common_module'].'/'); - // 加载全局初始化文件 - if(is_file( COMMON_PATH . 'init' . EXT )) { - include COMMON_PATH . 'init' . EXT; - }else{ - // 检测全局配置文件 - if(is_file(COMMON_PATH . 'config' . EXT)) { - $config = Config::set(include COMMON_PATH . 'config' . EXT); - } - // 加载全局别名文件 - if(is_file(COMMON_PATH . 'alias' . EXT)) { - Loader::addMap(include COMMON_PATH . 'alias' . EXT); - } - // 加载全局公共文件 - if(is_file( COMMON_PATH . 'common' . EXT)) { - include COMMON_PATH . 'common' . EXT; - } - if(is_file(COMMON_PATH . 'tags' . EXT)) { - // 全局行为扩展文件 - Hook::import(include COMMON_PATH . 'tags' . EXT); - } - } - - // 应用URL调度 - self::dispatch($config); - - // 监听app_run - Hook::listen('app_run'); - - // 执行操作 - if(!preg_match('/^[A-Za-z](\/|\w)*$/',CONTROLLER_NAME)){ // 安全检测 - $instance = false; - }elseif($config['action_bind_class']){ - // 操作绑定到类:模块\Controller\控制器\操作 - $layer = CONTROLLER_LAYER; - if(is_dir(MODULE_PATH.$layer.'/'.CONTROLLER_NAME)){ - $namespace = MODULE_NAME.'\\'.$layer.'\\'.CONTROLLER_NAME.'\\'; - }else{ - // 空控制器 - $namespace = MODULE_NAME.'\\'.$layer.'\\_empty\\'; - } - $actionName = strtolower(ACTION_NAME); - if(class_exists($namespace.$actionName)){ - $class = $namespace.$actionName; - }elseif(class_exists($namespace.'_empty')){ - // 空操作 - $class = $namespace.'_empty'; - }else{ - throw new Exception('_ERROR_ACTION_:'.ACTION_NAME); - } - $instance = new $class; - // 操作绑定到类后 固定执行run入口 - $action = 'run'; - }else{ - $instance = Loader::controller(CONTROLLER_NAME); - // 获取当前操作名 - $action = ACTION_NAME . $config['action_suffix']; - } - if(!$instance) { - throw new Exception('[ ' . MODULE_NAME . '\\'.CONTROLLER_LAYER.'\\' . parse_name(CONTROLLER_NAME, 1) . ' ] not exists'); - } - - try{ - // 操作方法开始监听 - $call = [$instance, $action]; - Hook::listen('action_begin', $call); - if(!preg_match('/^[A-Za-z](\w)*$/', $action)){ - // 非法操作 - throw new \ReflectionException(); - } - //执行当前操作 - $method = new \ReflectionMethod($instance, $action); - if($method->isPublic()) { - // URL参数绑定检测 - if($config['url_params_bind'] && $method->getNumberOfParameters() > 0){ - switch($_SERVER['REQUEST_METHOD']) { - case 'POST': - $vars = array_merge($_GET, $_POST); - break; - case 'PUT': - parse_str(file_get_contents('php://input'), $vars); - break; - default: - $vars = $_GET; - } - $params = $method->getParameters(); - $paramsBindType = $config['url_parmas_bind_type']; - foreach ($params as $param){ - $name = $param->getName(); - if( 1 == $paramsBindType && !empty($vars) ){ - $args[] = array_shift($vars); - }if(0 == $paramsBindType && isset($vars[$name])) { - $args[] = $vars[$name]; - }elseif($param->isDefaultValueAvailable()){ - $args[] = $param->getDefaultValue(); - }else{ - E('_PARAM_ERROR_:' . $name); - } - } - array_walk_recursive($args,'Input::filterExp'); - $method->invokeArgs($instance, $args); - }else{ - $method->invoke($instance); - } - // 操作方法执行完成监听 - Hook::listen('action_end', $call); - }else{ - // 操作方法不是Public 抛出异常 - throw new \ReflectionException(); - } - } catch (\ReflectionException $e) { - // 操作不存在 - if(method_exists($instance, '_empty')) { - $method = new \ReflectionMethod($instance, '_empty'); - $method->invokeArgs($instance, [$action, '']); - }else{ - throw new Exception('[ ' . (new \ReflectionClass($instance))->getName() . ':' . $action . ' ] not exists ', 404); - } - } - // 监听app_end - Hook::listen('app_end'); - return ; - } - - /** - * URL调度 - * @access public - * @return void - */ - static public function dispatch($config) { - if(isset($_GET[$config['var_pathinfo']])) { // 判断URL里面是否有兼容模式参数 - $_SERVER['PATH_INFO'] = $_GET[$config['var_pathinfo']]; - unset($_GET[$config['var_pathinfo']]); - }elseif(IS_CLI){ // CLI模式下 index.php module/controller/action/params/... - $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; - } - - // 检测域名部署 - if(!IS_CLI && isset($config['sub_domain_deploy']) && $config['sub_domain_deploy']) { - Route::checkDomain($config); - } - - // 监听path_info - Hook::listen('path_info'); - // 分析PATHINFO信息 - if(!isset($_SERVER['PATH_INFO']) && $_SERVER['SCRIPT_NAME'] != $_SERVER['PHP_SELF']) { - $types = explode(',', $config['pathinfo_fetch']); - foreach ($types as $type){ - if(0 === strpos($type, ':')) {// 支持函数判断 - $_SERVER['PATH_INFO'] = call_user_func(substr($type,1)); - break; - }elseif(!empty($_SERVER[$type])) { - $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ? - substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; - break; - } - } - } - - if(empty($_SERVER['PATH_INFO'])) { - $_SERVER['PATH_INFO'] = ''; - define('__INFO__',''); - define('__EXT__',''); - }else{ - define('__INFO__',trim($_SERVER['PATH_INFO'],'/')); - // URL后缀 - define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'],PATHINFO_EXTENSION))); - $_SERVER['PATH_INFO'] = __INFO__; - if(__INFO__ && !defined('BIND_MODULE')){ - if($config['url_deny_suffix'] && preg_match('/\.('.$config['url_deny_suffix'].')$/i', __INFO__)){ - exit; - } - $paths = explode($config['pathinfo_depr'], __INFO__,2); - // 获取URL中的模块名 - if($config['require_module'] && !isset($_GET[$config['var_module']])) { - $_GET[$config['var_module']] = array_shift($paths); - $_SERVER['PATH_INFO'] = implode('/', $paths); - } - } - } - - // 获取模块名称 - define('MODULE_NAME', defined('BIND_MODULE')? BIND_MODULE : self::getModule($config)); - - // 模块初始化 - if(MODULE_NAME && $config['common_module'] != MODULE_NAME && is_dir( APP_PATH . MODULE_NAME )) { - Hook::listen('app_begin'); - define('MODULE_PATH', APP_PATH . MODULE_NAME . '/'); - define('VIEW_PATH', MODULE_PATH.VIEW_LAYER.'/'); - - // 加载模块初始化文件 - if(is_file( MODULE_PATH . 'init' . EXT )) { - include MODULE_PATH . 'init' . EXT; - $config = Config::get(); - }else{ - // 检测项目(或模块)配置文件 - if(is_file(MODULE_PATH . 'config' . EXT)) { - $config = Config::set(include MODULE_PATH . 'config' . EXT); - } - if($config['app_status'] && is_file(MODULE_PATH . $config['app_status'] . EXT)) { - // 加载对应的项目配置文件 - $config = Config::set(include MODULE_PATH . $config['app_status'] . EXT); - } - // 加载别名文件 - if(is_file(MODULE_PATH . 'alias' . EXT)) { - Loader::addMap(include MODULE_PATH . 'alias' . EXT); - } - // 加载公共文件 - if(is_file( MODULE_PATH . 'common' . EXT)) { - include MODULE_PATH . 'common' . EXT; - } - if(is_file(MODULE_PATH . 'tags' . EXT)) { - // 行为扩展文件 - Hook::import(include MODULE_PATH . 'tags' . EXT); - } - } - }else{ - throw new Exception('module not exists :' . MODULE_NAME); - } - // 路由检测和控制器、操作解析 - Route::check($_SERVER['PATH_INFO'],$config); - - // 获取控制器名 - define('CONTROLLER_NAME', strip_tags(strtolower(isset($_GET[$config['var_controller']]) ? $_GET[$config['var_controller']] : $config['default_controller']))); - - // 获取操作名 - define('ACTION_NAME', strip_tags(strtolower(isset($_GET[$config['var_action']]) ? $_GET[$config['var_action']] : $config['default_action']))); - - unset($_GET[$config['var_action']], $_GET[$config['var_controller']], $_GET[$config['var_module']]); - //保证$_REQUEST正常取值 - $_REQUEST = array_merge($_POST, $_GET); - } - - static private function getModule($config){ - $module = strtolower(isset($_GET[$config['var_module']]) ? $_GET[$config['var_module']] : $config['default_module']); - if($maps = $config['url_module_map']) { - if(isset($maps[$module])) { - // 记录当前别名 - define('MODULE_ALIAS',$module); - // 获取实际的项目名 - $module = $maps[MODULE_ALIAS]; - }elseif(array_search($module,$maps)){ - // 禁止访问原始项目 - $module = ''; - } - } - return strip_tags($module); - } -} diff --git a/Library/Think/Behavior/ContentReplace.php b/Library/Think/Behavior/ContentReplace.php deleted file mode 100644 index 76e3300b..00000000 --- a/Library/Think/Behavior/ContentReplace.php +++ /dev/null @@ -1,65 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Behavior; -use Think\Config; - -/** - * 系统行为扩展:模板内容输出替换 - * @category Think - * @package Think - * @subpackage Behavior - * @author liu21st - */ -class ContentReplace { - - // 行为扩展的执行入口必须是run - public function run(&$content){ - $content = $this->templateContentReplace($content); - } - - /** - * 模板内容替换 - * @access protected - * @param string $content 模板内容 - * @return string - */ - protected function templateContentReplace($content) { - if(IS_CGI) { - //CGI/FASTCGI模式下 - $_temp = explode('.php',$_SERVER['PHP_SELF']); - $script_name = rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/'); - }else { - $script_name = rtrim($_SERVER['SCRIPT_NAME'],'/'); - } - define('ROOT_URL', rtrim(dirname(str_replace("\\","\/",$script_name)),'/')); - define('MODULE_URL', ROOT_URL.(Config::get('require_module')?'/'.(defined('MODULE_ALIAS')?MODULE_ALIAS:MODULE_NAME):'')); - define('CONTROLLER_URL', MODULE_URL.(Config::get('require_controller')?'/'.CONTROLLER_NAME:'')); - define('ACTION_URL', CONTROLLER_URL.'/'.ACTION_NAME); - - // 系统默认的特殊变量替换 - $replace = [ - '__ROOT__' => ROOT_URL, // 当前网站地址 - '__APP__' => MODULE_URL, // 当前项目地址 - '__CONTROLL__' => CONTROLLER_URL, // 当前操作地址 - '__URL__' => CONTROLLER_URL, - '__ACTION__' => ACTION_URL, // 当前操作地址 - '__SELF__' => $_SERVER['PHP_SELF'], // 当前页面地址 - '__PUBLIC__' => ROOT_URL.'/Public',// 站点公共目录 - ]; - // 允许用户自定义模板的字符串替换 - if(is_array(Config::get('tmpl_parse_string')) ) - $replace = array_merge($replace,Config::get('tmpl_parse_string')); - $content = str_replace(array_keys($replace),array_values($replace),$content); - return $content; - } - -} diff --git a/Library/Think/Behavior/LocationTemplate.php b/Library/Think/Behavior/LocationTemplate.php deleted file mode 100644 index 327553d5..00000000 --- a/Library/Think/Behavior/LocationTemplate.php +++ /dev/null @@ -1,48 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Behavior; - -/** - * 系统行为扩展:定位模板文件 - * @category Think - * @package Think - * @subpackage Behavior - * @author liu21st - */ -class LocationTemplate { - // 行为扩展的执行入口必须是run - public function run(&$templateFile){ - // 自动定位模板文件 - if(!is_file($templateFile)) - $templateFile = $this->parseTemplateFile($templateFile); - } - - /** - * 自动定位模板文件 - * @access private - * @param string $templateFile 文件名 - * @return string - */ - private function parseTemplateFile($template) { - $template = str_replace(':','/',$template); - if(''==$template) { - // 如果模板文件名为空 按照默认规则定位 - $template = CONTROLLER_NAME.'/'.ACTION_NAME; - }elseif(false === strpos($template,'/')){ - $template = CONTROLLER_NAME.'/'.$template; - }elseif(false === strpos($template,'.')) { - $template = $template; - } - $templateFile = MODULE_PATH.'View/'.$template.'.html'; - return $templateFile; - } -} diff --git a/Library/Think/Behavior/ReadHtmlCache.php b/Library/Think/Behavior/ReadHtmlCache.php deleted file mode 100644 index 9027d447..00000000 --- a/Library/Think/Behavior/ReadHtmlCache.php +++ /dev/null @@ -1,122 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 系统行为扩展:静态缓存读取 - * @category Think - * @package Think - * @subpackage Behavior - * @author liu21st - */ -class ReadHtmlCacheBehavior { - protected $options = [ - 'HTML_CACHE_ON' => false, - 'HTML_CACHE_TIME' => 60, - 'HTML_CACHE_RULES' => [], - 'HTML_FILE_SUFFIX' => '.html', - ]; - - // 行为扩展的执行入口必须是run - public function run(&$params){ - // 开启静态缓存 - if(C('HTML_CACHE_ON')) { - $cacheTime = $this->requireHtmlCache(); - if( false !== $cacheTime && $this->checkHTMLCache(HTML_FILE_NAME,$cacheTime)) { //静态页面有效 - // 读取静态页面输出 - readfile(HTML_FILE_NAME); - exit(); - } - } - } - - // 判断是否需要静态缓存 - static private function requireHtmlCache() { - // 分析当前的静态规则 - $htmls = C('HTML_CACHE_RULES'); // 读取静态规则 - if(!empty($htmls)) { - $htmls = array_change_key_case($htmls); - // 静态规则文件定义格式 actionName=>array('静态规则','缓存时间','附加规则') - // 'read'=>array('{id},{name}',60,'md5') 必须保证静态规则的唯一性 和 可判断性 - // 检测静态规则 - $moduleName = strtolower(MODULE_NAME); - $actionName = strtolower(ACTION_NAME); - if(isset($htmls[$moduleName.':'.$actionName])) { - $html = $htmls[$moduleName.':'.$actionName]; // 某个模块的操作的静态规则 - }elseif(isset($htmls[$moduleName.':'])){// 某个模块的静态规则 - $html = $htmls[$moduleName.':']; - }elseif(isset($htmls[$actionName])){ - $html = $htmls[$actionName]; // 所有操作的静态规则 - }elseif(isset($htmls['*'])){ - $html = $htmls['*']; // 全局静态规则 - }elseif(isset($htmls['empty:index']) && !class_exists(MODULE_NAME.'Action')){ - $html = $htmls['empty:index']; // 空模块静态规则 - }elseif(isset($htmls[$moduleName.':_empty']) && $this->isEmptyAction(MODULE_NAME,ACTION_NAME)){ - $html = $htmls[$moduleName.':_empty']; // 空操作静态规则 - } - if(!empty($html)) { - // 解读静态规则 - $rule = $html[0]; - // 以$_开头的系统变量 - $rule = preg_replace('/{\$(_\w+)\.(\w+)\|(\w+)}/e',"\\3(\$\\1['\\2'])",$rule); - $rule = preg_replace('/{\$(_\w+)\.(\w+)}/e',"\$\\1['\\2']",$rule); - // {ID|FUN} GET变量的简写 - $rule = preg_replace('/{(\w+)\|(\w+)}/e',"\\2(\$_GET['\\1'])",$rule); - $rule = preg_replace('/{(\w+)}/e',"\$_GET['\\1']",$rule); - // 特殊系统变量 - $rule = str_ireplace( - ['{:app}','{:module}','{:action}','{:group}'], - [APP_NAME,MODULE_NAME,ACTION_NAME,defined('GROUP_NAME')?GROUP_NAME:''], - $rule); - // {|FUN} 单独使用函数 - $rule = preg_replace('/{|(\w+)}/e',"\\1()",$rule); - if(!empty($html[2])) $rule = $html[2]($rule); // 应用附加函数 - $cacheTime = isset($html[1])?$html[1]:C('HTML_CACHE_TIME'); // 缓存有效期 - // 当前缓存文件 - define('HTML_FILE_NAME',HTML_PATH . $rule.C('HTML_FILE_SUFFIX')); - return $cacheTime; - } - } - // 无需缓存 - return false; - } - - /** - * 检查静态HTML文件是否有效 - * 如果无效需要重新更新 - * @access public - * @param string $cacheFile 静态文件名 - * @param integer $cacheTime 缓存有效期 - * @return boolen - */ - static public function checkHTMLCache($cacheFile='',$cacheTime='') { - if(!is_file($cacheFile)){ - return false; - }elseif (filemtime(C('TEMPLATE_NAME')) > filemtime($cacheFile)) { - // 模板文件如果更新静态文件需要更新 - return false; - }elseif(!is_numeric($cacheTime) && function_exists($cacheTime)){ - return $cacheTime($cacheFile); - }elseif ($cacheTime != 0 && NOW_TIME > filemtime($cacheFile)+$cacheTime) { - // 文件是否在有效期 - return false; - } - //静态文件有效 - return true; - } - - //检测是否是空操作 - static private function isEmptyAction($module,$action) { - $className = $module.'Action'; - $class = new $className; - return !method_exists($class,$action); - } - -} diff --git a/Library/Think/Behavior/ShowPageTrace.php b/Library/Think/Behavior/ShowPageTrace.php deleted file mode 100644 index 0fff7677..00000000 --- a/Library/Think/Behavior/ShowPageTrace.php +++ /dev/null @@ -1,90 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Behavior; -use Think\Config; -use Think\Log; -use Think\Debug; - -/** - * 系统行为扩展:页面Trace显示输出 - * @category Think - * @package Think - * @subpackage Behavior - * @author liu21st - */ -class ShowPageTrace { - - // 行为扩展的执行入口必须是run - public function run(&$params){ - if(!IS_AJAX && Config::get('show_page_trace')) { - echo $this->showTrace(); - } - } - - /** - * 显示页面Trace信息 - * @access private - */ - private function showTrace() { - // 系统默认显示信息 - $files = get_included_files(); - $info = []; - foreach ($files as $key=>$file){ - $info[] = $file.' ( '.number_format(filesize($file)/1024,2).' KB )'; - } - $trace = []; - Debug::remark('START',$GLOBALS['startTime']); - $base = [ - '请求信息' => date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']).' '.$_SERVER['SERVER_PROTOCOL'].' '.$_SERVER['REQUEST_METHOD'].' : '.$_SERVER['PHP_SELF'], - '运行时间' => Debug::getUseTime('START','END',6).'s', - '内存开销' => MEMORY_LIMIT_ON?G('START','END','m').'b':'不支持', - '查询信息' => N('db_query').' queries '.N('db_write').' writes ', - '文件加载' => count($files), - '缓存信息' => N('cache_read').' gets '.N('cache_write').' writes ', - '配置加载' => count(Config::get()), - ]; - // 读取项目定义的Trace文件 - $traceFile = MODULE_PATH.'trace.php'; - if(is_file($traceFile)) { - $base = array_merge($base,include $traceFile); - } - $debug = Log::getLog(); - $tabs = Config::get('trace_page_tabs'); - foreach ($tabs as $name=>$title){ - switch(strtoupper($name)) { - case 'BASE':// 基本信息 - $trace[$title] = $base; - break; - case 'FILE': // 文件信息 - $trace[$title] = $info; - break; - default:// 调试信息 - $name = strtoupper($name); - if(strpos($name,'|')) {// 多组信息 - $array = explode('|',$name); - $result = []; - foreach($array as $name){ - $result += isset($debug[$name])?$debug[$name]:[]; - } - $trace[$title] = $result; - }else{ - $trace[$title] = isset($debug[$name])?$debug[$name]:''; - } - } - } - unset($files,$info,$base,$debug); - // 调用Trace页面模板 - ob_start(); - include Config::has('tmpl_trace_file')?Config::get('tmpl_trace_file'):THINK_PATH.'tpl/page_trace.tpl'; - return ob_get_clean(); - } -} diff --git a/Library/Think/Behavior/TokenBuild.php b/Library/Think/Behavior/TokenBuild.php deleted file mode 100644 index 082e25b3..00000000 --- a/Library/Think/Behavior/TokenBuild.php +++ /dev/null @@ -1,61 +0,0 @@ - -// +---------------------------------------------------------------------- - -defined('THINK_PATH') or exit(); -/** - * 系统行为扩展:表单令牌生成 - * @category Think - * @package Think - * @subpackage Behavior - * @author liu21st - */ -class TokenBuildBehavior extends Behavior { - // 行为参数定义 - protected $options = [ - 'TOKEN_ON' => false, // 开启令牌验证 - 'TOKEN_NAME' => '__hash__', // 令牌验证的表单隐藏字段名称 - 'TOKEN_TYPE' => 'md5', // 令牌验证哈希规则 - 'TOKEN_RESET' => true, // 令牌错误后是否重置 - ]; - - public function run(&$content){ - if(C('TOKEN_ON')) { - if(strpos($content,'{__TOKEN__}')) { - // 指定表单令牌隐藏域位置 - $content = str_replace('{__TOKEN__}',$this->buildToken(),$content); - }elseif(preg_match('/<\/form(\s*)>/is',$content,$match)) { - // 智能生成表单令牌隐藏域 - $content = str_replace($match[0],$this->buildToken().$match[0],$content); - } - }else{ - $content = str_replace('{__TOKEN__}','',$content); - } - } - - // 创建表单令牌 - private function buildToken() { - $tokenName = C('TOKEN_NAME'); - $tokenType = C('TOKEN_TYPE'); - if(!isset($_SESSION[$tokenName])) { - $_SESSION[$tokenName] = []; - } - // 标识当前页面唯一性 - $tokenKey = md5($_SERVER['REQUEST_URI']); - if(isset($_SESSION[$tokenName][$tokenKey])) {// 相同页面不重复生成session - $tokenValue = $_SESSION[$tokenName][$tokenKey]; - }else{ - $tokenValue = $tokenType(microtime(true)); - $_SESSION[$tokenName][$tokenKey] = $tokenValue; - } - $token = ''; - return $token; - } -} diff --git a/Library/Think/Cache.php b/Library/Think/Cache.php deleted file mode 100644 index b49d8312..00000000 --- a/Library/Think/Cache.php +++ /dev/null @@ -1,38 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Cache { - /** - * 操作句柄 - * @var object - * @access protected - */ - static protected $handler = null; - - /** - * 连接缓存 - * @access public - * @param array $options 配置数组 - * @return object - */ - static public function connect($options=[]) { - $type = !empty($options['type'])?$options['type']:'File'; - $class = 'Think\\Cache\\Driver\\'.ucwords($type); - self::$handler = new $class($options); - return self::$handler; - } - - static public function __callStatic($method, $params){ - return call_user_func_array(array(self::$handler, $method), $params); - } -} diff --git a/Library/Think/Cache/Driver/Apc.php b/Library/Think/Cache/Driver/Apc.php deleted file mode 100644 index aad5bd11..00000000 --- a/Library/Think/Cache/Driver/Apc.php +++ /dev/null @@ -1,101 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Apc缓存驱动 - * @author liu21st - */ -class Apc { - - protected $options = [ - 'expire' => 0, - 'prefix' => '', - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if(!function_exists('apc_cache_info')) { - E('_NOT_SUPPERT_:Apc'); - } - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - return apc_fetch($this->options['prefix'].$name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value, $expire = null) { - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'].$name; - if($result = apc_store($name, $value, $expire)) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = apc_fetch('__info__'); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - apc_delete($key); - } - apc_store('__info__', $queue); - } - } - return $result; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return apc_delete($this->options['prefix'].$name); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return apc_clear_cache(); - } -} diff --git a/Library/Think/Cache/Driver/Db.php b/Library/Think/Cache/Driver/Db.php deleted file mode 100644 index c2a02898..00000000 --- a/Library/Think/Cache/Driver/Db.php +++ /dev/null @@ -1,146 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * 数据库方式缓存驱动 - * CREATE TABLE think_cache ( - * cachekey varchar(255) NOT NULL, - * expire int(11) NOT NULL, - * data blob, - * datacrc int(32), - * UNIQUE KEY `cachekey` (`cachekey`) - * ); - * @author liu21st - */ -class Db { - - protected $handler = null; - protected $options = [ - 'db' => '', - 'table' => '', - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - $this->handler = \Think\Db::instance(); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $name = $this->options['prefix'].addslashes($name); - $result = $this->handler->query('SELECT `data`,`datacrc` FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$name.'\' AND (`expire` =0 OR `expire`>'.time().') LIMIT 0,1'); - if(false !== $result ) { - $result = $result[0]; - $content = $result['data']; - if(function_exists('gzcompress')) { - //启用数据压缩 - $content = gzuncompress($content); - } - $content = unserialize($content); - return $content; - } - else { - return false; - } - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value,$expire=null) { - $data = serialize($value); - $name = $this->options['prefix'].addslashes($name); - if(function_exists('gzcompress')) { - //数据压缩 - $data = gzcompress($data,3); - } - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $expire = ($expire==0)?0: (time()+$expire) ;//缓存有效期为0表示永久缓存 - $result = $this->handler->query('select `cachekey` from `'.$this->options['table'].'` where `cachekey`=\''.$name.'\' limit 0,1'); - if(!empty($result) ) { - //更新记录 - $result = $this->handler->execute('UPDATE '.$this->options['table'].' SET data=\''.$data.'\' ,expire='.$expire.' WHERE `cachekey`=\''.$name.'\''); - }else { - //新增记录 - $result = $this->handler->execute('INSERT INTO '.$this->options['table'].' (`cachekey`,`data`,`expire`) VALUES (\''.$name.'\',\''.$data.'\','.$expire.')'); - } - if($result) { - if($this->options['length']>0) { - // 记录缓存队列 - $result = $this->handler->query('SELECT `data`,`datacrc` FROM `'.$this->options['table'].'` WHERE `cachekey`=\'__info__\' AND `expire` =0 LIMIT 0,1'); - $queue = xcache_get('__info__'); - if(!$result) { - $this->handler->execute('INSERT INTO '.$this->options['table'].' (`cachekey`,`data`,`expire`) VALUES (\'__info__\',\'\',0)'); - $queue = []; - }else{ - $queue = unserialize($result[0]['data']); - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->execute('DELETE FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$key.'\''); - } - $this->handler->execute('UPDATE '.$this->options['table'].' SET data=\''.serialize($queue).'\' ,expire=0 WHERE `cachekey`=\'__info__\''); - xcache_set('__info__', $queue); - } - return true; - }else { - return false; - } - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - $name = $this->options['prefix'].addslashes($name); - return $this->handler->execute('DELETE FROM `'.$this->options['table'].'` WHERE `cachekey`=\''.$name.'\''); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return $this->handler->execute('TRUNCATE TABLE `'.$this->options['table'].'`'); - } - -} diff --git a/Library/Think/Cache/Driver/Eaccelerator.php b/Library/Think/Cache/Driver/Eaccelerator.php deleted file mode 100644 index a0ec2795..00000000 --- a/Library/Think/Cache/Driver/Eaccelerator.php +++ /dev/null @@ -1,101 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Eaccelerator缓存驱动 - * @author liu21st - */ -class Eaccelerator { - - protected $options = [ - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - return eaccelerator_get($this->options['prefix'].$name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value, $expire = null) { - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'].$name; - eaccelerator_lock($name); - if(eaccelerator_put($name, $value, $expire)) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = eaccelerator_get('__info__'); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - eaccelerator_rm($key); - } - eaccelerator_put('__info__', $queue); - } - return true; - } - return false; - } - - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return eaccelerator_rm($this->options['prefix'].$name); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return ; - } -} diff --git a/Library/Think/Cache/Driver/File.php b/Library/Think/Cache/Driver/File.php deleted file mode 100644 index 285fb9b1..00000000 --- a/Library/Think/Cache/Driver/File.php +++ /dev/null @@ -1,184 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * 文件类型缓存类 - * @author liu21st - */ -class File { - - protected $options = [ - 'expire' => 0, - 'cache_subdir' => false, - 'path_level' => 1, - 'prefix' => '', - 'length' => 0, - 'temp' => '', - 'data_compress' => false, - ]; - - /** - * 架构函数 - * @access public - */ - public function __construct($options=[]) { - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; - $this->init(); - } - - /** - * 初始化检查 - * @access private - * @return boolen - */ - private function init() { - // 创建项目缓存目录 - if (!is_dir($this->options['temp'])) { - if (! mkdir($this->options['temp'],0755)) - return false; - } - } - - /** - * 取得变量的存储文件名 - * @access private - * @param string $name 缓存变量名 - * @return string - */ - private function filename($name) { - $name = md5($name); - if($this->options['cache_subdir']) { - // 使用子目录 - $dir = ''; - $len = $this->options['path_level']; - for($i=0;$i<$len;$i++) { - $dir .= $name{$i}.'/'; - } - if(!is_dir($this->options['temp'].$dir)) { - mkdir($this->options['temp'].$dir,0755,true); - } - $filename = $dir.$this->options['prefix'].$name.'.php'; - }else{ - $filename = $this->options['prefix'].$name.'.php'; - } - return $this->options['temp'].$filename; - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $filename = $this->filename($name); - if (!is_file($filename)) { - return false; - } - $content = file_get_contents($filename); - if( false !== $content) { - $expire = (int)substr($content,8, 12); - if($expire != 0 && time() > filemtime($filename) + $expire) { - //缓存过期删除缓存文件 - unlink($filename); - return false; - } - $content = substr($content,20, -3); - if($this->options['data_compress'] && function_exists('gzcompress')) { - //启用数据压缩 - $content = gzuncompress($content); - } - $content = unserialize($content); - return $content; - } - else { - return false; - } - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param int $expire 有效时间 0为永久 - * @return boolen - */ - public function set($name,$value,$expire=null) { - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $filename = $this->filename($name); - $data = serialize($value); - if($this->options['data_compress'] && function_exists('gzcompress')) { - //数据压缩 - $data = gzcompress($data,3); - } - $data = ""; - $result = file_put_contents($filename,$data); - if($result) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue_file = dirname($filename).'/__info__.php'; - $queue = unserialize(file_get_contents($queue_file)); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - unlink($this->filename($key)); - } - file_put_contents($queue_file, serialize($queue)); - } - clearstatcache(); - return true; - }else { - return false; - } - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return unlink($this->filename($name)); - } - - /** - * 清除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function clear() { - $path = $this->options['temp']; - if ( $dir = opendir( $path ) ) { - while ( $file = readdir( $dir ) ) { - $check = is_dir( $file ); - if ( !$check ) - unlink( $path . $file ); - } - closedir( $dir ); - return true; - } - } -} diff --git a/Library/Think/Cache/Driver/Memcache.php b/Library/Think/Cache/Driver/Memcache.php deleted file mode 100644 index bd3b0a3f..00000000 --- a/Library/Think/Cache/Driver/Memcache.php +++ /dev/null @@ -1,113 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Memcache缓存驱动 - * @author liu21st - */ -class Memcache { - protected $handler = null; - protected $options = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'expire' => 0, - 'timeout' => false, - 'persistent' => false, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if ( !extension_loaded('memcache') ) { - E('_NOT_SUPPERT_:memcache'); - } - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - $func = $this->options['persistent'] ? 'pconnect' : 'connect'; - $this->handler = new \Memcache; - $options['timeout'] === false ? - $this->handler->$func($options['host'], $options['port']) : - $this->handler->$func($options['host'], $options['port'], $options['timeout']); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - return $this->handler->get($this->options['prefix'].$name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value, $expire = null) { - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'].$name; - if($this->handler->set($name, $value, 0, $expire)) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = $this->handler->get('__info__'); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->delete($key); - } - $this->handler->set('__info__', $queue); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name, $ttl = false) { - $name = $this->options['prefix'].$name; - return $ttl === false ? - $this->handler->delete($name) : - $this->handler->delete($name, $ttl); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return $this->handler->flush(); - } -} diff --git a/Library/Think/Cache/Driver/Redis.php b/Library/Think/Cache/Driver/Redis.php deleted file mode 100644 index e66affdf..00000000 --- a/Library/Think/Cache/Driver/Redis.php +++ /dev/null @@ -1,116 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Redis缓存驱动 - * 要求安装phpredis扩展:https://github.com/nicolasff/phpredis - * @author 尘缘 <130775@qq.com> - */ -class Redis { - protected $handler = null; - protected $options = [ - 'host' => '127.0.0.1', - 'port' => 6379, - 'timeout' => false, - 'expire' => 0, - 'persistent' => false, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if ( !extension_loaded('redis') ) { - E('_NOT_SUPPERT_:redis'); - } - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - $func = $options['persistent'] ? 'pconnect' : 'connect'; - $this->handler = new \Redis; - $options['timeout'] === false ? - $this->handler->$func($options['host'], $options['port']) : - $this->handler->$func($options['host'], $options['port'], $options['timeout']); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - return $this->handler->get($this->options['prefix'].$name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value, $expire = null) { - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'].$name; - if(is_int($expire)) { - $result = $this->handler->setex($name, $expire, $value); - }else{ - $result = $this->handler->set($name, $value); - } - if($result && $this->options['length']>0) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = $this->handler->get('__info__'); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->delete($key); - } - $this->handler->set('__info__', $queue); - } - } - return $result; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return $this->handler->delete($this->options['prefix'].$name); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return $this->handler->flushDB(); - } - -} diff --git a/Library/Think/Cache/Driver/Secache.php b/Library/Think/Cache/Driver/Secache.php deleted file mode 100644 index 88d4bec0..00000000 --- a/Library/Think/Cache/Driver/Secache.php +++ /dev/null @@ -1,722 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Secache缓存驱动 - * @author liu21st - */ -class Secache { - - protected $handler = null; - protected $options = [ - 'project' => '', - 'temp' => '', - 'expire' => 0, - 'prefix' => '', - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; - $this->handler = new SecacheClient; - $this->handler->workat($this->options['temp'].$this->options['project']); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $name = $this->options['prefix'].$name; - $key = md5($name); - $this->handler->fetch($key,$return); - return $return; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value) { - $name = $this->options['prefix'].$name; - $key = md5($name); - if($result = $this->handler->store($key, $value)) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = $this->handler->fetch(md5('__info__')); - if(!$queue) { - $queue = []; - } - if(false===array_search($key, $queue)) array_push($queue,$key); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->delete($key); - } - $this->handler->store(md5('__info__'), $queue); - } - } - return $result; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - $name = $this->options['prefix'].$name; - $key = md5($name); - return $this->handler->delete($key); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return $this->handler->_format(true); - } - -} - -if(!defined('SECACHE_SIZE')){ - define('SECACHE_SIZE','15M'); -} -class SecacheClient{ - - var $idx_node_size = 40; - var $data_base_pos = 262588; //40+20+24*16+16*16*16*16*4; - var $schema_item_size = 24; - var $header_padding = 20; //保留空间 放置php标记防止下载 - var $info_size = 20; //保留空间 4+16 maxsize|ver - - //40起 添加20字节保留区域 - var $idx_seq_pos = 40; //id 计数器节点地址 - var $dfile_cur_pos = 44; //id 计数器节点地址 - var $idx_free_pos = 48; //id 空闲链表入口地址 - - var $idx_base_pos = 444; //40+20+24*16 - var $min_size = 10240; //10M最小值 - var $schema_struct = array('size','free','lru_head','lru_tail','hits','miss'); - var $ver = '$Rev: 3 $'; - var $name = '系统默认缓存(文件型)'; - - function workat($file){ - - $this->_file = $file.'.php'; - $this->_bsize_list = array( - 512=>10, - 3<<10=>10, - 8<<10=>10, - 20<<10=>4, - 30<<10=>2, - 50<<10=>2, - 80<<10=>2, - 96<<10=>2, - 128<<10=>2, - 224<<10=>2, - 256<<10=>2, - 512<<10=>1, - 1024<<10=>1, - ); - - $this->_node_struct = array( - 'next'=>array(0,'V'), - 'prev'=>array(4,'V'), - 'data'=>array(8,'V'), - 'size'=>array(12,'V'), - 'lru_right'=>array(16,'V'), - 'lru_left'=>array(20,'V'), - 'key'=>array(24,'H*'), - ); - - if(!file_exists($this->_file)){ - $this->create(); - }else{ - $this->_rs = fopen($this->_file,'rb+') or $this->trigger_error('Can\'t open the cachefile: '.realpath($this->_file),E_USER_ERROR); - $this->_seek($this->header_padding); - $info = unpack('V1max_size/a*ver',fread($this->_rs,$this->info_size)); - if($info['ver']!=$this->ver){ - $this->_format(true); - }else{ - $this->max_size = $info['max_size']; - } - } - - $this->idx_node_base = $this->data_base_pos+$this->max_size; - $this->_block_size_list = array_keys($this->_bsize_list); - sort($this->_block_size_list); - return true; - } - - function create(){ - $this->_rs = fopen($this->_file,'wb+') or $this->trigger_error('Can\'t open the cachefile: '.realpath($this->_file),E_USER_ERROR);; - fseek($this->_rs,0); - fputs($this->_rs,'<'.'?php exit()?'.'>'); - return $this->_format(); - } - - function _puts($offset,$data){ - if($offset < $this->max_size*1.5){ - $this->_seek($offset); - return fputs($this->_rs,$data); - }else{ - $this->trigger_error('Offset over quota:'.$offset,E_USER_ERROR); - } - } - - function _seek($offset){ - return fseek($this->_rs,$offset); - } - - function clear(){ - return $this->_format(true); - } - - function fetch($key,&$return){ - - if($this->lock(false)){ - $locked = true; - } - - if($this->search($key,$offset)){ - $info = $this->_get_node($offset); - $schema_id = $this->_get_size_schema_id($info['size']); - if($schema_id===false){ - if($locked) $this->unlock(); - return false; - } - - $this->_seek($info['data']); - $data = fread($this->_rs,$info['size']); - $return = unserialize($data); - - if($return===false){ - if($locked) $this->unlock(); - return false; - } - - if($locked){ - $this->_lru_push($schema_id,$info['offset']); - $this->_set_schema($schema_id,'hits',$this->_get_schema($schema_id,'hits')+1); - return $this->unlock(); - }else{ - return true; - } - }else{ - if($locked) $this->unlock(); - return false; - } - } - - /** - * lock - * 如果flock不管用,请继承本类,并重载此方法 - * - * @param mixed $is_block 是否阻塞 - * @access public - * @return void - */ - function lock($is_block,$whatever=false){ - return flock($this->_rs, $is_block?LOCK_EX:LOCK_EX+LOCK_NB); - } - - /** - * unlock - * 如果flock不管用,请继承本类,并重载此方法 - * - * @access public - * @return void - */ - function unlock(){ - return flock($this->_rs, LOCK_UN); - } - - function delete($key,$pos=false){ - if($pos || $this->search($key,$pos)){ - if($info = $this->_get_node($pos)){ - //删除data区域 - if($info['prev']){ - $this->_set_node($info['prev'],'next',$info['next']); - $this->_set_node($info['next'],'prev',$info['prev']); - }else{ //改入口位置 - $this->_set_node($info['next'],'prev',0); - $this->_set_node_root($key,$info['next']); - } - $this->_free_dspace($info['size'],$info['data']); - $this->_lru_delete($info); - $this->_free_node($pos); - return $info['prev']; - } - } - return false; - } - - function store($key,$value){ - - if($this->lock(true)){ - //save data - $data = serialize($value); - $size = strlen($data); - - //get list_idx - $has_key = $this->search($key,$list_idx_offset); - $schema_id = $this->_get_size_schema_id($size); - if($schema_id===false){ - $this->unlock(); - return false; - } - if($has_key){ - $hdseq = $list_idx_offset; - - $info = $this->_get_node($hdseq); - if($schema_id == $this->_get_size_schema_id($info['size'])){ - $dataoffset = $info['data']; - }else{ - //破掉原有lru - $this->_lru_delete($info); - if(!($dataoffset = $this->_dalloc($schema_id))){ - $this->unlock(); - return false; - } - $this->_free_dspace($info['size'],$info['data']); - $this->_set_node($hdseq,'lru_left',0); - $this->_set_node($hdseq,'lru_right',0); - } - - $this->_set_node($hdseq,'size',$size); - $this->_set_node($hdseq,'data',$dataoffset); - }else{ - - if(!($dataoffset = $this->_dalloc($schema_id))){ - $this->unlock(); - return false; - } - $hdseq = $this->_alloc_idx(array( - 'next'=>0, - 'prev'=>$list_idx_offset, - 'data'=>$dataoffset, - 'size'=>$size, - 'lru_right'=>0, - 'lru_left'=>0, - 'key'=>$key, - )); - - if($list_idx_offset>0){ - $this->_set_node($list_idx_offset,'next',$hdseq); - }else{ - $this->_set_node_root($key,$hdseq); - } - } - - if($dataoffset>$this->max_size){ - $this->trigger_error('alloc datasize:'.$dataoffset,E_USER_WARNING); - return false; - } - $this->_puts($dataoffset,$data); - - $this->_set_schema($schema_id,'miss',$this->_get_schema($schema_id,'miss')+1); - - $this->_lru_push($schema_id,$hdseq); - $this->unlock(); - return true; - }else{ - $this->trigger_error("Couldn't lock the file !",E_USER_WARNING); - return false; - } - - } - - /** - * search - * 查找指定的key - * 如果找到节点则$pos=节点本身 返回true - * 否则 $pos=树的末端 返回false - * - * @param mixed $key - * @access public - * @return void - */ - function search($key,&$pos){ - return $this->_get_pos_by_key($this->_get_node_root($key),$key,$pos); - } - - function _get_size_schema_id($size){ - foreach($this->_block_size_list as $k=>$block_size){ - if($size <= $block_size){ - return $k; - } - } - return false; - } - - function _parse_str_size($str_size,$default){ - if(preg_match('/^([0-9]+)\s*([gmk]|)$/i',$str_size,$match)){ - switch(strtolower($match[2])){ - case 'g': - if($match[1]>1){ - $this->trigger_error('Max cache size 1G',E_USER_ERROR); - } - $size = $match[1]<<30; - break; - case 'm': - $size = $match[1]<<20; - break; - case 'k': - $size = $match[1]<<10; - break; - default: - $size = $match[1]; - } - if($size<=0){ - $this->trigger_error('Error cache size '.$this->max_size,E_USER_ERROR); - return false; - }elseif($size<10485760){ - return 10485760; - }else{ - return $size; - } - }else{ - return $default; - } - } - - - function _format($truncate=false){ - if($this->lock(true,true)){ - - if($truncate){ - $this->_seek(0); - ftruncate($this->_rs,$this->idx_node_base); - } - - $this->max_size = $this->_parse_str_size(SECACHE_SIZE,15728640); //default:15m - $this->_puts($this->header_padding,pack('V1a*',$this->max_size,$this->ver)); - - ksort($this->_bsize_list); - $ds_offset = $this->data_base_pos; - $i=0; - foreach($this->_bsize_list as $size=>$count){ - - //将预分配的空间注册到free链表里 - $count *= min(3,floor($this->max_size/10485760)); - $next_free_node = 0; - for($j=0;$j<$count;$j++){ - $this->_puts($ds_offset,pack('V',$next_free_node)); - $next_free_node = $ds_offset; - $ds_offset+=intval($size); - } - - $code = pack(str_repeat('V1',count($this->schema_struct)),$size,$next_free_node,0,0,0,0); - - $this->_puts(60+$i*$this->schema_item_size,$code); - $i++; - } - $this->_set_dcur_pos($ds_offset); - - $this->_puts($this->idx_base_pos,str_repeat("\0",262144)); - $this->_puts($this->idx_seq_pos,pack('V',1)); - $this->unlock(); - return true; - }else{ - $this->trigger_error("Couldn't lock the file !",E_USER_ERROR); - return false; - } - } - - function _get_node_root($key){ - $this->_seek(hexdec(substr($key,0,4))*4+$this->idx_base_pos); - $a= fread($this->_rs,4); - list(,$offset) = unpack('V',$a); - return $offset; - } - - function _set_node_root($key,$value){ - return $this->_puts(hexdec(substr($key,0,4))*4+$this->idx_base_pos,pack('V',$value)); - } - - function _set_node($pos,$key,$value){ - - if(!$pos){ - return false; - } - - if(isset($this->_node_struct[$key])){ - return $this->_puts($pos*$this->idx_node_size+$this->idx_node_base+$this->_node_struct[$key][0],pack($this->_node_struct[$key][1],$value)); - }else{ - return false; - } - } - - function _get_pos_by_key($offset,$key,&$pos){ - if(!$offset){ - $pos = 0; - return false; - } - - $info = $this->_get_node($offset); - - if($info['key']==$key){ - $pos = $info['offset']; - return true; - }elseif($info['next'] && $info['next']!=$offset){ - return $this->_get_pos_by_key($info['next'],$key,$pos); - }else{ - $pos = $offset; - return false; - } - } - - function _lru_delete($info){ - - if($info['lru_right']){ - $this->_set_node($info['lru_right'],'lru_left',$info['lru_left']); - }else{ - $this->_set_schema($this->_get_size_schema_id($info['size']),'lru_tail',$info['lru_left']); - } - - if($info['lru_left']){ - $this->_set_node($info['lru_left'],'lru_right',$info['lru_right']); - }else{ - $this->_set_schema($this->_get_size_schema_id($info['size']),'lru_head',$info['lru_right']); - } - - return true; - } - - function _lru_push($schema_id,$offset){ - $lru_head = $this->_get_schema($schema_id,'lru_head'); - $lru_tail = $this->_get_schema($schema_id,'lru_tail'); - - if((!$offset) || ($lru_head==$offset))return; - - $info = $this->_get_node($offset); - - $this->_set_node($info['lru_right'],'lru_left',$info['lru_left']); - $this->_set_node($info['lru_left'],'lru_right',$info['lru_right']); - - $this->_set_node($offset,'lru_right',$lru_head); - $this->_set_node($offset,'lru_left',0); - - $this->_set_node($lru_head,'lru_left',$offset); - $this->_set_schema($schema_id,'lru_head',$offset); - - if($lru_tail==0){ - $this->_set_schema($schema_id,'lru_tail',$offset); - }elseif($lru_tail==$offset && $info['lru_left']){ - $this->_set_schema($schema_id,'lru_tail',$info['lru_left']); - } - return true; - } - - function _get_node($offset){ - $this->_seek($offset*$this->idx_node_size + $this->idx_node_base); - $info = unpack('V1next/V1prev/V1data/V1size/V1lru_right/V1lru_left/H*key',fread($this->_rs,$this->idx_node_size)); - $info['offset'] = $offset; - return $info; - } - - function _lru_pop($schema_id){ - if($node = $this->_get_schema($schema_id,'lru_tail')){ - $info = $this->_get_node($node); - if(!$info['data']){ - return false; - } - $this->delete($info['key'],$info['offset']); - if(!$this->_get_schema($schema_id,'free')){ - $this->trigger_error('pop lru,But nothing free...',E_USER_ERROR); - } - return $info; - }else{ - return false; - } - } - - function _dalloc($schema_id,$lru_freed=false){ - - if($free = $this->_get_schema($schema_id,'free')){ //如果lru里有链表 - $this->_seek($free); - list(,$next) = unpack('V',fread($this->_rs,4)); - $this->_set_schema($schema_id,'free',$next); - return $free; - }elseif($lru_freed){ - $this->trigger_error('Bat lru poped freesize',E_USER_ERROR); - return false; - }else{ - $ds_offset = $this->_get_dcur_pos(); - $size = $this->_get_schema($schema_id,'size'); - - if($size+$ds_offset > $this->max_size){ - if($info = $this->_lru_pop($schema_id)){ - return $this->_dalloc($schema_id,$info); - }else{ - $this->trigger_error('Can\'t alloc dataspace',E_USER_ERROR); - return false; - } - }else{ - $this->_set_dcur_pos($ds_offset+$size); - return $ds_offset; - } - } - } - - function _get_dcur_pos(){ - $this->_seek($this->dfile_cur_pos); - list(,$ds_offset) = unpack('V',fread($this->_rs,4)); - return $ds_offset; - } - function _set_dcur_pos($pos){ - return $this->_puts($this->dfile_cur_pos,pack('V',$pos)); - } - - function _free_dspace($size,$pos){ - - if($pos>$this->max_size){ - $this->trigger_error('free dspace over quota:'.$pos,E_USER_ERROR); - return false; - } - - $schema_id = $this->_get_size_schema_id($size); - if($free = $this->_get_schema($schema_id,'free')){ - $this->_puts($free,pack('V1',$pos)); - }else{ - $this->_set_schema($schema_id,'free',$pos); - } - $this->_puts($pos,pack('V1',0)); - } - - function _dfollow($pos,&$c){ - $c++; - $this->_seek($pos); - list(,$next) = unpack('V1',fread($this->_rs,4)); - if($next){ - return $this->_dfollow($next,$c); - }else{ - return $pos; - } - } - - function _free_node($pos){ - $this->_seek($this->idx_free_pos); - list(,$prev_free_node) = unpack('V',fread($this->_rs,4)); - $this->_puts($pos*$this->idx_node_size+$this->idx_node_base,pack('V',$prev_free_node).str_repeat("\0",$this->idx_node_size-4)); - return $this->_puts($this->idx_free_pos,pack('V',$pos)); - } - - function _alloc_idx($data){ - $this->_seek($this->idx_free_pos); - list(,$list_pos) = unpack('V',fread($this->_rs,4)); - if($list_pos){ - - $this->_seek($list_pos*$this->idx_node_size+$this->idx_node_base); - list(,$prev_free_node) = unpack('V',fread($this->_rs,4)); - $this->_puts($this->idx_free_pos,pack('V',$prev_free_node)); - - }else{ - $this->_seek($this->idx_seq_pos); - list(,$list_pos) = unpack('V',fread($this->_rs,4)); - $this->_puts($this->idx_seq_pos,pack('V',$list_pos+1)); - } - return $this->_create_node($list_pos,$data); - } - - function _create_node($pos,$data){ - $this->_puts($pos*$this->idx_node_size + $this->idx_node_base - ,pack('V1V1V1V1V1V1H*',$data['next'],$data['prev'],$data['data'],$data['size'],$data['lru_right'],$data['lru_left'],$data['key'])); - return $pos; - } - - function _set_schema($schema_id,$key,$value){ - $info = array_flip($this->schema_struct); - return $this->_puts(60+$schema_id*$this->schema_item_size + $info[$key]*4,pack('V',$value)); - } - - function _get_schema($id,$key){ - $info = array_flip($this->schema_struct); - - $this->_seek(60+$id*$this->schema_item_size); - unpack('V1'.implode('/V1',$this->schema_struct),fread($this->_rs,$this->schema_item_size)); - - $this->_seek(60+$id*$this->schema_item_size + $info[$key]*4); - list(,$value) =unpack('V',fread($this->_rs,4)); - return $value; - } - - function _all_schemas(){ - $schema = []; - for($i=0;$i<16;$i++){ - $this->_seek(60+$i*$this->schema_item_size); - $info = unpack('V1'.implode('/V1',$this->schema_struct),fread($this->_rs,$this->schema_item_size)); - if($info['size']){ - $info['id'] = $i; - $schema[$i] = $info; - }else{ - return $schema; - } - } - } - - function schemaStatus(){ - $return = []; - foreach($this->_all_schemas() as $k=>$schemaItem){ - if($schemaItem['free']){ - $this->_dfollow($schemaItem['free'],$schemaItem['freecount']); - } - $return[] = $schemaItem; - } - return $return; - } - - function status(&$curBytes,&$totalBytes){ - $totalBytes = $curBytes = 0; - $hits = $miss = 0; - - $schemaStatus = $this->schemaStatus(); - $totalBytes = $this->max_size; - $freeBytes = $this->max_size - $this->_get_dcur_pos(); - - foreach($schemaStatus as $schema){ - $freeBytes+=$schema['freecount']*$schema['size']; - $miss += $schema['miss']; - $hits += $schema['hits']; - } - $curBytes = $totalBytes-$freeBytes; - - $return[] = array('name'=>'缓存命中','value'=>$hits); - $return[] = array('name'=>'缓存未命中','value'=>$miss); - return $return; - } - - function trigger_error($errstr,$errno){ - trigger_error($errstr,$errno); - } - -} diff --git a/Library/Think/Cache/Driver/Simple.php b/Library/Think/Cache/Driver/Simple.php deleted file mode 100644 index e6231d92..00000000 --- a/Library/Think/Cache/Driver/Simple.php +++ /dev/null @@ -1,99 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * 文件类型缓存类 - * @author liu21st - */ -class Simple { - - protected $options = [ - 'prefix' => '', - 'temp' => '', - ]; - - /** - * 架构函数 - * @access public - */ - public function __construct($options=[]) { - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - if(substr($this->options['temp'], -1) != '/') $this->options['temp'] .= '/'; - } - - /** - * 取得变量的存储文件名 - * @access private - * @param string $name 缓存变量名 - * @return string - */ - private function filename($name) { - return $this->options['temp'].$this->options['prefix'].md5($name).'.php'; - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $filename = $this->filename($name); - if (is_file($filename)) { - return include $filename; - }else{ - return false; - } - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param int $expire 有效时间 0为永久 - * @return boolen - */ - public function set($name,$value,$expire=null) { - $filename = $this->filename($name); - // 缓存数据 - $dir = dirname($filename); - // 目录不存在则创建 - //if (!is_dir($dir)) - // mkdir($dir,0755,true); - return file_put_contents($filename, ("")); - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return unlink($this->filename($name)); - } - - /** - * 清除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function clear() { - $filename = $this->filename('*'); - array_map("unlink", glob($filename)); - } -} diff --git a/Library/Think/Cache/Driver/Sqlite.php b/Library/Think/Cache/Driver/Sqlite.php deleted file mode 100644 index d98da914..00000000 --- a/Library/Think/Cache/Driver/Sqlite.php +++ /dev/null @@ -1,119 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Sqlite缓存驱动 - * @author liu21st - */ -class Sqlite { - - protected $options = [ - 'db' => ':memory:', - 'table' => 'sharedmemory', - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - 'persistent' => false, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if ( !extension_loaded('sqlite') ) { - E('_NOT_SUPPERT_:sqlite'); - } - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - $func = $this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open'; - $this->handler = $func($this->options['db']); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $name = $this->options['prefix'].sqlite_escape_string($name); - $sql = 'SELECT value FROM '.$this->options['table'].' WHERE var=\''.$name.'\' AND (expire=0 OR expire >'.time().') LIMIT 1'; - $result = sqlite_query($this->handler, $sql); - if (sqlite_num_rows($result)) { - $content = sqlite_fetch_single($result); - if(function_exists('gzcompress')) { - //启用数据压缩 - $content = gzuncompress($content); - } - return unserialize($content); - } - return false; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value,$expire=null) { - $name = $this->options['prefix'].sqlite_escape_string($name); - $value = sqlite_escape_string(serialize($value)); - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $expire = ($expire==0)?0: (time()+$expire) ;//缓存有效期为0表示永久缓存 - if(function_exists('gzcompress')) { - //数据压缩 - $value = gzcompress($value,3); - } - $sql = 'REPLACE INTO '.$this->options['table'].' (var, value,expire) VALUES (\''.$name.'\', \''.$value.'\', \''.$expire.'\')'; - if(sqlite_query($this->handler, $sql)){ - if($this->options['length']>0) { - // 记录缓存队列 - $this->queue($name); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - $name = $this->options['prefix'].sqlite_escape_string($name); - $sql = 'DELETE FROM '.$this->options['table'].' WHERE var=\''.$name.'\''; - sqlite_query($this->handler, $sql); - return true; - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - $sql = 'DELETE FROM '.$this->options['table']; - sqlite_query($this->handler, $sql); - return ; - } -} diff --git a/Library/Think/Cache/Driver/Wincache.php b/Library/Think/Cache/Driver/Wincache.php deleted file mode 100644 index 9b963f75..00000000 --- a/Library/Think/Cache/Driver/Wincache.php +++ /dev/null @@ -1,103 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Wincache缓存驱动 - * @author liu21st - */ -class Wincache { - - protected $options = [ - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if ( !function_exists('wincache_ucache_info') ) { - E('_NOT_SUPPERT_:WinCache'); - } - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $name = $this->options['prefix'].$name; - return wincache_ucache_exists($name)? wincache_ucache_get($name) : false; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value,$expire=null) { - if(is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'].$name; - if(wincache_ucache_set($name, $value, $expire)) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = wincache_ucache_get('__info__'); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - wincache_ucache_delete($key); - } - wincache_ucache_set('__info__', $queue); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return wincache_ucache_delete($this->options['prefix'].$name); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return ; - } -} diff --git a/Library/Think/Cache/Driver/Xcache.php b/Library/Think/Cache/Driver/Xcache.php deleted file mode 100644 index ce4b37a8..00000000 --- a/Library/Think/Cache/Driver/Xcache.php +++ /dev/null @@ -1,106 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Cache\Driver; - -/** - * Xcache缓存驱动 - * @author liu21st - */ -class Xcache { - - protected $options = [ - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options=[]) { - if ( !function_exists('xcache_info') ) { - E('_NOT_SUPPERT_:Xcache'); - } - if(!empty($options)) { - $this->options = array_merge($this->options,$options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) { - $name = $this->options['prefix'].$name; - if (xcache_isset($name)) { - return xcache_get($name); - } - return false; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value,$expire=null) { - if(is_null($expire)) { - $expire = $this->options['expire'] ; - } - $name = $this->options['prefix'].$name; - if(xcache_set($name, $value, $expire)) { - if($this->options['length']>0) { - // 记录缓存队列 - $queue = xcache_get('__info__'); - if(!$queue) { - $queue = []; - } - if(false===array_search($name, $queue)) array_push($queue,$name); - if(count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - xcache_unset($key); - } - xcache_set('__info__', $queue); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) { - return xcache_unset($this->options['prefix'].$name); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() { - return ; - } -} diff --git a/Library/Think/Config.php b/Library/Think/Config.php deleted file mode 100644 index d1ce9e90..00000000 --- a/Library/Think/Config.php +++ /dev/null @@ -1,92 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Config { - static private $_config = []; // 配置参数 - static private $_range = '_sys_'; // 参数作用域 - - // 设定配置参数的作用域 - static public function range($range){ - self::$_range = $range; - } - - // 解析其他格式的配置参数 - static public function parse($config,$type='',$range=''){ - if(empty($type)) { - $type = substr(strrchr($config, '.'),1); - } - $class = '\Think\Config\Driver\\'.ucwords($type); - self::set((new $class())->parse($config),'',$range); - } - - // 加载配置文件 - static public function load($file,$range=''){ - return self::set(include $file,'',$range); - } - - // 检测配置是否存在 - static public function has($name,$range=''){ - $range = $range ? $range : self::$_range; - $name = strtolower($name); - - if (!strpos($name, '.')) { - return isset(self::$_config[$range][$name]); - }else{ - // 二维数组设置和获取支持 - $name = explode('.', $name); - return isset(self::$_config[$range][$name[0]][$name[1]]); - } - } - - // 获取配置参数 为空则获取所有配置 - static public function get($name=null,$range='') { - $range = $range?$range:self::$_range; - // 无参数时获取所有 - if (empty($name)) { - return self::$_config[$range]; - } - $name = strtolower($name); - if (!strpos($name, '.')) { - return isset(self::$_config[$range][$name]) ? self::$_config[$range][$name] : null; - }else{ - // 二维数组设置和获取支持 - $name = explode('.', $name); - return isset(self::$_config[$range][$name[0]][$name[1]]) ? self::$_config[$range][$name[0]][$name[1]] : null; - } - } - - // 设置配置参数 name为数组则为批量设置 - static public function set($name, $value=null,$range='') { - $range = $range?$range:self::$_range; - if(!isset(self::$_config[$range])) { - self::$_config[$range] = []; - } - if (is_string($name)) { - $name = strtolower($name); - if (!strpos($name, '.')) { - self::$_config[$range][$name] = $value; - }else{ - // 二维数组设置和获取支持 - $name = explode('.', $name); - self::$_config[$range][$name[0]][$name[1]] = $value; - } - return; - }elseif (is_array($name)){ - // 批量设置 - self::$_config[$range] = array_merge(self::$_config[$range], array_change_key_case($name)); - return self::$_config[$range]; - }else{ - return null; // 避免非法参数 - } - } -} diff --git a/Library/Think/Config/Driver/Ini.php b/Library/Think/Config/Driver/Ini.php deleted file mode 100644 index 398e631a..00000000 --- a/Library/Think/Config/Driver/Ini.php +++ /dev/null @@ -1,22 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Config\Driver; - -class Ini { - public function parse($config){ - if(is_file($config)) { - return parse_ini_file($config,true); - }else{ - return parse_ini_string($config,true); - } - } -} diff --git a/Library/Think/Config/Driver/Xml.php b/Library/Think/Config/Driver/Xml.php deleted file mode 100644 index e19e3e48..00000000 --- a/Library/Think/Config/Driver/Xml.php +++ /dev/null @@ -1,29 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Config\Driver; - -class Xml { - public function parse($config){ - if(is_file($config)) { - $content = simplexml_load_file($config); - }else{ - $content = simplexml_load_string($config); - } - $result = (array)$content; - foreach($result as $key=>$val){ - if(is_object($val)) { - $result[$key] = (array)$val; - } - } - return $result; - } -} diff --git a/Library/Think/Controller.php b/Library/Think/Controller.php deleted file mode 100644 index 102b691a..00000000 --- a/Library/Think/Controller.php +++ /dev/null @@ -1,192 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; -use Think\View; -use Think\Transform; - -class Controller { - // 视图类实例 - protected $view = null; - - /** - * 架构函数 初始化视图类 并采用内置模板引擎 - * @access public - */ - public function __construct(){ - // 模板引擎参数 - $this->view = new View(); - - //控制器初始化 - if(method_exists($this, '_initialize')) - $this->_initialize(); - } - - /** - * 加载模板和页面输出 可以返回输出内容 - * @access public - * @param string $template 模板文件名 - * @param array $vars 模板输出变量 - * @param string $cache_id 模板缓存标识 - * @return mixed - */ - public function display($template = '', $vars = [], $cache_id = ''){ - $this->view->display($template, $vars, $cache_id); - } - - /** - * 渲染内容输出 - * @access public - * @param string $content 内容 - * @param array $vars 模板输出变量 - * @return mixed - */ - public function show($content, $vars = []){ - $this->view->http('http_render_content', true)->display($content, $vars); - } - - /** - * 模板变量赋值 - * @access protected - * @param mixed $name 要显示的模板变量 - * @param mixed $value 变量的值 - * @return void - */ - public function assign($name, $value = ''){ - $this->view->assign($name, $value); - } - - public function __set($name, $value){ - return $this->assign($name, $value); - } - - /** - * Ajax方式返回数据到客户端 - * @access protected - * @param mixed $data 要返回的数据 - * @param String $type AJAX返回数据格式 - * @return void - */ - protected function ajaxReturn($data, $type='') { - if(empty($type)) $type = Config::get('default_ajax_return'); - switch (strtoupper($type)){ - case 'JSON': - // 返回JSON数据格式到客户端 包含状态信息 - header('Content-Type:application/json; charset=utf-8'); - $data = Transform::jsonEncode($data); - break; - case 'XML': - // 返回xml格式数据 - header('Content-Type:text/xml; charset=utf-8'); - $data = Transform::xmlEncode($data); - break; - case 'JSONP': - // 返回JSON数据格式到客户端 包含状态信息 - header('Content-Type:application/javascript; charset=utf-8'); - $handler = isset($_GET[C('var_jsonp_handler')]) ? $_GET[C('var_jsonp_handler')] : C('default_jsonp_handler'); - $data = $handler . '(' . Transform::jsonEncode($data) . ');'; - break; - case 'SCRIPT': - // 返回可执行的js脚本 - header('Content-Type:application/javascript; charset=utf-8'); - break; - case 'HTML': - // 返回html片段 - header('Content-Type:text/html; charset=utf-8'); - break; - case 'TEXT': - // 返回一段纯文本 - header('Content-Type:text/plain; charset=utf-8'); - break; - default: - // 用于扩展其他返回格式数据 - $data = Hook::listen('ajax_return', $data); - } - exit($data); - } - - /** - * 操作错误跳转的快捷方法 - * @access protected - * @param string $message 错误信息 - * @param string $jumpUrl 页面跳转地址 - * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 - * @return void - */ - protected function error($message, $jumpUrl = '', $ajax = false) { - $this->dispatchJump($message, 0, $jumpUrl, $ajax); - } - - /** - * 操作成功跳转的快捷方法 - * @access protected - * @param string $message 提示信息 - * @param string $jumpUrl 页面跳转地址 - * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 - * @return void - */ - protected function success($message, $jumpUrl = '', $ajax = false) { - $this->dispatchJump($message, 1, $jumpUrl, $ajax); - } - - /** - * 默认跳转操作 支持错误导向和正确跳转 - * 调用模板显示 默认为public目录下面的success页面 - * 提示页面为可配置 支持模板标签 - * @access private - * @param string $message 提示信息 - * @param Boolean $status 状态 - * @param string $jumpUrl 页面跳转地址 - * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 - * @return void - */ - private function dispatchJump($message, $status = 1, $jumpUrl = '', $ajax = false) { - if(true === $ajax || IS_AJAX) {// AJAX提交 - $data = is_array($ajax) ? $ajax : []; - $data['info'] = $message; - $data['status'] = $status; - $data['url'] = $jumpUrl; - $this->ajaxReturn($data); - } - // 模板变量 - $data = []; - if(is_int($ajax)) - $data['waitSecond'] = $ajax; - if(!empty($jumpUrl)) - $data['jumpUrl'] = $jumpUrl; - - // 提示标题 - $data['msgTitle'] = $status ? L('_OPERATION_SUCCESS_') : L('_OPERATION_FAIL_'); - $data['status'] = $status; // 状态 - - //保证输出不受静态缓存影响 - Config::set('html_cache_on',false); - if($status) { //发送成功信息 - $data['message'] = $message;// 提示信息 - // 成功操作后默认停留1秒 - $data['waitSecond'] = '1'; - // 默认操作成功自动返回操作前页面 - if(!$jumpUrl) - $data["jumpUrl"] = $_SERVER["HTTP_REFERER"]; - $this->display(Config::get('success_tmpl'),$data); - }else{ - $data['error'] = $message;// 提示信息 - //发生错误时候默认停留3秒 - $data['waitSecond'] = '3'; - // 默认发生错误的话自动返回上页 - if(!$jumpUrl) - $data['jumpUrl'] = 'javascript:history.back(-1);'; - $this->display(Config::get('error_tmpl'),$data); - // 中止执行 避免出错后继续执行 - exit ; - } - } -} diff --git a/Library/Think/Cookie.php b/Library/Think/Cookie.php deleted file mode 100644 index 00868771..00000000 --- a/Library/Think/Cookie.php +++ /dev/null @@ -1,138 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Cookie { - - static protected $config = [ - 'prefix' => '', // cookie 名称前缀 - 'expire' => 0, // cookie 保存时间 - 'path' => '/', // cookie 保存路径 - 'domain' => '', // cookie 有效域名 - 'secure' => false, // cookie 启用安全传输 - 'httponly' => '', // httponly设置 - ]; - - /** - * Cookie初始化 - * @param array $config - * @return void - */ - static public function init($config=[]){ - self::$config = array_merge(self::$config, array_change_key_case($config)); - if(!empty(self::$config['httponly'])){ - ini_set('session.cookie_httponly', 1); - } - } - - /** - * 设置或者获取cookie作用域(前缀) - * @param string $prefix - * @return string|void - */ - static public function prefix($prefix=''){ - if(empty($prefix)) { - return self::$config['prefix']; - }else{ - self::$config['prefix'] = $prefix; - } - } - - /** - * Cookie 设置、获取、删除 - * @param string $name cookie名称 - * @param mixed $value cookie值 - * @param mixed $options cookie参数 - * @return mixed - */ - static public function set($name, $value='', $option=null) { - // 参数设置(会覆盖黙认设置) - if (!is_null($option)) { - if (is_numeric($option)) - $option = ['expire' => $option]; - elseif (is_string($option)) - parse_str($option, $option); - $config = array_merge(self::$config, array_change_key_case($option)); - }else{ - $config = self::$config; - } - $name = $config['prefix'] . $name; - // 设置cookie - if(is_array($value)){ - $value = 'think:'.json_encode(array_map('urlencode',$value)); - } - $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0; - setcookie($name, $value, $expire, $config['path'], $config['domain'],$config['secure'],$config['httponly']); - $_COOKIE[$name] = $value; - } - - /** - * Cookie获取 - * @param string $name cookie名称 - * @param string $prefix cookie前缀 - * @return mixed - */ - static public function get($name, $prefix='') { - $prefix = $prefix ? $prefix : self::$config['prefix']; - $name = $prefix . $name; - if(isset($_COOKIE[$name])){ - $value = $_COOKIE[$name]; - if(0 === strpos($value,'think:')){ - $value = substr($value,6); - return array_map('urldecode',json_decode($value,true)); - }else{ - return $value; - } - }else{ - return null; - } - } - - /** - * Cookie删除 - * @param string $name cookie名称 - * @param string $prefix cookie前缀 - * @return mixed - */ - static public function delete($name, $prefix='') { - $config = self::$config; - $prefix = $prefix ? $prefix : $config['prefix']; - $name = $prefix . $name; - setcookie($name, '', time() - 3600, $config['path'], $config['domain'],$config['secure'],$config['httponly']); - unset($_COOKIE[$name]); // 删除指定cookie - } - - /** - * Cookie清空 - * @param string $prefix cookie前缀 - * @return mixed - */ - static public function clear($prefix='') { - // 清除指定前缀的所有cookie - if (empty($_COOKIE)) - return; - // 要删除的cookie前缀,不指定则删除config设置的指定前缀 - $config = self::$config; - $prefix = $prefix ? $prefix: $config['prefix']; - if ($prefix) {// 如果前缀为空字符串将不作处理直接返回 - foreach ($_COOKIE as $key => $val) { - if (0 === strpos($key, $prefix)) { - setcookie($key, '', time() - 3600, $config['path'], $config['domain'],$config['secure'],$config['httponly']); - unset($_COOKIE[$key]); - } - } - }else{ - unset($_COOKIE); - } - return; - } -} diff --git a/Library/Think/Create.php b/Library/Think/Create.php deleted file mode 100644 index 72f98d0d..00000000 --- a/Library/Think/Create.php +++ /dev/null @@ -1,102 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Create { - static public function build($build) { - // 锁定 - $lockfile = APP_PATH.'create.lock'; - if(is_writable($lockfile)) { - return ; - } else { - if(!touch($lockfile)){ - header('Content-Type:text/html; charset=utf-8'); - exit('目录 [ '.APP_PATH.' ] 不可写!'); - } - } - foreach ($build as $module=>$list){ - if(!is_dir(APP_PATH.$module)) {// 创建模块目录 - mkdir(APP_PATH.$module); - } - // 创建配置文件和公共文件 - self::buildCommonFile($module); - // 创建欢迎页面 - self::buildHelloController($module); - - // 创建子目录和文件 - foreach($list as $path=>$file){ - if(is_int($path)) { - // 生成文件 - if(!is_file(APP_PATH.$module.'/'.$file)) { - file_put_contents(APP_PATH.$module.'/'.$file," -// +---------------------------------------------------------------------- - -namespace Think; - -/** - * ThinkPHP 数据库中间层实现类 - */ -class Db { - - static private $instance = []; // 数据库连接实例 - static private $_instance = null; // 当前数据库连接实例 - - /** - * 取得数据库类实例 - * @static - * @access public - * @param mixed $config 连接配置 - * @param boolean $lite 是否lite方式 - * @return Object 返回数据库驱动类 - */ - static public function instance($config=[],$lite=false) { - $md5 = md5(serialize($config)); - if(!isset(self::$instance[$md5])) { - // 解析连接参数 支持数组和字符串 - $options = self::parseConfig($config); - // 如果采用lite方式 仅支持原生SQL 包括query和execute方法 - $class = $lite? 'Think\Db\Lite' : 'Think\\Db\\Driver\\'.ucwords($options['type']); - self::$instance[$md5] = new $class($options); - } - self::$_instance = self::$instance[$md5]; - return self::$_instance; - } - - /** - * 数据库连接参数解析 - * @static - * @access private - * @param mixed $config - * @return array - */ - static private function parseConfig($config){ - if(empty($config)) { - $config = Config::get('database'); - } - if(is_string($config)) { - return self::parseDsn($config); - }else{ - return $config; - } - } - - /** - * DSN解析 - * 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1¶m2=val2#utf8 - * @static - * @access private - * @param string $dsnStr - * @return array - */ - static private function parseDsn($dsnStr) { - if( empty($dsnStr) ){return false;} - $info = parse_url($dsnStr); - if(!$info) { - return false; - } - $dsn = [ - 'type' => $info['scheme'], - 'username' => isset($info['user']) ? $info['user'] : '', - 'password' => isset($info['pass']) ? $info['pass'] : '', - 'hostname' => isset($info['host']) ? $info['host'] : '', - 'hostport' => isset($info['port']) ? $info['port'] : '', - 'database' => isset($info['path']) ? substr($info['path'],1) : '', - 'charset' => isset($info['fragment'])?$info['fragment']:'utf8', - ]; - - if(isset($info['query'])) { - parse_str($info['query'],$dsn['params']); - }else{ - $dsn['params'] = []; - } - return $dsn; - } - - // 调用驱动类的方法 - static public function __callStatic($method, $params){ - return call_user_func_array(array(self::$_instance, $method), $params); - } -} diff --git a/Library/Think/Db/Driver.php b/Library/Think/Db/Driver.php deleted file mode 100644 index 293fa164..00000000 --- a/Library/Think/Db/Driver.php +++ /dev/null @@ -1,1037 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db; -use Think\Config; -use Think\Debug; -use Think\Log; -use PDO; - -abstract class Driver { - // PDO操作实例 - protected $PDOStatement = null; - // 当前操作所属的模型名 - protected $model = '_think_'; - // 当前SQL指令 - protected $queryStr = ''; - protected $modelSql = []; - // 最后插入ID - protected $lastInsID = null; - // 返回或者影响记录数 - protected $numRows = 0; - // 事务指令数 - protected $transTimes = 0; - // 错误信息 - protected $error = ''; - // 数据库连接ID 支持多个连接 - protected $linkID = []; - // 当前连接ID - protected $_linkID = null; - // 数据库连接参数配置 - protected $config = [ - 'type' => '', // 数据库类型 - 'hostname' => '127.0.0.1', // 服务器地址 - 'database' => '', // 数据库名 - 'username' => '', // 用户名 - 'password' => '', // 密码 - 'hostport' => '', // 端口 - 'dsn' => '', // - 'params' => [], // 数据库连接参数 - 'charset' => 'utf8', // 数据库编码默认采用utf8 - 'prefix' => '', // 数据库表前缀 - 'debug' => false, // 数据库调试模式 - 'deploy' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'rw_separate' => false, // 数据库读写是否分离 主从式有效 - 'master_num' => 1, // 读写分离后 主服务器数量 - 'slave_no' => '', // 指定从服务器序号 - ]; - // 数据库表达式 - protected $comparison = ['eq'=>'=','neq'=>'<>','gt'=>'>','egt'=>'>=','lt'=>'<','elt'=>'<=','notlike'=>'NOT LIKE','like'=>'LIKE','in'=>'IN','notin'=>'NOT IN']; - // 查询表达式 - protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%'; - // 查询次数 - protected $queryTimes = 0; - // 执行次数 - protected $executeTimes = 0; - // PDO连接参数 - protected $options = [ - PDO::ATTR_CASE => PDO::CASE_LOWER, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, - PDO::ATTR_STRINGIFY_FETCHES => false, - ]; - protected $bind = []; // 参数绑定 - - /** - * 架构函数 读取数据库配置信息 - * @access public - * @param array $config 数据库配置数组 - */ - public function __construct($config=''){ - if(!empty($config)) { - $this->config = array_merge($this->config,$config); - $this->config['params'] = $this->options+$this->config['params']; - } - } - - /** - * 连接数据库方法 - * @access public - */ - public function connect($config='',$linkNum=0) { - if ( !isset($this->linkID[$linkNum]) ) { - if(empty($config)) $config = $this->config; - try{ - if(empty($config['dsn'])) { - $config['dsn'] = $this->parseDsn($config); - } - $this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$config['params']); - }catch (\PDOException $e) { - E($e->getMessage()); - } - } - return $this->linkID[$linkNum]; - } - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config){} - - /** - * 释放查询结果 - * @access public - */ - public function free() { - $this->PDOStatement = null; - } - - /** - * 执行查询 返回数据集 - * @access public - * @param string $str sql指令 - * @param array $bind 参数绑定 - * @return mixed - */ - public function query($str,$bind=[]) { - $this->initConnect(false); - if ( !$this->_linkID ) return false; - $this->queryStr = $str; - if(!empty($bind)){ - $this->queryStr .= '[ '.print_r($bind,true).' ]'; - } - //释放前次的查询结果 - if ( !empty($this->PDOStatement) ) $this->free(); - $this->queryTimes++; - // 调试开始 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if(false === $this->PDOStatement) - E($this->error()); - foreach ($bind as $key => $val) { - if(is_array($val)){ - $this->PDOStatement->bindValue($key, $val[0], $val[1]); - }else{ - $this->PDOStatement->bindValue($key, $val); - } - } - $result = $this->PDOStatement->execute(); - // 调试结束 - $this->debug(false); - if ( false === $result ) { - $this->error(); - return false; - } else { - return $this->getResult(); - } - } - - /** - * 执行语句 - * @access public - * @param string $str sql指令 - * @param array $bind 参数绑定 - * @return integer - */ - public function execute($str,$bind=[]) { - $this->initConnect(true); - if ( !$this->_linkID ) return false; - $this->queryStr = $str; - if(!empty($bind)){ - $this->queryStr .= '[ '.print_r($bind,true).' ]'; - } - //释放前次的查询结果 - if ( !empty($this->PDOStatement) ) $this->free(); - $this->executeTimes++; - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if(false === $this->PDOStatement) { - E($this->error()); - } - foreach ($bind as $key => $val) { - if(is_array($val)){ - $this->PDOStatement->bindValue($key, $val[0], $val[1]); - }else{ - $this->PDOStatement->bindValue($key, $val); - } - } - $result = $this->PDOStatement->execute(); - $this->debug(false); - if ( false === $result) { - $this->error(); - return false; - } else { - $this->numRows = $this->PDOStatement->rowCount(); - if(preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { - $this->lastInsID = $this->_linkID->lastInsertId(); - } - return $this->numRows; - } - } - - /** - * 启动事务 - * @access public - * @return void - */ - public function startTrans() { - $this->initConnect(true); - if ( !$this->_linkID ) return false; - //数据rollback 支持 - if ($this->transTimes == 0) { - $this->_linkID->beginTransaction(); - } - $this->transTimes++; - return ; - } - - /** - * 用于非自动提交状态下面的查询提交 - * @access public - * @return boolen - */ - public function commit() { - if ($this->transTimes > 0) { - $result = $this->_linkID->commit(); - $this->transTimes = 0; - if(!$result){ - $this->error(); - return false; - } - } - return true; - } - - /** - * 事务回滚 - * @access public - * @return boolen - */ - public function rollback() { - if ($this->transTimes > 0) { - $result = $this->_linkID->rollback(); - $this->transTimes = 0; - if(!$result){ - $this->error(); - return false; - } - } - return true; - } - - /** - * 获得所有的查询数据 - * @access private - * @return array - */ - private function getResult() { - //返回数据集 - $result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC); - $this->numRows = count( $result ); - return $result; - } - - /** - * 获得查询次数 - * @access public - * @param boolean $execute 是否包含所有查询 - * @return integer - */ - public function getQueryTimes($execute=false){ - return $execute?$this->queryTimes+$this->executeTimes:$this->queryTimes; - } - - /** - * 获得执行次数 - * @access public - * @return integer - */ - public function getExecuteTimes(){ - return $this->executeTimes; - } - - /** - * 关闭数据库 - * @access public - */ - public function close() { - $this->_linkID = null; - } - - /** - * 数据库错误信息 - * 并显示当前的SQL语句 - * @access public - * @return string - */ - public function error() { - if($this->PDOStatement) { - $error = $this->PDOStatement->errorInfo(); - $this->error = $error[1].':'.$error[2]; - }else{ - $this->error = ''; - } - if('' != $this->queryStr){ - $this->error .= "\n [ SQL语句 ] : ".$this->queryStr; - } - // 记录错误日志 - Log::record($this->error,'ERR'); - if($this->config['debug']) {// 开启数据库调试模式 - E($this->error); - }else{ - return $this->error; - } - } - - /** - * 设置锁机制 - * @access protected - * @return string - */ - protected function parseLock($lock=false) { - return $lock? ' FOR UPDATE ' : ''; - } - - /** - * set分析 - * @access protected - * @param array $data - * @return string - */ - protected function parseSet($data) { - foreach ($data as $key=>$val){ - if(is_scalar($val)) {// 过滤非标量数据 - if(0===strpos($val,':')){ - $set[] = $this->parseKey($key).'='.$this->escapeString($val); - }else{ - $name = count($this->bind); - $set[] = $this->parseKey($key).'=:'.$name; - $this->bindParam($name,$val); - } - } - } - return ' SET '.implode(',',$set); - } - - /** - * 参数绑定 - * @access protected - * @param string $name 绑定参数名 - * @param mixed $value 绑定值 - * @return void - */ - protected function bindParam($name,$value){ - $this->bind[':'.$name] = $value; - } - - /** - * 字段名分析 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey(&$key) { - return $key; - } - - /** - * value分析 - * @access protected - * @param mixed $value - * @return string - */ - protected function parseValue($value) { - if(is_string($value)) { - $value = strpos($value,':') === 0 ? $this->escapeString($value) : '\''.$this->escapeString($value).'\''; - }elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){ - $value = $this->escapeString($value[1]); - }elseif(is_array($value)) { - $value = array_map([$this, 'parseValue'],$value); - }elseif(is_bool($value)){ - $value = $value ? '1' : '0'; - }elseif(is_null($value)){ - $value = 'null'; - } - return $value; - } - - /** - * field分析 - * @access protected - * @param mixed $fields - * @return string - */ - protected function parseField($fields) { - if(is_string($fields) && strpos($fields,',')) { - $fields = explode(',',$fields); - } - if(is_array($fields)) { - // 完善数组方式传字段名的支持 - // 支持 'field1'=>'field2' 这样的字段别名定义 - $array = []; - foreach ($fields as $key=>$field){ - if(!is_numeric($key)) - $array[] = $this->parseKey($key).' AS '.$this->parseKey($field); - else - $array[] = $this->parseKey($field); - } - $fieldsStr = implode(',', $array); - }elseif(is_string($fields) && !empty($fields)) { - $fieldsStr = $this->parseKey($fields); - }else{ - $fieldsStr = '*'; - } - //TODO 如果是查询全部字段,并且是join的方式,那么就把要查的表加个别名,以免字段被覆盖 - return $fieldsStr; - } - - /** - * table分析 - * @access protected - * @param mixed $table - * @return string - */ - protected function parseTable($tables) { - if(is_array($tables)) {// 支持别名定义 - $array = []; - foreach ($tables as $table=>$alias){ - if(!is_numeric($table)) - $array[] = $this->parseKey($table).' '.$this->parseKey($alias); - else - $array[] = $this->parseKey($alias); - } - $tables = $array; - }elseif(is_string($tables)){ - $tables = explode(',',$tables); - array_walk($tables, [&$this, 'parseKey']); - } - return implode(',',$tables); - } - - /** - * where分析 - * @access protected - * @param mixed $where - * @return string - */ - protected function parseWhere($where) { - $whereStr = ''; - if(is_string($where)) { - // 直接使用字符串条件 - $whereStr = $where; - }else{ // 使用数组表达式 - $operate = isset($where['_logic'])?strtoupper($where['_logic']):''; - if(in_array($operate,['AND','OR','XOR'])){ - // 定义逻辑运算规则 例如 OR XOR AND NOT - $operate = ' '.$operate.' '; - unset($where['_logic']); - }else{ - // 默认进行 AND 运算 - $operate = ' AND '; - } - foreach ($where as $key=>$val){ - $whereStr .= '( '; - if(0===strpos($key,'_')) { - // 解析特殊条件表达式 - $whereStr .= $this->parseThinkWhere($key,$val); - }else{ - // 查询字段的安全过滤 - if(!preg_match('/^[A-Z_\|\&\-.a-z0-9\(\)\,]+$/',trim($key))){ - E(L('_EXPRESS_ERROR_').':'.$key); - } - // 多条件支持 - $multi = is_array($val) && isset($val['_multi']); - $key = trim($key); - if(strpos($key,'|')) { // 支持 name|title|nickname 方式定义查询字段 - $array = explode('|',$key); - $str = []; - foreach ($array as $m=>$k){ - $v = $multi?$val[$m]:$val; - $str[] = '('.$this->parseWhereItem($this->parseKey($k),$v).')'; - } - $whereStr .= implode(' OR ',$str); - }elseif(strpos($key,'&')){ - $array = explode('&',$key); - $str = []; - foreach ($array as $m=>$k){ - $v = $multi?$val[$m]:$val; - $str[] = '('.$this->parseWhereItem($this->parseKey($k),$v).')'; - } - $whereStr .= implode(' AND ',$str); - }else{ - $whereStr .= $this->parseWhereItem($this->parseKey($key),$val); - } - } - $whereStr .= ' )'.$operate; - } - $whereStr = substr($whereStr,0,-strlen($operate)); - } - return empty($whereStr)?'':' WHERE '.$whereStr; - } - - // where子单元分析 - protected function parseWhereItem($key,$val) { - $whereStr = ''; - if(is_array($val)) { - if(is_string($val[0])) { - if(preg_match('/^(EQ|NEQ|GT|EGT|LT|ELT)$/i',$val[0])) { // 比较运算 - $whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]); - }elseif(preg_match('/^(NOTLIKE|LIKE)$/i',$val[0])){// 模糊查找 - if(is_array($val[1])) { - $likeLogic = isset($val[2])?strtoupper($val[2]):'OR'; - if(in_array($likeLogic,['AND','OR','XOR'])){ - $likeStr = $this->comparison[strtolower($val[0])]; - $like = []; - foreach ($val[1] as $item){ - $like[] = $key.' '.$likeStr.' '.$this->parseValue($item); - } - $whereStr .= '('.implode(' '.$likeLogic.' ',$like).')'; - } - }else{ - $whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]); - } - }elseif('bind'==strtolower($val[0])){ // 使用表达式 - $whereStr .= ' ('.$key.' = :'.$val[1].') '; - }elseif('exp'==strtolower($val[0])){ // 使用表达式 - $whereStr .= ' ('.$key.' '.$val[1].') '; - }elseif(preg_match('/IN/i',$val[0])){ // IN 运算 - if(isset($val[2]) && 'exp'==$val[2]) { - $whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1]; - }else{ - if(is_string($val[1])) { - $val[1] = explode(',',$val[1]); - } - $zone = implode(',',$this->parseValue($val[1])); - $whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')'; - } - }elseif(preg_match('/BETWEEN/i',$val[0])){ // BETWEEN运算 - $data = is_string($val[1])? explode(',',$val[1]):$val[1]; - $whereStr .= ' ('.$key.' '.strtoupper($val[0]).' '.$this->parseValue($data[0]).' AND '.$this->parseValue($data[1]).' )'; - }else{ - E(L('_EXPRESS_ERROR_').':'.$val[0]); - } - }else { - $count = count($val); - $rule = isset($val[$count-1])?strtoupper($val[$count-1]):''; - if(in_array($rule,['AND','OR','XOR'])) { - $count = $count -1; - }else{ - $rule = 'AND'; - } - for($i=0;$i<$count;$i++) { - $data = is_array($val[$i])?$val[$i][1]:$val[$i]; - if('exp'==strtolower($val[$i][0])) { - $whereStr .= '('.$key.' '.$data.') '.$rule.' '; - }else{ - $op = is_array($val[$i])?$this->comparison[strtolower($val[$i][0])]:'='; - $whereStr .= '('.$key.' '.$op.' '.$this->parseValue($data).') '.$rule.' '; - } - } - $whereStr = substr($whereStr,0,-4); - } - }else { - //对字符串类型字段采用模糊匹配 - if($this->config['db_like_fields'] && preg_match('/('.$this->config['db_like_fields'].')/i',$key)) { - $val = '%'.$val.'%'; - $whereStr .= $key.' LIKE '.$this->parseValue($val); - }else { - $whereStr .= $key.' = '.$this->parseValue($val); - } - } - return $whereStr; - } - - /** - * 特殊条件分析 - * @access protected - * @param string $key - * @param mixed $val - * @return string - */ - protected function parseThinkWhere($key,$val) { - $whereStr = ''; - switch($key) { - case '_string': - // 字符串模式查询条件 - $whereStr = $val; - break; - case '_complex': - // 复合查询条件 - $whereStr = substr($this->parseWhere($val),6); - break; - case '_query': - // 字符串模式查询条件 - parse_str($val,$where); - if(isset($where['_logic'])) { - $op = ' '.strtoupper($where['_logic']).' '; - unset($where['_logic']); - }else{ - $op = ' AND '; - } - $array = []; - foreach ($where as $field=>$data) - $array[] = $this->parseKey($field).' = '.$this->parseValue($data); - $whereStr = implode($op,$array); - break; - } - return $whereStr; - } - - /** - * limit分析 - * @access protected - * @param mixed $lmit - * @return string - */ - protected function parseLimit($limit) { - return !empty($limit)? ' LIMIT '.$limit.' ':''; - } - - /** - * join分析 - * @access protected - * @param mixed $join - * @return string - */ - protected function parseJoin($join) { - $joinStr = ''; - if(!empty($join)) { - if(is_array($join)) { - foreach ($join as $key=>$_join){ - if(false !== stripos($_join,'JOIN')) - $joinStr .= ' '.$_join; - else - $joinStr .= ' LEFT JOIN ' .$_join; - } - }else{ - $joinStr .= ' LEFT JOIN ' .$join; - } - } - //将__TABLE_NAME__这样的字符串替换成正规的表名,并且带上前缀和后缀 - $joinStr = preg_replace("/__([A-Z_-]+)__/esU",$this->config['prefix'].".strtolower('$1')",$joinStr); - return $joinStr; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return string - */ - protected function parseOrder($order) { - if(is_array($order)) { - $array = []; - foreach ($order as $key=>$val){ - if(is_numeric($key)) { - $array[] = $this->parseKey($val); - }else{ - $array[] = $this->parseKey($key).' '.$val; - } - } - $order = implode(',',$array); - } - return !empty($order)? ' ORDER BY '.$order:''; - } - - /** - * group分析 - * @access protected - * @param mixed $group - * @return string - */ - protected function parseGroup($group) { - return !empty($group)? ' GROUP BY '.$group:''; - } - - /** - * having分析 - * @access protected - * @param string $having - * @return string - */ - protected function parseHaving($having) { - return !empty($having)? ' HAVING '.$having:''; - } - - /** - * comment分析 - * @access protected - * @param string $comment - * @return string - */ - protected function parseComment($comment) { - return !empty($comment)? ' /* '.$comment.' */':''; - } - - /** - * distinct分析 - * @access protected - * @param mixed $distinct - * @return string - */ - protected function parseDistinct($distinct) { - return !empty($distinct)? ' DISTINCT ' :''; - } - - /** - * union分析 - * @access protected - * @param mixed $union - * @return string - */ - protected function parseUnion($union) { - if(empty($union)) return ''; - if(isset($union['_all'])) { - $str = 'UNION ALL '; - unset($union['_all']); - }else{ - $str = 'UNION '; - } - foreach ($union as $u){ - $sql[] = $str.(is_array($u)?$this->buildSelectSql($u):$u); - } - return implode(' ',$sql); - } - - /** - * 参数绑定分析 - * @access protected - * @param array $bind - * @return array - */ - protected function parseBind($bind){ - $bind = array_merge($this->bind,$bind); - $this->bind = []; - return $bind; - } - - /** - * 插入记录 - * @access public - * @param mixed $data 数据 - * @param array $options 参数表达式 - * @param boolean $replace 是否replace - * @return false | integer - */ - public function insert($data,$options=[],$replace=false) { - $values = $fields = []; - $this->model = $options['model']; - foreach ($data as $key=>$val){ - if(is_scalar($val)) { // 过滤非标量数据 - $fields[] = $this->parseKey($key); - if(0===strpos($val,':')){ - $values[] = $this->escapeString($val); - }else{ - $name = count($this->bind); - $values[] = ':'.$name; - $this->bindParam($name,$val); - } - } - } - $sql = ($replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')'; - $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false); - $sql .= $this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - } - - /** - * 通过Select方式插入记录 - * @access public - * @param string $fields 要插入的数据表字段名 - * @param string $table 要插入的数据表名 - * @param array $option 查询数据参数 - * @return false | integer - */ - public function selectInsert($fields,$table,$options=[]) { - $this->model = $options['model']; - if(is_string($fields)) $fields = explode(',',$fields); - array_walk($fields, [$this, 'parseKey']); - $sql = 'INSERT INTO '.$this->parseTable($table).' ('.implode(',', $fields).') '; - $sql .= $this->buildSelectSql($options); - return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - } - - /** - * 更新记录 - * @access public - * @param mixed $data 数据 - * @param array $options 表达式 - * @return false | integer - */ - public function update($data,$options) { - $this->model = $options['model']; - $sql = 'UPDATE ' - .$this->parseTable($options['table']) - .$this->parseSet($data) - .$this->parseWhere(!empty($options['where'])?$options['where']:'') - .$this->parseOrder(!empty($options['order'])?$options['order']:'') - .$this->parseLimit(!empty($options['limit'])?$options['limit']:'') - .$this->parseLock(isset($options['lock'])?$options['lock']:false) - .$this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options=[]) { - $this->model = $options['model']; - $sql = 'DELETE FROM ' - .$this->parseTable($options['table']) - .$this->parseWhere(!empty($options['where'])?$options['where']:'') - .$this->parseOrder(!empty($options['order'])?$options['order']:'') - .$this->parseLimit(!empty($options['limit'])?$options['limit']:'') - .$this->parseLock(isset($options['lock'])?$options['lock']:false) - .$this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - } - - /** - * 查找记录 - * @access public - * @param array $options 表达式 - * @return mixed - */ - public function select($options=[]) { - $this->model = $options['model']; - $sql = $this->buildSelectSql($options); - $cache = isset($options['cache'])?$options['cache']:false; - if($cache) { // 查询缓存检测 - $key = is_string($cache['key'])?$cache['key']:md5($sql); - $value = S($key,'',$cache); - if(false !== $value) { - return $value; - } - } - $result = $this->query($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - if($cache && false !== $result ) { // 查询缓存写入 - S($key,$result,$cache); - } - return $result; - } - - /** - * 生成查询SQL - * @access public - * @param array $options 表达式 - * @return string - */ - public function buildSelectSql($options=[]) { - if(isset($options['page'])) { - // 根据页数计算limit - if(strpos($options['page'],',')) { - list($page,$listRows) = explode(',',$options['page']); - }else{ - $page = $options['page']; - } - $page = $page?$page:1; - $listRows= isset($listRows)?$listRows:(is_numeric($options['limit'])?$options['limit']:20); - $offset = $listRows*((int)$page-1); - $options['limit'] = $offset.','.$listRows; - } - $sql = $this->parseSql($this->selectSql,$options); - $sql .= $this->parseLock(isset($options['lock'])?$options['lock']:false); - return $sql; - } - - /** - * 替换SQL语句中表达式 - * @access public - * @param array $options 表达式 - * @return string - */ - public function parseSql($sql,$options=[]){ - $sql = str_replace( - ['%TABLE%','%DISTINCT%','%FIELD%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%','%UNION%','%COMMENT%'], - [ - $this->parseTable($options['table']), - $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false), - $this->parseField(!empty($options['field'])?$options['field']:'*'), - $this->parseJoin(!empty($options['join'])?$options['join']:''), - $this->parseWhere(!empty($options['where'])?$options['where']:''), - $this->parseGroup(!empty($options['group'])?$options['group']:''), - $this->parseHaving(!empty($options['having'])?$options['having']:''), - $this->parseOrder(!empty($options['order'])?$options['order']:''), - $this->parseLimit(!empty($options['limit'])?$options['limit']:''), - $this->parseUnion(!empty($options['union'])?$options['union']:''), - $this->parseComment(!empty($options['comment'])?$options['comment']:'') - ],$sql); - return $sql; - } - - /** - * 获取最近一次查询的sql语句 - * @param string $model 模型名 - * @access public - * @return string - */ - public function getLastSql($model='') { - return $model?$this->modelSql[$model]:$this->queryStr; - } - - /** - * 获取最近插入的ID - * @access public - * @return string - */ - public function getLastInsID() { - return $this->lastInsID; - } - - /** - * 获取最近的错误信息 - * @access public - * @return string - */ - public function getError() { - return $this->error; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL字符串 - * @return string - */ - public function escapeString($str) { - return addslashes($str); - } - - /** - * 设置当前操作模型 - * @access public - * @param string $model 模型名 - * @return void - */ - public function setModel($model){ - $this->model = $model; - } - - /** - * 数据库调试 记录当前SQL - * @access protected - * @param boolean $start 调试开始标记 true 开始 false 结束 - */ - protected function debug($start) { - if($this->config['debug']) {// 开启数据库调试模式 - if($start) { - Debug::remark('queryStartTime','time'); - }else{ - $this->modelSql[$this->model] = $this->queryStr; - //$this->model = '_think_'; - // 记录操作结束时间 - Debug::remark('queryEndTime','time'); - Log::record($this->queryStr.' [ RunTime:'.Debug::getUseTime('queryStartTime','queryEndTime').'s ]','SQL'); - } - } - } - - /** - * 初始化数据库连接 - * @access protected - * @param boolean $master 主服务器 - * @return void - */ - protected function initConnect($master=true) { - if(!empty($this->config['deploy'])) - // 采用分布式数据库 - $this->_linkID = $this->multiConnect($master); - else - // 默认单数据库 - if ( !$this->_linkID ) $this->_linkID = $this->connect(); - } - - /** - * 连接分布式服务器 - * @access protected - * @param boolean $master 主服务器 - * @return void - */ - protected function multiConnect($master=false) { - static $_config = []; - if(empty($_config)) { - // 缓存分布式数据库配置解析 - $_config['username'] = explode(',',$$this->config['username']); - $_config['password'] = explode(',',$$this->config['password']); - $_config['hostname'] = explode(',',$$this->config['hostname']); - $_config['hostport'] = explode(',',$$this->config['hostport']); - $_config['database'] = explode(',',$$this->config['database']); - $_config['dsn'] = explode(',',$$this->config['dsn']); - } - // 数据库读写是否分离 - if($this->config['rw_separate']){ - // 主从式采用读写分离 - if($master) - // 主服务器写入 - $r = floor(mt_rand(0,$this->config['master_num']-1)); - else{ - if(is_numeric($this->config['slave_no'])) {// 指定服务器读 - $r = $this->config['slave_no']; - }else{ - // 读操作连接从服务器 - $r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库 - } - } - }else{ - // 读写操作不区分服务器 - $r = floor(mt_rand(0,count($_config['hostname'])-1)); // 每次随机连接的数据库 - } - $db_config = [ - 'username' => isset($_config['username'][$r])?$_config['username'][$r]:$_config['username'][0], - 'password' => isset($_config['password'][$r])?$_config['password'][$r]:$_config['password'][0], - 'hostname' => isset($_config['hostname'][$r])?$_config['hostname'][$r]:$_config['hostname'][0], - 'hostport' => isset($_config['hostport'][$r])?$_config['hostport'][$r]:$_config['hostport'][0], - 'database' => isset($_config['database'][$r])?$_config['database'][$r]:$_config['database'][0], - 'dsn' => isset($_config['dsn'][$r])?$_config['dsn'][$r]:$_config['dsn'][0], - ]; - return $this->connect($db_config,$r); - } - - /** - * 析构方法 - * @access public - */ - public function __destruct() { - // 释放查询 - if ($this->PDOStatement){ - $this->free(); - } - // 关闭连接 - $this->close(); - } -} diff --git a/Library/Think/Db/Driver/Mongo.php b/Library/Think/Db/Driver/Mongo.php deleted file mode 100644 index e17cbf77..00000000 --- a/Library/Think/Db/Driver/Mongo.php +++ /dev/null @@ -1,735 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Mongo数据库驱动 - */ -class Mongo extends Driver { - - protected $_mongo = null; // MongoDb Object - protected $_collection = null; // MongoCollection Object - protected $_dbName = ''; // dbName - protected $_collectionName = ''; // collectionName - protected $_cursor = null; // MongoCursor Object - protected $comparison = ['neq'=>'ne','ne'=>'ne','gt'=>'gt','egt'=>'gte','gte'=>'gte','lt'=>'lt','elt'=>'lte','lte'=>'lte','in'=>'in','not in'=>'nin','nin'=>'nin']; - - /** - * 架构函数 读取数据库配置信息 - * @access public - * @param array $config 数据库配置数组 - */ - public function __construct($config=''){ - if ( !class_exists('mongoClient') ) { - E(L('_NOT_SUPPERT_').':Mongo'); - } - if(!empty($config)) { - $this->config = array_merge($this->config,$config); - if(empty($this->config['params'])){ - $this->config['params'] = []; - } - } - } - - /** - * 连接数据库方法 - * @access public - */ - public function connect($config='',$linkNum=0) { - if ( !isset($this->linkID[$linkNum]) ) { - if(empty($config)) $config = $this->config['connection']; - $host = 'mongodb://'.($config['username']?"{$config['username']}":'').($config['password']?":{$config['password']}@":'').$config['hostname'].($config['hostport']?":{$config['hostport']}":'').'/'.($config['database']?"{$config['database']}":''); - try{ - $this->linkID[$linkNum] = new \mongoClient( $host,$this->config['params']); - }catch (\MongoConnectionException $e){ - E($e->getmessage()); - } - } - return $this->linkID[$linkNum]; - } - - /** - * 切换当前操作的Db和Collection - * @access public - * @param string $collection collection - * @param string $db db - * @param boolean $master 是否主服务器 - * @return void - */ - public function switchCollection($collection,$db='',$master=true){ - // 当前没有连接 则首先进行数据库连接 - if ( !$this->_linkID ) $this->initConnect($master); - try{ - if(!empty($db)) { // 传人Db则切换数据库 - // 当前MongoDb对象 - $this->_dbName = $db; - $this->_mongo = $this->_linkID->selectDb($db); - } - // 当前MongoCollection对象 - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.getCollection('.$collection.')'; - } - if($this->_collectionName != $collection) { - $this->queryTimes++; - $this->debug(true); - $this->_collection = $this->_mongo->selectCollection($collection); - $this->debug(false); - $this->_collectionName = $collection; // 记录当前Collection名称 - } - }catch (MongoException $e){ - E($e->getMessage()); - } - } - - /** - * 释放查询结果 - * @access public - */ - public function free() { - $this->_cursor = null; - } - - /** - * 执行命令 - * @access public - * @param array $command 指令 - * @return array - */ - public function command($command=[]) { - $this->executeTimes++; - $this->debug(true); - $this->queryStr = 'command:'.json_encode($command); - $result = $this->_mongo->command($command); - $this->debug(false); - if(!$result['ok']) { - E($result['errmsg']); - } - return $result; - } - - /** - * 执行语句 - * @access public - * @param string $code sql指令 - * @param array $args 参数 - * @return mixed - */ - public function execute($code,$args=[]) { - $this->executeTimes++; - $this->debug(true); - $this->queryStr = 'execute:'.$code; - $result = $this->_mongo->execute($code,$args); - $this->debug(false); - if($result['ok']) { - return $result['retval']; - }else{ - E($result['errmsg']); - } - } - - /** - * 关闭数据库 - * @access public - */ - public function close() { - if($this->_linkID) { - $this->_linkID->close(); - $this->_linkID = null; - $this->_mongo = null; - $this->_collection = null; - $this->_cursor = null; - } - } - - /** - * 数据库错误信息 - * @access public - * @return string - */ - public function error() { - $this->error = $this->_mongo->lastError(); - Log::record($this->error,'ERR'); - return $this->error; - } - - /** - * 插入记录 - * @access public - * @param mixed $data 数据 - * @param array $options 参数表达式 - * @param boolean $replace 是否replace - * @return false | integer - */ - public function insert($data,$options=[],$replace=false) { - if(isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.insert('; - $this->queryStr .= $data?json_encode($data):'{}'; - $this->queryStr .= ')'; - } - try{ - $this->debug(true); - $result = $replace? $this->_collection->save($data): $this->_collection->insert($data); - $this->debug(false); - if($result) { - $_id = $data['_id']; - if(is_object($_id)) { - $_id = $_id->__toString(); - } - $this->lastInsID = $_id; - } - return $result; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 插入多条记录 - * @access public - * @param array $dataList 数据 - * @param array $options 参数表达式 - * @return bool - */ - public function insertAll($dataList,$options=[]) { - if(isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - try{ - $this->debug(true); - $result = $this->_collection->batchInsert($dataList); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 生成下一条记录ID 用于自增非MongoId主键 - * @access public - * @param string $pk 主键名 - * @return integer - */ - public function getMongoNextId($pk) { - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.find({},{'.$pk.':1}).sort({'.$pk.':-1}).limit(1)'; - } - try{ - $this->debug(true); - $result = $this->_collection->find([],[$pk=>1])->sort([$pk=>-1])->limit(1); - $this->debug(false); - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - $data = $result->getNext(); - return isset($data[$pk])?$data[$pk]+1:1; - } - - /** - * 更新记录 - * @access public - * @param mixed $data 数据 - * @param array $options 表达式 - * @return bool - */ - public function update($data,$options) { - if(isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->executeTimes++; - $this->model = $options['model']; - $query = $this->parseWhere($options['where']); - $set = $this->parseSet($data); - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.update('; - $this->queryStr .= $query?json_encode($query):'{}'; - $this->queryStr .= ','.json_encode($set).')'; - } - try{ - $this->debug(true); - if(isset($options['limit']) && $options['limit'] == 1) { - $multiple = ["multiple" => false]; - }else{ - $multiple = ["multiple" => true]; - } - $result = $this->_collection->update($query,$set,$multiple); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options=[]) { - if(isset($options['table'])) { - $this->switchCollection($options['table']); - } - $query = $this->parseWhere($options['where']); - $this->model = $options['model']; - $this->executeTimes++; - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.remove('.json_encode($query).')'; - } - try{ - $this->debug(true); - $result = $this->_collection->remove($query); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 清空记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function clear($options=[]){ - if(isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.remove({})'; - } - try{ - $this->debug(true); - $result = $this->_collection->drop(); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 查找记录 - * @access public - * @param array $options 表达式 - * @return iterator - */ - public function select($options=[]) { - if(isset($options['table'])) { - $this->switchCollection($options['table'],'',false); - } - $cache = isset($options['cache'])?$options['cache']:false; - if($cache) { // 查询缓存检测 - $key = is_string($cache['key'])?$cache['key']:md5(serialize($options)); - $value = S($key,'','',$cache['type']); - if(false !== $value) { - return $value; - } - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere($options['where']); - $field = $this->parseField($options['field']); - try{ - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.find('; - $this->queryStr .= $query? json_encode($query):'{}'; - $this->queryStr .= $field? ','.json_encode($field):''; - $this->queryStr .= ')'; - } - $this->debug(true); - $_cursor = $this->_collection->find($query,$field); - if($options['order']) { - $order = $this->parseOrder($options['order']); - if($this->config['debug']) { - $this->queryStr .= '.sort('.json_encode($order).')'; - } - $_cursor = $_cursor->sort($order); - } - if(isset($options['page'])) { // 根据页数计算limit - if(strpos($options['page'],',')) { - list($page,$length) = explode(',',$options['page']); - }else{ - $page = $options['page']; - } - $page = $page?$page:1; - $length = isset($length)?$length:(is_numeric($options['limit'])?$options['limit']:20); - $offset = $length*((int)$page-1); - $options['limit'] = $offset.','.$length; - } - if(isset($options['limit'])) { - list($offset,$length) = $this->parseLimit($options['limit']); - if(!empty($offset)) { - if($this->config['debug']) { - $this->queryStr .= '.skip('.intval($offset).')'; - } - $_cursor = $_cursor->skip(intval($offset)); - } - if($this->config['debug']) { - $this->queryStr .= '.limit('.intval($length).')'; - } - $_cursor = $_cursor->limit(intval($length)); - } - $this->debug(false); - $this->_cursor = $_cursor; - $resultSet = iterator_to_array($_cursor); - if($cache && $resultSet ) { // 查询缓存写入 - S($key,$resultSet,$cache['expire'],$cache['type']); - } - return $resultSet; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 查找某个记录 - * @access public - * @param array $options 表达式 - * @return array - */ - public function find($options=[]){ - if(isset($options['table'])) { - $this->switchCollection($options['table'],'',false); - } - $cache = isset($options['cache'])?$options['cache']:false; - if($cache) { // 查询缓存检测 - $key = is_string($cache['key'])?$cache['key']:md5(serialize($options)); - $value = S($key,'','',$cache['type']); - if(false !== $value) { - return $value; - } - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere($options['where']); - $fields = $this->parseField($options['field']); - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.findOne('; - $this->queryStr .= $query?json_encode($query):'{}'; - $this->queryStr .= $fields?','.json_encode($fields):''; - $this->queryStr .= ')'; - } - try{ - $this->debug(true); - $result = $this->_collection->findOne($query,$fields); - $this->debug(false); - if($cache && $result ) { // 查询缓存写入 - S($key,$result,$cache['expire'],$cache['type']); - } - return $result; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - /** - * 统计记录数 - * @access public - * @param array $options 表达式 - * @return iterator - */ - public function count($options=[]){ - if(isset($options['table'])) { - $this->switchCollection($options['table'],'',false); - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere($options['where']); - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName; - $this->queryStr .= $query?'.find('.json_encode($query).')':''; - $this->queryStr .= '.count()'; - } - try{ - $this->debug(true); - $count = $this->_collection->count($query); - $this->debug(false); - return $count; - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - } - - public function group($keys,$initial,$reduce,$options=[]){ - $this->_collection->group($keys,$initial,$reduce,$options); - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($collection=''){ - if(!empty($collection) && $collection != $this->_collectionName) { - $this->switchCollection($collection,'',false); - } - $this->queryTimes++; - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.'.$this->_collectionName.'.findOne()'; - } - try{ - $this->debug(true); - $result = $this->_collection->findOne(); - $this->debug(false); - } catch (\MongoCursorException $e) { - E($e->getMessage()); - } - if($result) { // 存在数据则分析字段 - $info = []; - foreach ($result as $key=>$val){ - $info[$key] = [ - 'name' => $key, - 'type' => getType($val), - ]; - } - return $info; - } - // 暂时没有数据 返回false - return false; - } - - /** - * 取得当前数据库的collection信息 - * @access public - */ - public function getTables(){ - if($this->config['debug']) { - $this->queryStr = $this->_dbName.'.getCollenctionNames()'; - } - $this->queryTimes++; - $this->debug(true); - $list = $this->_mongo->listCollections(); - $this->debug(false); - $info = []; - foreach ($list as $collection){ - $info[] = $collection->getName(); - } - return $info; - } - - /** - * set分析 - * @access protected - * @param array $data - * @return string - */ - protected function parseSet($data) { - $result = []; - foreach ($data as $key=>$val){ - if(is_array($val)) { - switch($val[0]) { - case 'inc': - $result['$inc'][$key] = (int)$val[1]; - break; - case 'set': - case 'unset': - case 'push': - case 'pushall': - case 'addtoset': - case 'pop': - case 'pull': - case 'pullall': - $result['$'.$val[0]][$key] = $val[1]; - break; - default: - $result['$set'][$key] = $val; - } - }else{ - $result['$set'][$key] = $val; - } - } - return $result; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return array - */ - protected function parseOrder($order) { - if(is_string($order)) { - $array = explode(',',$order); - $order = []; - foreach ($array as $key=>$val){ - $arr = explode(' ',trim($val)); - if(isset($arr[1])) { - $arr[1] = $arr[1]=='asc'?1:-1; - }else{ - $arr[1] = 1; - } - $order[$arr[0]] = $arr[1]; - } - } - return $order; - } - - /** - * limit分析 - * @access protected - * @param mixed $limit - * @return array - */ - protected function parseLimit($limit) { - if(strpos($limit,',')) { - $array = explode(',',$limit); - }else{ - $array = [0,$limit]; - } - return $array; - } - - /** - * field分析 - * @access protected - * @param mixed $fields - * @return array - */ - public function parseField($fields){ - if(empty($fields)) { - $fields = []; - } - if(is_string($fields)) { - $fields = explode(',',$fields); - } - return $fields; - } - - /** - * where分析 - * @access protected - * @param mixed $where - * @return array - */ - public function parseWhere($where){ - $query = []; - foreach ($where as $key=>$val){ - if('_id' != $key && 0===strpos($key,'_')) { - // 解析特殊条件表达式 - $query = $this->parseThinkWhere($key,$val); - }else{ - // 查询字段的安全过滤 - if(!preg_match('/^[A-Z_\|\&\-.a-z0-9]+$/',trim($key))){ - E(L('_ERROR_QUERY_').':'.$key); - } - $key = trim($key); - if(strpos($key,'|')) { - $array = explode('|',$key); - $str = []; - foreach ($array as $k){ - $str[] = $this->parseWhereItem($k,$val); - } - $query['$or'] = $str; - }elseif(strpos($key,'&')){ - $array = explode('&',$key); - $str = []; - foreach ($array as $k){ - $str[] = $this->parseWhereItem($k,$val); - } - $query = array_merge($query,$str); - }else{ - $str = $this->parseWhereItem($key,$val); - $query = array_merge($query,$str); - } - } - } - return $query; - } - - /** - * 特殊条件分析 - * @access protected - * @param string $key - * @param mixed $val - * @return string - */ - protected function parseThinkWhere($key,$val) { - $query = []; - switch($key) { - case '_query': // 字符串模式查询条件 - parse_str($val,$query); - if(isset($query['_logic']) && strtolower($query['_logic']) == 'or' ) { - unset($query['_logic']); - $query['$or'] = $query; - } - break; - case '_string':// MongoCode查询 - $query['$where'] = new \MongoCode($val); - break; - } - return $query; - } - - /** - * where子单元分析 - * @access protected - * @param string $key - * @param mixed $val - * @return array - */ - protected function parseWhereItem($key,$val) { - $query = []; - if(is_array($val)) { - if(is_string($val[0])) { - $con = strtolower($val[0]); - if(in_array($con,['neq','ne','gt','egt','gte','lt','lte','elt'])) { // 比较运算 - $k = '$'.$this->comparison[$con]; - $query[$key] = [$k=>$val[1]]; - }elseif('like'== $con){ // 模糊查询 采用正则方式 - $query[$key] = new \MongoRegex("/".$val[1]."/"); - }elseif('mod'==$con){ // mod 查询 - $query[$key] = ['$mod'=>$val[1]]; - }elseif('regex'==$con){ // 正则查询 - $query[$key] = new \MongoRegex($val[1]); - }elseif(in_array($con,['in','nin','not in'])){ // IN NIN 运算 - $data = is_string($val[1])? explode(',',$val[1]):$val[1]; - $k = '$'.$this->comparison[$con]; - $query[$key] = [$k=>$data]; - }elseif('all'==$con){ // 满足所有指定条件 - $data = is_string($val[1])? explode(',',$val[1]):$val[1]; - $query[$key] = ['$all'=>$data]; - }elseif('between'==$con){ // BETWEEN运算 - $data = is_string($val[1])? explode(',',$val[1]):$val[1]; - $query[$key] = ['$gte'=>$data[0],'$lte'=>$data[1]]; - }elseif('not between'==$con){ - $data = is_string($val[1])? explode(',',$val[1]):$val[1]; - $query[$key] = ['$lt'=>$data[0],'$gt'=>$data[1]]; - }elseif('exp'==$con){ // 表达式查询 - $query['$where'] = new \MongoCode($val[1]); - }elseif('exists'==$con){ // 字段是否存在 - $query[$key] =['$exists'=>(bool)$val[1]]; - }elseif('size'==$con){ // 限制属性大小 - $query[$key] =['$size'=>intval($val[1])]; - }elseif('type'==$con){ // 限制字段类型 1 浮点型 2 字符型 3 对象或者MongoDBRef 5 MongoBinData 7 MongoId 8 布尔型 9 MongoDate 10 NULL 15 MongoCode 16 32位整型 17 MongoTimestamp 18 MongoInt64 如果是数组的话判断元素的类型 - $query[$key] =['$type'=>intval($val[1])]; - }else{ - $query[$key] = $val; - } - return $query; - } - } - $query[$key] = $val; - return $query; - } -} diff --git a/Library/Think/Db/Driver/Mysql.php b/Library/Think/Db/Driver/Mysql.php deleted file mode 100644 index 8f1b70bb..00000000 --- a/Library/Think/Db/Driver/Mysql.php +++ /dev/null @@ -1,92 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * mysql数据库驱动 - */ -class Mysql extends Driver{ - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config){ - $dsn = 'mysql:dbname='.$config['database'].';host='.$config['hostname']; - if(!empty($config['hostport'])) { - $dsn .= ';port='.$config['hostport']; - }elseif(!empty($config['socket'])){ - $dsn .= ';unix_socket='.$config['socket']; - } - if(!empty($config['charset'])){ - $dsn .= ';charset='.$config['charset']; - } - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - */ - public function getFields($tableName) { - $this->initConnect(true); - list($tableName) = explode(' ', $tableName); - $sql = 'SHOW COLUMNS FROM `'.$tableName.'`'; - $result = $this->query($sql); - $info = []; - if($result) { - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['key']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - */ - public function getTables($dbName='') { - $sql = !empty($dbName)?'SHOW TABLES FROM '.$dbName:'SHOW TABLES '; - $result = $this->query($sql); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * 字段和表名处理 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey(&$key) { - $key = trim($key); - if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) { - $key = '`'.$key.'`'; - } - return $key; - } - -} diff --git a/Library/Think/Db/Driver/Oracle.php b/Library/Think/Db/Driver/Oracle.php deleted file mode 100644 index ae77e14f..00000000 --- a/Library/Think/Db/Driver/Oracle.php +++ /dev/null @@ -1,153 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Oracle数据库驱动 - */ -class Oracle extends Driver{ - - private $table = ''; - protected $selectSql = 'SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%'; - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config){ - $dsn = 'oci:dbname='.$config['database']; - if(!empty($config['charset'])) { - $dsn .= ';charset='.$config['charset']; - } - return $dsn; - } - - /** - * 执行语句 - * @access public - * @param string $str sql指令 - * @return integer - */ - public function execute($str,$bind=[]) { - $this->initConnect(true); - if ( !$this->_linkID ) return false; - $this->queryStr = $str; - if(!empty($bind)){ - $this->queryStr .= '[ '.print_r($bind,true).' ]'; - } - $flag = false; - if(preg_match("/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i", $str, $match)) { - $this->table = C("DB_SEQUENCE_PREFIX").str_ireplace(C("DB_PREFIX"), "", $match[2]); - $flag = (boolean)$this->query("SELECT * FROM user_sequences WHERE sequence_name='" . strtoupper($this->table) . "'"); - } - //释放前次的查询结果 - if ( !empty($this->PDOStatement) ) $this->free(); - $this->executeTimes++; - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if(false === $this->PDOStatement) { - E($this->error()); - } - $result = $this->PDOStatement->execute($bind); - $this->debug(false); - if ( false === $result) { - $this->error(); - return false; - } else { - $this->numRows = $this->PDOStatement->rowCount(); - if($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { - $this->lastInsID = $this->_linkID->lastInsertId(); - } - return $this->numRows; - } - } - - /** - * 取得数据表的字段信息 - * @access public - */ - public function getFields($tableName) { - list($tableName) = explode(' ', $tableName); - $result = $this->query("select a.column_name,data_type,decode(nullable,'Y',0,1) notnull,data_default,decode(a.column_name,b.column_name,1,0) pk " - ."from user_tab_columns a,(select column_name from user_constraints c,user_cons_columns col " - ."where c.constraint_name=col.constraint_name and c.constraint_type='P'and c.table_name='".strtoupper($tableName) - ."') b where table_name='".strtoupper($tableName)."' and a.column_name=b.column_name(+)"); - $info = []; - if($result) { - foreach ($result as $key => $val) { - $info[strtolower($val['column_name'])] = [ - 'name' => strtolower($val['column_name']), - 'type' => strtolower($val['data_type']), - 'notnull' => $val['notnull'], - 'default' => $val['data_default'], - 'primary' => $val['pk'], - 'autoinc' => $val['pk'], - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息(暂时实现取得用户表信息) - * @access public - */ - public function getTables($dbName='') { - $result = $this->query("select table_name from user_tables"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL指令 - * @return string - */ - public function escapeString($str) { - return str_ireplace("'", "''", $str); - } - - /** - * limit - * @access public - * @return string - */ - public function parseLimit($limit) { - $limitStr = ''; - if(!empty($limit)) { - $limit = explode(',',$limit); - if(count($limit)>1) - $limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0]+$limit[1]) . ")"; - else - $limitStr = "(numrow>0 AND numrow<=".$limit[0].")"; - } - return $limitStr?' WHERE '.$limitStr:''; - } - - /** - * 设置锁机制 - * @access protected - * @return string - */ - protected function parseLock($lock=false) { - if(!$lock) return ''; - return ' FOR UPDATE NOWAIT '; - } -} diff --git a/Library/Think/Db/Driver/Pgsql.php b/Library/Think/Db/Driver/Pgsql.php deleted file mode 100644 index dc478103..00000000 --- a/Library/Think/Db/Driver/Pgsql.php +++ /dev/null @@ -1,91 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Pgsql数据库驱动 - */ -class Pgsql extends Driver{ - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config){ - $dsn = 'pgsql:dbname='.$config['database'].';host='.$config['hostname']; - if(!empty($config['hostport'])) { - $dsn .= ';port='.$config['hostport']; - } - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) { - list($tableName) = explode(' ', $tableName); - $result = $this->query('select fields_name as "field",fields_type as "type",fields_not_null as "null",fields_key_name as "key",fields_default as "default",fields_default as "extra" from table_msg('.$tableName.');'); - $info = []; - if($result){ - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['key']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @return array - */ - public function getTables($dbName='') { - $result = $this->query("select tablename as Tables_in_test from pg_tables where schemaname ='public'"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * limit分析 - * @access protected - * @param mixed $lmit - * @return string - */ - public function parseLimit($limit) { - $limitStr = ''; - if(!empty($limit)) { - $limit = explode(',',$limit); - if(count($limit)>1) { - $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; - }else{ - $limitStr .= ' LIMIT '.$limit[0].' '; - } - } - return $limitStr; - } - -} diff --git a/Library/Think/Db/Driver/Sqlite.php b/Library/Think/Db/Driver/Sqlite.php deleted file mode 100644 index 02c0f14a..00000000 --- a/Library/Think/Db/Driver/Sqlite.php +++ /dev/null @@ -1,98 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Sqlite数据库驱动 - */ -class Sqlite extends Driver { - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config){ - $dsn = 'sqlite:'.$config['database']; - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) { - list($tableName) = explode(' ', $tableName); - $result = $this->query('PRAGMA table_info( '.$tableName.' )'); - $info = []; - if($result){ - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['dey']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @return array - */ - public function getTables($dbName='') { - $result = $this->query("SELECT name FROM sqlite_master WHERE type='table' " - . "UNION ALL SELECT name FROM sqlite_temp_master " - . "WHERE type='table' ORDER BY name"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL指令 - * @return string - */ - public function escapeString($str) { - return str_ireplace("'", "''", $str); - } - - /** - * limit - * @access public - * @return string - */ - public function parseLimit($limit) { - $limitStr = ''; - if(!empty($limit)) { - $limit = explode(',',$limit); - if(count($limit)>1) { - $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; - }else{ - $limitStr .= ' LIMIT '.$limit[0].' '; - } - } - return $limitStr; - } -} diff --git a/Library/Think/Db/Driver/Sqlsrv.php b/Library/Think/Db/Driver/Sqlsrv.php deleted file mode 100644 index 04e71ad3..00000000 --- a/Library/Think/Db/Driver/Sqlsrv.php +++ /dev/null @@ -1,164 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; -use PDO; - -/** - * Sqlsrv数据库驱动 - */ -class Sqlsrv extends Driver{ - protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%'; - // PDO连接参数 - protected $options = [ - PDO::ATTR_CASE => PDO::CASE_LOWER, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_STRINGIFY_FETCHES => false, - PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, - ]; - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config){ - $dsn = 'sqlsrv:dbname='.$config['database'].';Server='.$config['hostname']; - if(!empty($config['hostport'])) { - $dsn .= ','.$config['hostport']; - } - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) { - list($tableName) = explode(' ', $tableName); - $result = $this->query("SELECT column_name, data_type, column_default, is_nullable - FROM information_schema.tables AS t - JOIN information_schema.columns AS c - ON t.table_catalog = c.table_catalog - AND t.table_schema = c.table_schema - AND t.table_name = c.table_name - WHERE t.table_name = '$tableName'"); - $info = []; - if($result) { - foreach ($result as $key => $val) { - $info[$val['column_name']] = [ - 'name' => $val['column_name'], - 'type' => $val['data_type'], - 'notnull' => (bool) ($val['is_nullable'] === ''), // not null is empty, null is yes - 'default' => $val['column_default'], - 'primary' => false, - 'autoinc' => false, - ]; - } - } - return $info; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getTables($dbName='') { - $result = $this->query("SELECT TABLE_NAME - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_TYPE = 'BASE TABLE' - "); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return string - */ - protected function parseOrder($order) { - return !empty($order)? ' ORDER BY '.$order:' ORDER BY rand()'; - } - - /** - * 字段名分析 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey(&$key) { - $key = trim($key); - if(!preg_match('/[,\'\"\*\(\)\[.\s]/',$key)) { - $key = '['.$key.']'; - } - return $key; - } - - /** - * limit - * @access public - * @param mixed $limit - * @return string - */ - public function parseLimit($limit) { - if(empty($limit)) return ''; - $limit = explode(',',$limit); - if(count($limit)>1) - $limitStr = '(T1.ROW_NUMBER BETWEEN '.$limit[0].' + 1 AND '.$limit[0].' + '.$limit[1].')'; - else - $limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND '.$limit[0].")"; - return 'WHERE '.$limitStr; - } - - /** - * 更新记录 - * @access public - * @param mixed $data 数据 - * @param array $options 表达式 - * @return false | integer - */ - public function update($data,$options) { - $this->model = $options['model']; - $sql = 'UPDATE ' - .$this->parseTable($options['table']) - .$this->parseSet($data) - .$this->parseWhere(!empty($options['where'])?$options['where']:'') - .$this->parseLock(isset($options['lock'])?$options['lock']:false) - .$this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options=[]) { - $this->model = $options['model']; - $sql = 'DELETE FROM ' - .$this->parseTable($options['table']) - .$this->parseWhere(!empty($options['where'])?$options['where']:'') - .$this->parseLock(isset($options['lock'])?$options['lock']:false) - .$this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); - } - -} \ No newline at end of file diff --git a/Library/Think/Db/Lite.php b/Library/Think/Db/Lite.php deleted file mode 100644 index d4f38e6f..00000000 --- a/Library/Think/Db/Lite.php +++ /dev/null @@ -1,449 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db; -use Think\Config; -use Think\Debug; -use Think\Log; -use PDO; - -class Lite { - // PDO操作实例 - protected $PDOStatement = null; - // 当前操作所属的模型名 - protected $model = '_think_'; - // 当前SQL指令 - protected $queryStr = ''; - protected $modelSql = []; - // 最后插入ID - protected $lastInsID = null; - // 返回或者影响记录数 - protected $numRows = 0; - // 事务指令数 - protected $transTimes = 0; - // 错误信息 - protected $error = ''; - // 数据库连接ID 支持多个连接 - protected $linkID = []; - // 当前连接ID - protected $_linkID = null; - // 数据库连接参数配置 - protected $config = [ - 'type' => '', // 数据库类型 - 'hostname' => '127.0.0.1', // 服务器地址 - 'database' => '', // 数据库名 - 'username' => '', // 用户名 - 'password' => '', // 密码 - 'hostport' => '', // 端口 - 'dsn' => '', // - 'params' => [], // 数据库连接参数 - 'charset' => 'utf8', // 数据库编码默认采用utf8 - 'prefix' => '', // 数据库表前缀 - 'debug' => false, // 数据库调试模式 - 'deploy' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'rw_separate' => false, // 数据库读写是否分离 主从式有效 - 'master_num' => 1, // 读写分离后 主服务器数量 - 'slave_no' => '', // 指定从服务器序号 - ]; - // 数据库表达式 - protected $comparison = ['eq'=>'=','neq'=>'<>','gt'=>'>','egt'=>'>=','lt'=>'<','elt'=>'<=','notlike'=>'NOT LIKE','like'=>'LIKE','in'=>'IN','notin'=>'NOT IN']; - // 查询表达式 - protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%'; - // 查询次数 - protected $queryTimes = 0; - // 执行次数 - protected $executeTimes = 0; - // PDO连接参数 - protected $options = [ - PDO::ATTR_CASE => PDO::CASE_LOWER, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, - PDO::ATTR_STRINGIFY_FETCHES => false, - ]; - - /** - * 架构函数 读取数据库配置信息 - * @access public - * @param array $config 数据库配置数组 - */ - public function __construct($config=''){ - if(!empty($config)) { - $this->config = array_merge($this->config,$config); - $this->config['params'] = $this->options+$this->config['params']; - } - } - - /** - * 连接数据库方法 - * @access public - */ - public function connect($config='',$linkNum=0) { - if ( !isset($this->linkID[$linkNum]) ) { - if(empty($config)) $config = $this->config; - try{ - if(empty($config['dsn'])) { - E('Think/Db/Lite 必须设置 dsn参数'); - } - $this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$config['params']); - }catch (\PDOException $e) { - E($e->getMessage()); - } - } - return $this->linkID[$linkNum]; - } - - /** - * 释放查询结果 - * @access public - */ - public function free() { - $this->PDOStatement = null; - } - - /** - * 执行查询 返回数据集 - * @access public - * @param string $str sql指令 - * @param array $bind 参数绑定 - * @return mixed - */ - public function query($str,$bind=[]) { - $this->initConnect(false); - if ( !$this->_linkID ) return false; - $this->queryStr = $str; - if(!empty($bind)){ - $this->queryStr .= '[ '.print_r($bind,true).' ]'; - } - //释放前次的查询结果 - if ( !empty($this->PDOStatement) ) $this->free(); - $this->queryTimes++; - // 调试开始 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if(false === $this->PDOStatement) - E($this->error()); - foreach ($bind as $key => $val) { - if(is_array($val)){ - $this->PDOStatement->bindValue($key, $val[0], $val[1]); - }else{ - $this->PDOStatement->bindValue($key, $val); - } - } - $result = $this->PDOStatement->execute(); - // 调试结束 - $this->debug(false); - if ( false === $result ) { - $this->error(); - return false; - } else { - return $this->getResult(); - } - } - - /** - * 执行语句 - * @access public - * @param string $str sql指令 - * @param array $bind 参数绑定 - * @return integer - */ - public function execute($str,$bind=[]) { - $this->initConnect(true); - if ( !$this->_linkID ) return false; - $this->queryStr = $str; - if(!empty($bind)){ - $this->queryStr .= '[ '.print_r($bind,true).' ]'; - } - //释放前次的查询结果 - if ( !empty($this->PDOStatement) ) $this->free(); - $this->executeTimes++; - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if(false === $this->PDOStatement) { - E($this->error()); - } - foreach ($bind as $key => $val) { - if(is_array($val)){ - $this->PDOStatement->bindValue($key, $val[0], $val[1]); - }else{ - $this->PDOStatement->bindValue($key, $val); - } - } - $result = $this->PDOStatement->execute(); - $this->debug(false); - if ( false === $result) { - $this->error(); - return false; - } else { - $this->numRows = $this->PDOStatement->rowCount(); - if(preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { - $this->lastInsID = $this->_linkID->lastInsertId(); - } - return $this->numRows; - } - } - - /** - * 启动事务 - * @access public - * @return void - */ - public function startTrans() { - $this->initConnect(true); - if ( !$this->_linkID ) return false; - //数据rollback 支持 - if ($this->transTimes == 0) { - $this->_linkID->beginTransaction(); - } - $this->transTimes++; - return ; - } - - /** - * 用于非自动提交状态下面的查询提交 - * @access public - * @return boolen - */ - public function commit() { - if ($this->transTimes > 0) { - $result = $this->_linkID->commit(); - $this->transTimes = 0; - if(!$result){ - $this->error(); - return false; - } - } - return true; - } - - /** - * 事务回滚 - * @access public - * @return boolen - */ - public function rollback() { - if ($this->transTimes > 0) { - $result = $this->_linkID->rollback(); - $this->transTimes = 0; - if(!$result){ - $this->error(); - return false; - } - } - return true; - } - - /** - * 获得所有的查询数据 - * @access private - * @return array - */ - private function getResult() { - //返回数据集 - $result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC); - $this->numRows = count( $result ); - return $result; - } - - /** - * 获得查询次数 - * @access public - * @param boolean $execute 是否包含所有查询 - * @return integer - */ - public function getQueryTimes($execute=false){ - return $execute?$this->queryTimes+$this->executeTimes:$this->queryTimes; - } - - /** - * 获得执行次数 - * @access public - * @return integer - */ - public function getExecuteTimes(){ - return $this->executeTimes; - } - - /** - * 关闭数据库 - * @access public - */ - public function close() { - $this->_linkID = null; - } - - /** - * 数据库错误信息 - * 并显示当前的SQL语句 - * @access public - * @return string - */ - public function error() { - if($this->PDOStatement) { - $error = $this->PDOStatement->errorInfo(); - $this->error = $error[1].':'.$error[2]; - }else{ - $this->error = ''; - } - if('' != $this->queryStr){ - $this->error .= "\n [ SQL语句 ] : ".$this->queryStr; - } - // 记录错误日志 - Log::record($this->error,'ERR'); - if($this->config['debug']) {// 开启数据库调试模式 - E($this->error); - }else{ - return $this->error; - } - } - - /** - * 获取最近一次查询的sql语句 - * @param string $model 模型名 - * @access public - * @return string - */ - public function getLastSql($model='') { - return $model?$this->modelSql[$model]:$this->queryStr; - } - - /** - * 获取最近插入的ID - * @access public - * @return string - */ - public function getLastInsID() { - return $this->lastInsID; - } - - /** - * 获取最近的错误信息 - * @access public - * @return string - */ - public function getError() { - return $this->error; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL字符串 - * @return string - */ - public function escapeString($str) { - return addslashes($str); - } - - /** - * 设置当前操作模型 - * @access public - * @param string $model 模型名 - * @return void - */ - public function setModel($model){ - $this->model = $model; - } - - /** - * 数据库调试 记录当前SQL - * @access protected - * @param boolean $start 调试开始标记 true 开始 false 结束 - */ - protected function debug($start) { - if($this->config['debug']) {// 开启数据库调试模式 - if($start) { - Debug::remark('queryStartTime','time'); - }else{ - $this->modelSql[$this->model] = $this->queryStr; - //$this->model = '_think_'; - // 记录操作结束时间 - Debug::remark('queryEndTime','time'); - Log::record($this->queryStr.' [ RunTime:'.Debug::getUseTime('queryStartTime','queryEndTime').'s ]','SQL'); - } - } - } - - /** - * 初始化数据库连接 - * @access protected - * @param boolean $master 主服务器 - * @return void - */ - protected function initConnect($master=true) { - if(!empty($this->config['deploy'])) - // 采用分布式数据库 - $this->_linkID = $this->multiConnect($master); - else - // 默认单数据库 - if ( !$this->_linkID ) $this->_linkID = $this->connect(); - } - - /** - * 连接分布式服务器 - * @access protected - * @param boolean $master 主服务器 - * @return void - */ - protected function multiConnect($master=false) { - static $_config = []; - if(empty($_config)) { - // 缓存分布式数据库配置解析 - $_config['username'] = explode(',',$$this->config['username']); - $_config['password'] = explode(',',$$this->config['password']); - $_config['hostname'] = explode(',',$$this->config['hostname']); - $_config['hostport'] = explode(',',$$this->config['hostport']); - $_config['database'] = explode(',',$$this->config['database']); - $_config['dsn'] = explode(',',$$this->config['dsn']); - } - // 数据库读写是否分离 - if($this->config['rw_separate']){ - // 主从式采用读写分离 - if($master) - // 主服务器写入 - $r = floor(mt_rand(0,$this->config['master_num']-1)); - else{ - if(is_numeric($this->config['slave_no'])) {// 指定服务器读 - $r = $this->config['slave_no']; - }else{ - // 读操作连接从服务器 - $r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库 - } - } - }else{ - // 读写操作不区分服务器 - $r = floor(mt_rand(0,count($_config['hostname'])-1)); // 每次随机连接的数据库 - } - $db_config = [ - 'username' => isset($_config['username'][$r])?$_config['username'][$r]:$_config['username'][0], - 'password' => isset($_config['password'][$r])?$_config['password'][$r]:$_config['password'][0], - 'hostname' => isset($_config['hostname'][$r])?$_config['hostname'][$r]:$_config['hostname'][0], - 'hostport' => isset($_config['hostport'][$r])?$_config['hostport'][$r]:$_config['hostport'][0], - 'database' => isset($_config['database'][$r])?$_config['database'][$r]:$_config['database'][0], - 'dsn' => isset($_config['dsn'][$r])?$_config['dsn'][$r]:$_config['dsn'][0], - ]; - return $this->connect($db_config,$r); - } - - /** - * 析构方法 - * @access public - */ - public function __destruct() { - // 释放查询 - if ($this->PDOStatement){ - $this->free(); - } - // 关闭连接 - $this->close(); - } -} \ No newline at end of file diff --git a/Library/Think/Debug.php b/Library/Think/Debug.php deleted file mode 100644 index 44555d3c..00000000 --- a/Library/Think/Debug.php +++ /dev/null @@ -1,114 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Debug { - - static protected $_info = []; - static protected $_mem = []; - - /** - * 记录时间(微秒)和内存使用情况 - * @param string $name 标记位置 - * @param mixed $value 标记值 留空则取当前 time 表示仅记录时间 否则同时记录时间和内存 - * @return mixed - */ - static public function remark($name,$value='') { - // 记录时间和内存使用 - self::$_info[$name] = is_float($value) ? $value : microtime(true); - if('time' != $value ) { - self::$_mem['mem'][$name] = is_float($value) ? $value : memory_get_usage(); - self::$_mem['peak'][$name] = function_exists('memory_get_peak_usage') ? memory_get_peak_usage() : self::$_mem['mem'][$name]; - } - } - - /** - * 统计某个区间的时间(微秒)使用情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer|string $dec 小数位 - * @return mixed - */ - static public function getUseTime($start,$end,$dec=6) { - if(!isset(self::$_info[$end])) - self::$_info[$end] = microtime(true); - return number_format((self::$_info[$end]-self::$_info[$start]),$dec); - } - - /** - * 记录内存使用情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer|string $dec 小数位 - * @return mixed - */ - static public function getUseMem($start,$end,$dec=2) { - if(!isset(self::$_mem['mem'][$end])) - self::$_mem['mem'][$end] = memory_get_usage(); - $size = self::$_mem['mem'][$end]-self::$_mem['mem'][$start]; - $a = ['B', 'KB', 'MB', 'GB', 'TB']; - $pos = 0; - while ($size >= 1024) { - $size /= 1024; - $pos++; - } - return round($size,$dec)." ".$a[$pos]; - } - - /** - * 统计内存峰值情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer|string $dec 小数位 - * @return mixed - */ - static public function getMemPeak($start,$end,$dec=2) { - if(!isset(self::$_mem['peak'][$end])) - self::$_mem['peak'][$end] = function_exists('memory_get_peak_usage') ? memory_get_peak_usage() : memory_get_usage(); - $size = self::$_mem['peak'][$end]-self::$_mem['peak'][$start]; - $a = ['B', 'KB', 'MB', 'GB', 'TB']; - $pos = 0; - while ($size >= 1024) { - $size /= 1024; - $pos++; - } - return round($size,$dec)." ".$a[$pos]; - } - - /** - * 浏览器友好的变量输出 - * @param mixed $var 变量 - * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串 - * @param string $label 标签 默认为空 - * @return void|string - */ - static public function dump($var, $echo=true, $label=null) { - $label = ($label === null) ? '' : rtrim($label) . ':'; - ob_start(); - var_dump($var); - $output = ob_get_clean(); - $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output); - if(IS_CLI) { - $output = PHP_EOL . $label. $output . PHP_EOL; - }else{ - if (!extension_loaded('xdebug')) { - $output = htmlspecialchars($output, ENT_QUOTES); - } - $output = '
' . $label . $output . '
'; - } - if ($echo) { - echo($output); - return null; - }else - return $output; - } -} diff --git a/Library/Think/Error.php b/Library/Think/Error.php deleted file mode 100644 index b7675325..00000000 --- a/Library/Think/Error.php +++ /dev/null @@ -1,128 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Error { - /** - * 自定义异常处理 - * @access public - * @param mixed $e 异常对象 - */ - static public function appException($e) { - $error = []; - $error['message'] = $e->getMessage(); - $trace = $e->getTrace(); - if('E' == $trace[0]['function']) { - $error['file'] = $trace[0]['file']; - $error['line'] = $trace[0]['line']; - }else{ - $error['file'] = $e->getFile(); - $error['line'] = $e->getLine(); - } - $error['trace'] = $e->getTraceAsString(); - // 记录异常日志 - Log::record($error['message'],'ERR'); - // 发送404信息 - header('HTTP/1.1 404 Not Found'); - header('Status:404 Not Found'); - // 输出异常页面 - self::halt($error); - } - - /** - * 自定义错误处理 - * @access public - * @param int $errno 错误类型 - * @param string $errstr 错误信息 - * @param string $errfile 错误文件 - * @param int $errline 错误行数 - * @return void - */ - static public function appError($errno, $errstr, $errfile, $errline) { - $errorStr = "[{$errno}] {$errstr} {$errfile} 第 {$errline} 行."; - switch ($errno) { - case E_ERROR: - case E_PARSE: - case E_CORE_ERROR: - case E_COMPILE_ERROR: - case E_USER_ERROR: - Log::record($errorStr, 'ERROR'); - self::halt($errorStr); - break; - case E_STRICT: - case E_USER_WARNING: - case E_USER_NOTICE: - default: - Log::record($errorStr, 'NOTIC'); - break; - } - } - - /** - * 应用关闭处理 - * @return void - */ - static public function appShutdown(){ - // 记录日志 - Log::save(); - if ($e = error_get_last()) { - switch ($e['type']) { - case E_ERROR: - case E_PARSE: - case E_CORE_ERROR: - case E_COMPILE_ERROR: - case E_USER_ERROR: - ob_end_clean(); - self::halt($e); - break; - } - } - } - - /** - * 错误输出 - * @param mixed $error 错误 - * @return void - */ - static public function halt($error) { - IS_CLI && exit(is_array($error)?$error['message']:$error); - $e = []; - if (Config::get('app_debug')) { - //调试模式下输出错误信息 - if (!is_array($error)) { - $trace = debug_backtrace(); - $e['message'] = $error; - $e['file'] = $trace[0]['file']; - $e['line'] = $trace[0]['line']; - ob_start(); - debug_print_backtrace(); - $e['trace'] = ob_get_clean(); - } else { - $e = $error; - } - } else { - //否则定向到错误页面 - $error_page = Config::get('error_page'); - if (!empty($error_page)) { - header('Location: ' . $error_page); - } else { - if (Config::get('show_error_msg')) - $e['message'] = is_array($error) ? $error['message'] : $error; - else - $e['message'] = C('error_message'); - } - } - // 包含异常页面模板 - include Config::get('exception_tmpl'); - exit; - } -} diff --git a/Library/Think/Exception.php b/Library/Think/Exception.php deleted file mode 100644 index 04b02c8d..00000000 --- a/Library/Think/Exception.php +++ /dev/null @@ -1,16 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Exception extends \Exception { - -} diff --git a/Library/Think/Hook.php b/Library/Think/Hook.php deleted file mode 100644 index 5f7b1817..00000000 --- a/Library/Think/Hook.php +++ /dev/null @@ -1,86 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Hook { - - 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 $name) { - - Config::get('app_debug') && Debug::remark('behavior_start','time'); - - $result = self::exec($name, $tag,$params); - - if(Config::get('app_debug')){ - Debug::remark('behavior_end','time'); - Log::record('Run '.$name.' [ RunTime:'.Debug::getUseTime('behavior_start','behavior_end').'s ]','INFO'); - } - if(false === $result) { - // 如果返回false 则中断行为执行 - return ; - } - } - } - return; - } - - /** - * 执行某个行为 - * @param string $name 行为名称 - * @param string $tag 方法名(标签名) - * @param Mixed $params 传人的参数 - * @return void - */ - static public function exec($name, $tag,&$params=null) { - if($name instanceof \Closure) { - return $name($params); - } - if('Behavior' == substr($name,-8) ){ - // 行为扩展必须用run入口方法 - $tag = 'run'; - } - $addon = new $name(); - return $addon->$tag($params); - } -} diff --git a/Library/Think/Input.php b/Library/Think/Input.php deleted file mode 100644 index fd14d790..00000000 --- a/Library/Think/Input.php +++ /dev/null @@ -1,174 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Input { - // 全局过滤规则 - static $filter = null; - - /** - * 获取系统变量 支持过滤和默认值 - * @access public - * @param string $method 输入数据类型 - * @param array $args 参数 array(key,filter,default) - * @return mixed - */ - static public function __callStatic($method,$args=[]) { - static $_PUT = null; - $name = $args[0]; - $default = isset($args[2]) ? $args[2] : null; - if(strpos($name,'/')){ // 指定修饰符 - list($name,$type) = explode('/',$name,2); - }else{ // 默认强制转换为字符串 - $type = 's'; - } - switch(strtolower($method)) { - case 'get' : - $input =& $_GET; - break; - case 'post' : - $input =& $_POST; - break; - case 'put' : - if(is_null($_PUT)){ - parse_str(file_get_contents('php://input'), $_PUT); - } - $input = $_PUT; - break; - case 'param' : - switch($_SERVER['REQUEST_METHOD']) { - case 'POST': - $input = $_POST; - break; - case 'PUT': - if(is_null($_PUT)){ - parse_str(file_get_contents('php://input'), $_PUT); - } - $input = $_PUT; - break; - default: - $input = $_GET; - } - break; - case 'path' : - $input = []; - if(!empty($_SERVER['PATH_INFO'])){ - $depr = Config::get('url_pathinfo_depr'); - $input = explode($depr,trim($_SERVER['PATH_INFO'],$depr)); - } - break; - case 'request' : - $input =& $_REQUEST; - break; - case 'session' : - $input =& $_SESSION; - break; - case 'cookie' : - $input =& $_COOKIE; - break; - case 'server' : - $input =& $_SERVER; - break; - case 'globals' : - $input =& $GLOBALS; - break; - default: - return null; - } - - if(''==$name) { // 获取全部变量 - $data = $input; - if(isset(self::$filter)) { - $filter = self::$filter; - if(is_string($filters)){ - $filters = explode(',',$filters); - } - foreach($filters as $filter){ - $data = self::filter($filter,$data); // 参数过滤 - } - } - }elseif(isset($input[$name])) { // 取值操作 - $data = $input[$name]; - if(!empty($args[1])) { - $filters = explode(',',$args[1]); - if(is_string($filters)){ - if(0 === strpos($filters,'/')){ - if(1 !== preg_match($filters,(string)$data)){ - // 支持正则验证 - return $default; - } - }else{ - $filters = explode(',',$filters); - } - }elseif(is_int($filters)){ - $filters = array($filters); - } - - if(is_array($filters)){ - foreach($filters as $filter){ - if(function_exists($filter)) { - $data = is_array($data) ? self::filter($filter,$data) : $filter($data); // 参数过滤 - }else{ - $data = filter_var($data,is_int($filter) ? $filter : filter_id($filter)); - if(false === $data) { - return $default; - } - } - } - } - } - if(!empty($type)){ - switch(strtolower($type)){ - case 'a': // 数组 - $data = (array)$data; - break; - case 'd': // 数字 - $data = (int)$data; - break; - case 'f': // 浮点 - $data = (float)$data; - break; - case 'b': // 布尔 - $data = (boolean)$data; - break; - case 's': // 字符串 - default: - $data = (string)$data; - } - } - }else{ // 变量默认值 - $data = $default; - } - is_array($data) && array_walk_recursive($data,'self::filterExp'); - return $data; - } - - // 过滤表单中的表达式 - static public function filterExp(&$value){ - // TODO 其他安全过滤 - - // 过滤查询特殊字符 - if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value)){ - $value .= ' '; - } - } - - static public function filter($filter, $data) { - $result = array(); - foreach ($data as $key => $val) { - $result[$key] = is_array($val) - ? self::filter($filter, $val) - : call_user_func($filter, $val); - } - return $result; - } -} diff --git a/Library/Think/Lang.php b/Library/Think/Lang.php deleted file mode 100644 index d4c17fd8..00000000 --- a/Library/Think/Lang.php +++ /dev/null @@ -1,54 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Lang { - static private $_lang = []; // 语言参数 - static private $_range = '_sys_'; // 作用域 - - // 设定语言参数的作用域 - static public function range($range){ - self::$_range = $range; - } - - /** - * 设置语言定义(不区分大小写) - * @param string|array $name 语言变量 - * @param string $value 语言值 - * @param string $range 作用域 - * @return mixed - */ - static public function set($name, $value=null,$range='') { - $range = $range?$range:self::$_range; - // 批量定义 - if (is_array($name)){ - return self::$_lang[$range] = array_merge(self::$_lang[$range], array_change_key_case($name)); - }else{ - return self::$_lang[$range][strtolower($name)] = $value; - } - } - - /** - * 获取语言定义(不区分大小写) - * @param string|null $name 语言变量 - * @param string $range 作用域 - * @return mixed - */ - static public function get($name=null, $range='') { - $range = $range?$range:self::$_range; - // 空参数返回所有定义 - if (empty($name)) - return self::$_lang[$range]; - $name = strtolower($name); - return isset(self::$_lang[$range][$name]) ? self::$_lang[$range][$name] : $name; - } -} diff --git a/Library/Think/Loader.php b/Library/Think/Loader.php deleted file mode 100644 index f5e077a6..00000000 --- a/Library/Think/Loader.php +++ /dev/null @@ -1,234 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; -use Think\Config; - -class Loader { - // 类名映射 - static protected $map = []; - // 命名空间 - static protected $namespace = []; - - // 自动加载 - static public function autoload($class){ - // 检查是否定义classmap - if(isset(self::$map[$class])) { - include self::$map[$class]; - }else{ // 命名空间自动加载 - $name = strstr($class, '\\', true); - if(isset(self::$namespace[$name])){ // 注册的命名空间 - $path = dirname(self::$namespace[$name]) . '/'; - }elseif(is_dir(LIB_PATH.$name)){ // Library目录下面的命名空间自动定位 - $path = LIB_PATH; - }else{ // 项目命名空间 - $path = APP_PATH; - } - $filename = $path . str_replace('\\', '/', str_replace('\\_','\\',strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $class), "_")))) . EXT; - if(is_file($filename)) { - include $filename; - } - } - } - - // 注册classmap - static public function addMap($class, $map=''){ - if(is_array($class)){ - self::$map = array_merge(self::$map, $class); - }else{ - self::$map[$class] = $map; - } - } - - // 注册命名空间 - static public function addNamespace($namespace, $path){ - self::$namespace[$namespace] = $path; - } - - // 注册自动加载机制 - static public function register($autoload = ''){ - spl_autoload_register($autoload ? $autoload : ['think\loader', 'autoload']); - } - - /** - * 导入所需的类库 同java的Import 本函数有缓存功能 - * @param string $class 类库命名空间字符串 - * @param string $baseUrl 起始路径 - * @param string $ext 导入的文件扩展名 - * @return boolean - */ - static public function import($class, $baseUrl = '', $ext= EXT ) { - static $_file = []; - $class = str_replace(['.', '#'], ['/', '.'], $class); - if (isset($_file[$class . $baseUrl])) - return true; - else - $_file[$class . $baseUrl] = true; - $class_strut = explode('/', $class); - if (empty($baseUrl)) { - if ('@' == $class_strut[0] || MODULE_NAME == $class_strut[0]) { - //加载当前项目应用类库 - $class = substr_replace($class, '', 0, strlen($class_strut[0]) + 1); - $baseUrl = MODULE_PATH; - }elseif (in_array($class_strut[0], ['think','org', 'com'])) { - // org 第三方公共类库 com 企业公共类库 - $baseUrl = LIB_PATH; - }elseif(in_array($class_strut[0], ['vendor', 'traits'])){ - $baseUrl = THINK_PATH; - }else { // 加载其他项目应用类库 - $class = substr_replace($class, '', 0, strlen($class_strut[0]) + 1); - $baseUrl = APP_PATH . $class_strut[0] . '/'; - } - } - if (substr($baseUrl, -1) != '/') - $baseUrl .= '/'; - // 如果类存在 则导入类库文件 - $filename = $baseUrl . $class . $ext; - if(is_file($filename)) { - include $filename; - return true; - } - return false; - } - - /** - * 实例化一个没有模型文件的Model(对应数据表) - * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User - * @param array $options 模型参数 - * @return Model - */ - static public function table($name = '', $options=[]) { - static $_model = []; - if(strpos($name, ':')) { - list($class, $name) = explode(':', $name); - }else{ - $class = 'think\model'; - } - $guid = $name . '_' . $class; - if (!isset($_model[$guid])) - $_model[$guid] = new $class($name, $options); - return $_model[$guid]; - } - - /** - * 实例化(分层)模型 - * @param string $name Model名称 - * @param string $layer 业务层名称 - * @return Object - */ - static public function model($name = '', $layer = MODEL_LAYER) { - if(empty($name)) { - return new Model; - } - static $_model = []; - if(isset($_model[$name . $layer])) { - return $_model[$name . $layer]; - } - if(strpos($name, '/')) { - list($module, $name) = explode('/', $name); - }else{ - $module = MODULE_NAME; - } - $class = $module . '\\' . $layer . '\\' . parse_name($name, 1); - if(class_exists($class)) { - $model = new $class($name); - }else { - Log::record('实例化不存在的类:' . $class, 'NOTIC'); - $model = new Model($name); - } - $_model[$name . $layer] = $model; - return $model; - } - - /** - * 实例化(分层)控制器 格式:[模块名/]控制器名 - * @param string $name 资源地址 - * @param string $layer 控制层名称 - * @return Object|false - */ - static public function controller($name, $layer = CONTROLLER_LAYER) { - static $_instance = []; - if(isset($_instance[$name.$layer])) { - return $_instance[$name . $layer]; - } - if(strpos($name, '/')) { - list($module,$name) = explode('/', $name); - }else{ - $module = MODULE_NAME; - } - $class = $module . '\\' . $layer . '\\' . parse_name($name, 1) ; - if(class_exists($class)) { - $action = new $class; - $_instance[$name . $layer] = $action; - return $action; - }elseif(class_exists($module . '\\' . $layer . '\\Empty')){ - $class = $module . '\\' . $layer . '\\Empty'; - return new $class; - }else{ - return false; - } - } - - /** - * 实例化数据库 - * @param mixed $config 数据库配置 - * @param boolean $lite 是否采用lite方式连接 - * @return object - */ - static public function db($config, $lite = false) { - return Db::instance($config, $lite); - } - - /** - * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作 - * @param string $url 调用地址 - * @param string|array $vars 调用参数 支持字符串和数组 - * @param string $layer 要调用的控制层名称 - * @return mixed - */ - static public function action($url, $vars = [], $layer = CONTROLLER_LAYER) { - $info = pathinfo($url); - $action = $info['basename']; - $module = '.' != $info['dirname'] ? $info['dirname'] : CONTROLLER_NAME; - $class = self::controller($module, $layer); - if($class){ - if(is_string($vars)) { - parse_str($vars, $vars); - } - return call_user_func_array([&$class, $action . Config::get('action_suffix')], $vars); - }else{ - return false; - } - } - - /** - * 取得对象实例 支持调用类的静态方法 - * @param string $class 对象类名 - * @param string $method 类的静态方法名 - * @return object - */ - static public function instance($class, $method = '') { - static $_instance = []; - $identify = $class . $method; - if(!isset($_instance[$identify])) { - if(class_exists($class)){ - $o = new $class(); - if(!empty($method) && method_exists($o, $method)) - $_instance[$identify] = call_user_func_array([&$o, $method]); - else - $_instance[$identify] = $o; - } - else - throw new Exception('_CLASS_NOT_EXIST_:' . $class); - } - return $_instance[$identify]; - } -} diff --git a/Library/Think/Log.php b/Library/Think/Log.php deleted file mode 100644 index 1b008e38..00000000 --- a/Library/Think/Log.php +++ /dev/null @@ -1,84 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Log { - // 日志信息 - static protected $log = []; - static protected $level = ['ERR','NOTIC','DEBUG','SQL','INFO']; - static protected $storage = null; - - // 日志初始化 - static public function init($config=[]){ - $type = isset($config['type'])?$config['type']:'File'; - $class = 'Think\\Log\\Driver\\'. ucwords($type); - unset($config['type']); - self::$storage = new $class($config); - } - - /** - * 记录日志 并且会过滤未经设置的级别 - * @access public - * @param string $message 日志信息 - * @param string $level 日志级别 - * @param boolean $record 是否强制记录 - * @return void - */ - static public function record($message,$level='INFO') { - self::$log[$level][] = "{$level}: {$message}"; - } - - /** - * 获取内存中的日志信息 - * @access public - * @param string $level 日志级别 - * @return array - */ - static public function getLog($level=''){ - return $level ? self::$log[$level] : self::$log; - } - - /** - * 日志保存 - * @access public - * @param string $destination 写入目标 - * @param string $level 保存的日志级别 - * @return void - */ - static public function save($destination='',$level='') { - $log = self::getLog($level); - if(empty($log)) return ; - $message = ''; - if($level) { - $message .= implode("\r\n",$log); - self::$log[$level] = []; - }else{ - foreach($log as $info){ - $message .= implode("\r\n",$info)."\r\n"; - } - self::$log = []; - } - self::$storage && self::$storage->write($message,$destination); - } - - /** - * 日志直接写入 - * @access public - * @param string $log 日志信息 - * @param string $level 日志级别 - * @param string $destination 写入目标 - * @return void - */ - static public function write($log,$level='',$destination='') { - self::$storage && self::$storage->write("{$level}: {$log}",$destination); - } -} diff --git a/Library/Think/Log/Driver/File.php b/Library/Think/Log/Driver/File.php deleted file mode 100644 index 1c2e81d3..00000000 --- a/Library/Think/Log/Driver/File.php +++ /dev/null @@ -1,43 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Log\Driver; - -class File { - - protected $config = [ - 'log_time_format' => ' c ', - 'log_file_size' => 2097152, - 'log_path' => '', - ]; - - // 实例化并传入参数 - public function __construct($config=[]){ - $this->config = array_merge($this->config,$config); - } - - /** - * 日志写入接口 - * @access public - * @param string $log 日志信息 - * @param string $destination 写入目标 - * @return void - */ - public function write($log,$destination='') { - $now = date($this->config['log_time_format']); - if(empty($destination)) - $destination = $this->config['log_path'].date('y_m_d').'.log'; - //检测日志文件大小,超过配置大小则备份日志文件重新生成 - if(is_file($destination) && floor($this->config['log_file_size']) <= filesize($destination) ) - rename($destination,dirname($destination).'/'.time().'-'.basename($destination)); - error_log("[{$now}] ".$_SERVER['REMOTE_ADDR'].' '.$_SERVER['REQUEST_URI']."\r\n{$log}\r\n", 3,$destination); - } -} diff --git a/Library/Think/Model.php b/Library/Think/Model.php deleted file mode 100644 index 233e0d5e..00000000 --- a/Library/Think/Model.php +++ /dev/null @@ -1,1026 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Model { - // 操作状态 - const MODEL_INSERT = 1; // 插入模型数据 - const MODEL_UPDATE = 2; // 更新模型数据 - const MODEL_BOTH = 3; // 包含上面两种方式 - // 当前数据库操作对象 - protected $db = null; - // 主键名称 - protected $pk = 'id'; - // 数据表前缀 - protected $tablePrefix = ''; - // 模型名称 - protected $name = ''; - // 数据库名称 - protected $dbName = ''; - //数据库配置 - protected $connection = ''; - // 数据表名(不包含表前缀) - protected $tableName = ''; - // 实际数据表名(包含表前缀) - protected $trueTableName = ''; - // 最近错误信息 - protected $error = ''; - // 字段信息 - protected $fields = []; - // 数据信息 - protected $data = []; - // 查询表达式参数 - protected $options = []; - // 命名范围定义 - protected $scope = []; - // 字段映射定义 - protected $map = []; - // 是否自动检测数据表字段信息 - protected $autoCheckFields = false; - - /** - * 架构函数 - * 取得DB类的实例对象 字段检查 - * @access public - * @param string $name 模型名称 - * @param array $config 模型配置 - */ - public function __construct($name='',$config=[]) { - // 模型初始化 - $this->_initialize(); - // 传入模型参数 - if(!empty($name)){ - $this->name = $name; - }elseif(empty($this->name)){ - $this->name = $this->getModelName(); - } - if(strpos($this->name,'.')) { // 支持 数据库名.模型名的 定义 - list($this->dbName,$this->name) = explode('.',$this->name); - } - - if(isset($config['table_prefix'])) { - $this->tablePrefix = $config['table_prefix']; - } - if(isset($config['connection'])) { - $this->connection = $config['connection']; - } - if(isset($config['table_name'])) { - $this->tableName = $config['table_name']; - } - if(isset($config['true_table_name'])) { - $this->trueTableName = $config['true_table_name']; - } - if(isset($config['db_name'])) { - $this->dbName = $config['db_name']; - } - - // 数据库初始化操作 - // 获取数据库操作对象 - // 当前模型有独立的数据库连接信息 - $this->db(0,$this->connection); - } - - /** - * 设置数据对象的值 - * @access public - * @param string $name 名称 - * @param mixed $value 值 - * @return void - */ - public function __set($name,$value) { - // 设置数据对象属性 - $this->data[$name] = $value; - } - - /** - * 获取数据对象的值 - * @access public - * @param string $name 名称 - * @return mixed - */ - public function __get($name) { - return isset($this->data[$name])?$this->data[$name]:null; - } - - /** - * 检测数据对象的值 - * @access public - * @param string $name 名称 - * @return boolean - */ - public function __isset($name) { - return isset($this->data[$name]); - } - - /** - * 销毁数据对象的值 - * @access public - * @param string $name 名称 - * @return void - */ - public function __unset($name) { - unset($this->data[$name]); - } - - // 回调方法 初始化模型 - protected function _initialize() {} - - /** - * 对写入到数据库的数据进行处理 - * @access protected - * @param mixed $data 要操作的数据 - * @return array - */ - protected function _write_data($data) { - // 检查字段映射 - if(!empty($this->map)) { - foreach ($this->map as $key=>$val){ - if(isset($data[$key])) { - $data[$val] = $data[$key]; - unset($data[$key]); - } - } - } - // 检查非数据字段 - if(!empty($this->fields)) { - foreach ($data as $key=>$val){ - if(!in_array($key,$this->fields,true)){ - unset($data[$key]); - }elseif(is_scalar($val) && empty($this->options['bind'][':'.$key])) { - // 字段类型检查 - $this->_parseType($data,$key); - } - } - } - // 安全过滤 - if(!empty($this->options['filter'])) { - $data = array_map($this->options['filter'],$data); - unset($this->options['filter']); - } - // 回调方法 - $this->_before_write($data); - return $data; - } - // 写入数据前的回调方法 包括新增和更新 - protected function _before_write(&$data) {} - - /** - * 新增数据 - * @access public - * @param mixed $data 数据 - * @param boolean $replace 是否replace - * @return mixed - */ - public function add($data='',$replace=false) { - if(empty($data)) { - // 没有传递数据,获取当前数据对象的值 - if(!empty($this->data)) { - $data = $this->data; - // 重置数据 - $this->data = []; - }else{ - $this->error = L('_DATA_TYPE_INVALID_'); - return false; - } - } - // 数据处理 - $data = $this->_write_data($data); - // 分析表达式 - $options = $this->_parseOptions(); - if(false === $this->_before_insert($data,$options)) { - return false; - } - // 写入数据到数据库 - $result = $this->db->insert($data,$options,$replace); - if(false !== $result ) { - $insertId = $this->getLastInsID(); - if($insertId) { - // 自增主键返回插入ID - $data[$this->getPk()] = $insertId; - $this->_after_insert($data,$options); - return $insertId; - } - $this->_after_insert($data,$options); - } - return $result; - } - // 插入数据前的回调方法 - protected function _before_insert(&$data,$options) {} - // 插入成功后的回调方法 - protected function _after_insert($data,$options) {} - - /** - * 保存数据 - * @access public - * @param mixed $data 数据 - * @return boolean - */ - public function save($data='') { - if(empty($data)) { - // 没有传递数据,获取当前数据对象的值 - if(!empty($this->data)) { - $data = $this->data; - // 重置数据 - $this->data = []; - }else{ - $this->error = L('_DATA_TYPE_INVALID_'); - return false; - } - } - // 数据处理 - $data = $this->_write_data($data); - // 分析表达式 - $options = $this->_parseOptions(); - if(false === $this->_before_update($data,$options)) { - return false; - } - if(!isset($options['where']) ) { - // 如果存在主键数据 则自动作为更新条件 - if(isset($data[$this->getPk()])) { - $pk = $this->getPk(); - $where[$pk] = $data[$pk]; - $options['where'] = $where; - $pkValue = $data[$pk]; - unset($data[$pk]); - }else{ - // 如果没有任何更新条件则不执行 - $this->error = Lang::get('_OPERATION_WRONG_'); - return false; - } - } - $result = $this->db->update($data,$options); - if(false !== $result) { - if(isset($pkValue)) $data[$pk] = $pkValue; - $this->_after_update($data,$options); - } - return $result; - } - // 更新数据前的回调方法 - protected function _before_update(&$data,$options) {} - // 更新成功后的回调方法 - protected function _after_update($data,$options) {} - - /** - * 删除数据 - * @access public - * @param mixed $options 表达式 - * @return mixed - */ - public function delete($options=[]) { - if(empty($options) && empty($this->options['where'])) { - // 如果删除条件为空 则删除当前数据对象所对应的记录 - if(!empty($this->data) && isset($this->data[$this->getPk()])) - return $this->delete($this->data[$this->getPk()]); - else - return false; - } - if(is_numeric($options) || is_string($options)) { - // 根据主键删除记录 - $pk = $this->getPk(); - if(strpos($options,',')) { - $where[$pk] = ['IN', $options]; - }else{ - $where[$pk] = $options; - } - $pkValue = $where[$pk]; - $options = []; - $options['where'] = $where; - } - // 分析表达式 - $options = $this->_parseOptions($options); - $result= $this->db->delete($options); - if(false !== $result) { - $data = []; - if(isset($pkValue)) $data[$pk] = $pkValue; - $this->_after_delete($data,$options); - } - // 返回删除记录个数 - return $result; - } - // 删除成功后的回调方法 - protected function _after_delete($data,$options) {} - - /** - * 查询数据集 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function select($options=[]) { - if(is_string($options) || is_numeric($options)) { - // 根据主键查询 - $pk = $this->getPk(); - if(strpos($options,',')) { - $where[$pk] = ['IN',$options]; - }else{ - $where[$pk] = $options; - } - $options = []; - $options['where'] = $where; - }elseif(false === $options){ // 用于子查询 不查询只返回SQL - $options = []; - // 分析表达式 - $options = $this->_parseOptions($options); - return '( '.$this->db->buildSelectSql($options).' )'; - } - // 分析表达式 - $options = $this->_parseOptions($options); - $resultSet = $this->db->select($options); - if(false === $resultSet) { - return false; - } - if(empty($resultSet)) { // 查询结果为空 - return null; - } - // 数据列表读取后的处理 - $resultSet = $this->_read_datalist($resultSet); - return $resultSet; - } - - /** - * 数据列表读取后的处理 - * @access protected - * @param array $data 当前数据 - * @return array - */ - protected function _read_datalist($resultSet) { - $resultSet = array_map([$this,'_read_data'],$resultSet); - $this->_after_select($resultSet); - return $resultSet; - } - // 查询成功后的回调方法 - protected function _after_select(&$resultSet) {} - - /** - * 生成查询SQL 可用于子查询 - * @access public - * @param array $options 表达式参数 - * @return string - */ - public function buildSql($options=[]) { - // 分析表达式 - $options = $this->_parseOptions($options); - return '( '.$this->db->buildSelectSql($options).' )'; - } - - /** - * 分析表达式(可用于查询或者写入操作) - * @access protected - * @param array $options 表达式参数 - * @return array - */ - protected function _parseOptions($options=[]) { - if(is_array($options)) - $options = array_merge($this->options,$options); - // 查询过后清空sql表达式组装 避免影响下次查询 - $this->options = []; - - if(!empty($options['alias'])) { - $options['table'] .= ' '.$options['alias']; - } - // 记录操作的模型名称 - $options['model'] = $this->name; - - if(isset($options['table'])) {// 动态指定表名 - $fields = $this->db->getFields($options['table']); - $fields = $fields?array_keys($fields):false; - }else{ - $options['table'] = $this->getTableName(); - $fields = $this->getDbFields(); - } - // 字段类型验证 - if(isset($options['where']) && is_array($options['where']) && !empty($fields)) { - // 对数组查询条件进行字段类型检查 - foreach ($options['where'] as $key=>$val){ - $key = trim($key); - if(in_array($key,$fields,true)){ - if(is_scalar($val) && empty($options['bind'][':'.$key])) { - $this->_parseType($options['where'],$key); - } - }elseif('_' != substr($key,0,1) && false === strpos($key,'.') && false === strpos($key,'(') && false === strpos($key,'|') && false === strpos($key,'&')){ - unset($options['where'][$key]); - } - } - } - // 表达式过滤 - $this->_options_filter($options); - return $options; - } - // 表达式过滤回调方法 - protected function _options_filter(&$options) {} - - /** - * 数据类型检测 - * @access protected - * @param mixed $data 数据 - * @param string $key 字段名 - * @return void - */ - protected function _parseType(&$data,$key) { - if(isset($this->fields['_type'][$key])) { - $fieldType = strtolower($this->fields['_type'][$key]); - if(false === strpos($fieldType,'bigint') && false !== strpos($fieldType,'int')) { - $data[$key] = intval($data[$key]); - }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){ - $data[$key] = floatval($data[$key]); - }elseif(false !== strpos($fieldType,'bool')){ - $data[$key] = (bool)$data[$key]; - } - } - } - - /** - * 查询数据 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function find($options=[]) { - if(is_numeric($options) || is_string($options)) { - $where[$this->getPk()] = $options; - $options = []; - $options['where'] = $where; - } - // 总是查找一条记录 - $options['limit'] = 1; - // 分析表达式 - $options = $this->_parseOptions($options); - $resultSet = $this->db->select($options); - if(false === $resultSet) { - return false; - } - if(empty($resultSet)) {// 查询结果为空 - return null; - } - // 数据处理 - $data = $this->_read_data($resultSet[0]); - // 数据对象赋值 - $this->data = $data; - return $this->data; - } - - /** - * 数据读取后的处理 - * @access protected - * @param array $data 当前数据 - * @return array - */ - protected function _read_data($data) { - // 检查字段映射 - if(!empty($this->map)) { - foreach ($this->map as $key=>$val){ - if(isset($data[$val])) { - $data[$key] = $data[$val]; - unset($data[$val]); - } - } - } - $this->_after_find($data); - return $data; - } - // 数据读取成功后的回调方法 - protected function _after_find(&$result) {} - - /** - * 创建数据对象 但不保存到数据库 - * @access public - * @param mixed $data 创建数据 - * @param string $type 状态 - * @return mixed - */ - public function create($data='',$type='') { - // 如果没有传值默认取POST数据 - if(empty($data)) { - $data = $_POST; - }elseif(is_object($data)){ - $data = get_object_vars($data); - } - // 验证数据 - if(empty($data) || !is_array($data)) { - $this->error = L('_DATA_TYPE_INVALID_'); - return false; - } - - // 状态 - $type = $type?$type:(!empty($data[$this->getPk()])?self::MODEL_UPDATE:self::MODEL_INSERT); - - // 检测提交字段的合法性 - if(isset($this->options['field'])) { // $this->field('field1,field2...')->create() - $fields = $this->options['field']; - unset($this->options['field']); - }elseif($type == self::MODEL_INSERT && isset($this->insertFields)) { - $fields = $this->insertFields; - }elseif($type == self::MODEL_UPDATE && isset($this->updateFields)) { - $fields = $this->updateFields; - } - if(isset($fields)) { - if(is_string($fields)) { - $fields = explode(',',$fields); - } - foreach ($data as $key=>$val){ - if(!in_array($key,$fields)) { - unset($data[$key]); - } - } - } - // 过滤创建的数据 - $this->_create_filter($data); - // 赋值当前数据对象 - $this->data = $data; - // 返回创建的数据以供其他调用 - return $data; - } - // 数据对象创建后的回调方法 - protected function _create_filter(&$data){} - - /** - * 切换当前的数据库连接 - * @access public - * @param integer $linkNum 连接序号 - * @param mixed $config 数据库连接信息 - * @return Model - */ - public function db($linkNum='',$config=''){ - if(''===$linkNum && $this->db) { - return $this->db; - } - static $_linkNum = []; - static $_db = []; - if(!isset($_db[$linkNum]) || (isset($_db[$linkNum]) && $config && $_linkNum[$linkNum]!=$config) ) { - // 创建一个新的实例 - if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数 - $config = C($config); - } - $_db[$linkNum] = Db::instance($config); - }elseif(null === $config){ - $_db[$linkNum]->close(); // 关闭数据库连接 - unset($_db[$linkNum]); - return ; - } - - // 记录连接信息 - $_linkNum[$linkNum] = $config; - // 切换数据库连接 - $this->db = $_db[$linkNum]; - $this->_after_db(); - return $this; - } - // 数据库切换后回调方法 - protected function _after_db() {} - - /** - * 得到当前的数据对象名称 - * @access public - * @return string - */ - public function getModelName() { - if(empty($this->name)) - $this->name = substr(get_class($this),0,-5); - return $this->name; - } - - /** - * 得到完整的数据表名 - * @access public - * @return string - */ - public function getTableName() { - if(empty($this->trueTableName)) { - $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - if(!empty($this->tableName)) { - $tableName .= $this->tableName; - }else{ - $tableName .= parse_name($this->name); - } - $this->trueTableName = strtolower($tableName); - } - return (!empty($this->dbName)?$this->dbName.'.':'').$this->trueTableName; - } - - /** - * 返回模型的错误信息 - * @access public - * @return string - */ - public function getError(){ - return $this->error; - } - - /** - * 返回数据库的错误信息 - * @access public - * @return string - */ - public function getDbError() { - return $this->db->getError(); - } - - /** - * 返回最后插入的ID - * @access public - * @return string - */ - public function getLastInsID() { - return $this->db->getLastInsID(); - } - - /** - * 返回最后执行的sql语句 - * @access public - * @return string - */ - public function getLastSql() { - return $this->db->getLastSql($this->name); - } - - /** - * 获取主键名称 - * @access public - * @return string - */ - public function getPk() { - return isset($this->fields['_pk'])?$this->fields['_pk']:$this->pk; - } - - /** - * 获取数据表字段信息 - * @access public - * @return array - */ - public function getDbFields(){ - if($this->fields) { - $fields = $this->fields; - unset($fields['_pk'],$fields['_type']); - return $fields; - }else{ - $fields = Cache::get(md5($this->getTableName())); - if(!$fields) { - $fields = $this->db->getFields($this->getTableName()); - $this->fields = array_keys($fields); - foreach ($fields as $key=>$val){ - // 记录字段类型 - $type[$key] = $val['type']; - if($val['primary']) { - $this->fields['_pk'] = $key; - } - } - // 记录字段类型信息 - $this->fields['_type'] = $type; - Cache::set(md5($this->trueTableName),$this->fields); - $fields = $this->fields; - }else{ - $this->fields = $fields; - } - unset($fields['_pk'],$fields['_type']); - return $fields; - } - } - - /** - * SQL查询 - * @access public - * @param string $sql SQL指令 - * @param array $bind 参数绑定 - * @return mixed - */ - public function query($sql,$bind=[]) { - $sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); - return $this->db->query($sql,$bind); - } - - /** - * 执行SQL语句 - * @access public - * @param string $sql SQL指令 - * @param array $bind 参数绑定 - * @return false | integer - */ - public function execute($sql,$bind=[]) { - $sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); - return $this->db->execute($sql,$bind); - } - - /** - * 设置数据对象值 - * @access public - * @param mixed $data 数据 - * @return Model - */ - public function data($data=''){ - if('' === $data && !empty($this->data)) { - return $this->data; - } - if(is_object($data)){ - $data = get_object_vars($data); - }elseif(is_string($data)){ - parse_str($data,$data); - }elseif(!is_array($data)){ - E(L('_DATA_TYPE_INVALID_')); - } - $this->data = $data; - return $this; - } - - /** - * 查询SQL组装 join - * @access public - * @param mixed $join - * @return Model - */ - public function join($join) { - if(is_array($join)) { - $this->options['join'] = $join; - }elseif(!empty($join)) { - $this->options['join'][] = $join; - } - return $this; - } - - /** - * 查询SQL组装 union - * @access public - * @param mixed $union - * @param boolean $all - * @return Model - */ - public function union($union,$all=false) { - if(empty($union)) return $this; - if($all) { - $this->options['union']['_all'] = true; - } - if(is_object($union)) { - $union = get_object_vars($union); - } - // 转换union表达式 - if(is_string($union) ) { - $options = $union; - }elseif(is_array($union)){ - if(isset($union[0])) { - $this->options['union'] = array_merge($this->options['union'],$union); - return $this; - }else{ - $options = $union; - } - }else{ - E(L('_DATA_TYPE_INVALID_')); - } - $this->options['union'][] = $options; - return $this; - } - - /** - * 查询缓存 - * @access public - * @param mixed $key - * @param integer $expire - * @param string $type - * @return Model - */ - public function cache($key=true,$expire=null,$type=''){ - if(false !== $key) - $this->options['cache'] = ['key'=>$key,'expire'=>$expire,'type'=>$type]; - return $this; - } - - /** - * 指定查询字段 支持字段排除 - * @access public - * @param mixed $field - * @param boolean $except 是否排除 - * @return Model - */ - public function field($field,$except=false){ - if(true === $field) {// 获取全部字段 - $fields = $this->getDbFields(); - $field = $fields?$fields:'*'; - }elseif($except) {// 字段排除 - if(is_string($field)) { - $field = explode(',',$field); - } - $fields = $this->getDbFields(); - $field = $fields?array_diff($fields,$field):$field; - } - $this->options['field'] = $field; - return $this; - } - - /** - * 调用命名范围 - * @access public - * @param mixed $scope 命名范围名称 支持多个 和直接定义 - * @param array $args 参数 - * @return Model - */ - public function scope($scope='',$args=null){ - if('' === $scope) { - if(isset($this->scope['default'])) { - // 默认的命名范围 - $options = $this->scope['default']; - }else{ - return $this; - } - }elseif(is_string($scope)){ // 支持多个命名范围调用 用逗号分割 - $scopes = explode(',',$scope); - $options = []; - foreach ($scopes as $name){ - if(!isset($this->scope[$name])) continue; - $options = array_merge($options,$this->scope[$name]); - } - if(!empty($args) && is_array($args)) { - $options = array_merge($options,$args); - } - }elseif(is_array($scope)){ // 直接传入命名范围定义 - $options = $scope; - } - - if(is_array($options) && !empty($options)){ - $this->options = array_merge($this->options,array_change_key_case($options)); - } - return $this; - } - - /** - * 指定查询条件 支持安全过滤 - * @access public - * @param mixed $where 条件表达式 - * @param mixed $parse 预处理参数 - * @return Model - */ - public function where($where,$parse=null){ - if(!is_null($parse) && is_string($where)) { - if(!is_array($parse)) { - $parse = func_get_args(); - array_shift($parse); - } - $parse = array_map([$this->db,'escapeString'],$parse); - $where = vsprintf($where,$parse); - }elseif(is_object($where)){ - $where = get_object_vars($where); - } - if(is_string($where) && '' != $where){ - $map = []; - $map['_string'] = $where; - $where = $map; - } - if(isset($this->options['where'])){ - $this->options['where'] = array_merge($this->options['where'],$where); - }else{ - $this->options['where'] = $where; - } - return $this; - } - - /** - * 指定查询数量 - * @access public - * @param mixed $offset 起始位置 - * @param mixed $length 查询数量 - * @return Model - */ - public function limit($offset,$length=null){ - $this->options['limit'] = is_null($length)?$offset:$offset.','.$length; - return $this; - } - - /** - * 指定分页 - * @access public - * @param mixed $page 页数 - * @param mixed $listRows 每页数量 - * @return Model - */ - public function page($page,$listRows=null){ - $this->options['page'] = is_null($listRows)?$page:$page.','.$listRows; - return $this; - } - - /** - * 指定数据表 - * @access public - * @param string $table 表名 - * @return Model - */ - public function table($table){ - $this->options['table'] = $table; - return $this; - } - - /** - * 指定排序 - * @access public - * @param string $order 排序 - * @return Model - */ - public function order($order){ - $this->options['order'] = $order; - return $this; - } - - /** - * 指定group查询 - * @access public - * @param string $group GROUP - * @return Model - */ - public function group($group){ - $this->options['group'] = $group; - return $this; - } - - /** - * 指定having查询 - * @access public - * @param string $having having - * @return Model - */ - public function having($table){ - $this->options['having'] = $having; - return $this; - } - - /** - * 指定查询lock - * @access public - * @param boolean $lock 是否lock - * @return Model - */ - public function lock($lock=false){ - $this->options['lock'] = $lock; - return $this; - } - - /** - * 指定distinct查询 - * @access public - * @param string $distinct 是否唯一 - * @return Model - */ - public function distinct($distinct){ - $this->options['distinct'] = $distinct; - return $this; - } - - /** - * 指定数据表别名 - * @access public - * @param string $alias 数据表别名 - * @return Model - */ - public function alias($alias){ - $this->options['alias'] = $alias; - return $this; - } - - /** - * 指定写入过滤方法 - * @access public - * @param string $filter 指定过滤方法 - * @return Model - */ - public function filter($filter){ - $this->options['filter'] = $filter; - return $this; - } - - /** - * 指定参数绑定 - * @access public - * @param array $bind 指定参数绑定 - * @return Model - */ - public function bind($bind){ - $this->options['bind'] = $bind; - return $this; - } - - /** - * 查询注释 - * @access public - * @param string $comment 注释 - * @return Model - */ - public function comment($comment){ - $this->options['comment'] = $comment; - return $this; - } - - /** - * 设置字段映射 - * @access public - * @param array $map 映射 - * @return Model - */ - public function map($map){ - $this->map = $map; - return $this; - } -} \ No newline at end of file diff --git a/Library/Think/Model/ExtendModel.php b/Library/Think/Model/ExtendModel.php deleted file mode 100644 index dc878991..00000000 --- a/Library/Think/Model/ExtendModel.php +++ /dev/null @@ -1,18 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Model; -use Traits\Think\Model\Extend,Traits\Think\Model\Query; -T('Think/Model/Extend'); -T('Think/Model/Query'); -class ExtendModel extends \Think\Model { - use Extend,Query; -} \ No newline at end of file diff --git a/Library/Think/Model/MongoModel.php b/Library/Think/Model/MongoModel.php deleted file mode 100644 index a3858e87..00000000 --- a/Library/Think/Model/MongoModel.php +++ /dev/null @@ -1,274 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace Think\Model; -/** - * MongoModel模型类 - * 实现了ODM和ActiveRecords模式 - */ -class MongoModel extends \Think\Model{ - // 主键类型 - const TYPE_OBJECT = 1; - const TYPE_INT = 2; - const TYPE_STRING = 3; - - // 主键名称 - protected $pk = '_id'; - // _id 类型 1 Object 采用MongoId对象 2 Int 整形 支持自动增长 3 String 字符串Hash - protected $_idType = self::TYPE_OBJECT; - // 主键是否自动增长 支持Int型主键 - protected $_autoInc = false; - // Mongo默认关闭字段检测 可以动态追加字段 - protected $autoCheckFields = false; - - /** - * 利用__call方法实现一些特殊的Model方法 - * @access public - * @param string $method 方法名称 - * @param array $args 调用参数 - * @return mixed - */ - public function __call($method,$args) { - if(strtolower(substr($method,0,5))=='getby') { - // 根据某个字段获取记录 - $field = parse_name(substr($method,5)); - $where[$field] =$args[0]; - return $this->where($where)->find(); - }elseif(strtolower(substr($method,0,10))=='getfieldby') { - // 根据某个字段获取记录的某个值 - $name = parse_name(substr($method,10)); - $where[$name] =$args[0]; - return $this->where($where)->getField($args[1]); - }else{ - throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_')); - return; - } - } - - // 写入数据前的回调方法 包括新增和更新 - protected function _before_write(&$data) { - $pk = $this->getPk(); - // 根据主键类型处理主键数据 - if(isset($data[$pk]) && $this->_idType == self::TYPE_OBJECT) { - $data[$pk] = new MongoId($data[$pk]); - } - } - - /** - * count统计 配合where连贯操作 - * @access public - * @return integer - */ - public function count(){ - // 分析表达式 - $options = $this->_parseOptions(); - return $this->db->count($options); - } - - /** - * 获取下一ID 用于自动增长型 - * @access public - * @param string $pk 字段名 默认为主键 - * @return mixed - */ - public function getMongoNextId($pk=''){ - if(empty($pk)) { - $pk = $this->getPk(); - } - return $this->db->getMongoNextId($pk); - } - - // 插入数据前的回调方法 - protected function _before_insert(&$data,$options) { - // 写入数据到数据库 - if($this->_autoInc && $this->_idType== self::TYPE_INT) { // 主键自动增长 - $pk = $this->getPk(); - if(!isset($data[$pk])) { - $data[$pk] = $this->db->mongo_next_id($pk); - } - } - } - - public function clear(){ - return $this->db->clear(); - } - - // 查询成功后的回调方法 - protected function _after_select(&$resultSet,$options) { - array_walk($resultSet,array($this,'checkMongoId')); - } - - /** - * 获取MongoId - * @access protected - * @param array $result 返回数据 - * @return array - */ - protected function checkMongoId(&$result){ - if(is_object($result['_id'])) { - $result['_id'] = $result['_id']->__toString(); - } - return $result; - } - - // 表达式过滤回调方法 - protected function _options_filter(&$options) { - $id = $this->getPk(); - if(isset($options['where'][$id]) && is_scalar($options['where'][$id]) && $this->_idType== self::TYPE_OBJECT) { - $options['where'][$id] = new MongoId($options['where'][$id]); - } - } - - /** - * 查询数据 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function find($options=array()) { - if( is_numeric($options) || is_string($options)) { - $id = $this->getPk(); - $where[$id] = $options; - $options = array(); - $options['where'] = $where; - } - // 分析表达式 - $options = $this->_parseOptions($options); - $result = $this->db->find($options); - if(false === $result) { - return false; - } - if(empty($result)) {// 查询结果为空 - return null; - }else{ - $this->checkMongoId($result); - } - $this->data = $result; - $this->_after_find($this->data,$options); - return $this->data; - } - - /** - * 字段值增长 - * @access public - * @param string $field 字段名 - * @param integer $step 增长值 - * @return boolean - */ - public function setInc($field,$step=1) { - return $this->setField($field,array('inc',$step)); - } - - /** - * 字段值减少 - * @access public - * @param string $field 字段名 - * @param integer $step 减少值 - * @return boolean - */ - public function setDec($field,$step=1) { - return $this->setField($field,array('inc','-'.$step)); - } - - /** - * 获取一条记录的某个字段值 - * @access public - * @param string $field 字段名 - * @param string $spea 字段数据间隔符号 - * @return mixed - */ - public function getField($field,$sepa=null) { - $options['field'] = $field; - $options = $this->_parseOptions($options); - if(strpos($field,',')) { // 多字段 - if(is_numeric($sepa)) {// 限定数量 - $options['limit'] = $sepa; - $sepa = null;// 重置为null 返回数组 - } - $resultSet = $this->db->select($options); - if(!empty($resultSet)) { - $_field = explode(',', $field); - $field = array_keys($resultSet[0]); - $key = array_shift($field); - $key2 = array_shift($field); - $cols = array(); - $count = count($_field); - foreach ($resultSet as $result){ - $name = $result[$key]; - if(2==$count) { - $cols[$name] = $result[$key2]; - }else{ - $cols[$name] = is_null($sepa)?$result:implode($sepa,$result); - } - } - return $cols; - } - }else{ - // 返回数据个数 - if(true !== $sepa) {// 当sepa指定为true的时候 返回所有数据 - $options['limit'] = is_numeric($sepa)?$sepa:1; - } // 查找一条记录 - $result = $this->db->find($options); - if(!empty($result)) { - if(1==$options['limit']) return reset($result[0]); - foreach ($result as $val){ - $array[] = $val[$field]; - } - return $array; - } - } - return null; - } - - /** - * 执行Mongo指令 - * @access public - * @param array $command 指令 - * @return mixed - */ - public function command($command) { - return $this->db->command($command); - } - - /** - * 执行MongoCode - * @access public - * @param string $code MongoCode - * @param array $args 参数 - * @return mixed - */ - public function mongoCode($code,$args=array()) { - return $this->db->execute($code,$args); - } - - // 数据库切换后回调方法 - protected function _after_db() { - // 切换Collection - $this->db->switchCollection($this->getTableName(),$this->dbName); - } - - /** - * 得到完整的数据表名 Mongo表名不带dbName - * @access public - * @return string - */ - public function getTableName() { - if(empty($this->trueTableName)) { - $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - if(!empty($this->tableName)) { - $tableName .= $this->tableName; - }else{ - $tableName .= parse_name($this->name); - } - $this->trueTableName = strtolower($tableName); - } - return $this->trueTableName; - } -} \ No newline at end of file diff --git a/Library/Think/Model/RelationModel.php b/Library/Think/Model/RelationModel.php deleted file mode 100644 index 4989bee3..00000000 --- a/Library/Think/Model/RelationModel.php +++ /dev/null @@ -1,16 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Model; -T('Think/Model/Relation'); -class RelationModel extends \Think\Model { - use \Traits\Think\Model\Relation; -} \ No newline at end of file diff --git a/Library/Think/Model/ViewModel.php b/Library/Think/Model/ViewModel.php deleted file mode 100644 index 44faee86..00000000 --- a/Library/Think/Model/ViewModel.php +++ /dev/null @@ -1,16 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Model; -T('Think/Model/View'); -class ViewModel extends \Think\Model { - use \Traits\Think\Model\View; -} \ No newline at end of file diff --git a/Library/Think/Parser.php b/Library/Think/Parser.php deleted file mode 100644 index 934d9497..00000000 --- a/Library/Think/Parser.php +++ /dev/null @@ -1,32 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -// 内容解析类 -class Parser { - - static private $handler = []; - - // 解析内容 - static public function parse($content,$type){ - if(!isset(self::$handler[$type])) { - $class = '\\Think\\Parser\\Driver\\'.ucwords($type); - self::$handler[$type] = new $class(); - } - return self::$handler[$type]->parse($content); - } - - // 调用驱动类的方法 - static public function __callStatic($method, $params){ - return self::parse($params[0],$method); - } -} diff --git a/Library/Think/Parser/Driver/Markdown.php b/Library/Think/Parser/Driver/Markdown.php deleted file mode 100644 index 334f7a60..00000000 --- a/Library/Think/Parser/Driver/Markdown.php +++ /dev/null @@ -1,1534 +0,0 @@ - -# -# Original Markdown -# Copyright (c) 2004-2006 John Gruber -# -# - -# 应用到ThinkPHP中,因而修改为ThinkPHP规范的命名空间 -# namespace Michelf; -namespace Think\Parser\Driver; - -# -# The following two constants are deprecated: avoid using them, they'll -# disappear when the Lib branch becomes the only one to be updated. -# -# You can get the parser's version using the constant inside of the parser -# class: \Michelf\Markdown::MARKDOWNLIB_VERSION. -# - -const MARKDOWN_VERSION = "1.0.1p"; # Sun 13 Jan 2013 -const MARKDOWNEXTRA_VERSION = "1.2.6"; # Sun 13 Jan 2013 - -# -# Markdown Parser Class -# - -class Markdown { - - ### Version ### - - const MARKDOWNLIB_VERSION = "1.3-beta4"; - - ### Simple Function Interface ### - - public static function defaultTransform($text) { - # - # Initialize the parser and return the result of its transform method. - # This will work fine for derived classes too. - # - # Take parser class on which this function was called. - $parser_class = \get_called_class(); - - # try to take parser from the static parser list - static $parser_list; - $parser =& $parser_list[$parser_class]; - - # create the parser it not already set - if (!$parser) - $parser = new $parser_class; - - # Transform text using parser. - return $parser->transform($text); - } - - ### Configuration Variables ### - - # Change to ">" for HTML output. - public $empty_element_suffix = " />"; - public $tab_width = 4; - - # Change to `true` to disallow markup or entities. - public $no_markup = false; - public $no_entities = false; - - # Predefined urls and titles for reference links and images. - public $predef_urls = array(); - public $predef_titles = array(); - - - ### Parser Implementation ### - - # Regex to match balanced [brackets]. - # Needed to insert a maximum bracked depth while converting to PHP. - protected $nested_brackets_depth = 6; - protected $nested_brackets_re; - - protected $nested_url_parenthesis_depth = 4; - protected $nested_url_parenthesis_re; - - # Table of hash values for escaped characters: - protected $escape_chars = '\`*_{}[]()>#+-.!'; - protected $escape_chars_re; - - - public function __construct() { - # - # Constructor function. Initialize appropriate member variables. - # - $this->_initDetab(); - $this->prepareItalicsAndBold(); - - $this->nested_brackets_re = - str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). - str_repeat('\])*', $this->nested_brackets_depth); - - $this->nested_url_parenthesis_re = - str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). - str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); - - $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; - - # Sort document, block, and span gamut in ascendent priority order. - asort($this->document_gamut); - asort($this->block_gamut); - asort($this->span_gamut); - } - - - # Internal hashes used during transformation. - protected $urls = array(); - protected $titles = array(); - protected $html_hashes = array(); - - # Status flag to avoid invalid nesting. - protected $in_anchor = false; - - - protected function setup() { - # - # Called before the transformation process starts to setup parser - # states. - # - # Clear global hashes. - $this->urls = $this->predef_urls; - $this->titles = $this->predef_titles; - $this->html_hashes = array(); - - $this->in_anchor = false; - } - - protected function teardown() { - # - # Called after the transformation process to clear any variable - # which may be taking up memory unnecessarly. - # - $this->urls = array(); - $this->titles = array(); - $this->html_hashes = array(); - } - - /** - * 提供给ThinkPHP外部调用的方法,麦当苗儿为ThinkPHP添加 - * @author - * @param string $content 需要解析的Markdown字符串 - * @return string 解析后的HTML字符串 - */ - public function parse($content){ - return $this->transform($content); - } - - protected function transform($text) { - # - # Main function. Performs some preprocessing on the input text - # and pass it through the document gamut. - # - $this->setup(); - - # Remove UTF-8 BOM and marker character in input, if present. - $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); - - # Standardize line endings: - # DOS to Unix and Mac to Unix - $text = preg_replace('{\r\n?}', "\n", $text); - - # Make sure $text ends with a couple of newlines: - $text .= "\n\n"; - - # Convert all tabs to spaces. - $text = $this->detab($text); - - # Turn block-level HTML blocks into hash entries - $text = $this->hashHTMLBlocks($text); - - # Strip any lines consisting only of spaces and tabs. - # This makes subsequent regexen easier to write, because we can - # match consecutive blank lines with /\n+/ instead of something - # contorted like /[ ]*\n+/ . - $text = preg_replace('/^[ ]+$/m', '', $text); - - # Run document gamut methods. - foreach ($this->document_gamut as $method => $priority) { - $text = $this->$method($text); - } - - $this->teardown(); - - return $text . "\n"; - } - - protected $document_gamut = array( - # Strip link definitions, store in hashes. - "stripLinkDefinitions" => 20, - - "runBasicBlockGamut" => 30, - ); - - - protected function stripLinkDefinitions($text) { - # - # Strips link definitions from text, stores the URLs and titles in - # hash references. - # - $less_than_tab = $this->tab_width - 1; - - # Link defs are in the form: ^[id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 - [ ]* - \n? # maybe *one* newline - [ ]* - (?: - <(.+?)> # url = $2 - | - (\S+?) # url = $3 - ) - [ ]* - \n? # maybe one newline - [ ]* - (?: - (?<=\s) # lookbehind for whitespace - ["(] - (.*?) # title = $4 - [")] - [ ]* - )? # title is optional - (?:\n+|\Z) - }xm', - array(&$this, '_stripLinkDefinitions_callback'), - $text); - return $text; - } - protected function _stripLinkDefinitions_callback($matches) { - $link_id = strtolower($matches[1]); - $url = $matches[2] == '' ? $matches[3] : $matches[2]; - $this->urls[$link_id] = $url; - $this->titles[$link_id] =& $matches[4]; - return ''; # String that will replace the block - } - - - protected function hashHTMLBlocks($text) { - if ($this->no_markup) return $text; - - $less_than_tab = $this->tab_width - 1; - - # Hashify HTML blocks: - # We only want to do this for block-level HTML tags, such as headers, - # lists, and tables. That's because we still want to wrap

s around - # "paragraphs" that are wrapped in non-block-level tags, such as anchors, - # phrase emphasis, and spans. The list of tags we're looking for is - # hard-coded: - # - # * List "a" is made of tags which can be both inline or block-level. - # These will be treated block-level when the start tag is alone on - # its line, otherwise they're not matched here and will be taken as - # inline later. - # * List "b" is made of tags which are always block-level; - # - $block_tags_a_re = 'ins|del'; - $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. - 'script|noscript|form|fieldset|iframe|math|svg|'. - 'article|section|nav|aside|hgroup|header|footer|'. - 'figure'; - - # Regular expression for the content of a block tag. - $nested_tags_level = 4; - $attr = ' - (?> # optional tag attributes - \s # starts with whitespace - (?> - [^>"/]+ # text outside quotes - | - /+(?!>) # slash not followed by ">" - | - "[^"]*" # text inside double quotes (tolerate ">") - | - \'[^\']*\' # text inside single quotes (tolerate ">") - )* - )? - '; - $content = - str_repeat(' - (?> - [^<]+ # content without tag - | - <\2 # nested opening tag - '.$attr.' # attributes - (?> - /> - | - >', $nested_tags_level). # end of opening tag - '.*?'. # last level nested tag content - str_repeat(' - # closing nested tag - ) - | - <(?!/\2\s*> # other tags with a different name - ) - )*', - $nested_tags_level); - $content2 = str_replace('\2', '\3', $content); - - # First, look for nested blocks, e.g.: - #

- #
- # tags for inner block must be indented. - #
- #
- # - # The outermost tags must start at the left margin for this to match, and - # the inner nested divs must be indented. - # We need to do this before the next, more liberal match, because the next - # match will start at the first `
` and stop at the first `
`. - $text = preg_replace_callback('{(?> - (?> - (?<=\n\n) # Starting after a blank line - | # or - \A\n? # the beginning of the doc - ) - ( # save in $1 - - # Match from `\n` to `\n`, handling nested tags - # in between. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_b_re.')# start tag = $2 - '.$attr.'> # attributes followed by > and \n - '.$content.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special version for tags of group a. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_a_re.')# start tag = $3 - '.$attr.'>[ ]*\n # attributes followed by > - '.$content2.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special case just for
. It was easier to make a special - # case than to make the other regex more complicated. - - [ ]{0,'.$less_than_tab.'} - <(hr) # start tag = $2 - '.$attr.' # attributes - /?> # the matching end tag - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # Special case for standalone HTML comments: - - [ ]{0,'.$less_than_tab.'} - (?s: - - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # PHP and ASP-style processor instructions ( - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - ) - )}Sxmi', - array(&$this, '_hashHTMLBlocks_callback'), - $text); - - return $text; - } - protected function _hashHTMLBlocks_callback($matches) { - $text = $matches[1]; - $key = $this->hashBlock($text); - return "\n\n$key\n\n"; - } - - - protected function hashPart($text, $boundary = 'X') { - # - # Called whenever a tag must be hashed when a function insert an atomic - # element in the text stream. Passing $text to through this function gives - # a unique text-token which will be reverted back when calling unhash. - # - # The $boundary argument specify what character should be used to surround - # the token. By convension, "B" is used for block elements that needs not - # to be wrapped into paragraph tags at the end, ":" is used for elements - # that are word separators and "X" is used in the general case. - # - # Swap back any tag hash found in $text so we do not have to `unhash` - # multiple times at the end. - $text = $this->unhash($text); - - # Then hash the block. - static $i = 0; - $key = "$boundary\x1A" . ++$i . $boundary; - $this->html_hashes[$key] = $text; - return $key; # String that will replace the tag. - } - - - protected function hashBlock($text) { - # - # Shortcut function for hashPart with block-level boundaries. - # - return $this->hashPart($text, 'B'); - } - - - protected $block_gamut = array( - # - # These are all the transformations that form block-level - # tags like paragraphs, headers, and list items. - # - "doHeaders" => 10, - "doHorizontalRules" => 20, - - "doLists" => 40, - "doCodeBlocks" => 50, - "doBlockQuotes" => 60, - ); - - protected function runBlockGamut($text) { - # - # Run block gamut tranformations. - # - # We need to escape raw HTML in Markdown source before doing anything - # else. This need to be done for each block, and not only at the - # begining in the Markdown function since hashed blocks can be part of - # list items and could have been indented. Indented blocks would have - # been seen as a code block in a previous pass of hashHTMLBlocks. - $text = $this->hashHTMLBlocks($text); - - return $this->runBasicBlockGamut($text); - } - - protected function runBasicBlockGamut($text) { - # - # Run block gamut tranformations, without hashing HTML blocks. This is - # useful when HTML blocks are known to be already hashed, like in the first - # whole-document pass. - # - foreach ($this->block_gamut as $method => $priority) { - $text = $this->$method($text); - } - - # Finally form paragraph and restore hashed blocks. - $text = $this->formParagraphs($text); - - return $text; - } - - - protected function doHorizontalRules($text) { - # Do Horizontal Rules: - return preg_replace( - '{ - ^[ ]{0,3} # Leading space - ([-*_]) # $1: First marker - (?> # Repeated marker group - [ ]{0,2} # Zero, one, or two spaces. - \1 # Marker character - ){2,} # Group repeated at least twice - [ ]* # Tailing spaces - $ # End of line. - }mx', - "\n".$this->hashBlock("empty_element_suffix")."\n", - $text); - } - - - protected $span_gamut = array( - # - # These are all the transformations that occur *within* block-level - # tags like paragraphs, headers, and list items. - # - # Process character escapes, code spans, and inline HTML - # in one shot. - "parseSpan" => -30, - - # Process anchor and image tags. Images must come first, - # because ![foo][f] looks like an anchor. - "doImages" => 10, - "doAnchors" => 20, - - # Make links out of things like `` - # Must come after doAnchors, because you can use < and > - # delimiters in inline links like [this](). - "doAutoLinks" => 30, - "encodeAmpsAndAngles" => 40, - - "doItalicsAndBold" => 50, - "doHardBreaks" => 60, - ); - - protected function runSpanGamut($text) { - # - # Run span gamut tranformations. - # - foreach ($this->span_gamut as $method => $priority) { - $text = $this->$method($text); - } - - return $text; - } - - - protected function doHardBreaks($text) { - # Do hard breaks: - return preg_replace_callback('/ {2,}\n/', - array(&$this, '_doHardBreaks_callback'), $text); - } - protected function _doHardBreaks_callback($matches) { - return $this->hashPart("empty_element_suffix\n"); - } - - - protected function doAnchors($text) { - # - # Turn Markdown link shortcuts into XHTML tags. - # - if ($this->in_anchor) return $text; - $this->in_anchor = true; - - # - # First, handle reference-style links: [link text] [id] - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - ) - }xs', - array(&$this, '_doAnchors_reference_callback'), $text); - - # - # Next, inline-style links: [link text](url "optional title") - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - \( # literal paren - [ \n]* - (?: - <(.+?)> # href = $3 - | - ('.$this->nested_url_parenthesis_re.') # href = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # Title = $7 - \6 # matching quote - [ \n]* # ignore any spaces/tabs between closing quote and ) - )? # title is optional - \) - ) - }xs', - array(&$this, '_doAnchors_inline_callback'), $text); - - # - # Last, handle reference-style shortcuts: [link text] - # These must come last in case you've also got [link text][1] - # or [link text](/foo) - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ([^\[\]]+) # link text = $2; can\'t contain [ or ] - \] - ) - }xs', - array(&$this, '_doAnchors_reference_callback'), $text); - - $this->in_anchor = false; - return $text; - } - protected function _doAnchors_reference_callback($matches) { - $whole_match = $matches[1]; - $link_text = $matches[2]; - $link_id =& $matches[3]; - - if ($link_id == "") { - # for shortcut links like [this][] or [this]. - $link_id = $link_text; - } - - # lower-case and turn embedded newlines into spaces - $link_id = strtolower($link_id); - $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); - - if (isset($this->urls[$link_id])) { - $url = $this->urls[$link_id]; - $url = $this->encodeAttribute($url); - - $result = "titles[$link_id] ) ) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - $result = $this->hashPart($result); - } - else { - $result = $whole_match; - } - return $result; - } - protected function _doAnchors_inline_callback($matches) { - $whole_match = $matches[1]; - $link_text = $this->runSpanGamut($matches[2]); - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $url = $this->encodeAttribute($url); - - $result = "encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - - return $this->hashPart($result); - } - - - protected function doImages($text) { - # - # Turn Markdown image shortcuts into tags. - # - # - # First, handle reference-style labeled images: ![alt text][id] - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - - ) - }xs', - array(&$this, '_doImages_reference_callback'), $text); - - # - # Next, handle inline images: ![alt text](url "optional title") - # Don't forget: encode * and _ - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - \s? # One optional whitespace character - \( # literal paren - [ \n]* - (?: - <(\S*)> # src url = $3 - | - ('.$this->nested_url_parenthesis_re.') # src url = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # title = $7 - \6 # matching quote - [ \n]* - )? # title is optional - \) - ) - }xs', - array(&$this, '_doImages_inline_callback'), $text); - - return $text; - } - protected function _doImages_reference_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $link_id = strtolower($matches[3]); - - if ($link_id == "") { - $link_id = strtolower($alt_text); # for shortcut links like ![this][]. - } - - $alt_text = $this->encodeAttribute($alt_text); - if (isset($this->urls[$link_id])) { - $url = $this->encodeAttribute($this->urls[$link_id]); - $result = "\"$alt_text\"";titles[$link_id])) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - $result .= $this->empty_element_suffix; - $result = $this->hashPart($result); - } - else { - # If there's no such link ID, leave intact: - $result = $whole_match; - } - - return $result; - } - protected function _doImages_inline_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $alt_text = $this->encodeAttribute($alt_text); - $url = $this->encodeAttribute($url); - $result = "\"$alt_text\"";encodeAttribute($title); - $result .= " title=\"$title\""; # $title already quoted - } - $result .= $this->empty_element_suffix; - - return $this->hashPart($result); - } - - - protected function doHeaders($text) { - # Setext-style headers: - # Header 1 - # ======== - # - # Header 2 - # -------- - # - $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', - array(&$this, '_doHeaders_callback_setext'), $text); - - # atx-style headers: - # # Header 1 - # ## Header 2 - # ## Header 2 with closing hashes ## - # ... - # ###### Header 6 - # - $text = preg_replace_callback('{ - ^(\#{1,6}) # $1 = string of #\'s - [ ]* - (.+?) # $2 = Header text - [ ]* - \#* # optional closing #\'s (not counted) - \n+ - }xm', - array(&$this, '_doHeaders_callback_atx'), $text); - - return $text; - } - protected function _doHeaders_callback_setext($matches) { - # Terrible hack to check we haven't found an empty list item. - if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) - return $matches[0]; - - $level = $matches[2]{0} == '=' ? 1 : 2; - $block = "".$this->runSpanGamut($matches[1]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - protected function _doHeaders_callback_atx($matches) { - $level = strlen($matches[1]); - $block = "".$this->runSpanGamut($matches[2]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - - protected function doLists($text) { - # - # Form HTML ordered (numbered) and unordered (bulleted) lists. - # - $less_than_tab = $this->tab_width - 1; - - # Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - - $markers_relist = array( - $marker_ul_re => $marker_ol_re, - $marker_ol_re => $marker_ul_re, - ); - - foreach ($markers_relist as $marker_re => $other_marker_re) { - # Re-usable pattern to match any entirel ul or ol list: - $whole_list_re = ' - ( # $1 = whole list - ( # $2 - ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces - ('.$marker_re.') # $4 = first list item marker - [ ]+ - ) - (?s:.+?) - ( # $5 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another list item marker - [ ]* - '.$marker_re.'[ ]+ - ) - | - (?= # Lookahead for another kind of list - \n - \3 # Must have the same indentation - '.$other_marker_re.'[ ]+ - ) - ) - ) - '; // mx - - # We use a different prefix before nested lists than top-level lists. - # See extended comment in _ProcessListItems(). - - if ($this->list_level) { - $text = preg_replace_callback('{ - ^ - '.$whole_list_re.' - }mx', - array(&$this, '_doLists_callback'), $text); - } - else { - $text = preg_replace_callback('{ - (?:(?<=\n)\n|\A\n?) # Must eat the newline - '.$whole_list_re.' - }mx', - array(&$this, '_doLists_callback'), $text); - } - } - - return $text; - } - protected function _doLists_callback($matches) { - # Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - - $list = $matches[1]; - $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; - - $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); - - $list .= "\n"; - $result = $this->processListItems($list, $marker_any_re); - - $result = $this->hashBlock("<$list_type>\n" . $result . ""); - return "\n". $result ."\n\n"; - } - - protected $list_level = 0; - - protected function processListItems($list_str, $marker_any_re) { - # - # Process the contents of a single ordered or unordered list, splitting it - # into individual list items. - # - # The $this->list_level global keeps track of when we're inside a list. - # Each time we enter a list, we increment it; when we leave a list, - # we decrement. If it's zero, we're not in a list anymore. - # - # We do this because when we're not inside a list, we want to treat - # something like this: - # - # I recommend upgrading to version - # 8. Oops, now this line is treated - # as a sub-list. - # - # As a single paragraph, despite the fact that the second line starts - # with a digit-period-space sequence. - # - # Whereas when we're inside a list (or sub-list), that line will be - # treated as the start of a sub-list. What a kludge, huh? This is - # an aspect of Markdown's syntax that's hard to parse perfectly - # without resorting to mind-reading. Perhaps the solution is to - # change the syntax rules such that sub-lists must start with a - # starting cardinal number; e.g. "1." or "a.". - - $this->list_level++; - - # trim trailing blank lines: - $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); - - $list_str = preg_replace_callback('{ - (\n)? # leading line = $1 - (^[ ]*) # leading whitespace = $2 - ('.$marker_any_re.' # list marker and space = $3 - (?:[ ]+|(?=\n)) # space only required if item is not empty - ) - ((?s:.*?)) # list item text = $4 - (?:(\n+(?=\n))|\n) # tailing blank line = $5 - (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) - }xm', - array(&$this, '_processListItems_callback'), $list_str); - - $this->list_level--; - return $list_str; - } - protected function _processListItems_callback($matches) { - $item = $matches[4]; - $leading_line =& $matches[1]; - $leading_space =& $matches[2]; - $marker_space = $matches[3]; - $tailing_blank_line =& $matches[5]; - - if ($leading_line || $tailing_blank_line || - preg_match('/\n{2,}/', $item)) - { - # Replace marker with the appropriate whitespace indentation - $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; - $item = $this->runBlockGamut($this->outdent($item)."\n"); - } - else { - # Recursion for sub-lists: - $item = $this->doLists($this->outdent($item)); - $item = preg_replace('/\n+$/', '', $item); - $item = $this->runSpanGamut($item); - } - - return "
  • " . $item . "
  • \n"; - } - - - protected function doCodeBlocks($text) { - # - # Process Markdown `
    ` blocks.
    -	#
    -		$text = preg_replace_callback('{
    -				(?:\n\n|\A\n?)
    -				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    -				  (?>
    -					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    -					.*\n+
    -				  )+
    -				)
    -				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    -			}xm',
    -			array(&$this, '_doCodeBlocks_callback'), $text);
    -
    -		return $text;
    -	}
    -	protected function _doCodeBlocks_callback($matches) {
    -		$codeblock = $matches[1];
    -
    -		$codeblock = $this->outdent($codeblock);
    -		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    -
    -		# trim leading newlines and trailing newlines
    -		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    -
    -		$codeblock = "
    $codeblock\n
    "; - return "\n\n".$this->hashBlock($codeblock)."\n\n"; - } - - - protected function makeCodeSpan($code) { - # - # Create a code span markup for $code. Called from handleSpanToken. - # - $code = htmlspecialchars(trim($code), ENT_NOQUOTES); - return $this->hashPart("$code"); - } - - - protected $em_relist = array( - '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { - foreach ($this->strong_relist as $strong => $strong_re) { - # Construct list of allowed token expressions. - $token_relist = array(); - if (isset($this->em_strong_relist["$em$strong"])) { - $token_relist[] = $this->em_strong_relist["$em$strong"]; - } - $token_relist[] = $em_re; - $token_relist[] = $strong_re; - - # Construct master expression from list. - $token_re = '{('. implode('|', $token_relist) .')}'; - $this->em_strong_prepared_relist["$em$strong"] = $token_re; - } - } - } - - protected function doItalicsAndBold($text) { - $token_stack = array(''); - $text_stack = array(''); - $em = ''; - $strong = ''; - $tree_char_em = false; - - while (1) { - # - # Get prepared regular expression for seraching emphasis tokens - # in current context. - # - $token_re = $this->em_strong_prepared_relist["$em$strong"]; - - # - # Each loop iteration search for the next emphasis token. - # Each token is then passed to handleSpanToken. - # - $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); - $text_stack[0] .= $parts[0]; - $token =& $parts[1]; - $text =& $parts[2]; - - if (empty($token)) { - # Reached end of text span: empty stack without emitting. - # any more emphasis. - while ($token_stack[0]) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - break; - } - - $token_len = strlen($token); - if ($tree_char_em) { - # Reached closing marker while inside a three-char emphasis. - if ($token_len == 3) { - # Three-char closing marker, close em and strong. - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - $strong = ''; - } else { - # Other closing marker: close one em or strong and - # change current token state to match the other - $token_stack[0] = str_repeat($token{0}, 3-$token_len); - $tag = $token_len == 2 ? "strong" : "em"; - $span = $text_stack[0]; - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] = $this->hashPart($span); - $$tag = ''; # $$tag stands for $em or $strong - } - $tree_char_em = false; - } else if ($token_len == 3) { - if ($em) { - # Reached closing marker for both em and strong. - # Closing strong marker: - for ($i = 0; $i < 2; ++$i) { - $shifted_token = array_shift($token_stack); - $tag = strlen($shifted_token) == 2 ? "strong" : "em"; - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] .= $this->hashPart($span); - $$tag = ''; # $$tag stands for $em or $strong - } - } else { - # Reached opening three-char emphasis marker. Push on token - # stack; will be handled by the special condition above. - $em = $token{0}; - $strong = "$em$em"; - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $tree_char_em = true; - } - } else if ($token_len == 2) { - if ($strong) { - # Unwind any dangling emphasis marker: - if (strlen($token_stack[0]) == 1) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - # Closing strong marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $strong = ''; - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $strong = $token; - } - } else { - # Here $token_len == 1 - if ($em) { - if (strlen($token_stack[0]) == 1) { - # Closing emphasis marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - } else { - $text_stack[0] .= $token; - } - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $em = $token; - } - } - } - return $text_stack[0]; - } - - - protected function doBlockQuotes($text) { - $text = preg_replace_callback('/ - ( # Wrap whole match in $1 - (?> - ^[ ]*>[ ]? # ">" at the start of a line - .+\n # rest of the first line - (.+\n)* # subsequent consecutive lines - \n* # blanks - )+ - ) - /xm', - array(&$this, '_doBlockQuotes_callback'), $text); - - return $text; - } - protected function _doBlockQuotes_callback($matches) { - $bq = $matches[1]; - # trim one level of quoting - trim whitespace-only lines - $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); - $bq = $this->runBlockGamut($bq); # recurse - - $bq = preg_replace('/^/m', " ", $bq); - # These leading spaces cause problem with
     content, 
    -		# so we need to fix that:
    -		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', - array(&$this, '_doBlockQuotes_callback2'), $bq); - - return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; - } - protected function _doBlockQuotes_callback2($matches) { - $pre = $matches[1]; - $pre = preg_replace('/^ /m', '', $pre); - return $pre; - } - - - protected function formParagraphs($text) { - # - # Params: - # $text - string to process with html

    tags - # - # Strip leading and trailing lines: - $text = preg_replace('/\A\n+|\n+\z/', '', $text); - - $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); - - # - # Wrap

    tags and unhashify HTML blocks - # - foreach ($grafs as $key => $value) { - if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { - # Is a paragraph. - $value = $this->runSpanGamut($value); - $value = preg_replace('/^([ ]*)/', "

    ", $value); - $value .= "

    "; - $grafs[$key] = $this->unhash($value); - } - else { - # Is a block. - # Modify elements of @grafs in-place... - $graf = $value; - $block = $this->html_hashes[$graf]; - $graf = $block; -// if (preg_match('{ -// \A -// ( # $1 =
    tag -//
    ]* -// \b -// markdown\s*=\s* ([\'"]) # $2 = attr quote char -// 1 -// \2 -// [^>]* -// > -// ) -// ( # $3 = contents -// .* -// ) -// (
    ) # $4 = closing tag -// \z -// }xs', $block, $matches)) -// { -// list(, $div_open, , $div_content, $div_close) = $matches; -// -// # We can't call Markdown(), because that resets the hash; -// # that initialization code should be pulled into its own sub, though. -// $div_content = $this->hashHTMLBlocks($div_content); -// -// # Run document gamut methods on the content. -// foreach ($this->document_gamut as $method => $priority) { -// $div_content = $this->$method($div_content); -// } -// -// $div_open = preg_replace( -// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); -// -// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; -// } - $grafs[$key] = $graf; - } - } - - return implode("\n\n", $grafs); - } - - - protected function encodeAttribute($text) { - # - # Encode text for a double-quoted HTML attribute. This function - # is *not* suitable for attributes enclosed in single quotes. - # - $text = $this->encodeAmpsAndAngles($text); - $text = str_replace('"', '"', $text); - return $text; - } - - - protected function encodeAmpsAndAngles($text) { - # - # Smart processing for ampersands and angle brackets that need to - # be encoded. Valid character entities are left alone unless the - # no-entities mode is set. - # - if ($this->no_entities) { - $text = str_replace('&', '&', $text); - } else { - # Ampersand-encoding based entirely on Nat Irons's Amputator - # MT plugin: - $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', - '&', $text);; - } - # Encode remaining <'s - $text = str_replace('<', '<', $text); - - return $text; - } - - - protected function doAutoLinks($text) { - $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', - array(&$this, '_doAutoLinks_url_callback'), $text); - - # Email addresses: - $text = preg_replace_callback('{ - < - (?:mailto:)? - ( - (?: - [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ - | - ".*?" - ) - \@ - (?: - [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ - | - \[[\d.a-fA-F:]+\] # IPv4 & IPv6 - ) - ) - > - }xi', - array(&$this, '_doAutoLinks_email_callback'), $text); - - return $text; - } - protected function _doAutoLinks_url_callback($matches) { - $url = $this->encodeAttribute($matches[1]); - $link = "$url"; - return $this->hashPart($link); - } - protected function _doAutoLinks_email_callback($matches) { - $address = $matches[1]; - $link = $this->encodeEmailAddress($address); - return $this->hashPart($link); - } - - - protected function encodeEmailAddress($addr) { - # - # Input: an email address, e.g. "foo@example.com" - # - # Output: the email address as a mailto link, with each character - # of the address encoded as either a decimal or hex entity, in - # the hopes of foiling most address harvesting spam bots. E.g.: - # - #

    foo@exampl - # e.com

    - # - # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. - # With some optimizations by Milian Wolff. - # - $addr = "mailto:" . $addr; - $chars = preg_split('/(? $char) { - $ord = ord($char); - # Ignore non-ascii chars. - if ($ord < 128) { - $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. - # roughly 10% raw, 45% hex, 45% dec - # '@' *must* be encoded. I insist. - if ($r > 90 && $char != '@') /* do nothing */; - else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; - else $chars[$key] = '&#'.$ord.';'; - } - } - - $addr = implode('', $chars); - $text = implode('', array_slice($chars, 7)); # text without `mailto:` - $addr = "$text"; - - return $addr; - } - - - protected function parseSpan($str) { - # - # Take the string $str and parse it into tokens, hashing embeded HTML, - # escaped characters and handling code spans. - # - $output = ''; - - $span_re = '{ - ( - \\\\'.$this->escape_chars_re.' - | - (?no_markup ? '' : ' - | - # comment - | - <\?.*?\?> | <%.*?%> # processing instruction - | - <[!$]?[-a-zA-Z0-9:_]+ # regular tags - (?> - \s - (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* - )? - > - | - <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag - | - # closing tag - ').' - ) - }xs'; - - while (1) { - # - # Each loop iteration seach for either the next tag, the next - # openning code span marker, or the next escaped character. - # Each token is then passed to handleSpanToken. - # - $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); - - # Create token from text preceding tag. - if ($parts[0] != "") { - $output .= $parts[0]; - } - - # Check if we reach the end. - if (isset($parts[1])) { - $output .= $this->handleSpanToken($parts[1], $parts[2]); - $str = $parts[2]; - } - else { - break; - } - } - - return $output; - } - - - protected function handleSpanToken($token, &$str) { - # - # Handle $token provided by parseSpan by determining its nature and - # returning the corresponding value that should replace it. - # - switch ($token{0}) { - case "\\": - return $this->hashPart("&#". ord($token{1}). ";"); - case "`": - # Search for end marker in remaining text. - if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', - $str, $matches)) - { - $str = $matches[2]; - $codespan = $this->makeCodeSpan($matches[1]); - return $this->hashPart($codespan); - } - return $token; // return as text since no ending marker found. - default: - return $this->hashPart($token); - } - } - - - protected function outdent($text) { - # - # Remove one level of line-leading tabs or spaces - # - return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); - } - - - # String length function for detab. `_initDetab` will create a function to - # hanlde UTF-8 if the default function does not exist. - protected $utf8_strlen = 'mb_strlen'; - - protected function detab($text) { - # - # Replace tabs with the appropriate amount of space. - # - # For each line we separate the line in blocks delemited by - # tab characters. Then we reconstruct every line by adding the - # appropriate number of space between each blocks. - - $text = preg_replace_callback('/^.*\t.*$/m', - array(&$this, '_detab_callback'), $text); - - return $text; - } - protected function _detab_callback($matches) { - $line = $matches[0]; - $strlen = $this->utf8_strlen; # strlen function for UTF-8. - - # Split in blocks. - $blocks = explode("\t", $line); - # Add each blocks to the line. - $line = $blocks[0]; - unset($blocks[0]); # Do not add first block twice. - foreach ($blocks as $block) { - # Calculate amount of space, insert spaces, insert block. - $amount = $this->tab_width - - $strlen($line, 'UTF-8') % $this->tab_width; - $line .= str_repeat(" ", $amount) . $block; - } - return $line; - } - protected function _initDetab() { - # - # Check for the availability of the function in the `utf8_strlen` property - # (initially `mb_strlen`). If the function is not available, create a - # function that will loosely count the number of UTF-8 characters with a - # regular expression. - # - if (function_exists($this->utf8_strlen)) return; - $this->utf8_strlen = create_function('$text', 'return preg_match_all( - "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", - $text, $m);'); - } - - - protected function unhash($text) { - # - # Swap back in all the tags hashed by _HashHTMLBlocks. - # - return preg_replace_callback('/(.)\x1A[0-9]+\1/', - array(&$this, '_unhash_callback'), $text); - } - protected function _unhash_callback($matches) { - return $this->html_hashes[$matches[0]]; - } - -} diff --git a/Library/Think/Parser/Driver/Ubb.php b/Library/Think/Parser/Driver/Ubb.php deleted file mode 100644 index 525549ce..00000000 --- a/Library/Think/Parser/Driver/Ubb.php +++ /dev/null @@ -1,290 +0,0 @@ - -// +---------------------------------------------------------------------- -// | Ubb.php 2013-04-03 -// +---------------------------------------------------------------------- - -namespace Think\Parser\Driver; - -class Ubb{ - /** - * UBB标签匹配规则 - * @var array - */ - private $ubb = [ - ['table' , '\[table(?:=([\d%]*))?\]', '\[\/table\]', 'width'], - ['tr' , '\[tr\]', '\[\/tr\]', 'tag'], - ['th' , '\[th(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/th\]', 'widthAndHeight'], - ['td' , '\[td(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/td\]', 'widthAndHeight'], - ['img' , '\[img(?:=([\d%]*)(?:,([\d%]*))?)?\]', '\[\/img\]', 'imgWidthAndHeight'], - ['img' , '\[img=(.*?)(?:,([\d%]*)(?:,([\d%]*))?)?\/\]', 'img'], - ['a' , '\[url(?:=(.*?)(?:,([\w\-]*))?)?\]', '\[\/url\]', 'urlClass'], - ['a' , '\[a(?:=(.*?)(?:,([\w\-]*))?)?\]', '\[\/a\]', 'urlClass'], - ['a' , '\[url=(.*?)(?:,([\w\-]*))?\/\]', 'url'], - ['a' , '\[a=(.*?)(?:,([\w\-]*))?\/\]', 'url'], - ['a' , '\[email(?:=([\w\-]*))?\]', '\[\/email\]', 'emailClass'], - ['ul' , '\[ul(?:=([\w\-]*))?\]', '\[\/ul\]', 'class'], - ['ol' , '\[ol(?:=([\w\-]*))?\]', '\[\/ol\]', 'class'], - ['li' , '\[li(?:=([\w\-]*))?\]', '\[\/li\]', 'class'], - ['span' , '\[span(?:=([\w\-]*))?\]', '\[\/span\]', 'class'], - ['div' , '\[div(?:=([\w\-]*))?\]', '\[\/div\]', 'class'], - ['p' , '\[p(?:=([\w\-]*))?\]', '\[\/p\]', 'class'], - ['strong' , '\[b\]', '\[\/b\]', 'tag'], - ['strong' , '\[strong\]', '\[\/strong\]', 'tag'], - ['i' , '\[i\]', '\[\/i\]', 'tag'], - ['em' , '\[em\]', '\[\/em\]', 'tag'], - ['sub' , '\[sub\]', '\[\/sub\]', 'tag'], - ['sup' , '\[sup\]', '\[\/sup\]', 'tag'], - ['pre' , '\[code(?:=([a-z#\+\/]*))?\]', '\[\/code\]', 'code'], - ['code' , '\[line(?:=([a-z#\+\/]*))?\]', '\[\/line\]', 'code'], - ]; - - /** - * 解析UBB代码为HTML - * @param string $content 要解析的UBB代码 - * @return string 解析后的HTML代码 - */ - public function parse($content = ''){ - if(empty($content)) return ''; - - for($i = 0, $count = count($this->ubb); $i < $count; $i++){ - if(count($this->ubb[$i]) == 4){ //解析闭合标签 - $content = $this->closeTag($content, $this->ubb[$i]); - } else { - $content = $this->onceTag($content, $this->ubb[$i]); - } - } - - return nl2br($content); - } - - /** - * 解析闭合标签,支持嵌套 - * @param string $data 要解析的数据 - * @param array $rule 解析规则 - * @return string 解析后的内容 - */ - private function closeTag($data, $rule = ''){ - static $tag, $reg, $func, $count = 0; - if(is_string($data)){ - list($tag, $reg[0], $reg[1], $func) = $rule; - do{ - $data = preg_replace_callback("/({$reg[0]})(.*?)({$reg[1]})/is", - [$this, 'closeTag'], $data); - } while ($count && $count--); //递归解析,直到嵌套解析完毕 - return $data; - } elseif(is_array($data)){ - $num = count($data); - if(preg_match("/{$reg[0]}/is", $data[$num-2])){ //存在嵌套,进一步解析 - $count = 1; - $data[$num-2] = preg_replace_callback("/({$reg[0]})(.*?)({$reg[1]})/is", - [$this, 'closeTag'], $data[$num-2] . $data[$num-1]); - return $data[1] . $data[$num-2]; - } else { //不存在嵌套,直接解析内容 - $parse = '_' . $func; - $data[$num-2] = trim($data[$num-2], "\r\n"); //去掉标签内容两端的换行符 - return $this->$parse($tag, $data); - } - } - } - - /** - * 解析单标签 - * @param string $data 要解析的数据 - * @param array $rule 解析规则 - * @return string 解析后的内容 - */ - private function onceTag($data, $rule = ''){ - list($tag, $reg, $func) = $rule; - return preg_replace_callback("/{$reg}/is", [$this, '_' . $func], $data); - } - - /** - * 解析img单标签 - * @param array $data 解析数据 - * @return string 解析后的标签 - */ - private function _img($data){ - $data[4] = $data[1]; - return $this->_imgWidthAndHeight('', $data); - } - - /** - * 解析url单标签 - * @param array $data 解析数据 - * @return string 解析后的标签 - */ - private function _url($data){ - $data[3] = $data[2]; - $data[4] = $data[2] = $data[1]; - return $this->_urlClass('', $data); - } - - /** - * 解析没有属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - 标签内容 - * @return string 解析后的标签 - */ - private function _tag($name, $data){ - return "<{$name}>{$data[2]}"; - } - - /** - * 解析代码 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - 语言类型,[3] - 代码内容 - * @return string 解析后的标签 - */ - private function _code($name, $data){ - $fix = ($name == 'pre') ? ['
    ', '
    '] : ['', '']; - if(empty($data[2])){ - $data = "{$fix[0]}{$data[3]}{$fix[1]}"; - } else { - $data = "{$fix[0]}{$data[3]}{$fix[1]}"; - } - return $data; - } - - /** - * 解析含有width属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - width, [3] - 标签内容 - * @return string 解析后的标签 - */ - private function _width($name, $data){ - if(empty($data[2])){ - $data = "<{$name}>{$data[3]}"; - } else { - $data = "<{$name} width=\"{$data[2]}\">{$data[3]}"; - } - return $data; - } - - /** - * 解析含有width和height属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - width, [3] - height, [4] - 标签内容 - * @return string 解析后的标签 - */ - private function _widthAndHeight($name, $data){ - if(empty($data[2]) && empty($data[3])){ - $data = "<{$name}>{$data[4]}"; - } elseif(!empty($data[2]) && empty($data[3])) { - $data = "<{$name} width=\"{$data[2]}\">{$data[4]}"; - } elseif(empty($data[2]) && !empty($data[3])) { - $data = "<{$name} height=\"{$data[3]}\">{$data[4]}"; - } else { - $data = "<{$name} width=\"{$data[2]}\" height=\"{$data[3]}\">{$data[4]}"; - } - return $data; - } - - /** - * 解析含有width和height属性的图片标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - width, [3] - height, [4] - 图片URL - * @return string 解析后的标签 - */ - private function _imgWidthAndHeight($name, $data){ - if(empty($data[2]) && empty($data[3])){ - $data = ""; - } elseif(!empty($data[2]) && empty($data[3])) { - $data = ""; - } elseif(empty($data[2]) && !empty($data[3])) { - $data = ""; - } else { - $data = ""; - } - return $data; - } - - /** - * 解析含有class属性的标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - class, [3] - 标签内容 - * @return string 解析后的标签 - */ - private function _class($name, $data){ - if(empty($data[2])){ - $data = "<{$name}>{$data[3]}"; - } else { - $data = "<{$name} class=\"{$data[2]}\">{$data[3]}"; - } - return $data; - } - - /** - * 解析含有class属性的url标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - url, [3] - text - * @return string 解析后的标签 - */ - private function _urlClass($name, $data){ - empty($data[2]) && $data[2] = $data[4]; - if(empty($data[3])){ - $data = "{$data[4]}"; - } else { - $data = "{$data[4]}"; - } - return $data; - } - - /** - * 解析含有class属性的email标签 - * @param string $name 标签名 - * @param array $data 解析数据 [2] - class, [3] - email地址 - * @return string 解析后的标签 - */ - private function _emailClass($name, $data){ - //不是正确的EMAIL则不解析 - if(preg_match('/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', $data[3])) - return $data[0]; - - //编码email地址,防治被采集 - $email = $this->encodeEmailAddress($data[3]); - - if(empty($data[2])){ - $data = "{$email[1]}"; - } else { - $data = "{$email[1]}"; - } - return $data; - } - - /** - * 编码EMAIL地址,可以防治部分采集软件 - * @param string $addr EMAIL地址 - * @return array 编码后的EMAIL地址 [0] - 带mailto, [1] - 不带mailto - */ - private function encodeEmailAddress($addr) { - $addr = "mailto:" . $addr; - $chars = preg_split('/(? $char) { - $ord = ord($char); - # Ignore non-ascii chars. - if ($ord < 128) { - $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. - # roughly 10% raw, 45% hex, 45% dec - # '@' *must* be encoded. I insist. - if ($r > 90 && $char != '@') /* do nothing */; - else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; - else $chars[$key] = '&#'.$ord.';'; - } - } - - $addr = implode('', $chars); - $text = implode('', array_slice($chars, 7)); # text without `mailto:` - - return [$addr, $text]; - } -} diff --git a/Library/Think/Route.php b/Library/Think/Route.php deleted file mode 100644 index 100d2c71..00000000 --- a/Library/Think/Route.php +++ /dev/null @@ -1,452 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Route { - // 路由规则 - static private $rules = [ - 'GET' => [], - 'POST' => [], - 'PUT' => [], - 'DELETE' => [], - '*' => [], - ]; - - // URL映射规则 - static private $map = []; - // 子域名部署规则 - static private $domain = []; - - // 添加URL映射规则 - static public function map($map, $route = ''){ - if(is_array($map)) { - self::$map = array_merge(self::$map, $map); - }else{ - self::$map[$map] = $route; - } - } - - // 添加子域名部署规则 - static public function domain($domain, $rule = ''){ - if(is_array($domain)) { - self::$domain = array_merge(self::$domain,$domain); - }else{ - self::$domain[$domain] = $rule; - } - } - - // 注册路由规则 - static public function register($rule, $route = '', $type = 'GET', $option = []){ - if(strpos($type, '|')) { - foreach (explode('|', $type) as $val){ - self::register($rule, $route, $val, $option); - } - }else{ - if(is_array($rule)) { - foreach ($rule as $key => $val){ - self::$rules[$type][$key] = ['route' => $val, 'option' => $option]; - } - }else{ - self::$rules[$type][$rule] = ['route' => $route, 'option' => $option]; - } - } - } - - // 注册任意请求的路由规则 - static public function any($rule, $route = '', $option = []){ - self::register($rule, $route, '*', $option); - } - - // 注册get请求的路由规则 - static public function get($rule, $route = '', $option = []){ - self::register($rule, $route, 'GET', $option); - } - - // 注册post请求的路由规则 - static public function post($rule, $route = '', $option = []){ - self::register($rule, $route, 'POST', $option); - } - - // 注册put请求的路由规则 - static public function put($rule, $route = '', $option = []){ - self::register($rule, $route, 'PUT', $option); - } - - // 注册delete请求的路由规则 - static public function delete($rule, $route = '', $option = []){ - self::register($rule, $route, 'DELETE', $option); - } - - // 检测子域名部署 - static public function checkDomain($config=[]){ - // 开启子域名部署 支持二级和三级域名 - if(!empty(self::$domain)) { - $rules = self::$domain; - if(isset($rules[$_SERVER['HTTP_HOST']])) { // 完整域名或者IP配置 - $rule = $rules[$_SERVER['HTTP_HOST']]; - }else{// 子域名配置 - $domain = array_slice(explode('.', $_SERVER['HTTP_HOST']), 0, -2); - if(!empty($domain)) { - $subDomain = implode('.', $domain); - $domain2 = array_pop($domain); // 二级域名 - if($domain) { // 存在三级域名 - $domain3 = array_pop($domain); - } - if($subDomain && isset($rules[$subDomain])) { // 子域名配置 - $rule = $rules[$subDomain]; - }elseif(isset($rules['*.' . $domain2]) && !empty($domain3)){ // 泛三级域名 - $rule = $rules['*.' . $domain2]; - $panDomain = $domain3; - }elseif(isset($rules['*']) && !empty($domain2)){ // 泛二级域名 - if('www' != $domain2 ) { - $rule = $rules['*']; - $panDomain = $domain2; - } - } - } - } - if(!empty($rule)) { - // 子域名部署规则 - // '子域名'=>'模块名' - // '子域名'=>['模块名','var1=a&var2=b&var3=*']; - if($rule instanceof \Closure) { - // 执行闭包并中止 - self::invokeRule($rule); - exit; - } - if(is_array($rule)) { - $_GET[$config['var_module']] = $rule[0]; - if(isset($rule[1])) { // 传入参数 - parse_str($rule[1], $parms); - if(isset($panDomain)) { - $pos = array_search('*', $parms); - if(false !== $pos) { - // 泛域名作为参数 - $parms[$pos] = $panDomain; - } - } - $_GET = array_merge($_GET,$parms); - } - }else{ - $_GET[$config['var_module']] = $rule; - } - } - } - } - - // 检测URL路由 - static public function check($regx,$config) { - // 优先检测是否存在PATH_INFO - if(empty($regx)) $regx = '/' ; - // 分隔符替换 确保路由定义使用统一的分隔符 - if('/' != $config['pathinfo_depr']){ - $regx = str_replace($config['pathinfo_depr'], '/', $regx); - } - if(isset(self::$map[$regx])) { // URL映射 - return self::parseUrl(self::$map[$regx]); - } - // 获取当前请求类型的路由规则 - $rules = self::$rules[REQUEST_METHOD]; - if(!empty(self::$rules['*'])) { // 合并任意请求的路由规则 - $rules = array_merge(self::$rules['*'], $rules); - } - // 路由规则检测 - if(!empty($rules)) { - foreach ($rules as $rule=>$val){ - $route = $val['route']; - $option = $val['option']; - - // 伪静态后缀检测 - if(isset($option['ext']) && __EXT__ != $option['ext']) { - continue; - } - // https检测 - if(!empty($option['https']) && !self::isSsl()) { - continue; - } - // 自定义检测 - if(!empty($option['callback']) && is_callable($option['callback'])) { - if(false === call_user_func($option['callback'])) { - continue; - } - } - if(0 === strpos($rule, '/') && preg_match($rule, $regx, $matches)) { // 正则路由 - if(!empty($option['file'])){ - // 调度到某个文件中执行 - include $route; - exit; - } - if($route instanceof \Closure) { - // 执行闭包并中止 - self::invokeRegx($route, $matches); - exit; - } - return self::parseRegex($matches, $route, $regx,$config); - }else{ // 规则路由 - $len1 = substr_count($regx, '/'); - $len2 = substr_count($rule, '/'); - if($len1 >= $len2) { - if('$' == substr($rule, -1, 1)) {// 完整匹配 - if($len1 != $len2) { - continue; - }else{ - $rule = substr($rule, 0, -1); - } - } - if(false !== $var = self::match($regx, $rule)){ - if(!empty($option['file'])){ - // 调度到某个文件中执行 - include $route; - exit; - } - if($route instanceof \Closure) { - // 执行闭包并中止 - self::invokeRule($route, $var); - exit; - } - return self::parseRule($rule, $route, $regx,$config); - } - } - } - } - } - return self::parseUrl($regx,$config); - } - - /** - * 判断是否SSL协议 - * @return boolean - */ - static public function isSsl() { - if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){ - return true; - }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) { - return true; - } - return false; - } - - // 执行正则匹配下的闭包方法 支持参数调用 - static private function invokeRegx($closure, $var = []) { - $reflect = new \ReflectionFunction($closure); - $params = $reflect->getParameters(); - $args = []; - array_shift($var); - foreach ($params as $param){ - $name = $param->getName(); - if(!empty($var)) { - $args[] = array_shift($var); - }elseif($param->isDefaultValueAvailable()){ - $args[] = $param->getDefaultValue(); - } - } - $reflect->invokeArgs($args); - } - - // 执行规则匹配下的闭包方法 支持参数调用 - static private function invokeRule($closure, $var = []) { - $reflect = new \ReflectionFunction($closure); - $params = $reflect->getParameters(); - $args = []; - foreach ($params as $param){ - $name = $param->getName(); - if(isset($var[$name])) { - $args[] = $var[$name]; - }elseif($param->isDefaultValueAvailable()){ - $args[] = $param->getDefaultValue(); - } - } - $reflect->invokeArgs($args); - } - - // 解析模块的URL地址 [模块/]控制器/操作 - static private function parseUrl($url,$config=[]) { - if('/' == $url) { - return ; - } - $paths = explode('/', $url); - - if(!defined('BIND_MODULE') && !isset($_GET[$config['var_module']])) { - $_GET[$config['var_module']] = array_shift($paths); - } - - if(!defined('BIND_CONTROLLER') && !isset($_GET[$config['var_controller']])) { - $_GET[$config['var_controller']] = array_shift($paths); - } - - if($paths){ - $_GET[$config['var_action']] = array_shift($paths); - } - - // 解析剩余的URL参数 - $var = []; - if(!empty($paths)) { - preg_replace_callback('/(\w+)\/([^\/]+)/', function($match) use(&$var){ $var[strtolower($match[1])]=strip_tags($match[2]);}, implode('/',$paths)); - } - $_GET = array_merge($var, $_GET); - } - - // 解析规范的路由地址 - // 地址格式 [控制器/操作?]参数1=值1&参数2=值2... - static private function parseRoute($url,$config=[]) { - $var = []; - if(false !== strpos($url, '?')) { // [控制器/操作?]参数1=值1&参数2=值2... - $info = parse_url($url); - $path = explode('/', $info['path']); - parse_str($info['query'], $var); - }elseif(strpos($url, '/')){ // [控制器/操作] - $path = explode('/', $url); - }else{ // 参数1=值1&参数2=值2... - parse_str($url, $var); - } - if(isset($path)) { - $action = array_pop($path); - $_GET[$config['var_action']] = '[rest]'==$action ? REQUEST_METHOD : $action; - if(!empty($path)) { - $_GET[$config['var_controller']] = array_pop($path); - } - if(!empty($path)) { - $_GET[$config['var_module']] = array_pop($path); - } - } - return $var; - } - - // 检测URL和规则路由是否匹配 - static private function match($regx, $rule) { - $m1 = explode('/', $regx); - $m2 = explode('/', $rule); - $var = []; - foreach ($m2 as $key=>$val){ - if(0 === strpos($val, ':')) {// 动态变量 - if(strpos($val, '\\')) { - $type = substr($val, -1); - if('d' == $type && !is_numeric($m1[$key])) { - return false; - } - $name = substr($val, 1, -2); - }elseif($pos = strpos($val, '^')){ - $array = explode('|', substr(strstr($val, '^'), 1)); - if(in_array($m1[$key], $array)) { - return false; - } - $name = substr($val, 1, $pos - 1); - }else{ - $name = substr($val, 1); - } - $var[$name] = $m1[$key]; - }elseif(0 !== strcasecmp($val, $m1[$key])){ - return false; - } - } - // 成功匹配后返回URL中的动态变量数组 - return $var; - } - - // 解析规则路由 - // '路由规则'=>'[控制器/操作]?额外参数1=值1&额外参数2=值2...' - // '路由规则'=>array('[控制器/操作]','额外参数1=值1&额外参数2=值2...') - // '路由规则'=>'外部地址' - // '路由规则'=>array('外部地址','重定向代码') - // 路由规则中 :开头 表示动态变量 - // 外部地址中可以用动态变量 采用 :1 :2 的方式 - // 'news/:month/:day/:id'=>array('News/read?cate=1','status=1'), - // 'new/:id'=>array('/new.php?id=:1',301), 重定向 - static private function parseRule($rule, $route, $regx,$config) { - // 获取路由地址规则 - $url = is_array($route) ? $route[0] : $route; - // 获取URL地址中的参数 - $paths = explode('/', $regx); - // 解析路由规则 - $matches = []; - $rule = explode('/', $rule); - foreach ($rule as $item){ - if(0 === strpos($item, ':')) { // 动态变量获取 - if($pos = strpos($item, '^') ) { - $var = substr($item, 1, $pos - 1); - }elseif(strpos($item, '\\')){ - $var = substr($item, 1, -2); - }else{ - $var = substr($item, 1); - } - $matches[$var] = array_shift($paths); - }else{ // 过滤URL中的静态变量 - array_shift($paths); - } - } - if(0 === strpos($url, '/') || 0 === strpos($url, 'http')) { // 路由重定向跳转 - if(strpos($url, ':')) { // 传递动态参数 - $values = array_values($matches); - $url = preg_replace('/:(\d+)/e', '$values[\\1-1]', $url); - } - header("Location: $url", true, (is_array($route) && isset($route[1])) ? $route[1] : 301); - exit; - }else{ - // 解析路由地址 - $var = self::parseRoute($url,$config); - // 解析路由地址里面的动态参数 - $values = array_values($matches); - foreach ($var as $key => $val){ - if(0 === strpos($val, ':')) { - $var[$key] = $values[substr($val, 1) - 1]; - } - } - $var = array_merge($matches, $var); - // 解析剩余的URL参数 - if(!empty($paths)) { - preg_replace_callback('/(\w+)\/([^\/]+)/', function($match) use(&$var){ - $var[strtolower($match[1])] = strip_tags($match[2]); - }, implode('/',$paths)); - } - // 解析路由自动传人参数 - if(is_array($route) && isset($route[1])) { - parse_str($route[1], $params); - $var = array_merge($var, $params); - } - $_GET = array_merge($var, $_GET); - } - } - - // 解析正则路由 - // '路由正则'=>'[控制器/操作]?参数1=值1&参数2=值2...' - // '路由正则'=>array('[控制器/操作]?参数1=值1&参数2=值2...','额外参数1=值1&额外参数2=值2...') - // '路由正则'=>'外部地址' - // '路由正则'=>array('外部地址','重定向代码') - // 参数值和外部地址中可以用动态变量 采用 :1 :2 的方式 - // '/new\/(\d+)\/(\d+)/'=>array('News/read?id=:1&page=:2&cate=1','status=1'), - // '/new\/(\d+)/'=>array('/new.php?id=:1&page=:2&status=1','301'), 重定向 - static private function parseRegex($matches, $route, $regx,$config) { - // 获取路由地址规则 - $url = is_array($route) ? $route[0] : $route; - $url = preg_replace('/:(\d+)/e', '$matches[\\1]', $url); - if(0 === strpos($url, '/') || 0 === strpos($url, 'http')) { // 路由重定向跳转 - header("Location: $url", true, (is_array($route) && isset($route[1])) ? $route[1] : 301); - exit; - }else{ - // 解析路由地址 - $var = self::parseRoute($url,$config); - // 解析剩余的URL参数 - $regx = substr_replace($regx, '', 0, strlen($matches[0])); - if($regx) { - preg_replace_callback('/(\w+)\/([^\/]+)/', function($match) use(&$var){ - $var[strtolower($match[1])] = strip_tags($match[2]); - }, $regx); - } - // 解析路由自动传人参数 - if(is_array($route) && isset($route[1])) { - parse_str($route[1], $params); - $var = array_merge($var, $params); - } - $_GET = array_merge($var, $_GET); - } - } -} diff --git a/Library/Think/Seesion/Driver.php b/Library/Think/Seesion/Driver.php deleted file mode 100644 index 06e0a38e..00000000 --- a/Library/Think/Seesion/Driver.php +++ /dev/null @@ -1,22 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Session\Driver; -use SessionHandler; - -class Driver extends SessionHandler { - protected $config = []; - - public function __construct($config=[]){ - $this->config = array_merge($this->config,$config); - } - -} diff --git a/Library/Think/Session.php b/Library/Think/Session.php deleted file mode 100644 index 2ab37b94..00000000 --- a/Library/Think/Session.php +++ /dev/null @@ -1,200 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Session { - static protected $prefix = ''; - - /** - * 设置或者获取session作用域(前缀) - * @param string $prefix - * @return string|void - */ - static public function prefix($prefix=''){ - if(empty($prefix)) { - return self::$config['prefix']; - }else{ - self::$config['prefix'] = $prefix; - } - } - - /** - * session初始化 - * @param array $config - * @return void - */ - static public function init($config=[]) { - if(isset($config['prefix'])) - self::$prefix = $config['prefix']; - if(isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])){ - session_id($_REQUEST[$config['var_session_id']]); - }elseif(isset($config['id'])) { - session_id($config['id']); - } - ini_set('session.auto_start', 0); - if(isset($config['name'])) - session_name($config['name']); - if(isset($config['path'])) - session_save_path($config['path']); - if(isset($config['domain'])) - ini_set('session.cookie_domain', $config['domain']); - if(isset($name['expire'])) { - ini_set('session.gc_maxlifetime', $name['expire']); - ini_set('session.cookie_lifetime', $name['expire']); - } - if(isset($config['use_trans_sid'])) - ini_set('session.use_trans_sid', $config['use_trans_sid']?1:0); - if(isset($config['use_cookies'])) - ini_set('session.use_cookies', $config['use_cookies']?1:0); - if(isset($config['cache_limiter'])) - session_cache_limiter($config['cache_limiter']); - if(isset($config['cache_expire'])) - session_cache_expire($config['cache_expire']); - if(!empty($config['type'])) { // 读取session驱动 - $class = 'Think\\Session\\Driver\\'. ucwords(strtolower($config['type'])); - // 检查驱动类 - session_set_save_handler(new $class()); - } - // 启动session - if($config['auto_start']) session_start(); - } - - /** - * session设置 - * @param string $name session名称 - * @param mixed $value session值 - * @param string $prefix 作用域(前缀) - * @return void - */ - static public function set($name,$value='',$prefix='') { - $prefix = $prefix ? $prefix : self::$prefix; - if(strpos($name,'.')){ - // 二维数组赋值 - list($name1,$name2) = explode('.',$name); - if($prefix){ - $_SESSION[$prefix][$name1][$name2] = $value; - }else{ - $_SESSION[$name1][$name2] = $value; - } - }elseif($prefix){ - $_SESSION[$prefix][$name] = $value; - }else{ - $_SESSION[$name] = $value; - } - } - - /** - * session获取 - * @param string $name session名称 - * @param string $prefix 作用域(前缀) - * @return mixed - */ - static public function get($name='',$prefix='') { - $prefix = $prefix ? $prefix : self::$prefix; - if(''==$name){ - // 获取全部的session - $value = $prefix ? $_SESSION[$prefix] : $_SESSION; - }elseif($prefix){ // 获取session - if(strpos($name,'.')){ - list($name1,$name2) = explode('.',$name); - $value = isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null; - }else{ - $value = isset($_SESSION[$prefix][$name]) ? $_SESSION[$prefix][$name] : null; - } - }else{ - if(strpos($name,'.')){ - list($name1,$name2) = explode('.',$name); - $value = isset($_SESSION[$name1][$name2]) ? $_SESSION[$name1][$name2] : null; - }else{ - $value = isset($_SESSION[$name]) ? $_SESSION[$name] : null; - } - } - return $value; - } - - /** - * 删除session数据 - * @param string $name session名称 - * @param string $prefix 作用域(前缀) - * @return void - */ - static public function delete($name,$prefix='') { - $prefix = $prefix?$prefix:$this->prefix; - if(strpos($name,'.')){ - list($name1,$name2) = explode('.',$name); - if($prefix){ - unset($_SESSION[$prefix][$name1][$name2]); - }else{ - unset($_SESSION[$name1][$name2]); - } - }else{ - if($prefix){ - unset($_SESSION[$prefix][$name]); - }else{ - unset($_SESSION[$name]); - } - } - } - - /** - * 清空session数据 - * @param string $prefix 作用域(前缀) - * @return void - */ - static public function clear($prefix='') { - $prefix = $prefix?$prefix:self::$prefix; - if($prefix) { - unset($_SESSION[$prefix]); - }else{ - $_SESSION = []; - } - } - - /** - * 判断session数据 - * @param string $name session名称 - * @param mixed $value session值 - * @return boolean - */ - static public function has($name,$prefix='') { - $prefix = $prefix ? $prefix : self::$prefix; - if(strpos($name,'.')){ // 支持数组 - list($name1,$name2) = explode('.',$name); - return $prefix ? isset($_SESSION[$prefix][$name1][$name2]) : isset($_SESSION[$name1][$name2]); - }else{ - return $prefix ? isset($_SESSION[$prefix][$name]) : isset($_SESSION[$name]); - } - } - - /** - * session管理 - * @param string $name session操作名称 - * @return void - */ - static private function operate($name) { - if('pause'==$name){ // 暂停session - session_write_close(); - }elseif('start'==$name){ // 启动session - session_start(); - }elseif('destroy'==$name){ // 销毁session - $_SESSION = []; - session_unset(); - session_destroy(); - }elseif('regenerate'==$name){ // 重新生成id - session_regenerate_id(); - } - } - - static public function __callStatic($name,$args) { - self::operate($name); - } -} diff --git a/Library/Think/Storage.php b/Library/Think/Storage.php deleted file mode 100644 index aa62e677..00000000 --- a/Library/Think/Storage.php +++ /dev/null @@ -1,40 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace Think; -// 分布式文件存储类 -class Storage { - - /** - * 操作句柄 - * @var string - * @access protected - */ - static protected $handler; - - /** - * 连接分布式文件系统 - * @access public - * @param string $type 文件类型 - * @param array $options 配置数组 - * @return void - */ - static public function connect($type='File',$options=array()) { - $class = 'Think\\Storage\\Driver\\'.ucwords($type); - self::$handler = new $class($options); - } - - static public function __callstatic($method,$args){ - //调用缓存驱动的方法 - if(method_exists(self::$handler, $method)){ - return call_user_func_array(array(self::$handler,$method), $args); - } - } -} diff --git a/Library/Think/Storage/Driver/File.php b/Library/Think/Storage/Driver/File.php deleted file mode 100644 index cc8a0333..00000000 --- a/Library/Think/Storage/Driver/File.php +++ /dev/null @@ -1,125 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace Think\Storage\Driver; -use Think\Storage; -// 本地文件写入存储类 -class File extends Storage{ - - private $contents=array(); - - /** - * 架构函数 - * @access public - */ - public function __construct() { - } - - /** - * 文件内容读取 - * @access public - * @param string $filename 文件名 - * @return string - */ - public function read($filename,$type=''){ - return $this->get($filename,'content',$type); - } - - /** - * 文件写入 - * @access public - * @param string $filename 文件名 - * @param string $content 文件内容 - * @return boolean - */ - public function put($filename,$content,$type=''){ - $dir = dirname($filename); - if(!is_dir($dir)){ - mkdir($dir,0777,true); - } - if(false === file_put_contents($filename,$content)){ - E(L('_STORAGE_WRITE_ERROR_').':'.$filename); - }else{ - $this->contents[$filename]=$content; - return true; - } - } - - /** - * 文件追加写入 - * @access public - * @param string $filename 文件名 - * @param string $content 追加的文件内容 - * @return boolean - */ - public function append($filename,$content,$type=''){ - if(is_file($filename)){ - $content = $this->read($filename,$type).$content; - } - return $this->put($filename,$content,$type); - } - - /** - * 加载文件 - * @access public - * @param string $filename 文件名 - * @param array $vars 传入变量 - * @return void - */ - public function load($_filename,$vars=null){ - if(!is_null($vars)){ - extract($vars, EXTR_OVERWRITE); - } - include $_filename; - } - - /** - * 文件是否存在 - * @access public - * @param string $filename 文件名 - * @return boolean - */ - public function has($filename,$type=''){ - return is_file($filename); - } - - /** - * 文件删除 - * @access public - * @param string $filename 文件名 - * @return boolean - */ - public function unlink($filename,$type=''){ - unset($this->contents[$filename]); - return is_file($filename) ? unlink($filename) : false; - } - - /** - * 读取文件信息 - * @access public - * @param string $filename 文件名 - * @param string $name 信息名 mtime或者content - * @return boolean - */ - public function get($filename,$name,$type=''){ - if(!isset($this->contents[$filename])){ - if(!is_file($filename)) { - return false; - } - $this->contents[$filename] = file_get_contents($filename); - } - $content=$this->contents[$filename]; - $info = array( - 'mtime' => filemtime($filename), - 'content' => $content - ); - return $info[$name]; - } -} diff --git a/Library/Think/Storage/Driver/Sae.php b/Library/Think/Storage/Driver/Sae.php deleted file mode 100644 index 98970081..00000000 --- a/Library/Think/Storage/Driver/Sae.php +++ /dev/null @@ -1,194 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace Think\Storage\Driver; -use Think\Storage; -// SAE环境文件写入存储类 -class Sae extends Storage{ - - /** - * 架构函数 - * @access public - */ - private $mc; - private $kvs = array(); - private $htmls = array(); - private $contents = array(); - public function __construct() { - if(!function_exists('memcache_init')){ - header('Content-Type:text/html;charset=utf-8'); - exit('请在SAE平台上运行代码。'); - } - $this->mc = @memcache_init(); - if(!$this->mc){ - header('Content-Type:text/html;charset=utf-8'); - exit('您未开通Memcache服务,请在SAE管理平台初始化Memcache服务'); - } - } - - /** - * 获得SaeKv对象 - */ - private function getKv(){ - static $kv; - if(!$kv){ - $kv = new \SaeKV(); - if(!$kv->init()) - E('您没有初始化KVDB,请在SAE管理平台初始化KVDB服务'); - } - return $kv; - } - - - /** - * 文件内容读取 - * @access public - * @param string $filename 文件名 - * @return string - */ - public function read($filename,$type=''){ - switch(strtolower($type)){ - case 'f': - $kv = $this->getKv(); - if(!isset($this->kvs[$filename])){ - $this->kvs[$filename]=$kv->get($filename); - } - return $this->kvs[$filename]; - default: - return $this->get($filename,'content',$type); - } - } - - /** - * 文件写入 - * @access public - * @param string $filename 文件名 - * @param string $content 文件内容 - * @return boolean - */ - public function put($filename,$content,$type=''){ - switch(strtolower($type)){ - case 'f': - $kv = $this->getKv(); - $this->kvs[$filename] = $content; - return $kv->set($filename,$content); - case 'html': - $kv = $this->getKv(); - $content = time().$content; - $this->htmls[$filename] = $content; - return $kv->set($filename,$content); - default: - $content = time().$content; - if(!$this->mc->set($filename,$content,MEMCACHE_COMPRESSED,0)){ - E(L('_STORAGE_WRITE_ERROR_').':'.$filename); - }else{ - $this->contents[$filename] = $content; - return true; - } - } - } - - /** - * 文件追加写入 - * @access public - * @param string $filename 文件名 - * @param string $content 追加的文件内容 - * @return boolean - */ - public function append($filename,$content,$type=''){ - if($old_content = $this->read($filename,$type)){ - $content = $old_content.$content; - } - return $this->put($filename,$content,$type); - } - - /** - * 加载文件 - * @access public - * @param string $_filename 文件名 - * @param array $vars 传入变量 - * @return void - */ - public function load($_filename,$vars=null){ - if(!is_null($vars)){ - extract($vars, EXTR_OVERWRITE); - } - eval('?>'.$this->read($_filename)); - } - - /** - * 文件是否存在 - * @access public - * @param string $filename 文件名 - * @return boolean - */ - public function has($filename,$type=''){ - if($this->read($filename,$type)){ - return true; - }else{ - return false; - } - } - - /** - * 文件删除 - * @access public - * @param string $filename 文件名 - * @return boolean - */ - public function unlink($filename,$type=''){ - switch(strtolower($type)){ - case 'f': - $kv = $this->getKv(); - unset($this->kvs[$filename]); - return $kv->delete($filename); - case 'html': - $kv = $this->getKv(); - unset($this->htmls[$filename]); - return $kv->delete($filename); - default: - unset($this->contents[$filename]); - return $this->mc->delete($filename); - } - } - - /** - * 读取文件信息 - * @access public - * @param string $filename 文件名 - * @param string $name 信息名 mtime或者content - * @return boolean - */ - public function get($filename,$name,$type=''){ - switch(strtolower($type)){ - case 'html': - if(!isset($this->htmls[$filename])){ - $kv = $this->getKv(); - $this->htmls[$filename] = $kv->get($filename); - } - $content = $this->htmls[$filename]; - break; - default: - if(!isset($this->contents[$filename])){ - $this->contents[$filename] = $this->mc->get($filename); - } - $content = $this->contents[$filename]; - } - if(false===$content){ - return false; - } - $info = array( - 'mtime' => substr($content,0,10), - 'content' => substr($content,10) - ); - return $info[$name]; - } - -} \ No newline at end of file diff --git a/Library/Think/Template.php b/Library/Think/Template.php deleted file mode 100644 index c9a7e679..00000000 --- a/Library/Think/Template.php +++ /dev/null @@ -1,743 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -/** - * ThinkPHP分离出来的模板引擎 - * 支持XML标签和普通标签的模板解析 - * 编译型模板引擎 支持动态缓存 - */ -class Template { - protected $data = []; // 模板变量 - protected $config = [ // 引擎配置 - 'tpl_path' => VIEW_PATH, // 模板路径 - 'tpl_suffix' => '.html', // 默认模板文件后缀 - 'cache_suffix' => '.php', // 默认模板缓存后缀 - 'tpl_deny_func_list' => 'echo,exit', // 模板引擎禁用函数 - 'tpl_deny_php' => false, // 默认模板引擎是否禁用PHP原生代码 - 'tpl_begin' => '{', // 模板引擎普通标签开始标记 - 'tpl_end' => '}', // 模板引擎普通标签结束标记 - 'strip_space' => false, // 是否去除模板文件里面的html空格与换行 - 'tpl_cache' => true, // 是否开启模板编译缓存,设为false则每次都会重新编译 - 'compile_type' => 'file', // 模板编译类型 - 'cache_path' => CACHE_PATH, // 模板缓存目录 - 'cache_prefix' => '', // 模板缓存前缀标识,可以动态改变 - 'cache_time' => 0, // 模板缓存有效期 0 为永久,(以数字为值,单位:秒) - 'layout_item' => '{__CONTENT__}', // 布局模板的内容替换标识 - 'taglib_begin' => '<', // 标签库标签开始标记 - 'taglib_end' => '>', // 标签库标签结束标记 - 'taglib_load' => true, // 是否使用内置标签库之外的其它标签库,默认自动检测 - 'taglib_build_in' => 'cx', // 内置标签库名称(标签使用不必指定标签库名称),以逗号分隔 注意解析顺序 - 'taglib_pre_load' => '', // 需要额外加载的标签库(须指定标签库名称),多个以逗号分隔 - 'display_cache' => false, // 模板渲染缓存 - ]; - - private $literal = []; - private $block = []; - protected $storage = null; - - /** - * 架构函数 - * @access public - */ - public function __construct($config=[]){ - if(!empty($config)) { - $this->config = array_merge($this->config,$config); - } - $this->config['taglib_begin'] = $this->stripPreg($this->config['taglib_begin']); - $this->config['taglib_end'] = $this->stripPreg($this->config['taglib_end']); - $this->config['tpl_begin'] = $this->stripPreg($this->config['tpl_begin']); - $this->config['tpl_end'] = $this->stripPreg($this->config['tpl_end']); - - // 初始化模板编译存储器 - $type = $this->config['compile_type']?$this->config['compile_type']:'File'; - $class = '\Think\Template\Driver\\'.ucwords($type); - $this->storage = new $class(); - } - - /** - * 字符串替换 避免正则混淆 - * @access private - * @param string $str - */ - private function stripPreg($str) { - return str_replace( - ['{','}','(',')','|','[',']','-','+','*','.','^','?'], - ['\{','\}','\(','\)','\|','\[','\]','\-','\+','\*','\.','\^','\?'], - $str); - } - - /** - * 模板变量赋值 - * @access public - * @param mixed $name - * @param mixed $value - */ - public function assign($name,$value=''){ - if(is_array($name)) { - $this->data = array_merge($this->data,$name); - }else { - $this->data[$name] = $value; - } - } - - /** - * 模板引擎参数赋值 - * @access public - * @param mixed $name - * @param mixed $value - */ - public function __set($name,$value){ - $this->config[$name] = $value; - } - - public function config($config){ - $this->config = array_merge($this->config,$config); - } - - public function get($name){ - return $this->data[$name]; - } - - /** - * 渲染模板文件 - * @access public - * @param string $template 模板文件 - * @param array $vars 模板变量 - * @param array $config 模板参数 - * @return void - */ - public function display($template,$vars=[],$config=[]) { - if($vars){ - $this->data = $vars; - } - if($config){ - $this->config($config); - } - $template = $this->parseTemplateFile($template); - $cacheFile = $this->config['cache_path'].$this->config['cache_prefix'].md5($template).$this->config['cache_suffix']; - if(!$this->checkCache($template,$cacheFile)) { // 缓存无效 - // 模板编译 - $this->compiler(file_get_contents($template),$cacheFile); - } - // 页面缓存 - ob_start(); - ob_implicit_flush(0); - // 读取编译存储 - $this->storage->read($cacheFile,$this->data); - // 获取并清空缓存 - $content = ob_get_clean(); - if($this->config['cache_id'] && $this->config['display_cache']) { - // 缓存页面输出 - Cache::set($this->config['cache_id'],$content,$this->config['cache_time']); - } - echo $content; - } - - /** - * 渲染模板内容 - * @access public - * @param string $content 模板内容 - * @param array $vars 模板变量 - * @return void - */ - public function fetch($content,$vars=[]) { - if($vars){ - $this->data = $vars; - } - $cacheFile = $this->config['cache_path'].$this->config['cache_prefix'].md5($content).$this->config['cache_suffix']; - if(!$this->checkCache($content,$cacheFile)) { // 缓存无效 - // 模板编译 - $this->compiler($content,$cacheFile); - } - // 读取编译存储 - $this->storage->read($cacheFile,$this->data); - } - - /** - * 检查编译缓存是否有效 - * 如果无效则需要重新编译 - * @access private - * @param string $template 模板文件名 - * @param string $cacheFile 缓存文件名 - * @return boolen - */ - private function checkCache($template,$cacheFile) { - if (!$this->config['tpl_cache']) // 优先对配置设定检测 - return false; - // 检查编译存储是否有效 - return $this->storage->check($template,$cacheFile,$this->config['cache_time']); - } - - public function isCache($cacheId){ - if($cacheId && $this->config['display_cache']) { - // 缓存页面输出 - return Cache::get($cacheId)?true:false; - } - return null; - } - - /** - * 编译模板文件内容 - * @access private - * @param string $content 模板内容 - * @param string $cacheFile 缓存文件名 - * @return void - */ - private function compiler($content,$cacheFile) { - // 模板解析 - $content = $this->parse($content); - // 还原被替换的Literal标签 - $content = preg_replace('//eis',"\$this->restoreLiteral('\\1')",$content); - // 添加安全代码 - $content = ''.$content; - if($this->config['strip_space']) { - /* 去除html空格与换行 */ - $find = ['~>\s+<~','~>(\s+\n|\r)~']; - $replace = ['><','>']; - $content = preg_replace($find, $replace, $content); - } - // 优化生成的php代码 - $content = str_replace('?>storage->write($cacheFile,$content); - return ; - } - - /** - * 模板解析入口 - * 支持普通标签和TagLib解析 支持自定义标签库 - * @access public - * @param string $content 要解析的模板内容 - * @return string - */ - public function parse($content) { - // 内容为空不解析 - if(empty($content)) return ''; - $begin = $this->config['taglib_begin']; - $end = $this->config['taglib_end']; - // 检查include语法 - $content = $this->parseInclude($content); - // 检查PHP语法 - $content = $this->parsePhp($content); - // 首先替换literal标签内容 - $content = preg_replace('/'.$begin.'literal'.$end.'(.*?)'.$begin.'\/literal'.$end.'/eis',"\$this->parseLiteral('\\1')",$content); - - // 获取需要引入的标签库列表 - // 标签库只需要定义一次,允许引入多个一次 - // 一般放在文件的最前面 - // 格式: - // 当TAGLIB_LOAD配置为true时才会进行检测 - if($this->config['taglib_load']) { - $tagLibs = $this->getIncludeTagLib($content); - if(!empty($tagLibs)) { - // 对导入的TagLib进行解析 - foreach($tagLibs as $tagLibName) { - $this->parseTagLib($tagLibName,$content); - } - } - } - // 预先加载的标签库 无需在每个模板中使用taglib标签加载 但必须使用标签库XML前缀 - if($this->config['taglib_pre_load']) { - $tagLibs = explode(',',$this->config['taglib_pre_load']); - foreach ($tagLibs as $tag){ - $this->parseTagLib($tag,$content); - } - } - // 内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀 - $tagLibs = explode(',',$this->config['taglib_build_in']); - foreach ($tagLibs as $tag){ - $this->parseTagLib($tag,$content,true); - } - // 解析普通模板标签 {tagName} - $content = preg_replace('/('.$this->config['tpl_begin'].')([^\d\s'.$this->config['tpl_begin'].$this->config['tpl_end'].'].+?)('.$this->config['tpl_end'].')/eis',"\$this->parseTag('\\2','\\0')",$content); - return $content; - } - - // 检查PHP语法 - private function parsePhp($content) { - if(ini_get('short_open_tag')){ - // 开启短标签的情况要将'."\n", $content ); - } - // PHP语法检查 - if($this->config['tpl_deny_php'] && false !== strpos($content,'parseExtend($content); - // 解析布局 - $content = $this->parseLayout($content); - // 读取模板中的include标签 - $find = preg_match_all('/'.$this->config['taglib_begin'].'include\s(.+?)\s*?\/'.$this->config['taglib_end'].'/is',$content,$matches); - if($find) { - for($i=0;$i<$find;$i++) { - $include = $matches[1][$i]; - $array = $this->parseXmlAttrs($include); - $file = $array['file']; - unset($array['file']); - $content = str_replace($matches[0][$i],$this->parseIncludeItem($file,$array),$content); - } - } - return $content; - } - - // 解析模板中的布局标签 - private function parseLayout($content) { - // 读取模板中的布局标签 - $find = preg_match('/'.$this->config['taglib_begin'].'layout\s(.+?)\s*?\/'.$this->config['taglib_end'].'/is',$content,$matches); - if($find) { - //替换Layout标签 - $content = str_replace($matches[0],'',$content); - //解析Layout标签 - $array = $this->parseXmlAttrs($matches[1]); - // 读取布局模板 - $layoutFile = $this->config['tpl_path'].$array['name'].$this->config['tpl_suffix']; - $replace = isset($array['replace'])?$array['replace']:$this->config['layout_item']; - // 替换布局的主体内容 - $content = str_replace($replace,$content,file_get_contents($layoutFile)); - }else{ - $content = str_replace('{__NOLAYOUT__}','',$content); - } - return $content; - } - - // 解析模板中的extend标签 - private function parseExtend($content) { - $begin = $this->config['taglib_begin']; - $end = $this->config['taglib_end']; - // 读取模板中的继承标签 - $find = preg_match('/'.$begin.'extend\s(.+?)\s*?\/'.$end.'/is',$content,$matches); - if($find) { - //替换extend标签 - $content = str_replace($matches[0],'',$content); - // 记录页面中的block标签 - preg_replace('/'.$begin.'block\sname=(.+?)\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/eis',"\$this->parseBlock('\\1','\\2')",$content); - // 读取继承模板 - $array = $this->parseXmlAttrs($matches[1]); - $content = $this->parseTemplateName($array['name']); - // 替换block标签 - $content = preg_replace('/'.$begin.'block\sname=(.+?)\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/eis',"\$this->replaceBlock('\\1','\\2')",$content); - }else{ - $content = preg_replace('/'.$begin.'block\sname=(.+?)\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/eis',"stripslashes('\\2')",$content); - } - return $content; - } - - /** - * 分析XML属性 - * @access private - * @param string $attrs XML属性字符串 - * @return array - */ - private function parseXmlAttrs($attrs) { - $xml = ''; - $xml = simplexml_load_string($xml); - if(!$xml) - exit('_XML_TAG_ERROR_'); - $xml = (array)($xml->tag->attributes()); - $array = array_change_key_case($xml['@attributes']); - return $array; - } - - /** - * 替换页面中的literal标签 - * @access private - * @param string $content 模板内容 - * @return string - */ - private function parseLiteral($content) { - if(trim($content)=='') return ''; - $content = stripslashes($content); - $i = count($this->literal); - $parseStr = ""; - $this->literal[$i] = $content; - return $parseStr; - } - - /** - * 还原被替换的literal标签 - * @access private - * @param string $tag literal标签序号 - * @return string - */ - private function restoreLiteral($tag) { - // 还原literal标签 - $parseStr = $this->literal[$tag]; - // 销毁literal记录 - unset($this->literal[$tag]); - return $parseStr; - } - - /** - * 记录当前页面中的block标签 - * @access private - * @param string $name block名称 - * @param string $content 模板内容 - * @return string - */ - private function parseBlock($name,$content) { - $this->block[$name] = $content; - return ''; - } - - /** - * 替换继承模板中的block标签 - * @access private - * @param string $name block名称 - * @param string $content 模板内容 - * @return string - */ - private function replaceBlock($name,$content) { - // 替换block标签 没有重新定义则使用原来的 - $replace = isset($this->block[$name])? $this->block[$name] : $content; - return stripslashes($replace); - } - - /** - * 搜索模板页面中包含的TagLib库 - * 并返回列表 - * @access private - * @param string $content 模板内容 - * @return array - */ - private function getIncludeTagLib(& $content) { - //搜索是否有TagLib标签 - $find = preg_match('/'.$this->config['taglib_begin'].'taglib\s(.+?)(\s*?)\/'.$this->config['taglib_end'].'\W/is',$content,$matches); - if($find) { - //替换TagLib标签 - $content = str_replace($matches[0],'',$content); - //解析TagLib标签 - $array = $this->parseXmlAttrs($matches[1]); - return explode(',',$array['name']); - } - return []; - } - - /** - * TagLib库解析 - * @access private - * @param string $tagLib 要解析的标签库 - * @param string $content 要解析的模板内容 - * @param boolen $hide 是否隐藏标签库前缀 - * @return void - */ - protected function parseTagLib($tagLib,&$content,$hide=false) { - $begin = $this->config['taglib_begin']; - $end = $this->config['taglib_end']; - $className = '\\Think\\Template\\Taglib\\'.ucwords($tagLib); - $tLib = new $className($this); - foreach ($tLib->getTags() as $name=>$val){ - $tags = [$name]; - if(isset($val['alias'])) {// 别名设置 - $tags = explode(',',$val['alias']); - $tags[] = $name; - } - $level = isset($val['level'])?$val['level']:1; - $closeTag = isset($val['close'])?$val['close']:true; - foreach ($tags as $tag){ - $parseTag = !$hide? $tagLib.':'.$tag: $tag;// 实际要解析的标签名称 - if(!method_exists($tLib,'_'.$tag)) { - // 别名可以无需定义解析方法 - $tag = $name; - } - $n1 = empty($val['attr'])?'(\s*?)':'\s([^'.$end.']*)'; - if (!$closeTag){ - $patterns = '/'.$begin.$parseTag.$n1.'\/(\s*?)'.$end.'/eis'; - $replacement = "\$this->parseXmlTag(\$tLib,'$tagLib','$tag','$1','')"; - $content = preg_replace($patterns, $replacement,$content); - }else{ - $patterns = '/'.$begin.$parseTag.$n1.$end.'(.*?)'.$begin.'\/'.$parseTag.'(\s*?)'.$end.'/eis'; - $replacement = "\$this->parseXmlTag(\$tLib,'$tagLib','$tag','$1','$2')"; - for($i=0;$i<$level;$i++) - $content=preg_replace($patterns,$replacement,$content); - } - } - } - } - - /** - * 解析标签库的标签 - * 需要调用对应的标签库文件解析类 - * @access private - * @param object $tLib 模板引擎实例 - * @param string $tagLib 标签库名称 - * @param string $tag 标签名 - * @param string $attr 标签属性 - * @param string $content 标签内容 - * @return string - */ - private function parseXmlTag($tLib,$tagLib,$tag,$attr,$content) { - $attr = stripslashes($attr); - $content= stripslashes($content); - if(ini_get('magic_quotes_sybase')) - $attr = str_replace('\"','\'',$attr); - $parse = '_'.$tag; - $content = trim($content); - $tags = $tLib->parseXmlAttr($attr,$tag); - $tLib->tpl = $this; - return $tLib->$parse($tags,$content); - } - - /** - * 模板标签解析 - * 格式: {TagName:args [|content] } - * @access private - * @param string $tagStr 标签内容 - * @param string $content 原始内容 - * @return string - */ - private function parseTag($tagStr,$content){ - $tagStr = stripslashes($tagStr); - - //还原非模板标签 - if(!preg_match('/^[\s|\d]/is',$tagStr)){ - $flag = substr($tagStr,0,1); - $flag2 = substr($tagStr,1,1); - $name = substr($tagStr,1); - if('$' == $flag && '.' != $flag2 && '(' != $flag2){ //解析模板变量 格式 {$varName} - return $this->parseVar($name); - }elseif('-' == $flag || '+'== $flag){ // 输出计算 - return ''; - }elseif(':' == $flag){ // 输出某个函数的结果 - return ''; - }elseif('~' == $flag){ // 执行某个函数 - return ''; - }elseif(substr($tagStr,0,2)=='//' || (substr($tagStr,0,2)=='/*' && substr($tagStr,-2)=='*/')){ - //注释标签 - return ''; - } - } - // 非法标签直接返回 - return $content; - } - - /** - * 模板变量解析,支持使用函数 - * 格式: {$varname|function1|function2=arg1,arg2} - * @access private - * @param string $varStr 变量数据 - * @return string - */ - private function parseVar($varStr){ - $varStr = trim($varStr); - static $_varParseList = []; - //如果已经解析过该变量字串,则直接返回变量值 - if(isset($_varParseList[$varStr])) return $_varParseList[$varStr]; - $parseStr = ''; - if(!empty($varStr)){ - $varArray = explode('|',$varStr); - //取得变量名称 - $var = array_shift($varArray); - if('Think.' == substr($var,0,6)){ - // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出 - $name = $this->parseThinkVar($var); - }elseif( false !== strpos($var,'.')) { - //支持 {$var.property} - $vars = explode('.',$var); - $var = array_shift($vars); - $name = '$'.$var; - foreach ($vars as $key=>$val) - $name .= '["'.$val.'"]'; - }elseif(false !== strpos($var,'[')) { - //支持 {$var['key']} 方式输出数组 - $name = "$".$var; - }elseif(false !==strpos($var,':') && false ===strpos($var,'(') && false ===strpos($var,'::') && false ===strpos($var,'?')){ - //支持 {$var:property} 方式输出对象的属性 - $vars = explode(':',$var); - $var = str_replace(':','->',$var); - $name = "$".$var; - }else { - $name = "$$var"; - } - //对变量使用函数 - if(count($varArray)>0) - $name = $this->parseVarFunction($name,$varArray); - $parseStr = ''; - } - $_varParseList[$varStr] = $parseStr; - return $parseStr; - } - - /** - * 对模板变量使用函数 - * 格式 {$varname|function1|function2=arg1,arg2} - * @access private - * @param string $name 变量名 - * @param array $varArray 函数列表 - * @return string - */ - private function parseVarFunction($name,$varArray){ - //对变量使用函数 - $length = count($varArray); - //取得模板禁止使用函数列表 - $template_deny_funs = explode(',',$this->config['tpl_deny_func_list']); - for($i=0;$i<$length ;$i++ ){ - $args = explode('=',$varArray[$i],2); - //模板函数过滤 - $fun = strtolower(trim($args[0])); - switch($fun) { - case 'default': // 特殊模板函数 - $name = '('.$name.')?('.$name.'):'.$args[1]; - break; - default: // 通用模板函数 - if(!in_array($fun,$template_deny_funs)){ - if(isset($args[1])){ - if(strstr($args[1],'###')){ - $args[1] = str_replace('###',$name,$args[1]); - $name = "$fun($args[1])"; - }else{ - $name = "$fun($name,$args[1])"; - } - }else if(!empty($args[0])){ - $name = "$fun($name)"; - } - } - } - } - return $name; - } - - /** - * 特殊模板变量解析 - * 格式 以 $Think. 打头的变量属于特殊模板变量 - * @access private - * @param string $varStr 变量字符串 - * @return string - */ - private function parseThinkVar($varStr){ - $vars = explode('.',$varStr); - $vars[1] = strtoupper(trim($vars[1])); - $parseStr = ''; - if(count($vars)>=3){ - $vars[2] = trim($vars[2]); - switch($vars[1]){ - case 'SERVER': - $parseStr = '$_SERVER[\''.strtoupper($vars[2]).'\']'; - break; - case 'GET': - $parseStr = '$_GET[\''.$vars[2].'\']'; - break; - case 'POST': - $parseStr = '$_POST[\''.$vars[2].'\']'; - break; - case 'COOKIE': - if(isset($vars[3])) { - $parseStr = '$_COOKIE[\''.$vars[2].'\'][\''.$vars[3].'\']'; - }else{ - $parseStr = 'cookie(\''.$vars[2].'\')'; - } - break; - case 'SESSION': - if(isset($vars[3])) { - $parseStr = '$_SESSION[\''.$vars[2].'\'][\''.$vars[3].'\']'; - }else{ - $parseStr = 'session(\''.$vars[2].'\')'; - } - break; - case 'ENV': - $parseStr = '$_ENV[\''.strtoupper($vars[2]).'\']'; - break; - case 'REQUEST': - $parseStr = '$_REQUEST[\''.$vars[2].'\']'; - break; - case 'CONST': - $parseStr = strtoupper($vars[2]); - break; - case 'LANG': - $parseStr = 'L("'.$vars[2].'")'; - break; - case 'CONFIG': - if(isset($vars[3])) { - $vars[2] .= '.'.$vars[3]; - } - $parseStr = 'C("'.$vars[2].'")'; - break; - default: - break; - } - }else if(count($vars)==2){ - switch($vars[1]){ - case 'NOW': - $parseStr = "date('Y-m-d g:i a',time())"; - break; - case 'VERSION': - $parseStr = 'THINK_TEMPLATE_VERSION'; - break; - case 'LDELIM': - $parseStr = $this->config['tpl_begin']; - break; - case 'RDELIM': - $parseStr = $this->config['tpl_end']; - break; - default: - if(defined($vars[1])){ - $parseStr = $vars[1]; - } - } - } - return $parseStr; - } - - /** - * 加载公共模板并缓存 和当前模板在同一路径,否则使用相对路径 - * @access private - * @param string $tmplPublicName 公共模板文件名 - * @param array $vars 要传递的变量列表 - * @return string - */ - private function parseIncludeItem($tmplPublicName,$vars=[]){ - // 分析模板文件名并读取内容 - $parseStr = $this->parseTemplateName($tmplPublicName); - // 替换变量 - foreach ($vars as $key=>$val) { - if(strpos($val,'['.$key.']')) { - $parseStr = str_replace('['.$key.']',$val,$parseStr); - } - } - // 再次对包含文件进行模板分析 - return $this->parseInclude($parseStr); - } - - /** - * 分析加载的模板文件并读取内容 支持多个模板文件读取 - * @access private - * @param string $tmplPublicName 模板文件名 - * @return string - */ - private function parseTemplateName($templateName){ - if(substr($templateName,0,1)=='$') - //支持加载变量文件名 - $templateName = $this->get(substr($templateName,1)); - $array = explode(',',$templateName); - $parseStr = ''; - foreach ($array as $templateName){ - $template = $this->parseTemplateFile($templateName); - // 获取模板文件内容 - $parseStr .= file_get_contents($template); - } - return $parseStr; - } - - private function parseTemplateFile($template) { - if(false === strpos($template,'.')) { - return $this->config['tpl_path'].$template.$this->config['tpl_suffix']; - }else{ - return $template; - } - } -} diff --git a/Library/Think/Template/Driver/File.php b/Library/Think/Template/Driver/File.php deleted file mode 100644 index 09c9de4f..00000000 --- a/Library/Think/Template/Driver/File.php +++ /dev/null @@ -1,48 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Template\Driver; -use Think\Exception; - -class File { - // 写入编译缓存 - public function write($cacheFile,$content){ - // 检测模板目录 - $dir = dirname($cacheFile); - if(!is_dir($dir)){ - mkdir($dir,0777,true); - } - // 生成模板缓存文件 - if( false === file_put_contents($cacheFile,$content)){ - throw new Exception('_CACHE_WRITE_ERROR_:'.$cacheFile); - } - } - - // 读取编译编译 - public function read($cacheFile,$vars){ - // 模板阵列变量分解成为独立变量 - extract($vars, EXTR_OVERWRITE); - //载入模版缓存文件 - include $cacheFile; - } - - // 检查编译缓存是否有效 - public function check($template,$cacheFile,$cacheTime){ - if(!is_file($cacheFile)|| (is_file($template) && filemtime($template) > filemtime($cacheFile))) { - // 模板文件如果有更新则缓存需要更新 - return false; - }elseif ($cacheTime != 0 && time() > filemtime($cacheFile)+$cacheTime) { - // 缓存是否在有效期 - return false; - } - return true; - } -} diff --git a/Library/Think/Template/TagLib.php b/Library/Think/Template/TagLib.php deleted file mode 100644 index d6bf9a6e..00000000 --- a/Library/Think/Template/TagLib.php +++ /dev/null @@ -1,248 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Template; - -/** - * ThinkPHP标签库TagLib解析基类 - * @category Think - * @package Think - * @subpackage Template - * @author liu21st - */ -class TagLib { - - /** - * 标签库定义XML文件 - * @var string - * @access protected - */ - protected $xml = ''; - protected $tags = [];// 标签定义 - /** - * 标签库名称 - * @var string - * @access protected - */ - protected $tagLib =''; - - /** - * 标签库标签列表 - * @var string - * @access protected - */ - protected $tagList = []; - - /** - * 标签库分析数组 - * @var string - * @access protected - */ - protected $parse = []; - - /** - * 标签库是否有效 - * @var string - * @access protected - */ - protected $valid = false; - - /** - * 当前模板对象 - * @var object - * @access protected - */ - protected $tpl; - - protected $comparison = [' nheq '=>' !== ',' heq '=>' === ',' neq '=>' != ',' eq '=>' == ',' egt '=>' >= ',' gt '=>' > ',' elt '=>' <= ',' lt '=>' < ']; - - public function __construct($template){ - $this->tpl = $template; - } - - /** - * TagLib标签属性分析 返回标签属性数组 - * @access public - * @param string $tagStr 标签内容 - * @return array - */ - public function parseXmlAttr($attr,$tag) { - if(''== trim($attr)) { - return []; - } - //XML解析安全过滤 - $attr = str_replace('&','___', $attr); - $xml = ''; - $xml = simplexml_load_string($xml); - if(!$xml) { - exit('_XML_TAG_ERROR_ : '.$attr); - } - $xml = (array)($xml->tag->attributes()); - $array = array_change_key_case($xml['@attributes']); - if($array) { - $tag = strtolower($tag); - if(isset($this->tags[$tag]['attr'])) { - $attrs = explode(',',$this->tags[$tag]['attr']); - if(isset($this->tags[strtolower($tag)]['must'])){ - $must = explode(',',$this->tags[$tag]['must']); - }else{ - $must = []; - } - foreach($attrs as $name) { - if( isset($array[$name])) { - $array[$name] = str_replace('___','&',$array[$name]); - }elseif(false !== array_search($name,$must)){ - exit('_PARAM_ERROR_:'.$name); - } - } - } - return $array; - } - } - - /** - * 解析条件表达式 - * @access public - * @param string $condition 表达式标签内容 - * @return array - */ - public function parseCondition($condition) { - $condition = str_ireplace(array_keys($this->comparison),array_values($this->comparison),$condition); - $condition = preg_replace('/\$(\w+):(\w+)\s/is','$\\1->\\2 ',$condition); - $condition = preg_replace('/\$(\w+)\.(\w+)\s/is','$\\1["\\2"] ',$condition); - - if(false !== strpos($condition, '$Think')) - $condition = preg_replace('/(\$Think.*?)\s/ies',"\$this->parseThinkVar('\\1');" , $condition); - return $condition; - } - - /** - * 自动识别构建变量 - * @access public - * @param string $name 变量描述 - * @return string - */ - public function autoBuildVar($name) { - if('Think.' == substr($name,0,6)){ - // 特殊变量 - return $this->parseThinkVar($name); - }elseif(strpos($name,'.')) { - $vars = explode('.',$name); - $var = array_shift($vars); - $name = '$'.$var; - foreach ($vars as $key=>$val){ - if(0===strpos($val,'$')) { - $name .= '["{'.$val.'}"]'; - }else{ - $name .= '["'.$val.'"]'; - } - } - }elseif(strpos($name,':')){ - // 额外的对象方式支持 - $name = '$'.str_replace(':','->',$name); - }elseif(!defined($name)) { - $name = '$'.$name; - } - return $name; - } - - /** - * 用于标签属性里面的特殊模板变量解析 - * 格式 以 Think. 打头的变量属于特殊模板变量 - * @access public - * @param string $varStr 变量字符串 - * @return string - */ - public function parseThinkVar($varStr){ - $vars = explode('.',$varStr); - $vars[1] = strtoupper(trim($vars[1])); - $parseStr = ''; - if(count($vars)>=3){ - $vars[2] = trim($vars[2]); - switch($vars[1]){ - case 'SERVER': $parseStr = '$_SERVER[\''.$vars[2].'\']';break; - case 'GET': $parseStr = '$_GET[\''.$vars[2].'\']';break; - case 'POST': $parseStr = '$_POST[\''.$vars[2].'\']';break; - case 'COOKIE': - if(isset($vars[3])) { - $parseStr = '$_COOKIE[\''.$vars[2].'\'][\''.$vars[3].'\']'; - }else{ - $parseStr = '$_COOKIE[\''.$vars[2].'\']'; - } - break; - case 'SESSION': - if(isset($vars[3])) { - $parseStr = '$_SESSION[\''.$vars[2].'\'][\''.$vars[3].'\']'; - }else{ - $parseStr = '$_SESSION[\''.$vars[2].'\']'; - } - break; - case 'ENV': $parseStr = '$_ENV[\''.$vars[2].'\']';break; - case 'REQUEST': $parseStr = '$_REQUEST[\''.$vars[2].'\']';break; - case 'CONST': $parseStr = strtoupper($vars[2]);break; - case 'LANG': - $parseStr = 'L("'.$vars[2].'")';break; - case 'CONFIG': - if(isset($vars[3])) { - $vars[2] .= '.'.$vars[3]; - } - $parseStr = 'C("'.$vars[2].'")';break; - } - }else if(count($vars)==2){ - switch($vars[1]){ - case 'NOW': $parseStr = "date('Y-m-d g:i a',time())";break; - case 'VERSION': $parseStr = 'THINK_VERSION';break; - default: if(defined($vars[1])) $parseStr = $vars[1]; - } - } - return $parseStr; - } - - /** - * 对模板变量使用函数 - * 格式 {$varname|function1|function2=arg1,arg2} - * @access protected - * @param string $name 变量名 - * @param array $varArray 函数列表 - * @return string - */ - protected function parseVarFunction($name,$varArray){ - //对变量使用函数 - $length = count($varArray); - for($i=0;$i<$length ;$i++ ){ - $args = explode('=',$varArray[$i],2); - //模板函数过滤 - $fun = strtolower(trim($args[0])); - switch($fun) { - case 'default': // 特殊模板函数 - $name = '('.$name.')?('.$name.'):'.$args[1]; - break; - default: // 通用模板函数 - if(isset($args[1])){ - if(strstr($args[1],'###')){ - $args[1] = str_replace('###',$name,$args[1]); - $name = "$fun($args[1])"; - }else{ - $name = "$fun($name,$args[1])"; - } - }else if(!empty($args[0])){ - $name = "$fun($name)"; - } - } - } - return $name; - } - - // 获取标签定义 - public function getTags(){ - return $this->tags; - } -} diff --git a/Library/Think/Template/TagLib/Cx.php b/Library/Think/Template/TagLib/Cx.php deleted file mode 100644 index fe52c0b0..00000000 --- a/Library/Think/Template/TagLib/Cx.php +++ /dev/null @@ -1,614 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Template\Taglib; -use Think\Template\Taglib; - -/** - * CX标签库解析类 - * @category Think - * @package Think - * @subpackage Driver.Taglib - * @author liu21st - */ -class Cx extends Taglib { - - // 标签定义 - protected $tags = [ - // 标签定义: attr 属性列表 close 是否闭合(0 或者1 默认1) alias 标签别名 level 嵌套层次 - 'php' => [], - 'volist' => ['attr'=>'name,id,offset,length,key,mod','level'=>3,'alias'=>'iterate'], - 'foreach' => ['attr'=>'name,item,key','level'=>3], - 'if' => ['attr'=>'condition','level'=>2], - 'elseif' => ['attr'=>'condition','close'=>0], - 'else' => ['attr'=>'','close'=>0], - 'switch' => ['attr'=>'name','level'=>2], - 'case' => ['attr'=>'value,break'], - 'default' => ['attr'=>'','close'=>0], - 'compare' => ['attr'=>'name,value,type','level'=>3,'alias'=>'eq,equal,notequal,neq,gt,lt,egt,elt,heq,nheq'], - 'range' => ['attr'=>'name,value,type','level'=>3,'alias'=>'in,notin,between,notbetween'], - 'empty' => ['attr'=>'name','level'=>3], - 'notempty' => ['attr'=>'name','level'=>3], - 'present' => ['attr'=>'name','level'=>3], - 'notpresent'=> ['attr'=>'name','level'=>3], - 'defined' => ['attr'=>'name','level'=>3], - 'notdefined'=> ['attr'=>'name','level'=>3], - 'import' => ['attr'=>'file,href,type,value,basepath','close'=>0,'alias'=>'load,css,js'], - 'assign' => ['attr'=>'name,value','close'=>0], - 'define' => ['attr'=>'name,value','close'=>0], - 'for' => ['attr'=>'start,end,name,comparison,step', 'level'=>3], - ]; - - /** - * php标签解析 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _php($tag,$content) { - $parseStr = ''; - return $parseStr; - } - - /** - * volist标签解析 循环输出数据集 - * 格式: - * - * {user.username} - * {user.email} - * - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string|void - */ - public function _volist($tag,$content) { - $name = $tag['name']; - $id = $tag['id']; - $empty = isset($tag['empty'])?$tag['empty']:''; - $key = !empty($tag['key'])?$tag['key']:'i'; - $mod = isset($tag['mod'])?$tag['mod']:'2'; - // 允许使用函数设定数据集 {$vo.name} - $parseStr = 'autoBuildVar($name); - } - $parseStr .= 'if(is_array('.$name.')): $'.$key.' = 0;'; - if(isset($tag['length']) && '' !=$tag['length'] ) { - $parseStr .= ' $__LIST__ = array_slice('.$name.','.$tag['offset'].','.$tag['length'].',true);'; - }elseif(isset($tag['offset']) && '' !=$tag['offset']){ - $parseStr .= ' $__LIST__ = array_slice('.$name.','.$tag['offset'].',null,true);'; - }else{ - $parseStr .= ' $__LIST__ = '.$name.';'; - } - $parseStr .= 'if( count($__LIST__)==0 ) : echo "'.$empty.'" ;'; - $parseStr .= 'else: '; - $parseStr .= 'foreach($__LIST__ as $key=>$'.$id.'): '; - $parseStr .= '$mod = ($'.$key.' % '.$mod.' );'; - $parseStr .= '++$'.$key.';?>'; - $parseStr .= ($content); - $parseStr .= ''; - - if(!empty($parseStr)) { - return $parseStr; - } - return ; - } - - /** - * foreach标签解析 循环输出数据集 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string|void - */ - public function _foreach($tag,$content) { - $name = $tag['name']; - $item = $tag['item']; - $key = !empty($tag['key'])?$tag['key']:'key'; - $name = $this->autoBuildVar($name); - $parseStr = '$'.$item.'): ?>'; - $parseStr .= ($content); - $parseStr .= ''; - if(!empty($parseStr)) { - return $parseStr; - } - return ; - } - - /** - * if标签解析 - * 格式: - * - * - * - * - * 表达式支持 eq neq gt egt lt elt == > >= < <= or and || && - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _if($tag,$content) { - $condition = $this->parseCondition($tag['condition']); - $parseStr = ''.$content.''; - return $parseStr; - } - - /** - * else标签解析 - * 格式:见if标签 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _elseif($tag,$content) { - $condition = $this->parseCondition($tag['condition']); - $parseStr = ''; - return $parseStr; - } - - /** - * else标签解析 - * @access public - * @param array $tag 标签属性 - * @return string - */ - public function _else($tag) { - $parseStr = ''; - return $parseStr; - } - - /** - * switch标签解析 - * 格式: - * - * 1 - * 2 - * other - * - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _switch($tag,$content) { - $name = $tag['name']; - $varArray = explode('|',$name); - $name = array_shift($varArray); - $name = $this->autoBuildVar($name); - if(count($varArray)>0) - $name = $this->parseVarFunction($name,$varArray); - $parseStr = ''.$content.''; - return $parseStr; - } - - /** - * case标签解析 需要配合switch才有效 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _case($tag,$content) { - $value = $tag['value']; - if('$' == substr($value,0,1)) { - $varArray = explode('|',$value); - $value = array_shift($varArray); - $value = $this->autoBuildVar(substr($value,1)); - if(count($varArray)>0) - $value = $this->parseVarFunction($value,$varArray); - $value = 'case '.$value.': '; - }elseif(strpos($value,'|')){ - $values = explode('|',$value); - $value = ''; - foreach ($values as $val){ - $value .= 'case "'.addslashes($val).'": '; - } - }else{ - $value = 'case "'.$value.'": '; - } - $parseStr = ''.$content; - $isBreak = isset($tag['break']) ? $tag['break'] : ''; - if('' ==$isBreak || $isBreak) { - $parseStr .= ''; - } - return $parseStr; - } - - /** - * default标签解析 需要配合switch才有效 - * 使用: ddfdf - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _default($tag) { - $parseStr = ''; - return $parseStr; - } - - /** - * compare标签解析 - * 用于值的比较 支持 eq neq gt lt egt elt heq nheq 默认是eq - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _compare($tag,$content,$type='eq') { - $name = $tag['name']; - $value = $tag['value']; - $type = isset($tag['type'])?$tag['type']:$type; - $type = $this->parseCondition(' '.$type.' '); - $varArray = explode('|',$name); - $name = array_shift($varArray); - $name = $this->autoBuildVar($name); - if(count($varArray)>0) - $name = $this->parseVarFunction($name,$varArray); - if('$' == substr($value,0,1)) { - $value = $this->autoBuildVar(substr($value,1)); - }else { - $value = '"'.$value.'"'; - } - $parseStr = ''.$content.''; - return $parseStr; - } - - public function _eq($tag,$content) { - return $this->_compare($tag,$content,'eq'); - } - - public function _equal($tag,$content) { - return $this->_compare($tag,$content,'eq'); - } - - public function _neq($tag,$content) { - return $this->_compare($tag,$content,'neq'); - } - - public function _notequal($tag,$content) { - return $this->_compare($tag,$content,'neq'); - } - - public function _gt($tag,$content) { - return $this->_compare($tag,$content,'gt'); - } - - public function _lt($tag,$content) { - return $this->_compare($tag,$content,'lt'); - } - - public function _egt($tag,$content) { - return $this->_compare($tag,$content,'egt'); - } - - public function _elt($tag,$content) { - return $this->_compare($tag,$content,'elt'); - } - - public function _heq($tag,$content) { - return $this->_compare($tag,$content,'heq'); - } - - public function _nheq($tag,$content) { - return $this->_compare($tag,$content,'nheq'); - } - - /** - * range标签解析 - * 如果某个变量存在于某个范围 则输出内容 type= in 表示在范围内 否则表示在范围外 - * 格式: content - * example: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @param string $type 比较类型 - * @return string - */ - public function _range($tag,$content,$type='in') { - $name = $tag['name']; - $value = $tag['value']; - $varArray = explode('|',$name); - $name = array_shift($varArray); - $name = $this->autoBuildVar($name); - if(count($varArray)>0) - $name = $this->parseVarFunction($name,$varArray); - - $type = isset($tag['type'])?$tag['type']:$type; - - if('$' == substr($value,0,1)) { - $value = $this->autoBuildVar(substr($value,1)); - $str = 'is_array('.$value.')?'.$value.':explode(\',\','.$value.')'; - }else{ - $value = '"'.$value.'"'; - $str = 'explode(\',\','.$value.')'; - } - if($type=='between') { - $parseStr = '= $_RANGE_VAR_[0] && '.$name.'<= $_RANGE_VAR_[1]):?>'.$content.''; - }elseif($type=='notbetween'){ - $parseStr = '$_RANGE_VAR_[1]):?>'.$content.''; - }else{ - $fun = ($type == 'in')? 'in_array' : '!in_array'; - $parseStr = ''.$content.''; - } - return $parseStr; - } - - // range标签的别名 用于in判断 - public function _in($tag,$content) { - return $this->_range($tag,$content,'in'); - } - - // range标签的别名 用于notin判断 - public function _notin($tag,$content) { - return $this->_range($tag,$content,'notin'); - } - - public function _between($tag,$content){ - return $this->_range($tag,$content,'between'); - } - - public function _notbetween($tag,$content){ - return $this->_range($tag,$content,'notbetween'); - } - - /** - * present标签解析 - * 如果某个变量已经设置 则输出内容 - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _present($tag,$content) { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = ''.$content.''; - return $parseStr; - } - - /** - * notpresent标签解析 - * 如果某个变量没有设置,则输出内容 - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _notpresent($tag,$content) { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = ''.$content.''; - return $parseStr; - } - - /** - * empty标签解析 - * 如果某个变量为empty 则输出内容 - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _empty($tag,$content) { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = ''.$content.''; - return $parseStr; - } - - public function _notempty($tag,$content) { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = ''.$content.''; - return $parseStr; - } - - /** - * 判断是否已经定义了该常量 - * 已定义 - * @param $tag - * @param $content - * @return string - */ - public function _defined($tag,$content) { - $name = $tag['name']; - $parseStr = ''.$content.''; - return $parseStr; - } - - public function _notdefined($tag,$content) { - $name = $tag['name']; - $parseStr = ''.$content.''; - return $parseStr; - } - - /** - * import 标签解析 - * - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @param boolean $isFile 是否文件方式 - * @param string $type 类型 - * @return string - */ - public function _import($tag,$content,$isFile=false,$type='') { - $file = isset($tag['file'])?$tag['file']:$tag['href']; - $parseStr = ''; - $endStr = ''; - // 判断是否存在加载条件 允许使用函数判断(默认为isset) - if (isset($tag['value'])) { - $varArray = explode('|',$tag['value']); - $name = array_shift($varArray); - $name = $this->autoBuildVar($name); - if (!empty($varArray)) - $name = $this->parseVarFunction($name,$varArray); - else - $name = 'isset('.$name.')'; - $parseStr .= ''; - $endStr = ''; - } - if($isFile) { - // 根据文件名后缀自动识别 - $type = $type?$type:(!empty($tag['type'])?strtolower($tag['type']):null); - // 文件方式导入 - $array = explode(',',$file); - foreach ($array as $val){ - if (!$type || isset($reset)) { - $type = $reset = strtolower(substr(strrchr($val, '.'),1)); - } - switch($type) { - case 'js': - $parseStr .= ''; - break; - case 'css': - $parseStr .= ''; - break; - case 'php': - $parseStr .= ''; - break; - } - } - }else{ - // 命名空间导入模式 默认是js - $type = $type?$type:(!empty($tag['type'])?strtolower($tag['type']):'js'); - $basepath = !empty($tag['basepath'])?$tag['basepath']:__ROOT__.'/Public'; - // 命名空间方式导入外部文件 - $array = explode(',',$file); - foreach ($array as $val){ - list($val,$version) = explode('?',$val); - switch($type) { - case 'js': - $parseStr .= ''; - break; - case 'css': - $parseStr .= ''; - break; - case 'php': - $parseStr .= ''; - break; - } - } - } - return $parseStr.$endStr; - } - - // import别名 采用文件方式加载(要使用命名空间必须用import) 例如 - public function _load($tag,$content) { - return $this->_import($tag,$content,true); - } - - // import别名使用 导入css文件 - public function _css($tag,$content) { - return $this->_import($tag,$content,true,'css'); - } - - // import别名使用 导入js文件 - public function _js($tag,$content) { - return $this->_import($tag,$content,true,'js'); - } - - /** - * assign标签解析 - * 在模板中给某个变量赋值 支持变量赋值 - * 格式: - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _assign($tag,$content) { - $name = $this->autoBuildVar($tag['name']); - if('$'==substr($tag['value'],0,1)) { - $value = $this->autoBuildVar(substr($tag['value'],1)); - }else{ - $value = '\''.$tag['value']. '\''; - } - $parseStr = ''; - return $parseStr; - } - - /** - * define标签解析 - * 在模板中定义常量 支持变量赋值 - * 格式: - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _define($tag,$content) { - $name = '\''.$tag['name']. '\''; - if('$'==substr($tag['value'],0,1)) { - $value = $this->autoBuildVar(substr($tag['value'],1)); - }else{ - $value = '\''.$tag['value']. '\''; - } - $parseStr = ''; - return $parseStr; - } - - /** - * for标签解析 - * 格式: - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _for($tag, $content){ - //设置默认值 - $start = 0; - $end = 0; - $step = 1; - $comparison = 'lt'; - $name = 'i'; - $rand = rand(); //添加随机数,防止嵌套变量冲突 - //获取属性 - foreach ($tag as $key => $value){ - $value = trim($value); - if(':'==substr($value,0,1)) - $value = substr($value,1); - elseif('$'==substr($value,0,1)) - $value = $this->autoBuildVar(substr($value,1)); - switch ($key){ - case 'start': - $start = $value; break; - case 'end' : - $end = $value; break; - case 'step': - $step = $value; break; - case 'comparison': - $comparison = $value; break; - case 'name': - $name = $value; break; - } - } - - $parseStr = 'parseCondition('$'.$name.' '.$comparison.' $__FOR_END_'.$rand.'__').';$'.$name.'+='.$step.'){ ?>'; - $parseStr .= $content; - $parseStr .= ''; - return $parseStr; - } -} diff --git a/Library/Think/Transform.php b/Library/Think/Transform.php deleted file mode 100644 index fb234023..00000000 --- a/Library/Think/Transform.php +++ /dev/null @@ -1,81 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -// 内容解析类 -class Transform { - static private $handler = []; - - /** - * 初始化解析驱动 - * @static - * @access private - * @param string $type 驱动类型 - */ - static private function init($type){ - if(!isset(self::$handler[$type])) { - $class = '\\Think\\Transform\\Driver\\' . ucwords($type); - self::$handler[$type] = new $class(); - } - } - - /** - * 编码内容 - * @static - * @access public - * @param mixed $content 要编码的数据 - * @param string $type 数据类型 - * @param array $config XML配置参数,JSON格式生成无此参数 - * @return string 编码后的数据 - */ - static public function encode($content, $type, array $config = []){ - self::init($type); - return self::$handler[$type]->encode($content, $config); - } - - /** - * 解码数据 - * @param string $content 要解码的数据 - * @param string $type 数据类型 - * @param boolean $assoc 是否返回数组 - * @param array $config XML配置参数,JSON格式解码无此参数 - * @return mixed 解码后的数据 - */ - static public function decode($content, $type, $assoc = true, array $config = []){ - self::init($type); - return self::$handler[$type]->decode($content, $assoc, $config); - } - - // 调用驱动类的方法 - // Transform::xmlEncode('abc') - // Transform::jsonDecode('abc', true); - static public function __callStatic($method, $params){ - if(empty($params[0])){ - return ''; - } - - //获取类型 - $type = substr($method, 0, strlen($method) - 6); - - switch (strtolower(substr($method, -6))) { - case 'encode': - $config = empty($params[1]) ? [] : $params[1]; - return self::encode($params[0], $type, $config); - case 'decode': - $assoc = empty($params[1]) ? true : $params[1]; - $config = empty($params[2]) ? [] : $params[2]; - return self::decode($params[0], $type, $assoc, $config); - default: - throw new Exception("call to undefined method {$method}"); - } - } -} diff --git a/Library/Think/Url.php b/Library/Think/Url.php deleted file mode 100644 index 2bb463ae..00000000 --- a/Library/Think/Url.php +++ /dev/null @@ -1,151 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -class Url { - - static public function param($num,$default=''){ - $paths = explode(Config::get('url_pathinfo_depr'),trim($_SERVER['PATH_INFO'],'/')); - return isset($paths[$num])?$paths[$num]:$default; - } - - static public function route($route){ - } - - /** - * URL组装 支持不同URL模式 - * @param string $url URL表达式,格式:'[分组/模块/操作#锚点@域名]?参数1=值1&参数2=值2...' - * @param string|array $vars 传入的参数,支持数组和字符串 - * @param string $suffix 伪静态后缀,默认为true表示获取配置值 - * @param boolean $domain 是否显示域名 - * @return string - */ - static public function build($url='',$vars='',$suffix=true,$domain=false) { - // 解析URL - $info = parse_url($url); - $url = !empty($info['path'])?$info['path']:ACTION_NAME; - if(isset($info['fragment'])) { // 解析锚点 - $anchor = $info['fragment']; - if(false !== strpos($anchor,'?')) { // 解析参数 - list($anchor,$info['query']) = explode('?',$anchor,2); - } - if(false !== strpos($anchor,'@')) { // 解析域名 - list($anchor,$host) = explode('@',$anchor, 2); - } - }elseif(false !== strpos($url,'@')) { // 解析域名 - list($url,$host) = explode('@',$info['path'], 2); - } - // 解析子域名 - if(isset($host)) { - $domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.')); - }elseif($domain===true){ - $domain = $_SERVER['HTTP_HOST']; - if(Config::get('app_sub_domain_deplay') ) { // 开启子域名部署 - $domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.'); - // '子域名'=>array('项目[/分组]'); - foreach (Config::get('app_sub_domain_rules') as $key => $rule) { - if(false === strpos($key,'*') && 0=== strpos($url,$rule[0])) { - $domain = $key.strstr($domain,'.'); // 生成对应子域名 - $url = substr_replace($url,'',0,strlen($rule[0])); - break; - } - } - } - } - - // 解析参数 - if(is_string($vars)) { // aaa=1&bbb=2 转换成数组 - parse_str($vars,$vars); - }elseif(!is_array($vars)){ - $vars = []; - } - if(isset($info['query'])) { // 解析地址里面参数 合并到vars - parse_str($info['query'],$params); - $vars = array_merge($params,$vars); - } - - // URL组装 - $depr = Config::get('pathinfo_depr'); - if($url) { - if(0=== strpos($url,'/')) {// 定义路由 - $route = true; - $url = substr($url,1); - if('/' != $depr) { - $url = str_replace('/',$depr,$url); - } - }else{ - if('/' != $depr) { // 安全替换 - $url = str_replace('/',$depr,$url); - } - // 解析分组、模块和操作 - $url = trim($url,$depr); - $path = explode($depr,$url); - $var = []; - $var[Config::get('var_action')] = !empty($path)?array_pop($path):ACTION_NAME; - if(Config::get('require_controller')) { - $var[Config::get('var_controller')] = !empty($path)?array_pop($path):CONTROLLER_NAME; - } - if(Config::get('require_module')) { - $var[Config::get('var_module')] = !empty($path)?array_pop($path):MODULE_NAME; - } - } - } - - if(Config::get('url_model') == 0) { // 普通模式URL转换 - $url = Config::get('base_url').'?'.http_build_query(array_reverse($var)); - if(!empty($vars)) { - $vars = urldecode(http_build_query($vars)); - $url .= '&'.$vars; - } - }else{ // PATHINFO模式或者兼容URL模式 - if(isset($route)) { - $url = Config::get('base_url').'/'.rtrim($url,$depr); - }else{ - $url = Config::get('base_url').'/'.implode($depr,array_reverse($var)); - } - if(!empty($vars)) { // 添加参数 - foreach ($vars as $var => $val){ - if('' !== trim($val)) $url .= $depr . $var . $depr . urlencode($val); - } - } - if($suffix) { - $suffix = $suffix===true?Config::get('url_html_suffix'):$suffix; - if($pos = strpos($suffix, '|')){ - $suffix = substr($suffix, 0, $pos); - } - if($suffix && '/' != substr($url,-1)){ - $url .= '.'.ltrim($suffix,'.'); - } - } - } - if(isset($anchor)){ - $url .= '#'.$anchor; - } - if($domain) { - $url = (self::is_ssl()?'https://':'http://').$domain.$url; - } - return $url; - } - - /** - * 判断是否SSL协议 - * @return boolean - */ - static public function is_ssl() { - if(isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))){ - return true; - }elseif(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'] )) { - return true; - } - return false; - } -} diff --git a/Library/Think/View.php b/Library/Think/View.php deleted file mode 100644 index 9b58b9af..00000000 --- a/Library/Think/View.php +++ /dev/null @@ -1,261 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; -use Think\Exception; - -class View { - protected $engine = null; // 模板引擎实例 - protected $theme = ''; // 模板主题名称 - protected $data = []; // 模板变量 - protected $config = [ // 视图参数 - 'http_output_content' => true, - 'http_content_type' => 'text/html', - 'http_charset' => 'utf-8', - 'http_cache_control' => 'private', - 'http_render_content' => false, - 'theme_on' => false, - 'auto_detect_theme' => false, - 'var_theme' => 't', - 'default_theme' => 'default', - 'http_cache_id' => null, - 'view_path' => '', - 'view_suffix' => '.html', - 'view_depr' => '/', - 'view_layer' => VIEW_LAYER, - 'engine_type' => 'think', - ]; - - /** - * 模板变量赋值 - * @access public - * @param mixed $name 变量名 - * @param mixed $value 变量值 - */ - public function assign($name, $value = ''){ - if(is_array($name)) { - $this->data = array_merge($this->data, $name); - return $this; - }else { - $this->data[$name] = $value; - } - } - - /** - * 视图参数设置 - * @access public - * @param mixed $name - * @param mixed $value - */ - public function __set($name, $value = ''){ - $this->config[$name] = $value; - } - - public function __construct(array $config = []){ - $this->config = array_merge($this->config, $config); - $this->engine($this->config['engine_type']); - } - - /** - * 设置当前模板解析的引擎 - * @access public - * @param string $engine 引擎名称 - * @param array $config 引擎参数 - * @return View - */ - public function engine($engine, array $config = []){ - $class = '\\Think\\View\\Driver\\' . ucwords($engine); - $this->engine = new $class($config); - return $this; - } - - /** - * 设置当前输出的模板主题 - * @access public - * @param mixed $theme 主题名称 - * @return View - */ - public function theme($theme){ - if(true === $theme) { // 自动侦测 - $this->config['theme_on'] = true; - $this->config['auto_detect_theme'] = true; - }elseif(false === $theme){ // 关闭主题 - $this->config['theme_on'] = false; - }else{ // 指定模板主题 - $this->config['theme_on'] = true; - $this->theme = $theme; - } - return $this; - } - - /** - * 加载模板和页面输出 可以返回输出内容 - * @access public - * @param string $template 模板文件名 - * @param array $vars 模板输出变量 - * @param string $cache_id 模板缓存标识 - * @return mixed - */ - public function display($template = '', $vars = [], $cache_id = '') { - Hook::listen('view_begin', $template); - // 解析并获取模板内容 - $content = $this->fetch($template, $vars, $cache_id); - // 输出内容过滤 - Hook::listen('view_filter', $content); - // 输出模板内容 - if($this->config['http_output_content']) { - $this->render($content); - }else{ // 返回解析后的内容 - return $content; - } - } - - /** - * 解析和获取模板内容 用于输出 - * @access protected - * @param string $template 模板文件名或者内容 - * @param array $vars 模板输出变量 - * @param string $cache_id 模板缓存标识 - * @return string - */ - protected function fetch($template, $vars = [], $cache_id='') { - if(!$this->config['http_render_content']) { - // 获取模板文件名 - $template = $this->parseTemplate($template); - // 模板不存在 抛出异常 - if(!is_file($template)) { - throw new Exception('template file not exists:' . $template); - } - } - $vars = $vars ? $vars : $this->data; - // 页面缓存 - ob_start(); - ob_implicit_flush(0); - if($this->engine) { // 指定模板引擎 - $this->engine->fetch($template, $vars, $cache_id); - }else{ // 原生PHP解析 - extract($vars, EXTR_OVERWRITE); - is_file($template) ? include $template : eval('?>' . $template); - } - // 获取并清空缓存 - return ob_get_clean(); - } - - /** - * 自动定位模板文件 - * @access private - * @param string $template 模板文件规则 - * @return string - */ - private function parseTemplate($template) { - if(is_file($template)) { - return $template; - } - $depr = $this->config['view_depr']; - $template = str_replace(':', $depr, $template); - - // 获取当前模块 - $module = MODULE_NAME; - if(strpos($template,'@')){ // 跨模块调用模版文件 - list($module,$template) = explode('@',$template); - } - // 获取当前主题的模版路径 - defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath($module)); - - // 分析模板文件规则 - if('' == $template) { - // 如果模板文件名为空 按照默认规则定位 - $template = CONTROLLER_NAME . $depr . ACTION_NAME; - }elseif(false === strpos($template, $depr)){ - $template = CONTROLLER_NAME . $depr . $template; - } - return THEME_PATH.$template.$this->config['view_suffix']; - } - - /** - * 获取当前的模板主题 - * @access private - * @return string - */ - private function getTemplateTheme($module) { - if($this->config['theme_on']) { - if($this->theme) { // 指定模板主题 - $theme = $this->theme; - }elseif($this->config['auto_detect_theme']){ - // 自动侦测模板主题 - $t = $this->config['var_theme']; - if (isset($_GET[$t])){ - $theme = $_GET[$t]; - }elseif(Cookie::get('think_theme')){ - $theme = Cookie::get('think_theme'); - } - if(!is_dir(APP_PATH.$module . '/'. $this->config['view_layer'].'/' . $theme)) { - $theme = $this->config['default_theme']; - } - Cookie::set('think_theme', $theme, 864000); - }else{ - $theme = $this->config['default_theme']; - } - return $theme . '/'; - } - return ''; - } - - /** - * 获取当前的模板路径 - * @access protected - * @param string $module 模块名 - * @return string - */ - protected function getThemePath($module=MODULE_NAME){ - // 获取当前主题名称 - $theme = $this->getTemplateTheme($module); - // 获取当前主题的模版路径 - $tmplPath = $this->config['view_path']; // 模块设置独立的视图目录 - if(!$tmplPath){ - // 定义TMPL_PATH 则改变全局的视图目录到模块之外 - $tmplPath = defined('TMPL_PATH')? TMPL_PATH.$module.'/' : APP_PATH.$module.'/'.$this->config['view_layer'].'/'; - } - return $tmplPath.$theme; - } - - /** - * 视图输出参数设置 - * @access public - * @param mixed $config - * @param mixed $value - */ - public function http($config = [], $value = ''){ - if(is_array($config)) { - $this->config = array_merge($this->config, $config); - }else{ - $this->config[$config] = $value; - } - return $this; - } - - /** - * 输出内容文本可以包括Html - * @access private - * @param string $content 输出内容 - * @param string $charset 模板输出字符集 - * @param string $contentType 输出类型 - * @return mixed - */ - private function render($content){ - // 网页字符编码 - header('Content-Type:' . $this->config['http_content_type'] . '; charset=' . $this->config['http_charset']); - header('Cache-control:' . $this->config['http_cache_control']); // 页面缓存控制 - header('X-Powered-By:ThinkPHP'); - // 输出模板文件 - echo $content; - } -} diff --git a/Library/Think/View/Driver/Think.php b/Library/Think/View/Driver/Think.php deleted file mode 100644 index bf73462d..00000000 --- a/Library/Think/View/Driver/Think.php +++ /dev/null @@ -1,28 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think\View\Driver; -use Think\Template; - -class Think { - private $template = null; - public function __construct($config=[]){ - $this->template = new Template($config); - } - - public function fetch($template,$data=[],$cacheId=''){ - if(is_file($template)) { - $this->template->display($template,$data,$cacheId); - }else{ - $this->template->fetch($template,$data); - } - } -} diff --git a/Mode/common.php b/Mode/common.php deleted file mode 100644 index 3e02eefa..00000000 --- a/Mode/common.php +++ /dev/null @@ -1,106 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace Think; -/** - * ThinkPHP 普通模式定义 - */ - -return [ - // 配置文件 - 'config' => [ - 'app_debug' => true, // 调试模式 - 'app_status' => 'debug',// 应用模式状态 - 'var_module' => 'm', // 模块变量名 - 'var_controller' => 'c', // 控制器变量名 - 'var_action' => 'a', // 操作变量名 - 'var_pathinfo' => 's', // PATHINFO变量名 用于兼容模式 - 'pathinfo_fetch' => 'ORIG_PATH_INFO,REDIRECT_PATH_INFO,REDIRECT_URL', - 'pathinfo_depr' => '/', // pathinfo分隔符 - 'require_module' => true, // 是否显示模块 - 'default_module' => 'index', // 默认模块名 - 'default_controller' => 'index', // 默认控制器名 - 'default_action' => 'index', // 默认操作名 - 'action_suffix' => '', // 操作方法后缀 - 'url_model' => 1, // URL模式 - 'base_url' => $_SERVER["SCRIPT_NAME"], // 基础URL路径 - 'url_html_suffix' => '.html', - 'url_params_bind' => false, // url变量绑定 - 'exception_tmpl' => THINK_PATH.'Tpl/think_exception.tpl',// 异常页面的模板文件 - 'error_tmpl' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认错误跳转对应的模板文件 - 'success_tmpl' => THINK_PATH.'Tpl/dispatch_jump.tpl', // 默认成功跳转对应的模板文件 - 'default_ajax_return' => 'JSON', // 默认AJAX 数据返回格式,可选JSON XML ... - 'default_jsonp_handler' => 'jsonpReturn', // 默认JSONP格式返回的处理方法 - 'var_jsonp_handler' => 'callback', - 'template_engine' => 'think', - 'common_module' => 'Common', - 'log_path' => LOG_PATH, - 'log_type' => 'File', - 'cache_type' => 'File', - 'caceh_path' => CACHE_PATH, - 'session_prefix' => 'think', - 'session_auto_start' => true, - 'action_bind_class' => false, - 'url_module_map' => [], - - /* 错误设置 */ - 'error_message' => '页面错误!请稍后再试~',//错误显示信息,非调试模式有效 - 'error_page' => '', // 错误定向页面 - 'show_error_msg' => false, // 显示错误信息 - - /* 数据库设置 */ - 'database' => [ - 'type' => 'mysql', // 数据库类型 - 'dsn' => '', // - 'hostname' => 'localhost', // 服务器地址 - 'database' => '', // 数据库名 - 'username' => 'root', // 用户名 - 'password' => '', // 密码 - 'hostport' => '', // 端口 - 'params' => [], // 数据库连接参数 - 'charset' => 'utf8', // 数据库编码默认采用utf8 - 'prefix' => '', // 数据库表前缀 - 'debug' => false, // 数据库调试模式 - 'deploy' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'rw_separate' => false, // 数据库读写是否分离 主从式有效 - 'master_num' => 1, // 读写分离后 主服务器数量 - 'slave_no' => '', // 指定从服务器序号 - ], - ], - - // 别名定义 - 'alias' => [ - 'Think\App' => CORE_PATH . 'App.php', - 'Think\Log' => CORE_PATH . 'Log.php', - 'Think\Log\Driver\File' => CORE_PATH . 'Log/Driver/File.php', - 'Think\Config' => CORE_PATH . 'Config.php', - 'Think\Route' => CORE_PATH . 'Route.php', - 'Think\Exception' => CORE_PATH . 'Exception.php', - 'Think\Model' => CORE_PATH . 'Model.php', - 'Think\Db' => CORE_PATH . 'Db.php', - 'Think\Db\Driver' => CORE_PATH . 'Db/Driver.php', - 'Think\Template' => CORE_PATH . 'Template.php', - 'Think\Error' => CORE_PATH . 'Error.php', - 'Think\Cache' => CORE_PATH . 'Cache.php', - 'Think\Cache\Driver\File' => CORE_PATH . 'Cache/Driver/File.php', - 'Think\Hook' => CORE_PATH . 'Hook.php', - 'Think\Session' => CORE_PATH . 'Session.php', - 'Think\Cookie' => CORE_PATH . 'Cookie.php', - 'Think\Controller' => CORE_PATH . 'Controller.php', - 'Think\View' => CORE_PATH . 'View.php', - 'Think\Url' => CORE_PATH . 'Url.php', - 'Think\Debug' => CORE_PATH . 'Debug.php', - 'Think\Input' => CORE_PATH . 'Input.php', - 'Think\Parser' => CORE_PATH . 'Parser.php', - 'Think\Lang' => CORE_PATH . 'Lang.php', - ], - - 'init' => [], -]; diff --git a/Mode/sae.php b/Mode/sae.php deleted file mode 100644 index a6c48f95..00000000 --- a/Mode/sae.php +++ /dev/null @@ -1,56 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * ThinkPHP SAE应用模式定义文件 - */ -$st = new SaeStorage(); -return [ - // 配置文件 - 'config' => [ - /* 数据库设置 */ - 'database' => [ - 'type' => 'mysql', // 数据库类型 - 'dsn' => '', // - 'hostname' => SAE_MYSQL_HOST_M.','.SAE_MYSQL_HOST_S, // 服务器地址 - 'database' => SAE_MYSQL_DB, // 数据库名 - 'username' => SAE_MYSQL_USER, // 用户名 - 'password' => SAE_MYSQL_PASS, // 密码 - 'hostport' => SAE_MYSQL_PORT, // 端口 - 'params' => [], // 数据库连接参数 - 'charset' => 'utf8', // 数据库编码默认采用utf8 - 'prefix' => '', // 数据库表前缀 - 'debug' => false, // 数据库调试模式 - 'deploy' => 1, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'rw_separate' => true, // 数据库读写是否分离 主从式有效 - 'master_num' => 1, // 读写分离后 主服务器数量 - 'slave_no' => '', // 指定从服务器序号 - ], - 'log_type' => 'Sae', - 'data_cache_type' => 'Memcachesae', - 'check_app_dir' => false, - 'file_upload_type' => 'Sae', - ], - - // 别名定义 - 'alias' => [ - 'Think\Log' => CORE_PATH . 'Log'.EXT, - 'Think\Log\Driver\File' => CORE_PATH . 'Log/Driver/File'.EXT, - 'Think\Exception' => CORE_PATH . 'Exception'.EXT, - 'Think\Model' => CORE_PATH . 'Model'.EXT, - 'Think\Db' => CORE_PATH . 'Db'.EXT, - 'Think\Template' => CORE_PATH . 'Template'.EXT, - 'Think\Cache' => CORE_PATH . 'Cache'.EXT, - 'Think\Cache\Driver\File' => CORE_PATH . 'Cache/Driver/File'.EXT, - 'Think\Storage' => CORE_PATH . 'Storage'.EXT, - ], - -]; diff --git a/Mode/sae/convention.php b/Mode/sae/convention.php deleted file mode 100644 index 9101e436..00000000 --- a/Mode/sae/convention.php +++ /dev/null @@ -1,39 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 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/Tpl/default_index.tpl b/Tpl/default_index.tpl deleted file mode 100644 index 4de55d92..00000000 --- a/Tpl/default_index.tpl +++ /dev/null @@ -1,8 +0,0 @@ -*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px }

    :)

    欢迎使用 ThinkPHP

    '); - } -} \ No newline at end of file diff --git a/Tpl/dispatch_jump.tpl b/Tpl/dispatch_jump.tpl deleted file mode 100644 index bf035c83..00000000 --- a/Tpl/dispatch_jump.tpl +++ /dev/null @@ -1,44 +0,0 @@ - - - - -跳转提示 - - - -
    - -

    :)

    -

    - -

    :(

    -

    -
    -

    -

    -页面自动 跳转 等待时间: -

    -
    - - - \ No newline at end of file diff --git a/Tpl/page_trace.tpl b/Tpl/page_trace.tpl deleted file mode 100644 index caa4c570..00000000 --- a/Tpl/page_trace.tpl +++ /dev/null @@ -1,67 +0,0 @@ -
    - - -
    -
    - \ No newline at end of file diff --git a/Tpl/think_exception.tpl b/Tpl/think_exception.tpl deleted file mode 100644 index 84b27e97..00000000 --- a/Tpl/think_exception.tpl +++ /dev/null @@ -1,53 +0,0 @@ - - - -系统发生错误 - - - -
    -

    :(

    -

    -
    - -
    -
    -

    错误位置

    -
    -
    -

    FILE:  LINE:

    -
    -
    - - -
    -
    -

    TRACE

    -
    -
    -

    -
    -
    - -
    -
    - - - \ No newline at end of file diff --git a/Traits/Think/Model/Auto.php b/Traits/Think/Model/Auto.php deleted file mode 100644 index cca5f0f6..00000000 --- a/Traits/Think/Model/Auto.php +++ /dev/null @@ -1,363 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Traits\Think\Model; -define('EXISTS_VALIDATE',0); -define('MUST_VALIDATE',1); -define('VALUE_VALIDATE',2); - -trait Auto { - - protected $validate = []; // 自动验证定义 - protected $auto = []; // 自动完成定义 - - /** - * 创建数据对象 但不保存到数据库 - * @access public - * @param mixed $data 创建数据 - * @param string $type 状态 - * @return mixed - */ - public function create($data='',$type='') { - // 如果没有传值默认取POST数据 - if(empty($data)) { - $data = $_POST; - }elseif(is_object($data)){ - $data = get_object_vars($data); - } - // 验证数据 - if(empty($data) || !is_array($data)) { - $this->error = L('_DATA_TYPE_INVALID_'); - return false; - } - - // 状态 - $type = $type?$type:(!empty($data[$this->getPk()])?self::MODEL_UPDATE:self::MODEL_INSERT); - - // 检测提交字段的合法性 - if(isset($this->options['field'])) { // $this->field('field1,field2...')->create() - $fields = $this->options['field']; - unset($this->options['field']); - }elseif($type == self::MODEL_INSERT && isset($this->insertFields)) { - $fields = $this->insertFields; - }elseif($type == self::MODEL_UPDATE && isset($this->updateFields)) { - $fields = $this->updateFields; - } - if(isset($fields)) { - if(is_string($fields)) { - $fields = explode(',',$fields); - } - // 判断令牌验证字段 - if(C('TOKEN_ON')) $fields[] = C('TOKEN_NAME'); - foreach ($data as $key=>$val){ - if(!in_array($key,$fields)) { - unset($data[$key]); - } - } - } - - // 数据自动验证 - if(!$this->autoValidation($data,$type)) return false; - - - // 验证完成生成数据对象 - if($this->autoCheckFields) { // 开启字段检测 则过滤非法字段数据 - $fields = $this->getDbFields(); - foreach ($data as $key=>$val){ - if(!in_array($key,$fields)) { - unset($data[$key]); - }elseif(MAGIC_QUOTES_GPC && is_string($val)){ - $data[$key] = stripslashes($val); - } - } - } - - // 创建完成对数据进行自动处理 - $this->autoOperation($data,$type); - // 赋值当前数据对象 - $this->data = $data; - // 返回创建的数据以供其他调用 - return $data; - } - - /** - * 使用正则验证数据 - * @access public - * @param string $value 要验证的数据 - * @param string $rule 验证规则 - * @return boolean - */ - public function regex($value,$rule) { - $validate = array( - 'require' => '/.+/', - 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', - 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', - 'currency' => '/^\d+(\.\d+)?$/', - 'number' => '/^\d+$/', - 'zip' => '/^\d{6}$/', - 'integer' => '/^[-\+]?\d+$/', - 'double' => '/^[-\+]?\d+(\.\d+)?$/', - 'english' => '/^[A-Za-z]+$/', - ); - // 检查是否有内置的正则表达式 - if(isset($validate[strtolower($rule)])) - $rule = $validate[strtolower($rule)]; - return preg_match($rule,$value)===1; - } - - /** - * 自动表单处理 - * @access public - * @param array $data 创建数据 - * @param string $type 创建类型 - * @return mixed - */ - private function autoOperation(&$data,$type) { - if(!empty($this->options['auto'])) { - $_auto = $this->options['auto']; - unset($this->options['auto']); - }elseif(!empty($this->auto)){ - $_auto = $this->auto; - } - // 自动填充 - if(isset($_auto)) { - foreach ($_auto as $auto){ - // 填充因子定义格式 - // array('field','填充内容','填充条件','附加规则',[额外参数]) - if(empty($auto[2])) $auto[2] = self::MODEL_INSERT; // 默认为新增的时候自动填充 - if( $type == $auto[2] || $auto[2] == self::MODEL_BOTH) { - switch(trim($auto[3])) { - case 'function': // 使用函数进行填充 字段的值作为参数 - case 'callback': // 使用回调方法 - $args = isset($auto[4])?(array)$auto[4]:[]; - if(isset($data[$auto[0]])) { - array_unshift($args,$data[$auto[0]]); - } - if('function'==$auto[3]) { - $data[$auto[0]] = call_user_func_array($auto[1], $args); - }else{ - $data[$auto[0]] = call_user_func_array(array(&$this,$auto[1]), $args); - } - break; - case 'field': // 用其它字段的值进行填充 - $data[$auto[0]] = $data[$auto[1]]; - break; - case 'ignore': // 为空忽略 - if(''===$data[$auto[0]]) - unset($data[$auto[0]]); - break; - case 'string': - default: // 默认作为字符串填充 - $data[$auto[0]] = $auto[1]; - } - if(false === $data[$auto[0]] ) unset($data[$auto[0]]); - } - } - } - return $data; - } - - /** - * 自动表单验证 - * @access protected - * @param array $data 创建数据 - * @param string $type 创建类型 - * @return boolean - */ - protected function autoValidation($data,$type) { - if(!empty($this->options['validate'])) { - $validate = $this->options['validate']; - unset($this->options['validate']); - }elseif(!empty($this->validate)){ - $validate = $this->validate; - } - // 属性验证 - if(isset($validate)) { // 如果设置了数据自动验证则进行数据验证 - if($this->patchValidate) { // 重置验证错误信息 - $this->error = []; - } - foreach($validate as $key=>$val) { - // 验证因子定义格式 - // array(field,rule,message,condition,type,when,params) - // 判断是否需要执行验证 - if(empty($val[5]) || $val[5]== self::MODEL_BOTH || $val[5]== $type ) { - if(0==strpos($val[2],'{%') && strpos($val[2],'}')) - // 支持提示信息的多语言 使用 {%语言定义} 方式 - $val[2] = L(substr($val[2],2,-1)); - $val[3] = isset($val[3])?$val[3]:EXISTS_VALIDATE; - $val[4] = isset($val[4])?$val[4]:'regex'; - // 判断验证条件 - switch($val[3]) { - case MUST_VALIDATE: // 必须验证 不管表单是否有设置该字段 - if(false === $this->_validationField($data,$val)) - return false; - break; - case VALUE_VALIDATE: // 值不为空的时候才验证 - if('' != trim($data[$val[0]])) - if(false === $this->_validationField($data,$val)) - return false; - break; - default: // 默认表单存在该字段就验证 - if(isset($data[$val[0]])) - if(false === $this->_validationField($data,$val)) - return false; - } - } - } - // 批量验证的时候最后返回错误 - if(!empty($this->error)) return false; - } - return true; - } - - /** - * 验证表单字段 支持批量验证 - * 如果批量验证返回错误的数组信息 - * @access protected - * @param array $data 创建数据 - * @param array $val 验证因子 - * @return boolean - */ - protected function _validationField($data,$val) { - if(false === $this->_validationFieldItem($data,$val)){ - if($this->patchValidate) { - $this->error[$val[0]] = $val[2]; - }else{ - $this->error = $val[2]; - return false; - } - } - return ; - } - - /** - * 根据验证因子验证字段 - * @access protected - * @param array $data 创建数据 - * @param array $val 验证因子 - * @return boolean - */ - protected function _validationFieldItem($data,$val) { - switch(strtolower(trim($val[4]))) { - case 'function':// 使用函数进行验证 - case 'callback':// 调用方法进行验证 - $args = isset($val[6])?(array)$val[6]:[]; - if(is_string($val[0]) && strpos($val[0], ',')) - $val[0] = explode(',', $val[0]); - if(is_array($val[0])){ - // 支持多个字段验证 - foreach($val[0] as $field) - $_data[$field] = $data[$field]; - array_unshift($args, $_data); - }else{ - array_unshift($args, $data[$val[0]]); - } - if('function'==$val[4]) { - return call_user_func_array($val[1], $args); - }else{ - return call_user_func_array(array(&$this, $val[1]), $args); - } - case 'confirm': // 验证两个字段是否相同 - return $data[$val[0]] == $data[$val[1]]; - case 'unique': // 验证某个值是否唯一 - if(is_string($val[0]) && strpos($val[0],',')) - $val[0] = explode(',',$val[0]); - $map = []; - if(is_array($val[0])) { - // 支持多个字段验证 - foreach ($val[0] as $field) - $map[$field] = $data[$field]; - }else{ - $map[$val[0]] = $data[$val[0]]; - } - if(!empty($data[$this->getPk()])) { // 完善编辑的时候验证唯一 - $map[$this->getPk()] = array('neq',$data[$this->getPk()]); - } - if($this->where($map)->find()) return false; - return true; - default: // 检查附加规则 - return $this->check($data[$val[0]],$val[1],$val[4]); - } - } - - /** - * 验证数据 支持 in between equal length regex expire ip_allow ip_deny - * @access public - * @param string $value 验证数据 - * @param mixed $rule 验证表达式 - * @param string $type 验证方式 默认为正则验证 - * @return boolean - */ - public function check($value,$rule,$type='regex'){ - $type = strtolower(trim($type)); - switch($type) { - case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组 - case 'notin': - $range = is_array($rule)? $rule : explode(',',$rule); - return $type == 'in' ? in_array($value ,$range) : !in_array($value ,$range); - case 'between': // 验证是否在某个范围 - case 'notbetween': // 验证是否不在某个范围 - if (is_array($rule)){ - $min = $rule[0]; - $max = $rule[1]; - }else{ - list($min,$max) = explode(',',$rule); - } - return $type == 'between' ? $value>=$min && $value<=$max : $value<$min || $value>$max; - case 'equal': // 验证是否等于某个值 - case 'notequal': // 验证是否等于某个值 - return $type == 'equal' ? $value == $rule : $value != $rule; - case 'length': // 验证长度 - $length = mb_strlen($value,'utf-8'); // 当前数据长度 - if(strpos($rule,',')) { // 长度区间 - list($min,$max) = explode(',',$rule); - return $length >= $min && $length <= $max; - }else{// 指定长度 - return $length == $rule; - } - case 'expire': - list($start,$end) = explode(',',$rule); - if(!is_numeric($start)) $start = strtotime($start); - if(!is_numeric($end)) $end = strtotime($end); - return NOW_TIME >= $start && NOW_TIME <= $end; - case 'ip_allow': // IP 操作许可验证 - return in_array(get_client_ip(),explode(',',$rule)); - case 'ip_deny': // IP 操作禁止验证 - return !in_array(get_client_ip(),explode(',',$rule)); - case 'regex': - default: // 默认使用正则验证 可以使用验证类中定义的验证名称 - // 检查附加规则 - return $this->regex($value,$rule); - } - } - - /** - * 指定自动完成 - * @access public - * @param array $auto 自动完成设置 - * @return Model - */ - public function auto($auto){ - $this->options['auto'] = $auto; - return $this; - } - - /** - * 指定自动验证 - * @access public - * @param array $validate 自动验证设置 - * @return Model - */ - public function validate($auto){ - $this->options['validate'] = $validate; - return $this; - } -} \ No newline at end of file diff --git a/Traits/Think/Model/Extend.php b/Traits/Think/Model/Extend.php deleted file mode 100644 index 1a7cea10..00000000 --- a/Traits/Think/Model/Extend.php +++ /dev/null @@ -1,261 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Traits\Think\Model; - -trait Extend { - - protected $partition = []; - - /** - * 利用__call方法实现一些特殊的Model方法 - * @access public - * @param string $method 方法名称 - * @param array $args 调用参数 - * @return mixed - */ - public function __call($method,$args) { - if(in_array(strtolower($method),array('count','sum','min','max','avg'),true)){ - // 统计查询的实现 - $field = isset($args[0])?$args[0]:'*'; - return $this->getField(strtoupper($method).'('.$field.') AS tp_'.$method); - }elseif(strtolower(substr($method,0,5))=='getby') { - // 根据某个字段获取记录 - $field = parse_name(substr($method,5)); - $where[$field] = $args[0]; - return $this->where($where)->find(); - }elseif(strtolower(substr($method,0,10))=='getfieldby') { - // 根据某个字段获取记录的某个值 - $name = parse_name(substr($method,10)); - $where[$name] =$args[0]; - return $this->where($where)->getField($args[1]); - }elseif(isset($this->scope[$method])){// 命名范围的单独调用支持 - return $this->scope($method,$args[0]); - }else{ - E(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_')); - return; - } - } - - /** - * 设置记录的某个字段值 - * 支持使用数据库字段和方法 - * @access public - * @param string|array $field 字段名 - * @param string $value 字段值 - * @return boolean - */ - public function setField($field,$value='') { - if(is_array($field)) { - $data = $field; - }else{ - $data[$field] = $value; - } - return $this->save($data); - } - - /** - * 字段值增长 - * @access public - * @param string $field 字段名 - * @param integer $step 增长值 - * @return boolean - */ - public function setInc($field,$step=1) { - return $this->setField($field,['exp',$field.'+'.$step]); - } - - /** - * 字段值减少 - * @access public - * @param string $field 字段名 - * @param integer $step 减少值 - * @return boolean - */ - public function setDec($field,$step=1) { - return $this->setField($field,['exp',$field.'-'.$step]); - } - - - /** - * 获取一条记录的某个字段值 - * @access public - * @param string $field 字段名 - * @param string $spea 字段数据间隔符号 NULL返回数组 - * @return mixed - */ - public function getField($field,$sepa=null) { - $options['field'] = $field; - $options = $this->_parseOptions($options); - $field = trim($field); - if(strpos($field,',')) { // 多字段 - if(!isset($options['limit'])){ - $options['limit'] = is_numeric($sepa)?$sepa:''; - } - $resultSet = $this->db->select($options); - if(!empty($resultSet)) { - $_field = explode(',', $field); - $field = array_keys($resultSet[0]); - $key = array_shift($field); - $key2 = array_shift($field); - $cols = []; - $count = count($_field); - foreach ($resultSet as $result){ - $name = $result[$key]; - if(2==$count) { - $cols[$name] = $result[$key2]; - }else{ - $cols[$name] = is_string($sepa)?implode($sepa,$result):$result; - } - } - return $cols; - } - }else{ // 查找一条记录 - // 返回数据个数 - if(true !== $sepa) {// 当sepa指定为true的时候 返回所有数据 - $options['limit'] = is_numeric($sepa)?$sepa:1; - } - $result = $this->db->select($options); - if(!empty($result)) { - if(true !== $sepa && 1==$options['limit']) return reset($result[0]); - foreach ($result as $val){ - $array[] = $val[$field]; - } - return $array; - } - } - return null; - } - - /** - * 字段值延迟增长 - * @access public - * @param string $field 字段名 - * @param integer $step 增长值 - * @param integer $lazyTime 延时时间(s) - * @return boolean - */ - public function setLazyInc($field,$step=1,$lazyTime=0) { - $condition = $this->options['where']; - if(empty($condition)) { // 没有条件不做任何更新 - return false; - } - if($lazyTime>0) {// 延迟写入 - $guid = md5($this->name.'_'.$field.'_'.serialize($condition)); - $step = $this->lazyWrite($guid,$step,$lazyTime); - if(false === $step ) return true; // 等待下次写入 - } - return $this->setField($field,array('exp',$field.'+'.$step)); - } - - /** - * 字段值延迟减少 - * @access public - * @param string $field 字段名 - * @param integer $step 减少值 - * @param integer $lazyTime 延时时间(s) - * @return boolean - */ - public function setLazyDec($field,$step=1,$lazyTime=0) { - $condition = $this->options['where']; - if(empty($condition)) { // 没有条件不做任何更新 - return false; - } - if($lazyTime>0) {// 延迟写入 - $guid = md5($this->name.'_'.$field.'_'.serialize($condition)); - $step = $this->lazyWrite($guid,$step,$lazyTime); - if(false === $step ) return true; // 等待下次写入 - } - return $this->setField($field,array('exp',$field.'-'.$step)); - } - - /** - * 延时更新检查 返回false表示需要延时 - * 否则返回实际写入的数值 - * @access public - * @param string $guid 写入标识 - * @param integer $step 写入步进值 - * @param integer $lazyTime 延时时间(s) - * @return false|integer - */ - protected function lazyWrite($guid,$step,$lazyTime) { - if(false !== ($value = F($guid))) { // 存在缓存写入数据 - if(time()>S($guid.'_time')+$lazyTime) { - // 延时更新时间到了,删除缓存数据 并实际写入数据库 - S($guid,null); - S($guid.'_time',null); - return $value+$step; - }else{ - // 追加数据到缓存 - S($guid,$value+$step); - return false; - } - }else{ // 没有缓存数据 - S($guid,$step); - // 计时开始 - S($guid.'_time',time()); - return false; - } - } - - /** - * 得到分表的的数据表名 - * @access public - * @param array $data 操作的数据 - * @return string - */ - public function getPartitionTableName($data=[]) { - // 对数据表进行分区 - if(isset($data[$this->partition['field']])) { - $field = $data[$this->partition['field']]; - switch($this->partition['type']) { - case 'id': - // 按照id范围分表 - $step = $this->partition['expr']; - $seq = floor($field / $step)+1; - break; - case 'year': - // 按照年份分表 - if(!is_numeric($field)) { - $field = strtotime($field); - } - $seq = date('Y',$field)-$this->partition['expr']+1; - break; - case 'mod': - // 按照id的模数分表 - $seq = ($field % $this->partition['num'])+1; - break; - case 'md5': - // 按照md5的序列分表 - $seq = (ord(substr(md5($field),0,1)) % $this->partition['num'])+1; - break; - default : - if(function_exists($this->partition['type'])) { - // 支持指定函数哈希 - $fun = $this->partition['type']; - $seq = (ord(substr($fun($field),0,1)) % $this->partition['num'])+1; - }else{ - // 按照字段的首字母的值分表 - $seq = (ord($field{0}) % $this->partition['num'])+1; - } - } - return $this->getTableName().'_'.$seq; - }else{ - // 当设置的分表字段不在查询条件或者数据中 - // 进行联合查询,必须设定 partition['num'] - $tableName = []; - for($i=0;$i<$this->partition['num'];$i++) - $tableName[] = 'SELECT * FROM '.$this->getTableName().'_'.($i+1); - $tableName = '( '.implode(" UNION ",$tableName).') AS '.$this->name; - return $tableName; - } - } -} \ No newline at end of file diff --git a/Traits/Think/Model/Query.php b/Traits/Think/Model/Query.php deleted file mode 100644 index 9c67853b..00000000 --- a/Traits/Think/Model/Query.php +++ /dev/null @@ -1,92 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Traits\Think\Model; - -trait Query { - - /** - * 启动事务 - * @access public - * @return void - */ - public function startTrans() { - $this->commit(); - $this->db->startTrans(); - return ; - } - - /** - * 提交事务 - * @access public - * @return boolean - */ - public function commit() { - return $this->db->commit(); - } - - /** - * 事务回滚 - * @access public - * @return boolean - */ - public function rollback() { - return $this->db->rollback(); - } - - /** - * 解析SQL语句 - * @access public - * @param string $sql SQL指令 - * @param boolean $parse 是否需要解析SQL - * @return string - */ - public function parseSql($sql,$parse) { - // 分析表达式 - if(true === $parse) { - $options = $this->_parseOptions(); - $sql = $this->db->parseSql($sql,$options); - }elseif(is_array($parse)){ // SQL预处理 - $sql = vsprintf($sql,$parse); - }else{ - $sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); - } - return $sql; - } - - /** - * 批处理执行SQL语句 - * 批处理的指令都认为是execute操作 - * @access public - * @param array $sql SQL批处理指令 - * @return boolean - */ - public function patchQuery($sql=[]) { - if(!is_array($sql)) return false; - // 自动启动事务支持 - $this->startTrans(); - try{ - foreach ($sql as $_sql){ - $result = $this->execute($_sql); - if(false === $result) { - // 发生错误自动回滚事务 - $this->rollback(); - return false; - } - } - // 提交事务 - $this->commit(); - } catch (\Think\Exception $e) { - $this->rollback(); - } - return true; - } -} \ No newline at end of file diff --git a/Traits/Think/Model/Relation.php b/Traits/Think/Model/Relation.php deleted file mode 100644 index 2cc297ae..00000000 --- a/Traits/Think/Model/Relation.php +++ /dev/null @@ -1,346 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Traits\Think\Model; - -define('HAS_ONE',1); -define('BELONGS_TO',2); -define('HAS_MANY',3); -define('MANY_TO_MANY',4); - -trait Relation { - // 关联定义 - protected $link = array(); - - /** - * 得到关联的数据表名 - * @access public - * @return string - */ - public function getRelationTableName($relation) { - $relationTable = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - $relationTable .= $this->tableName?$this->tableName:$this->name; - $relationTable .= '_'.$relation->getModelName(); - return strtolower($relationTable); - } - - // 查询成功后的回调方法 - protected function _after_find(&$result,$options) { - // 获取关联数据 并附加到结果中 - if(!empty($options['link'])) - $this->getRelation($result,$options['link']); - } - - // 查询数据集成功后的回调方法 - protected function _after_select(&$result,$options) { - // 获取关联数据 并附加到结果中 - if(!empty($options['link'])) - $this->getRelations($result,$options['link']); - } - - // 写入成功后的回调方法 - protected function _after_insert($data,$options) { - // 关联写入 - if(!empty($options['link'])) - $this->opRelation('ADD',$data,$options['link']); - } - - // 更新成功后的回调方法 - protected function _after_update($data,$options) { - // 关联更新 - if(!empty($options['link'])) - $this->opRelation('SAVE',$data,$options['link']); - } - - // 删除成功后的回调方法 - protected function _after_delete($data,$options) { - // 关联删除 - if(!empty($options['link'])) - $this->opRelation('DEL',$data,$options['link']); - } - - /** - * 对保存到数据库的数据进行处理 - * @access protected - * @param mixed $data 要操作的数据 - * @return boolean - */ - protected function _write_data($data) { - $this->_before_write($data); - return $data; - } - - /** - * 获取返回数据集的关联记录 - * @access protected - * @param array $resultSet 返回数据 - * @param string|array $name 关联名称 - * @return array - */ - protected function getRelations(&$resultSet,$name='') { - // 获取记录集的主键列表 - foreach($resultSet as $key=>$val) { - $val = $this->getRelation($val,$name); - $resultSet[$key] = $val; - } - return $resultSet; - } - - /** - * 获取返回数据的关联记录 - * @access protected - * @param mixed $result 返回数据 - * @param string|array $name 关联名称 - * @param boolean $return 是否返回关联数据本身 - * @return array - */ - protected function getRelation(&$result,$name='',$return=false) { - if(!empty($this->link)) { - foreach($this->link as $key=>$val) { - $mappingName = !empty($val['mapping_name'])?$val['mapping_name']:$key; // 映射名称 - if(empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName,$name))) { - $mappingType = !empty($val['mapping_type'])?$val['mapping_type']:$val; // 关联类型 - $mappingClass = !empty($val['class_name'])?$val['class_name']:$key; // 关联类名 - $mappingFields = !empty($val['mapping_fields'])?$val['mapping_fields']:'*'; // 映射字段 - $mappingCondition = !empty($val['condition'])?$val['condition']:'1=1'; // 关联条件 - $mappingKey =!empty($val['mapping_key'])? $val['mapping_key'] : $this->getPk(); // 关联键名 - if(strtoupper($mappingClass)==strtoupper($this->name)) { - // 自引用关联 获取父键名 - $mappingFk = !empty($val['parent_key'])? $val['parent_key'] : 'parent_id'; - }else{ - $mappingFk = !empty($val['foreign_key'])?$val['foreign_key']:strtolower($this->name).'_id'; // 关联外键 - } - // 获取关联模型对象 - $model = D($mappingClass); - switch($mappingType) { - case HAS_ONE: - $pk = $result[$mappingKey]; - $mappingCondition .= " AND {$mappingFk}='{$pk}'"; - $relationData = $model->where($mappingCondition)->field($mappingFields)->find(); - break; - case BELONGS_TO: - if(strtoupper($mappingClass)==strtoupper($this->name)) { - // 自引用关联 获取父键名 - $mappingFk = !empty($val['parent_key'])? $val['parent_key'] : 'parent_id'; - }else{ - $mappingFk = !empty($val['foreign_key'])?$val['foreign_key']:strtolower($model->getModelName()).'_id'; // 关联外键 - } - $fk = $result[$mappingFk]; - $mappingCondition .= " AND {$model->getPk()}='{$fk}'"; - $relationData = $model->where($mappingCondition)->field($mappingFields)->find(); - break; - case HAS_MANY: - $pk = $result[$mappingKey]; - $mappingCondition .= " AND {$mappingFk}='{$pk}'"; - $mappingOrder = !empty($val['mapping_order'])?$val['mapping_order']:''; - $mappingLimit = !empty($val['mapping_limit'])?$val['mapping_limit']:''; - // 延时获取关联记录 - $relationData = $model->where($mappingCondition)->field($mappingFields)->order($mappingOrder)->limit($mappingLimit)->select(); - break; - case MANY_TO_MANY: - $pk = $result[$mappingKey]; - $mappingCondition = " {$mappingFk}='{$pk}'"; - $mappingOrder = $val['mapping_order']; - $mappingLimit = $val['mapping_limit']; - $mappingRelationFk = $val['relation_foreign_key']?$val['relation_foreign_key']:$model->getModelName().'_id'; - $mappingRelationTable = $val['relation_table']?$val['relation_table']:$this->getRelationTableName($model); - $sql = "SELECT b.{$mappingFields} FROM {$mappingRelationTable} AS a, ".$model->getTableName()." AS b WHERE a.{$mappingRelationFk} = b.{$model->getPk()} AND a.{$mappingCondition}"; - if(!empty($val['condition'])) { - $sql .= ' AND '.$val['condition']; - } - if(!empty($mappingOrder)) { - $sql .= ' ORDER BY '.$mappingOrder; - } - if(!empty($mappingLimit)) { - $sql .= ' LIMIT '.$mappingLimit; - } - $relationData = $this->query($sql); - break; - } - if(!$return){ - if(isset($val['as_fields']) && in_array($mappingType,array(HAS_ONE,BELONGS_TO)) ) { - // 支持直接把关联的字段值映射成数据对象中的某个字段 - // 仅仅支持HAS_ONE BELONGS_TO - $fields = explode(',',$val['as_fields']); - foreach ($fields as $field){ - if(strpos($field,':')) { - list($relationName,$nick) = explode(':',$field); - $result[$nick] = $relationData[$relationName]; - }else{ - $result[$field] = $relationData[$field]; - } - } - }else{ - $result[$mappingName] = $relationData; - } - unset($relationData); - }else{ - return $relationData; - } - } - } - } - return $result; - } - - /** - * 操作关联数据 - * @access protected - * @param string $opType 操作方式 ADD SAVE DEL - * @param mixed $data 数据对象 - * @param string $name 关联名称 - * @return mixed - */ - protected function opRelation($opType,$data='',$name='') { - $result = false; - if(empty($data) && !empty($this->data)){ - $data = $this->data; - }elseif(!is_array($data)){ - // 数据无效返回 - return false; - } - if(!empty($this->link)) { - // 遍历关联定义 - foreach($this->link as $key=>$val) { - // 操作制定关联类型 - $mappingName = $val['mapping_name']?$val['mapping_name']:$key; // 映射名称 - if(empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName,$name)) ) { - // 操作制定的关联 - $mappingType = !empty($val['mapping_type'])?$val['mapping_type']:$val; // 关联类型 - $mappingClass = !empty($val['class_name'])?$val['class_name']:$key; // 关联类名 - $mappingKey =!empty($val['mapping_key'])? $val['mapping_key'] : $this->getPk(); // 关联键名 - // 当前数据对象主键值 - $pk = $data[$mappingKey]; - if(strtoupper($mappingClass)==strtoupper($this->name)) { - // 自引用关联 获取父键名 - $mappingFk = !empty($val['parent_key'])? $val['parent_key'] : 'parent_id'; - }else{ - $mappingFk = !empty($val['foreign_key'])?$val['foreign_key']:strtolower($this->name).'_id'; // 关联外键 - } - if(!empty($val['condition'])) { - $mappingCondition = $val['condition']; - }else{ - $mappingCondition = array(); - $mappingCondition[$mappingFk] = $pk; - } - // 获取关联model对象 - $model = D($mappingClass); - $mappingData = isset($data[$mappingName])?$data[$mappingName]:false; - if(!empty($mappingData) || $opType == 'DEL') { - switch($mappingType) { - case HAS_ONE: - switch (strtoupper($opType)){ - case 'ADD': // 增加关联数据 - $mappingData[$mappingFk] = $pk; - $result = $model->add($mappingData); - break; - case 'SAVE': // 更新关联数据 - $result = $model->where($mappingCondition)->save($mappingData); - break; - case 'DEL': // 根据外键删除关联数据 - $result = $model->where($mappingCondition)->delete(); - break; - } - break; - case BELONGS_TO: - break; - case HAS_MANY: - switch (strtoupper($opType)){ - case 'ADD' : // 增加关联数据 - $model->startTrans(); - foreach ($mappingData as $val){ - $val[$mappingFk] = $pk; - $result = $model->add($val); - } - $model->commit(); - break; - case 'SAVE' : // 更新关联数据 - $model->startTrans(); - $pk = $model->getPk(); - foreach ($mappingData as $vo){ - if(isset($vo[$pk])) {// 更新数据 - $mappingCondition = "$pk ={$vo[$pk]}"; - $result = $model->where($mappingCondition)->save($vo); - }else{ // 新增数据 - $vo[$mappingFk] = $data[$mappingKey]; - $result = $model->add($vo); - } - } - $model->commit(); - break; - case 'DEL' : // 删除关联数据 - $result = $model->where($mappingCondition)->delete(); - break; - } - break; - case MANY_TO_MANY: - $mappingRelationFk = $val['relation_foreign_key']?$val['relation_foreign_key']:$model->getModelName().'_id';// 关联 - $mappingRelationTable = $val['relation_table']?$val['relation_table']:$this->getRelationTableName($model); - if(is_array($mappingData)) { - $ids = array(); - foreach ($mappingData as $vo) - $ids[] = $vo[$mappingKey]; - $relationId = implode(',',$ids); - } - switch (strtoupper($opType)){ - case 'ADD': // 增加关联数据 - case 'SAVE': // 更新关联数据 - if(isset($relationId)) { - $this->startTrans(); - // 删除关联表数据 - $this->table($mappingRelationTable)->where($mappingCondition)->delete(); - // 插入关联表数据 - $sql = 'INSERT INTO '.$mappingRelationTable.' ('.$mappingFk.','.$mappingRelationFk.') SELECT a.'.$this->getPk().',b.'.$model->getPk().' FROM '.$this->getTableName().' AS a ,'.$model->getTableName()." AS b where a.".$this->getPk().' ='. $pk.' AND b.'.$model->getPk().' IN ('.$relationId.") "; - $result = $model->execute($sql); - if(false !== $result) - // 提交事务 - $this->commit(); - else - // 事务回滚 - $this->rollback(); - } - break; - case 'DEL': // 根据外键删除中间表关联数据 - $result = $this->table($mappingRelationTable)->where($mappingCondition)->delete(); - break; - } - break; - } - } - } - } - } - return $result; - } - - /** - * 进行关联查询 - * @access public - * @param mixed $name 关联名称 - * @return Model - */ - public function relation($name) { - $this->options['link'] = $name; - return $this; - } - - /** - * 关联数据获取 仅用于查询后 - * @access public - * @param string $name 关联名称 - * @return array - */ - public function relationGet($name) { - if(empty($this->data)) - return false; - return $this->getRelation($this->data,$name,true); - } -} \ No newline at end of file diff --git a/Traits/Think/Model/View.php b/Traits/Think/Model/View.php deleted file mode 100644 index 1f5589a2..00000000 --- a/Traits/Think/Model/View.php +++ /dev/null @@ -1,239 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Traits\Think\Model; - -trait View { - - protected $viewFields = []; - - /** - * 自动检测数据表信息 - * @access protected - * @return void - */ - protected function _checkTableInfo() {} - - /** - * 得到完整的数据表名 - * @access public - * @return string - */ - public function getTableName() { - if(empty($this->trueTableName)) { - $tableName = ''; - foreach ($this->viewFields as $key=>$view){ - // 获取数据表名称 - if(isset($view['_table'])) { // 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图 - $tableName .= $view['_table']; - }else{ - $class = $key.'Model'; - $Model = class_exists($class)?new $class():M($key); - $tableName .= $Model->getTableName(); - } - // 表别名定义 - $tableName .= !empty($view['_as'])?' '.$view['_as']:' '.$key; - // 支持ON 条件定义 - $tableName .= !empty($view['_on'])?' ON '.$view['_on']:''; - // 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效 - $type = !empty($view['_type'])?$view['_type']:''; - $tableName .= ' '.strtoupper($type).' JOIN '; - $len = strlen($type.'_JOIN '); - } - $tableName = substr($tableName,0,-$len); - $this->trueTableName = $tableName; - } - return $this->trueTableName; - } - - /** - * 表达式过滤方法 - * @access protected - * @param string $options 表达式 - * @return void - */ - protected function _options_filter(&$options) { - if(isset($options['field'])) - $options['field'] = $this->checkFields($options['field']); - else - $options['field'] = $this->checkFields(); - if(isset($options['group'])) - $options['group'] = $this->checkGroup($options['group']); - if(isset($options['where'])) - $options['where'] = $this->checkCondition($options['where']); - if(isset($options['order'])) - $options['order'] = $this->checkOrder($options['order']); - } - - /** - * 检查是否定义了所有字段 - * @access protected - * @param string $name 模型名称 - * @param array $fields 字段数组 - * @return array - */ - private function _checkFields($name,$fields) { - if(false !== $pos = array_search('*',$fields)) {// 定义所有字段 - $fields = array_merge($fields,M($name)->getDbFields()); - unset($fields[$pos]); - } - return $fields; - } - - /** - * 检查条件中的视图字段 - * @access protected - * @param mixed $data 条件表达式 - * @return array - */ - protected function checkCondition($where) { - if(is_array($where)) { - $view = []; - // 检查视图字段 - foreach ($this->viewFields as $key=>$val){ - $k = isset($val['_as'])?$val['_as']:$key; - $val = $this->_checkFields($key,$val); - foreach ($where as $name=>$value){ - if(false !== $field = array_search($name,$val,true)) { - // 存在视图字段 - $_key = is_numeric($field)? $k.'.'.$name : $k.'.'.$field; - $view[$_key] = $value; - unset($where[$name]); - } - } - } - $where = array_merge($where,$view); - } - return $where; - } - - /** - * 检查Order表达式中的视图字段 - * @access protected - * @param string $order 字段 - * @return string - */ - protected function checkOrder($order='') { - if(is_string($order) && !empty($order)) { - $orders = explode(',',$order); - $_order = []; - foreach ($orders as $order){ - $array = explode(' ',$order); - $field = $array[0]; - $sort = isset($array[1])?$array[1]:'ASC'; - // 解析成视图字段 - foreach ($this->viewFields as $name=>$val){ - $k = isset($val['_as'])?$val['_as']:$name; - $val = $this->_checkFields($name,$val); - if(false !== $_field = array_search($field,$val,true)) { - // 存在视图字段 - $field = is_numeric($_field)?$k.'.'.$field:$k.'.'.$_field; - break; - } - } - $_order[] = $field.' '.$sort; - } - $order = implode(',',$_order); - } - return $order; - } - - /** - * 检查Group表达式中的视图字段 - * @access protected - * @param string $group 字段 - * @return string - */ - protected function checkGroup($group='') { - if(!empty($group)) { - $groups = explode(',',$group); - $_group = []; - foreach ($groups as $field){ - // 解析成视图字段 - foreach ($this->viewFields as $name=>$val){ - $k = isset($val['_as'])?$val['_as']:$name; - $val = $this->_checkFields($name,$val); - if(false !== $_field = array_search($field,$val,true)) { - // 存在视图字段 - $field = is_numeric($_field)?$k.'.'.$field:$k.'.'.$_field; - break; - } - } - $_group[] = $field; - } - $group = implode(',',$_group); - } - return $group; - } - - /** - * 检查fields表达式中的视图字段 - * @access protected - * @param string $fields 字段 - * @return string - */ - protected function checkFields($fields='') { - if(empty($fields) || '*'==$fields ) { - // 获取全部视图字段 - $fields = []; - foreach ($this->viewFields as $name=>$val){ - $k = isset($val['_as'])?$val['_as']:$name; - $val = $this->_checkFields($name,$val); - foreach ($val as $key=>$field){ - if(is_numeric($key)) { - $fields[] = $k.'.'.$field.' AS '.$field; - }elseif('_' != substr($key,0,1)) { - // 以_开头的为特殊定义 - if( false !== strpos($key,'*') || false !== strpos($key,'(') || false !== strpos($key,'.')) { - //如果包含* 或者 使用了sql方法 则不再添加前面的表名 - $fields[] = $key.' AS '.$field; - }else{ - $fields[] = $k.'.'.$key.' AS '.$field; - } - } - } - } - $fields = implode(',',$fields); - }else{ - if(!is_array($fields)) - $fields = explode(',',$fields); - // 解析成视图字段 - $array = []; - foreach ($fields as $key=>$field){ - if(strpos($field,'(') || strpos(strtolower($field),' as ')){ - // 使用了函数或者别名 - $array[] = $field; - unset($fields[$key]); - } - } - foreach ($this->viewFields as $name=>$val){ - $k = isset($val['_as'])?$val['_as']:$name; - $val = $this->_checkFields($name,$val); - foreach ($fields as $key=>$field){ - if(false !== $_field = array_search($field,$val,true)) { - // 存在视图字段 - if(is_numeric($_field)) { - $array[] = $k.'.'.$field.' AS '.$field; - }elseif('_' != substr($_field,0,1)){ - if( false !== strpos($_field,'*') || false !== strpos($_field,'(') || false !== strpos($_field,'.')) - //如果包含* 或者 使用了sql方法 则不再添加前面的表名 - $array[] = $_field.' AS '.$field; - else - $array[] = $k.'.'.$_field.' AS '.$field; - } - } - } - } - $fields = implode(',',$array); - } - return $fields; - } -} \ No newline at end of file diff --git a/base.php b/base.php deleted file mode 100644 index 5a11f69b..00000000 --- a/base.php +++ /dev/null @@ -1,245 +0,0 @@ - -// +---------------------------------------------------------------------- - -if(version_compare(PHP_VERSION,'5.4.0','<')) die('require PHP > 5.4.0 !'); -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('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('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('APP_DEBUG') or define('APP_DEBUG', false); // 是否调试模式 - -if(function_exists('saeAutoLoader')){// 自动识别SAE环境 - defined('APP_MODE') or define('APP_MODE', 'sae'); - defined('STORAGE_TYPE') or define('STORAGE_TYPE', 'Sae'); -}else{ - defined('APP_MODE') or define('APP_MODE', 'common'); // 应用模式 默认为普通模式 - defined('STORAGE_TYPE') or define('STORAGE_TYPE', 'File'); // 存储类型 默认为File -} - -// 环境常量 -define('MEMORY_LIMIT_ON', function_exists('memory_get_usage')); -define('IS_CGI', strpos(PHP_SAPI, 'cgi') === 0 ? 1 : 0); -define('IS_WIN', strstr(PHP_OS, 'WIN') ? 1 : 0); -define('IS_CLI', PHP_SAPI=='cli' ? 1 : 0); -define('IS_AJAX', (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false); -define('NOW_TIME', $_SERVER['REQUEST_TIME']); -define('REQUEST_METHOD', $_SERVER['REQUEST_METHOD']); -define('IS_GET', REQUEST_METHOD =='GET' ? true : false); -define('IS_POST', REQUEST_METHOD =='POST' ? true : false); -define('IS_PUT', REQUEST_METHOD =='PUT' ? true : false); -define('IS_DELETE', REQUEST_METHOD =='DELETE' ? true : false); - -// 获取多语言变量 -function L($name){ - return Think\Lang::get($name); -} - -// 获取配置参数 -function C($name='',$range='') { - return Think\Config::get($name,$range); -} - -// 获取输入数据 支持默认值和过滤 -function I($key,$default='',$filter='') { - if(strpos($key,'.')) { // 指定参数来源 - list($method,$key) = explode('.',$key); - }else{ // 默认为自动判断 - $method = 'param'; - } - return Think\Input::$method($key,$filter,$default); -} - -/** - * 记录时间(微秒)和内存使用情况 - * @param string $label 记录标签 - * @return void - */ -function G($label) { - Think\Debug::remark($label); -} - -/** - * 实例化一个没有模型文件的Model - * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User - * @param string $tablePrefix 表前缀 - * @param mixed $connection 数据库连接信息 - * @return Model - */ -function M($name='', $tablePrefix='',$connection='') { - return Think\Loader::table($name,['table_prefix'=>$tablePrefix,'connection'=>$connection]); -} - -/** - * 实例化Model - * @param string $name Model名称 - * @param string $layer 业务层名称 - * @return object - */ -function D($name='',$layer='Model') { - return Think\Loader::model($name,$layer); -} - -/** - * 实例化数据库类 - * @param array $config 数据库配置参数 - * @param boolean $lite 是否lite连接 - * @return object - */ -function db($config=[],$lite=false) { - return Think\Db::instance($config,$lite); -} - -/** - * 实例化控制器 格式:[模块/]控制器 - * @param string $name 资源地址 - * @param string $layer 控制层名称 - * @return object - */ -function A($name,$layer='Controller') { - return Think\Loader::controller($name,$layer); -} - -/** - * 调用模块的操作方法 参数格式 [模块/控制器/]操作 - * @param string $url 调用地址 - * @param string|array $vars 调用参数 支持字符串和数组 - * @param string $layer 要调用的控制层名称 - * @return mixed - */ -function R($url,$vars=[],$layer='Controller') { - return Think\Loader::action($url,$vars,$layer); -} - -/** - * 导入所需的类库 同java的Import 本函数有缓存功能 - * @param string $class 类库命名空间字符串 - * @param string $baseUrl 起始路径 - * @param string $ext 导入的文件扩展名 - * @return boolean - */ -function import($class, $baseUrl = '', $ext= EXT ) { - return Think\Loader::import($class,$baseUrl,$ext); -} - -/** - * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面 - * @param string $class 类库 - * @param string $ext 类库后缀 - * @return boolean - */ -function vendor($class, $ext=EXT) { - return Think\Loader::import($class, VENDOR_PATH, $ext); -} - -/** - * 快速导入Traits - * @param string $class trait库 - * @param string $ext 类库后缀 - * @return boolean - */ -function T($class,$ext=EXT){ - return Think\Loader::import($class, TRAIT_PATH, $ext); -} - -/** - * 抛出异常处理 - * @param string $msg 异常消息 - * @param integer $code 异常代码 默认为0 - * @return void - */ -function E($msg, $code=0) { - throw new Think\Exception($msg, $code); -} - -/** - * 浏览器友好的变量输出 - * @param mixed $var 变量 - * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串 - * @param string $label 标签 默认为空 - * @return void|string - */ -function dump($var, $echo=true, $label=null) { - return Think\Debug::dump($var,$echo,$label); -} - -/** - * 渲染输出Widget - * @param string $name Widget名称 - * @param array $data 传人的参数 - * @return void - */ -function W($name, $data=[]) { - return Think\Loader::action($name,$data,'Widget'); -} - -/** - * 缓存管理 - * @param mixed $name 缓存名称,如果为数组表示进行缓存设置 - * @param mixed $value 缓存值 - * @param mixed $options 缓存参数 - * @return mixed - */ -function S($name,$value='',$options=null) { - static $cache = null; - if(is_array($options)){// 缓存操作的同时初始化 - $cache = Think\Cache::connect($options); - }elseif(is_array($name)) { // 缓存初始化 - $cache = Think\Cache::connect($name); - return $cache; - }elseif(is_null($cache)) {// 自动初始化 - $cache = Think\Cache::connect(); - } - if(''=== $value){ // 获取缓存 - return $cache->get($name); - }elseif(is_null($value)) { // 删除缓存 - return $cache->rm($name); - }else { // 缓存数据 - if(is_array($options)) { - $expire = isset($options['expire'])?$options['expire']:null; //修复查询缓存无法设置过期时间 - }else{ - $expire = is_numeric($options)?$options:null; //默认快捷缓存设置过期时间 - } - return $cache->set($name, $value, $expire); - } -} - -/** - * 字符串命名风格转换 - * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 - * @param string $name 字符串 - * @param integer $type 转换类型 - * @return string - */ -function parse_name($name, $type=0) { - if ($type) { - 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 deleted file mode 100644 index f75590ac..00000000 --- a/start.php +++ /dev/null @@ -1,49 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace Think; - -//-------------------------- -// ThinkPHP 引导文件 -//-------------------------- - -// 加载基础文件 -require __DIR__.'/base.php'; -require CORE_PATH.'loader.php'; - -// 注册自动加载 -Loader::register(); - -// 注册错误和异常处理机制 -register_shutdown_function(['Think\Error','appShutdown']); -set_error_handler(['Think\Error','appError']); -set_exception_handler(['Think\Error','appException']); - -// 加载模式定义文件 -$mode = require MODE_PATH.APP_MODE.EXT; - -// 加载模式别名定义 -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']); -} - -// 执行应用 -App::run(Config::get());