diff --git a/framework/control.class.php b/framework/control.class.php index 86792e7ede..52ea202626 100755 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -1,488 +1,475 @@ -. - * - * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) - * @author Chunsheng Wang - * @package ZenTaoPHP - * @version $Id: control.class.php 133 2010-09-11 07:22:48Z wwccss $ - * @link http://www.zentao.net - */ - -/** - * 控制器基类。 - * - * @package ZenTaoPHP - */ -class control -{ - /** - * 全局的$app对象。 - * - * @var object - * @access protected - */ - protected $app; - - /** - * 全局的$config对象。 - * - * @var object - * @access protected - */ - protected $config; - - /** - * 全局的$lang对象。 - * - * @var object - * @access protected - */ - protected $lang; - - /** - * 全局的$dbh(数据库访问句柄)对象。 - * - * @var object - * @access protected - */ - protected $dbh; - - /** - * dao对象。 - * - * @var object - * @access protected - */ - public $dao; - - /** - * POST对象。 - * - * @var ojbect - * @access public - */ - public $post; - - /** - * get对象。 - * - * @var ojbect - * @access public - */ - public $get; - - /** - * session对象。 - * - * @var ojbect - * @access public - */ - public $session; - - /** - * server对象。 - * - * @var ojbect - * @access public - */ - public $server; - - /** - * cookie对象。 - * - * @var ojbect - * @access public - */ - public $cookie; - - /** - * global对象。 - * - * @var ojbect - * @access public - */ - public $global; - - /** - * 所属模块的名字。 - * - * @var string - * @access protected - */ - protected $moduleName; - - /** - * 记录赋值到view的所有变量。 - * - * @var object - * @access public - */ - public $view; - - /** - * 视图类型 - * - * @var string - * @access private - */ - private $viewType; - - /** - * 要输出的内容。 - * - * @var string - * @access private - */ - private $output; - - /** - * 路径分隔符。 - * - * @var string - * @access protected - */ - protected $pathFix; - - /** - * 构造函数: - * - * 1. 引用全局对象,使之可以通过成员变量访问。 - * 2. 设置模块相应的路径信息,并加载对应的model文件。 - * 3. 自动将$lang和$config赋值到模板。 - * - * @access public - * @return void - */ - public function __construct($moduleName = '', $methodName = '') - { - /* 引用全局对象,并赋值。*/ - global $app, $config, $lang, $dbh; - $this->app = $app; - $this->config = $config; - $this->lang = $lang; - $this->dbh = $dbh; - $this->pathFix = $this->app->getPathFix(); - $this->viewType = $this->app->getViewType(); - - $this->setModuleName($moduleName); - $this->setMethodName($methodName); - - /* 自动加载当前模块的model文件。*/ - $this->loadModel(); - - /* 自动将$app, $config和$lang赋值到模板中。*/ - $this->assign('app', $app); - $this->assign('lang', $lang); - $this->assign('config', $config); - - if(isset($config->super2OBJ) and $config->super2OBJ) $this->setSuperVars(); - } - - //-------------------- model相关的方法。--------------------// - // - /* 设置模块名。*/ - private function setModuleName($moduleName = '') - { - $this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName(); - } - - /* 设置方法名。*/ - private function setMethodName($methodName = '') - { - $this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName(); - } - - /** - * 加载某一个模块的model文件。 - * - * @param string $moduleName 模块名字,如果为空,则取当前的模块名作为model名。 - * @access public - * @return void - */ - public function loadModel($moduleName = '') - { - /* 如果没有指定module名,则取当前加载的模块的名作为model名。*/ - if(empty($moduleName)) $moduleName = $this->moduleName; - $modelFile = helper::setModelFile($moduleName); - if(!file_exists($modelFile)) return false; - - helper::import($modelFile); - $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; - if(!class_exists($modelClass)) $this->app->error(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); - - $this->$moduleName = new $modelClass(); - if(isset($this->config->db->dao) and $this->config->db->dao) $this->dao = $this->$moduleName->dao; - return $this->$moduleName; - } - - /** - * 设置超全局变量。 - * - * @access protected - * @return void - */ - protected function setSuperVars() - { - $this->post = $this->app->post; - $this->get = $this->app->get; - $this->server = $this->app->server; - $this->session = $this->app->session; - $this->cookie = $this->app->cookie; - $this->global = $this->app->global; - } - - //-------------------- 加载view相关的方法。--------------------// - /** - * 设置视图文件。 - * - * 某一个module的控制器可以加载另外一个module的视图文件。 - * - * @param string $moduleName 模块名。 - * @param string $methodName 方法名。 - * @access private - * @return string 对应的视图文件。 - */ - private function setViewFile($moduleName, $methodName) - { - $moduleName = strtolower(trim($moduleName)); - $methodName = strtolower(trim($methodName)); - - $modulePath = $this->app->getModulePath($moduleName); - $viewExtPath = $this->app->getModuleExtPath($moduleName, 'view'); - - /* 主视图文件,扩展视图文件和扩展钩子文件。*/ - $mainViewFile = $modulePath . 'view' . $this->pathFix . $methodName . '.' . $this->viewType . '.php'; - $extViewFile = $viewExtPath . $methodName . ".{$this->viewType}.php"; - $extHookFile = $viewExtPath . $methodName . ".{$this->viewType}.hook.php"; - - $viewFile = file_exists($extViewFile) ? $extViewFile : $mainViewFile; - if(!file_exists($viewFile)) $this->app->error("the view file $viewFile not found", __FILE__, __LINE__, $exit = true); - if(file_exists($extHookFile)) return array('viewFile' => $viewFile, 'hookFile' => $extHookFile); - return $viewFile; - } - - /* 加载某一个视图文件所对应的扩展视图文件。*/ - public function getExtViewFile($viewFile) - { - $extPath = dirname(dirname(realpath($viewFile))) . '/opt/view/'; - $extViewFile = $extPath . basename($viewFile); - if(file_exists($extViewFile)) - { - helper::cd($extPath); - return $extViewFile; - } - } - - /** - * 赋值一个变量到view视图。 - * - * @param string $name 赋值到视图文件中的变量名。 - * @param mixed $value 所对应的值。 - * @access public - * @return void - */ - public function assign($name, $value) - { - $this->view->$name = $value; - } - - /** - * 重置output内容。 - * - * @access public - * @return void - */ - public function clear() - { - $this->output = ''; - } - - /** - * 解析视图文件。 - * - * 如果没有指定模块名和方法名,则取当前模块的当前方法。 - * - * @param string $moduleName 模块名。 - * @param string $methodName 方法名。 - * @access public - * @return void - */ - public function parse($moduleName = '', $methodName = '') - { - if(empty($moduleName)) $moduleName = $this->moduleName; - if(empty($methodName)) $methodName = $this->methodName; - - if($this->viewType == 'json') - { - $this->parseJSON($moduleName, $methodName); - } - else - { - $this->parseDefault($moduleName, $methodName); - } - return $this->output; - } - - /* 解析JSON格式的输出。*/ - private function parseJSON($moduleName, $methodName) - { - unset($this->view->app); - unset($this->view->config); - unset($this->view->lang); - unset($this->view->pager); - unset($this->view->header); - unset($this->view->position); - unset($this->view->moduleTree); - - $output['status'] = is_object($this->view) ? 'success' : 'fail'; - $output['data'] = json_encode($this->view); - $output['md5'] = md5(json_encode($this->view)); - $this->output = json_encode($output); - } - - /* 默认的输出。*/ - private function parseDefault($moduleName, $methodName) - { - /* 设置视图文件。*/ - $viewFile = $this->setViewFile($moduleName, $methodName); - if(is_array($viewFile)) extract($viewFile); - - /* 切换到视图文件所在的目录,以保证视图文件中的包含路径有效。*/ - $currentPWD = getcwd(); - chdir(dirname($viewFile)); - - extract((array)$this->view); - ob_start(); - include $viewFile; - if(isset($hookFile)) include $hookFile; - $this->output .= ob_get_contents(); - ob_end_clean(); - - /* 最后还要切换到原来的目录。*/ - chdir($currentPWD); - } - - /** - * 获取某一个模块的某一个方法的内容。 - * - * 如果没有指定模块名,则取当前模块当前方法的视图。如果指定了模块和方法,则调用对应的模块方法的视图内容。 - * - * @param string $moduleName 模块名。 - * @param string $methodName 方法名。 - * @param array $params 方法参数。 - * @access public - * @return string - */ - public function fetch($moduleName = '', $methodName = '', $params = array()) - { - if($moduleName == '') $moduleName = $this->moduleName; - if($methodName == '') $methodName = $this->methodName; - if($moduleName == $this->moduleName and $methodName == $this->methodName) - { - $this->parse($moduleName, $methodName); - return $this->output; - } - - /* 设置被调用的模块的路径及相应的文件。*/ - $modulePath = $this->app->getModulePath($moduleName); - $moduleControlFile = $modulePath . 'control.php'; - $actionExtFile = $this->app->getModuleExtPath($moduleName, 'control') . strtolower($methodName) . '.php'; - $file2Included = file_exists($actionExtFile) ? $actionExtFile : $moduleControlFile; - - /* 加载控制文件。*/ - if(!file_exists($file2Included)) $this->app->error("The control file $file2Included not found", __FILE__, __LINE__, $exit = true); - $currentPWD = getcwd(); - chdir(dirname($file2Included)); - if($moduleName != $this->moduleName) helper::import($file2Included); - - /* 设置要调用的类的名称。*/ - $className = class_exists("ext$moduleName") ? "ext$moduleName" : $moduleName; - if(!class_exists($className)) $this->app->error(" The class $className not found", __FILE__, __LINE__, $exit = true); - - /* 处理参数,生成对象。*/ - if(!is_array($params)) parse_str($params, $params); - $module = new $className($moduleName, $methodName); - - /* 调用方法,获得输出。*/ - ob_start(); - call_user_func_array(array($module, $methodName), $params); - $output = ob_get_contents(); - ob_end_clean(); - - unset($module); - chdir($currentPWD); - return $output; - } - - /** - * 显示视图内容。 - * - * @param string $moduleName 模块名。 - * @param string $methodName 方法名。 - * @access public - * @return void - */ - public function display($moduleName = '', $methodName = '') - { - if(empty($this->output)) $this->parse($moduleName, $methodName); - echo $this->output; - if($this->viewType == 'json') die(); - } - - /** - * 生成某一个模块某个方法的链接。 - * - * @param string $moduleName 模块名。 - * @param string $methodName 方法名。 - * @param mixed $vars 要传递的参数,可以是数组,array('var1'=>'value1')。也可以是var1=value1&var2=value2的形式。 - * @param string $viewType 视图格式。 - * @access public - * @return string - */ - public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '') - { - if(empty($moduleName)) $moduleName = $this->moduleName; - return helper::createLink($moduleName, $methodName, $vars, $viewType); - } - - /** - * 生成对本模块某个方法的链接。 - * - * @param string $methodName 方法名。 - * @param mixed $vars 要传递的参数,可以是数组,array('var1'=>'value1')。也可以是var1=value1&var2=value2的形式。 - * @param string $viewType 视图格式。 - * @access public - * @return string - */ - public function inlink($methodName = 'index', $vars = array(), $viewType = '') - { - return helper::createLink($this->moduleName, $methodName, $vars, $viewType); - } - - /** - * 跳转到另外一个页面。 - * - * @param string $url 要跳转的url地址。 - * @access public - * @return void - */ - public function locate($url) - { - header("location: $url"); - exit; - } -} + + * @package ZenTaoPHP + * @version $Id: control.class.php 133 2010-09-11 07:22:48Z wwccss $ + * @link http://www.zentao.net + */ + +/** + * 控制器基类。 + * + * @package ZenTaoPHP + */ +class control +{ + /** + * 全局的$app对象。 + * + * @var object + * @access protected + */ + protected $app; + + /** + * 全局的$config对象。 + * + * @var object + * @access protected + */ + protected $config; + + /** + * 全局的$lang对象。 + * + * @var object + * @access protected + */ + protected $lang; + + /** + * 全局的$dbh(数据库访问句柄)对象。 + * + * @var object + * @access protected + */ + protected $dbh; + + /** + * dao对象。 + * + * @var object + * @access protected + */ + public $dao; + + /** + * POST对象。 + * + * @var ojbect + * @access public + */ + public $post; + + /** + * get对象。 + * + * @var ojbect + * @access public + */ + public $get; + + /** + * session对象。 + * + * @var ojbect + * @access public + */ + public $session; + + /** + * server对象。 + * + * @var ojbect + * @access public + */ + public $server; + + /** + * cookie对象。 + * + * @var ojbect + * @access public + */ + public $cookie; + + /** + * global对象。 + * + * @var ojbect + * @access public + */ + public $global; + + /** + * 所属模块的名字。 + * + * @var string + * @access protected + */ + protected $moduleName; + + /** + * 记录赋值到view的所有变量。 + * + * @var object + * @access public + */ + public $view; + + /** + * 视图类型 + * + * @var string + * @access private + */ + private $viewType; + + /** + * 要输出的内容。 + * + * @var string + * @access private + */ + private $output; + + /** + * 路径分隔符。 + * + * @var string + * @access protected + */ + protected $pathFix; + + /** + * 构造函数: + * + * 1. 引用全局对象,使之可以通过成员变量访问。 + * 2. 设置模块相应的路径信息,并加载对应的model文件。 + * 3. 自动将$lang和$config赋值到模板。 + * + * @access public + * @return void + */ + public function __construct($moduleName = '', $methodName = '') + { + /* 引用全局对象,并赋值。*/ + global $app, $config, $lang, $dbh; + $this->app = $app; + $this->config = $config; + $this->lang = $lang; + $this->dbh = $dbh; + $this->pathFix = $this->app->getPathFix(); + $this->viewType = $this->app->getViewType(); + + $this->setModuleName($moduleName); + $this->setMethodName($methodName); + + /* 自动加载当前模块的model文件。*/ + $this->loadModel(); + + /* 自动将$app, $config和$lang赋值到模板中。*/ + $this->assign('app', $app); + $this->assign('lang', $lang); + $this->assign('config', $config); + + if(isset($config->super2OBJ) and $config->super2OBJ) $this->setSuperVars(); + } + + //-------------------- model相关的方法。--------------------// + // + /* 设置模块名。*/ + private function setModuleName($moduleName = '') + { + $this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName(); + } + + /* 设置方法名。*/ + private function setMethodName($methodName = '') + { + $this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName(); + } + + /** + * 加载某一个模块的model文件。 + * + * @param string $moduleName 模块名字,如果为空,则取当前的模块名作为model名。 + * @access public + * @return void + */ + public function loadModel($moduleName = '') + { + /* 如果没有指定module名,则取当前加载的模块的名作为model名。*/ + if(empty($moduleName)) $moduleName = $this->moduleName; + $modelFile = helper::setModelFile($moduleName); + if(!file_exists($modelFile)) return false; + + helper::import($modelFile); + $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; + if(!class_exists($modelClass)) $this->app->error(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + + $this->$moduleName = new $modelClass(); + if(isset($this->config->db->dao) and $this->config->db->dao) $this->dao = $this->$moduleName->dao; + return $this->$moduleName; + } + + /** + * 设置超全局变量。 + * + * @access protected + * @return void + */ + protected function setSuperVars() + { + $this->post = $this->app->post; + $this->get = $this->app->get; + $this->server = $this->app->server; + $this->session = $this->app->session; + $this->cookie = $this->app->cookie; + $this->global = $this->app->global; + } + + //-------------------- 加载view相关的方法。--------------------// + /** + * 设置视图文件。 + * + * 某一个module的控制器可以加载另外一个module的视图文件。 + * + * @param string $moduleName 模块名。 + * @param string $methodName 方法名。 + * @access private + * @return string 对应的视图文件。 + */ + private function setViewFile($moduleName, $methodName) + { + $moduleName = strtolower(trim($moduleName)); + $methodName = strtolower(trim($methodName)); + + $modulePath = $this->app->getModulePath($moduleName); + $viewExtPath = $this->app->getModuleExtPath($moduleName, 'view'); + + /* 主视图文件,扩展视图文件和扩展钩子文件。*/ + $mainViewFile = $modulePath . 'view' . $this->pathFix . $methodName . '.' . $this->viewType . '.php'; + $extViewFile = $viewExtPath . $methodName . ".{$this->viewType}.php"; + $extHookFile = $viewExtPath . $methodName . ".{$this->viewType}.hook.php"; + + $viewFile = file_exists($extViewFile) ? $extViewFile : $mainViewFile; + if(!file_exists($viewFile)) $this->app->error("the view file $viewFile not found", __FILE__, __LINE__, $exit = true); + if(file_exists($extHookFile)) return array('viewFile' => $viewFile, 'hookFile' => $extHookFile); + return $viewFile; + } + + /* 加载某一个视图文件所对应的扩展视图文件。*/ + public function getExtViewFile($viewFile) + { + $extPath = dirname(dirname(realpath($viewFile))) . '/opt/view/'; + $extViewFile = $extPath . basename($viewFile); + if(file_exists($extViewFile)) + { + helper::cd($extPath); + return $extViewFile; + } + } + + /** + * 赋值一个变量到view视图。 + * + * @param string $name 赋值到视图文件中的变量名。 + * @param mixed $value 所对应的值。 + * @access public + * @return void + */ + public function assign($name, $value) + { + $this->view->$name = $value; + } + + /** + * 重置output内容。 + * + * @access public + * @return void + */ + public function clear() + { + $this->output = ''; + } + + /** + * 解析视图文件。 + * + * 如果没有指定模块名和方法名,则取当前模块的当前方法。 + * + * @param string $moduleName 模块名。 + * @param string $methodName 方法名。 + * @access public + * @return void + */ + public function parse($moduleName = '', $methodName = '') + { + if(empty($moduleName)) $moduleName = $this->moduleName; + if(empty($methodName)) $methodName = $this->methodName; + + if($this->viewType == 'json') + { + $this->parseJSON($moduleName, $methodName); + } + else + { + $this->parseDefault($moduleName, $methodName); + } + return $this->output; + } + + /* 解析JSON格式的输出。*/ + private function parseJSON($moduleName, $methodName) + { + unset($this->view->app); + unset($this->view->config); + unset($this->view->lang); + unset($this->view->pager); + unset($this->view->header); + unset($this->view->position); + unset($this->view->moduleTree); + + $output['status'] = is_object($this->view) ? 'success' : 'fail'; + $output['data'] = json_encode($this->view); + $output['md5'] = md5(json_encode($this->view)); + $this->output = json_encode($output); + } + + /* 默认的输出。*/ + private function parseDefault($moduleName, $methodName) + { + /* 设置视图文件。*/ + $viewFile = $this->setViewFile($moduleName, $methodName); + if(is_array($viewFile)) extract($viewFile); + + /* 切换到视图文件所在的目录,以保证视图文件中的包含路径有效。*/ + $currentPWD = getcwd(); + chdir(dirname($viewFile)); + + extract((array)$this->view); + ob_start(); + include $viewFile; + if(isset($hookFile)) include $hookFile; + $this->output .= ob_get_contents(); + ob_end_clean(); + + /* 最后还要切换到原来的目录。*/ + chdir($currentPWD); + } + + /** + * 获取某一个模块的某一个方法的内容。 + * + * 如果没有指定模块名,则取当前模块当前方法的视图。如果指定了模块和方法,则调用对应的模块方法的视图内容。 + * + * @param string $moduleName 模块名。 + * @param string $methodName 方法名。 + * @param array $params 方法参数。 + * @access public + * @return string + */ + public function fetch($moduleName = '', $methodName = '', $params = array()) + { + if($moduleName == '') $moduleName = $this->moduleName; + if($methodName == '') $methodName = $this->methodName; + if($moduleName == $this->moduleName and $methodName == $this->methodName) + { + $this->parse($moduleName, $methodName); + return $this->output; + } + + /* 设置被调用的模块的路径及相应的文件。*/ + $modulePath = $this->app->getModulePath($moduleName); + $moduleControlFile = $modulePath . 'control.php'; + $actionExtFile = $this->app->getModuleExtPath($moduleName, 'control') . strtolower($methodName) . '.php'; + $file2Included = file_exists($actionExtFile) ? $actionExtFile : $moduleControlFile; + + /* 加载控制文件。*/ + if(!file_exists($file2Included)) $this->app->error("The control file $file2Included not found", __FILE__, __LINE__, $exit = true); + $currentPWD = getcwd(); + chdir(dirname($file2Included)); + if($moduleName != $this->moduleName) helper::import($file2Included); + + /* 设置要调用的类的名称。*/ + $className = class_exists("ext$moduleName") ? "ext$moduleName" : $moduleName; + if(!class_exists($className)) $this->app->error(" The class $className not found", __FILE__, __LINE__, $exit = true); + + /* 处理参数,生成对象。*/ + if(!is_array($params)) parse_str($params, $params); + $module = new $className($moduleName, $methodName); + + /* 调用方法,获得输出。*/ + ob_start(); + call_user_func_array(array($module, $methodName), $params); + $output = ob_get_contents(); + ob_end_clean(); + + unset($module); + chdir($currentPWD); + return $output; + } + + /** + * 显示视图内容。 + * + * @param string $moduleName 模块名。 + * @param string $methodName 方法名。 + * @access public + * @return void + */ + public function display($moduleName = '', $methodName = '') + { + if(empty($this->output)) $this->parse($moduleName, $methodName); + echo $this->output; + if($this->viewType == 'json') die(); + } + + /** + * 生成某一个模块某个方法的链接。 + * + * @param string $moduleName 模块名。 + * @param string $methodName 方法名。 + * @param mixed $vars 要传递的参数,可以是数组,array('var1'=>'value1')。也可以是var1=value1&var2=value2的形式。 + * @param string $viewType 视图格式。 + * @access public + * @return string + */ + public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '') + { + if(empty($moduleName)) $moduleName = $this->moduleName; + return helper::createLink($moduleName, $methodName, $vars, $viewType); + } + + /** + * 生成对本模块某个方法的链接。 + * + * @param string $methodName 方法名。 + * @param mixed $vars 要传递的参数,可以是数组,array('var1'=>'value1')。也可以是var1=value1&var2=value2的形式。 + * @param string $viewType 视图格式。 + * @access public + * @return string + */ + public function inlink($methodName = 'index', $vars = array(), $viewType = '') + { + return helper::createLink($this->moduleName, $methodName, $vars, $viewType); + } + + /** + * 跳转到另外一个页面。 + * + * @param string $url 要跳转的url地址。 + * @access public + * @return void + */ + public function locate($url) + { + header("location: $url"); + exit; + } +} diff --git a/framework/helper.class.php b/framework/helper.class.php index 7e61c8eef6..ec0a31f6a9 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -1,387 +1,374 @@ -. - * - * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) - * @author Chunsheng Wang - * @package ZenTaoPHP - * @version $Id: helper.class.php 138 2010-10-08 03:40:48Z wwccss $ - * @link http://www.zentao.net - */ -/** - * 工具类对象,存放着各种杂项的工具方法。 - * - * @package ZenTaoPHP - */ -class helper -{ - /** - * 为一个对象设置某一个属性,其中key可以是“father.child”的形式。 - * - * - * db->user = 'wwccss'; - * helper::setMember('lang', 'db.user', 'chunsheng.wang'); - * ?> - * - * @param string $objName 对象变量名。 - * @param string $key 要设置的属性,可以是father.child的形式。 - * @param mixed $value 要设置的值。 - * @static - * @access public - * @return void - */ - static public function setMember($objName, $key, $value) - { - global $$objName; - if(!is_object($$objName) or empty($key)) return false; - $key = str_replace('.', '->', $key); - $value = serialize($value); - $code = ("\$${objName}->{$key}=unserialize(<< - * 'value1', 'var2' => 'value2'); - * ?> - * - * @param string $moduleName 模块名。 - * @param string $methodName 方法名。 - * @param mixed $vars 要传递给method方法的各个参数,可以是数组,也可以是var1=value2&var2=value2的形式。 - * @param string $viewType 扩展名方式。 - * @static - * @access public - * @return string - */ - static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '') - { - global $app, $config; - - $link = $config->webRoot; - if($config->requestType == 'GET') - { - if(strpos($_SERVER['SCRIPT_NAME'], 'index.php') === false) - { - $link = $_SERVER['SCRIPT_NAME']; - } - } - - if(empty($viewType)) $viewType = $app->getViewType(); - - /* 如果传递进来的vars不是数组,尝试将其解析成数组格式。*/ - if(!is_array($vars)) parse_str($vars, $vars); - if($config->requestType == 'PATH_INFO') - { - $link .= "$moduleName{$config->requestFix}$methodName"; - if($config->pathType == 'full') - { - foreach($vars as $key => $value) $link .= "{$config->requestFix}$key{$config->requestFix}$value"; - } - else - { - foreach($vars as $value) $link .= "{$config->requestFix}$value"; - } - /* 如果访问的是/index/index.html,简化为/index.html。*/ - if($moduleName == $config->default->module and $methodName == $config->default->method) $link = $config->webRoot . 'index'; - $link .= '.' . $viewType; - } - elseif($config->requestType == 'GET') - { - $link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName"; - if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType; - foreach($vars as $key => $value) $link .= "&$key=$value"; - } - return $link; - } - - /** - * 将一个数组转成对象格式。此函数只是返回语句,需要eval。 - * - * - * - * - * @param array $array 要转换的数组。 - * @param string $objName 要转换成的对象的名字。 - * @param string $memberPath 成员变量路径,最开始为空,从根开始。 - * @param bool $firstRun 是否是第一次运行。 - * @static - * @access public - * @return void - */ - static public function array2Object($array, $objName, $memberPath = '', $firstRun = true) - { - if($firstRun) - { - if(!is_array($array) or empty($array)) return false; - } - static $code = ''; - $keys = array_keys($array); - foreach($keys as $keyNO => $key) - { - $value = $array[$key]; - if(is_int($key)) $key = 'item' . $key; - $memberID = $memberPath . '->' . $key; - if(!is_array($value)) - { - $value = addslashes($value); - $code .= "\$$objName$memberID='$value';\n"; - } - else - { - helper::array2object($value, $objName, $memberID, $firstRun = false); - } - } - return $code; - } - - /** - * 包含一个文件。router.class.php和control.class.php中包含文件都通过此函数来调用,这样保证文件不会重复加载。 - * - * @param string $file 要包含的文件的路径。 - * @static - * @access public - * @return void - */ - static public function import($file) - { - if(!file_exists($file)) return false; - static $includedFiles = array(); - if(!isset($includedFiles[$file])) - { - include $file; - $includedFiles[$file] = true; - return true; - } - return false; - } - - /** - * 设置model文件。 - * - * @param string $moduleName 模块名字。 - * @access private - * @return void - */ - static public function setModelFile($moduleName) - { - global $app; - - /* 设定主model文件和扩展路径,并获得所有的扩展文件。*/ - $mainModelFile = $app->getModulePath($moduleName) . 'model.php'; - $modelExtPath = $app->getModuleExtPath($moduleName, 'model'); - $extFiles = helper::ls($modelExtPath, '.php'); - - /* 不存在扩展文件,返回主配置文件。*/ - if(empty($extFiles)) return $mainModelFile; - - /* 存在扩展文件,判断是否需要更新。*/ - $mergedModelFile = $app->getTmpRoot() . 'model' . $app->getPathFix() . $moduleName . '.php'; - $needUpdate = false; - $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; - - if(filemtime($mainModelFile) > $lastTime) - { - $needUpdate = true; - } - else - { - foreach($extFiles as $extFile) - { - if(filemtime($extFile) > $lastTime) - { - $needUpdate = true; - break; - } - } - } - - /* 如果不需要更新,则直接返回合并之后的model文件。*/ - if(!$needUpdate) return $mergedModelFile; - - if($needUpdate) - { - /* 加载主的model文件,并获得其方法列表。*/ - helper::import($mainModelFile); - $modelMethods = get_class_methods($moduleName . 'model'); - foreach($modelMethods as $key => $modelMethod) $modelMethods[$key] = strtolower($modelMethod); - - /* 将主model文件读入数组。*/ - $modelLines = rtrim(file_get_contents($mainModelFile)); - $modelLines = rtrim($modelLines, '?>'); - $modelLines = rtrim($modelLines); - $modelLines = explode("\n", $modelLines); - $lines2Delete = array(count($modelLines) - 1); - $lines2Append = array(); - - /* 循环处理每个扩展方法文件。*/ - foreach($extFiles as $extFile) - { - $methodName = strtolower(basename($extFile, '.php')); - if(in_array($methodName, $modelMethods)) - { - $method = new ReflectionMethod($moduleName . 'model', $methodName); - $startLine = $method->getStartLine() - 1; - $endLine = $method->getEndLine() - 1; - $lines2Delete = array_merge($lines2Delete, range($startLine, $endLine)); - } - $extLines = explode("\n", ltrim(trim(file_get_contents($extFile)), 'getModuleName(), $methodName, $vars, $viewType); -} - -/* 循环一个数组。*/ -function cycle($items) -{ - static $i = 0; - if(!is_array($items)) $items = explode(',', $items); - if(!isset($items[$i])) $i = 0; - return $items[$i++]; -} + + * @package ZenTaoPHP + * @version $Id: helper.class.php 138 2010-10-08 03:40:48Z wwccss $ + * @link http://www.zentao.net + */ +/** + * 工具类对象,存放着各种杂项的工具方法。 + * + * @package ZenTaoPHP + */ +class helper +{ + /** + * 为一个对象设置某一个属性,其中key可以是“father.child”的形式。 + * + * + * db->user = 'wwccss'; + * helper::setMember('lang', 'db.user', 'chunsheng.wang'); + * ?> + * + * @param string $objName 对象变量名。 + * @param string $key 要设置的属性,可以是father.child的形式。 + * @param mixed $value 要设置的值。 + * @static + * @access public + * @return void + */ + static public function setMember($objName, $key, $value) + { + global $$objName; + if(!is_object($$objName) or empty($key)) return false; + $key = str_replace('.', '->', $key); + $value = serialize($value); + $code = ("\$${objName}->{$key}=unserialize(<< + * 'value1', 'var2' => 'value2'); + * ?> + * + * @param string $moduleName 模块名。 + * @param string $methodName 方法名。 + * @param mixed $vars 要传递给method方法的各个参数,可以是数组,也可以是var1=value2&var2=value2的形式。 + * @param string $viewType 扩展名方式。 + * @static + * @access public + * @return string + */ + static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '') + { + global $app, $config; + + $link = $config->webRoot; + if($config->requestType == 'GET') + { + if(strpos($_SERVER['SCRIPT_NAME'], 'index.php') === false) + { + $link = $_SERVER['SCRIPT_NAME']; + } + } + + if(empty($viewType)) $viewType = $app->getViewType(); + + /* 如果传递进来的vars不是数组,尝试将其解析成数组格式。*/ + if(!is_array($vars)) parse_str($vars, $vars); + if($config->requestType == 'PATH_INFO') + { + $link .= "$moduleName{$config->requestFix}$methodName"; + if($config->pathType == 'full') + { + foreach($vars as $key => $value) $link .= "{$config->requestFix}$key{$config->requestFix}$value"; + } + else + { + foreach($vars as $value) $link .= "{$config->requestFix}$value"; + } + /* 如果访问的是/index/index.html,简化为/index.html。*/ + if($moduleName == $config->default->module and $methodName == $config->default->method) $link = $config->webRoot . 'index'; + $link .= '.' . $viewType; + } + elseif($config->requestType == 'GET') + { + $link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName"; + if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType; + foreach($vars as $key => $value) $link .= "&$key=$value"; + } + return $link; + } + + /** + * 将一个数组转成对象格式。此函数只是返回语句,需要eval。 + * + * + * + * + * @param array $array 要转换的数组。 + * @param string $objName 要转换成的对象的名字。 + * @param string $memberPath 成员变量路径,最开始为空,从根开始。 + * @param bool $firstRun 是否是第一次运行。 + * @static + * @access public + * @return void + */ + static public function array2Object($array, $objName, $memberPath = '', $firstRun = true) + { + if($firstRun) + { + if(!is_array($array) or empty($array)) return false; + } + static $code = ''; + $keys = array_keys($array); + foreach($keys as $keyNO => $key) + { + $value = $array[$key]; + if(is_int($key)) $key = 'item' . $key; + $memberID = $memberPath . '->' . $key; + if(!is_array($value)) + { + $value = addslashes($value); + $code .= "\$$objName$memberID='$value';\n"; + } + else + { + helper::array2object($value, $objName, $memberID, $firstRun = false); + } + } + return $code; + } + + /** + * 包含一个文件。router.class.php和control.class.php中包含文件都通过此函数来调用,这样保证文件不会重复加载。 + * + * @param string $file 要包含的文件的路径。 + * @static + * @access public + * @return void + */ + static public function import($file) + { + if(!file_exists($file)) return false; + static $includedFiles = array(); + if(!isset($includedFiles[$file])) + { + include $file; + $includedFiles[$file] = true; + return true; + } + return false; + } + + /** + * 设置model文件。 + * + * @param string $moduleName 模块名字。 + * @access private + * @return void + */ + static public function setModelFile($moduleName) + { + global $app; + + /* 设定主model文件和扩展路径,并获得所有的扩展文件。*/ + $mainModelFile = $app->getModulePath($moduleName) . 'model.php'; + $modelExtPath = $app->getModuleExtPath($moduleName, 'model'); + $extFiles = helper::ls($modelExtPath, '.php'); + + /* 不存在扩展文件,返回主配置文件。*/ + if(empty($extFiles)) return $mainModelFile; + + /* 存在扩展文件,判断是否需要更新。*/ + $mergedModelFile = $app->getTmpRoot() . 'model' . $app->getPathFix() . $moduleName . '.php'; + $needUpdate = false; + $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; + + if(filemtime($mainModelFile) > $lastTime) + { + $needUpdate = true; + } + else + { + foreach($extFiles as $extFile) + { + if(filemtime($extFile) > $lastTime) + { + $needUpdate = true; + break; + } + } + } + + /* 如果不需要更新,则直接返回合并之后的model文件。*/ + if(!$needUpdate) return $mergedModelFile; + + if($needUpdate) + { + /* 加载主的model文件,并获得其方法列表。*/ + helper::import($mainModelFile); + $modelMethods = get_class_methods($moduleName . 'model'); + foreach($modelMethods as $key => $modelMethod) $modelMethods[$key] = strtolower($modelMethod); + + /* 将主model文件读入数组。*/ + $modelLines = rtrim(file_get_contents($mainModelFile)); + $modelLines = rtrim($modelLines, '?>'); + $modelLines = rtrim($modelLines); + $modelLines = explode("\n", $modelLines); + $lines2Delete = array(count($modelLines) - 1); + $lines2Append = array(); + + /* 循环处理每个扩展方法文件。*/ + foreach($extFiles as $extFile) + { + $methodName = strtolower(basename($extFile, '.php')); + if(in_array($methodName, $modelMethods)) + { + $method = new ReflectionMethod($moduleName . 'model', $methodName); + $startLine = $method->getStartLine() - 1; + $endLine = $method->getEndLine() - 1; + $lines2Delete = array_merge($lines2Delete, range($startLine, $endLine)); + } + $extLines = explode("\n", ltrim(trim(file_get_contents($extFile)), 'getModuleName(), $methodName, $vars, $viewType); +} + +/* 循环一个数组。*/ +function cycle($items) +{ + static $i = 0; + if(!is_array($items)) $items = explode(',', $items); + if(!isset($items[$i])) $i = 0; + return $items[$i++]; +} diff --git a/framework/model.class.php b/framework/model.class.php index ff808d6626..127e01f886 100755 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -1,228 +1,215 @@ -. - * - * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) - * @author Chunsheng Wang - * @package ZenTaoPHP - * @version $Id: model.class.php 135 2010-09-14 03:23:35Z yuren_@126.com $ - * @link http://www.zentao.net - */ -/** - * 模型基类。 - * - * @package ZenTaoPHP - */ -class model -{ - /** - * 全局的$app对象。 - * - * @var object - * @access protected - */ - protected $app; - - /** - * 全局的$config对象。 - * - * @var object - * @access protected - */ - protected $config; - - /** - * 全局的$lang对象。 - * - * @var object - * @access protected - */ - protected $lang; - - /** - * 全局的$dbh(数据库访问句柄)对象。 - * - * @var object - * @access protected - */ - protected $dbh; - - /** - * dao对象。 - * - * @var object - * @access protected - */ - public $dao; - - /** - * POST对象。 - * - * @var ojbect - * @access public - */ - public $post; - - /** - * get对象。 - * - * @var ojbect - * @access public - */ - public $get; - - /** - * session对象。 - * - * @var ojbect - * @access public - */ - public $session; - - /** - * server对象。 - * - * @var ojbect - * @access public - */ - public $server; - - /** - * cookie对象。 - * - * @var ojbect - * @access public - */ - public $cookie; - - /** - * global对象。 - * - * @var ojbect - * @access public - */ - public $global; - - /** - * 构造函数: - * - * 1. 引用全局变量,使之可以通过成员属性访问。 - * 2. 设置当前模块的路径、配置、语言等信息,并加载相应的文件。 - * - * @access public - * @return void - */ - public function __construct() - { - global $app, $config, $lang, $dbh; - $this->app = $app; - $this->config = $config; - $this->lang = $lang; - $this->dbh = $dbh; - - $moduleName = $this->getModuleName(); - $this->app->loadLang($moduleName, $exit = false); - $this->app->loadConfig($moduleName, $exit = false); - - if(isset($config->db->dao) and $config->db->dao) $this->loadDAO(); - if(isset($config->super2OBJ) and $config->super2OBJ) $this->setSuperVars(); - } - - /** - * 设置模块名:将类名中的model替换掉即为模块名。 - * 没有使用$app->getModule()方法,因为它返回的是当前调用的模块。 - * 而在一次请求中,当前模块的control文件很有可能会调用其他模块的model。 - * - * @access protected - * @return void - */ - protected function getModuleName() - { - $parentClass = get_parent_class($this); - $selfClass = get_class($this); - $className = $parentClass == 'model' ? $selfClass : $parentClass; - return strtolower(str_ireplace(array('ext', 'Model'), '', $className)); - } - - /** - * 设置超全局变量。 - * - * @access protected - * @return void - */ - protected function setSuperVars() - { - $this->post = $this->app->post; - $this->get = $this->app->get; - $this->server = $this->app->server; - $this->cookie = $this->app->cookie; - $this->session = $this->app->session; - $this->global = $this->app->global; - } - - /** - * 加载某一个模块的model文件。 - * - * @param string $moduleName 模块名字,如果为空,则取当前的模块名作为model名。 - * @access public - * @return void - */ - public function loadModel($moduleName) - { - if(empty($moduleName)) return false; - $modelFile = helper::setModelFile($moduleName); - if(!file_exists($modelFile)) return false; - - helper::import($modelFile); - $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; - if(!class_exists($modelClass)) $this->app->error(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); - - $this->$moduleName = new $modelClass(); - return $this->$moduleName; - } - - //-------------------- 数据库操作相应的方法。--------------------// - - /** - * 加载DAO类,并返回对象。 - * - * @access private - * @return void - */ - private function loadDAO() - { - $this->dao = $this->app->loadClass('dao'); - } - - /* 将一条记录标记为已删除。*/ - public function delete($table, $id) - { - $this->dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec(); - $object = str_replace($this->config->db->prefix, '', $table); - $this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED); - } - - /* 还原已经标记为删除的记录。*/ - public function undelete($actionID) - { - $action = $this->loadModel('action')->getById($actionID); - if($action->action != 'deleted') return; - $table = $this->config->action->objectTables[$action->objectType]; - $this->dao->update($table)->set('deleted')->eq(0)->where('id')->eq($action->objectID)->exec(); - $this->dao->update(TABLE_ACTION)->set('extra')->eq(ACTIONMODEL::BE_UNDELETED)->where('id')->eq($actionID)->exec(); - $this->action->create($action->objectType, $action->objectID, 'undeleted'); - } -} + + * @package ZenTaoPHP + * @version $Id: model.class.php 135 2010-09-14 03:23:35Z yuren_@126.com $ + * @link http://www.zentao.net + */ +/** + * 模型基类。 + * + * @package ZenTaoPHP + */ +class model +{ + /** + * 全局的$app对象。 + * + * @var object + * @access protected + */ + protected $app; + + /** + * 全局的$config对象。 + * + * @var object + * @access protected + */ + protected $config; + + /** + * 全局的$lang对象。 + * + * @var object + * @access protected + */ + protected $lang; + + /** + * 全局的$dbh(数据库访问句柄)对象。 + * + * @var object + * @access protected + */ + protected $dbh; + + /** + * dao对象。 + * + * @var object + * @access protected + */ + public $dao; + + /** + * POST对象。 + * + * @var ojbect + * @access public + */ + public $post; + + /** + * get对象。 + * + * @var ojbect + * @access public + */ + public $get; + + /** + * session对象。 + * + * @var ojbect + * @access public + */ + public $session; + + /** + * server对象。 + * + * @var ojbect + * @access public + */ + public $server; + + /** + * cookie对象。 + * + * @var ojbect + * @access public + */ + public $cookie; + + /** + * global对象。 + * + * @var ojbect + * @access public + */ + public $global; + + /** + * 构造函数: + * + * 1. 引用全局变量,使之可以通过成员属性访问。 + * 2. 设置当前模块的路径、配置、语言等信息,并加载相应的文件。 + * + * @access public + * @return void + */ + public function __construct() + { + global $app, $config, $lang, $dbh; + $this->app = $app; + $this->config = $config; + $this->lang = $lang; + $this->dbh = $dbh; + + $moduleName = $this->getModuleName(); + $this->app->loadLang($moduleName, $exit = false); + $this->app->loadConfig($moduleName, $exit = false); + + if(isset($config->db->dao) and $config->db->dao) $this->loadDAO(); + if(isset($config->super2OBJ) and $config->super2OBJ) $this->setSuperVars(); + } + + /** + * 设置模块名:将类名中的model替换掉即为模块名。 + * 没有使用$app->getModule()方法,因为它返回的是当前调用的模块。 + * 而在一次请求中,当前模块的control文件很有可能会调用其他模块的model。 + * + * @access protected + * @return void + */ + protected function getModuleName() + { + $parentClass = get_parent_class($this); + $selfClass = get_class($this); + $className = $parentClass == 'model' ? $selfClass : $parentClass; + return strtolower(str_ireplace(array('ext', 'Model'), '', $className)); + } + + /** + * 设置超全局变量。 + * + * @access protected + * @return void + */ + protected function setSuperVars() + { + $this->post = $this->app->post; + $this->get = $this->app->get; + $this->server = $this->app->server; + $this->cookie = $this->app->cookie; + $this->session = $this->app->session; + $this->global = $this->app->global; + } + + /** + * 加载某一个模块的model文件。 + * + * @param string $moduleName 模块名字,如果为空,则取当前的模块名作为model名。 + * @access public + * @return void + */ + public function loadModel($moduleName) + { + if(empty($moduleName)) return false; + $modelFile = helper::setModelFile($moduleName); + if(!file_exists($modelFile)) return false; + + helper::import($modelFile); + $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; + if(!class_exists($modelClass)) $this->app->error(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + + $this->$moduleName = new $modelClass(); + return $this->$moduleName; + } + + //-------------------- 数据库操作相应的方法。--------------------// + + /** + * 加载DAO类,并返回对象。 + * + * @access private + * @return void + */ + private function loadDAO() + { + $this->dao = $this->app->loadClass('dao'); + } + + /* 将一条记录标记为已删除。*/ + public function delete($table, $id) + { + $this->dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec(); + $object = str_replace($this->config->db->prefix, '', $table); + $this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED); + } + + /* 还原已经标记为删除的记录。*/ + public function undelete($actionID) + { + $action = $this->loadModel('action')->getById($actionID); + if($action->action != 'deleted') return; + $table = $this->config->action->objectTables[$action->objectType]; + $this->dao->update($table)->set('deleted')->eq(0)->where('id')->eq($action->objectID)->exec(); + $this->dao->update(TABLE_ACTION)->set('extra')->eq(ACTIONMODEL::BE_UNDELETED)->where('id')->eq($actionID)->exec(); + $this->action->create($action->objectType, $action->objectID, 'undeleted'); + } +} diff --git a/framework/router.class.php b/framework/router.class.php index d03b681372..23668a6d6b 100755 --- a/framework/router.class.php +++ b/framework/router.class.php @@ -2,19 +2,6 @@ /** * The router, config and lang class file of ZenTaoPHP. * - * ZenTaoPHP is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * ZenTaoPHP is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZenTaoPHP. If not, see . - * * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) * @author Chunsheng Wang * @package ZenTaoPHP diff --git a/lib/dao/dao.class.php b/lib/dao/dao.class.php index 490668dc9d..605b0ac6cc 100755 --- a/lib/dao/dao.class.php +++ b/lib/dao/dao.class.php @@ -1,1156 +1,1143 @@ -. - * - * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) - * @author Chunsheng Wang - * @package ZenTaoPHP - * @version $Id: dao.class.php 134 2010-09-11 07:24:27Z wwccss $ - * @link http://www.zentao.net - */ - -/** - * DAO类。提供各种便利的数据库操作方法。 - * - * @package ZenTaoPHP - */ -class dao -{ - /* 解决autoCompany带来的sql关键字冲突的问题。*/ - const WHERE = 'wHeRe'; - const GROUPBY = 'gRoUp bY'; - const HAVING = 'hAvInG'; - const ORDERBY = 'oRdEr bY'; - const LIMIT = 'lImiT'; - - /** - * 全局的$app对象。 - * - * @var object - * @access protected - */ - protected $app; - - /** - * 全局的$config对象。 - * - * @var object - * @access protected - */ - protected $config; - - /** - * 全局的$lang对象。 - * - * @var object - * @access protected - */ - protected $lang; - - /** - * 全局的$dbh(数据库访问句柄)对象。 - * - * @var object - * @access protected - */ - protected $dbh; - - /** - * 当前查询所对应的主表。 - * - * @var string - * @access public - */ - public $table; - - /** - * 主表所对应的alias - * - * @var string - * @access public - */ - public $alias; - - /** - * 当前查询所返回的字段列表。 - * - * @var string - * @access public - */ - public $fields; - - /** - * 查询的模式,现在支持两种,一种是通过魔术方法,一种是直接拼写sql查询。 - * - * 主要用来区分dao::from()方法和sql::from()方法。 - * - * @var string - * @access public - */ - public $mode; - - /** - * 查询的方法: insert, select, update, delete, replace - * - * @var string - * @access public - */ - public $method; - - /** - * 执行的sql查询列表。 - * - * 用来记录当前页面所有的sql查询。 - * - * @var array - * @access public - */ - static public $querys = array(); - - /** - * 数据检查结果。 - * - * @var array - * @access public - */ - static public $errors = array(); - - /** - * 构造函数。 - * - * 设置当前model对应的表名,并引用全局的变量。 - * - * @param string $table 表名。 - * @access public - * @return void - */ - public function __construct($table = '') - { - global $app, $config, $lang, $dbh; - $this->app = $app; - $this->config = $config; - $this->lang = $lang; - $this->dbh = $dbh; - - $this->reset(); - } - - /** - * 设置数据表。 - * - * @param string $table 表名。 - * @access private - * @return void - */ - private function setTable($table) - { - $this->table = $table; - } - - /** - * 设置当前查询主表的alias。 - * - * @param string $alias 别名。 - * @access private - * @return void - */ - private function setAlias($alias) - { - $this->alias = $alias; - } - - /** - * 设置返回的字段列表。 - * - * @param string $fields 字段列表。 - * @access private - * @return void - */ - private function setFields($fields) - { - $this->fields = $fields; - } - - /** - * 重新设置table, field, mode。 - * - * @access private - * @return void - */ - private function reset() - { - $this->setFields(''); - $this->setTable(''); - $this->setAlias(''); - $this->setMode(''); - $this->setMethod(''); - } - - //-------------------- 根据查询方式的不同,调用SQL类的对应方法。--------------------// - - /** - * 设置查询模式。magic是通过findby之类的魔术方法进行查询的,而raw则直接拼装sql进行查询。 - * - * @param string mode 查询模式: empty|magic|raw - * @access private - * @return void - */ - private function setMode($mode = '') - { - $this->mode = $mode; - } - - /* 设置查询的方法。select|update|insert|delete|replace */ - private function setMethod($method = '') - { - $this->method = $method; - } - - /* select:调用SQL类的select方法。*/ - public function select($fields = '*') - { - $this->setMode('raw'); - $this->setMethod('select'); - $this->sqlobj = sql::select($fields); - return $this; - } - - /* update:调用SQL类的update方法。*/ - public function update($table) - { - $this->setMode('raw'); - $this->setMethod('update'); - $this->sqlobj = sql::update($table); - $this->setTable($table); - return $this; - } - - /* delete:调用SQL类的delete方法。*/ - public function delete() - { - $this->setMode('raw'); - $this->setMethod('delete'); - $this->sqlobj = sql::delete(); - return $this; - } - - /* insert:调用SQL类的insert方法。*/ - public function insert($table) - { - $this->setMode('raw'); - $this->setMethod('insert'); - $this->sqlobj = sql::insert($table); - $this->setTable($table); - return $this; - } - - /* replace:调用SQL类的replace方法。*/ - public function replace($table) - { - $this->setMode('raw'); - $this->setMethod('replace'); - $this->sqlobj = sql::replace($table); - $this->setTable($table); - return $this; - } - - /* from: 设定要查询的table name。*/ - public function from($table) - { - $this->setTable($table); - if($this->mode == 'raw') $this->sqlobj->from($table); - return $this; - } - - /* fields方法:设置要查询的字段列表。*/ - public function fields($fields) - { - $this->setFields($fields); - return $this; - } - - /* alias方法。*/ - public function alias($alias) - { - if(empty($this->alias)) $this->setAlias($alias); - $this->sqlobj->alias($alias); - return $this; - } - - /* data方法。*/ - public function data($data, $autoCompany = true) - { - /* 如果当前模块不是company,都追加company字段。*/ - if(!is_object($data)) $data = (object)$data; - if($autoCompany and isset($this->app->company) and $this->table != TABLE_COMPANY and !isset($data->company)) $data->company = $this->app->company->id; - $this->sqlobj->data($data); - return $this; - } - - //-------------------- 拼装之后的SQL相关处理方法。--------------------// - - /* 返回SQL语句。*/ - public function get() - { - return $this->processKeywords($this->processSQL()); - } - - /* 打印SQL语句。*/ - public function printSQL() - { - echo $this->processSQL(); - } - - /* 处理SQL,将table和fields字段替换成对应的值。*/ - private function processSQL($autoCompany = true) - { - $sql = $this->sqlobj->get(); - - /* 如果查询模式是magic,处理fields和table两个变量。*/ - if($this->mode == 'magic') - { - if($this->fields == '') $this->fields = '*'; - if($this->table == '') $this->app->error('Must set the table name', __FILE__, __LINE__, $exit = true); - $sql = sprintf($this->sqlobj->get(), $this->fields, $this->table); - } - - /* 如果处理的不是company表,并且查询方法不是insert和replace, 追加company的查询条件。*/ - if(isset($this->app->company) and $autoCompany and $this->table != '' and $this->table != TABLE_COMPANY and $this->method != 'insert' and $this->method != 'replace') - { - /* 获得where 和 order by的位置。*/ - $wherePOS = strrpos($sql, DAO::WHERE); - $groupPOS = strrpos($sql, DAO::GROUPBY); // group by的位置。 - $havingPOS = strrpos($sql, DAO::HAVING); // having的位置。 - $orderPOS = strrpos($sql, DAO::ORDERBY); // order by的位置。 - $limitPOS = strrpos($sql, DAO::LIMIT); // limit的位置。 - $splitPOS = $orderPOS ? $orderPOS : $limitPOS; // order比limit靠前。 - $splitPOS = $havingPOS? $havingPOS: $splitPOS; // having比orer靠前。 - $splitPOS = $groupPOS ? $groupPOS : $splitPOS; // group比having靠前。 - - /* 要追加的条件语句。*/ - $tableName = !empty($this->alias) ? $this->alias : $this->table; - $companyCondition = " $tableName.company = '{$this->app->company->id}' "; - - /* SQL语句中有order by。*/ - if($splitPOS) - { - $firstPart = substr($sql, 0, $splitPOS); - $lastPart = substr($sql, $splitPOS); - if($wherePOS) - { - $sql = $firstPart . " AND $companyCondition " . $lastPart; - } - else - { - $sql = $firstPart . " WHERE $companyCondition " . $lastPart; - } - } - else - { - $sql .= $wherePOS ? " AND $companyCondition" : " WHERE $companyCondition"; - } - } - self::$querys[] = $this->processKeywords($sql); - return $sql; - } - - /* 处理SQL关键字。*/ - private function processKeywords($sql) - { - return str_replace(array(DAO::WHERE, DAO::GROUPBY, DAO::HAVING, DAO::ORDERBY, DAO::LIMIT), array('WHERE', 'GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT'), $sql); - } - - //-------------------- SQL查询相关的方法。--------------------// - - /* 设置数据库访问句柄。*/ - public function dbh($dbh) - { - $this->dbh = $dbh; - return $this; - } - - /* 执行sql查询,返回stmt对象。autoComapny设定是否自动追加company的查询条件。*/ - public function query($autoCompany = true) - { - /* 如果dao::$errors不为空,返回一个空的stmt对象,这样后续的方法调用还可以继续。*/ - if(!empty(dao::$errors)) return new PDOStatement(); - - /* 处理一下SQL语句。*/ - $sql = $this->processSQL($autoCompany); - try - { - $this->reset(); - return $this->dbh->query($sql); - } - catch (PDOException $e) - { - $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); - } - } - - /* 执行分页。*/ - public function page($pager) - { - if(!is_object($pager)) return $this; - - /* 没有传递recTotal,则自己进行计算。*/ - if($pager->recTotal == 0) - { - /* 获得SELECT和FROM的位置,据此算出查询的字段,然后将其替换为count(*)。*/ - $sql = $this->get(); - $selectPOS = strpos($sql, 'SELECT') + strlen('SELECT'); - $fromPOS = strpos($sql, 'FROM'); - $fields = substr($sql, $selectPOS, $fromPOS - $selectPOS ); - $sql = str_replace($fields, ' COUNT(*) AS recTotal ', $sql); - - /* 取得order 或者limit的位置,将后面的去掉。*/ - $subLength = strlen($sql); - $orderPOS = strripos($sql, 'order'); - $limitPOS = strripos($sql , 'limit'); - if($limitPOS) $subLength = $limitPOS; - if($orderPOS) $subLength = $orderPOS; - $sql = substr($sql, 0, $subLength); - self::$querys[] = $sql; - - /* 获得记录总数。*/ - try - { - $row = $this->dbh->query($sql)->fetch(PDO::FETCH_OBJ); - } - catch (PDOException $e) - { - $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); - } - - $pager->setRecTotal($row->recTotal); - $pager->setPageTotal(); - } - $this->sqlobj->limit($pager->limit()); - return $this; - } - - /* 执行sql查询,返回受影响的记录数。autoComapny设定是否自动追加company的查询条件。*/ - public function exec($autoCompany = true) - { - /* 如果dao::$errors不为空,返回一个空的stmt对象,这样后续的方法调用还可以继续。*/ - if(!empty(dao::$errors)) return new PDOStatement(); - - /* 处理一下SQL语句。*/ - $sql = $this->processSQL($autoCompany); - try - { - $this->reset(); - return $this->dbh->exec($sql); - } - catch (PDOException $e) - { - $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); - } - } - - //-------------------- 数据获取相关的方法。--------------------// - - /* 返回一条记录,如果指定了$field字段, 则直接返回该字段对应的值。*/ - public function fetch($field = '', $autoCompany = true) - { - if(empty($field)) return $this->query($autoCompany)->fetch(); - $this->setFields($field); - $result = $this->query($autoCompany)->fetch(PDO::FETCH_OBJ); - if($result) return $result->$field; - } - - /* 返回全部的结果。如果指定了$keyField,则以keyField的值作为key。*/ - public function fetchAll($keyField = '', $autoCompany = true) - { - $stmt = $this->query($autoCompany); - if(empty($keyField)) return $stmt->fetchAll(); - $rows = array(); - while($row = $stmt->fetch()) $rows[$row->$keyField] = $row; - return $rows; - } - - /* 返回结果并按照某个字段进行分组。*/ - public function fetchGroup($groupField, $keyField = '', $autoCompany = true) - { - $stmt = $this->query($autoCompany); - $rows = array(); - while($row = $stmt->fetch()) - { - empty($keyField) ? $rows[$row->$groupField][] = $row : $rows[$row->$groupField][$row->$keyField] = $row; - } - return $rows; - } - - /* fetchPairs方法:如果没有指定key和value字段,则取行字段里面的第一个作为key,最后一个作为value。*/ - public function fetchPairs($keyField = '', $valueField = '', $autoCompany = true) - { - $pairs = array(); - $ready = false; - $stmt = $this->query($autoCompany); - while($row = $stmt->fetch(PDO::FETCH_ASSOC)) - { - if(!$ready) - { - if(empty($keyField)) $keyField = key($row); - if(empty($valueField)) - { - end($row); - $valueField = key($row); - } - $ready = true; - } - - $pairs[$row[$keyField]] = $row[$valueField]; - } - return $pairs; - } - - /* 获取最后插入的id。*/ - public function lastInsertID() - { - return $this->dbh->lastInsertID(); - } - - //-------------------- 各种魔术方法。--------------------// - - /** - * 魔术方法,籍此提供各种便利的查询方法。 - * - * @param string $funcName 被调用的方法名。 - * @param array $funcArgs 传入的参数列表。 - * @access public - * @return void - */ - public function __call($funcName, $funcArgs) - { - /* 将funcName转为小写。*/ - $funcName = strtolower($funcName); - - /* findBy类的方法。*/ - if(strpos($funcName, 'findby') !== false) - { - $this->setMode('magic'); - $field = str_replace('findby', '', $funcName); - if(count($funcArgs) == 1) - { - $operator = '='; - $value = $funcArgs[0]; - } - else - { - $operator = $funcArgs[0]; - $value = $funcArgs[1]; - } - $this->sqlobj = sql::select('%s')->from('%s')->where($field, $operator, $value); // 使用占位符,执行查询之前替换为相应的字段和表名。 - return $this; - } - /* fetch10方法,真正的数据查询。*/ - elseif(strpos($funcName, 'fetch') !== false) - { - $max = str_replace('fetch', '', $funcName); - $stmt = $this->query(); - - /* 设定了key字段。 */ - $rows = array(); - $key = isset($funcArgs[0]) ? $funcArgs[0] : ''; - $i = 0; - while($row = $stmt->fetch()) - { - $key ? $rows[$row->$key] = $row : $rows[] = $row; - $i ++; - if($i == $max) break; - } - return $rows; - } - /* 其余的都直接调用sql类里面的方法。*/ - else - { - /* 取SQL类方法中参数个数最大值,生成一个最大集合的参数列表。。*/ - for($i = 0; $i < SQL::MAX_ARGS; $i ++) - { - ${"arg$i"} = isset($funcArgs[$i]) ? $funcArgs[$i] : null; - } - $this->sqlobj->$funcName($arg0, $arg1, $arg2); - return $this; - } - } - - //-------------------- 数据检查相关的方法。--------------------// - - /* 按照某个规则检查值是否符合要求。*/ - public function check($fieldName, $funcName) - { - /* 如果data变量里面没有这个字段,直接返回。*/ - if(!isset($this->sqlobj->data->$fieldName)) return $this; - - /* 引用全局的config, lang。*/ - global $lang, $config, $app; - $table = strtolower(str_replace($config->db->prefix, '', $this->table)); - $fieldLabel = isset($lang->$table->$fieldName) ? $lang->$table->$fieldName : $fieldName; - $value = $this->sqlobj->data->$fieldName; - - if($funcName == 'unique') - { - $args = func_get_args(); - $sql = "SELECT COUNT(*) AS count FROM $this->table WHERE `$fieldName` = " . $this->sqlobj->quote($value); - if($this->table != TABLE_COMPANY) $sql .= " AND company = {$this->app->company->id} "; - if(isset($args[2])) $sql .= ' AND ' . $args[2]; - try - { - $row = $this->dbh->query($sql)->fetch(); - if($row->count != 0) $this->logError($funcName, $fieldName, $fieldLabel, array($value)); - } - catch (PDOException $e) - { - $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); - } - } - else - { - /* 取validate类方法中参数个数最大值,生成一个最大集合的参数列表。。*/ - $funcArgs = func_get_args(); - unset($funcArgs[0]); - unset($funcArgs[1]); - - for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) - { - ${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null; - } - $checkFunc = 'check' . $funcName; - if(validater::$checkFunc($value, $arg0, $arg1, $arg2) === false) - { - $this->logError($funcName, $fieldName, $fieldLabel, $funcArgs); - } - } - - return $this; - } - - /* 如果满足某一个条件,按照某个规则检查值是否符合要求。*/ - public function checkIF($condition, $fieldName, $funcName) - { - if(!$condition) return $this; - $funcArgs = func_get_args(); - for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) - { - ${"arg$i"} = isset($funcArgs[$i + 3]) ? $funcArgs[$i + 3] : null; - } - $this->check($fieldName, $funcName, $arg0, $arg1, $arg2); - return $this; - } - - /* 批量检查。*/ - public function batchCheck($fields, $funcName) - { - $fields = explode(',', str_replace(' ', '', $fields)); - $funcArgs = func_get_args(); - for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) - { - ${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null; - } - foreach($fields as $fieldName) $this->check($fieldName, $funcName, $arg0, $arg1, $arg2); - return $this; - } - - /* 批量条件检查。*/ - public function batchCheckIF($condition, $fields, $funcName) - { - if(!$condition) return $this; - $fields = explode(',', str_replace(' ', '', $fields)); - $funcArgs = func_get_args(); - for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) - { - ${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null; - } - foreach($fields as $fieldName) $this->check($fieldName, $funcName, $arg0, $arg1, $arg2); - return $this; - } - - /* 自动根据数据库中表的字段格式进行检查。*/ - public function autoCheck($skipFields = '') - { - $fields = $this->getFieldsType(); - $skipFields = ",$skipFields,"; - - foreach($fields as $fieldName => $validater) - { - if(strpos($skipFields, $fieldName) !== false) continue; // 忽略。 - if(!isset($this->sqlobj->data->$fieldName)) continue; - if($validater['rule'] == 'skip') continue; - $options = array(); - if(isset($validater['options'])) $options = array_values($validater['options']); - for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) - { - ${"arg$i"} = isset($options[$i]) ? $options[$i] : null; - } - $this->check($fieldName, $validater['rule'], $arg0, $arg1, $arg2); - } - return $this; - } - - /* 记录错误。*/ - public function logError($checkType, $fieldName, $fieldLabel, $funcArgs = array()) - { - global $lang; - $error = $lang->error->$checkType; - $replaces = array_merge(array($fieldLabel), $funcArgs); - - /* 如果error不是数组,只是字符串,则循环replace,依次替换%s。*/ - if(!is_array($error)) - { - foreach($replaces as $replace) - { - $pos = strpos($error, '%s'); - if($pos === false) break; - $error = substr($error, 0, $pos) . $replace . substr($error, $pos +2); - } - } - /* 如果error是一个数组,则从数组中挑选%s个数与replace元素个数相同的。*/ - else - { - /* 去掉replace中空白的元素。*/ - foreach($replaces as $key => $value) if(is_null($value)) unset($replaces[$key]); - $replacesCount = count($replaces); - foreach($error as $errorString) - { - if(substr_count($errorString, '%s') == $replacesCount) - { - $error = vsprintf($errorString, $replaces); - } - } - } - dao::$errors[$fieldName][] = $error; - } - - /* 判断这次查询是否有错误。*/ - public function isError() - { - return !empty(dao::$errors); - } - - /* 返回error。*/ - public function getError() - { - $errors = dao::$errors; - dao::$errors = array(); - return $errors; - } - - /* 获得某一个表的字段类型。*/ - private function getFieldsType() - { - try - { - $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); - $sql = "DESC $this->table"; - $rawFields = $this->dbh->query($sql)->fetchAll(); - $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); - } - catch (PDOException $e) - { - $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); - } - - foreach($rawFields as $rawField) - { - $firstPOS = strpos($rawField->type, '('); - $type = substr($rawField->type, 0, $firstPOS > 0 ? $firstPOS : strlen($rawField->type)); - $type = str_replace(array('big', 'small', 'medium', 'tiny', 'var'), '', $type); - $field = array(); - - if($type == 'enum' or $type == 'set') - { - $rangeBegin = $firstPOS + 2; // 将第一个引号去掉。 - $rangeEnd = strrpos($rawField->type, ')') - 1; // 将最后一个引号去掉。 - $range = substr($rawField->type, $rangeBegin, $rangeEnd - $rangeBegin); - $field['rule'] = 'reg'; - $field['options']['reg'] = '/' . str_replace("','", '|', $range) . '/'; - } - elseif($type == 'char') - { - $begin = $firstPOS + 1; - $end = strpos($rawField->type, ')', $begin); - $length = substr($rawField->type, $begin, $end - $begin); - $field['rule'] = 'length'; - $field['options']['max'] = $length; - $field['options']['min'] = 0; - } - elseif($type == 'int') - { - $field['rule'] = 'int'; - } - elseif($type == 'float' or $type == 'double') - { - $field['rule'] = 'float'; - } - elseif($type == 'date') - { - $field['rule'] = 'date'; - } - else - { - $field['rule'] = 'skip'; - } - $fields[$rawField->field] = $field; - } - return $fields; - } -} - -/** - * SQL查询封装类。 - * - * @package ZenTaoPHP - */ -class sql -{ - /** - * 所有方法的参数个数最大值。 - * - */ - const MAX_ARGS = 3; - - /** - * SQL语句。 - * - * @var string - * @access private - */ - private $sql = ''; - - /** - * 全局的$dbh(数据库访问句柄)对象。 - * - * @var object - * @access protected - */ - protected $dbh; - - /** - * INSERT或者UPDATE时赋给的数据。 - * - * @var mix - * @access protected - */ - public $data; - - /** - * 是否是首次调用set。 - * - * @var bool - * @access private; - */ - private $isFirstSet = true; - - /** - * 是否在条件判断中。 - * - * @var bool - * @access private; - */ - private $inCondition = false; - - /** - * 判断条件是否为ture。 - * - * @var bool - * @access private; - */ - private $conditionIsTrue = false; - - /** - * 是否自动magic quote。 - * - * @var bool - * @access public - */ - public $magicQuote; - - /* 构造函数。*/ - private function __construct($table = '') - { - global $dbh; - $this->dbh = $dbh; - $this->magicQuote = get_magic_quotes_gpc(); - } - - /* 实例化方法,通过该方法实例对象。*/ - public function factory($table = '') - { - return new sql($table); - } - - /* 查询语句开始。*/ - public function select($field = '*') - { - $sqlobj = self::factory(); - $sqlobj->sql = "SELECT $field "; - return $sqlobj; - } - - /* 更新语句开始。*/ - public function update($table) - { - $sqlobj = self::factory(); - $sqlobj->sql = "UPDATE $table SET "; - return $sqlobj; - } - - /* 插入语句开始。*/ - public function insert($table) - { - $sqlobj = self::factory(); - $sqlobj->sql = "INSERT INTO $table SET "; - return $sqlobj; - } - - /* 替换语句开始。*/ - public function replace($table) - { - $sqlobj = self::factory(); - $sqlobj->sql = "REPLACE $table SET "; - return $sqlobj; - } - - /* 删除语句开始。*/ - public function delete() - { - $sqlobj = self::factory(); - $sqlobj->sql = "DELETE "; - return $sqlobj; - } - - /* 给定一个key=>value结构的数组或者对象,拼装成key = value的形式。*/ - public function data($data) - { - $this->data = $data; - foreach($data as $field => $value) $this->sql .= "`$field` = " . $this->quote($value) . ','; - $this->sql = rtrim($this->sql, ','); // 去掉最后面的逗号。 - return $this; - } - - /* 加左边的括弧。*/ - public function markLeft($count = 1) - { - $this->sql .= str_repeat('(', $count); - return $this; - } - - /* 加右边的括弧。*/ - public function markRight($count = 1) - { - $this->sql .= str_repeat(')', $count); - return $this; - } - - /* SET key=value。*/ - public function set($set) - { - if($this->isFirstSet) - { - $this->sql .= " $set "; - $this->isFirstSet = false; - } - else - { - $this->sql .= ", $set"; - } - return $this; - } - - /* 设定要查询的表名。*/ - public function from($table) - { - $this->sql .= "FROM $table"; - return $this; - } - - /* 设置别名。*/ - public function alias($alias) - { - $this->sql .= " AS $alias "; - } - - /* 设定LEFT JOIN语句。*/ - public function leftJoin($table) - { - $this->sql .= " LEFT JOIN $table"; - return $this; - } - - /* 设定ON条件。*/ - public function on($condition) - { - $this->sql .= " ON $condition "; - return $this; - } - - /* 条件判断开始。*/ - public function beginIF($condition) - { - $this->inCondition = true; - $this->conditionIsTrue = $condition; - } - - /* 条件判断结束。*/ - public function fi() - { - $this->inCondition = false; - $this->conditionIsTrue = false; - } - - /* WHERE语句部分开始。*/ - public function where($arg1, $arg2 = null, $arg3 = null) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - if($arg3 !== null) - { - $value = $this->quote($arg3); - $condition = "`$arg1` $arg2 " . $this->quote($arg3); - } - else - { - $condition = $arg1; - } - - $this->sql .= ' ' . DAO::WHERE ." $condition "; - return $this; - } - - /* 追加AND条件。*/ - public function andWhere($condition) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " AND $condition "; - return $this; - } - - /* 追加OR条件。*/ - public function orWhere($condition) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " OR $condition "; - return $this; - } - - /* 等于。*/ - public function eq($value) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " = " . $this->quote($value); - return $this; - } - - /* 不等于。*/ - public function ne($value) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " != " . $this->quote($value); - return $this; - } - - /* 大于。*/ - public function gt($value) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " > " . $this->quote($value); - return $this; - } - - /* 小于。*/ - public function lt($value) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " < " . $this->quote($value); - return $this; - } - - /* 生成between语句。*/ - public function between($min, $max) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " BETWEEN $min AND $max "; - return $this; - } - - /* 生成 IN部分语句。*/ - public function in($ids) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= helper::dbIN($ids); - return $this; - } - - /* 生成 NOTIN部分语句。*/ - public function notin($ids) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= ' NOT ' . helper::dbIN($ids); - return $this; - } - - /* 生成LIKE部分语句。*/ - public function like($string) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " LIKE " . $this->quote($string); - return $this; - } - - /* 设定ORDER BY。*/ - public function orderBy($order) - { - $order = str_replace(array('|', '', '_'), ' ', $order); - $order = str_replace('left', '`left`', $order); // 处理left关键字。 - $this->sql .= ' ' . DAO::ORDERBY . " $order"; - return $this; - } - - /* 设定LIMIT。*/ - public function limit($limit) - { - if(empty($limit)) return $this; - stripos($limit, 'limit') !== false ? $this->sql .= " $limit " : $this->sql .= ' ' . DAO::LIMIT . " $limit "; - return $this; - } - - /* 设定GROUP BY。*/ - public function groupBy($groupBy) - { - $this->sql .= ' ' . DAO::GROUPBY . " $groupBy"; - return $this; - } - - /* 设定having。*/ - public function having($having) - { - $this->sql .= ' ' . DAO::HAVING . " $having"; - return $this; - } - - /* 返回拼装好的语句。*/ - public function get() - { - return $this->sql; - } - - /* 转义。*/ - public function quote($value) - { - if($this->magicQuote) $value = stripslashes($value); - return $this->dbh->quote($value); - } -} + + * @package ZenTaoPHP + * @version $Id: dao.class.php 134 2010-09-11 07:24:27Z wwccss $ + * @link http://www.zentao.net + */ + +/** + * DAO类。提供各种便利的数据库操作方法。 + * + * @package ZenTaoPHP + */ +class dao +{ + /* 解决autoCompany带来的sql关键字冲突的问题。*/ + const WHERE = 'wHeRe'; + const GROUPBY = 'gRoUp bY'; + const HAVING = 'hAvInG'; + const ORDERBY = 'oRdEr bY'; + const LIMIT = 'lImiT'; + + /** + * 全局的$app对象。 + * + * @var object + * @access protected + */ + protected $app; + + /** + * 全局的$config对象。 + * + * @var object + * @access protected + */ + protected $config; + + /** + * 全局的$lang对象。 + * + * @var object + * @access protected + */ + protected $lang; + + /** + * 全局的$dbh(数据库访问句柄)对象。 + * + * @var object + * @access protected + */ + protected $dbh; + + /** + * 当前查询所对应的主表。 + * + * @var string + * @access public + */ + public $table; + + /** + * 主表所对应的alias + * + * @var string + * @access public + */ + public $alias; + + /** + * 当前查询所返回的字段列表。 + * + * @var string + * @access public + */ + public $fields; + + /** + * 查询的模式,现在支持两种,一种是通过魔术方法,一种是直接拼写sql查询。 + * + * 主要用来区分dao::from()方法和sql::from()方法。 + * + * @var string + * @access public + */ + public $mode; + + /** + * 查询的方法: insert, select, update, delete, replace + * + * @var string + * @access public + */ + public $method; + + /** + * 执行的sql查询列表。 + * + * 用来记录当前页面所有的sql查询。 + * + * @var array + * @access public + */ + static public $querys = array(); + + /** + * 数据检查结果。 + * + * @var array + * @access public + */ + static public $errors = array(); + + /** + * 构造函数。 + * + * 设置当前model对应的表名,并引用全局的变量。 + * + * @param string $table 表名。 + * @access public + * @return void + */ + public function __construct($table = '') + { + global $app, $config, $lang, $dbh; + $this->app = $app; + $this->config = $config; + $this->lang = $lang; + $this->dbh = $dbh; + + $this->reset(); + } + + /** + * 设置数据表。 + * + * @param string $table 表名。 + * @access private + * @return void + */ + private function setTable($table) + { + $this->table = $table; + } + + /** + * 设置当前查询主表的alias。 + * + * @param string $alias 别名。 + * @access private + * @return void + */ + private function setAlias($alias) + { + $this->alias = $alias; + } + + /** + * 设置返回的字段列表。 + * + * @param string $fields 字段列表。 + * @access private + * @return void + */ + private function setFields($fields) + { + $this->fields = $fields; + } + + /** + * 重新设置table, field, mode。 + * + * @access private + * @return void + */ + private function reset() + { + $this->setFields(''); + $this->setTable(''); + $this->setAlias(''); + $this->setMode(''); + $this->setMethod(''); + } + + //-------------------- 根据查询方式的不同,调用SQL类的对应方法。--------------------// + + /** + * 设置查询模式。magic是通过findby之类的魔术方法进行查询的,而raw则直接拼装sql进行查询。 + * + * @param string mode 查询模式: empty|magic|raw + * @access private + * @return void + */ + private function setMode($mode = '') + { + $this->mode = $mode; + } + + /* 设置查询的方法。select|update|insert|delete|replace */ + private function setMethod($method = '') + { + $this->method = $method; + } + + /* select:调用SQL类的select方法。*/ + public function select($fields = '*') + { + $this->setMode('raw'); + $this->setMethod('select'); + $this->sqlobj = sql::select($fields); + return $this; + } + + /* update:调用SQL类的update方法。*/ + public function update($table) + { + $this->setMode('raw'); + $this->setMethod('update'); + $this->sqlobj = sql::update($table); + $this->setTable($table); + return $this; + } + + /* delete:调用SQL类的delete方法。*/ + public function delete() + { + $this->setMode('raw'); + $this->setMethod('delete'); + $this->sqlobj = sql::delete(); + return $this; + } + + /* insert:调用SQL类的insert方法。*/ + public function insert($table) + { + $this->setMode('raw'); + $this->setMethod('insert'); + $this->sqlobj = sql::insert($table); + $this->setTable($table); + return $this; + } + + /* replace:调用SQL类的replace方法。*/ + public function replace($table) + { + $this->setMode('raw'); + $this->setMethod('replace'); + $this->sqlobj = sql::replace($table); + $this->setTable($table); + return $this; + } + + /* from: 设定要查询的table name。*/ + public function from($table) + { + $this->setTable($table); + if($this->mode == 'raw') $this->sqlobj->from($table); + return $this; + } + + /* fields方法:设置要查询的字段列表。*/ + public function fields($fields) + { + $this->setFields($fields); + return $this; + } + + /* alias方法。*/ + public function alias($alias) + { + if(empty($this->alias)) $this->setAlias($alias); + $this->sqlobj->alias($alias); + return $this; + } + + /* data方法。*/ + public function data($data, $autoCompany = true) + { + /* 如果当前模块不是company,都追加company字段。*/ + if(!is_object($data)) $data = (object)$data; + if($autoCompany and isset($this->app->company) and $this->table != TABLE_COMPANY and !isset($data->company)) $data->company = $this->app->company->id; + $this->sqlobj->data($data); + return $this; + } + + //-------------------- 拼装之后的SQL相关处理方法。--------------------// + + /* 返回SQL语句。*/ + public function get() + { + return $this->processKeywords($this->processSQL()); + } + + /* 打印SQL语句。*/ + public function printSQL() + { + echo $this->processSQL(); + } + + /* 处理SQL,将table和fields字段替换成对应的值。*/ + private function processSQL($autoCompany = true) + { + $sql = $this->sqlobj->get(); + + /* 如果查询模式是magic,处理fields和table两个变量。*/ + if($this->mode == 'magic') + { + if($this->fields == '') $this->fields = '*'; + if($this->table == '') $this->app->error('Must set the table name', __FILE__, __LINE__, $exit = true); + $sql = sprintf($this->sqlobj->get(), $this->fields, $this->table); + } + + /* 如果处理的不是company表,并且查询方法不是insert和replace, 追加company的查询条件。*/ + if(isset($this->app->company) and $autoCompany and $this->table != '' and $this->table != TABLE_COMPANY and $this->method != 'insert' and $this->method != 'replace') + { + /* 获得where 和 order by的位置。*/ + $wherePOS = strrpos($sql, DAO::WHERE); + $groupPOS = strrpos($sql, DAO::GROUPBY); // group by的位置。 + $havingPOS = strrpos($sql, DAO::HAVING); // having的位置。 + $orderPOS = strrpos($sql, DAO::ORDERBY); // order by的位置。 + $limitPOS = strrpos($sql, DAO::LIMIT); // limit的位置。 + $splitPOS = $orderPOS ? $orderPOS : $limitPOS; // order比limit靠前。 + $splitPOS = $havingPOS? $havingPOS: $splitPOS; // having比orer靠前。 + $splitPOS = $groupPOS ? $groupPOS : $splitPOS; // group比having靠前。 + + /* 要追加的条件语句。*/ + $tableName = !empty($this->alias) ? $this->alias : $this->table; + $companyCondition = " $tableName.company = '{$this->app->company->id}' "; + + /* SQL语句中有order by。*/ + if($splitPOS) + { + $firstPart = substr($sql, 0, $splitPOS); + $lastPart = substr($sql, $splitPOS); + if($wherePOS) + { + $sql = $firstPart . " AND $companyCondition " . $lastPart; + } + else + { + $sql = $firstPart . " WHERE $companyCondition " . $lastPart; + } + } + else + { + $sql .= $wherePOS ? " AND $companyCondition" : " WHERE $companyCondition"; + } + } + self::$querys[] = $this->processKeywords($sql); + return $sql; + } + + /* 处理SQL关键字。*/ + private function processKeywords($sql) + { + return str_replace(array(DAO::WHERE, DAO::GROUPBY, DAO::HAVING, DAO::ORDERBY, DAO::LIMIT), array('WHERE', 'GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT'), $sql); + } + + //-------------------- SQL查询相关的方法。--------------------// + + /* 设置数据库访问句柄。*/ + public function dbh($dbh) + { + $this->dbh = $dbh; + return $this; + } + + /* 执行sql查询,返回stmt对象。autoComapny设定是否自动追加company的查询条件。*/ + public function query($autoCompany = true) + { + /* 如果dao::$errors不为空,返回一个空的stmt对象,这样后续的方法调用还可以继续。*/ + if(!empty(dao::$errors)) return new PDOStatement(); + + /* 处理一下SQL语句。*/ + $sql = $this->processSQL($autoCompany); + try + { + $this->reset(); + return $this->dbh->query($sql); + } + catch (PDOException $e) + { + $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); + } + } + + /* 执行分页。*/ + public function page($pager) + { + if(!is_object($pager)) return $this; + + /* 没有传递recTotal,则自己进行计算。*/ + if($pager->recTotal == 0) + { + /* 获得SELECT和FROM的位置,据此算出查询的字段,然后将其替换为count(*)。*/ + $sql = $this->get(); + $selectPOS = strpos($sql, 'SELECT') + strlen('SELECT'); + $fromPOS = strpos($sql, 'FROM'); + $fields = substr($sql, $selectPOS, $fromPOS - $selectPOS ); + $sql = str_replace($fields, ' COUNT(*) AS recTotal ', $sql); + + /* 取得order 或者limit的位置,将后面的去掉。*/ + $subLength = strlen($sql); + $orderPOS = strripos($sql, 'order'); + $limitPOS = strripos($sql , 'limit'); + if($limitPOS) $subLength = $limitPOS; + if($orderPOS) $subLength = $orderPOS; + $sql = substr($sql, 0, $subLength); + self::$querys[] = $sql; + + /* 获得记录总数。*/ + try + { + $row = $this->dbh->query($sql)->fetch(PDO::FETCH_OBJ); + } + catch (PDOException $e) + { + $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); + } + + $pager->setRecTotal($row->recTotal); + $pager->setPageTotal(); + } + $this->sqlobj->limit($pager->limit()); + return $this; + } + + /* 执行sql查询,返回受影响的记录数。autoComapny设定是否自动追加company的查询条件。*/ + public function exec($autoCompany = true) + { + /* 如果dao::$errors不为空,返回一个空的stmt对象,这样后续的方法调用还可以继续。*/ + if(!empty(dao::$errors)) return new PDOStatement(); + + /* 处理一下SQL语句。*/ + $sql = $this->processSQL($autoCompany); + try + { + $this->reset(); + return $this->dbh->exec($sql); + } + catch (PDOException $e) + { + $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); + } + } + + //-------------------- 数据获取相关的方法。--------------------// + + /* 返回一条记录,如果指定了$field字段, 则直接返回该字段对应的值。*/ + public function fetch($field = '', $autoCompany = true) + { + if(empty($field)) return $this->query($autoCompany)->fetch(); + $this->setFields($field); + $result = $this->query($autoCompany)->fetch(PDO::FETCH_OBJ); + if($result) return $result->$field; + } + + /* 返回全部的结果。如果指定了$keyField,则以keyField的值作为key。*/ + public function fetchAll($keyField = '', $autoCompany = true) + { + $stmt = $this->query($autoCompany); + if(empty($keyField)) return $stmt->fetchAll(); + $rows = array(); + while($row = $stmt->fetch()) $rows[$row->$keyField] = $row; + return $rows; + } + + /* 返回结果并按照某个字段进行分组。*/ + public function fetchGroup($groupField, $keyField = '', $autoCompany = true) + { + $stmt = $this->query($autoCompany); + $rows = array(); + while($row = $stmt->fetch()) + { + empty($keyField) ? $rows[$row->$groupField][] = $row : $rows[$row->$groupField][$row->$keyField] = $row; + } + return $rows; + } + + /* fetchPairs方法:如果没有指定key和value字段,则取行字段里面的第一个作为key,最后一个作为value。*/ + public function fetchPairs($keyField = '', $valueField = '', $autoCompany = true) + { + $pairs = array(); + $ready = false; + $stmt = $this->query($autoCompany); + while($row = $stmt->fetch(PDO::FETCH_ASSOC)) + { + if(!$ready) + { + if(empty($keyField)) $keyField = key($row); + if(empty($valueField)) + { + end($row); + $valueField = key($row); + } + $ready = true; + } + + $pairs[$row[$keyField]] = $row[$valueField]; + } + return $pairs; + } + + /* 获取最后插入的id。*/ + public function lastInsertID() + { + return $this->dbh->lastInsertID(); + } + + //-------------------- 各种魔术方法。--------------------// + + /** + * 魔术方法,籍此提供各种便利的查询方法。 + * + * @param string $funcName 被调用的方法名。 + * @param array $funcArgs 传入的参数列表。 + * @access public + * @return void + */ + public function __call($funcName, $funcArgs) + { + /* 将funcName转为小写。*/ + $funcName = strtolower($funcName); + + /* findBy类的方法。*/ + if(strpos($funcName, 'findby') !== false) + { + $this->setMode('magic'); + $field = str_replace('findby', '', $funcName); + if(count($funcArgs) == 1) + { + $operator = '='; + $value = $funcArgs[0]; + } + else + { + $operator = $funcArgs[0]; + $value = $funcArgs[1]; + } + $this->sqlobj = sql::select('%s')->from('%s')->where($field, $operator, $value); // 使用占位符,执行查询之前替换为相应的字段和表名。 + return $this; + } + /* fetch10方法,真正的数据查询。*/ + elseif(strpos($funcName, 'fetch') !== false) + { + $max = str_replace('fetch', '', $funcName); + $stmt = $this->query(); + + /* 设定了key字段。 */ + $rows = array(); + $key = isset($funcArgs[0]) ? $funcArgs[0] : ''; + $i = 0; + while($row = $stmt->fetch()) + { + $key ? $rows[$row->$key] = $row : $rows[] = $row; + $i ++; + if($i == $max) break; + } + return $rows; + } + /* 其余的都直接调用sql类里面的方法。*/ + else + { + /* 取SQL类方法中参数个数最大值,生成一个最大集合的参数列表。。*/ + for($i = 0; $i < SQL::MAX_ARGS; $i ++) + { + ${"arg$i"} = isset($funcArgs[$i]) ? $funcArgs[$i] : null; + } + $this->sqlobj->$funcName($arg0, $arg1, $arg2); + return $this; + } + } + + //-------------------- 数据检查相关的方法。--------------------// + + /* 按照某个规则检查值是否符合要求。*/ + public function check($fieldName, $funcName) + { + /* 如果data变量里面没有这个字段,直接返回。*/ + if(!isset($this->sqlobj->data->$fieldName)) return $this; + + /* 引用全局的config, lang。*/ + global $lang, $config, $app; + $table = strtolower(str_replace($config->db->prefix, '', $this->table)); + $fieldLabel = isset($lang->$table->$fieldName) ? $lang->$table->$fieldName : $fieldName; + $value = $this->sqlobj->data->$fieldName; + + if($funcName == 'unique') + { + $args = func_get_args(); + $sql = "SELECT COUNT(*) AS count FROM $this->table WHERE `$fieldName` = " . $this->sqlobj->quote($value); + if($this->table != TABLE_COMPANY) $sql .= " AND company = {$this->app->company->id} "; + if(isset($args[2])) $sql .= ' AND ' . $args[2]; + try + { + $row = $this->dbh->query($sql)->fetch(); + if($row->count != 0) $this->logError($funcName, $fieldName, $fieldLabel, array($value)); + } + catch (PDOException $e) + { + $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); + } + } + else + { + /* 取validate类方法中参数个数最大值,生成一个最大集合的参数列表。。*/ + $funcArgs = func_get_args(); + unset($funcArgs[0]); + unset($funcArgs[1]); + + for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) + { + ${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null; + } + $checkFunc = 'check' . $funcName; + if(validater::$checkFunc($value, $arg0, $arg1, $arg2) === false) + { + $this->logError($funcName, $fieldName, $fieldLabel, $funcArgs); + } + } + + return $this; + } + + /* 如果满足某一个条件,按照某个规则检查值是否符合要求。*/ + public function checkIF($condition, $fieldName, $funcName) + { + if(!$condition) return $this; + $funcArgs = func_get_args(); + for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) + { + ${"arg$i"} = isset($funcArgs[$i + 3]) ? $funcArgs[$i + 3] : null; + } + $this->check($fieldName, $funcName, $arg0, $arg1, $arg2); + return $this; + } + + /* 批量检查。*/ + public function batchCheck($fields, $funcName) + { + $fields = explode(',', str_replace(' ', '', $fields)); + $funcArgs = func_get_args(); + for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) + { + ${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null; + } + foreach($fields as $fieldName) $this->check($fieldName, $funcName, $arg0, $arg1, $arg2); + return $this; + } + + /* 批量条件检查。*/ + public function batchCheckIF($condition, $fields, $funcName) + { + if(!$condition) return $this; + $fields = explode(',', str_replace(' ', '', $fields)); + $funcArgs = func_get_args(); + for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) + { + ${"arg$i"} = isset($funcArgs[$i + 2]) ? $funcArgs[$i + 2] : null; + } + foreach($fields as $fieldName) $this->check($fieldName, $funcName, $arg0, $arg1, $arg2); + return $this; + } + + /* 自动根据数据库中表的字段格式进行检查。*/ + public function autoCheck($skipFields = '') + { + $fields = $this->getFieldsType(); + $skipFields = ",$skipFields,"; + + foreach($fields as $fieldName => $validater) + { + if(strpos($skipFields, $fieldName) !== false) continue; // 忽略。 + if(!isset($this->sqlobj->data->$fieldName)) continue; + if($validater['rule'] == 'skip') continue; + $options = array(); + if(isset($validater['options'])) $options = array_values($validater['options']); + for($i = 0; $i < VALIDATER::MAX_ARGS; $i ++) + { + ${"arg$i"} = isset($options[$i]) ? $options[$i] : null; + } + $this->check($fieldName, $validater['rule'], $arg0, $arg1, $arg2); + } + return $this; + } + + /* 记录错误。*/ + public function logError($checkType, $fieldName, $fieldLabel, $funcArgs = array()) + { + global $lang; + $error = $lang->error->$checkType; + $replaces = array_merge(array($fieldLabel), $funcArgs); + + /* 如果error不是数组,只是字符串,则循环replace,依次替换%s。*/ + if(!is_array($error)) + { + foreach($replaces as $replace) + { + $pos = strpos($error, '%s'); + if($pos === false) break; + $error = substr($error, 0, $pos) . $replace . substr($error, $pos +2); + } + } + /* 如果error是一个数组,则从数组中挑选%s个数与replace元素个数相同的。*/ + else + { + /* 去掉replace中空白的元素。*/ + foreach($replaces as $key => $value) if(is_null($value)) unset($replaces[$key]); + $replacesCount = count($replaces); + foreach($error as $errorString) + { + if(substr_count($errorString, '%s') == $replacesCount) + { + $error = vsprintf($errorString, $replaces); + } + } + } + dao::$errors[$fieldName][] = $error; + } + + /* 判断这次查询是否有错误。*/ + public function isError() + { + return !empty(dao::$errors); + } + + /* 返回error。*/ + public function getError() + { + $errors = dao::$errors; + dao::$errors = array(); + return $errors; + } + + /* 获得某一个表的字段类型。*/ + private function getFieldsType() + { + try + { + $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); + $sql = "DESC $this->table"; + $rawFields = $this->dbh->query($sql)->fetchAll(); + $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + } + catch (PDOException $e) + { + $this->app->error($e->getMessage() . "

The sql is: $sql

", __FILE__, __LINE__, $exit = true); + } + + foreach($rawFields as $rawField) + { + $firstPOS = strpos($rawField->type, '('); + $type = substr($rawField->type, 0, $firstPOS > 0 ? $firstPOS : strlen($rawField->type)); + $type = str_replace(array('big', 'small', 'medium', 'tiny', 'var'), '', $type); + $field = array(); + + if($type == 'enum' or $type == 'set') + { + $rangeBegin = $firstPOS + 2; // 将第一个引号去掉。 + $rangeEnd = strrpos($rawField->type, ')') - 1; // 将最后一个引号去掉。 + $range = substr($rawField->type, $rangeBegin, $rangeEnd - $rangeBegin); + $field['rule'] = 'reg'; + $field['options']['reg'] = '/' . str_replace("','", '|', $range) . '/'; + } + elseif($type == 'char') + { + $begin = $firstPOS + 1; + $end = strpos($rawField->type, ')', $begin); + $length = substr($rawField->type, $begin, $end - $begin); + $field['rule'] = 'length'; + $field['options']['max'] = $length; + $field['options']['min'] = 0; + } + elseif($type == 'int') + { + $field['rule'] = 'int'; + } + elseif($type == 'float' or $type == 'double') + { + $field['rule'] = 'float'; + } + elseif($type == 'date') + { + $field['rule'] = 'date'; + } + else + { + $field['rule'] = 'skip'; + } + $fields[$rawField->field] = $field; + } + return $fields; + } +} + +/** + * SQL查询封装类。 + * + * @package ZenTaoPHP + */ +class sql +{ + /** + * 所有方法的参数个数最大值。 + * + */ + const MAX_ARGS = 3; + + /** + * SQL语句。 + * + * @var string + * @access private + */ + private $sql = ''; + + /** + * 全局的$dbh(数据库访问句柄)对象。 + * + * @var object + * @access protected + */ + protected $dbh; + + /** + * INSERT或者UPDATE时赋给的数据。 + * + * @var mix + * @access protected + */ + public $data; + + /** + * 是否是首次调用set。 + * + * @var bool + * @access private; + */ + private $isFirstSet = true; + + /** + * 是否在条件判断中。 + * + * @var bool + * @access private; + */ + private $inCondition = false; + + /** + * 判断条件是否为ture。 + * + * @var bool + * @access private; + */ + private $conditionIsTrue = false; + + /** + * 是否自动magic quote。 + * + * @var bool + * @access public + */ + public $magicQuote; + + /* 构造函数。*/ + private function __construct($table = '') + { + global $dbh; + $this->dbh = $dbh; + $this->magicQuote = get_magic_quotes_gpc(); + } + + /* 实例化方法,通过该方法实例对象。*/ + public function factory($table = '') + { + return new sql($table); + } + + /* 查询语句开始。*/ + public function select($field = '*') + { + $sqlobj = self::factory(); + $sqlobj->sql = "SELECT $field "; + return $sqlobj; + } + + /* 更新语句开始。*/ + public function update($table) + { + $sqlobj = self::factory(); + $sqlobj->sql = "UPDATE $table SET "; + return $sqlobj; + } + + /* 插入语句开始。*/ + public function insert($table) + { + $sqlobj = self::factory(); + $sqlobj->sql = "INSERT INTO $table SET "; + return $sqlobj; + } + + /* 替换语句开始。*/ + public function replace($table) + { + $sqlobj = self::factory(); + $sqlobj->sql = "REPLACE $table SET "; + return $sqlobj; + } + + /* 删除语句开始。*/ + public function delete() + { + $sqlobj = self::factory(); + $sqlobj->sql = "DELETE "; + return $sqlobj; + } + + /* 给定一个key=>value结构的数组或者对象,拼装成key = value的形式。*/ + public function data($data) + { + $this->data = $data; + foreach($data as $field => $value) $this->sql .= "`$field` = " . $this->quote($value) . ','; + $this->sql = rtrim($this->sql, ','); // 去掉最后面的逗号。 + return $this; + } + + /* 加左边的括弧。*/ + public function markLeft($count = 1) + { + $this->sql .= str_repeat('(', $count); + return $this; + } + + /* 加右边的括弧。*/ + public function markRight($count = 1) + { + $this->sql .= str_repeat(')', $count); + return $this; + } + + /* SET key=value。*/ + public function set($set) + { + if($this->isFirstSet) + { + $this->sql .= " $set "; + $this->isFirstSet = false; + } + else + { + $this->sql .= ", $set"; + } + return $this; + } + + /* 设定要查询的表名。*/ + public function from($table) + { + $this->sql .= "FROM $table"; + return $this; + } + + /* 设置别名。*/ + public function alias($alias) + { + $this->sql .= " AS $alias "; + } + + /* 设定LEFT JOIN语句。*/ + public function leftJoin($table) + { + $this->sql .= " LEFT JOIN $table"; + return $this; + } + + /* 设定ON条件。*/ + public function on($condition) + { + $this->sql .= " ON $condition "; + return $this; + } + + /* 条件判断开始。*/ + public function beginIF($condition) + { + $this->inCondition = true; + $this->conditionIsTrue = $condition; + } + + /* 条件判断结束。*/ + public function fi() + { + $this->inCondition = false; + $this->conditionIsTrue = false; + } + + /* WHERE语句部分开始。*/ + public function where($arg1, $arg2 = null, $arg3 = null) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + if($arg3 !== null) + { + $value = $this->quote($arg3); + $condition = "`$arg1` $arg2 " . $this->quote($arg3); + } + else + { + $condition = $arg1; + } + + $this->sql .= ' ' . DAO::WHERE ." $condition "; + return $this; + } + + /* 追加AND条件。*/ + public function andWhere($condition) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " AND $condition "; + return $this; + } + + /* 追加OR条件。*/ + public function orWhere($condition) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " OR $condition "; + return $this; + } + + /* 等于。*/ + public function eq($value) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " = " . $this->quote($value); + return $this; + } + + /* 不等于。*/ + public function ne($value) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " != " . $this->quote($value); + return $this; + } + + /* 大于。*/ + public function gt($value) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " > " . $this->quote($value); + return $this; + } + + /* 小于。*/ + public function lt($value) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " < " . $this->quote($value); + return $this; + } + + /* 生成between语句。*/ + public function between($min, $max) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " BETWEEN $min AND $max "; + return $this; + } + + /* 生成 IN部分语句。*/ + public function in($ids) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= helper::dbIN($ids); + return $this; + } + + /* 生成 NOTIN部分语句。*/ + public function notin($ids) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= ' NOT ' . helper::dbIN($ids); + return $this; + } + + /* 生成LIKE部分语句。*/ + public function like($string) + { + if($this->inCondition and !$this->conditionIsTrue) return $this; + $this->sql .= " LIKE " . $this->quote($string); + return $this; + } + + /* 设定ORDER BY。*/ + public function orderBy($order) + { + $order = str_replace(array('|', '', '_'), ' ', $order); + $order = str_replace('left', '`left`', $order); // 处理left关键字。 + $this->sql .= ' ' . DAO::ORDERBY . " $order"; + return $this; + } + + /* 设定LIMIT。*/ + public function limit($limit) + { + if(empty($limit)) return $this; + stripos($limit, 'limit') !== false ? $this->sql .= " $limit " : $this->sql .= ' ' . DAO::LIMIT . " $limit "; + return $this; + } + + /* 设定GROUP BY。*/ + public function groupBy($groupBy) + { + $this->sql .= ' ' . DAO::GROUPBY . " $groupBy"; + return $this; + } + + /* 设定having。*/ + public function having($having) + { + $this->sql .= ' ' . DAO::HAVING . " $having"; + return $this; + } + + /* 返回拼装好的语句。*/ + public function get() + { + return $this->sql; + } + + /* 转义。*/ + public function quote($value) + { + if($this->magicQuote) $value = stripslashes($value); + return $this->dbh->quote($value); + } +} diff --git a/lib/filter/filter.class.php b/lib/filter/filter.class.php index 61ef8210f2..928747a6f2 100755 --- a/lib/filter/filter.class.php +++ b/lib/filter/filter.class.php @@ -2,19 +2,6 @@ /** * The validater and fixer class file of ZenTaoPHP. * - * ZenTaoPHP is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * ZenTaoPHP is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZenTaoPHP. If not, see . - * * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) * @author Chunsheng Wang * @package ZenTaoPHP diff --git a/lib/pager/pager.class.php b/lib/pager/pager.class.php index 1739e455af..ab9f979de7 100755 --- a/lib/pager/pager.class.php +++ b/lib/pager/pager.class.php @@ -2,19 +2,6 @@ /** * The pager class file of ZenTaoPHP. * - * ZenTaoPHP is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * ZenTaoPHP is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZenTaoPHP. If not, see . - * * @copyright Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com) * @author Chunsheng Wang * @package ZenTaoPHP