From e23311969d521af6f1fdde20115639cba3a7cdb2 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 1 Mar 2016 10:57:53 +0800 Subject: [PATCH] * change for new framework. --- config/config.php | 6 + framework/control.class.php | 360 ++++++-- framework/helper.class.php | 770 +++++++++++++++-- framework/model.class.php | 97 ++- framework/router.class.php | 953 +++++++++++++++------- lib/dao/dao.class.php | 522 +++++++++--- lib/filter/filter.class.php | 283 +++++-- lib/front/front.class.php | 644 ++++++++++----- lib/pager/pager.class.php | 157 +++- module/bug/view/browse.html.php | 2 - module/common/lang/zh-cn.php | 1 + module/common/model.php | 1 + module/common/view/header.lite.html.php | 20 +- module/common/view/m.header.lite.html.php | 20 +- module/company/view/browse.html.php | 2 +- module/mail/view/browse.html.php | 2 +- module/my/view/bug.html.php | 2 +- module/my/view/story.html.php | 2 +- module/my/view/task.html.php | 2 +- module/my/view/testcase.html.php | 2 +- module/my/view/todo.html.php | 2 +- module/product/view/browse.html.php | 2 +- module/product/view/index.html.php | 2 +- module/productplan/view/view.html.php | 4 +- module/project/view/bug.html.php | 2 +- module/project/view/importbug.html.php | 2 +- module/project/view/importtask.html.php | 2 +- module/project/view/index.html.php | 2 +- module/project/view/linkstory.html.php | 2 +- module/project/view/story.html.php | 2 +- module/project/view/task.html.php | 2 +- module/story/view/zerocase.html.php | 2 +- module/task/js/create.js | 2 +- module/testcase/js/create.js | 2 +- module/testcase/view/browse.html.php | 4 +- module/testcase/view/createbug.html.php | 2 +- module/testtask/view/cases.html.php | 2 +- module/testtask/view/linkcase.html.php | 2 +- www/index.php | 5 +- www/install.php | 4 +- www/js/m.my.full.js | 2 +- www/js/my.full.js | 16 +- www/upgrade.php | 4 +- 43 files changed, 2962 insertions(+), 957 deletions(-) mode change 100755 => 100644 framework/control.class.php mode change 100755 => 100644 framework/model.class.php mode change 100755 => 100644 framework/router.class.php mode change 100755 => 100644 lib/dao/dao.class.php mode change 100755 => 100644 lib/filter/filter.class.php mode change 100755 => 100644 lib/pager/pager.class.php diff --git a/config/config.php b/config/config.php index 3e26e09ff0..5ed1f70d7d 100644 --- a/config/config.php +++ b/config/config.php @@ -101,6 +101,11 @@ $config->slaveDB->encoding = 'UTF8'; $config->slaveDB->strictMode = false; $config->slaveDB->checkCentOS= true; +/* Framework config. */ +$config->framework = new stdclass(); +$config->framework->jsWithPrefix = false; +$config->framework->autoRepairTable = true; + /* Include the custom config file. */ $configRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR; $myConfig = $configRoot . 'my.php'; @@ -109,6 +114,7 @@ if(file_exists($myConfig)) include $myConfig; /* Set default table prefix. */ if(!isset($config->db->prefix)) $config->db->prefix = 'zt_'; +define('LANG_CREATED', false); /* Define the tables. */ define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`'); define('TABLE_DEPT', '`' . $config->db->prefix . 'dept`'); diff --git a/framework/control.class.php b/framework/control.class.php old mode 100755 new mode 100644 index 166be72c28..42f852aaed --- a/framework/control.class.php +++ b/framework/control.class.php @@ -1,23 +1,26 @@ app. - * 2. set the pathes of current module, and load it's mode class. + * 2. set the pathes of current module, and load it's model class. * 3. auto assign the $lang and $config to the view. * + * @param string $moduleName + * @param string $methodName + * @param string $appName * @access public * @return void */ - public function __construct($moduleName = '', $methodName = '') + public function __construct($moduleName = '', $methodName = '', $appName = '') { - /* Global the globals, and refer them to the class member. */ - global $app, $config, $lang, $dbh; + /* + * 将全局变量设为control类的成员变量,方便control的派生类调用。 + * Global the globals, and refer them to the class member. + **/ + global $app, $config, $lang, $dbh, $common; $this->app = $app; $this->config = $config; $this->lang = $lang; $this->dbh = $dbh; $this->viewType = $this->app->getViewType(); + $this->appName = $appName ? $appName : $this->app->getAppName(); - /* Load the model file auto. */ + /* + * 设置当前模块,读取该模块的model类。 + * Load the model file auto. + **/ $this->setModuleName($moduleName); $this->setMethodName($methodName); - $this->loadModel(); + $this->loadModel($this->moduleName, $appName); $this->setViewPrefix(); - /* Init the view vars. */ + /* + * 初始化$view视图类。 + * Init the view vars. + **/ $this->view = new stdclass(); - $this->view->app = $app; - $this->view->lang = $lang; - $this->view->config = $config; - $this->view->title = ''; + $this->view->app = $app; + $this->view->lang = $lang; + $this->view->config = $config; + $this->view->common = $common; + $this->view->title = ''; - /* Set super vars. */ + /* + * 设置超级变量,从$app引用过来。 + * Set super vars. + **/ $this->setSuperVars(); } - //-------------------- Model related methods --------------------// + //-------------------- Model相关方法(Model related methods) --------------------// - /* Set the module name. + /* + * 设置模块名。 + * Set the module name. * - * @param string $moduleName The module name, if empty, get it from $app. + * @param string $moduleName 模块名,如果为空,则从$app中获取 The module name, if empty, get it from $app. * @access private * @return void */ @@ -195,9 +254,10 @@ class control $this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName(); } - /* Set the method name. + /* Set the method name. + * 设置方法名。 * - * @param string $methodName The method name, if empty, get it from $app. + * @param string $methodName 方法名,如果为空,则从$app中获取 The method name, if empty, get it from $app. * @access private * @return void */ @@ -207,35 +267,46 @@ class control } /** + * 加载指定模块的model文件。 * Load the model file of one module. * - * @param string $methodName The method name, if empty, use current module's name. + * @param string $moduleName 模块名,如果为空,使用当前模块 The module name, if empty, use current module's name. + * @param string $appName The app name, if empty, use current app's name. * @access public - * @return object|bool If no model file, return false. Else return the model object. + * @return object|bool 如果没有model文件,返回false,否则返回model对象。 If no model file, return false. Else return the model object. */ - public function loadModel($moduleName = '') + public function loadModel($moduleName = '', $appName = '') { if(empty($moduleName)) $moduleName = $this->moduleName; - $modelFile = helper::setModelFile($moduleName); + if(empty($appName)) $appName = $this->appName; + $modelFile = helper::setModelFile($moduleName, $appName); - /* If no model file, try load config. */ + /* + * 如果没有model文件,尝试加载config配置信息。 + * If no model file, try load config. + */ if(!helper::import($modelFile)) { - $this->app->loadConfig($moduleName, false); - $this->app->loadLang($moduleName); + $this->app->loadConfig($moduleName, $appName, false); + $this->app->loadLang($moduleName, $appName); $this->dao = new dao(); return false; } - $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; - if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + $modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model'; + if(!class_exists($modelClass)) + { + $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; + if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + } - $this->$moduleName = new $modelClass(); + $this->$moduleName = new $modelClass($appName); $this->dao = $this->$moduleName->dao; return $this->$moduleName; } /** + * 设置超级全局变量,$app已经设置过了,直接引用。 * Set the super vars. * * @access protected @@ -252,6 +323,7 @@ class control } /** + * 为客户端是PC还是移动设备,设置视图文件前缀名。 * Set the prefix of view file for mobile or PC. * * @access public @@ -263,9 +335,22 @@ class control if(isset($this->config->viewPrefix[$this->viewType])) $this->viewPrefix = $this->config->viewPrefix[$this->viewType]; } - //-------------------- View related methods --------------------// - /** + * 设置客户端的设备类型 + * Set current device of visit website. + * + * @access public + * @return void + */ + public function setCurrentDevice() + { + $this->app->setCurrentDevice(); + $this->device = $this->app->device; + } + //-------------------- 视图相关方法(View related methods) --------------------// + + /** + * 设置视图文件,可以获取其他模块的视图文件。 * Set the view file, thus can use fetch other module's page. * * @param string $moduleName module name @@ -273,30 +358,42 @@ class control * @access private * @return string the view file */ - private function setViewFile($moduleName, $methodName) + public function setViewFile($moduleName, $methodName) { $moduleName = strtolower(trim($moduleName)); $methodName = strtolower(trim($methodName)); - $modulePath = $this->app->getModulePath($moduleName); - $viewExtPath = $this->app->getModuleExtPath($moduleName, 'view'); + $modulePath = $this->app->getModulePath($this->appName, $moduleName); + $viewExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'view'); /* Set infix for view file in mobile or pc. */ $viewType = $this->viewType; if(isset($this->config->viewPrefix[$this->viewType])) $viewType = 'html'; - /* The main view file, extension view file and hook file. */ + /* + * 主视图文件,扩展视图文件和钩子文件。 + * The main view file, extension view file and hook file. + **/ $mainViewFile = $modulePath . 'view' . DS . $this->viewPrefix . $methodName . '.' . $viewType . '.php'; - $extViewFile = $viewExtPath . $this->viewPrefix . $methodName . ".{$viewType}.php"; - $extHookFiles = glob($viewExtPath . $this->viewPrefix . $methodName . ".*.{$viewType}.hook.php"); - $viewFile = file_exists($extViewFile) ? $extViewFile : $mainViewFile; + /* Extension view file. */ + $commonExtViewFile = $viewExtPath['common'] . $this->viewPrefix . $methodName . ".{$viewType}.php"; + $siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->viewPrefix . $methodName . ".{$viewType}.php"; + + $viewFile = file_exists($commonExtViewFile) ? $commonExtViewFile : $mainViewFile; + $viewFile = (!empty($siteExtViewFile) and file_exists($siteExtViewFile)) ? $siteExtViewFile : $viewFile; if(!is_file($viewFile)) $this->app->triggerError("the view file $viewFile not found", __FILE__, __LINE__, $exit = true); + + /* Extension hook file. */ + $commonExtHookFiles = glob($viewExtPath['common'] . $this->viewPrefix . $methodName . ".*.{$viewType}.hook.php"); + $siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->viewPrefix . $methodName . ".*.{$viewType}.hook.php"); + $extHookFiles = array_merge((array) $commonExtHookFiles, (array) $siteExtHookFiles); if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles); return $viewFile; } /** + * 获取视图的扩展文件,在ext/view/目录下 * Get the extension file of an view. * * @param string $viewFile @@ -305,7 +402,19 @@ class control */ public function getExtViewFile($viewFile) { - $extPath = dirname(dirname(realpath($viewFile))) . '/ext/view/'; + if($this->config->site->code) + { + $extPath = dirname(dirname(realpath($viewFile))) . "/ext/_{$this->config->site->code}/view"; + $extViewFile = $extPath . basename($viewFile); + + if(file_exists($extViewFile)) + { + helper::cd($extPath); + return $extViewFile; + } + } + + $extPath = dirname(dirname(realpath($viewFile))) . '/ext/view/'; $extViewFile = $extPath . basename($viewFile); if(file_exists($extViewFile)) { @@ -316,6 +425,7 @@ class control } /** + * 获取方法的css内容,common.css + 该方法的css。 * Get css code for a method. * * @param string $moduleName @@ -327,37 +437,50 @@ class control { $moduleName = strtolower(trim($moduleName)); $methodName = strtolower(trim($methodName)); - $modulePath = $this->app->getModulePath($moduleName); - $cssMethodExt = $this->app->getModuleExtPath($moduleName, 'css') . $methodName . DS; - $cssCommonExt = $this->app->getModuleExtPath($moduleName, 'css') . 'common' . DS; + + $modulePath = $this->app->getModulePath($this->appName, $moduleName); + $cssExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'css') ; + $cssMethodExt = $cssExtPath['common'] . $methodName . DS; + $cssCommonExt = $cssExtPath['common'] . 'common' . DS; $css = ''; $mainCssFile = $modulePath . 'css' . DS . $this->viewPrefix . 'common.css'; $methodCssFile = $modulePath . 'css' . DS . $this->viewPrefix . $methodName . '.css'; - if(file_exists($mainCssFile)) $css .= file_get_contents($mainCssFile); - if(is_file($methodCssFile)) $css .= file_get_contents($methodCssFile); + if(file_exists($mainCssFile)) $css .= file_get_contents($mainCssFile); + if(is_file($methodCssFile)) $css .= file_get_contents($methodCssFile); $cssExtFiles = glob($cssCommonExt . $this->viewPrefix . '*.css'); - if(is_array($cssExtFiles)) + if(!empty($cssExtFiles) and is_array($cssExtFiles)) { - foreach($cssExtFiles as $cssFile) - { - $css .= file_get_contents($cssFile); - } + foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile); } $cssExtFiles = glob($cssMethodExt . $this->viewPrefix . '*.css'); - if(is_array($cssExtFiles)) + if(!empty($cssExtFiles) and is_array($cssExtFiles)) { - foreach($cssExtFiles as $cssFile) + foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile); + } + if(!empty($cssExtPath['site'])) + { + $cssMethodExt = $cssExtPath['site'] . $methodName . DS; + $cssCommonExt = $cssExtPath['site'] . 'common' . DS; + $cssExtFiles = glob($cssCommonExt . $this->viewPrefix . '*.css'); + if(!empty($cssExtFiles) and is_array($cssExtFiles)) { - $css .= file_get_contents($cssFile); + foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile); + } + + $cssExtFiles = glob($cssMethodExt . $this->viewPrefix . '*.css'); + if(!empty($cssExtFiles) and is_array($cssExtFiles)) + { + foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile); } } return $css; } /** + * 获取方法的js,common.js + 该方法的js。 * Get js code for a method. * * @param string $moduleName @@ -369,9 +492,11 @@ class control { $moduleName = strtolower(trim($moduleName)); $methodName = strtolower(trim($methodName)); - $modulePath = $this->app->getModulePath($moduleName); - $jsMethodExt = $this->app->getModuleExtPath($moduleName, 'js') . $methodName . DS; - $jsCommonExt = $this->app->getModuleExtPath($moduleName, 'js') . 'common' . DS; + + $modulePath = $this->app->getModulePath($this->appName, $moduleName); + $jsExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'js'); + $jsMethodExt = $jsExtPath['common'] . $methodName . DS; + $jsCommonExt = $jsExtPath['common'] . 'common' . DS; $js = ''; $mainJsFile = $modulePath . 'js' . DS . $this->viewPrefix . 'common.js'; @@ -380,26 +505,39 @@ class control if(is_file($methodJsFile)) $js .= file_get_contents($methodJsFile); $jsExtFiles = glob($jsCommonExt . $this->viewPrefix . '*.js'); - if(is_array($jsExtFiles)) + if(!empty($jsExtFiles) and is_array($jsExtFiles)) { - foreach($jsExtFiles as $jsFile) - { - $js .= file_get_contents($jsFile); - } + foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile); } $jsExtFiles = glob($jsMethodExt . $this->viewPrefix . '*.js'); - if(is_array($jsExtFiles)) + if(!empty($jsExtFiles) and is_array($jsExtFiles)) { - foreach($jsExtFiles as $jsFile) + foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile); + } + + if(!empty($jsExtPath['site'])) + { + $jsMethodExt = $jsExtPath['site'] . $methodName . DS; + $jsCommonExt = $jsExtPath['site'] . 'common' . DS; + + $jsExtFiles = glob($jsCommonExt . $this->viewPrefix . '*.js'); + if(!empty($jsExtFiles) and is_array($jsExtFiles)) { - $js .= file_get_contents($jsFile); + foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile); + } + + $jsExtFiles = glob($jsMethodExt . $this->viewPrefix . '*.js'); + if(!empty($jsExtFiles) and is_array($jsExtFiles)) + { + foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile); } } return $js; } /** + * 向$view传递一个变量。 * Assign one var to the view vars. * * @param string $name the name. @@ -413,8 +551,9 @@ class control } /** + * 将之前打算输出的内容清空。 * Clear the output. - * + * * @access public * @return void */ @@ -424,6 +563,7 @@ class control } /** + * 根据请求的视图类型,生成输出内容。 * Parse view file. * * @param string $moduleName module name, if empty, use current module. @@ -448,6 +588,7 @@ class control } /** + * 请求为json格式的处理逻辑。 * Parse json format. * * @param string $moduleName module name @@ -471,6 +612,7 @@ class control } /** + * 其他请求格式的处理逻辑,输出视图文件的内容。 * Parse default html format. * * @param string $moduleName module name @@ -481,13 +623,14 @@ class control private function parseDefault($moduleName, $methodName) { /* Set the view file. */ - $viewFile = $this->setViewFile($moduleName, $methodName); - if(is_array($viewFile)) extract($viewFile); + $results = $this->setViewFile($moduleName, $methodName); + $viewFile = $results; + if(is_array($results)) extract($results); /* Get css and js. */ $css = $this->getCSS($moduleName, $methodName); $js = $this->getJS($moduleName, $methodName); - if($css) $this->view->pageCss = $css; + if($css) $this->view->pageCSS = $css; if($js) $this->view->pageJS = $js; /* Change the dir to the view file to keep the relative pathes work. */ @@ -497,7 +640,7 @@ class control extract((array)$this->view); ob_start(); include $viewFile; - if(isset($hookFiles)) foreach($hookFiles as $hookFile) include $hookFile; + if(isset($hookFiles)) foreach($hookFiles as $hookFile) if(file_exists($hookFile)) include $hookFile; $this->output .= ob_get_contents(); ob_end_clean(); @@ -506,8 +649,10 @@ class control } /** + * 获取一个方法的输出内容,这样我们可以在一个方法里获取其他模块方法的内容。 + * 如果模块名为空,则调用该模块、该方法;如果设置了模块名,调用指定模块指定方法。 + * * Get the output of one module's one method as a string, thus in one module's method, can fetch other module's content. - * * If the module name is empty, then use the current module and method. If set, use the user defined module and method. * * @param string $moduleName module name. @@ -516,42 +661,58 @@ class control * @access public * @return string the parsed html. */ - public function fetch($moduleName = '', $methodName = '', $params = array()) + public function fetch($moduleName = '', $methodName = '', $params = array(), $appName = '') { if($moduleName == '') $moduleName = $this->moduleName; if($methodName == '') $methodName = $this->methodName; + if($appName == '') $appName = $this->appName; if($moduleName == $this->moduleName and $methodName == $this->methodName) { $this->parse($moduleName, $methodName); return $this->output; } - /* Set the pathes and files to included. */ - $modulePath = $this->app->getModulePath($moduleName); + /* + * 设置引用的文件和路径。 + * Set the pathes and files to included. + **/ + $modulePath = $this->app->getModulePath($appName, $moduleName); $moduleControlFile = $modulePath . 'control.php'; - $actionExtFile = $this->app->getModuleExtPath($moduleName, 'control') . strtolower($methodName) . '.php'; - $file2Included = file_exists($actionExtFile) ? $actionExtFile : $moduleControlFile; + $actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control'); + $commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php'; + $file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile; + if(!empty($actionExtPath['site'])) + { + $siteActionExtFile = $actionExtPath['site'] . strtolower($methodName) . '.php'; + $file2Included = file_exists($siteActionExtFile) ? $siteActionExtFile : $file2Included; + } + + /* 加载控制器文件。 */ /* Load the control file. */ if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true); $currentPWD = getcwd(); chdir(dirname($file2Included)); if($moduleName != $this->moduleName) helper::import($file2Included); - + + /* 设置调用的类名。 */ /* Set the name of the class to be called. */ $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName; if(!class_exists($className)) $this->app->triggerError(" The class $className not found", __FILE__, __LINE__, $exit = true); + /* 解析参数,创建模块control对象。 */ /* Parse the params, create the $module control object. */ if(!is_array($params)) parse_str($params, $params); - $module = new $className($moduleName, $methodName); + $module = new $className($moduleName, $methodName, $appName); + /* 调用对应方法,使用ob方法获取输出内容。 */ /* Call the method and use ob function to get the output. */ ob_start(); call_user_func_array(array($module, $methodName), $params); $output = ob_get_contents(); ob_end_clean(); + /* 返回内容。 */ /* Return the content. */ unset($module); chdir($currentPWD); @@ -559,8 +720,9 @@ class control } /** + * 向浏览器输出内容。 * Print the content of the view. - * + * * @param string $moduleName module name * @param string $methodName method name * @access public @@ -571,24 +733,54 @@ class control if(empty($this->output)) $this->parse($moduleName, $methodName); echo $this->output; } - /** + * 直接输出data数据,通常用于ajax请求中。 * Send data directly, for ajax requests. - * + * * @param misc $data * @param string $type * @access public * @return void */ public function send($data, $type = 'json') - { - if($type == 'json') echo json_encode($data); + { + $data = (array) $data; + if($type == 'json') + { + if(!helper::isAjaxRequest()) + { + if(isset($data['result']) and $data['result'] == 'success') + { + if(!empty($data['message'])) echo js::alert($data['message']); + $locate = isset($data['locate']) ? $data['locate'] : (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''); + if(!empty($locate)) die(js::locate($locate)); + die(isset($data['message']) ? $data['message'] : 'success'); + } + + if(isset($data['result']) and $data['result'] == 'fail') + { + if(!empty($data['message'])) + { + $message = json_decode(json_encode((array)$data['message'])); + foreach((array)$message as $item => $errors) + { + $message->$item = implode(',', $errors); + } + echo js::alert(strip_tags(implode(" ", (array) $message))); + die(js::locate('back')); + } + } + } + + echo json_encode($data); + } die(helper::removeUTF8Bom(ob_get_clean())); - } + } /** + * 创建一个模块方法的链接。 * Create a link to one method of one module. - * + * * @param string $moduleName module name * @param string $methodName method name * @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2 @@ -603,6 +795,7 @@ class control } /** + * 创建当前模块的一个方法链接。 * Create a link to the inner method of current module. * * @param string $methodName method name @@ -617,6 +810,7 @@ class control } /** + * 重定向到另一个页面。 * Location to another page. * * @param string $url the target url. diff --git a/framework/helper.class.php b/framework/helper.class.php index baf866105d..71e5364ff8 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -1,16 +1,18 @@ * * 'value') or key1=value1&key2=value2) or key1=value1&key2=value2 * @param string $viewType the view type - * @param string $onlybody the view type + * @param bool $onlybody whether onlybody * @static * @access public * @return string the link string. @@ -65,43 +71,50 @@ class helper static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlybody = false) { global $app, $config; - $link = $config->requestType == 'PATH_INFO' ? $config->webRoot : $_SERVER['PHP_SELF']; + $appName = $app->getAppName(); + $appName = empty($appName) ? '' : $appName . '/'; + if(strpos($moduleName, '.') !== false) list($appName, $moduleName) = explode('.', $moduleName); + + $link = $config->requestType == 'PATH_INFO' ? $config->webRoot . $appName : $config->webRoot . $appName . basename($_SERVER['SCRIPT_NAME']); + if($config->requestType == 'PATH_INFO2') $link .= '/'; + + /* 设置视图类型和变量。 */ /* Set the view type and vars. */ if(empty($viewType)) $viewType = $app->getViewType(); if(!is_array($vars)) parse_str($vars, $vars); - /* The PATH_INFO type. */ - if($config->requestType == 'PATH_INFO') + /* PATH_INFO方式。 */ + /* The PATH_INFO and PATH_INFO2 type. */ + if($config->requestType != 'GET') { + /* 如果方法名与默认方法相等,并且参数是空的,转换为友好的链接地址。 */ /* If the method equal the default method defined in the config file and the vars is empty, convert the link. */ if($methodName == $config->default->method and empty($vars)) { + /* 如果模块名与默认模块名相等,转换为index.html。*/ /* If the module also equal the default module, change index-index to index.html. */ if($moduleName == $config->default->module) { $link .= 'index.' . $viewType; } - else + elseif($viewType == $app->getViewType()) { $link .= $moduleName . '/'; } + else + { + $link .= $moduleName . '.' . $viewType; + } } else { $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"; - } + foreach($vars as $value) $link .= "{$config->requestFix}$value"; $link .= '.' . $viewType; } } - elseif($config->requestType == 'GET') + else { $link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName"; if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType; @@ -111,15 +124,16 @@ class helper /* if page has onlybody param then add this param in all link. the param hide header and footer. */ if($onlybody or isonlybody()) { - $onlybody = $config->requestType == 'PATH_INFO' ? "?onlybody=yes" : "&onlybody=yes"; + $onlybody = $config->requestType != 'GET' ? "?onlybody=yes" : "&onlybody=yes"; $link .= $onlybody; } return $link; } /** - * Import a file instend of include or requie. - * + * 引用一个文件,替换内置的include及require方法 + * Import a file instend of include or require. + * * @param string $file the file to be imported. * @static * @access public @@ -127,11 +141,11 @@ class helper */ static public function import($file) { + if(!is_file($file)) return false; static $includedFiles = array(); if(!isset($includedFiles[$file])) { - $return = include $file; - if(!$return) return false; + include $file; $includedFiles[$file] = true; return true; } @@ -139,39 +153,65 @@ class helper } /** + * 设置一个模块的model文件,如果存在model扩展,一起合并 * Set the model file of one module. If there's an extension file, merge it with the main model file. * * @param string $moduleName the module name + * @param string $appName the app name * @static * @access public * @return string the model file */ - static public function setModelFile($moduleName) + static public function setModelFile($moduleName, $appName = '') { global $app; + if($appName == '') $appName = $app->getAppName(); - /* Set the main model file and extension and hook pathes and files. */ - $mainModelFile = $app->getModulePath($moduleName) . 'model.php'; - $modelExtPath = $app->getModuleExtPath($moduleName, 'model'); - $modelHookPath = $modelExtPath . 'hook/'; - $extFiles = helper::ls($modelExtPath, '.php'); - $hookFiles = helper::ls($modelHookPath, '.php'); + /* 设置主model文件,扩展文件和路径。 */ + /* Set the main model file, extension path and files. */ + $mainModelFile = $app->getModulePath($appName, $moduleName) . 'model.php'; + $modelExtPaths = $app->getModuleExtPath($appName, $moduleName, 'model'); - /* If no extension files and no hook files, return the main file directly. */ + $hookFiles = array(); + $extFiles = array(); + foreach($modelExtPaths as $modelExtPath) + { + $hookFiles = array_merge($hookFiles, helper::ls($modelExtPath . 'hook/', '.php')); + $extFiles = array_merge($extFiles, helper::ls($modelExtPath, '.php')); + } + + /* Get ext's app name from realname. */ + if($appName) $extAppName = basename(dirname(dirname(dirname($modelExtPath)))); + + /* 如果没有扩展文件,返回主文件目录。 */ + /* If no extension file, return the main file directly. */ if(empty($extFiles) and empty($hookFiles)) return $mainModelFile; + /* 通过对比合并后的缓存文件和扩展文件的修改时间,确定是否要重新生成缓存 */ /* Else, judge whether needed update or not .*/ + $extModelPrefix = empty($app->siteCode) ? '' : $app->siteCode{0} . DS . $app->siteCode; + $mergedModelDir = $app->getTmpRoot() . 'model' . DS . $extModelPrefix . DS; + $mergedModelFile = $mergedModelDir . (empty($app->siteCode) ? '' : $app->siteCode . '.') . $moduleName . '.php'; $needUpdate = false; - $mergedModelFile = $app->getTmpRoot() . 'model' . DS . $moduleName . '.php'; $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; + if(!is_dir($mergedModelDir)) mkdir($mergedModelDir, 0755, true); while(!$needUpdate) { foreach($extFiles as $extFile) if(filemtime($extFile) > $lastTime) break 2; foreach($hookFiles as $hookFile) if(filemtime($hookFile) > $lastTime) break 2; + $modelExtPath = $modelExtPaths['common']; + $modelHookPath = $modelExtPaths['common'] . 'hook/'; if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) break; if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) break; + if($modelExtPaths['site']) + { + $modelExtPath = $modelExtPaths['site']; + $modelHookPath = $modelExtPaths['site'] . 'hook/'; + if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) break; + if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) break; + } if(filemtime($mainModelFile) > $lastTime) break; @@ -237,7 +277,7 @@ class helper $modelLines = join("\n", $modelLines); } - $tmpMergedModelFile = $app->getTmpRoot() . 'model' . DS . 'tmp.' . $moduleName . '.php'; + $tmpMergedModelFile = $mergedModelDir . 'tmp.' . (empty($app->siteCode) ? '' : $app->siteCode . '.') . $moduleName . '.php'; if(!@file_put_contents($tmpMergedModelFile, $modelLines)) { die("ERROR: $tmpMergedModelFile not writable, please make sure the " . dirname($tmpMergedModelFile) . ' directory exists and writable'); @@ -307,6 +347,7 @@ class helper } /** + * 将数组转化成 IN( 'a', 'b') 的形式,用于数据库字符串拼接 * Create the in('a', 'b') string. * * @param string|array $ids the id lists, can be a array or a string with ids joined with comma. @@ -316,11 +357,21 @@ class helper */ static public function dbIN($ids) { - if(is_array($ids)) return "IN ('" . join("','", $ids) . "')"; - return "IN ('" . str_replace(',', "','", str_replace(' ', '',$ids)) . "')"; + if(is_array($ids)) + { + if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) + { + foreach ($ids as $key=>$value) $ids[$key] = addslashes($value); + } + return "IN ('" . join("','", $ids) . "')"; + } + + if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) $ids = addslashes($ids); + return "IN ('" . str_replace(',', "','", str_replace(' ', '', $ids)) . "')"; } /** + * base64编码,框架对'/'字符比较敏感,转换为'.' * Create safe base64 encoded string for the framework. * * @param string $string the string to encode. @@ -334,6 +385,7 @@ class helper } /** + * 解码base64,先将之前的'.' 转换回'/' * Decode the string encoded by safe64Encode. * * @param string $string the string to decode @@ -347,6 +399,20 @@ class helper } /** + * Json encode and addslashe if magic_quotes_gpc is on. + * + * @param mixed $data the object to encode + * @static + * @access public + * @return string decoded string. + */ + static public function jsonEncode($data) + { + return (version_compare(phpversion(), '5.4', '<') and function_exists('get_magic_quotes_gpc') and get_magic_quotes_gpc()) ? addslashes(json_encode($data)) : json_encode($data); + } + + /** + * 判断是否是utf8编码 * Judge a string is utf-8 or not. * * @param string $string @@ -388,10 +454,11 @@ class helper } /** + * 计算两个日期相差的天数,取整 * Compute the diff days of two date. * - * @param date $date1 the first date. - * @param date $date2 the sencode date. + * @param string $date1 the first date. + * @param string $date2 the sencode date. * @access public * @return int the diff of the two days. */ @@ -401,6 +468,7 @@ class helper } /** + * 获取当前时间,使用common语言文件定义的DT_DATETIME1常量 * Get now time use the DT_DATETIME1 constant defined in the lang file. * * @access public @@ -412,8 +480,9 @@ class helper } /** + * 获取当前日期,使用common语言文件定义的DT_DATE1常量 * Get today according to the DT_DATE1 constant defined in the lang file. - * + * * @access public * @return date today */ @@ -423,6 +492,19 @@ class helper } /** + * 获取当前日期,使用common语言文件定义的DT_DATE1常量 + * Get now time use the DT_TIME1 constant defined in the lang file. + * + * @access public + * @return date today + */ + static public function time() + { + return date(DT_TIME1); + } + + /** + * 判断日期是不是零 * Judge a date is zero or not. * * @access public @@ -434,6 +516,7 @@ class helper } /** + * 列出目录中符合该正则表达式的文件 * Get files match the pattern under one directory. * * @access public @@ -441,13 +524,16 @@ class helper */ static public function ls($dir, $pattern = '') { + if(empty($dir)) return array(); + $files = array(); - $dir = realpath($dir); + $dir = realpath($dir); if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern); return empty($files) ? array() : $files; } /** + * 切换目录 * Change directory. * * @param string $path @@ -458,18 +544,12 @@ class helper static function cd($path = '') { static $cwd = ''; - if($path) - { - $cwd = getcwd(); - chdir($path); - } - else - { - chdir($cwd); - } + if($path) $cwd = getcwd(); + !empty($path) ? chdir($path) : chdir($cwd); } /** + * 去掉UTF8 Bom头 * Remove UTF8 Bom * * @param string $string @@ -483,6 +563,67 @@ class helper } /** + * 通过域名获取站点代号。 + * Get siteCode from domain. + * @param string $domain + * @return string $siteCode + **/ + public static function getSiteCode($domain) + { + global $config; + + if(strpos($domain, ':') !== false) $domain = substr($domain, 0, strpos($domain, ':')); // Remove port from domain. + $domain = strtolower($domain); + + if(isset($config->siteCode[$domain])) return $config->siteCode[$domain]; + + if($domain == 'localhost') return $domain; + if(!preg_match('/^([a-z0-9\-_]+\.)+[a-z0-9\-]+$/', $domain)) die('domain denied'); + + $domain = str_replace('-', '_', $domain); // Replace '-' by '_'. + $items = explode('.', $domain); + $postfix = str_replace($items[0] . '.', '', $domain); + if(isset($config->chanzhi->node->domain) and $postfix == $config->chanzhi->node->domain) return $items[0]; + if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0]; + + $postfix = str_replace($items[0] . '.' . $items[1] . '.', '', $domain); + if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[1]; + + return null; + } + + /** + * 增强substr方法:支持多字节语言,比如中文。 + * Enhanced substr version: support multibyte languages like Chinese. + * + * @param string $string + * @param int $length + * @param string $append + * @return string + **/ + public static function substr($string, $length, $append = '') + { + if (strlen($string) <= $length ) $append = ''; + if(function_exists('mb_substr')) return mb_substr($string, 0, $length, 'utf-8') . $append; + + preg_match_all("/./su", $string, $data); + return join("", array_slice($data[0], 0, $length)) . $append; + } + + /** + * 检查是否是SEO模式 + * Check in seo mode or not. + * + * return bool + */ + public static function inSeoMode() + { + global $config; + return (!empty($config->seoMode) and ($config->requestType != 'GET')); + } + + /** + * 检查是否是AJAX请求 * Check is ajax request. * * @static @@ -495,6 +636,147 @@ class helper } /** + * 301跳转 + * Header 301 Moved Permanently. + * + * @param string $locate + * @access public + * @return void + */ + public static function header301($locate) + { + header('HTTP/1.1 301 Moved Permanently'); + die(header('Location:' . $locate)); + } + + /** + * 获取浏览器类型。 + * Get browser. + * + * @access public + * @return string + */ + public static function getBrowser() + { + if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow'; + + $agent = $_SERVER["HTTP_USER_AGENT"]; + if(strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) + { + return "ie"; + } + else if(strpos($agent, 'Firefox') !== false) + { + return "firefox"; + } + else if(strpos($agent, 'Chrome') !== false) + { + return "chrome"; + } + else if(strpos($agent, 'Opera') !== false) + { + return 'opera'; + } + else if((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false) + { + return 'safari'; + } + else + { + return 'unknown'; + } + } + + /** + * 获取浏览器版本 + * Get browser version. + * + * @access public + * @return string + */ + public static function getBrowserVersion() + { + if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow'; + + $agent = $_SERVER['HTTP_USER_AGENT']; + if(preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) + { + return $regs[1]; + } + else if(preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) + { + return $regs[1]; + } + else if(preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) + { + return $regs[1]; + } + else if(preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) + { + return $regs[1]; + } + else if((strpos($agent,'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) + { + return $regs[1]; + } + else if(preg_match('/rv:(\d+)\..*/i', $agent, $regs)) + { + return $regs[1]; + } + else + { + return 'unknow'; + } + } + + /** + * 获取客户端操作系统 + * Get client os from agent info. + * + * @static + * @access public + * @return string + */ + public static function getOS() + { + if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow'; + + $osList = array( + '/windows nt 10/i' => 'Windows 10', + '/windows nt 6.3/i' => 'Windows 8.1', + '/windows nt 6.2/i' => 'Windows 8', + '/windows nt 6.1/i' => 'Windows 7', + '/windows nt 6.0/i' => 'Windows Vista', + '/windows nt 5.2/i' => 'Windows Server 2003/XP x64', + '/windows nt 5.1/i' => 'Windows XP', + '/windows xp/i' => 'Windows XP', + '/windows nt 5.0/i' => 'Windows 2000', + '/windows me/i' => 'Windows ME', + '/win98/i' => 'Windows 98', + '/win95/i' => 'Windows 95', + '/win16/i' => 'Windows 3.11', + '/macintosh|mac os x/i' => 'Mac OS X', + '/mac_powerpc/i' => 'Mac OS 9', + '/linux/i' => 'Linux', + '/ubuntu/i' => 'Ubuntu', + '/iphone/i' => 'iPhone', + '/ipod/i' => 'iPod', + '/ipad/i' => 'iPad', + '/android/i' => 'Android', + '/blackberry/i' => 'BlackBerry', + '/webos/i' => 'Mobile' + ); + + foreach ($osList as $regex => $value) + { + if(preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) return $value; + } + + return 'unknown'; + } + + /** + * 设置$viewType,html还是mhtml或其他。 * Set viewType. * * @static @@ -537,9 +819,192 @@ class helper if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view; $app->viewType = isset($viewType) ? $viewType : $config->default->view; } + + /** + * 数据配置合并到主配置 + * Merge config items in database and config files. + * + * @param array $dbConfig + * @param string $moduleName + * @static + * @access public + * @return void + */ + public static function mergeConfig($dbConfig, $moduleName = 'common') + { + global $config; + + $config2Merge = $config; + if($moduleName != 'common') $config2Merge = $config->$moduleName; + + foreach($dbConfig as $item) + { + foreach($item as $record) + { + if(!is_object($record)) + { + $config2Merge->{$item->key} = $item->value; + break; + } + + if(!isset($config2Merge->{$record->section})) $config2Merge->{$record->section} = new stdclass(); + if($record->key) $config2Merge->{$record->section}->{$record->key} = $record->value; + } + } + } + + /** + * 将字符串中的字符统一到标准字符。 + * Unify string to standard chars. + * + * @param string $string + * @param string $to + * @static + * @access public + * @return string + */ + public static function unify($string, $to = ',') + { + $labels = array('_', '、', ' ', '-', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', ',', '。'); + $string = str_replace($labels, $to, $string); + return preg_replace("/[{$to}]+/", $to, trim($string, $to)); + } + + /** + * 获取远程IP。 + * Get remote ip. + * + * @access public + * @return string + */ + public static function getRemoteIp() + { + $ip = ''; + if(!empty($_SERVER['HTTP_CLIENT_IP'])) + { + $ip = $_SERVER['HTTP_CLIENT_IP']; + } + else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) + { + $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; + } + else if(!empty($_SERVER["REMOTE_ADDR"])) + { + $ip = $_SERVER["REMOTE_ADDR"]; + } + + return $ip; + } + + /** + * 检查IP是否在给定的IP范围内。 + * check ip is in network. + * + * @param string $ip + * @param string $network + * @access public + * @return void + */ + public static function checkIpScope($ip, $network) + { + if(strpos($network, '/') === false) return $ip == $network; + + $ip = (double) (sprintf("%u", ip2long($ip))); + $s = explode('/', $network); + $networkStart = (double) (sprintf("%u", ip2long($s[0]))); + $networkLen = pow(2, 32 - $s[1]); + $networkEnd = $networkStart + $networkLen - 1; + + if ($ip >= $networkStart && $ip <= $networkEnd) + { + return true; + } + return false; + } + + /** + * 检查IP是否合法。 + * Check ip avaliable. + * + * @param string $ip + * @access public + * @return bool + */ + public static function checkIP($ip) + { + $ip = trim($ip); + if(strpos($ip, '/') !== false) + { + $s = explode('/', $ip); + preg_match('/^(((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)(\.((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)){3})$/', $s[0], $matches); + if(!empty($matches) and $s[1] > 0 and $s[1] < 36) return true; + } + else + { + preg_match('/^(((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)(\.((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)){3})$/', $ip, $matches); + if(!empty($matches)) return true; + } + return false; + } + + /** + * 创建随机的字符串。 + * Create random string. + * + * @param int $length + * @param string $skip A-Z|a-z|0-9 + * @static + * @access public + * @return void + */ + public static function createRandomStr($length, $skip = '') + { + $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $skip = str_replace('A-Z', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', $skip); + $skip = str_replace('a-z', 'abcdefghijklmnopqrstuvwxyz', $skip); + $skip = str_replace('0-9', '0123456789', $skip); + for($i = 0; $i < strlen($skip); $i++) + { + $str = str_replace($skip[$i], '', $str); + } + + $strlen = strlen($str); + while($length > strlen($str)) $str .= $str; + + $str = str_shuffle($str); + return substr($str,0,$length); + } + + /** + * 获取设备类型。 + * Get device. + * + * @access public + * @return void + */ + public static function getDevice() + { + global $app, $config; + + $viewType = $app->getViewType(); + if($viewType == 'mhtml') return 'mobile'; + + if(isset($_COOKIE['visualDevice'])) return $_COOKIE['visualDevice']; + + /* Detect mobile. */ + $mobile = $app->loadClass('mobile'); + if($mobile->isMobile()) + { + if(!isset($config->template->mobile)) return 'desktop'; + if(isset($config->site->mobileTemplate) and $config->site->mobileTemplate == 'close') return 'desktop'; + return 'mobile'; + } + return 'desktop'; + } } /** + * helper::createLink()的别名,方便创建本模块的链接 * The short alias of helper::createLink() method. * * @param string $methodName the method name @@ -554,7 +1019,8 @@ function inLink($methodName = 'index', $vars = '', $viewType = '') } /** - * Static cycle a array + * 通过一个静态游标,可以遍历数组 + * Static cycle a array * * @param array $items the array to be cycled. * @return mixed @@ -568,6 +1034,7 @@ function cycle($items) } /** + * 获取当前时间的Unix时间戳,精确到微妙 * Get current microtime. * * @access protected @@ -580,6 +1047,7 @@ function getTime() } /** + * 打印变量的信息 * dump a var. * * @param mixed $var @@ -594,27 +1062,7 @@ function a($var) } /** - * When the $var has the $key, return it, esle result one default value. - * - * @param array|object $var - * @param string|int $key - * @param mixed $valueWhenNone value when the key not exits. - * @param mixed $valueWhenExists value when the key exits. - * @access public - * @return void - */ -function zget($var, $key, $valueWhenNone = '', $valueWhenExists = '') -{ - $var = (array)$var; - if(isset($var[$key])) - { - if($valueWhenExists) return $valueWhenExists; - return $var[$key]; - } - return $valueWhenNone; -} - -/** + * 判断是否内外IP。 * Judge the server ip is local or not. * * @access public @@ -624,10 +1072,12 @@ function isLocalIP() { $serverIP = $_SERVER['SERVER_ADDR']; if($serverIP == '127.0.0.1') return true; + if(strpos($serverIP, '10.60') !== false) return false; return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); } /** + * 获取webRoot。 * Get web root. * * @access public @@ -647,6 +1097,7 @@ function getWebRoot() } /** + * 检查是否是onlybody模式。 * Check exist onlybody param. * * @access public @@ -656,3 +1107,184 @@ function isonlybody() { return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes'); } + +/** + * 格式化钱。 + * Format money. + * + * @param float $money + * @access public + * @return string + */ +function formatMoney($money) +{ + return trim(preg_replace('/\.0*$/', '', number_format($money, 2))); +} + +/** + * 格式化时间 + * Format time. + * + * @param int $time + * @param string $format + * @access public + * @return void + */ +function formatTime($time, $format = '') +{ + $time = str_replace('0000-00-00', '', $time); + $time = str_replace('00:00:00', '', $time); + if(trim($time) == '') return ; + if($format) return date($format, strtotime($time)); + return trim($time); +} + +/** + * 检查可用curl ssl。 + * Check curl ssl enabled. + * + * @access public + * @return void + */ +function checkCurlSSL() +{ + $version = curl_version(); + return ($version['features'] & CURL_VERSION_SSL); +} + +/** + * 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。 + * When the $var has the $key, return it, esle result one default value. + * + * @param array|object $var + * @param string|int $key + * @param mixed $valueWhenNone value when the key not exits. + * @param mixed $valueWhenExists value when the key exits. + * @access public + * @return string + */ +function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false) +{ + if(!is_array($var) and !is_object($var)) return false; + $type = is_array($var) ? 'array' : 'object'; + $checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key); + if($checkExists) + { + if($valueWhenExists !== false) return $valueWhenExists; + return $type == 'array' ? $var[$key] : $var->$key; + } + if($valueWhenNone !== false) return $valueWhenNone; + return $key; +} + +/** + * 301跳转。 + * Header lcoation 301. + * + * @param string $url + * @access public + * @return void + */ +function header301($url) +{ + header('HTTP/1.1 301 Moved Permanently'); + die(header('Location:' . $url)); +} + +/** + * 处理恶意参数. + * Process evil params. + * + * @param string $value + * @access public + * @return void + */ +function processEvil($value) +{ + if(strpos(htmlspecialchars_decode($value), ' $values) + { + if(!is_array($values)) + { + $params[$item] = processEvil($values); + if(processEvil($item) != $item) unset($params[$item]); + } + else + { + foreach($values as $key => $value) + { + if(is_array($value)) continue; + $params[$item][$key] = processEvil($value); + if(processEvil($key) != $key) unset($params[$item][$key]); + } + } + } + return $params; +} + +/** + * 获取主机地址。 + * Get host URL. + * + * @access public + * @return bool + */ +function getHostURL() +{ + return ((isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) != 'off') ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']; +} + +/** + * 判断requestType是否是GET类型。 + * Check current request is GET. + * + * @access public + * @return void + */ +function isGetUrl() +{ + $webRoot = getWebRoot(); + if(strpos($_SERVER['REQUEST_URI'], "{$webRoot}?") === 0) return true; + if(strpos($_SERVER['REQUEST_URI'], "{$webRoot}index.php?") === 0) return true; + if(strpos($_SERVER['REQUEST_URI'], "{$webRoot}index.php/?") === 0) return true; + return false; +} + +/** + * 获取文件mime。 + * Get file mime type. + * + * @param int $file + * @access public + * @return void + */ +function getFileMimeType($file) +{ + if(function_exists('mime_content_type')) return mime_content_type($file); + if(function_exists('finfo_open')) + { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + return finfo_file($finfo, $file); + } + return false; +} diff --git a/framework/model.class.php b/framework/model.class.php old mode 100755 new mode 100644 index 3a0cdef7b2..3de646e4eb --- a/framework/model.class.php +++ b/framework/model.class.php @@ -1,5 +1,6 @@ app. * 2. set the pathes, config, lang of current module - * + * + * @param string $appName * @access public * @return void */ - public function __construct() + public function __construct($appName = '') { global $app, $config, $lang, $dbh; - $this->app = $app; - $this->config = $config; - $this->lang = $lang; - $this->dbh = $dbh; + $this->app = $app; + $this->config = $config; + $this->lang = $lang; + $this->dbh = $dbh; + $this->appName = empty($appName) ? $this->app->getAppName() : $appName; $moduleName = $this->getModuleName(); - $this->app->loadLang($moduleName, $exit = false); - $this->app->loadConfig($moduleName, $exit = false); - + $this->app->loadLang($moduleName, $this->appName); + $this->app->loadConfig($moduleName, $this->appName, $exitIfNone = false); + $this->loadDAO(); $this->setSuperVars(); } /** + * 获取该model的模块名,而不是用户请求的模块名。 + * + * 这个方法通过去掉该model类名的'ext'和'model'字符串,来获取当前模块名。 + * 不要使用$app->getModuleName(),因为其返回的是用户请求的模块名。 + * 另一个model可以通过loadModel()加载进来,与请求的模块名不一致。 + * * Get the module name of this model. Not the module user visiting. * * This method replace the 'ext' and 'model' string from the model class name, thus get the module name. - * Not useing $app->getModuleName() because it return the module user is visiting. But one module can be - * loaded by loadModel() so we must get the module name of thie model. - * + * Not using $app->getModuleName() because it return the module user is visiting. But one module can be + * loaded by loadModel() so we must get the module name of this model. + * * @access protected * @return string the module name. */ @@ -150,6 +183,7 @@ class model } /** + * 设置全局超级变量。 * Set the super vars. * * @access protected @@ -166,26 +200,35 @@ class model } /** - * Load the model of one module. After loaded, can use $this->modulename to visit the model object. + * 加载一个模块的model。加载完成后,使用$this->$moduleName来访问这个model对象。 + * 比如:loadModel('user')引入user模块的model实例对象,可以通过$this->user来访问它。 + * + * Load the model of one module. After loaded, can use $this->$moduleName to visit the model object. * * @param string $moduleName * @access public * @return object|bool the model object or false if model file not exists. */ - public function loadModel($moduleName) + public function loadModel($moduleName, $appName = '') { if(empty($moduleName)) return false; - $modelFile = helper::setModelFile($moduleName); + if(empty($appName)) $appName = $this->appName; + $modelFile = helper::setModelFile($moduleName, $appName); if(!helper::import($modelFile)) return false; - $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; - if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + $modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model'; + if(!class_exists($modelClass)) + { + $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model'; + if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true); + } - $this->$moduleName = new $modelClass(); + $this->$moduleName = new $modelClass($appName); return $this->$moduleName; } /** + * 加载model的class扩展。 * Load extension class of a model. Saved to $moduleName/ext/model/class/$extensionName.class.php. * * @param string $extensionName @@ -200,10 +243,12 @@ class model /* Set extenson name and extension file. */ $extensionName = strtolower($extensionName); $moduleName = $moduleName ? $moduleName : $this->getModuleName(); - $extensionFile = $this->app->getModuleExtPath($moduleName, 'model') . 'class/' . $extensionName . '.class.php'; + $moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model'); + if(!empty($moduleExtPath['site']))$extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php'; + if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php'; /* Try to import parent model file auto and then import the extension file. */ - if(!class_exists($moduleName . 'Model')) helper::import($this->app->getModulePath($moduleName) . 'model.php'); + if(!class_exists($moduleName . 'Model')) helper::import($this->app->getModulePath($this->appName, $moduleName) . 'model.php'); if(!helper::import($extensionFile)) return false; /* Set the extension class name. */ @@ -217,9 +262,8 @@ class model return $extensionObject; } - //-------------------- DAO related method s--------------------// - /** + * 加载DAO。 * Load DAO. * * @access private @@ -231,6 +275,7 @@ class model } /** + * 删除记录 * Delete one record. * * @param string $table the table name @@ -241,7 +286,7 @@ class model 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); + $object = ltrim(strstr(trim($table, '`'), '_'), '_'); $this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED); } -} +} \ No newline at end of file diff --git a/framework/router.class.php b/framework/router.class.php old mode 100755 new mode 100644 index 29d7b278f7..3926072079 --- a/framework/router.class.php +++ b/framework/router.class.php @@ -1,8 +1,9 @@ basePath/framework) * * @var string - * @access private + * @access public */ - private $frameRoot; + public $frameRoot; /** - * The root directory of the core library($this->basePath/lib) + * 应用类库的根目录($this->appRoot/lib)。 + * The root directory of the app library($this->appRoot/lib). * * @var string - * @access private + * @access public */ - private $coreLibRoot; + public $coreLibRoot; /** + * 应用程序的根目录。 * The root directory of the app. * * @var string - * @access private + * @access public */ - private $appRoot; + public $appRoot; /** + * 临时文件的根目录。 * The root directory of temp. * * @var string - * @access private + * @access public */ - private $tmpRoot; + public $tmpRoot; /** + * 缓存的根目录。 * The root directory of cache. * * @var string - * @access private + * @access public */ - private $cacheRoot; + public $cacheRoot; /** + *WWW目录 + * The root directory of www. + * + * @var string + * @access public + */ + public $wwwRoot; + + /** + * 附件存放目录 + * The root directory of data. + * + * @var string + * @access public + */ + public $dataRoot; + + /** + * 日志文件的根目录。 * The root directory of log. * * @var string - * @access private + * @access public */ - private $logRoot; + public $logRoot; /** + * 配置文件的根目录。 * The root directory of config. * * @var string - * @access private + * @access public */ - private $configRoot; + public $configRoot; /** + * 模块的根目录。 * The root directory of module. * * @var string - * @access private + * @access public */ - private $moduleRoot; + public $moduleRoot; /** + * 主题的根目录。 * The root directory of theme. * * @var string - * @access private + * @access public */ - private $themeRoot; + public $themeRoot; /** + * 用户使用的语言。 * The lang of the client user. * * @var string - * @access private + * @access public */ - private $clientLang; + public $clientLang; /** + * 用户使用的主题。 * The theme of the client user. * * @var string - * @access private + * @access public */ - private $clientTheme; + public $clientTheme; /** + * 当前模块的control对象。 * The control object of current module. * * @var object @@ -122,54 +156,61 @@ class router public $control; /** + * 模块名。 * The module name * * @var string - * @access private + * @access public */ - private $moduleName; + public $moduleName; /** + * 当前访问模块的control文件。 * The control file of the module current visiting. * * @var string - * @access private + * @access public */ - private $controlFile; + public $controlFile; /** + * 当前访问的方法名。 * The name of the method current visiting. * * @var string - * @access private + * @access public */ - private $methodName; + public $methodName; /** + * 当前方法的扩展文件。 * The action extension file of current method. * * @var string - * @access private + * @access public */ - private $extActionFile; + public $extActionFile; /** + * 访问的URI。 * The URI. * * @var string - * @access private + * @access public */ - private $URI; + public $URI; /** + * url地址传递的参数。 * The params passed in through url. * * @var array - * @access private + * @access public */ - private $params; + public $params; /** + * 视图类型。 * The view type. * * @var string @@ -178,6 +219,7 @@ class router public $viewType; /** + * 全局$config对象。 * The global $config object. * * @var object @@ -186,6 +228,7 @@ class router public $config; /** + * 全局$lang对象。 * The global $lang object. * * @var object @@ -194,22 +237,25 @@ class router public $lang; /** + * 全局$dbh对象,数据库连接句柄。 * The global $dbh object, the database connection handler. * * @var object - * @access private + * @access public */ public $dbh; /** + * 从数据库的句柄。 * The slave database handler. * * @var object - * @access private + * @access public */ public $slaveDBH; /** + * $post对象,用于访问$_POST变量。 * The $post object, used to access the $_POST var. * * @var ojbect @@ -218,6 +264,7 @@ class router public $post; /** + * $get对象,用于访问$_GET变量。 * The $get object, used to access the $_GET var. * * @var ojbect @@ -226,6 +273,7 @@ class router public $get; /** + * $session对象,用于访问$_SESSION变量。 * The $session object, used to access the $_SESSION var. * * @var ojbect @@ -234,6 +282,7 @@ class router public $session; /** + * $server对象,用于访问$_SERVER变量。 * The $server object, used to access the $_SERVER var. * * @var ojbect @@ -242,6 +291,7 @@ class router public $server; /** + * $cookie对象,用于访问$_COOKIE变量。 * The $cookie object, used to access the $_COOKIE var. * * @var ojbect @@ -250,6 +300,7 @@ class router public $cookie; /** + * $global对象,用于访问$_GLOBAL变量。 * The $global object, used to access the $_GLOBAL var. * * @var ojbect @@ -258,19 +309,49 @@ class router public $global; /** - * The construct function. + * 网站代号 + * The code of current site. * + * @var string + * @access public + */ + public $siteCode; + + /** + * 客户端设备类型 + * The device type of client. + * + * @var string + * @access public + */ + public $device; + + /** + * 应用名称 + * The appName. + * + * @var string + * @access public + */ + public $appName = ''; + + /** + * 构造方法, 设置路径,类,超级变量等。注意: + * 1.应该使用createApp()方法实例化router类; + * 2.如果$appRoot为空,框架会根据$appName计算应用路径。 + * + * The construct function. * Prepare all the paths, classes, super objects and so on. * Notice: * 1. You should use the createApp() method to get an instance of the router. - * 2. If the $appRoot is empty, the framework will comput the appRoot according the $appName + * 2. If the $appRoot is empty, the framework will compute the appRoot according the $appName * * @param string $appName the name of the app * @param string $appRoot the root path of the app - * @access protected + * @access public * @return void */ - protected function __construct($appName = 'demo', $appRoot = '') + public function __construct($appName = 'demo', $appRoot = '') { $this->setPathFix(); $this->setBasePath(); @@ -283,10 +364,13 @@ class router $this->setConfigRoot(); $this->setModuleRoot(); $this->setThemeRoot(); + $this->setWwwRoot(); + $this->setDataRoot(); - $this->loadConfig('common'); $this->filterSuperVars(); $this->setSuperVars(); + + $this->loadConfig('common'); $this->setDebug(); $this->setErrorHandler(); @@ -303,6 +387,7 @@ class router } /** + * 创建一个应用。 * Create an application. * * @@ -321,67 +406,97 @@ class router * @access public * @return object the app object */ - public static function createApp($appName = 'demo', $appRoot = '', $className = 'router') + public static function createApp($appName = 'demo', $appRoot = '', $className = '') { if(empty($className)) $className = __CLASS__; return new $className($appName, $appRoot); } - //-------------------- path related methods --------------------// + //-------------------- 路径相关方法(Path related methods)--------------------// /** - * Set the path directory. + * 设置应用名称 + * Set app name. * - * @access protected + * @param string $appName + * @access public * @return void */ - protected function setPathFix() + public function setAppName($appName) + { + $this->appName = $appName; + } + + /** + * 设置目录分隔符。 + * Set the path directory separator. + * + * @access public + * @return void + */ + public function setPathFix() { define('DS', DIRECTORY_SEPARATOR); } - + /** - * Set the base path. - * - * @access protected + * 设置设备类型 + * Set current device of visit website. + * + * @access public * @return void */ - protected function setBasePath() + public function setCurrentDevice() + { + $this->device = helper::getDevice(); + } + + /** + * 设置基础目录。 + * Set the base path. + * + * @access public + * @return void + */ + public function setBasePath() { $this->basePath = realpath(dirname(dirname(__FILE__))) . DS; } - + /** + * 设置框架根目录。 * Set the frame root. * - * @access protected + * @access public * @return void */ - protected function setFrameRoot() + public function setFrameRoot() { $this->frameRoot = $this->basePath . 'framework' . DS; } /** - * Set the core library root. + * 设置应用类库的根目录。 + * Set the app lib root. * - * @access protected + * @access public * @return void */ - protected function setCoreLibRoot() + public function setCoreLibRoot() { $this->coreLibRoot = $this->basePath . 'lib' . DS; } /** + * 设置应用的根目录。 * Set the app root. * * @param string $appName * @param string $appRoot - * @access protected + * @access public * @return void */ - protected function setAppRoot($appName = 'demo', $appRoot = '') + public function setAppRoot($appName = 'demo', $appRoot = '') { if(empty($appRoot)) { @@ -395,72 +510,101 @@ class router } /** + * 设置临时文件的根目录。 * Set the tmp root. * - * @access protected + * @access public * @return void */ - protected function setTmpRoot() + public function setTmpRoot() { - $this->tmpRoot = $this->appRoot . 'tmp' . DS; + $this->tmpRoot = $this->basePath . 'tmp' . DS; } /** + * 设置缓存的根目录。 * Set the cache root. * - * @access protected + * @access public * @return void */ - protected function setCacheRoot() + public function setCacheRoot() { $this->cacheRoot = $this->tmpRoot . 'cache' . DS; } /** + * 设置log的根目录。 * Set the log root. * - * @access protected + * @access public * @return void */ - protected function setLogRoot() + public function setLogRoot() { $this->logRoot = $this->tmpRoot . 'log' . DS; } /** + * 设置config配置文件的根目录。 * Set the config root. * - * @access protected + * @access public * @return void */ - protected function setConfigRoot() + public function setConfigRoot() { - $this->configRoot = $this->appRoot . 'config' . DS; + $this->configRoot = $this->basePath . 'config' . DS; } /** + * 设置模块的根目录。 * Set the module root. * - * @access protected + * @access public * @return void */ - protected function setModuleRoot() + public function setModuleRoot() { - $this->moduleRoot = $this->appRoot . 'module' . DS; + $this->moduleRoot = $this->basePath . 'module' . DS; } /** + * Set the www root. + * + * @access public + * @return void + */ + public function setWwwRoot() + { + $this->wwwRoot = rtrim(dirname($_SERVER['SCRIPT_FILENAME']), DS) . DS; + } + + /** + * Set the data root. + * + * @access public + * @return void + */ + public function setDataRoot() + { + $this->dataRoot = $this->wwwRoot . 'data' . DS; + } + + /** + * 设置主题根目录。 * Set the theme root. * - * @access protected + * @access public * @return void */ - protected function setThemeRoot() + public function setThemeRoot() { - $this->themeRoot = $this->appRoot . 'www' . DS . 'theme' . DS; + $this->themeRoot = $this->wwwRoot . 'theme' . DS; } /** + * 过滤超级变量数据 * Filter superVars. * * @access public @@ -503,14 +647,18 @@ class router } } } - unset($_GLOBALS); + $_POST = processArrayEvils($_POST); + $_GET = processArrayEvils($_GET); + $_COOKIE = processArrayEvils($_COOKIE); + unset($GLOBALS); unset($_REQUEST); } /** + * 设置超级变量。 * Set the super vars. * - * @access protected + * @access public * @return void */ public function setSuperVars() @@ -524,7 +672,27 @@ class router } /** - * set Debug + * 设置站点代号 + * Set the code of current site. + * + * www.xirang.com => xirang + * xirang.com => xirang + * xirang.com.cn => xirang + * xirang.cn => xirang + * xirang => xirang + * 192.168.1.1 => 192.168.1.1 + * + * @access public + * @return void + */ + public function setSiteCode() + { + return $this->siteCode = helper::getSiteCode($this->server->http_host); + } + + /** + * 设置Debug模式。 + * set Debug. * * @access public * @return void @@ -535,6 +703,7 @@ class router } /** + * 设置错误处理句柄。 * Set the error handler. * * @access public @@ -547,6 +716,7 @@ class router } /** + * 根据配置设置当前时区。 * Set the time zone according to the config. * * @access public @@ -558,7 +728,20 @@ class router } /** - * Get the $basePath var + * 获取应用名称 + * Get app name + * + * @access public + * @return string + */ + public function getAppName() + { + return $this->appName; + } + + /** + * 获取$basePath,即基础路径。 + * Get the $basePath var. * * @access public * @return string @@ -567,9 +750,10 @@ class router { return $this->basePath; } - + /** - * Get the $frameRoot var + * 获取$frameRoot,即框架根目录。 + * Get the $frameRoot var. * * @access public * @return string @@ -580,18 +764,8 @@ class router } /** - * Get the $coreLibRoot var - * - * @access public - * @return string - */ - public function getCoreLibRoot() - { - return $this->coreLibRoot; - } - - /** - * Get the $appRoot var + * 获取$appRoot变量,即应用的根目录。 + * Get the $appRoot var. * * @access public * @return string @@ -602,7 +776,32 @@ class router } /** - * Get the $tmpRoot var + * 获取$wwwRoot变量。 + * Get the $wwwRoot var + * + * @access public + * @return string + */ + public function getWwwRoot() + { + return $this->wwwRoot; + } + + /** + * 获取$coreLibRoot变量,即应用类库的根目录。 + * Get the $coreLibRoot var. + * + * @access public + * @return string + */ + public function getCoreLibRoot() + { + return $this->coreLibRoot; + } + + /** + * 获取$tmpRoot变量,即临时文件的根目录。 + * Get the $tmpRoot var. * * @access public * @return string @@ -613,7 +812,8 @@ class router } /** - * Get the $cacheRoot var + * 获取$cacheRoot变量,即缓存文件的根目录。 + * Get the $cacheRoot var. * * @access public * @return string @@ -624,7 +824,8 @@ class router } /** - * Get the $logRoot var + * 获取$logRoot变量,即日志文件的根目录。 + * Get the $logRoot var. * * @access public * @return string @@ -635,7 +836,8 @@ class router } /** - * Get the $configRoot var + * 获取$configRoot变量,即配置文件的根目录。 + * Get the $configRoot var. * * @access public * @return string @@ -646,18 +848,34 @@ class router } /** - * Get the $moduleRoot var + * 获取$moduleRoot变量,即应用模块的根目录。 + * Get the $moduleRoot var. + * + * @param string $appName + * @access public + * @return string + */ + public function getModuleRoot($appName = '') + { + if($appName == '') return $this->moduleRoot; + return dirname($this->moduleRoot) . DS . $appName . DS; + } + + /** + * 获取$dataRoot目录 + * Get the $dataRoot var * * @access public * @return string */ - public function getModuleRoot() + public function getDataRoot() { - return $this->moduleRoot; + return $this->dataRoot; } /** - * Get the $themeRoot var + * 获取$themeRoot变量,即主题的根目录。 + * Get the $themeRoot var. * * @access public * @return string @@ -667,12 +885,14 @@ class router return $this->themeRoot; } - //-------------------- Client environment related functions --------------------// + //------ 客户端环境有关的函数(Client environment related functions) ------// /** - * Set the language used by the client user. - * - * Using the order of method $lang param, session, cookie, browser and last the default lang. + * 根据用户浏览器的语言设置和服务器配置,选择显示的语言。 + * 优先级:$lang参数 > session > cookie > 浏览器 > 配置文件。 + * + * Set the language. + * Using the order of method $lang param, session, cookie, browser and the default lang. * * @param string $lang zh-cn|zh-tw|zh-hk|en * @access public @@ -721,6 +941,7 @@ class router } /** + * 获取$clientLang变量,即客户端的语言。 * Get the $clientLang var. * * @access public @@ -732,8 +953,10 @@ class router } /** - * Set the them client user using. The logic is same as the clientLang. + * 设置客户端使用的主题,判断逻辑与客户端的语言相同。 + * 主题的css和图片文件应该存放在www/theme/$themeName路径。 * + * Set the theme the client user using. The logic is same as the clientLang. * The css and images files of an theme should saved at www/theme/$themeName * * @param string $theme @@ -758,6 +981,7 @@ class router if(!empty($this->clientTheme)) { $this->clientTheme = strtolower($this->clientTheme); + if(!isset($this->config->themes[$this->clientTheme])) $this->clientTheme = $this->config->default->theme; } else { @@ -768,6 +992,7 @@ class router } /** + * 获取$clientTheme变量。 * Get the $clientTheme var. * * @access public @@ -779,6 +1004,7 @@ class router } /** + * 获取$webRoot,即应用的路径。 * Get the $webRoot var. * * @access public @@ -789,9 +1015,10 @@ class router return $this->config->webRoot; } - //-------------------- Request related methods. --------------------// + //-------------------- 请求相关的方法(Request related methods) --------------------// /** + * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。 * The entrance of parseing request. According to the requestType, call related methods. * * @access public @@ -799,7 +1026,13 @@ class router */ public function parseRequest() { - if($this->config->requestType == 'PATH_INFO') + if(isGetUrl()) + { + if($this->config->requestType == 'PATH_INFO2') define('FIX_PATH_INFO2', true); + $this->config->requestType = 'GET'; + } + + if($this->config->requestType == 'PATH_INFO' or $this->config->requestType == 'PATH_INFO2') { $this->parsePathInfo(); $this->setRouteByPathInfo(); @@ -816,6 +1049,7 @@ class router } /** + * PATH_INFO方式解析,获取$URI和$viewType。 * Parse PATH_INFO, get the $URI and $viewType. * * @access public @@ -823,8 +1057,8 @@ class router */ public function parsePathInfo() { - $pathInfo = $this->getPathInfo('PATH_INFO'); - if(empty($pathInfo)) $pathInfo = $this->getPathInfo('ORIG_PATH_INFO'); + $pathInfo = $this->getPathInfo(); + if(trim($pathInfo, '/') == trim($this->config->webRoot, '/')) $pathInfo = ''; if(!empty($pathInfo)) { $dotPos = strrpos($pathInfo, '.'); @@ -850,37 +1084,50 @@ class router } /** - * Get $PATH_INFO from $_SERVER or $_ENV by the pathinfo var name. - * - * Mostly, the var name of PATH_INFO is PATH_INFO, but may be ORIG_PATH_INFO. + * 从$_SERVER或者$_ENV全局变量根据pathinfo变量名获取$PATH_INFO值。 + * PATH_INFO的变量名几乎都是'PATH_INFO',但也有可能是ORIG_PATH_INFO。 * - * @param string $varName PATH_INFO, ORIG_PATH_INFO + * Get $PATH_INFO from $_SERVER or $_ENV by the pathinfo var name. + * Mostly, the var name of PATH_INFO is PATH_INFO, but may be ORIG_PATH_INFO. + * * @access public * @return string the PATH_INFO */ - public function getPathInfo($varName) + public function getPathInfo() { - $value = @getenv($varName); - if(isset($_SERVER[$varName])) $value = $_SERVER[$varName]; - if(($pos = strpos($value, '?')) !== false) $value = substr($value, 0, $pos); - return trim($value, '/'); + if(isset($_SERVER['PATH_INFO'])) + { + $value = $_SERVER['PATH_INFO']; + } + elseif(isset($_SERVER['ORIG_PATH_INFO'])) + { + $value = $_SERVER['ORIG_PATH_INFO']; + } + else + { + $value = @getenv('PATH_INFO'); + if(empty($value)) $value = @getenv('ORIG_PATH_INFO'); + if(strpos($value, $_SERVER['SCRIPT_NAME']) !== false) $value = str_replace($_SERVER['SCRIPT_NAME'], '', $value); + } + + if(strpos($value, '?') === false) return trim($value, '/'); + $value = parse_url($value); + return trim($value['path'], '/'); } /** + * GET请求方式解析,获取$URI和$viewType。 * Parse GET, get $URI and $viewType. - * - * @access private + * + * @access public * @return void */ - private function parseGET() + public function parseGET() { if(isset($_GET[$this->config->viewVar])) { $this->viewType = $_GET[$this->config->viewVar]; - if(strpos($this->config->views, ',' . $this->viewType . ',') === false) - { - $this->viewType = $this->config->default->view; - } + if(strpos($this->config->views, ',' . $this->viewType . ',') === false) $this->viewType = $this->config->default->view; } else { @@ -888,9 +1135,10 @@ class router } $this->URI = $_SERVER['REQUEST_URI']; } - + /** - * Get the $URL + * 获取$URL。 + * Get the $URL. * * @param bool $full true, the URI contains the webRoot, else only hte URI. * @access public @@ -907,6 +1155,7 @@ class router } /** + * 获取$vewType变量。 * Get the $viewType var. * * @access public @@ -917,14 +1166,20 @@ class router return $this->viewType; } - //-------------------- Routing related methods.--------------------// + //-------------------- 路由相关方法(Routing related methods) --------------------// /** + * 加载common模块。 + * + * common模块比较特别,它会执行几乎每次请求都需要执行的操作,例如: + * 打开session,检查权限等等。 + * 加载完$lang, $config, $dbh后,需要在入口文件(www/index.php)中手动调用该方法。 + * * Load the common module * * The common module is a special module, which can be used to do some common things. For examle: * start session, check priviledge and so on. - * This method should called manually in the router file(www/index.php) after the $lang, $config, $dbh loadde. + * This method should called manually in the router file(www/index.php) after the $lang, $config, $dbh loaded. * * @access public * @return object|bool the common control object or false if not exits. @@ -938,14 +1193,10 @@ class router helper::import($commonModelFile); if(class_exists('extcommonModel')) { - $commonClass = 'class common extends extcommonModel{}'; - eval($commonClass); return new extcommonModel(); } elseif(class_exists('commonModel')) { - $commonClass = 'class common extends commonModel{}'; - eval($commonClass); return new commonModel(); } else @@ -956,6 +1207,7 @@ class router } /** + * 设置要被调用的模块名。 * Set the name of the module to be called. * * @param string $moduleName the module name @@ -964,13 +1216,16 @@ class router */ public function setModuleName($moduleName = '') { - $this->moduleName = strtolower($moduleName); + if(!preg_match('/^[a-zA-Z0-9]+$/', $moduleName)) $this->triggerError("The modulename '$moduleName' illegal. ", __FILE__, __LINE__, $exit = true); + $this->moduleName = strip_tags(urldecode(strtolower($moduleName))); } /** + * 设置要被调用的控制器文件。 * Set the control file of the module to be called. * - * @param bool $exitIfNone If control file not foundde, how to do. True, die the whole app. false, log error. + * @param bool $exitIfNone 没有找到该控制器文件的情况:如果该参数为true,则终止程序;如果为false,则打印错误日志 + * If control file not foundde, how to do. True, die the whole app. false, log error. * @access public * @return bool */ @@ -984,8 +1239,9 @@ class router } return true; } - + /** + * 设置要被调用的方法名。 * Set the name of the method calling. * * @param string $methodName @@ -994,36 +1250,49 @@ class router */ public function setMethodName($methodName = '') { - $this->methodName = strtolower($methodName); + if(!preg_match('/^[a-zA-Z0-9]+$/', $methodName)) $this->triggerError("The methodname '$methodName' illegal. ", __FILE__, __LINE__, $exit = true); + $this->methodName = strip_tags(urldecode(strtolower($methodName))); } /** + * 获取一个模块的路径。 * Get the path of one module. * + * @param string $appName the app name * @param string $moduleName the module name * @access public * @return string the module path */ - public function getModulePath($moduleName = '') + public function getModulePath($appName = '', $moduleName = '') { if($moduleName == '') $moduleName = $this->moduleName; - return $this->getModuleRoot() . strtolower(trim($moduleName)) . DS; + if(!preg_match('/^[a-zA-Z0-9]+$/', $moduleName)) $this->triggerError("The modulename '$moduleName' illegal. ", __FILE__, __LINE__, $exit = true); + $modulePath = $this->getModuleRoot($appName) . strtolower(trim($moduleName)) . DS; + + return $modulePath; } /** + * 获取一个模块的扩展路径。 * Get extension path of one module. * + * @param string $appName the app name * @param string $moduleName the module name * @param string $ext the extension type, can be control|model|view|lang|config * @access public * @return string the extension path. */ - public function getModuleExtPath($moduleName, $ext) + public function getModuleExtPath($appName, $moduleName, $ext) { - return $this->getModuleRoot() . strtolower(trim($moduleName)) . DS . 'ext' . DS . $ext . DS; + if(!preg_match('/^[a-zA-Z0-9]+$/', $moduleName) or !preg_match('/^[a-zA-Z0-9]+$/', $ext)) $this->triggerError("The modulename '$moduleName' or ext '$ext' illegal. ", __FILE__, __LINE__, $exit = true); + $paths = array(); + $paths['common'] = $this->getModulePath($appName, $moduleName) . 'ext' . DS . $ext . DS; + $paths['site'] = empty($this->siteCode) ? '' : $this->getModulePath($appName, $moduleName) . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS; + return $paths; } /** + * 设置请求方法的扩展文件。 * Set the action extension file. * * @access public @@ -1031,14 +1300,22 @@ class router */ public function setActionExtFile() { - $moduleExtPath = $this->getModuleExtPath($this->moduleName, 'control'); - $this->extActionFile = $moduleExtPath . $this->methodName . '.php'; + $moduleExtPaths = $this->getModuleExtPath('', $this->moduleName, 'control'); + + $this->extActionFile = ''; + if($moduleExtPaths['site']) $this->extActionFile = $moduleExtPaths['site'] . $this->methodName . '.php'; + if(empty($this->extActionFile) or !file_exists($this->extActionFile)) $this->extActionFile = $moduleExtPaths['common'] . $this->methodName . '.php'; + return file_exists($this->extActionFile); } /** + * 设置路由(PATH_INFO 方式): + * 1.设置模块名; + * 2.设置方法名; + * 3.设置控制器文件。 + * * Set the route according to PATH_INFO. - * * 1. set the module name. * 2. set the method name. * 3. set the control file. @@ -1050,14 +1327,20 @@ class router { if(!empty($this->URI)) { - /* There's the request seperator, split the URI by it. */ + /* + * 根据$requestFix分割符,分割网址。 + * There's the request seperator, split the URI by it. + **/ if(strpos($this->URI, $this->config->requestFix) !== false) { $items = explode($this->config->requestFix, $this->URI); $this->setModuleName($items[0]); $this->setMethodName($items[1]); } - /* No reqeust seperator, use the default method name. */ + /* + * 如果网址中没有分隔符,使用默认的方法。 + * No reqeust seperator, use the default method name. + **/ else { $this->setModuleName($this->URI); @@ -1066,15 +1349,19 @@ class router } else { - $this->setModuleName($this->config->default->module); // use the default module. - $this->setMethodName($this->config->default->method); // use the default method. + $this->setModuleName($this->config->default->module); // 使用默认模块 use the default module. + $this->setMethodName($this->config->default->method); // 使用默认方法 use the default method. } $this->setControlFile(); } /** + * 设置路由(GET 方式): + * 1.设置模块名; + * 2.设置方法名; + * 3.设置控制器文件。 + * * Set the route according to GET. - * * 1. set the module name. * 2. set the method name. * 3. set the control file. @@ -1092,8 +1379,13 @@ class router } /** - * Load a module. + * 加载一个模块: + * 1. 引入控制器文件或扩展的方法文件; + * 2. 创建control对象; + * 3. 解析url,得到请求的参数; + * 4. 使用call_user_function_array调用相应的方法。 * + * Load a module. * 1. include the control file or the extension action file. * 2. create the control object. * 3. set the params passed in through url. @@ -1107,16 +1399,25 @@ class router $moduleName = $this->moduleName; $methodName = $this->methodName; - /* Include the contror file of the module. */ + /* + * 引入该模块的control文件。 + * Include the control file of the module. + **/ $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile; chdir(dirname($file2Included)); include $file2Included; - /* Set the class name of the control. */ + /* + * 设置control的类名。 + * Set the class name of the control. + **/ $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName; if(!class_exists($className)) $this->triggerError("the control $className not found", __FILE__, __LINE__, $exit = true); - /* Create a instance of the control. */ + /* + * 创建control类的实例。 + * Create a instance of the control. + **/ $module = new $className(); if(!method_exists($module, $methodName)) $this->triggerError("the module $moduleName has no $methodName method", __FILE__, __LINE__, $exit = true); $this->control = $module; @@ -1125,14 +1426,17 @@ class router $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php"); if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file; - /* Get the default setings of the method to be called useing the reflecting. */ + /* + * 使用反射机制获取函数参数的默认值。 + * Get the default settings of the method to be called using the reflecting. + * + * */ $defaultParams = array(); $methodReflect = new reflectionMethod($className, $methodName); - foreach($methodReflect->getParameters() as $param) { $name = $param->getName(); - + $default = '_NOT_SET'; if(isset($paramDefaultValue[$className][$methodName][$name])) { @@ -1146,23 +1450,27 @@ class router $defaultParams[$name] = $default; } - /* Set params according PATH_INFO or GET. */ - if($this->config->requestType == 'PATH_INFO') + /** + * 根据PATH_INFO或者GET方式设置请求的参数。 + * Set params according PATH_INFO or GET. + */ + if($this->config->requestType != 'GET') { $this->setParamsByPathInfo($defaultParams); } - elseif($this->config->requestType == 'GET') + else { $this->setParamsByGET($defaultParams); } - /* Call the method. */ - call_user_func_array(array(&$module, $methodName), $this->params); + /* 调用该方法 Call the method. */ + call_user_func_array(array($module, $methodName), $this->params); return $module; } /** - * Set the params by PATH_INFO + * 设置请求的参数(PATH_INFO 方式)。 + * Set the params by PATH_INFO. * * @param array $defaultParams the default settings of the params. * @access public @@ -1170,36 +1478,27 @@ class router */ public function setParamsByPathInfo($defaultParams = array()) { - /* Spit the URI. */ + /* 分割URI。 Spit the URI. */ $items = explode($this->config->requestFix, $this->URI); $itemCount = count($items); + $params = array(); - $params = array(); - /* The clean mode, only passed in values, no keys. */ - if($this->config->pathType == 'clean') + /** + * 前两项为模块名和方法名,参数从下标2开始。 + * The first two item is moduleName and methodName. So the params should begin at 2. + **/ + for($i = 2; $i < $itemCount; $i ++) { - /* The first two item is moduleName and methodName. So the params should begin at 2.*/ - for($i = 2; $i < $itemCount; $i ++) - { - $key = key($defaultParams); // Get key from the $defaultParams. - $params[$key] = $items[$i]; - next($defaultParams); - } - } - /* The full mode, both key and value passed in. */ - elseif($this->config->pathType == 'full') - { - for($i = 2; $i < $itemCount; $i += 2) - { - $key = $items[$i]; - $value = $items[$i + 1]; - $params[$key] = $value; - } + $key = key($defaultParams); // Get key from the $defaultParams. + $params[$key] = $items[$i]; + next($defaultParams); } + $this->params = $this->mergeParams($defaultParams, $params); } /** + * 设置请求的参数(GET 方式)。 * Set the params by GET. * * @param array $defaultParams the default settings of the params. @@ -1208,6 +1507,7 @@ class router */ public function setParamsByGET($defaultParams) { + /* Unset moduleVar, methodVar, viewVar and session 变量, 剩下的作为参数。 */ /* Unset the moduleVar, methodVar, viewVar and session var, all the left are the params. */ unset($_GET[$this->config->moduleVar]); unset($_GET[$this->config->methodVar]); @@ -1217,14 +1517,15 @@ class router } /** + * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。 * Merge the params passed in and the default params. Thus the params which have default values needn't pass value, just like a function. * * @param array $defaultParams the default params defined by the method. * @param array $passedParams the params passed in through url. - * @access private + * @access public * @return array the merged params. */ - private function mergeParams($defaultParams, $passedParams) + public function mergeParams($defaultParams, $passedParams) { /* Check params from URL. */ foreach($passedParams as $param => $value) @@ -1233,44 +1534,27 @@ class router if(preg_match('/[^a-zA-Z0-9=_,`+\/\.%\|\x7f-\xff]/', trim($value))) die('Bad Request!'); } - /* If not strict mode, the keys of passed params and default params must be the same order. */ - if(!isset($this->config->strictParams) or $this->config->strictParams == false) + unset($passedParams['onlybody']); + $passedParams = array_values($passedParams); + $i = 0; + foreach($defaultParams as $key => $defaultValue) { - unset($passedParams['onlybody']); - $passedParams = array_values($passedParams); - $i = 0; - foreach($defaultParams as $key => $defaultValue) + if(isset($passedParams[$i])) { - if(isset($passedParams[$i])) - { - $defaultParams[$key] = $passedParams[$i]; - } - else - { - if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true); - } - $i ++; + $defaultParams[$key] = strip_tags(urldecode($passedParams[$i])); } - } - /* If in strict mode, the keys of the passed params must be the same with the default params, but order can be different. */ - else - { - foreach($defaultParams as $key => $defaultValue) + else { - if(isset($passedParams[$key])) - { - $defaultParams[$key] = $passedParams[$key]; - } - else - { - if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true); - } + if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true); } + $i ++; } + return $defaultParams; } - + /** + * 获取$moduleName变量。 * Get the $moduleName var. * * @access public @@ -1282,6 +1566,7 @@ class router } /** + * 获取$controlFile变量。 * Get the $controlFile var. * * @access public @@ -1293,6 +1578,7 @@ class router } /** + * 获取$methodName变量。 * Get the $methodName var. * * @access public @@ -1304,6 +1590,7 @@ class router } /** + * 获取$param变量。 * Get the $param var. * * @access public @@ -1314,12 +1601,12 @@ class router return $this->params; } - //-------------------- Tool methods.------------------// - + //-------------------- 常用的工具方法(Tool methods) ------------------// + /** + * 从类库中加载一个类文件。 + * * Load a class file. - * - * Search in $coreLibRoot. * * @param string $className the class name * @param bool $static statis class or not @@ -1330,16 +1617,16 @@ class router { $className = strtolower($className); - /* Search in $coreLibRoot. */ + /* 搜索$coreLibRoot(Search in $coreLibRoot) */ $classFile = $this->coreLibRoot . $className; if(is_dir($classFile)) $classFile .= DS . $className; $classFile .= '.class.php'; if(!helper::import($classFile)) $this->triggerError("class file $classFile not found", __FILE__, __LINE__, $exit = true); - /* If staitc, return. */ + /* 如果是静态调用,则返回(If staitc, return) */ if($static) return true; - /* Instance it. */ + /* 实例化该类(Instance it) */ global $$className; if(!class_exists($className)) $this->triggerError("the class $className not found in $classFile", __FILE__, __LINE__, $exit = true); if(!is_object($$className)) $$className = new $className(); @@ -1347,16 +1634,19 @@ class router } /** + * 加载模块的config文件,返回全局$config对象。 + * 如果该模块是common,加载$configRoot的配置文件,其他模块则加载其模块的配置文件。 + * * Load config and return it as the global config object. - * * If the module is common, search in $configRoot, else in $modulePath. * * @param string $moduleName module name - * @param bool $exitIfNone exit or not + * @param string $appName app name + * @param bool $exitIfNone exit or not * @access public * @return object|bool the config object or false. */ - public function loadConfig($moduleName, $exitIfNone = true) + public function loadConfig($moduleName, $appName = '', $exitIfNone = true) { global $config; if(!is_object($config)) $config = new config(); @@ -1364,19 +1654,28 @@ class router $extConfigFiles = array(); - /* Set the main config file and extension config file. */ + /* + * 设置主配置文件和扩展配置文件。 + * Set the main config file and extension config file. + * */ if($moduleName == 'common') { $mainConfigFile = $this->configRoot . 'config.php'; + $myConfig = $this->configRoot . 'my.php'; + if(is_file($myConfig)) $extConfigFiles[] = $myConfig; } else { - $mainConfigFile = $this->getModulePath($moduleName) . 'config.php'; - $extConfigPath = $this->getModuleExtPath($moduleName, 'config'); - $extConfigFiles = helper::ls($extConfigPath, '.php'); + $mainConfigFile = $this->getModulePath($appName, $moduleName) . 'config.php'; + + /* Get config extension. */ + $extConfigPath = $this->getModuleExtPath($appName, $moduleName, 'config'); + $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php'); + $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php'); + $extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles); } - /* Set the files to include. */ + /* 设置引用的文件(Set the files to include) */ if(!is_file($mainConfigFile)) { if($exitIfNone) self::triggerError("config file $mainConfigFile not found", __FILE__, __LINE__, true); @@ -1387,7 +1686,7 @@ class router { $configFiles = array_merge(array($mainConfigFile), $extConfigFiles); } - + static $loadedConfigs = array(); foreach($configFiles as $configFile) { @@ -1396,31 +1695,37 @@ class router $loadedConfigs[] = $configFile; } - /* Merge from the db configs. */ - foreach(array('system', 'personal') as $type) + if($moduleName == 'common') { - if($moduleName != 'common' and isset($config->$type->$moduleName)) + $this->config = $config; + $this->setSiteCode(); + if(!isset($config->site)) $config->site = new stdclass(); + $config->site->code = $this->siteCode; + + if(!empty($config->multi)) { - foreach($config->$type->$moduleName as $item) - { - if($item->section) - { - if(!isset($config->{$moduleName}->{$item->section})) $config->{$moduleName}->{$item->section} = new stdclass(); - $config->{$moduleName}->{$item->section}->{$item->key} = $item->value; - } - else - { - if(!$item->section) $config->{$moduleName}->{$item->key} = $item->value; - } - } + $multiConfigFile = $this->configRoot . "multi.php"; + if(is_file($multiConfigFile)) include $multiConfigFile; + } + + if(empty($this->siteCode)) + { + $siteConfigFile = $this->configRoot . "sites/{$this->siteCode}.php"; + if(is_file($siteConfigFile)) include $siteConfigFile; } } + + /* Merge from the db configs. */ + if($moduleName != 'common' and isset($config->system->$moduleName)) helper::mergeConfig($config->system->$moduleName, $moduleName); + if($moduleName != 'common' and isset($config->personal->$moduleName)) helper::mergeConfig($config->personal->$moduleName, $moduleName); + $this->config = $config; return $config; } /** + * 向客户端输出配置参数,客户端可以根据这些参数实现和调整请求的逻辑。 * Export the config params to the client, thus the client can adjust it's logic according the config. * * @access public @@ -1431,7 +1736,6 @@ class router $view = new stdclass(); $view->version = $this->config->version; $view->requestType = $this->config->requestType; - $view->pathType = $this->config->pathType; $view->requestFix = $this->config->requestFix; $view->moduleVar = $this->config->moduleVar; $view->methodVar = $this->config->methodVar; @@ -1444,27 +1748,35 @@ class router $view->rand = $this->session->rand; $view->expiredTime = ini_get('session.gc_maxlifetime'); $view->serverTime = time(); + + $view->ip = gethostbyname($_SERVER['HTTP_HOST']); + $view->name = isset($this->config->socket->name) ? $this->config->socket->name : ''; + $view->port = isset($this->config->socket->port) ? $this->config->socket->port : ''; echo json_encode($view); } - + /** + * 加载语言文件,返回全局$lang对象。 * Load lang and return it as the global lang object. * * @param string $moduleName the module name + * @param string $appName the app name * @access public * @return bool|ojbect the lang object or false. */ - public function loadLang($moduleName) + public function loadLang($moduleName, $appName = '') { - $modulePath = $this->getModulePath($moduleName); + $modulePath = $this->getModulePath($appName, $moduleName); $mainLangFile = $modulePath . 'lang' . DS . $this->clientLang . '.php'; - $extLangPath = $this->getModuleExtPath($moduleName, 'lang'); - $extLangFiles = helper::ls($extLangPath . $this->clientLang, '.php'); + $extLangPath = $this->getModuleExtPath($appName, $moduleName, 'lang'); + $commonExtLangFiles = helper::ls($extLangPath['common'] . $this->clientLang, '.php'); + $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php'); + $extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles); - /* Set the files to includ. */ + /* 设置引用的文件(Set the files to include). */ if(!is_file($mainLangFile)) { - if(empty($extLangFiles)) return false; // also no extension file. + if(empty($extLangFiles)) return false; // 没有扩展文件,返回false(Return false if no extension file). $langFiles = $extLangFiles; } else @@ -1475,22 +1787,6 @@ class router global $lang; if(!is_object($lang)) $lang = new language(); - /* Set productCommon and projectCommon for flow. */ - if($moduleName == 'common') - { - $productProject = false; - if($this->dbh and !empty($this->config->db->name)) $productProject = $this->dbh->query('SELECT value FROM' . TABLE_CONFIG . "WHERE `owner`='system' AND `module`='custom' AND `key`='productproject'")->fetch(); - - $productCommon = $projectCommon = 0; - if($productProject) - { - $productProject = $productProject->value; - list($productCommon, $projectCommon) = explode('_', $productProject); - } - $lang->productCommon = isset($this->config->productCommonList[$this->clientLang][(int)$productCommon]) ? $this->config->productCommonList[$this->clientLang][(int)$productCommon] : $this->config->productCommonList['zh-cn'][0]; - $lang->projectCommon = isset($this->config->projectCommonList[$this->clientLang][(int)$projectCommon]) ? $this->config->projectCommonList[$this->clientLang][(int)$projectCommon] : $this->config->projectCommonList['zh-cn'][0]; - } - static $loadedLangs = array(); foreach($langFiles as $langFile) { @@ -1517,6 +1813,7 @@ class router } /** + * 连接数据库。 * Connect to database. * * @access public @@ -1532,13 +1829,14 @@ class router } /** + * 使用PDO连接数据库。 * Connect database by PDO. * * @param object $params the database params. - * @access private + * @access public * @return object|bool */ - private function connectByPDO($params) + public function connectByPDO($params) { if(!isset($params->driver)) self::triggerError('no pdo driver defined, it should be mysql or sqlite', __FILE__, __LINE__, $exit = true); if(!isset($params->user)) return false; @@ -1551,7 +1849,10 @@ class router $dbh = new PDO($dsn, $params->user, $params->password, array(PDO::ATTR_PERSISTENT => $params->persistant)); $dbh->exec("SET NAMES {$params->encoding}"); - /* If run on linux, set emulatePrepare and bufferQuery to true. */ + /* + * 如果系统是Linux,开启仿真预处理和缓冲查询。 + * If run on linux, set emulatePrepare and bufferQuery to true. + **/ if(!isset($params->emulatePrepare) and PHP_OS == 'Linux') $params->emulatePrepare = true; if(!isset($params->bufferQuery) and PHP_OS == 'Linux') $params->bufferQuery = true; @@ -1569,9 +1870,10 @@ class router } } - //-------------------- Error methods.------------------// - + //-------------------- 错误处理方法(Error methods) ------------------// + /** + * 程序停止时执行的函数。 * The shutdown handler. * * @access public @@ -1579,28 +1881,32 @@ class router */ public function shutdown() { - /* If debug on, save sql lines. */ + /* 如果debug模式开启,保存sql语句(If debug on, save sql queries) */ if(!empty($this->config->debug)) $this->saveSQL(); - /* If any error occers, save it. */ + /* + * 发现错误,保存到日志中。 + * If any error occers, save it. + * */ if(!function_exists('error_get_last')) return; $error = error_get_last(); if($error) $this->saveError($error['type'], $error['message'], $error['file'], $error['line']); } /** - * Trriger an error. + * 触发一个错误。 + * Trigger an error. * - * @param string $message error message - * @param string $file the file error occers - * @param int $line the line error occers - * @param bool $exit exit the program or not + * @param string $message 错误信息 error message + * @param string $file 所在文件 the file error occers + * @param int $line 错误行 the line error occers + * @param bool $exit 是否停止程序 exit the program or not * @access public * @return void */ public function triggerError($message, $file, $line, $exit = false) { - /* Set the error info. */ + /* 设置错误信息(Set the error info) */ $log = "ERROR: $message in $file on line $line"; if(isset($_SERVER['SCRIPT_URI'])) $log .= ", request: $_SERVER[SCRIPT_URI]";; $trace = debug_backtrace(); @@ -1608,11 +1914,12 @@ class router extract($trace[1]); $log .= ", last called by $file on line $line through function $function.\n"; - /* Trigger it. */ + /* 触发错误(Trigger the error) */ trigger_error($log, $exit ? E_USER_ERROR : E_USER_WARNING); } /** + * 保存错误信息。 * Save error info. * * @param int $level @@ -1624,27 +1931,41 @@ class router */ public function saveError($level, $message, $file, $line) { - /* Skip the error: Redefining already defined constructor. */ + if(empty($this->config->debug)) return true; + + /* + * 忽略该错误:Redefining already defined constructor。 + * Skip the error: Redefining already defined constructor. + **/ if(strpos($message, 'Redefining') !== false) return true; - /* Set the error info. */ + /* + * 设置错误信息。 + * Set the error info. + **/ $errorLog = "\n" . date('H:i:s') . " $message in $file on line $line "; $errorLog .= "when visiting " . $this->getURI() . "\n"; - /* If the ip is pulic, hidden the full path of scripts. */ - if(PHP_SAPI != 'cli' and !($this->server->server_addr == '127.0.0.1' or filter_var($this->server->server_addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false)) + /* + * 为了安全起见,对公网环境隐藏脚本路径。 + * If the ip is pulic, hidden the full path of scripts. + */ + if(!defined('IN_SHELL') and !($this->server->server_addr == '127.0.0.1' or filter_var($this->server->server_addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false)) { $errorLog = str_replace($this->getBasePath(), '', $errorLog); } - /* Save to log file. */ + /* 保存到日志文件(Save to log file) */ $errorFile = $this->getLogRoot() . 'php.' . date('Ymd') . '.log.php'; if(!is_file($errorFile)) file_put_contents($errorFile, "\n"); $fh = @fopen($errorFile, 'a'); if($fh) fwrite($fh, strip_tags($errorLog)) && fclose($fh); - /* If the debug > 1, show warning, notice error. */ + /* + * 如果debug > 1,显示warning, notice级别的错误。 + * If the debug > 1, show warning, notice error. + **/ if($level == E_NOTICE or $level == E_WARNING or $level == E_STRICT or $level == 8192) // 8192: E_DEPRECATED { if(!empty($this->config->debug) and $this->config->debug > 1) @@ -1656,7 +1977,10 @@ class router } } - /* If error level is serious, die. */ + /* + * 如果是严重错误,停止程序。 + * If error level is serious, die. + * */ if($level == E_ERROR or $level == E_PARSE or $level == E_CORE_ERROR or $level == E_COMPILE_ERROR or $level == E_USER_ERROR) { if(empty($this->config->debug)) die(); @@ -1669,13 +1993,15 @@ class router } /** + * 保存sql语句。 * Save the sql. * - * @access protected + * @access public * @return void */ public function saveSQL() { + if(!$this->config->debug) return true; if(!class_exists('dao')) return; $sqlLog = $this->getLogRoot() . 'sql.' . date('Ymd') . '.log.php'; @@ -1691,6 +2017,7 @@ class router } /** + * config类。 * The config class. * * @package framework @@ -1698,7 +2025,8 @@ class router class config { /** - * Set the value of a member. the member can be the foramt like db.user. + * 设置成员变量,成员可以是'db.user'类似的格式。 + * Set the value of a member. the member can be the format like db.user. * * * @@ -1731,7 +2061,8 @@ class language * $lang->set('version', '1.0); * ?> * - * @param string $key the key of the member, can be father.child + * @param string $key 成员的键名,可以是father.child的形式。 + * the key of the member, can be father.child * @param mixed $value the value * @access public * @return void @@ -1742,7 +2073,8 @@ class language } /** - * Show a member + * 显示一个成员的值。 + * Show a member. * * @param object $obj the object * @param string $key the key @@ -1752,11 +2084,12 @@ class language public function show($obj, $key) { $obj = (array)$obj; - if(isset($obj[$key])) echo $obj[$key]; else echo ''; + echo isset($obj[$key]) ? $obj[$key] : ''; } } /** + * 超级对象类,转化超级全局变量。 * The super object class. * * @package framework @@ -1764,6 +2097,7 @@ class language class super { /** + * 构造函数,设置超级变量名。 * Construct, set the var scope. * * @param string $scope the scope, can be server, post, get, cookie, session, global @@ -1776,6 +2110,7 @@ class super } /** + * 设置超级变量的成员值。 * Set one member value. * * @param string the key @@ -1811,16 +2146,17 @@ class super } elseif($this->scope == 'global') { - $GLOBAL[$key] = $value; + $GLOBALS[$key] = $value; } } /** + * 超级变量的魔术方法,比如用$post->key访问$_POST['key']。 * The magic get method. * * @param string $key the key * @access public - * @return mixed|bool return the value of the key or false. + * @return mixed|bool return the value of the key or false. */ public function __get($key) { @@ -1869,6 +2205,7 @@ class super } /** + * 打印变量的详细结构。 * Print the structure. * * @access public @@ -1882,6 +2219,6 @@ class super if($this->scope == 'cookie') a($_COOKIE); if($this->scope == 'session') a($_SESSION); if($this->scope == 'env') a($_ENV); - if($this->scope == 'global') a($GLOBAL); + if($this->scope == 'global') a($GLOBALS); } } diff --git a/lib/dao/dao.class.php b/lib/dao/dao.class.php old mode 100755 new mode 100644 index d64a971392..b676e8096a --- a/lib/dao/dao.class.php +++ b/lib/dao/dao.class.php @@ -1,18 +1,20 @@ table的别名。 * The alias of $this->table. * * @var string @@ -89,6 +99,7 @@ class dao public $alias; /** + * 查询的字段。 * The fields will be returned. * * @var string @@ -97,6 +108,7 @@ class dao public $fields; /** + * 查询模式,raw模式用于正常的select update等sql拼接操作,magic模式用于findByXXX等魔术方法。 * The query mode, raw or magic. * * This var is used to diff dao::from() with sql::from(). @@ -107,6 +119,7 @@ class dao public $mode; /** + * 执行方式:insert, select, update, delete, replace。 * The query method: insert, select, update, delete, replace. * * @var string @@ -115,6 +128,16 @@ class dao public $method; /** + * 是否自动增加lang条件。 + * If auto add lang statement. + * + * @var bool + * @access public + */ + public $autoLang; + + /** + * 需要修复表的错误代码 * The sql code of need repair table. * * @var string @@ -123,6 +146,7 @@ class dao public $repairCode = '|1034|1035|1194|1195|1459|'; /** + * 执行的请求,所有的查询都保存在该数组。 * The queries executed. Every query will be saved in this array. * * @var array @@ -131,6 +155,7 @@ class dao static public $querys = array(); /** + * 存放错误的数组。 * The errors. * * @var array @@ -139,6 +164,16 @@ class dao static public $errors = array(); /** + * 缓存。 + * The cache. + * + * @var array + * @access public + */ + static public $cache = array(); + + /** + * 构造方法。 * The construct method. * * @access public @@ -157,6 +192,7 @@ class dao } /** + * 设置$table属性。 * Set the $table property. * * @param string $table @@ -169,6 +205,7 @@ class dao } /** + * 设置$alias属性。 * Set the $alias property. * * @param string $alias @@ -181,6 +218,7 @@ class dao } /** + * 设置$fields属性。 * Set the $fields property. * * @param string $fields @@ -193,6 +231,21 @@ class dao } /** + * 设置autoLang项。 + * Set autoLang item. + * + * @param bool $autoLang + * @access public + * @return void + */ + public function setAutoLang($autoLang) + { + $this->autoLang = $autoLang; + return $this; + } + + /** + * 重置属性。 * Reset the vars. * * @access private @@ -205,11 +258,20 @@ class dao $this->setAlias(''); $this->setMode(''); $this->setMethod(''); + if(defined('LANG_CREATED') and LANG_CREATED == false) + { + $this->setAutoLang(false); + } + else + { + $this->setAutoLang(true); + } } - //-------------------- According to the query method, call according method of sql class. --------------------// + //-----根据请求的方式,调用sql类相应的方法(Call according method of sql class by query method. -----// /** + * 设置请求模式。像findByxxx之类的方法,使用的是magic模式;其他方法使用的是raw模式。 * Set the query mode. If the method if like findByxxx, the mode is magic. Else, the mode is raw. * * @param string $mode magic|raw @@ -222,6 +284,7 @@ class dao } /** + * 设置请求方法:select|update|insert|delete|replace 。 * Set the query method: select|update|insert|delete|replace * * @param string $method @@ -234,6 +297,43 @@ class dao } /** + * 开始事务。 + * Begin Transaction + * + * @access public + * @return void + */ + public function begin() + { + $this->dbh->beginTransaction(); + } + + /** + * 事务回滚。 + * Roll back + * + * @access public + * @return void + */ + public function rollBack() + { + $this->dbh->rollBack(); + } + + /** + * 提交事务。 + * Commits a transaction. + * + * @access public + * @return void + */ + public function commit() + { + $this->dbh->commit(); + } + + /** + * select方法,调用sql::select()。 * The select method, call sql::select(). * * @param string $fields @@ -249,28 +349,41 @@ class dao } /** + * 获取查询记录条数。 * The count method, call sql::select() and from(). * use as $this->dao->select()->from(TABLE_BUG)->where()->count(); * + * @param string $distinctField * @access public * @return void */ - public function count() + public function count($distinctField = '') { + /* 获得SELECT,FROM的位置,使用count(*)替换其字段。 */ /* Get the SELECT, FROM position, thus get the fields, replace it by count(*). */ - $sql = $this->processSQL(); - $sql = str_replace('SELECT', 'SELECT SQL_CALC_FOUND_ROWS ', $sql); + $sql = $this->get(); + $selectPOS = strpos($sql, 'SELECT') + strlen('SELECT'); + $fromPOS = strpos($sql, 'FROM'); + $fields = substr($sql, $selectPOS, $fromPOS - $selectPOS ); + $countField = $distinctField ? 'distinct ' . $distinctField : '*'; + $sql = str_replace($fields, " COUNT($countField) AS recTotal ", substr($sql, 0, $fromPOS)) . substr($sql, $fromPOS); - /* Remove the part after order and limit. */ + /* + * 去掉SQL语句中order和limit之后的部分。 + * Remove the part after order and limit. + **/ $subLength = strlen($sql); - $orderPOS = strripos($sql, DAO::ORDERBY); - $limitPOS = strripos($sql , DAO::LIMIT); + $orderPOS = strripos($sql, 'order by'); + $limitPOS = strripos($sql, 'limit'); if($limitPOS) $subLength = $limitPOS; if($orderPOS) $subLength = $orderPOS; $sql = substr($sql, 0, $subLength); self::$querys[] = $sql; - /* Get the records count. */ + /* + * 获取记录数。 + * Get the records count. + **/ try { $row = $this->dbh->query($sql)->fetch(PDO::FETCH_OBJ); @@ -280,14 +393,12 @@ class dao $this->sqlError($e); } - $sql = 'SELECT FOUND_ROWS() as recTotal;'; - $row = $this->dbh->query($sql)->fetch(); - return $row->recTotal; } /** - * The select method, call sql::update(). + * update方法,调用sql::update()。 + * The update method, call sql::update(). * * @param string $table * @access public @@ -303,6 +414,7 @@ class dao } /** + * delete方法,调用sql::delete()。 * The delete method, call sql::delete(). * * @access public @@ -317,6 +429,7 @@ class dao } /** + * insert方法,调用sql::insert()。 * The insert method, call sql::insert(). * * @param string $table @@ -333,6 +446,7 @@ class dao } /** + * replace方法,调用sql::replace()。 * The replace method, call sql::replace(). * * @param string $table @@ -349,6 +463,7 @@ class dao } /** + * 设置要操作的表。 * Set the from table. * * @param string $table @@ -363,6 +478,7 @@ class dao } /** + * 设置字段。 * Set the fields. * * @param string $fields @@ -376,6 +492,7 @@ class dao } /** + * 表别名,相当于sql里的AS。(as是php的关键词,使用alias代替) * Alias a table, equal the AS keyword. (Don't use AS, because it's a php keyword.) * * @param string $alias @@ -390,23 +507,30 @@ class dao } /** + * 设置需要更新或插入的数据。 * Set the data to update or insert. * - * @param object $data the data object or array - * @param object $skipFields the fields to skip. + * @param object $data the data object or array * @access public * @return object the dao object self. */ public function data($data, $skipFields = '') { if(!is_object($data)) $data = (object)$data; + if($this->autoLang and !isset($data->lang)) + { + $data->lang = $this->app->getClientLang(); + if(defined('RUN_MODE') and RUN_MODE == 'front' and !empty($this->app->config->cn2tw)) $data->lang = str_replace('zh-tw', 'zh-cn', $data->lang); + } + $this->sqlobj->data($data, $skipFields); return $this; } - //-------------------- The sql related method. --------------------// + //-------------------- sql相关的方法(The sql related method) --------------------// /** + * 获取sql字符串。 * Get the sql string. * * @access public @@ -418,6 +542,7 @@ class dao } /** + * 打印sql字符串。 * Print the sql string. * * @access public @@ -429,6 +554,7 @@ class dao } /** + * 查看SQL索引。 * Explain sql. * * @param string $sql @@ -443,6 +569,7 @@ class dao } /** + * 处理sql语句,替换表和字段。 * Process the sql, replace the table, fields. * * @access private @@ -452,7 +579,10 @@ class dao { $sql = $this->sqlobj->get(); - /* If the mode is magic, process the $fields and $table. */ + /** + * 如果是magic模式,处理表和字段。 + * If the mode is magic, process the $fields and $table. + **/ if($this->mode == 'magic') { if($this->fields == '') $this->fields = '*'; @@ -460,11 +590,54 @@ class dao $sql = sprintf($this->sqlobj->get(), $this->fields, $this->table); } + /* If the method if select, update or delete, set the lang condition. */ + if($this->autoLang and $this->table != '' and $this->method != 'insert' and $this->method != 'replace') + { + $lang = $this->app->getClientLang(); + + /* Get the position to insert lang = ?. */ + $wherePOS = strrpos($sql, DAO::WHERE); // The position of WHERE keyword. + $groupPOS = strrpos($sql, DAO::GROUPBY); // The position of GROUP BY keyword. + $havingPOS = strrpos($sql, DAO::HAVING); // The position of HAVING keyword. + $orderPOS = strrpos($sql, DAO::ORDERBY); // The position of ORDERBY keyword. + $limitPOS = strrpos($sql, DAO::LIMIT); // The position of LIMIT keyword. + $splitPOS = $orderPOS ? $orderPOS : $limitPOS; // If $orderPOS, use it instead of $limitPOS. + $splitPOS = $havingPOS? $havingPOS: $splitPOS; // If $havingPOS, use it instead of $orderPOS. + $splitPOS = $groupPOS ? $groupPOS : $splitPOS; // If $groupPOS, use it instead of $havingPOS. + + /* Set the conditon to be appened. */ + $tableName = !empty($this->alias) ? $this->alias : $this->table; + + if(!empty($this->app->config->cn2tw)) $lang = str_replace('zh-tw', 'zh-cn', $lang); + + $langCondition = " $tableName.lang in('{$lang}', 'all') "; + + /* If $spliPOS > 0, split the sql at $splitPOS. */ + if($splitPOS) + { + $firstPart = substr($sql, 0, $splitPOS); + $lastPart = substr($sql, $splitPOS); + if($wherePOS) + { + $sql = $firstPart . " AND $langCondition " . $lastPart; + } + else + { + $sql = $firstPart . " WHERE $langCondition " . $lastPart; + } + } + else + { + $sql .= $wherePOS ? " AND $langCondition" : " WHERE $langCondition"; + } + } + self::$querys[] = $this->processKeywords($sql); return $sql; } /** + * 替换sql常量关键字。 * Process the sql keywords, replace the constants to normal. * * @param string $sql @@ -476,9 +649,10 @@ class dao return str_replace(array(DAO::WHERE, DAO::GROUPBY, DAO::HAVING, DAO::ORDERBY, DAO::LIMIT), array('WHERE', 'GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT'), $sql); } - //-------------------- Query related methods. --------------------// - + //-------------------- 查询相关方法(Query related methods) --------------------// + /** + * 设置$dbh,数据库连接句柄。 * Set the dbh. * * You can use like this: $this->dao->dbh($dbh), thus you can handle two database. @@ -494,18 +668,21 @@ class dao } /** + * 执行SQL语句,返回PDOStatement结果集。 * Query the sql, return the statement object. * - * @param string $sql * @access public * @return object the PDOStatement object. */ public function query($sql = '') { - if(!empty(dao::$errors)) return new PDOStatement(); // If any error, return an empty statement object to make sure the remain method to execute. + /* 如果有错误,返回一个空的PDOStatement对象,确保后续方法能够执行。*/ + /* If any error, return an empty statement object to make sure the remain method to execute. */ + if(!empty(dao::$errors)) return new PDOStatement(); if($sql) $this->sqlobj->sql = $sql; $sql = $this->processSQL(); + $key = md5($sql); try { @@ -514,10 +691,21 @@ class dao if($this->slaveDBH and $method == 'select') { - return $this->slaveDBH->query($sql); + if(isset(dao::$cache[$key])) return dao::$cache[$key]; + $result = $this->slaveDBH->query($sql); + dao::$cache[$key] = $result; + return $result; } else { + if($this->method == 'select') + { + if(isset(dao::$cache[$key])) return dao::$cache[$key]; + $result = $this->slaveDBH->query($sql); + dao::$cache[$key] = $result; + return $result; + } + return $this->dbh->query($sql); } } @@ -528,6 +716,7 @@ class dao } /** + * 将记录进行分页,自动设置limit语句。 * Page the records, set the limit part auto. * * @param object $pager @@ -538,37 +727,14 @@ class dao { if(!is_object($pager)) return $this; - /* If the record total is 0, compute it. */ + /* + * 如果$pager的总记录为0,需要计算总结果数。 + * If the record total is 0, compute it. + **/ if($pager->recTotal == 0) { - /* Get the SELECT, FROM position, thus get the fields, replace it by count(*). */ - $sql = $this->get(); - $selectPOS = strpos($sql, 'SELECT') + strlen('SELECT'); - $fromPOS = strpos($sql, 'FROM'); - $fields = substr($sql, $selectPOS, $fromPOS - $selectPOS ); - $countField = $distinctField ? 'distinct ' . $distinctField : '*'; - $sql = str_replace($fields, " COUNT($countField) AS recTotal ", $sql); - - /* Remove the part after order and limit. */ - $subLength = strlen($sql); - $orderPOS = strripos($sql, 'order by'); - $limitPOS = strripos($sql, 'limit'); - if($limitPOS) $subLength = $limitPOS; - if($orderPOS) $subLength = $orderPOS; - $sql = substr($sql, 0, $subLength); - self::$querys[] = $sql; - - /* Get the records count. */ - try - { - $row = $this->dbh->query($sql)->fetch(PDO::FETCH_OBJ); - } - catch (PDOException $e) - { - $this->sqlError($e); - } - - $pager->setRecTotal($row->recTotal); + $recTotal = $this->count($distinctField); + $pager->setRecTotal($recTotal); $pager->setPageTotal(); } $this->sqlobj->limit($pager->limit()); @@ -576,11 +742,12 @@ class dao } /** + * 执行SQL。query()会返回stmt对象,该方法只返回更改或删除的记录数。 * Execute the sql. It's different with query(), which return the stmt object. But this not. * * @param string $sql * @access public - * @return int the modified or deleted records. + * @return int the modified or deleted records. 更改或删除的记录数。 */ public function exec($sql = '') { @@ -600,12 +767,14 @@ class dao } } - //-------------------- Fetch related methods. -------------------// + //-------------------- Fetch相关方法(Fetch related methods) -------------------// /** + * 获取一个记录。 * Fetch one record. * - * @param string $field if the field is set, only return the value of this field, else return this record + * @param string $field 如果已经设置获取的字段,则只返回这个字段的值,否则返回这个记录。 + * if the field is set, only return the value of this field, else return this record * @access public * @return object|mixed */ @@ -618,9 +787,11 @@ class dao } /** + * 获取所有记录。 * Fetch all records. * - * @param string $keyField the key field, thus the return records is keyed by this field + * @param string $keyField 返回以该字段做键的记录 + * the key field, thus the return records is keyed by this field * @access public * @return array the records */ @@ -634,10 +805,11 @@ class dao } /** + * 获取所有记录并将按照字段分组。 * Fetch all records and group them by one field. * - * @param string $groupField the field to group by - * @param string $keyField the field of key + * @param string $groupField 分组的字段 the field to group by + * @param string $keyField 键字段 the field of key * @access public * @return array the records. */ @@ -653,8 +825,10 @@ class dao } /** + * 获取的记录是以关联数组的形式 * Fetch array like key=>value. * + * 如果没有设置参数,用首末两键作为参数。 * If the keyFiled and valueField not set, use the first and last in the record. * * @param string $keyField @@ -664,6 +838,9 @@ class dao */ public function fetchPairs($keyField = '', $valueField = '') { + $keyField = trim($keyField, '`'); + $valueField = trim($valueField, '`'); + $pairs = array(); $ready = false; $stmt = $this->query(); @@ -686,6 +863,7 @@ class dao } /** + * 返回最后插入的ID。 * Return the last insert ID. * * @access public @@ -696,9 +874,10 @@ class dao return $this->dbh->lastInsertID(); } - //-------------------- Magic methods.--------------------// + //-------------------- 魔术方法(Magic methods) --------------------// /** + * 解析dao的方法名,处理魔术方法。 * Use it to do some convenient queries. * * @param string $funcName the function name to be called @@ -710,7 +889,10 @@ class dao { $funcName = strtolower($funcName); - /* findByxxx, xxx as will be in the where. */ + /* + * 如果是findByxxx,转换为where条件语句。 + * findByxxx, xxx as will be in the where. + **/ if(strpos($funcName, 'findby') !== false) { $this->setMode('magic'); @@ -728,7 +910,10 @@ class dao $this->sqlobj = sql::select('%s')->from('%s')->where($field, $operator, $value); return $this; } - /* Fetch10. */ + /* + * 获取指定个数的记录:fetch10 获取10条记录。 + * Fetch10. + **/ elseif(strpos($funcName, 'fetch') !== false) { $max = str_replace('fetch', '', $funcName); @@ -745,10 +930,16 @@ class dao } return $rows; } - /* Others, call the method in sql class. */ + /* + * 其他的方法,转到sqlobj对象执行。 + * Others, call the method in sql class. + **/ else { - /* Create the max counts of sql class methods, and then create $arg0, $arg1... */ + /* + * 使用$arg0, $arg1... 生成调用的参数。 + * Create the max counts of sql class methods, and then create $arg0, $arg1... + **/ for($i = 0; $i < SQL::MAX_ARGS; $i ++) { ${"arg$i"} = isset($funcArgs[$i]) ? $funcArgs[$i] : null; @@ -758,37 +949,58 @@ class dao } } - //-------------------- Checking.--------------------// - + //-------------------- 条件检查( Data Checking)--------------------// + /** + * 检查字段是否满足条件。 * Check a filed is satisfied with the check rule. * * @param string $fieldName the field to check * @param string $funcName the check rule + * @param string $condition the condition * @access public * @return object the dao object self. */ - public function check($fieldName, $funcName) + public function check($fieldName, $funcName, $condition = '') { - /* If no this field in the data, reuturn. */ - if(!isset($this->sqlobj->data->$fieldName)) return $this; + /* + * 如果没数据中没有该字段,直接返回。 + * If no this field in the data, return. + **/ + if(!isset($this->sqlobj->data->$fieldName) && $funcName != 'notempty') return $this; + /* 设置字段值。 */ /* Set the field label and value. */ global $lang, $config, $app; - $table = strtolower(str_replace(array($config->db->prefix, '`'), '', $this->table)); + if(isset($config->db->prefix)) + { + $table = strtolower(str_replace(array($config->db->prefix, '`'), '', $this->table)); + } + elseif(strpos($this->table, '_') !== false) + { + $table = strtolower(substr($this->table, strpos($this->table, '_') + 1)); + $table = str_replace('`', '', $table); + } + else + { + $table = strtolower($this->table); + } $fieldLabel = isset($lang->$table->$fieldName) ? $lang->$table->$fieldName : $fieldName; - $value = $this->sqlobj->data->$fieldName; - - /* Check unique. */ + $value = isset($this->sqlobj->data->$fieldName) ? $this->sqlobj->data->$fieldName : null; + + /* + * 检查唯一性。 + * Check unique. + **/ if($funcName == 'unique') { $args = func_get_args(); $sql = "SELECT COUNT(*) AS count FROM $this->table WHERE `$fieldName` = " . $this->sqlobj->quote($value); - if(isset($args[2])) $sql .= ' AND ' . $args[2]; + if($condition) $sql .= ' AND ' . $condition; try { - $row = $this->dbh->query($sql)->fetch(); - if($row->count != 0) $this->logError($funcName, $fieldName, $fieldLabel, array($value)); + $row = $this->dbh->query($sql)->fetch(); + if($row->count != 0) $this->logError($funcName, $fieldName, $fieldLabel, array($value)); } catch (PDOException $e) { @@ -797,7 +1009,10 @@ class dao } else { - /* Create the params. */ + /* + * 创建参数。 + * Create the params. + **/ $funcArgs = func_get_args(); unset($funcArgs[0]); unset($funcArgs[1]); @@ -817,6 +1032,7 @@ class dao } /** + * 检查一个字段是否满足条件。 * Check a field, if satisfied with the condition. * * @param string $condition @@ -838,6 +1054,7 @@ class dao } /** + * 批量检查字段。 * Batch check some fileds. * * @param string $fields the fields to check, join with , @@ -858,6 +1075,7 @@ class dao } /** + * 批量检查字段是否满足条件。 * Batch check fields on the condition is true. * * @param string $condition @@ -880,6 +1098,7 @@ class dao } /** + * 根据数据库结构检查字段。 * Check the fields according the the database schema. * * @param string $skipFields fields to skip checking @@ -908,8 +1127,10 @@ class dao } /** + * 记录错误到日志。 * Log the error. * + * module/common/lang中定义了错误提示信息。 * For the error notice, see module/common/lang. * * @param string $checkType the check rule @@ -925,7 +1146,10 @@ class dao $error = $lang->error->$checkType; $replaces = array_merge(array($fieldLabel), $funcArgs); // the replace values. - /* Just a string, cycle the $replaces. */ + /* + * 如果$error错误信息是一个字符串,进行替换。 + * Just a string, cycle the $replaces. + **/ if(!is_array($error)) { foreach($replaces as $replace) @@ -935,10 +1159,16 @@ class dao $error = substr($error, 0, $pos) . $replace . substr($error, $pos + 2); } } - /* If the error define is an array, select the one which %s counts match the $replaces. */ + /* + * 如果error错误信息是一个数组,选择一个%s满足替换个数的进行替换。 + * If the error define is an array, select the one which %s counts match the $replaces. + **/ else { - /* Remove the empty items. */ + /* + * 去掉空值项。 + * Remove the empty items. + **/ foreach($replaces as $key => $value) if(is_null($value)) unset($replaces[$key]); $replacesCount = count($replaces); foreach($error as $errorString) @@ -953,6 +1183,7 @@ class dao } /** + * 判断是否有错误。 * Judge any error or not. * * @access public @@ -964,16 +1195,16 @@ class dao } /** + * 获取错误。 * Get the errors. * - * @param boolean $join * @access public * @return array */ public static function getError($join = false) { $errors = dao::$errors; - dao::$errors = array(); // Must clear it. + dao::$errors = array(); // 清除dao的错误信息(Must clear errors) if(!$join) return $errors; @@ -989,6 +1220,7 @@ class dao } /** + * 获取表的字段类型。 * Get the defination of fields of the table. * * @access private @@ -1017,8 +1249,8 @@ class dao if($type == 'enum' or $type == 'set') { - $rangeBegin = $firstPOS + 2; // Remove the first quote. - $rangeEnd = strrpos($rawField->type, ')') - 1; // Remove the last quote. + $rangeBegin = $firstPOS + 2; // 移除开始的引用符 Remove the first quote. + $rangeEnd = strrpos($rawField->type, ')') - 1; // 移除结束的引用符 Remove the last quote. $range = substr($rawField->type, $rangeBegin, $rangeEnd - $rangeBegin); $field['rule'] = 'reg'; $field['options']['reg'] = '/' . str_replace("','", '|', $range) . '/'; @@ -1068,6 +1300,8 @@ class dao $message = $exception->getMessage(); if(strpos($this->repairCode, "|$errorCode|") !== false or ($errorCode == '1016' and strpos($errorMsg, 'errno: 145') !== false)) { + global $config; + if(isset($config->framework->autoRepairTable) and $config->framework->autoRepairTable) die(js::locate(helper::createLink('misc', 'checkTable'))); $message .= ' ' . $this->lang->repairTable; } $sql = $this->sqlobj->get(); @@ -1076,6 +1310,7 @@ class dao } /** + * SQL类。 * The SQL class. * * @package framework @@ -1083,12 +1318,14 @@ class dao class sql { /** + * 所有方法的最大参数个数。 * The max count of params of all methods. * */ const MAX_ARGS = 3; /** + * SQL字符串。 * The sql string. * * @var string @@ -1097,6 +1334,7 @@ class sql public $sql = ''; /** + * 全局变量$dbh。 * The global $dbh. * * @var object @@ -1105,6 +1343,7 @@ class sql protected $dbh; /** + * 更新或插入日期。 * The data to update or insert. * * @var mix @@ -1113,7 +1352,8 @@ class sql public $data; /** - * Is the first time to call set. + * 是否是第一次设置。 + * Is the first time to call set. * * @var bool * @access private; @@ -1121,6 +1361,7 @@ class sql private $isFirstSet = true; /** + * 是否是在条件语句中。 * If in the logic of judge condition or not. * * @var bool @@ -1129,6 +1370,7 @@ class sql private $inCondition = false; /** + * 条件是否为真。 * The condition is true or not. * * @var bool @@ -1137,17 +1379,28 @@ class sql private $conditionIsTrue = false; /** + * WHERE条件嵌套小括号标记。 + * If in mark or not. + * + * @var bool + * @access private; + */ + private $inMark = false; + + + /** + * 是否开启特殊字符转义。 * Magic quote or not. * * @var bool * @access public */ - public $magicQuote; + public $magicQuote; /** - * The construct function. user factory() to instance it. + * 构造方法。 + * The construct function. * - * @param string $table * @access private * @return void */ @@ -1155,10 +1408,11 @@ class sql { global $dbh; $this->dbh = $dbh; - $this->magicQuote = get_magic_quotes_gpc(); + $this->magicQuote = (version_compare(phpversion(), '5.4', '<') and function_exists('get_magic_quotes_gpc') and get_magic_quotes_gpc()); } /** + * 工厂方法。 * The factory method. * * @param string $table @@ -1171,6 +1425,7 @@ class sql } /** + * select语句。 * The sql is select. * * @param string $field @@ -1185,6 +1440,7 @@ class sql } /** + * update语句。 * The sql is update. * * @param string $table @@ -1199,6 +1455,7 @@ class sql } /** + * insert语句。 * The sql is insert. * * @param string $table @@ -1213,6 +1470,7 @@ class sql } /** + * replace语句。 * The sql is replace. * * @param string $table @@ -1227,6 +1485,7 @@ class sql } /** + * delete语句。 * The sql is delete. * * @access public @@ -1240,6 +1499,7 @@ class sql } /** + * 将关联数组转换为sql语句中 `key` = value 的形式。 * Join the data items by key = value. * * @param object $data @@ -1269,7 +1529,8 @@ class sql } /** - * Aadd an '(' at left. + * 在左边添加'('。 + * Add an '(' at left. * * @param int $count * @access public @@ -1279,11 +1540,13 @@ class sql { if($this->inCondition and !$this->conditionIsTrue) return $this; $this->sql .= str_repeat('(', $count); + $this->inMark = true; return $this; } /** - * Add an ')' ad right. + * 在右边增加')'。 + * Add an ')' at right. * * @param int $count * @access public @@ -1293,10 +1556,12 @@ class sql { if($this->inCondition and !$this->conditionIsTrue) return $this; $this->sql .= str_repeat(')', $count); + $this->inMark = false; return $this; } /** + * SET部分。 * The set part. * * @param string $set @@ -1305,19 +1570,20 @@ class sql */ public function set($set) { - if($this->isFirstSet) + /* Add ` to avoid keywords of mysql. */ + if(strpos($set, '=') ===false) { - $this->sql .= " $set "; - $this->isFirstSet = false; - } - else - { - $this->sql .= ", $set"; + $set = str_replace(',', '', $set); + $set = '`' . str_replace('`', '', $set) . '`'; } + + $this->sql .= $this->isFirstSet ? " $set" : ", $set"; + if($this->isFirstSet) $this->isFirstSet = false; return $this; } /** + * 创建From部分。 * Create the from part. * * @param string $table @@ -1331,6 +1597,7 @@ class sql } /** + * 创建Alias部分,Alias转为AS。 * Create the Alias part. * * @param string $alias @@ -1344,6 +1611,7 @@ class sql } /** + * 创建LEFT JOIN部分。 * Create the left join part. * * @param string $table @@ -1357,6 +1625,7 @@ class sql } /** + * 创建ON部分。 * Create the on part. * * @param string $condition @@ -1370,6 +1639,7 @@ class sql } /** + * 开始条件判断。 * Begin condition judge. * * @param bool $condition @@ -1384,6 +1654,7 @@ class sql } /** + * 结束条件判断。 * End the condition judge. * * @access public @@ -1397,6 +1668,7 @@ class sql } /** + * 创建WHERE部分。 * Create the where part. * * @param string $arg1 the field name @@ -1418,25 +1690,29 @@ class sql $condition = $arg1; } - $this->sql .= ' ' . DAO::WHERE ." $condition "; + if(!$this->inMark) $this->sql .= ' ' . DAO::WHERE ." $condition "; + if($this->inMark) $this->sql .= " $condition "; return $this; } /** + * 创建AND部分。 * Create the AND part. * * @param string $condition * @access public * @return object the sql object. */ - public function andWhere($condition) + public function andWhere($condition, $addMark = false) { if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= " AND $condition "; + $mark = $addMark ? '(' : ''; + $this->sql .= " AND {$mark} $condition "; return $this; } /** + * 创建OR部分。 * Create the OR part. * * @param bool $condition @@ -1451,6 +1727,7 @@ class sql } /** + * 创建'='部分。 * Create the '='. * * @param string $value @@ -1465,6 +1742,7 @@ class sql } /** + * 创建'!='。 * Create '!='. * * @param string $value @@ -1479,6 +1757,7 @@ class sql } /** + * 创建'>'。 * Create '>'. * * @param string $value @@ -1493,6 +1772,7 @@ class sql } /** + * 创建'>=' * Create '>='. * * @param string $value @@ -1507,6 +1787,7 @@ class sql } /** + * 创建'<'。 * Create '<'. * * @param mixed $value @@ -1521,6 +1802,7 @@ class sql } /** + * 创建 '<='。 * Create '<='. * * @param mixed $value @@ -1535,6 +1817,7 @@ class sql } /** + * 创建"between and"。 * Create "between and" * * @param string $min @@ -1552,9 +1835,10 @@ class sql } /** + * 创建IN部分。 * Create in part. * - * @param string|array $ids list string by ',' or an array + * @param string|array $ids ','分割的字符串或者数组 list string by ',' or an array * @access public * @return object the sql object. */ @@ -1566,6 +1850,7 @@ class sql } /** + * 创建'NOT IN'部分。 * Create not in part. * * @param string|array $ids list string by ',' or an array @@ -1580,6 +1865,7 @@ class sql } /** + * 创建LIKE部分。 * Create the like by part. * * @param string $string @@ -1594,6 +1880,7 @@ class sql } /** + * 创建NOT LIKE部分。 * Create the not like by part. * * @param string $string @@ -1608,20 +1895,7 @@ class sql } /** - * Create the find_in_set by part. - * - * @param int $str - * @param int $strList - * @access public - * @return object the sql object. - */ - public function findInSet($str, $strList) - { - if($this->inCondition and !$this->conditionIsTrue) return $this; - $this->sql .= "FIND_IN_SET(" . $str . "," . $strList . ")"; - } - - /** + * 创建ORDER BY部分。 * Create the order by part. * * @param string $order @@ -1630,9 +1904,7 @@ class sql */ public function orderBy($order) { - if($this->inCondition and !$this->conditionIsTrue) return $this; - - $order = str_replace(array('|', '', '_'), ' ', $order); + $order = str_replace(array('|', '', '_'), ' ', $order); /* Add "`" in order string. */ /* When order has limit string. */ @@ -1652,7 +1924,8 @@ class sql /* such as t1.id field. */ if(strpos($value, '.') !== false) list($table, $field) = explode('.', $field); - $field = "`$field`"; + /* Ignore order with function e.g. order by length(tag) asc. */ + if(strpos($field, '(') === false) $field = "`$field`"; $orderParse[$key] = isset($table) ? $table . '.' . $field : $field; unset($table); @@ -1666,6 +1939,7 @@ class sql } /** + * 创建LIMIT部分。 * Create the limit part. * * @param string $limit @@ -1680,6 +1954,7 @@ class sql } /** + * 创建GROUP BY部分。 * Create the groupby part. * * @param string $groupBy @@ -1693,6 +1968,7 @@ class sql } /** + * 创建HAVING部分。 * Create the having part. * * @param string $having @@ -1706,6 +1982,7 @@ class sql } /** + * 获取SQL字符串。 * Get the sql string. * * @access public @@ -1717,7 +1994,8 @@ class sql } /** - * Uuote a var. + * 对字段加转义。 + * Quote a var. * * @param mixed $value * @access public @@ -1726,6 +2004,6 @@ class sql public function quote($value) { if($this->magicQuote) $value = stripslashes($value); - return $this->dbh->quote($value); + return $this->dbh->quote((string)$value); } } diff --git a/lib/filter/filter.class.php b/lib/filter/filter.class.php old mode 100755 new mode 100644 index 4f1dfda05c..d6b5128b55 --- a/lib/filter/filter.class.php +++ b/lib/filter/filter.class.php @@ -1,28 +1,32 @@ array('min_range' => $args[1], 'max_range' => $args[2])); @@ -70,6 +76,21 @@ class validater } /** + * 检查不是Int类型。 + * Not int checking. + * + * @param int $var + * @static + * @access public + * @return bool + */ + public static function checkNotInt($var) + { + return !self::checkInt($var); + } + + /** + * 检查Float类型。 * Float checking. * * @param float $var @@ -80,10 +101,11 @@ class validater */ public static function checkFloat($var, $decimal = '.') { - return filter_var($var, FILTER_VALIDATE_FLOAT, array('options' => array('decimail' => $decimal))); + return filter_var($var, FILTER_VALIDATE_FLOAT, array('options' => array('decimal' => $decimal))); } /** + * 检查Email。 * Email checking. * * @param string $var @@ -97,8 +119,52 @@ class validater } /** - * URL checking. + * 检查电话或手机号码 + * Check phone number. + * + * @param string $var + * @static + * @access public + * @return void + */ + public static function checkPhone($var) + { + return (validater::checkTel($var) or validater::checkMobile($var)); + } + + /** + * 检查电话号码 + * Check tel number. + * + * @param int $var + * @static + * @access public + * @return void + */ + public static function checkTel($var) + { + return preg_match("/^([0-9]{3,4}-)?[0-9]{7,8}$/", $var); + } + + /** + * 检查手机号码 + * Check mobile number. + * + * @param string $var + * @static + * @access public + * @return void + */ + public static function checkMobile($var) + { + return preg_match("/^1[3-5,8]{1}[0-9]{9}$/", $var); + } + + /** + * 检查网址。 + * 该规则不支持中文字符的网址。 * + * URL checking. * The check rule of filter don't support chinese. * * @param string $var @@ -112,6 +178,23 @@ class validater } /** + * 检查域名,不支持中文。 + * Domain checking. + * + * The check rule of filter don't support chinese. + * + * @param string $var + * @static + * @access public + * @return bool + */ + public static function checkDomain($var) + { + return preg_match('/^([a-z0-9-]+\.)+[a-z]{2,15}$/', $var); + } + + /** + * 检查IP地址。 * IP checking. * * @param ip $var @@ -132,6 +215,7 @@ class validater } /** + * 日期检查。注意,2009-09-31是一个合法日期,系统会将它转换为2009-10-01。 * Date checking. Note: 2009-09-31 will be an valid date, because strtotime auto fixed it to 10-01. * * @param date $date @@ -148,6 +232,7 @@ class validater } /** + * 检查正则表达式。 * REG checking. * * @param string $var @@ -160,8 +245,9 @@ class validater { return filter_var($var, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => $reg))); } - + /** + * 检查长度。 * Length checking. * * @param string $var @@ -178,6 +264,7 @@ class validater } /** + * 检查不为空。 * Not empty checking. * * @param mixed $var @@ -191,6 +278,7 @@ class validater } /** + * 检查为空。 * Empty checking. * * @param mixed $var @@ -204,6 +292,7 @@ class validater } /** + * 检查用户名。 * Account checking. * * @param string $var @@ -219,6 +308,21 @@ class validater } /** + * 检查Code。 + * Check code. + * + * @param string $var + * @static + * @access public + * @return bool + */ + public static function checkCode($var) + { + return self::checkREG($var, '|^[A-Za-z0-9]+$|'); + } + + /** + * 检查验证码。 * Check captcha. * * @param mixed $var @@ -233,6 +337,7 @@ class validater } /** + * 是否等于给定的值。 * Must equal a value. * * @param mixed $var @@ -247,6 +352,22 @@ class validater } /** + * 检查不等于给定的值 + * Must not equal a value. + * + * @param mixed $var + * @param mixed $value + * @static + * @access public + * @return bool + */ + public static function checkNotEqual($var, $value) + { + return $var != $value; + } + + /** + * 检查大于给定的值。 * Must greater than a value. * * @param mixed $var @@ -261,6 +382,7 @@ class validater } /** + * 检查小于给定的值 * Must less than a value. * * @param mixed $var @@ -275,6 +397,7 @@ class validater } /** + * 检查大于等于给定的值 * Must greater than a value or equal a value. * * @param mixed $var @@ -289,6 +412,7 @@ class validater } /** + * 检查小于等于给定的值 * Must less than a value or equal a value. * * @param mixed $var @@ -303,6 +427,7 @@ class validater } /** + * 检查是否在给定的列表里面。 * Must in value list. * * @param mixed $var @@ -316,8 +441,9 @@ class validater if(!is_array($value)) $value = explode(',', $value); return in_array($var, $value); } - + /** + * 检查文件名。 * Check file name. * * @param string $var @@ -331,6 +457,31 @@ class validater } /** + * 检查敏感词。 + * Check sensitive words. + * + * @param object $vars + * @param array $dicts + * @static + * @access public + * @return void + */ + public static function checkSensitive($vars, $dicts) + { + foreach($vars as $var) + { + if(!$var) continue; + foreach($dicts as $dict) + { + if(strpos($var, $dict) === false) continue; + if(strpos($var, $dict) !== false) return false; + } + } + return true; + } + + /** + * 调用一个方法进行检查。 * Call a function to check it. * * @param mixed $var @@ -346,6 +497,7 @@ class validater } /** + * fixer类,处理数据。 * fixer class, to fix data types. * * @package framework @@ -353,6 +505,7 @@ class validater class fixer { /** + * 处理的数据。 * The data to be fixed. * * @var ojbect @@ -360,8 +513,17 @@ class fixer */ private $data; - private $stripedFields = array(); /** + * 跳过处理的字段。 + * The fields to striped. + * + * @var array + * @access private + */ + private $stripedFields = array(); + + /** + * 构造方法,将超级全局变量转换为对象。 * The construction function, according the scope, convert it to object. * * @param string $scope the scope of the var, should be post|get|server|session|cookie|env @@ -370,36 +532,37 @@ class fixer */ private function __construct($scope) { - switch($scope) - { - case 'post': - $this->data = (object)$_POST; - break; - case 'server': - $this->data = (object)$_SERVER; - break; - case 'get': - $this->data = (object)$_GET; - break; - case 'session': - $this->data = (object)$_SESSION; - break; - case 'cookie': - $this->data = (object)$_COOKIE; - break; - case 'env': - $this->data = (object)$_ENV; - break; - case 'file': - $this->data = (object)$_FILES; - break; + switch($scope) + { + case 'post': + $this->data = (object)$_POST; + break; + case 'server': + $this->data = (object)$_SERVER; + break; + case 'get': + $this->data = (object)$_GET; + break; + case 'session': + $this->data = (object)$_SESSION; + break; + case 'cookie': + $this->data = (object)$_COOKIE; + break; + case 'env': + $this->data = (object)$_ENV; + break; + case 'file': + $this->data = (object)$_FILES; + break; - default: - die('scope not supported, should be post|get|server|session|cookie|env'); - } + default: + die('scope not supported, should be post|get|server|session|cookie|env'); + } } /** + * 工厂方法。 * The factory function. * * @param string $scope @@ -412,6 +575,7 @@ class fixer } /** + * 处理Email。 * Email fix. * * @param string $fieldName @@ -426,7 +590,8 @@ class fixer } /** - * urlenocde. + * url编码。 + * urlencode. * * @param string $fieldName * @access public @@ -444,6 +609,7 @@ class fixer } /** + * 清理网址。 * Clean the url. * * @param string $fieldName @@ -458,6 +624,7 @@ class fixer } /** + * 处理Float类型。 * Float fixer. * * @param string $fieldName @@ -472,6 +639,7 @@ class fixer } /** + * 处理Int类型。 * Int fixer. * * @param string $fieldName @@ -486,7 +654,8 @@ class fixer } /** - * Special chars + * 将字符串转换为可以在浏览器查看的编码。 + * Special chars. * * @param string $fieldName * @access public @@ -519,10 +688,11 @@ class fixer } /** - * Strip tags - * - * @param string $fieldName - * @param string $allowedTags + * 忽略该标签。 + * Strip tags + * + * @param string $fieldName + * @param string $allowableTags * @access public * @return object fixer object */ @@ -545,14 +715,18 @@ class fixer { if(version_compare(phpversion(), '5.4', '<') and get_magic_quotes_gpc()) $this->data->$fieldName = stripslashes($this->data->$fieldName); - if(!in_array($fieldName, $this->stripedFields)) $this->data->$fieldName = $purifier->purify($this->data->$fieldName); + if(!in_array($fieldName, $this->stripedFields)) + { + if(!defined('RUN_MODE') or RUN_MODE != 'admin') $this->data->$fieldName = $purifier->purify($this->data->$fieldName); + } $this->stripedFields[] = $fieldName; } return $this; } /** - * Skip special chars. + * 忽略处理给定的字段。 + * Skip special chars check. * * @param string $filename * @access public @@ -566,6 +740,7 @@ class fixer } /** + * 给字段添加引用,防止字符与关键字冲突。 * Quote * * @param string $fieldName @@ -580,6 +755,7 @@ class fixer } /** + * 设置字段的默认值。 * Set default value of some fileds. * * @param string $fields @@ -595,6 +771,7 @@ class fixer } /** + * 如果条件为真,则为字段赋值。 * Set value of a filed on the condition is true. * * @param bool $condition @@ -610,6 +787,7 @@ class fixer } /** + * 强制给字段赋值。 * Set the value of a filed in force. * * @param string $fieldName @@ -624,6 +802,7 @@ class fixer } /** + * 移除一个字段。 * Remove a field. * * @param string $fieldName @@ -638,6 +817,7 @@ class fixer } /** + * 如果条件为真,移除该字段。 * Remove a filed on the condition is true. * * @param bool $condition @@ -653,6 +833,7 @@ class fixer } /** + * 为数据添加新的项。 * Add an item to the data. * * @param string $fieldName @@ -667,6 +848,7 @@ class fixer } /** + * 如果条件为真,则为数据添加新的项。 * Add an item to the data on the condition if true. * * @param bool $condition @@ -682,6 +864,7 @@ class fixer } /** + * 为指定字段增加值。 * Join the field. * * @param string $fieldName @@ -697,6 +880,7 @@ class fixer } /** + * 调用一个方法来处理数据。 * Call a function to fix it. * * @param string $fieldName @@ -712,14 +896,12 @@ class fixer } /** + * 处理完成后返回数据。 * Get the data after fixing. - * - * If only one field, return it's value directly. - * More fields, remove other fields not in the list and return $data. * - * @param string $fields the fields list. + * @param string $fieldName * @access public - * @return mix + * @return object */ public function get($fields = '') { @@ -740,6 +922,7 @@ class fixer } /** + * 处理字段,如果字段中含有',',拆分成数组。如果字段不在$data中,删除掉。 * Process fields, if contains ',', split it to array. If not in $data, remove it. * * @param string $fields diff --git a/lib/front/front.class.php b/lib/front/front.class.php index 96468196a0..faae47ff67 100644 --- a/lib/front/front.class.php +++ b/lib/front/front.class.php @@ -1,5 +1,6 @@ \n"; return "\n"; } /** - * Create fav icon tag - * + * 生成favicon标签。 + * Create favicon tag + * * @param mixed $url the url of the icon. + * @static * @access public - * @return string + * @return string */ public static function favicon($url) { - return "\n" . - "\n"; - + return "\n\n"; } /** - * Create icon tag + * 创建图标。 + * Create icon. * * @param name $name the name of the icon. * @param cssClass $class the extra css class of the icon. + * @static * @access public * @return string */ @@ -68,9 +77,11 @@ class html { $class = empty($class) ? ('icon-' . $name) : ('icon-' . $name . ' ' . $class); return ""; + } /** + * 生成rss标签。 * Create the rss tag. * * @param string $url @@ -85,13 +96,15 @@ class html } /** + * 生成超链接。 * Create tags like text * * @param string $href the link url. * @param string $title the link title. - * @param string $target the target window * @param string $misc other params. - * @param boolean $newline + * @param string $newline + * @static + * @access public * @return string */ static public function a($href = '', $title = '', $target = "_self", $misc = '', $newline = true) @@ -103,7 +116,7 @@ class html /* if page has onlybody param then add this param in all link. the param hide header and footer. */ if(strpos($href, 'onlybody=yes') === false and isonlybody()) { - $onlybody = $config->requestType == 'PATH_INFO' ? "?onlybody=yes" : "&onlybody=yes"; + $onlybody = $config->requestType != 'GET' ? "?onlybody=yes" : "&onlybody=yes"; $href .= $onlybody; } @@ -112,19 +125,31 @@ class html } /** + * 生成邮件链接。 * Create tags like text * * @param string $mail the email address * @param string $title the email title. + * @static + * @access public * @return string */ static public function mailto($mail = '', $title = '') { - if(empty($title)) $title = $mail; - return "$title"; + $html = ''; + $mails = explode(',', $mail); + $titles = explode(',', $title); + foreach($mails as $key => $m) + { + if(empty($m)) continue; + $t = empty($titles[$key]) ? $mail : $titles[$key]; + $html .= " $t"; + } + return $html; } /** + * 生成select标签。 * Create tags like "" * * @param string $name the name of the select tag. @@ -132,6 +157,8 @@ class html * @param string $selectedItems the item(s) to be selected, can like item1,item2. * @param string $attrib other params such as multiple, size and style. * @param string $append adjust if add options[$selectedItems]. + * @static + * @access public * @return string */ static public function select($name = '', $options = array(), $selectedItems = "", $attrib = "", $append = false) @@ -142,10 +169,14 @@ class html /* The begin. */ $id = $name; - if(strpos($name, '[') !== false) $id = trim(str_replace(']', '', str_replace('[', '', $name))); - $string = "\n"; /* The options. */ + if(is_array($selectedItems)) $selectedItems = implode(',', $selectedItems); $selectedItems = ",$selectedItems,"; foreach($options as $key => $value) { @@ -159,12 +190,15 @@ class html } /** + * 生成带optgroup标签的select标签。 * Create select with optgroup. * * @param string $name the name of the select tag. * @param array $groups the option groups. * @param string $selectedItems the item(s) to be selected, can like item1,item2. * @param string $attrib other params such as multiple, size and style. + * @static + * @access public * @return string */ static public function selectGroup($name = '', $groups = array(), $selectedItems = "", $attrib = "") @@ -173,7 +207,7 @@ class html /* The begin. */ $id = $name; - if(strpos($name, '[') !== false) $id = trim(str_replace(']', '', str_replace('[', '', $name))); + if($pos = strpos($name, '[')) $id = substr($name, 0, $pos); $string = "" * * @param string $name the name of the radio tag. @@ -202,6 +237,8 @@ class html * @param string $checked the value to checked by default. * @param string $attrib other attribs. * @param string $type inline or block + * @static + * @access public * @return string */ static public function radio($name = '', $options = array(), $checked = '', $attrib = '', $type = 'inline') @@ -227,18 +264,24 @@ class html } /** + * 生成多选按钮。 * Create tags like "" * * @param string $name the name of the checkbox tag. * @param array $options the array to create checkbox tag from. * @param string $checked the value to checked by default, can be item1,item2 * @param string $attrib other attribs. + * @param string $type inline or block + * @static + * @access public * @return string */ static public function checkbox($name, $options, $checked = "", $attrib = "", $type = 'inline') { $options = (array)($options); if(!is_array($options) or empty($options)) return false; + + if(is_array($checked)) $checked = implode(',', $checked); $string = ''; $checked = ",$checked,"; $isBlock = $type == 'block'; @@ -260,162 +303,32 @@ class html } /** - * Create tags like "" - * - * @param string $scope the scope of select all. - * @param string $type the type of input tag. - * @param boolean $checked if the type is checkbox, set the checked attribute. - * @return string - */ - static public function selectAll($scope = "", $type = "button", $checked = false, $class = '') - { - $string = << -function selectAll(checker, scope, type) -{ - if(scope) - { - if(type == 'button') - { - $('#' + scope + ' input').each(function() - { - $(this).attr("checked", true) - }); - } - else if(type == 'checkbox') - { - $('#' + scope + ' input').each(function() - { - $(this).attr("checked", checker.checked) - }); - } - } - else - { - if(type == 'button') - { - $('input:checkbox').each(function() - { - $(this).attr("checked", true) - }); - } - else if(type == 'checkbox') - { - $('input:checkbox').each(function() - { - $(this).attr("checked", checker.checked) - }); - } - } -} - -EOT; - global $lang; - if($type == 'checkbox') - { - if($checked) - { - $string .= " "; - } - else - { - $string .= " "; - } - } - elseif($type == 'button') - { - $string .= ""; - } - - return $string; - } - - /** - * Create tags like "" - * - * @param string $scope the scope of select reverse. - * @return string - */ - static public function selectReverse($scope = "") - { - $string = << -function selectReverse(scope) -{ - if(scope) - { - $('#' + scope + ' input').each(function() - { - $(this).attr("checked", !$(this).attr("checked")) - }); - } - else - { - $('input:checkbox').each(function() - { - $(this).attr("checked", !$(this).attr("checked")) - }); - } -} - -EOT; - global $lang; - $string .= ""; - - return $string; - } - - /** - * Create select buttons include 'selectAll' and 'selectAll'. - * - * @param string $scope the scope of select reverse. - * @return string - */ - static public function selectButton($scope = "", $appendClass = '') - { - $string = << -$(function() -{ - if($('body').data('bindSelectBtn')) return; - $('body').data('bindSelectBtn', true); - $(document).on('click', '.check-all, .check-inverse', function() - { - var e = $(this); - if(e.closest('.datatable').length) return; - scope = e.data('scope'); - scope = scope ? $('#' + scope) : e.closest('.table'); - if(!scope.length) scope = e.closest('form'); - scope.find('input:checkbox').each(e.hasClass('check-inverse') ? function() { $(this).attr("checked", !$(this).attr("checked"));} : function() { $(this).attr("checked", true);}); - }); -}); - -EOT; - global $lang; - $string .= "{$lang->selectAll}"; - $string .= "{$lang->selectReverse}"; - return $string; - } - - /** + * 生成input输入标签。 * Create tags like "" * * @param string $name the name of the text input tag. * @param string $value the default value. * @param string $attrib other attribs. + * @static + * @access public * @return string */ static public function input($name, $value = "", $attrib = "") { - return "\n"; + $id = "id='$name'"; + if(strpos($attrib, 'id=') !== false) $id = ''; + return "\n"; } /** + * 生成隐藏的提交标签。 * Create tags like "" * * @param string $name the name of the text input tag. * @param string $value the default value. * @param string $attrib other attribs. + * @static + * @access public * @return string */ static public function hidden($name, $value = "", $attrib = "") @@ -424,11 +337,14 @@ EOT; } /** + * 创建密码输入框。 * Create tags like "" * * @param string $name the name of the text input tag. * @param string $value the default value. * @param string $attrib other attribs. + * @static + * @access public * @return string */ static public function password($name, $value = "", $attrib = "") @@ -437,11 +353,14 @@ EOT; } /** + * 创建编辑器标签。 * Create tags like "" * * @param string $name the name of the textarea tag. * @param string $value the default value of the textarea tag. * @param string $attrib other attribs. + * @static + * @access public * @return string */ static public function textarea($name, $value = "", $attrib = "") @@ -450,10 +369,13 @@ EOT; } /** + * 创建文件上传标签。 * Create tags like "". * * @param string $name the name of the file name. * @param string $attrib other attribs. + * @static + * @access public * @return string */ static public function file($name, $attrib = "") @@ -462,32 +384,92 @@ EOT; } /** + * 创建日期输入框。 + * Create date picker. + * + * @param string $name the name of the text input tag. + * @param string $value the default value. + * @param string $options + * @param string $attrib + * @static + * @access public + * @return void + */ + static public function date($name, $value = "", $options = '', $attrib = '') + { + $html = "
"; + $html .= "\n"; + $html .= "
"; + return $html; + } + + /** + * 创建日期时间输入框。 + * Create dateTime picker. + * + * @param string $name the name of the text input tag. + * @param string $value the default value. + * @param string $options + * @param string $attrib + * @static + * @access public + * @return void + */ + static public function dateTime($name, $value = "", $options = '', $attrib = '') + { + $html = "
"; + $html .= "\n"; + $html .= "
"; + return $html; + } + + /** + * 创建img标签。 + * create tags like "". + * + * @param string $name the name of the image name. + * @param string $attrib other attribs. + * @static + * @access public + * @return string + */ + static public function image($image, $attrib = '') + { + return "\n"; + } + + /** + * 创建提交按钮。 * Create submit button. * * @param string $label the label of the button + * @param string $class the class of the button * @param string $misc other params * @static * @access public * @return string the submit button tag. */ - public static function submitButton($label = '', $misc = '', $class = 'btn-primary') + public static function submitButton($label = '', $misc = '', $class = 'btn btn-primary') { - if(empty($label)) - { - global $lang; - $label = $lang->save; - } - return " "; + global $lang; + + $label = empty($label) ? $lang->save : $label; + $misc .= strpos($misc, 'data-loading') === false ? " data-loading='$lang->loading'" : ''; + + return " "; } /** + * 创建重置按钮。 * Create reset button. * + * @param string $label + * @param string $class * @static * @access public * @return string the reset button tag. */ - public static function resetButton($label = '', $misc = '', $class = '') + public static function resetButton($label = '', $class = '') { if(empty($label)) { @@ -498,48 +480,60 @@ EOT; } /** + * 创建返回按钮。 * Back button. * + * @param string $label + * @param string $misc * @static * @access public * @return string the back button tag. */ - public static function backButton($misc = '') + public static function backButton($label = '', $misc = '') { - global $lang; if(isonlybody()) return false; - return "{$lang->goback}"; + + global $lang; + if(empty($label)) + { + global $lang; + $label = $lang->goback; + } + return "{$label}"; } /** + * 创建通用按钮。 * Create common button. * * @param string $label the label of the button + * @param string $class the class of the button * @param string $misc other params + * @param string $icon icon * @static * @access public * @return string the common button tag. */ - public static function commonButton($label = '', $misc = '', $class = '', $icon = '') + public static function commonButton($label = '', $misc = '', $class = 'btn btn-default', $icon = '') { if($icon) $label = " " . $label; - if($class) $class = 'btn ' . $class; else $class = 'btn'; - return " "; + return " "; } /** + * 创建一个带有链接的按钮。 * create a button, when click, go to a link. * * @param string $label the link title * @param string $link the link url - * @param string $target the target window + * @param string $class the link style * @param string $misc other params - * @param string $class css class + * @param string $target the target window * @static * @access public * @return string */ - public static function linkButton($label = '', $link = '', $target = 'self', $misc = '', $class = '') + public static function linkButton($label = '', $link = '', $target = 'self', $misc = '', $class = 'btn btn-default') { global $config, $lang; @@ -548,27 +542,190 @@ EOT; /* if page has onlybody param then add this param in all link. the param hide header and footer. */ if(strpos($link, 'onlybody=') === false and isonlybody()) { - $onlybody = $config->requestType == 'PATH_INFO' ? "?onlybody=yes" : "&onlybody=yes"; + $onlybody = strpos($link, '?') === false ? "?onlybody=yes" : "&onlybody=yes"; $link .= $onlybody; } - - return " "; + return " "; } /** + * 创建关闭模态框按钮。 + * Create a button to close. + * + * @static + * @access public + * @return string + */ + public static function closeButton() + { + return ""; + } + + /** + * 创建全选标签。 + * Create tags like "" + * + * @param string $scope the scope of select all. + * @param string $type the type of input tag. + * @param boolean $checked if the type is checkbox, set the checked attribute. + * @param string $class + * @static + * @access public + * @return string + */ + static public function selectAll($scope = "", $type = "button", $checked = false, $class = '') + { + $string = << +function selectAll(checker, scope, type) +{ + if(scope) + { + if(type == 'button') + { + $('#' + scope + ' input').each(function() + { + $(this).prop("checked", true) + }); + } + else if(type == 'checkbox') + { + $('#' + scope + ' input').each(function() + { + $(this).prop("checked", checker.checked) + }); + } + } + else + { + if(type == 'button') + { + $('input:checkbox').each(function() + { + $(this).prop("checked", true) + }); + } + else if(type == 'checkbox') + { + $('input:checkbox').each(function() + { + $(this).prop("checked", checker.checked) + }); + } + } +} + +EOT; + global $lang; + if($type == 'checkbox') + { + $string .= " "; + } + elseif($type == 'button') + { + $string .= ""; + } + + return $string; + } + + /** + * 创建反选标签。 + * Create tags like "" + * + * @param string $scope the scope of select reverse. + * @static + * @access public + * @return string + */ + static public function selectReverse($scope = "") + { + $string = << +function selectReverse(scope) +{ + if(scope) + { + $('#' + scope + ' input').each(function() + { + $(this).prop("checked", !$(this).prop("checked")) + }); + } + else + { + $('input:checkbox').each(function() + { + $(this).prop("checked", !$(this).prop("checked")) + }); + } +} + +EOT; + global $lang; + $string .= ""; + + return $string; + } + + /** + * 创建全选、反选按钮组。 + * Create select buttons include 'selectAll' and 'selectReverse'. + * + * @param string $scope the scope of select reverse. + * @param bool $asGroup + * @param string $appendClass + * @static + * @access public + * @return string + */ + static public function selectButton($scope = "", $asGroup = true, $appendClass = '') + { + $string = << +$(function() +{ + if($('body').data('bindSelectBtn')) return; + $('body').data('bindSelectBtn', true); + $(document).on('click', '.check-all, .check-inverse, #allchecker, #reversechecker', function() + { + var e = $(this); + if(e.closest('.datatable').length) return; + scope = e.data('scope'); + scope = scope ? $('#' + scope) : e.closest('.table'); + if(!scope.length) scope = e.closest('form'); + scope.find('input:checkbox').each(e.hasClass('check-inverse') ? function() { $(this).prop("checked", !$(this).prop("checked"));} : function() { $(this).prop("checked", true);}); + }); +}); + +EOT; + global $lang; + if($asGroup) $string .= "
"; + $string .= "{$lang->selectAll}"; + $string .= "{$lang->selectReverse}"; + if($asGroup) $string .= "
"; + return $string; + } + + /** + * 打印星星。 * Print the star images. * * @param float $stars 0 1 1.5 2 2.5 3 3.5 4 4.5 5 * @access public + * @static + * @access public * @return void */ public static function printStars($stars) { $redStars = 0; $halfStars = 0; - $whiteStars = 5; + $whiteStars = 5; if($stars) { + /* If stars more than max, then fix it. */ + if($stars > $whiteStars) $stars = $whiteStars; + $redStars = floor($stars); $halfStars = $stars - $redStars ? 1 : 0; $whiteStars = 5 - ceil($stars); @@ -582,29 +739,38 @@ EOT; } /** + * JS类。 * JS class. * * @package front */ class js { - /** + /** + * 引入一个js文件。 * Import a js file. * * @param string $url - * @param string $version + * @param string $ieParam like 'lt IE 9' + * @static * @access public * @return string */ - public static function import($url, $version = '') + public static function import($url, $ieParam = '') { - if(!$version) $version = filemtime(__FILE__); - echo "\n"; + global $config; + $pathInfo = parse_url($url); + $mark = !empty($pathInfo['query']) ? '&' : '?'; + + if(empty($ieParam)) echo "\n"; + echo "\n"; } /** + * 开始输出js。 * The start of javascript. * + * @param bool $full * @static * @access private * @return string @@ -612,22 +778,26 @@ class js static private function start($full = true) { if($full) return "\n"; + if($newline) return "\n\n"; + return "\n"; } /** + * 显示一个警告框。 * Show a alert box. * * @param string $message @@ -641,6 +811,20 @@ class js } /** + * 关闭浏览器窗口。 + * Close window + * + * @static + * @access public + * @return void + */ + static public function close() + { + return self::start() . "window.close()" . self::end(); + } + + /** + * 显示错误信息。 * Show error info. * * @param string|array $message @@ -666,6 +850,7 @@ class js } /** + * 重置禁用的提交按钮。 * Reset the submit form. * * @static @@ -678,16 +863,19 @@ class js } /** + * 显示一个确认框,点击确定跳转到$okURL,点击取消跳转到$cancelURL。 * show a confirm box, press ok go to okURL, else go to cancleURL. * - * @param string $message the text to be showed. - * @param string $okURL the url to go to when press 'ok'. - * @param string $cancleURL the url to go to when press 'cancle'. - * @param string $okTarget the target to go to when press 'ok'. - * @param string $cancleTarget the target to go to when press 'cancle'. + * @param string $message 显示的内容。 the text to be showed. + * @param string $okURL 点击确定后跳转的地址。 the url to go to when press 'ok'. + * @param string $cancleURL 点击取消后跳转的地址。 the url to go to when press 'cancle'. + * @param string $okTarget 点击确定后跳转的target。 the target to go to when press 'ok'. + * @param string $cancleTarget 点击取消后跳转的target。 the target to go to when press 'cancle'. + * @static + * @access public * @return string */ - static public function confirm($message = '', $okURL = '', $cancleURL = '', $okTarget = "self", $cancleTarget = "self", $Echo = true) + static public function confirm($message = '', $okURL = '', $cancleURL = '', $okTarget = "self", $cancleTarget = "self") { $js = self::start(); @@ -726,10 +914,13 @@ EOT; } /** + * $target会跳转到$url指定的地址。 * change the location of the $target window to the $URL. * * @param string $url the url will go to. * @param string $target the target of the url. + * @static + * @access public * @return string the javascript string. */ static public function locate($url, $target = "self") @@ -754,6 +945,7 @@ EOT; } /** + * 关闭当前窗口。 * Close current window. * * @static @@ -766,11 +958,14 @@ EOT; } /** + * 经过一段时间后跳转到指定的页面。 * Goto a page after a timer. * * @param string $url the url will go to. * @param string $target the target of the url. * @param int $time the timer, msec. + * @static + * @access public * @return string the javascript string. */ static public function refresh($url, $target = "self", $time = 3000) @@ -782,9 +977,12 @@ EOT; } /** + * 重新加载窗口。 * Reload a window. * * @param string $window the window to reload. + * @static + * @access public * @return string the javascript string. */ static public function reload($window = 'self') @@ -798,13 +996,14 @@ EOT; } /** + * 用Javascript关闭colorbox弹出框。 * Close colorbox in javascript. * This is a obsolete method, you can use 'closeModal' instead. * * @param string $window * @static * @access public - * @return void + * @return string */ static public function closeColorbox($window = 'self') { @@ -812,12 +1011,15 @@ EOT; } /** + * 用Javascript关闭模态框。 * Close modal with javascript. * * @param string $window + * @param string $location + * @param string $callback * @static * @access public - * @return void + * @return string */ static public function closeModal($window = 'self', $location = 'this', $callback = 'null') { @@ -829,6 +1031,7 @@ EOT; } /** + * 导出$config到js,因为js的createLink()方法需要获取config信息。 * Export the config vars for createLink() js version. * * @static @@ -845,14 +1048,15 @@ EOT; $moduleName = $app->getModuleName(); $methodName = $app->getMethodName(); $clientLang = $app->getClientLang(); + $runMode = defined('RUN_MODE') ? RUN_MODE : ''; $requiredFields = ''; if(isset($config->$moduleName->$methodName->requiredFields)) $requiredFields = str_replace(' ', '', $config->$moduleName->$methodName->requiredFields); $jsConfig = new stdclass(); $jsConfig->webRoot = $config->webRoot; + $jsConfig->appName = $app->getAppName(); $jsConfig->cookieLife = ceil(($config->cookieLife - time()) / 86400); $jsConfig->requestType = $config->requestType; - $jsConfig->pathType = $config->pathType; $jsConfig->requestFix = $config->requestFix; $jsConfig->moduleVar = $config->moduleVar; $jsConfig->methodVar = $config->methodVar; @@ -863,13 +1067,16 @@ EOT; $jsConfig->currentMethod = $methodName; $jsConfig->clientLang = $clientLang; $jsConfig->requiredFields = $requiredFields; - $jsConfig->router = $app->server->PHP_SELF; - $jsConfig->timeout = $config->timeout; + $jsConfig->router = $app->server->SCRIPT_NAME; + $jsConfig->save = isset($lang->save) ? $lang->save : ''; + $jsConfig->runMode = $runMode; + $jsConfig->timeout = isset($config->timeout) ? $config->timeout : ''; + $jsConfig->pingInterval = isset($config->pingInterval) ? $config->pingInterval : ''; $jsLang = new stdclass(); - $jsLang->submitting = $lang->submitting; - $jsLang->save = $lang->save; - $jsLang->timeout = $lang->timeout; + $jsLang->submitting = isset($lang->loading) ? $lang->loading : ''; + $jsLang->save = $jsConfig->save; + $jsLang->timeout = isset($lang->timeout) ? $lang->timeout : ''; $js = self::start(false); $js .= 'var config=' . json_encode($jsConfig) . ";\n"; @@ -879,6 +1086,7 @@ EOT; } /** + * 执行js代码。 * Execute some js code. * * @param string $code @@ -895,20 +1103,31 @@ EOT; } /** + * 设置Javascript变量值。 * Set js value. * * @param string $key * @param mix $value * @static * @access public - * @return void + * @return string */ static public function set($key, $value) { + global $config; + $prefix = (isset($config->framework->jsWithPrefix) and $config->framework->jsWithPrefix == false) ? '' : 'v.'; + + static $viewOBJOut; $js = self::start(false); + if(!$viewOBJOut and $prefix) + { + $js .= 'if(typeof(v) != "object") v = {};'; + $viewOBJOut = true; + } + if(is_numeric($value)) { - $js .= "$key = $value"; + $js .= "{$prefix}{$key} = {$value};"; } elseif(is_array($value) or is_object($value) or is_string($value)) { @@ -921,26 +1140,27 @@ EOT; if(is_numeric($v)) $value[$k] = (string)$v; } } - + $value = json_encode($value); - $js .= "$key = $value"; + $js .= "{$prefix}{$key} = {$value};"; } elseif(is_bool($value)) { $value = $value ? 'true' : 'false'; - $js .= "$key = $value"; + $js .= "{$prefix}{$key} = $value;"; } else { $value = addslashes($value); - $js .= "$key = '$value'"; + $js .= "{$prefix}{$key} = '{$value};'"; } - $js .= self::end(); + $js .= self::end($newline = false); echo $js; } } /** + * css类。 * css class. * * @package front @@ -948,20 +1168,22 @@ EOT; class css { /** + * 引入css文件。 * Import a css file. * * @param string $url - * @param string $version * @access public - * @return vod + * @return void */ - public static function import($url, $version = '') + public static function import($url, $attrib = '') { - if(!$version) $version = filemtime(__FILE__); - echo "\n"; + global $config; + if(!empty($attrib)) $attrib = ' ' . $attrib; + echo "\n"; } /** + * 打印css代码。 * Print a css code. * * @param string $css @@ -973,4 +1195,4 @@ class css { echo ""; } -} +} \ No newline at end of file diff --git a/lib/pager/pager.class.php b/lib/pager/pager.class.php old mode 100755 new mode 100644 index de199a24b9..8bf97ded47 --- a/lib/pager/pager.class.php +++ b/lib/pager/pager.class.php @@ -1,5 +1,6 @@ pageCookie = 'pager' . ucfirst($this->app->getModuleName()) . ucfirst($this->app->getMethodName()); if(isset($_COOKIE[$this->pageCookie])) $recPerPage = $_COOKIE[$this->pageCookie]; - $this->recPerPage = ($recPerPage > 0) ? $recPerPage : PAGER::DEFAULT_REC_PRE_PAGE; + $this->recPerPage = ($recPerPage > 0) ? $recPerPage : PAGER::DEFAULT_REC_PER_PAGE; } /** + * 设置总页数。 * Set the pageTotal property. * * @access public @@ -178,6 +195,7 @@ class pager } /** + * 设置页码。 * Set the page id. * * @param int $pageID @@ -186,7 +204,7 @@ class pager */ public function setPageID($pageID) { - if($pageID > 0 and $pageID <= $this->pageTotal) + if($pageID > 0 and ($this->pageTotal == 0 or $pageID <= $this->pageTotal)) { $this->pageID = $pageID; } @@ -197,6 +215,7 @@ class pager } /** + * 设置全局变量$app。 * Set the $app property; * * @access private @@ -209,6 +228,7 @@ class pager } /** + * 设置全局变量$lang。 * Set the $lang property. * * @access private @@ -221,6 +241,7 @@ class pager } /** + * 设置模块名。 * Set the $moduleName property. * * @access private @@ -232,6 +253,7 @@ class pager } /** + * 设置方法名。 * Set the $methodName property. * * @access private @@ -243,6 +265,7 @@ class pager } /** + * 从请求网址中获取记录总数、每页记录数、页码。 * Get recTotal, recPerpage, pageID from the request params, and add them to params. * * @access private @@ -257,9 +280,19 @@ class pager if(strtolower($key) == 'recperpage') $this->params[$key] = $this->recPerPage; if(strtolower($key) == 'pageid') $this->params[$key] = $this->pageID; } + + parse_str(strip_tags(urldecode($_SERVER['QUERY_STRING'])), $query); + + unset($query['m']); + unset($query['f']); + unset($query['t']); + + $this->params = array_merge($this->params, $query); + } /** + * 创建limit语句。 * Create the limit string. * * @access public @@ -271,8 +304,9 @@ class pager if($this->pageTotal > 1) $limit = ' limit ' . ($this->pageID - 1) * $this->recPerPage . ", $this->recPerPage"; return $limit; } - + /** + * 向页面显示分页信息。 * Print the pager's html. * * @param string $align @@ -282,10 +316,48 @@ class pager */ public function show($align = 'right', $type = 'full') { - echo $this->get($align, $type); + if($align === 'justify') + { + echo $this->getJustify($type); + } + else + { + echo $this->get($align, $type); + } } /** + * 获取优化后的分页。 + * Get the justify pager html string + * + * @access public + * @return [type] [description] + */ + public function getJustify() + { + if($this->recTotal <= 0) return ''; + + $this->setParams(); + $pager = ''; + + $pager .= "
  • "; + $this->params['pageID'] = 1; + $pager .= $this->createLink('« ' . $this->lang->pager->previousPage) . '
  • '; + + $pager .= "
  • "; + $firstId = $this->recPerPage * ($this->pageID - 1) + 1; + $pager .= sprintf($this->lang->pager->summery, $firstId, max(min($this->recPerPage * $this->pageID, $this->recTotal), $firstId), $this->recTotal); + $pager .= '
  • '; + + $pager .= "
  • "; + $this->params['pageID'] = min($this->pageTotal, $this->pageID + 1); + $pager .= $this->createLink($this->lang->pager->nextPage . ' »') . '
  • '; + + return "
      {$pager}
    "; + } + + /** + * 设置分页信息的样式。 * Get the pager html string. * * @param string $align @@ -295,17 +367,19 @@ class pager */ public function get($align = 'right', $type = 'full') { + /* 如果记录个数为0,返回没有记录。 */ /* If the RecTotal is zero, return with no record. */ - if($this->recTotal == 0) { return $type == 'mobile' ? '' : "
    {$this->lang->pager->noRecord}
    "; } + if($this->recTotal == 0) return $type == 'mobile' ? '' : "
    {$this->lang->pager->noRecord}
    "; /* Set the params. */ $this->setParams(); - + + /* 创建前一页和后一页链接。 */ /* Create the prePage and nextpage, all types have them. */ $pager = $this->createPrePage($type); $pager .= $this->createNextPage($type); - /* The short and full type. */ + /* 简单和完全模式。 The short and full type. */ if($type !== 'shortest' and $type !== 'mobile') { $pager = $this->createFirstPage() . $pager; @@ -322,7 +396,7 @@ class pager $pager = $this->pageID . '/' . $this->pageTotal . ' ' . $pager; } - /* Only the full type . */ + /* 只是完全模式。 Only the full type . */ if($type == 'full') { $pager = $this->createDigest() . $pager; @@ -330,10 +404,11 @@ class pager $pager .= $this->createRecPerPageJS(); } - return "
    $pager
    "; + return "
    $pager
    "; } /** + * 生成分页摘要信息。 * Create the digest code. * * @access private @@ -345,6 +420,7 @@ class pager } /** + * 创建首页链接。 * Create the first page. * * @access private @@ -354,12 +430,14 @@ class pager { if($this->pageID == 1) return $this->lang->pager->first . ' '; $this->params['pageID'] = 1; - return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->first); + return $this->createLink($this->lang->pager->first); } /** + * 创建前一页链接。 * Create the pre page html. * + * @param string $type * @access private * @return string */ @@ -369,19 +447,21 @@ class pager { if($this->pageID == 1) return ''; $this->params['pageID'] = $this->pageID - 1; - return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->pre, '', 'data-role="button" data-icon="arrow-l" data-iconpos="left" data-inline="true"'); + return $this->createLink($this->lang->pager->pre); } else { if($this->pageID == 1) return $this->lang->pager->pre . ' '; $this->params['pageID'] = $this->pageID - 1; - return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->pre); + return $this->createLink($this->lang->pager->pre); } } /** + * 创建下一页链接。 * Create the next page html. * + * @param string $type * @access private * @return string */ @@ -391,17 +471,18 @@ class pager { if($this->pageID == $this->pageTotal) return ''; $this->params['pageID'] = $this->pageID + 1; - return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->next, '', 'data-role="button" data-icon="arrow-r" data-iconpos="right" data-inline="true"'); + return $this->createLink($this->lang->pager->next); } else { if($this->pageID == $this->pageTotal) return $this->lang->pager->next . ' '; $this->params['pageID'] = $this->pageID + 1; - return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->next); + return $this->createLink($this->lang->pager->next); } } /** + * 创建最后一页链接。 * Create the last page * * @access private @@ -411,10 +492,11 @@ class pager { if($this->pageID == $this->pageTotal) return $this->lang->pager->last . ' '; $this->params['pageID'] = $this->pageTotal; - return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->last); + return $this->createLink($this->lang->pager->last); } /** + * 创建每页显示记录数的select标签。 * Create the select object of record perpage. * * @access private @@ -422,7 +504,10 @@ class pager */ private function createRecPerPageJS() { - /* Replace the recTotal, recPerPage, pageID to special string, and then replace them with values by JS. */ + /* + * 替换recTotal, recPerPage, pageID为特殊的字符串,然后用js代码替换掉。 + * Replace the recTotal, recPerPage, pageID to special string, and then replace them with values by JS. + **/ $params = $this->params; foreach($params as $key => $value) { @@ -435,7 +520,7 @@ class pager $vars = rtrim($vars, '&'); $js = << +