From 2e7698db31cf5a0d8f2756435685a7367d46e994 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 9 Mar 2016 17:36:02 +0800 Subject: [PATCH] * change for framework. --- config/config.php | 4 +- framework/base/control.class.php | 828 +++++++++++ framework/base/helper.class.php | 1269 +++++++++++++++++ framework/base/model.class.php | 290 ++++ framework/base/router.class.php | 2226 ++++++++++++++++++++++++++++++ framework/control.class.php | 824 +---------- framework/helper.class.php | 1305 +----------------- framework/model.class.php | 278 +--- framework/myrouter.class.php | 94 -- framework/router.class.php | 2192 +---------------------------- lib/dao/dao.class.php | 9 +- www/index.php | 5 +- www/install.php | 4 +- www/upgrade.php | 4 +- 14 files changed, 4653 insertions(+), 4679 deletions(-) create mode 100644 framework/base/control.class.php create mode 100644 framework/base/helper.class.php create mode 100644 framework/base/model.class.php create mode 100644 framework/base/router.class.php delete mode 100755 framework/myrouter.class.php mode change 100644 => 100755 framework/router.class.php diff --git a/config/config.php b/config/config.php index e006d6a7d0..739901b4d9 100644 --- a/config/config.php +++ b/config/config.php @@ -86,7 +86,7 @@ $config->ip = new stdclass(); $config->ip->whiteList = '*'; /* View type settings. */ -$config->viewPrefix['mhtml'] = 'm.'; +$config->devicePrefix['mhtml'] = 'm.'; /* Master database settings. */ $config->db = new stdclass(); @@ -111,6 +111,7 @@ $config->framework->jsWithPrefix = false; $config->framework->autoRepairTable = true; $config->framework->logDays = 14; $config->framework->purifier = true; +$config->framework->autoLang = false; /* Include the custom config file. */ $configRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR; @@ -120,7 +121,6 @@ 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/base/control.class.php b/framework/base/control.class.php new file mode 100644 index 0000000000..e36b865171 --- /dev/null +++ b/framework/base/control.class.php @@ -0,0 +1,828 @@ +app. + * 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 = '', $appName = '') + { + /* + * 将全局变量设为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(); + + /* + * 设置当前模块,读取该模块的model类。 + * Load the model file auto. + **/ + $this->setModuleName($moduleName); + $this->setMethodName($methodName); + $this->loadModel($this->moduleName, $appName); + $this->setDevicePrefix(); + + /* + * 初始化$view视图类。 + * Init the view vars. + **/ + $this->view = new stdclass(); + $this->view->app = $app; + $this->view->lang = $lang; + $this->view->config = $config; + $this->view->common = $common; + $this->view->title = ''; + + /* + * 设置超级变量,从$app引用过来。 + * Set super vars. + **/ + $this->setSuperVars(); + } + + //-------------------- Model相关方法(Model related methods) --------------------// + + /* + * 设置模块名。 + * Set the module name. + * + * @param string $moduleName 模块名,如果为空,则从$app中获取 The module name, if empty, get it from $app. + * @access public + * @return void + */ + public function setModuleName($moduleName = '') + { + $this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName(); + } + + /* Set the method name. + * 设置方法名。 + * + * @param string $methodName 方法名,如果为空,则从$app中获取 The method name, if empty, get it from $app. + * @access public + * @return void + */ + public function setMethodName($methodName = '') + { + $this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName(); + } + + /** + * 加载指定模块的model文件。 + * Load the model file of one module. + * + * @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 如果没有model文件,返回false,否则返回model对象。 If no model file, return false. Else return the model object. + */ + public function loadModel($moduleName = '', $appName = '') + { + if(empty($moduleName)) $moduleName = $this->moduleName; + if(empty($appName)) $appName = $this->appName; + $modelFile = helper::setModelFile($moduleName, $appName); + + /* + * 如果没有model文件,尝试加载config配置信息。 + * If no model file, try load config. + */ + if(!helper::import($modelFile)) + { + $this->app->loadConfig($moduleName, $appName, false); + $this->app->loadLang($moduleName, $appName); + $this->dao = new dao(); + return false; + } + + $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($appName); + $this->dao = $this->$moduleName->dao; + return $this->$moduleName; + } + + /** + * 设置超级全局变量,方便直接引用。 + * Set the super vars. + * + * @access public + * @return void + */ + public function setSuperVars() + { + $this->post = $this->app->post; + $this->get = $this->app->get; + $this->server = $this->app->server; + $this->session = $this->app->session; + $this->cookie = $this->app->cookie; + $this->global = $this->app->global; + } + + /** + * 为客户端是PC还是移动设备,设置视图文件前缀名。 + * Set the prefix of view file for mobile or PC. + * + * @access public + * @return void + */ + public function setDevicePrefix() + { + $this->devicePrefix = zget($this->config->devicePrefix, $this->viewType, ''); + } + + /** + * 设置客户端的设备类型 + * Set client device. + * + * @access public + * @return void + */ + public function setClientDevice() + { + $this->clientDevice = helper::getClientDevice(); + $this->app->clientDevice = $this->clientDevice; + } + + //-------------------- 视图相关方法(View related methods) --------------------// + + /** + * 设置视图文件,可以获取其他模块的视图文件。 + * Set the view file, thus can use fetch other module's page. + * + * @param string $moduleName module name + * @param string $methodName method name + * @access public + * @return string the view file + */ + public function setViewFile($moduleName, $methodName) + { + $moduleName = strtolower(trim($moduleName)); + $methodName = strtolower(trim($methodName)); + + $modulePath = $this->app->getModulePath($this->appName, $moduleName); + $viewExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'view'); + + /* Set viewType to html when it is mhtml. */ + $viewType = $this->viewType == 'mhtml' ? 'html' : $this->viewType; + + /* + * 主视图文件,扩展视图文件和钩子文件。 + * The main view file, extension view file and hook file. + **/ + $mainViewFile = $modulePath . 'view' . DS . $this->devicePrefix . $methodName . '.' . $viewType . '.php'; + + /* Extension view file. */ + $commonExtViewFile = $viewExtPath['common'] . $this->devicePrefix . $methodName . ".{$viewType}.php"; + $siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->devicePrefix . $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->devicePrefix . $methodName . ".*.{$viewType}.hook.php"); + $siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $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 + * @access public + * @return string|bool If extension view file exists, return the path. Else return fasle. + */ + public function getExtViewFile($viewFile) + { + /** + * 首先找sitecode下的扩展文件,如果没有,再找ext下的扩展文件。 + * Find extViewFile in ext/_$siteCode/view first, then try 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)) + { + helper::cd($extPath); + return $extViewFile; + } + return false; + } + + /** + * 获取方法的css内容,common.css + 该方法的css。 + * Get css code for a method. + * + * @param string $moduleName + * @param string $methodName + * @access public + * @return string + */ + public function getCSS($moduleName, $methodName) + { + $moduleName = strtolower(trim($moduleName)); + $methodName = strtolower(trim($methodName)); + + $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->devicePrefix . 'common.css'; + $methodCssFile = $modulePath . 'css' . DS . $this->devicePrefix . $methodName . '.css'; + if(file_exists($mainCssFile)) $css .= file_get_contents($mainCssFile); + if(is_file($methodCssFile)) $css .= file_get_contents($methodCssFile); + + $cssExtFiles = glob($cssCommonExt . $this->devicePrefix . '*.css'); + if(!empty($cssExtFiles) and is_array($cssExtFiles)) + { + foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile); + } + + $cssExtFiles = glob($cssMethodExt . $this->devicePrefix . '*.css'); + if(!empty($cssExtFiles) and is_array($cssExtFiles)) + { + 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->devicePrefix . '*.css'); + if(!empty($cssExtFiles) and is_array($cssExtFiles)) + { + foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile); + } + + $cssExtFiles = glob($cssMethodExt . $this->devicePrefix . '*.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 + * @param string $methodName + * @access public + * @return string + */ + public function getJS($moduleName, $methodName) + { + $moduleName = strtolower(trim($moduleName)); + $methodName = strtolower(trim($methodName)); + + $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->devicePrefix . 'common.js'; + $methodJsFile = $modulePath . 'js' . DS . $this->devicePrefix . $methodName . '.js'; + if(file_exists($mainJsFile)) $js .= file_get_contents($mainJsFile); + if(is_file($methodJsFile)) $js .= file_get_contents($methodJsFile); + + $jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js'); + if(!empty($jsExtFiles) and is_array($jsExtFiles)) + { + foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile); + } + + $jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.js'); + if(!empty($jsExtFiles) and is_array($jsExtFiles)) + { + 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->devicePrefix . '*.js'); + if(!empty($jsExtFiles) and is_array($jsExtFiles)) + { + foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile); + } + + $jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.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. + * @param mixed $value the value. + * @access public + * @return void + */ + public function assign($name, $value) + { + $this->view->$name = $value; + } + + /** + * 将之前打算输出的内容清空。 + * Clear the output. + * + * @access public + * @return void + */ + public function clear() + { + $this->output = ''; + } + + /** + * 根据请求的视图类型,生成输出内容。 + * Parse view file. + * + * @param string $moduleName module name, if empty, use current module. + * @param string $methodName method name, if empty, use current method. + * @access public + * @return string the parsed result. + */ + public function parse($moduleName = '', $methodName = '') + { + if(empty($moduleName)) $moduleName = $this->moduleName; + if(empty($methodName)) $methodName = $this->methodName; + + if($this->viewType == 'json') + { + $this->parseJSON($moduleName, $methodName); + } + else + { + $this->parseDefault($moduleName, $methodName); + } + return $this->output; + } + + /** + * 请求为json格式的处理逻辑。 + * Parse json format. + * + * @param string $moduleName module name + * @param string $methodName method name + * @access public + * @return void + */ + public function parseJSON($moduleName, $methodName) + { + unset($this->view->app); + unset($this->view->config); + unset($this->view->lang); + unset($this->view->header); + unset($this->view->position); + unset($this->view->moduleTree); + + $output['status'] = is_object($this->view) ? 'success' : 'fail'; + $output['data'] = json_encode($this->view); + $output['md5'] = md5(json_encode($this->view)); + $this->output = json_encode($output); + } + + /** + * 其他请求格式的处理逻辑,输出视图文件的内容。 + * Parse default html format. + * + * @param string $moduleName module name + * @param string $methodName method name + * @access public + * @return void + */ + public function parseDefault($moduleName, $methodName) + { + /* Set the view file. Fix it for php7. */ + $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($js) $this->view->pageJS = $js; + + /* Change the dir to the view file to keep the relative pathes work. */ + $currentPWD = getcwd(); + chdir(dirname($viewFile)); + + extract((array)$this->view); + ob_start(); + include $viewFile; + if(isset($hookFiles)) foreach($hookFiles as $hookFile) if(file_exists($hookFile)) include $hookFile; + $this->output .= ob_get_contents(); + ob_end_clean(); + + /* At the end, chang the dir to the previous. */ + chdir($currentPWD); + } + + /** + * 获取一个方法的输出内容,这样我们可以在一个方法里获取其他模块方法的内容。 + * 如果模块名为空,则调用该模块、该方法;如果设置了模块名,调用指定模块指定方法。 + * + * 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. + * @param string $methodName method name. + * @param array $params params. + * @access public + * @return string the parsed html. + */ + 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($appName, $moduleName); + $moduleControlFile = $modulePath . 'control.php'; + $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, $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); + return $output; + } + + /** + * 向浏览器输出内容。 + * Print the content of the view. + * + * @param string $moduleName module name + * @param string $methodName method name + * @access public + * @return void + */ + public function display($moduleName = '', $methodName = '') + { + 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') die(); + + $data = (array) $data; + if(helper::isAjaxRequest()) print(json_encode($data)) && die(helper::removeUTF8Bom(ob_get_clean())); + + /** + * 响应非ajax的请求。 + * Response request not ajax. + **/ + + 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')); + } + die('fail'); + } + } + + /** + * 创建一个模块方法的链接。 + * 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 + * @param string $viewType the view type + * @access public + * @return string the link string. + */ + public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '', $onlybody = false) + { + if(empty($moduleName)) $moduleName = $this->moduleName; + return helper::createLink($moduleName, $methodName, $vars, $viewType, $onlybody); + } + + /** + * 创建当前模块的一个方法链接。 + * Create a link to the inner method of current module. + * + * @param string $methodName method name + * @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2 + * @param string $viewType the view type + * @access public + * @return string the link string. + */ + public function inlink($methodName = 'index', $vars = array(), $viewType = '', $onlybody = false) + { + return helper::createLink($this->moduleName, $methodName, $vars, $viewType, $onlybody); + } + + /** + * 重定向到另一个页面。 + * Location to another page. + * + * @param string $url the target url. + * @access public + * @return void + */ + public function locate($url) + { + header("location: $url"); + exit; + } +} diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php new file mode 100644 index 0000000000..1806819fff --- /dev/null +++ b/framework/base/helper.class.php @@ -0,0 +1,1269 @@ + + * db->user = 'wwccss'; + * helper::setMember('lang', 'db.user', 'chunsheng.wang'); + * ?> + * + * @param string $objName the var name of the object. + * @param string $key the key of the member, can be parent.child. + * @param mixed $value the value to be set. + * @static + * @access public + * @return bool + */ + static public function setMember($objName, $key, $value) + { + global $$objName; + if(!is_object($$objName) or empty($key)) return false; + $key = str_replace('.', '->', $key); + $value = serialize($value); + $code = ("\$${objName}->{$key}=unserialize(<< + * 'value1', 'var2' => 'value2'); + * ?> + * + * @param string $moduleName module name + * @param string $methodName method name + * @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) or key1=value1&key2=value2 + * @param string $viewType the view type + * @param bool $onlybody whether onlybody + * @static + * @access public + * @return string the link string. + */ + static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlybody = false) + { + global $app, $config; + $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); + + /* 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; + } + elseif($viewType == $app->getViewType()) + { + $link .= $moduleName . '/'; + } + else + { + $link .= $moduleName . '.' . $viewType; + } + } + else + { + $link .= "$moduleName{$config->requestFix}$methodName"; + foreach($vars as $value) $link .= "{$config->requestFix}$value"; + $link .= '.' . $viewType; + } + } + else + { + $link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName"; + if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType; + foreach($vars as $key => $value) $link .= "&$key=$value"; + } + + /* 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 != 'GET' ? "?onlybody=yes" : "&onlybody=yes"; + $link .= $onlybody; + } + return $link; + } + + /** + * 引用一个文件,替换内置的include及require方法 + * Import a file instend of include or require. + * + * @param string $file the file to be imported. + * @static + * @access public + * @return bool + */ + static public function import($file) + { + if(!is_file($file)) return false; + static $includedFiles = array(); + if(!isset($includedFiles[$file])) + { + include $file; + $includedFiles[$file] = true; + return true; + } + return true; + } + + /** + * 设置一个模块的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, $appName = '') + { + global $app; + if($appName == '') $appName = $app->getAppName(); + + /* 设置主model文件,扩展文件和路径。 */ + /* Set the main model file, extension path and files. */ + $mainModelFile = $app->getModulePath($appName, $moduleName) . 'model.php'; + $modelExtPaths = $app->getModuleExtPath($appName, $moduleName, 'model'); + + $hookFiles = array(); + $extFiles = array(); + foreach($modelExtPaths as $modelExtPath) + { + if(empty($modelExtPath)) continue; + $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; + $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; + + return $mergedModelFile; + } + + /* If loaded zend opcache module, turn off cache when create tmp model file to avoid the conflics. */ + if(extension_loaded('Zend OPcache')) ini_set('opcache.enable', 0); + + /* Update the cache file. */ + $modelClass = $moduleName . 'Model'; + $extModelClass = 'ext' . $modelClass; + $extTmpModelClass = 'tmpExt' . $modelClass; + $modelLines = "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'); + } + if(!class_exists($extTmpModelClass)) include $tmpMergedModelFile; + + /* Get hook codes need to merge. */ + $hookCodes = array(); + foreach($hookFiles as $hookFile) + { + $fileName = baseName($hookFile); + list($method) = explode('.', $fileName); + $hookCodes[$method][] = self::removeTagsOfPHP($hookFile); + } + + /* Cycle the hook methods and merge hook codes. */ + $hookedMethods = array_keys($hookCodes); + $mainModelCodes = file($mainModelFile); + $mergedModelCodes = file($tmpMergedModelFile); + foreach($hookedMethods as $method) + { + /* Reflection the hooked method to get it's defined position. */ + $methodRelfection = new reflectionMethod($extTmpModelClass, $method); + $definedFile = $methodRelfection->getFileName(); + $startLine = $methodRelfection->getStartLine() . ' '; + $endLine = $methodRelfection->getEndLine() . ' '; + + /* Merge hook codes. */ + $oldCodes = $definedFile == $tmpMergedModelFile ? $mergedModelCodes : $mainModelCodes; + $oldCodes = join("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1)); + $openBrace = strpos($oldCodes, '{'); + $newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . join("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1); + + /* Replace it. */ + if($definedFile == $tmpMergedModelFile) + { + $modelLines = str_replace($oldCodes, $newCodes, $modelLines); + } + else + { + $modelLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $modelLines); + } + } + unlink($tmpMergedModelFile); + + /* Save it. */ + $modelLines = str_replace($extTmpModelClass, $extModelClass, $modelLines); + file_put_contents($mergedModelFile, $modelLines); + + return $mergedModelFile; + } + + /** + * Remove tags of PHP + * + * @param string $fileName + * @static + * @access public + * @return string + */ + static public function removeTagsOfPHP($fileName) + { + $code = trim(file_get_contents($fileName)); + if(strpos($code, '') !== false) $code = rtrim($code, '?>'); + return trim($code); + } + + /** + * 将数组转化成 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. + * @static + * @access public + * @return string the string like IN('a', 'b'). + */ + static public function dbIN($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. + * @static + * @access public + * @return string encoded string. + */ + static public function safe64Encode($string) + { + return strtr(base64_encode($string), '/', '.'); + } + + /** + * 解码base64,先将之前的'.' 转换回'/' + * Decode the string encoded by safe64Encode. + * + * @param string $string the string to decode + * @static + * @access public + * @return string decoded string. + */ + static public function safe64Decode($string) + { + return base64_decode(strtr($string, '.', '/')); + } + + /** + * 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 + * @author hmdker@gmail.com + * @see http://php.net/manual/en/function.mb-detect-encoding.php + * @static + * @access public + * @return bool + */ + static public function isUTF8($string) + { + $c = 0; + $b = 0; + $bits = 0; + $len = strlen($string); + for($i=0; $i<$len; $i++) + { + $c = ord($string[$i]); + if($c > 128) + { + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1) + { + $i++; + $b=ord($string[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + + /** + * 计算两个日期相差的天数,取整 + * Compute the diff days of two date. + * + * @param string $date1 the first date. + * @param string $date2 the sencode date. + * @access public + * @return int the diff of the two days. + */ + static public function diffDate($date1, $date2) + { + return round((strtotime($date1) - strtotime($date2)) / 86400, 0); + } + + /** + * 获取当前时间,使用common语言文件定义的DT_DATETIME1常量 + * Get now time use the DT_DATETIME1 constant defined in the lang file. + * + * @access public + * @return datetime now + */ + static public function now() + { + return date(DT_DATETIME1); + } + + /** + * 获取当前日期,使用common语言文件定义的DT_DATE1常量 + * Get today according to the DT_DATE1 constant defined in the lang file. + * + * @access public + * @return date today + */ + static public function today() + { + return date(DT_DATE1); + } + + /** + * 获取当前日期,使用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 + * @return bool + */ + static public function isZeroDate($date) + { + return substr($date, 0, 4) == '0000'; + } + + /** + * 列出目录中符合该正则表达式的文件 + * Get files match the pattern under one directory. + * + * @access public + * @return array the files match the pattern + */ + static public function ls($dir, $pattern = '') + { + if(empty($dir)) return array(); + + $files = array(); + $dir = realpath($dir); + if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern); + return empty($files) ? array() : $files; + } + + /** + * 切换目录 + * Change directory. + * + * @param string $path + * @static + * @access public + * @return void + */ + static function cd($path = '') + { + static $cwd = ''; + if($path) $cwd = getcwd(); + !empty($path) ? chdir($path) : chdir($cwd); + } + + /** + * 去掉UTF8 Bom头 + * Remove UTF8 Bom + * + * @param string $string + * @access public + * @return string + */ + public static function removeUTF8Bom($string) + { + if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3); + return $string; + } + + /** + * 通过域名获取站点代号。 + * 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 + * @access public + * @return bool + */ + public static function isAjaxRequest() + { + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'; + } + + /** + * 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 + * @access public + * @return void + */ + public static function setViewType() + { + global $config, $app; + if($config->requestType != 'GET') + { + $pathInfo = $app->getPathInfo(); + if(!empty($pathInfo)) + { + $dotPos = strrpos($pathInfo, '.'); + if($dotPos) + { + $viewType = substr($pathInfo, $dotPos + 1); + } + else + { + $config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view; + } + } + } + elseif($config->requestType == 'GET') + { + if(isset($_GET[$config->viewVar])) + { + $viewType = $_GET[$config->viewVar]; + } + else + { + /* Set default view when url has not module name. such as only domain. */ + $config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view; + } + } + + 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)) + { + if($item->section and !isset($config2Merge->{$item->section})) $config2Merge->{$item->section} = new stdclass(); + $configItem = $item->section ? $config2Merge->{$item->section} : $config2Merge; + if($item->key) $configItem->{$item->key} = $item->value; + break; + } + + if($record->section and !isset($config2Merge->{$record->section})) $config2Merge->{$record->section} = new stdclass(); + $configItem = $record->section ? $config2Merge->{$record->section} : $config2Merge; + if($record->key) $configItem->{$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 getClientDevice() + { + 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 + * @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) + * @param string $viewType + * @return string the link string. + */ +function inLink($methodName = 'index', $vars = '', $viewType = '') +{ + global $app; + return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType); +} + +/** + * 通过一个静态游标,可以遍历数组 + * Static cycle a array + * + * @param array $items the array to be cycled. + * @return mixed + */ +function cycle($items) +{ + static $i = 0; + if(!is_array($items)) $items = explode(',', $items); + if(!isset($items[$i])) $i = 0; + return $items[$i++]; +} + +/** + * 获取当前时间的Unix时间戳,精确到微妙 + * Get current microtime. + * + * @access public + * @return float current time. + */ +function getTime() +{ + list($usec, $sec) = explode(" ", microtime()); + return ((float)$usec + (float)$sec); +} + +/** + * 打印变量的信息 + * dump a var. + * + * @param mixed $var + * @access public + * @return void + */ +function a($var) +{ + echo ""; + print_r($var); + echo ""; +} + +/** + * 判断是否内外IP。 + * Judge the server ip is local or not. + * + * @access public + * @return void + */ +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 + * @return string + */ +function getWebRoot() +{ + $path = $_SERVER['SCRIPT_NAME']; + if(PHP_SAPI == 'cli') + { + $url = parse_url($_SERVER['argv'][1]); + $path = empty($url['path']) ? '/' : rtrim($url['path'], '/'); + $path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path); + } + + return substr($path, 0, (strrpos($path, '/') + 1)); +} + +/** + * 检查是否是onlybody模式。 + * Check exist onlybody param. + * + * @access public + * @return void + */ +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) +{ + global $config; + if(strpos(htmlspecialchars_decode($value), 'framework->stripXSS) and $config->framework->stripXSS) + { + if(stripos($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/base/model.class.php b/framework/base/model.class.php new file mode 100644 index 0000000000..8ae9e974d9 --- /dev/null +++ b/framework/base/model.class.php @@ -0,0 +1,290 @@ +app. + * 2. set the pathes, config, lang of current module + * + * @param string $appName + * @access public + * @return void + */ + public function __construct($appName = '') + { + global $app, $config, $lang, $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, $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 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 public + * @return string the module name. + */ + public function getModuleName() + { + $parentClass = get_parent_class($this); + $selfClass = get_class($this); + $className = $parentClass == 'model' ? $selfClass : $parentClass; + if($className == 'extensionModel') return 'extension'; + return strtolower(str_ireplace(array('ext', 'Model'), '', $className)); + } + + /** + * 设置全局超级变量。 + * Set the super vars. + * + * @access public + * @return void + */ + public function setSuperVars() + { + $this->post = $this->app->post; + $this->get = $this->app->get; + $this->server = $this->app->server; + $this->cookie = $this->app->cookie; + $this->session = $this->app->session; + $this->global = $this->app->global; + } + + /** + * 加载一个模块的model。加载完成后,使用$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, $appName = '') + { + if(empty($moduleName)) return false; + if(empty($appName)) $appName = $this->appName; + $modelFile = helper::setModelFile($moduleName, $appName); + + if(!helper::import($modelFile)) return false; + $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($appName); + return $this->$moduleName; + } + + /** + * 加载model的class扩展。 + * Load extension class of a model. Saved to $moduleName/ext/model/class/$extensionName.class.php. + * + * @param string $extensionName + * @param string $moduleName + * @access public + * @return void + */ + public function loadExtension($extensionName, $moduleName = '') + { + if(empty($extensionName)) return false; + + /* Set extenson name and extension file. */ + $extensionName = strtolower($extensionName); + $moduleName = $moduleName ? $moduleName : $this->getModuleName(); + $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($this->appName, $moduleName) . 'model.php'); + if(!helper::import($extensionFile)) return false; + + /* Set the extension class name. */ + $extensionClass = $extensionName . ucfirst($moduleName); + if(!class_exists($extensionClass)) return false; + + /* Create an instance of the extension class and return it. */ + $extensionObject = new $extensionClass; + $extensionClass = str_replace('Model', '', $extensionClass); + $this->$extensionClass = $extensionObject; + return $extensionObject; + } + + /** + * 加载DAO。 + * Load DAO. + * + * @access public + * @return void + */ + public function loadDAO() + { + $this->dao = $this->app->loadClass('dao'); + } + + /** + * 删除记录 + * Delete one record. + * + * @param string $table the table name + * @param string $id the id value of the record to be deleted + * @access public + * @return void + */ + public function delete($table, $id) + { + $this->dao->delete()->from($table)->where('id')->eq($id)->exec(); + } +} diff --git a/framework/base/router.class.php b/framework/base/router.class.php new file mode 100644 index 0000000000..1f571d8416 --- /dev/null +++ b/framework/base/router.class.php @@ -0,0 +1,2226 @@ +basePath/framework) + * + * @var string + * @access public + */ + public $frameRoot; + + /** + * 应用类库的根目录($this->appRoot/lib)。 + * The root directory of the app library($this->appRoot/lib). + * + * @var string + * @access public + */ + public $coreLibRoot; + + /** + * 应用程序的根目录。 + * The root directory of the app. + * + * @var string + * @access public + */ + public $appRoot; + + /** + * 临时文件的根目录。 + * The root directory of temp. + * + * @var string + * @access public + */ + public $tmpRoot; + + /** + * 缓存的根目录。 + * The root directory of cache. + * + * @var string + * @access public + */ + 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 public + */ + public $logRoot; + + /** + * 配置文件的根目录。 + * The root directory of config. + * + * @var string + * @access public + */ + public $configRoot; + + /** + * 模块的根目录。 + * The root directory of module. + * + * @var string + * @access public + */ + public $moduleRoot; + + /** + * 主题的根目录。 + * The root directory of theme. + * + * @var string + * @access public + */ + public $themeRoot; + + /** + * 用户使用的语言。 + * The lang of the client user. + * + * @var string + * @access public + */ + public $clientLang; + + /** + * 用户使用的主题。 + * The theme of the client user. + * + * @var string + * @access public + */ + public $clientTheme; + + /** + * 当前模块的control对象。 + * The control object of current module. + * + * @var object + * @access public + */ + public $control; + + /** + * 模块名。 + * The module name + * + * @var string + * @access public + */ + public $moduleName; + + /** + * 当前访问模块的control文件。 + * The control file of the module current visiting. + * + * @var string + * @access public + */ + public $controlFile; + + /** + * 当前访问的方法名。 + * The name of the method current visiting. + * + * @var string + * @access public + */ + public $methodName; + + /** + * 当前方法的扩展文件。 + * The action extension file of current method. + * + * @var string + * @access public + */ + public $extActionFile; + + /** + * 访问的URI。 + * The URI. + * + * @var string + * @access public + */ + public $URI; + + /** + * url地址传递的参数。 + * The params passed in through url. + * + * @var array + * @access public + */ + public $params; + + /** + * 视图类型。 + * The view type. + * + * @var string + * @access public + */ + public $viewType; + + /** + * 全局$config对象。 + * The global $config object. + * + * @var object + * @access public + */ + public $config; + + /** + * 全局$lang对象。 + * The global $lang object. + * + * @var object + * @access public + */ + public $lang; + + /** + * 全局$dbh对象,数据库连接句柄。 + * The global $dbh object, the database connection handler. + * + * @var object + * @access public + */ + public $dbh; + + /** + * 从数据库的句柄。 + * The slave database handler. + * + * @var object + * @access public + */ + public $slaveDBH; + + /** + * $post对象,用于访问$_POST变量。 + * The $post object, used to access the $_POST var. + * + * @var ojbect + * @access public + */ + public $post; + + /** + * $get对象,用于访问$_GET变量。 + * The $get object, used to access the $_GET var. + * + * @var ojbect + * @access public + */ + public $get; + + /** + * $session对象,用于访问$_SESSION变量。 + * The $session object, used to access the $_SESSION var. + * + * @var ojbect + * @access public + */ + public $session; + + /** + * $server对象,用于访问$_SERVER变量。 + * The $server object, used to access the $_SERVER var. + * + * @var ojbect + * @access public + */ + public $server; + + /** + * $cookie对象,用于访问$_COOKIE变量。 + * The $cookie object, used to access the $_COOKIE var. + * + * @var ojbect + * @access public + */ + public $cookie; + + /** + * $global对象,用于访问$_GLOBAL变量。 + * The $global object, used to access the $_GLOBAL var. + * + * @var ojbect + * @access public + */ + public $global; + + /** + * 网站代号 + * The code of current site. + * + * @var string + * @access public + */ + public $siteCode; + + /** + * 客户端设备类型 + * The device type of client. + * + * @var string + * @access public + */ + public $clientDevice; + + /** + * 应用名称 + * 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 compute the appRoot according the $appName + * + * @param string $appName the name of the app + * @param string $appRoot the root path of the app + * @access public + * @return void + */ + public function __construct($appName = 'demo', $appRoot = '') + { + $this->setPathFix(); + $this->setBasePath(); + $this->setFrameRoot(); + $this->setCoreLibRoot(); + $this->setAppRoot($appName, $appRoot); + $this->setTmpRoot(); + $this->setCacheRoot(); + $this->setLogRoot(); + $this->setConfigRoot(); + $this->setModuleRoot(); + $this->setThemeRoot(); + $this->setWwwRoot(); + $this->setDataRoot(); + + $this->setSuperVars(); + $this->loadConfig('common'); + $this->filterSuperVars(); + + $this->setDebug(); + $this->setErrorHandler(); + + $this->connectDB(); + + $this->setTimezone(); + $this->setClientLang(); + $this->loadLang('common'); + $this->setClientTheme(); + + $this->loadClass('front', $static = true); + $this->loadClass('filter', $static = true); + $this->loadClass('dao', $static = true); + } + + /** + * 创建一个应用。 + * Create an application. + * + * + * + * or specify the root path of the app. Thus the app and framework can be seperated. + * + * + * @param string $appName the name of the app + * @param string $appRoot the root path of the app + * @param string $className the name of the router class. When extends a child, you should pass in the child router class name. + * @static + * @access public + * @return object the app object + */ + public static function createApp($appName = 'demo', $appRoot = '', $className = '') + { + if(empty($className)) $className = __CLASS__; + return new $className($appName, $appRoot); + } + + //-------------------- 路径相关方法(Path related methods)--------------------// + + /** + * 设置应用名称 + * Set app name. + * + * @param string $appName + * @access public + * @return void + */ + 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 public + * @return void + */ + public function setBasePath() + { + $this->basePath = realpath(dirname(dirname(dirname(__FILE__)))) . DS; + } + + /** + * 设置框架根目录。 + * Set the frame root. + * + * @access public + * @return void + */ + public function setFrameRoot() + { + $this->frameRoot = $this->basePath . 'framework' . DS; + } + + /** + * 设置应用类库的根目录。 + * Set the app lib root. + * + * @access public + * @return void + */ + public function setCoreLibRoot() + { + $this->coreLibRoot = $this->basePath . 'lib' . DS; + } + + /** + * 设置应用的根目录。 + * Set the app root. + * + * @param string $appName + * @param string $appRoot + * @access public + * @return void + */ + public function setAppRoot($appName = 'demo', $appRoot = '') + { + if(empty($appRoot)) + { + $this->appRoot = $this->basePath . 'app' . DS . $appName . DS; + } + else + { + $this->appRoot = realpath($appRoot) . DS; + } + if(!is_dir($this->appRoot)) $this->triggerError("The app you call not found in {$this->appRoot}", __FILE__, __LINE__, $exit = true); + } + + /** + * 设置临时文件的根目录。 + * Set the tmp root. + * + * @access public + * @return void + */ + public function setTmpRoot() + { + $this->tmpRoot = $this->basePath . 'tmp' . DS; + } + + /** + * 设置缓存的根目录。 + * Set the cache root. + * + * @access public + * @return void + */ + public function setCacheRoot() + { + $this->cacheRoot = $this->tmpRoot . 'cache' . DS; + } + + /** + * 设置log的根目录。 + * Set the log root. + * + * @access public + * @return void + */ + public function setLogRoot() + { + $this->logRoot = $this->tmpRoot . 'log' . DS; + } + + /** + * 设置config配置文件的根目录。 + * Set the config root. + * + * @access public + * @return void + */ + public function setConfigRoot() + { + $this->configRoot = $this->basePath . 'config' . DS; + } + + /** + * 设置模块的根目录。 + * Set the module root. + * + * @access public + * @return void + */ + public function setModuleRoot() + { + $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 public + * @return void + */ + public function setThemeRoot() + { + $this->themeRoot = $this->wwwRoot . 'theme' . DS; + } + + /** + * 过滤超级变量数据 + * Filter superVars. + * + * @access public + * @return void + */ + public function filterSuperVars() + { + if(!empty($_COOKIE)) + { + foreach($_COOKIE as $cookieKey => $cookieValue) + { + if(preg_match('/[^a-zA-Z0-9_\.]/', $cookieKey)) unset($_COOKIE[$cookieKey]); + if(preg_match('/[^a-zA-Z0-9=_\|\- ,`+\/\.%\x7f-\xff]/', $cookieValue)) unset($_COOKIE[$cookieKey]); + } + } + + if(!empty($_FILES)) + { + foreach($_FILES as $varName => $files) + { + if(is_array($files['name'])) + { + foreach($files['name'] as $i => $fileName) + { + $extension = ltrim(strrchr($fileName, '.'), '.'); + if(strrpos($this->config->file->dangers, $extension) !== false) + { + foreach($files as $fileKey => $value) + { + unset($_FILES); + break 2; + } + } + } + } + else + { + $extension = ltrim(strrchr($files['name'], '.'), '.'); + if(strrpos($this->config->file->dangers, $extension) !== false) unset($_FILES); + } + } + } + $_POST = processArrayEvils($_POST); + $_GET = processArrayEvils($_GET); + $_COOKIE = processArrayEvils($_COOKIE); + unset($GLOBALS); + unset($_REQUEST); + } + + /** + * 设置超级变量。 + * Set the super vars. + * + * @access public + * @return void + */ + public function setSuperVars() + { + $this->post = new super('post'); + $this->get = new super('get'); + $this->server = new super('server'); + $this->cookie = new super('cookie'); + $this->session = new super('session'); + $this->global = new super('global'); + } + + /** + * 设置站点代号 + * 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 + */ + public function setDebug() + { + if(!empty($this->config->debug)) error_reporting(E_ALL & ~ E_STRICT); + } + + /** + * 设置错误处理句柄。 + * Set the error handler. + * + * @access public + * @return void + */ + public function setErrorHandler() + { + set_error_handler(array($this, 'saveError')); + register_shutdown_function(array($this, 'shutdown')); + } + + /** + * 根据配置设置当前时区。 + * Set the time zone according to the config. + * + * @access public + * @return void + */ + public function setTimezone() + { + if(isset($this->config->timezone)) date_default_timezone_set($this->config->timezone); + } + + /** + * 获取应用名称 + * Get app name + * + * @access public + * @return string + */ + public function getAppName() + { + return $this->appName; + } + + /** + * 获取$basePath,即基础路径。 + * Get the $basePath var. + * + * @access public + * @return string + */ + public function getBasePath() + { + return $this->basePath; + } + + /** + * 获取$frameRoot,即框架根目录。 + * Get the $frameRoot var. + * + * @access public + * @return string + */ + public function getFrameRoot() + { + return $this->frameRoot; + } + + /** + * 获取$appRoot变量,即应用的根目录。 + * Get the $appRoot var. + * + * @access public + * @return string + */ + public function getAppRoot() + { + return $this->appRoot; + } + + /** + * 获取$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 + */ + public function getTmpRoot() + { + return $this->tmpRoot; + } + + /** + * 获取$cacheRoot变量,即缓存文件的根目录。 + * Get the $cacheRoot var. + * + * @access public + * @return string + */ + public function getCacheRoot() + { + return $this->cacheRoot; + } + + /** + * 获取$logRoot变量,即日志文件的根目录。 + * Get the $logRoot var. + * + * @access public + * @return string + */ + public function getLogRoot() + { + return $this->logRoot; + } + + /** + * 获取$configRoot变量,即配置文件的根目录。 + * Get the $configRoot var. + * + * @access public + * @return string + */ + public function getConfigRoot() + { + return $this->configRoot; + } + + /** + * 获取$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 getDataRoot() + { + return $this->dataRoot; + } + + /** + * 获取$themeRoot变量,即主题的根目录。 + * Get the $themeRoot var. + * + * @access public + * @return string + */ + public function getThemeRoot() + { + return $this->themeRoot; + } + + //------ 客户端环境有关的函数(Client environment related functions) ------// + + /** + * 根据用户浏览器的语言设置和服务器配置,选择显示的语言。 + * 优先级:$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 + * @return void + */ + public function setClientLang($lang = '') + { + if(!empty($lang)) + { + $this->clientLang = $lang; + } + elseif(isset($_SESSION['lang'])) + { + $this->clientLang = $_SESSION['lang']; + } + elseif(isset($_COOKIE['lang'])) + { + $this->clientLang = $_COOKIE['lang']; + } + elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + { + if(strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], ',') === false) + { + $this->clientLang = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + } + else + { + $this->clientLang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], ',')); + } + + /* Fix clientLang for ie >= 10. https://www.drupal.org/node/365615. */ + if(stripos($this->clientLang, 'hans')) $this->clientLang = 'zh-cn'; + if(stripos($this->clientLang, 'hant')) $this->clientLang = 'zh-tw'; + } + if(!empty($this->clientLang)) + { + $this->clientLang = strtolower($this->clientLang); + if(!isset($this->config->langs[$this->clientLang])) $this->clientLang = $this->config->default->lang; + } + else + { + $this->clientLang = $this->config->default->lang; + } + setcookie('lang', $this->clientLang, $this->config->cookieLife, $this->config->webRoot); + if(!isset($_COOKIE['lang'])) $_COOKIE['lang'] = $this->clientLang; + } + + /** + * 获取$clientLang变量,即客户端的语言。 + * Get the $clientLang var. + * + * @access public + * @return string + */ + public function getClientLang() + { + return $this->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 + * @access public + * @return void + */ + public function setClientTheme($theme = '') + { + if(!empty($theme)) + { + $this->clientTheme = $theme; + } + elseif(isset($_COOKIE['theme'])) + { + $this->clientTheme = $_COOKIE['theme']; + } + elseif(isset($this->config->client->theme)) + { + $this->clientTheme = $this->config->client->theme; + } + + if(!empty($this->clientTheme)) + { + $this->clientTheme = strtolower($this->clientTheme); + if(!isset($this->config->themes[$this->clientTheme])) $this->clientTheme = $this->config->default->theme; + } + else + { + $this->clientTheme = $this->config->default->theme; + } + setcookie('theme', $this->clientTheme, $this->config->cookieLife, $this->config->webRoot); + if(!isset($_COOKIE['theme'])) $_COOKIE['theme'] = $this->clientTheme; + } + + /** + * 获取$clientTheme变量。 + * Get the $clientTheme var. + * + * @access public + * @return string + */ + public function getClientTheme() + { + return $this->config->webRoot . 'theme/' . $this->clientTheme . '/'; + } + + /** + * 获取$webRoot,即应用的路径。 + * Get the $webRoot var. + * + * @access public + * @return string + */ + public function getWebRoot() + { + return $this->config->webRoot; + } + + //-------------------- 请求相关的方法(Request related methods) --------------------// + + /** + * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。 + * The entrance of parseing request. According to the requestType, call related methods. + * + * @access public + * @return void + */ + public function parseRequest() + { + 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(); + } + elseif($this->config->requestType == 'GET') + { + $this->parseGET(); + $this->setRouteByGET(); + } + else + { + $this->triggerError("The request type {$this->config->requestType} not supported", __FILE__, __LINE__, $exit = true); + } + } + + /** + * PATH_INFO方式解析,获取$URI和$viewType。 + * Parse PATH_INFO, get the $URI and $viewType. + * + * @access public + * @return void + */ + public function parsePathInfo() + { + $pathInfo = $this->getPathInfo(); + if(trim($pathInfo, '/') == trim($this->config->webRoot, '/')) $pathInfo = ''; + if(!empty($pathInfo)) + { + $dotPos = strrpos($pathInfo, '.'); + if($dotPos) + { + $this->URI = substr($pathInfo, 0, $dotPos); + $this->viewType = substr($pathInfo, $dotPos + 1); + if(strpos($this->config->views, ',' . $this->viewType . ',') === false) + { + $this->viewType = $this->config->default->view; + } + } + else + { + $this->URI = $pathInfo; + $this->viewType = $this->config->default->view; + } + } + else + { + $this->viewType = $this->config->default->view; + } + } + + /** + * 从$_SERVER或者$_ENV全局变量根据pathinfo变量名获取$PATH_INFO值。 + * PATH_INFO的变量名几乎都是'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() + { + 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 public + * @return void + */ + 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; + } + else + { + $this->viewType = $this->config->default->view; + } + $this->URI = $_SERVER['REQUEST_URI']; + } + + /** + * 获取$URL。 + * Get the $URL. + * + * @param bool $full true, the URI contains the webRoot, else only hte URI. + * @access public + * @return string + */ + public function getURI($full = false) + { + if($full and $this->config->requestType == 'PATH_INFO') + { + if($this->URI) return $this->config->webRoot . $this->URI . '.' . $this->viewType; + return $this->config->webRoot; + } + return $this->URI; + } + + /** + * 获取$vewType变量。 + * Get the $viewType var. + * + * @access public + * @return string + */ + public function getViewType() + { + return $this->viewType; + } + + //-------------------- 路由相关方法(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 loaded. + * + * @access public + * @return object|bool the common control object or false if not exits. + */ + public function loadCommon() + { + $this->setModuleName('common'); + $commonModelFile = helper::setModelFile('common'); + if(file_exists($commonModelFile)) + { + helper::import($commonModelFile); + if(class_exists('extcommonModel')) + { + return new extcommonModel(); + } + elseif(class_exists('commonModel')) + { + return new commonModel(); + } + else + { + return false; + } + } + } + + /** + * 设置要被调用的模块名。 + * Set the name of the module to be called. + * + * @param string $moduleName the module name + * @access public + * @return void + */ + public function setModuleName($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 没有找到该控制器文件的情况:如果该参数为true,则终止程序;如果为false,则打印错误日志 + * If control file not foundde, how to do. True, die the whole app. false, log error. + * @access public + * @return bool + */ + public function setControlFile($exitIfNone = true) + { + $this->controlFile = $this->moduleRoot . $this->moduleName . DS . 'control.php'; + if(!is_file($this->controlFile)) + { + $this->triggerError("the control file $this->controlFile not found.", __FILE__, __LINE__, $exitIfNone); + return false; + } + return true; + } + + /** + * 设置要被调用的方法名。 + * Set the name of the method calling. + * + * @param string $methodName + * @access public + * @return void + */ + public function setMethodName($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($appName = '', $moduleName = '') + { + if($moduleName == '') $moduleName = $this->moduleName; + 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($appName, $moduleName, $ext) + { + 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 + * @return bool + */ + public function setActionExtFile() + { + $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. + * + * @access public + * @return void + */ + public function setRouteByPathInfo() + { + if(!empty($this->URI)) + { + /* + * 根据$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. + **/ + else + { + $this->setModuleName($this->URI); + $this->setMethodName($this->config->default->method); + } + } + else + { + $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. + * + * @access public + * @return void + */ + public function setRouteByGET() + { + $moduleName = isset($_GET[$this->config->moduleVar]) ? strtolower($_GET[$this->config->moduleVar]) : $this->config->default->module; + $methodName = isset($_GET[$this->config->methodVar]) ? strtolower($_GET[$this->config->methodVar]) : $this->config->default->method; + $this->setModuleName($moduleName); + $this->setControlFile(); + $this->setMethodName($methodName); + } + + /** + * 加载一个模块: + * 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. + * 4. call the method by call_user_function_array + * + * @access public + * @return bool|object if the module object of die. + */ + public function loadModule() + { + $moduleName = $this->moduleName; + $methodName = $this->methodName; + + /* + * 引入该模块的control文件。 + * Include the control file of the module. + **/ + $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile; + chdir(dirname($file2Included)); + include $file2Included; + + /* + * 设置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); + + /* + * 创建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; + + /* include default value for module*/ + $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php"); + if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file; + + /* + * 使用反射机制获取函数参数的默认值。 + * 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])) + { + $default = $paramDefaultValue[$className][$methodName][$name]; + } + elseif($param->isDefaultValueAvailable()) + { + $default = $param->getDefaultValue(); + } + + $defaultParams[$name] = $default; + } + + /** + * 根据PATH_INFO或者GET方式设置请求的参数。 + * Set params according PATH_INFO or GET. + */ + if($this->config->requestType != 'GET') + { + $this->setParamsByPathInfo($defaultParams); + } + else + { + $this->setParamsByGET($defaultParams); + } + + /* 调用该方法 Call the method. */ + call_user_func_array(array($module, $methodName), $this->params); + return $module; + } + + /** + * 设置请求的参数(PATH_INFO 方式)。 + * Set the params by PATH_INFO. + * + * @param array $defaultParams the default settings of the params. + * @access public + * @return void + */ + public function setParamsByPathInfo($defaultParams = array()) + { + /* 分割URI。 Spit the URI. */ + $items = explode($this->config->requestFix, $this->URI); + $itemCount = count($items); + $params = array(); + + /** + * 前两项为模块名和方法名,参数从下标2开始。 + * 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); + } + + $this->params = $this->mergeParams($defaultParams, $params); + } + + /** + * 设置请求的参数(GET 方式)。 + * Set the params by GET. + * + * @param array $defaultParams the default settings of the params. + * @access public + * @return void + */ + 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]); + unset($_GET[$this->config->viewVar]); + unset($_GET[$this->config->sessionVar]); + $this->params = $this->mergeParams($defaultParams, $_GET); + } + + /** + * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。 + * 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 public + * @return array the merged params. + */ + public function mergeParams($defaultParams, $passedParams) + { + /* Check params from URL. */ + foreach($passedParams as $param => $value) + { + if(preg_match('/[^a-zA-Z0-9_\.]/', $param)) die('Bad Request!'); + if(preg_match('/[^a-zA-Z0-9=_,`#+\/\.%\|\x7f-\xff]/', trim($value))) die('Bad Request!'); + } + + unset($passedParams['onlybody']); + $passedParams = array_values($passedParams); + $i = 0; + foreach($defaultParams as $key => $defaultValue) + { + if(isset($passedParams[$i])) + { + $defaultParams[$key] = strip_tags(urldecode($passedParams[$i])); + } + else + { + 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 + * @return string + */ + public function getModuleName() + { + return $this->moduleName; + } + + /** + * 获取$controlFile变量。 + * Get the $controlFile var. + * + * @access public + * @return string + */ + public function getControlFile() + { + return $this->controlFile; + } + + /** + * 获取$methodName变量。 + * Get the $methodName var. + * + * @access public + * @return string + */ + public function getMethodName() + { + return $this->methodName; + } + + /** + * 获取$param变量。 + * Get the $param var. + * + * @access public + * @return string + */ + public function getParams() + { + return $this->params; + } + + //-------------------- 常用的工具方法(Tool methods) ------------------// + + /** + * 从类库中加载一个类文件。 + * + * Load a class file. + * + * @param string $className the class name + * @param bool $static statis class or not + * @access public + * @return object|bool the instance of the class or just true. + */ + public function loadClass($className, $static = false) + { + $className = strtolower($className); + + /* 搜索$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($static) return true; + + /* 实例化该类(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(); + return $$className; + } + + /** + * 加载模块的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 string $appName app name + * @param bool $exitIfNone exit or not + * @access public + * @return object|bool the config object or false. + */ + public function loadConfig($moduleName, $appName = '', $exitIfNone = true) + { + global $config; + if(!is_object($config)) $config = new config(); + if(!isset($config->$moduleName)) $config->$moduleName = new stdclass(); + + $extConfigFiles = array(); + + /* + * 设置主配置文件和扩展配置文件。 + * 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($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) */ + if(!is_file($mainConfigFile)) + { + if($exitIfNone) self::triggerError("config file $mainConfigFile not found", __FILE__, __LINE__, true); + if(empty($extConfigFiles) and !isset($config->system->$moduleName)) return false; // and no extension file or extension in db, exit. + $configFiles = $extConfigFiles; + } + else + { + $configFiles = array_merge(array($mainConfigFile), $extConfigFiles); + } + + static $loadedConfigs = array(); + foreach($configFiles as $configFile) + { + if(in_array($configFile, $loadedConfigs)) continue; + include $configFile; + $loadedConfigs[] = $configFile; + } + + if($moduleName == 'common') + { + $this->config = $config; + $this->setSiteCode(); + if(!isset($config->site)) $config->site = new stdclass(); + $config->site->code = $this->siteCode; + + if(!empty($config->multi)) + { + $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 + * @return void + */ + public function exportConfig() + { + $view = new stdclass(); + $view->version = $this->config->version; + $view->requestType = $this->config->requestType; + $view->requestFix = $this->config->requestFix; + $view->moduleVar = $this->config->moduleVar; + $view->methodVar = $this->config->methodVar; + $view->viewVar = $this->config->viewVar; + $view->sessionVar = $this->config->sessionVar; + + $this->session->set('rand', mt_rand(0, 10000)); + $view->sessionName = session_name(); + $view->sessionID = session_id(); + $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, $appName = '') + { + $modulePath = $this->getModulePath($appName, $moduleName); + $mainLangFile = $modulePath . 'lang' . DS . $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 include). */ + if(!is_file($mainLangFile)) + { + if(empty($extLangFiles)) return false; // 没有扩展文件,返回false(Return false if no extension file). + $langFiles = $extLangFiles; + } + else + { + $langFiles = array_merge(array($mainLangFile), $extLangFiles); + } + + global $lang; + if(!is_object($lang)) $lang = new language(); + + static $loadedLangs = array(); + foreach($langFiles as $langFile) + { + if(in_array($langFile, $loadedLangs)) continue; + include $langFile; + $loadedLangs[] = $langFile; + } + + /* Merge from the db lang. */ + if($moduleName != 'common' and isset($lang->db->custom[$moduleName])) + { + foreach($lang->db->custom[$moduleName] as $section => $fields) + { + foreach($fields as $key => $value) + { + unset($lang->{$moduleName}->{$section}[$key]); + $lang->{$moduleName}->{$section}[$key] = $value; + } + } + } + + $this->lang = $lang; + return $lang; + } + + /** + * 连接数据库。 + * Connect to database. + * + * @access public + * @return void + */ + public function connectDB() + { + global $config, $dbh, $slaveDBH; + if(!isset($config->installed) or !$config->installed) return; + + if(isset($config->db->host)) $this->dbh = $dbh = $this->connectByPDO($config->db); + if(isset($config->slaveDB->host)) $this->slaveDBH = $slaveDBH = $this->connectByPDO($config->slaveDB); + } + + /** + * 使用PDO连接数据库。 + * Connect database by PDO. + * + * @param object $params the database params. + * @access public + * @return object|bool + */ + 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; + if($params->driver == 'mysql') + { + $dsn = "mysql:host={$params->host}; port={$params->port}; dbname={$params->name}"; + } + try + { + $dbh = new PDO($dsn, $params->user, $params->password, array(PDO::ATTR_PERSISTENT => $params->persistant)); + $dbh->exec("SET NAMES {$params->encoding}"); + + /* + * 如果系统是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; + + $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + if(isset($params->strictMode) and $params->strictMode == false) $dbh->exec("SET @@sql_mode= ''"); + if(isset($params->emulatePrepare)) $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $params->emulatePrepare); + if(isset($params->bufferQuery)) $dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $params->bufferQuery); + + return $dbh; + } + catch (PDOException $exception) + { + self::triggerError($exception->getMessage(), __FILE__, __LINE__, $exit = true); + } + } + + //-------------------- 错误处理方法(Error methods) ------------------// + + /** + * 程序停止时执行的函数。 + * The shutdown handler. + * + * @access public + * @return void + */ + public function shutdown() + { + /* 如果debug模式开启,保存sql语句(If debug on, save sql queries) */ + if(!empty($this->config->debug)) $this->saveSQL(); + + /* + * 发现错误,保存到日志中。 + * 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']); + } + + /** + * 触发一个错误。 + * 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 + * @access public + * @return void + */ + public function triggerError($message, $file, $line, $exit = false) + { + /* 设置错误信息(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(); + extract($trace[0]); + extract($trace[1]); + $log .= ", last called by $file on line $line through function $function.\n"; + + /* 触发错误(Trigger the error) */ + trigger_error($log, $exit ? E_USER_ERROR : E_USER_WARNING); + } + + /** + * 保存错误信息。 + * Save error info. + * + * @param int $level + * @param string $message + * @param string $file + * @param int $line + * @access public + * @return void + */ + public function saveError($level, $message, $file, $line) + { + if(empty($this->config->debug)) return true; + + /* + * 删除设定时间之前的日志。 + * Delete the log before the set time. + **/ + if(mt_rand(0, 1) == 1) + { + $logDays = isset($this->config->framework->logDays) ? $this->config->framework->logDays : 14; + $dayTime = time() - $logDays * 24 * 3600; + foreach(glob($this->getLogRoot() . '*') as $logFile) + { + if(filemtime($logFile) <= $dayTime) unlink($logFile); + } + } + + /* + * 忽略该错误:Redefining already defined constructor。 + * Skip the error: Redefining already defined constructor. + **/ + if(strpos($message, 'Redefining') !== false) return true; + + /* + * 设置错误信息。 + * 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(!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) */ + $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); + + /* + * 如果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) + { + $cmd = "vim +$line $file"; + $size = strlen($cmd); + echo "
$message: ";
+                echo "
"; + } + } + + /* + * 如果是严重错误,停止程序。 + * 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(); + if(PHP_SAPI == 'cli') die($errorLog); + + $htmlError = ""; + $htmlError .= "" . nl2br($errorLog) . ""; + die($htmlError); + } + } + + /** + * 保存sql语句。 + * Save the sql. + * + * @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'; + if(!is_file($sqlLog)) file_put_contents($sqlLog, "\n"); + + $fh = @fopen($sqlLog, 'a'); + if(!$fh) return false; + fwrite($fh, date('Ymd H:i:s') . ": " . $this->getURI() . "\n"); + foreach(dao::$querys as $query) fwrite($fh, " $query\n"); + fwrite($fh, "\n"); + fclose($fh); + } +} + +/** + * config类。 + * The config class. + * + * @package framework + */ +class config +{ + /** + * 设置成员变量,成员可以是'db.user'类似的格式。 + * Set the value of a member. the member can be the format like db.user. + * + * + * set('db.user', 'wwccss'); + * ?> + * + * @param string $key the key of the member + * @param mixed $value the value + * @access public + * @return void + */ + public function set($key, $value) + { + helper::setMember('config', $key, $value); + } +} + +/** + * lang类。 + * The lang class. + * + * @package framework + */ +class language +{ + /** + * 设置成员变量,成员可以是'db.user'类似的格式。 + * Set the value of a member. the member can be the foramt like db.user. + * + * + * set('version', '1.0); + * ?> + * + * @param string $key 成员的键名,可以是father.child的形式。 + * the key of the member, can be father.child + * @param mixed $value the value + * @access public + * @return void + */ + public function set($key, $value) + { + helper::setMember('lang', $key, $value); + } + + /** + * 显示一个成员的值。 + * Show a member. + * + * @param object $obj the object + * @param string $key the key + * @access public + * @return void + */ + public function show($obj, $key) + { + $obj = (array)$obj; + echo isset($obj[$key]) ? $obj[$key] : ''; + } +} + +/** + * 超级对象类,转化超级全局变量。 + * The super object class. + * + * @package framework + */ +class super +{ + /** + * 构造函数,设置超级变量名。 + * Construct, set the var scope. + * + * @param string $scope the scope, can be server, post, get, cookie, session, global + * @access public + * @return void + */ + public function __construct($scope) + { + $this->scope = $scope; + } + + /** + * 设置超级变量的成员值。 + * Set one member value. + * + * @param string the key + * @param mixed $value the value + * @access public + * @return void + */ + public function set($key, $value) + { + if($this->scope == 'post') + { + $_POST[$key] = $value; + } + elseif($this->scope == 'get') + { + $_GET[$key] = $value; + } + elseif($this->scope == 'server') + { + $_SERVER[$key] = $value; + } + elseif($this->scope == 'cookie') + { + $_COOKIE[$key] = $value; + } + elseif($this->scope == 'session') + { + $_SESSION[$key] = $value; + } + elseif($this->scope == 'env') + { + $_ENV[$key] = $value; + } + elseif($this->scope == 'global') + { + $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. + */ + public function __get($key) + { + if($this->scope == 'post') + { + if(isset($_POST[$key])) return $_POST[$key]; + return false; + } + elseif($this->scope == 'get') + { + if(isset($_GET[$key])) return $_GET[$key]; + return false; + } + elseif($this->scope == 'server') + { + if($key == 'ajax') return isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? true : false; + if(isset($_SERVER[$key])) return $_SERVER[$key]; + $key = strtoupper($key); + if(isset($_SERVER[$key])) return $_SERVER[$key]; + return false; + } + elseif($this->scope == 'cookie') + { + if(isset($_COOKIE[$key])) return $_COOKIE[$key]; + return false; + } + elseif($this->scope == 'session') + { + if(isset($_SESSION[$key])) return $_SESSION[$key]; + return false; + } + elseif($this->scope == 'env') + { + if(isset($_ENV[$key])) return $_ENV[$key]; + return false; + } + elseif($this->scope == 'global') + { + if(isset($GLOBALS[$key])) return $GLOBALS[$key]; + return false; + } + else + { + return false; + } + } + + /** + * 打印变量的详细结构。 + * Print the structure. + * + * @access public + * @return void + */ + public function a() + { + if($this->scope == 'post') a($_POST); + if($this->scope == 'get') a($_GET); + if($this->scope == 'server') a($_SERVER); + if($this->scope == 'cookie') a($_COOKIE); + if($this->scope == 'session') a($_SESSION); + if($this->scope == 'env') a($_ENV); + if($this->scope == 'global') a($GLOBALS); + } +} diff --git a/framework/control.class.php b/framework/control.class.php index 42f852aaed..6bc6b8a6e8 100644 --- a/framework/control.class.php +++ b/framework/control.class.php @@ -1,825 +1,5 @@ app. - * 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 = '', $appName = '') - { - /* - * 将全局变量设为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(); - - /* - * 设置当前模块,读取该模块的model类。 - * Load the model file auto. - **/ - $this->setModuleName($moduleName); - $this->setMethodName($methodName); - $this->loadModel($this->moduleName, $appName); - $this->setViewPrefix(); - - /* - * 初始化$view视图类。 - * Init the view vars. - **/ - $this->view = new stdclass(); - $this->view->app = $app; - $this->view->lang = $lang; - $this->view->config = $config; - $this->view->common = $common; - $this->view->title = ''; - - /* - * 设置超级变量,从$app引用过来。 - * Set super vars. - **/ - $this->setSuperVars(); - } - - //-------------------- Model相关方法(Model related methods) --------------------// - - /* - * 设置模块名。 - * Set the module name. - * - * @param string $moduleName 模块名,如果为空,则从$app中获取 The module name, if empty, get it from $app. - * @access private - * @return void - */ - private function setModuleName($moduleName = '') - { - $this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName(); - } - - /* Set the method name. - * 设置方法名。 - * - * @param string $methodName 方法名,如果为空,则从$app中获取 The method name, if empty, get it from $app. - * @access private - * @return void - */ - private function setMethodName($methodName = '') - { - $this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName(); - } - - /** - * 加载指定模块的model文件。 - * Load the model file of one module. - * - * @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 如果没有model文件,返回false,否则返回model对象。 If no model file, return false. Else return the model object. - */ - public function loadModel($moduleName = '', $appName = '') - { - if(empty($moduleName)) $moduleName = $this->moduleName; - if(empty($appName)) $appName = $this->appName; - $modelFile = helper::setModelFile($moduleName, $appName); - - /* - * 如果没有model文件,尝试加载config配置信息。 - * If no model file, try load config. - */ - if(!helper::import($modelFile)) - { - $this->app->loadConfig($moduleName, $appName, false); - $this->app->loadLang($moduleName, $appName); - $this->dao = new dao(); - return false; - } - - $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($appName); - $this->dao = $this->$moduleName->dao; - return $this->$moduleName; - } - - /** - * 设置超级全局变量,$app已经设置过了,直接引用。 - * Set the super vars. - * - * @access protected - * @return void - */ - protected function setSuperVars() - { - $this->post = $this->app->post; - $this->get = $this->app->get; - $this->server = $this->app->server; - $this->session = $this->app->session; - $this->cookie = $this->app->cookie; - $this->global = $this->app->global; - } - - /** - * 为客户端是PC还是移动设备,设置视图文件前缀名。 - * Set the prefix of view file for mobile or PC. - * - * @access public - * @return void - */ - public function setViewPrefix() - { - $this->viewPrefix = ''; - if(isset($this->config->viewPrefix[$this->viewType])) $this->viewPrefix = $this->config->viewPrefix[$this->viewType]; - } - - /** - * 设置客户端的设备类型 - * 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 - * @param string $methodName method name - * @access private - * @return string the view file - */ - public function setViewFile($moduleName, $methodName) - { - $moduleName = strtolower(trim($moduleName)); - $methodName = strtolower(trim($methodName)); - - $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. - **/ - $mainViewFile = $modulePath . 'view' . DS . $this->viewPrefix . $methodName . '.' . $viewType . '.php'; - - /* 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 - * @access public - * @return string|bool If extension view file exists, return the path. Else return fasle. - */ - public function getExtViewFile($viewFile) - { - 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)) - { - helper::cd($extPath); - return $extViewFile; - } - return false; - } - - /** - * 获取方法的css内容,common.css + 该方法的css。 - * Get css code for a method. - * - * @param string $moduleName - * @param string $methodName - * @access private - * @return string - */ - private function getCSS($moduleName, $methodName) - { - $moduleName = strtolower(trim($moduleName)); - $methodName = strtolower(trim($methodName)); - - $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); - - $cssExtFiles = glob($cssCommonExt . $this->viewPrefix . '*.css'); - if(!empty($cssExtFiles) and is_array($cssExtFiles)) - { - 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); - } - 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)) - { - 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 - * @param string $methodName - * @access private - * @return string - */ - private function getJS($moduleName, $methodName) - { - $moduleName = strtolower(trim($moduleName)); - $methodName = strtolower(trim($methodName)); - - $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'; - $methodJsFile = $modulePath . 'js' . DS . $this->viewPrefix . $methodName . '.js'; - if(file_exists($mainJsFile)) $js .= file_get_contents($mainJsFile); - if(is_file($methodJsFile)) $js .= file_get_contents($methodJsFile); - - $jsExtFiles = glob($jsCommonExt . $this->viewPrefix . '*.js'); - if(!empty($jsExtFiles) and is_array($jsExtFiles)) - { - 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); - } - - 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)) - { - 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. - * @param mixed $value the value. - * @access public - * @return void - */ - public function assign($name, $value) - { - $this->view->$name = $value; - } - - /** - * 将之前打算输出的内容清空。 - * Clear the output. - * - * @access public - * @return void - */ - public function clear() - { - $this->output = ''; - } - - /** - * 根据请求的视图类型,生成输出内容。 - * Parse view file. - * - * @param string $moduleName module name, if empty, use current module. - * @param string $methodName method name, if empty, use current method. - * @access public - * @return string the parsed result. - */ - public function parse($moduleName = '', $methodName = '') - { - if(empty($moduleName)) $moduleName = $this->moduleName; - if(empty($methodName)) $methodName = $this->methodName; - - if($this->viewType == 'json') - { - $this->parseJSON($moduleName, $methodName); - } - else - { - $this->parseDefault($moduleName, $methodName); - } - return $this->output; - } - - /** - * 请求为json格式的处理逻辑。 - * Parse json format. - * - * @param string $moduleName module name - * @param string $methodName method name - * @access private - * @return void - */ - private function parseJSON($moduleName, $methodName) - { - unset($this->view->app); - unset($this->view->config); - unset($this->view->lang); - unset($this->view->header); - unset($this->view->position); - unset($this->view->moduleTree); - - $output['status'] = is_object($this->view) ? 'success' : 'fail'; - $output['data'] = json_encode($this->view); - $output['md5'] = md5(json_encode($this->view)); - $this->output = json_encode($output); - } - - /** - * 其他请求格式的处理逻辑,输出视图文件的内容。 - * Parse default html format. - * - * @param string $moduleName module name - * @param string $methodName method name - * @access private - * @return void - */ - private function parseDefault($moduleName, $methodName) - { - /* Set the view file. */ - $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($js) $this->view->pageJS = $js; - - /* Change the dir to the view file to keep the relative pathes work. */ - $currentPWD = getcwd(); - chdir(dirname($viewFile)); - - extract((array)$this->view); - ob_start(); - include $viewFile; - if(isset($hookFiles)) foreach($hookFiles as $hookFile) if(file_exists($hookFile)) include $hookFile; - $this->output .= ob_get_contents(); - ob_end_clean(); - - /* At the end, chang the dir to the previous. */ - chdir($currentPWD); - } - - /** - * 获取一个方法的输出内容,这样我们可以在一个方法里获取其他模块方法的内容。 - * 如果模块名为空,则调用该模块、该方法;如果设置了模块名,调用指定模块指定方法。 - * - * 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. - * @param string $methodName method name. - * @param array $params params. - * @access public - * @return string the parsed html. - */ - 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($appName, $moduleName); - $moduleControlFile = $modulePath . 'control.php'; - $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, $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); - return $output; - } - - /** - * 向浏览器输出内容。 - * Print the content of the view. - * - * @param string $moduleName module name - * @param string $methodName method name - * @access public - * @return void - */ - public function display($moduleName = '', $methodName = '') - { - 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') - { - $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 - * @param string $viewType the view type - * @access public - * @return string the link string. - */ - public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '', $onlybody = false) - { - if(empty($moduleName)) $moduleName = $this->moduleName; - return helper::createLink($moduleName, $methodName, $vars, $viewType, $onlybody); - } - - /** - * 创建当前模块的一个方法链接。 - * Create a link to the inner method of current module. - * - * @param string $methodName method name - * @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2 - * @param string $viewType the view type - * @access public - * @return string the link string. - */ - public function inlink($methodName = 'index', $vars = array(), $viewType = '', $onlybody = false) - { - return helper::createLink($this->moduleName, $methodName, $vars, $viewType, $onlybody); - } - - /** - * 重定向到另一个页面。 - * Location to another page. - * - * @param string $url the target url. - * @access public - * @return void - */ - public function locate($url) - { - header("location: $url"); - exit; - } } diff --git a/framework/helper.class.php b/framework/helper.class.php index 7a18028526..59154192dc 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -1,1306 +1,5 @@ - * db->user = 'wwccss'; - * helper::setMember('lang', 'db.user', 'chunsheng.wang'); - * ?> - * - * @param string $objName the var name of the object. - * @param string $key the key of the member, can be parent.child. - * @param mixed $value the value to be set. - * @static - * @access public - * @return bool - */ - static public function setMember($objName, $key, $value) - { - global $$objName; - if(!is_object($$objName) or empty($key)) return false; - $key = str_replace('.', '->', $key); - $value = serialize($value); - $code = ("\$${objName}->{$key}=unserialize(<< - * 'value1', 'var2' => 'value2'); - * ?> - * - * @param string $moduleName module name - * @param string $methodName method name - * @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) or key1=value1&key2=value2 - * @param string $viewType the view type - * @param bool $onlybody whether onlybody - * @static - * @access public - * @return string the link string. - */ - static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlybody = false) - { - global $app, $config; - $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); - - /* 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; - } - elseif($viewType == $app->getViewType()) - { - $link .= $moduleName . '/'; - } - else - { - $link .= $moduleName . '.' . $viewType; - } - } - else - { - $link .= "$moduleName{$config->requestFix}$methodName"; - foreach($vars as $value) $link .= "{$config->requestFix}$value"; - $link .= '.' . $viewType; - } - } - else - { - $link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName"; - if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType; - foreach($vars as $key => $value) $link .= "&$key=$value"; - } - - /* 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 != 'GET' ? "?onlybody=yes" : "&onlybody=yes"; - $link .= $onlybody; - } - return $link; - } - - /** - * 引用一个文件,替换内置的include及require方法 - * Import a file instend of include or require. - * - * @param string $file the file to be imported. - * @static - * @access public - * @return bool - */ - static public function import($file) - { - if(!is_file($file)) return false; - static $includedFiles = array(); - if(!isset($includedFiles[$file])) - { - include $file; - $includedFiles[$file] = true; - return true; - } - return true; - } - - /** - * 设置一个模块的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, $appName = '') - { - global $app; - if($appName == '') $appName = $app->getAppName(); - - /* 设置主model文件,扩展文件和路径。 */ - /* Set the main model file, extension path and files. */ - $mainModelFile = $app->getModulePath($appName, $moduleName) . 'model.php'; - $modelExtPaths = $app->getModuleExtPath($appName, $moduleName, 'model'); - - $hookFiles = array(); - $extFiles = array(); - foreach($modelExtPaths as $modelExtPath) - { - if(empty($modelExtPath)) continue; - $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; - $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; - - return $mergedModelFile; - } - - /* If loaded zend opcache module, turn off cache when create tmp model file to avoid the conflics. */ - if(extension_loaded('Zend OPcache')) ini_set('opcache.enable', 0); - - /* Update the cache file. */ - $modelClass = $moduleName . 'Model'; - $extModelClass = 'ext' . $modelClass; - $extTmpModelClass = 'tmpExt' . $modelClass; - $modelLines = " $count) - { - if($count <= 1) unset($conflics[$functionName]); - } - if($conflics) - { - $modelLines = explode("\n", $modelLines); - $startDel = false; - foreach($modelLines as $line => $code) - { - if($startDel and preg_match('/.* function\s+(\w+)\s*\(.*\)/Ui', $code)) $startDel = false; - if($startDel) - { - unset($modelLines[$line]); - } - else - { - foreach($conflics as $functionName => $count) - { - if($count <= 1) continue; - if(preg_match('/.* function\s+' . $functionName . '\s*\(.*\)/Ui', $code)) - { - $conflics[$functionName] = $count - 1; - $startDel = true; - unset($modelLines[$line]); - } - } - } - } - - $modelLines = join("\n", $modelLines); - } - - $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'); - } - if(!class_exists($extTmpModelClass)) include $tmpMergedModelFile; - - /* Get hook codes need to merge. */ - $hookCodes = array(); - foreach($hookFiles as $hookFile) - { - $fileName = baseName($hookFile); - list($method) = explode('.', $fileName); - $hookCodes[$method][] = self::removeTagsOfPHP($hookFile); - } - - /* Cycle the hook methods and merge hook codes. */ - $hookedMethods = array_keys($hookCodes); - $mainModelCodes = file($mainModelFile); - $mergedModelCodes = file($tmpMergedModelFile); - foreach($hookedMethods as $method) - { - /* Reflection the hooked method to get it's defined position. */ - $methodRelfection = new reflectionMethod($extTmpModelClass, $method); - $definedFile = $methodRelfection->getFileName(); - $startLine = $methodRelfection->getStartLine() . ' '; - $endLine = $methodRelfection->getEndLine() . ' '; - - /* Merge hook codes. */ - $oldCodes = $definedFile == $tmpMergedModelFile ? $mergedModelCodes : $mainModelCodes; - $oldCodes = join("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1)); - $openBrace = strpos($oldCodes, '{'); - $newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . join("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1); - - /* Replace it. */ - if($definedFile == $tmpMergedModelFile) - { - $modelLines = str_replace($oldCodes, $newCodes, $modelLines); - } - else - { - $modelLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $modelLines); - } - } - unlink($tmpMergedModelFile); - - /* Save it. */ - $modelLines = str_replace($extTmpModelClass, $extModelClass, $modelLines); - file_put_contents($mergedModelFile, $modelLines); - - return $mergedModelFile; - } - - /** - * Remove tags of PHP - * - * @param string $fileName - * @static - * @access public - * @return string - */ - static public function removeTagsOfPHP($fileName) - { - $code = trim(file_get_contents($fileName)); - if(strpos($code, '') !== false) $code = rtrim($code, '?>'); - return trim($code); - } - - /** - * 将数组转化成 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. - * @static - * @access public - * @return string the string like IN('a', 'b'). - */ - static public function dbIN($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. - * @static - * @access public - * @return string encoded string. - */ - static public function safe64Encode($string) - { - return strtr(base64_encode($string), '/', '.'); - } - - /** - * 解码base64,先将之前的'.' 转换回'/' - * Decode the string encoded by safe64Encode. - * - * @param string $string the string to decode - * @static - * @access public - * @return string decoded string. - */ - static public function safe64Decode($string) - { - return base64_decode(strtr($string, '.', '/')); - } - - /** - * 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 - * @author hmdker@gmail.com - * @see http://php.net/manual/en/function.mb-detect-encoding.php - * @static - * @access public - * @return bool - */ - static public function isUTF8($string) - { - $c = 0; - $b = 0; - $bits = 0; - $len = strlen($string); - for($i=0; $i<$len; $i++) - { - $c = ord($string[$i]); - if($c > 128) - { - if(($c >= 254)) return false; - elseif($c >= 252) $bits=6; - elseif($c >= 248) $bits=5; - elseif($c >= 240) $bits=4; - elseif($c >= 224) $bits=3; - elseif($c >= 192) $bits=2; - else return false; - if(($i+$bits) > $len) return false; - while($bits > 1) - { - $i++; - $b=ord($string[$i]); - if($b < 128 || $b > 191) return false; - $bits--; - } - } - } - return true; - } - - /** - * 计算两个日期相差的天数,取整 - * Compute the diff days of two date. - * - * @param string $date1 the first date. - * @param string $date2 the sencode date. - * @access public - * @return int the diff of the two days. - */ - static public function diffDate($date1, $date2) - { - return round((strtotime($date1) - strtotime($date2)) / 86400, 0); - } - - /** - * 获取当前时间,使用common语言文件定义的DT_DATETIME1常量 - * Get now time use the DT_DATETIME1 constant defined in the lang file. - * - * @access public - * @return datetime now - */ - static public function now() - { - return date(DT_DATETIME1); - } - - /** - * 获取当前日期,使用common语言文件定义的DT_DATE1常量 - * Get today according to the DT_DATE1 constant defined in the lang file. - * - * @access public - * @return date today - */ - static public function today() - { - return date(DT_DATE1); - } - - /** - * 获取当前日期,使用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 - * @return bool - */ - static public function isZeroDate($date) - { - return substr($date, 0, 4) == '0000'; - } - - /** - * 列出目录中符合该正则表达式的文件 - * Get files match the pattern under one directory. - * - * @access public - * @return array the files match the pattern - */ - static public function ls($dir, $pattern = '') - { - if(empty($dir)) return array(); - - $files = array(); - $dir = realpath($dir); - if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern); - return empty($files) ? array() : $files; - } - - /** - * 切换目录 - * Change directory. - * - * @param string $path - * @static - * @access public - * @return void - */ - static function cd($path = '') - { - static $cwd = ''; - if($path) $cwd = getcwd(); - !empty($path) ? chdir($path) : chdir($cwd); - } - - /** - * 去掉UTF8 Bom头 - * Remove UTF8 Bom - * - * @param string $string - * @access public - * @return string - */ - public static function removeUTF8Bom($string) - { - if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3); - return $string; - } - - /** - * 通过域名获取站点代号。 - * 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 - * @access public - * @return bool - */ - public static function isAjaxRequest() - { - return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'; - } - - /** - * 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 - * @access public - * @return void - */ - public static function setViewType() - { - global $config, $app; - if($config->requestType != 'GET') - { - $pathInfo = $app->getPathInfo(); - if(!empty($pathInfo)) - { - $dotPos = strrpos($pathInfo, '.'); - if($dotPos) - { - $viewType = substr($pathInfo, $dotPos + 1); - } - else - { - $config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view; - } - } - } - elseif($config->requestType == 'GET') - { - if(isset($_GET[$config->viewVar])) - { - $viewType = $_GET[$config->viewVar]; - } - else - { - /* Set default view when url has not module name. such as only domain. */ - $config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view; - } - } - - 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)) - { - if($item->section and !isset($config2Merge->{$item->section})) $config2Merge->{$item->section} = new stdclass(); - $configItem = $item->section ? $config2Merge->{$item->section} : $config2Merge; - if($item->key) $configItem->{$item->key} = $item->value; - break; - } - - if($record->section and !isset($config2Merge->{$record->section})) $config2Merge->{$record->section} = new stdclass(); - $configItem = $record->section ? $config2Merge->{$record->section} : $config2Merge; - if($record->key) $configItem->{$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 - * @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) - * @param string $viewType - * @return string the link string. - */ -function inLink($methodName = 'index', $vars = '', $viewType = '') -{ - global $app; - return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType); -} - -/** - * 通过一个静态游标,可以遍历数组 - * Static cycle a array - * - * @param array $items the array to be cycled. - * @return mixed - */ -function cycle($items) -{ - static $i = 0; - if(!is_array($items)) $items = explode(',', $items); - if(!isset($items[$i])) $i = 0; - return $items[$i++]; -} - -/** - * 获取当前时间的Unix时间戳,精确到微妙 - * Get current microtime. - * - * @access protected - * @return float current time. - */ -function getTime() -{ - list($usec, $sec) = explode(" ", microtime()); - return ((float)$usec + (float)$sec); -} - -/** - * 打印变量的信息 - * dump a var. - * - * @param mixed $var - * @access public - * @return void - */ -function a($var) -{ - echo ""; - print_r($var); - echo ""; -} - -/** - * 判断是否内外IP。 - * Judge the server ip is local or not. - * - * @access public - * @return void - */ -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 - * @return string - */ -function getWebRoot() -{ - $path = $_SERVER['SCRIPT_NAME']; - if(PHP_SAPI == 'cli') - { - $url = parse_url($_SERVER['argv'][1]); - $path = empty($url['path']) ? '/' : rtrim($url['path'], '/'); - $path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path); - } - - return substr($path, 0, (strrpos($path, '/') + 1)); -} - -/** - * 检查是否是onlybody模式。 - * Check exist onlybody param. - * - * @access public - * @return void - */ -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) -{ - global $config; - if(strpos(htmlspecialchars_decode($value), 'framework->stripXSS) and $config->framework->stripXSS) - { - if(stripos($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 index 3de646e4eb..65cf71496c 100644 --- a/framework/model.class.php +++ b/framework/model.class.php @@ -1,279 +1,7 @@ app. - * 2. set the pathes, config, lang of current module - * - * @param string $appName - * @access public - * @return void - */ - public function __construct($appName = '') - { - global $app, $config, $lang, $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, $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 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. - */ - protected function getModuleName() - { - $parentClass = get_parent_class($this); - $selfClass = get_class($this); - $className = $parentClass == 'model' ? $selfClass : $parentClass; - if($className == 'extensionModel') return 'extension'; - return strtolower(str_ireplace(array('ext', 'Model'), '', $className)); - } - - /** - * 设置全局超级变量。 - * Set the super vars. - * - * @access protected - * @return void - */ - protected function setSuperVars() - { - $this->post = $this->app->post; - $this->get = $this->app->get; - $this->server = $this->app->server; - $this->cookie = $this->app->cookie; - $this->session = $this->app->session; - $this->global = $this->app->global; - } - - /** - * 加载一个模块的model。加载完成后,使用$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, $appName = '') - { - if(empty($moduleName)) return false; - if(empty($appName)) $appName = $this->appName; - $modelFile = helper::setModelFile($moduleName, $appName); - - if(!helper::import($modelFile)) return false; - $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($appName); - return $this->$moduleName; - } - - /** - * 加载model的class扩展。 - * Load extension class of a model. Saved to $moduleName/ext/model/class/$extensionName.class.php. - * - * @param string $extensionName - * @param string $moduleName - * @access public - * @return void - */ - public function loadExtension($extensionName, $moduleName = '') - { - if(empty($extensionName)) return false; - - /* Set extenson name and extension file. */ - $extensionName = strtolower($extensionName); - $moduleName = $moduleName ? $moduleName : $this->getModuleName(); - $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($this->appName, $moduleName) . 'model.php'); - if(!helper::import($extensionFile)) return false; - - /* Set the extension class name. */ - $extensionClass = $extensionName . ucfirst($moduleName); - if(!class_exists($extensionClass)) return false; - - /* Create an instance of the extension class and return it. */ - $extensionObject = new $extensionClass; - $extensionClass = str_replace('Model', '', $extensionClass); - $this->$extensionClass = $extensionObject; - return $extensionObject; - } - - /** - * 加载DAO。 - * Load DAO. - * - * @access private - * @return void - */ - private function loadDAO() - { - $this->dao = $this->app->loadClass('dao'); - } - /** * 删除记录 * Delete one record. @@ -289,4 +17,4 @@ class model $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/myrouter.class.php b/framework/myrouter.class.php deleted file mode 100755 index 43207b18cd..0000000000 --- a/framework/myrouter.class.php +++ /dev/null @@ -1,94 +0,0 @@ -setModuleName('common'); - $commonModelFile = helper::setModelFile('common'); - if(file_exists($commonModelFile)) - { - 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 - { - return false; - } - } - } - - public function loadLang($moduleName, $appName = '') - { - $modulePath = $this->getModulePath($appName, $moduleName); - $mainLangFile = $modulePath . 'lang' . DS . $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. */ - if(!is_file($mainLangFile)) - { - if(empty($extLangFiles)) return false; // also no extension file. - $langFiles = $extLangFiles; - } - else - { - $langFiles = array_merge(array($mainLangFile), $extLangFiles); - } - - 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) - { - if(in_array($langFile, $loadedLangs)) continue; - include $langFile; - $loadedLangs[] = $langFile; - } - - /* Merge from the db lang. */ - if($moduleName != 'common' and isset($lang->db->custom[$moduleName])) - { - foreach($lang->db->custom[$moduleName] as $section => $fields) - { - foreach($fields as $key => $value) - { - unset($lang->{$moduleName}->{$section}[$key]); - $lang->{$moduleName}->{$section}[$key] = $value; - } - } - } - - $this->lang = $lang; - return $lang; - } -} diff --git a/framework/router.class.php b/framework/router.class.php old mode 100644 new mode 100755 index b83324f404..365623d4ec --- a/framework/router.class.php +++ b/framework/router.class.php @@ -1,1189 +1,7 @@ basePath/framework) - * - * @var string - * @access public - */ - public $frameRoot; - - /** - * 应用类库的根目录($this->appRoot/lib)。 - * The root directory of the app library($this->appRoot/lib). - * - * @var string - * @access public - */ - public $coreLibRoot; - - /** - * 应用程序的根目录。 - * The root directory of the app. - * - * @var string - * @access public - */ - public $appRoot; - - /** - * 临时文件的根目录。 - * The root directory of temp. - * - * @var string - * @access public - */ - public $tmpRoot; - - /** - * 缓存的根目录。 - * The root directory of cache. - * - * @var string - * @access public - */ - 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 public - */ - public $logRoot; - - /** - * 配置文件的根目录。 - * The root directory of config. - * - * @var string - * @access public - */ - public $configRoot; - - /** - * 模块的根目录。 - * The root directory of module. - * - * @var string - * @access public - */ - public $moduleRoot; - - /** - * 主题的根目录。 - * The root directory of theme. - * - * @var string - * @access public - */ - public $themeRoot; - - /** - * 用户使用的语言。 - * The lang of the client user. - * - * @var string - * @access public - */ - public $clientLang; - - /** - * 用户使用的主题。 - * The theme of the client user. - * - * @var string - * @access public - */ - public $clientTheme; - - /** - * 当前模块的control对象。 - * The control object of current module. - * - * @var object - * @access public - */ - public $control; - - /** - * 模块名。 - * The module name - * - * @var string - * @access public - */ - public $moduleName; - - /** - * 当前访问模块的control文件。 - * The control file of the module current visiting. - * - * @var string - * @access public - */ - public $controlFile; - - /** - * 当前访问的方法名。 - * The name of the method current visiting. - * - * @var string - * @access public - */ - public $methodName; - - /** - * 当前方法的扩展文件。 - * The action extension file of current method. - * - * @var string - * @access public - */ - public $extActionFile; - - /** - * 访问的URI。 - * The URI. - * - * @var string - * @access public - */ - public $URI; - - /** - * url地址传递的参数。 - * The params passed in through url. - * - * @var array - * @access public - */ - public $params; - - /** - * 视图类型。 - * The view type. - * - * @var string - * @access public - */ - public $viewType; - - /** - * 全局$config对象。 - * The global $config object. - * - * @var object - * @access public - */ - public $config; - - /** - * 全局$lang对象。 - * The global $lang object. - * - * @var object - * @access public - */ - public $lang; - - /** - * 全局$dbh对象,数据库连接句柄。 - * The global $dbh object, the database connection handler. - * - * @var object - * @access public - */ - public $dbh; - - /** - * 从数据库的句柄。 - * The slave database handler. - * - * @var object - * @access public - */ - public $slaveDBH; - - /** - * $post对象,用于访问$_POST变量。 - * The $post object, used to access the $_POST var. - * - * @var ojbect - * @access public - */ - public $post; - - /** - * $get对象,用于访问$_GET变量。 - * The $get object, used to access the $_GET var. - * - * @var ojbect - * @access public - */ - public $get; - - /** - * $session对象,用于访问$_SESSION变量。 - * The $session object, used to access the $_SESSION var. - * - * @var ojbect - * @access public - */ - public $session; - - /** - * $server对象,用于访问$_SERVER变量。 - * The $server object, used to access the $_SERVER var. - * - * @var ojbect - * @access public - */ - public $server; - - /** - * $cookie对象,用于访问$_COOKIE变量。 - * The $cookie object, used to access the $_COOKIE var. - * - * @var ojbect - * @access public - */ - public $cookie; - - /** - * $global对象,用于访问$_GLOBAL变量。 - * The $global object, used to access the $_GLOBAL var. - * - * @var ojbect - * @access public - */ - public $global; - - /** - * 网站代号 - * 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 compute the appRoot according the $appName - * - * @param string $appName the name of the app - * @param string $appRoot the root path of the app - * @access public - * @return void - */ - public function __construct($appName = 'demo', $appRoot = '') - { - $this->setPathFix(); - $this->setBasePath(); - $this->setFrameRoot(); - $this->setCoreLibRoot(); - $this->setAppRoot($appName, $appRoot); - $this->setTmpRoot(); - $this->setCacheRoot(); - $this->setLogRoot(); - $this->setConfigRoot(); - $this->setModuleRoot(); - $this->setThemeRoot(); - $this->setWwwRoot(); - $this->setDataRoot(); - - $this->setSuperVars(); - $this->loadConfig('common'); - $this->filterSuperVars(); - - $this->setDebug(); - $this->setErrorHandler(); - - $this->connectDB(); - - $this->setTimezone(); - $this->setClientLang(); - $this->loadLang('common'); - $this->setClientTheme(); - - $this->loadClass('front', $static = true); - $this->loadClass('filter', $static = true); - $this->loadClass('dao', $static = true); - } - - /** - * 创建一个应用。 - * Create an application. - * - * - * - * or specify the root path of the app. Thus the app and framework can be seperated. - * - * - * @param string $appName the name of the app - * @param string $appRoot the root path of the app - * @param string $className the name of the router class. When extends a child, you should pass in the child router class name. - * @static - * @access public - * @return object the app object - */ - public static function createApp($appName = 'demo', $appRoot = '', $className = '') - { - if(empty($className)) $className = __CLASS__; - return new $className($appName, $appRoot); - } - - //-------------------- 路径相关方法(Path related methods)--------------------// - - /** - * 设置应用名称 - * Set app name. - * - * @param string $appName - * @access public - * @return void - */ - public function setAppName($appName) - { - $this->appName = $appName; - } - - /** - * 设置目录分隔符。 - * Set the path directory separator. - * - * @access public - * @return void - */ - public function setPathFix() - { - define('DS', DIRECTORY_SEPARATOR); - } - - /** - * 设置设备类型 - * Set current device of visit website. - * - * @access public - * @return void - */ - 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 public - * @return void - */ - public function setFrameRoot() - { - $this->frameRoot = $this->basePath . 'framework' . DS; - } - - /** - * 设置应用类库的根目录。 - * Set the app lib root. - * - * @access public - * @return void - */ - public function setCoreLibRoot() - { - $this->coreLibRoot = $this->basePath . 'lib' . DS; - } - - /** - * 设置应用的根目录。 - * Set the app root. - * - * @param string $appName - * @param string $appRoot - * @access public - * @return void - */ - public function setAppRoot($appName = 'demo', $appRoot = '') - { - if(empty($appRoot)) - { - $this->appRoot = $this->basePath . 'app' . DS . $appName . DS; - } - else - { - $this->appRoot = realpath($appRoot) . DS; - } - if(!is_dir($this->appRoot)) $this->triggerError("The app you call not found in {$this->appRoot}", __FILE__, __LINE__, $exit = true); - } - - /** - * 设置临时文件的根目录。 - * Set the tmp root. - * - * @access public - * @return void - */ - public function setTmpRoot() - { - $this->tmpRoot = $this->basePath . 'tmp' . DS; - } - - /** - * 设置缓存的根目录。 - * Set the cache root. - * - * @access public - * @return void - */ - public function setCacheRoot() - { - $this->cacheRoot = $this->tmpRoot . 'cache' . DS; - } - - /** - * 设置log的根目录。 - * Set the log root. - * - * @access public - * @return void - */ - public function setLogRoot() - { - $this->logRoot = $this->tmpRoot . 'log' . DS; - } - - /** - * 设置config配置文件的根目录。 - * Set the config root. - * - * @access public - * @return void - */ - public function setConfigRoot() - { - $this->configRoot = $this->basePath . 'config' . DS; - } - - /** - * 设置模块的根目录。 - * Set the module root. - * - * @access public - * @return void - */ - public function setModuleRoot() - { - $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 public - * @return void - */ - public function setThemeRoot() - { - $this->themeRoot = $this->wwwRoot . 'theme' . DS; - } - - /** - * 过滤超级变量数据 - * Filter superVars. - * - * @access public - * @return void - */ - public function filterSuperVars() - { - if(!empty($_COOKIE)) - { - foreach($_COOKIE as $cookieKey => $cookieValue) - { - if(preg_match('/[^a-zA-Z0-9_\.]/', $cookieKey)) unset($_COOKIE[$cookieKey]); - if(preg_match('/[^a-zA-Z0-9=_\|\- ,`+\/\.%\x7f-\xff]/', $cookieValue)) unset($_COOKIE[$cookieKey]); - } - } - - if(!empty($_FILES)) - { - foreach($_FILES as $varName => $files) - { - if(is_array($files['name'])) - { - foreach($files['name'] as $i => $fileName) - { - $extension = ltrim(strrchr($fileName, '.'), '.'); - if(strrpos($this->config->file->dangers, $extension) !== false) - { - foreach($files as $fileKey => $value) - { - unset($_FILES); - break 2; - } - } - } - } - else - { - $extension = ltrim(strrchr($files['name'], '.'), '.'); - if(strrpos($this->config->file->dangers, $extension) !== false) unset($_FILES); - } - } - } - $_POST = processArrayEvils($_POST); - $_GET = processArrayEvils($_GET); - $_COOKIE = processArrayEvils($_COOKIE); - unset($GLOBALS); - unset($_REQUEST); - } - - /** - * 设置超级变量。 - * Set the super vars. - * - * @access public - * @return void - */ - public function setSuperVars() - { - $this->post = new super('post'); - $this->get = new super('get'); - $this->server = new super('server'); - $this->cookie = new super('cookie'); - $this->session = new super('session'); - $this->global = new super('global'); - } - - /** - * 设置站点代号 - * 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 - */ - public function setDebug() - { - if(!empty($this->config->debug)) error_reporting(E_ALL & ~ E_STRICT); - } - - /** - * 设置错误处理句柄。 - * Set the error handler. - * - * @access public - * @return void - */ - public function setErrorHandler() - { - set_error_handler(array($this, 'saveError')); - register_shutdown_function(array($this, 'shutdown')); - } - - /** - * 根据配置设置当前时区。 - * Set the time zone according to the config. - * - * @access public - * @return void - */ - public function setTimezone() - { - if(isset($this->config->timezone)) date_default_timezone_set($this->config->timezone); - } - - /** - * 获取应用名称 - * Get app name - * - * @access public - * @return string - */ - public function getAppName() - { - return $this->appName; - } - - /** - * 获取$basePath,即基础路径。 - * Get the $basePath var. - * - * @access public - * @return string - */ - public function getBasePath() - { - return $this->basePath; - } - - /** - * 获取$frameRoot,即框架根目录。 - * Get the $frameRoot var. - * - * @access public - * @return string - */ - public function getFrameRoot() - { - return $this->frameRoot; - } - - /** - * 获取$appRoot变量,即应用的根目录。 - * Get the $appRoot var. - * - * @access public - * @return string - */ - public function getAppRoot() - { - return $this->appRoot; - } - - /** - * 获取$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 - */ - public function getTmpRoot() - { - return $this->tmpRoot; - } - - /** - * 获取$cacheRoot变量,即缓存文件的根目录。 - * Get the $cacheRoot var. - * - * @access public - * @return string - */ - public function getCacheRoot() - { - return $this->cacheRoot; - } - - /** - * 获取$logRoot变量,即日志文件的根目录。 - * Get the $logRoot var. - * - * @access public - * @return string - */ - public function getLogRoot() - { - return $this->logRoot; - } - - /** - * 获取$configRoot变量,即配置文件的根目录。 - * Get the $configRoot var. - * - * @access public - * @return string - */ - public function getConfigRoot() - { - return $this->configRoot; - } - - /** - * 获取$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 getDataRoot() - { - return $this->dataRoot; - } - - /** - * 获取$themeRoot变量,即主题的根目录。 - * Get the $themeRoot var. - * - * @access public - * @return string - */ - public function getThemeRoot() - { - return $this->themeRoot; - } - - //------ 客户端环境有关的函数(Client environment related functions) ------// - - /** - * 根据用户浏览器的语言设置和服务器配置,选择显示的语言。 - * 优先级:$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 - * @return void - */ - public function setClientLang($lang = '') - { - if(!empty($lang)) - { - $this->clientLang = $lang; - } - elseif(isset($_SESSION['lang'])) - { - $this->clientLang = $_SESSION['lang']; - } - elseif(isset($_COOKIE['lang'])) - { - $this->clientLang = $_COOKIE['lang']; - } - elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - { - if(strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], ',') === false) - { - $this->clientLang = $_SERVER['HTTP_ACCEPT_LANGUAGE']; - } - else - { - $this->clientLang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], ',')); - } - - /* Fix clientLang for ie >= 10. https://www.drupal.org/node/365615. */ - if(stripos($this->clientLang, 'hans')) $this->clientLang = 'zh-cn'; - if(stripos($this->clientLang, 'hant')) $this->clientLang = 'zh-tw'; - } - if(!empty($this->clientLang)) - { - $this->clientLang = strtolower($this->clientLang); - if(!isset($this->config->langs[$this->clientLang])) $this->clientLang = $this->config->default->lang; - } - else - { - $this->clientLang = $this->config->default->lang; - } - setcookie('lang', $this->clientLang, $this->config->cookieLife, $this->config->webRoot); - if(!isset($_COOKIE['lang'])) $_COOKIE['lang'] = $this->clientLang; - } - - /** - * 获取$clientLang变量,即客户端的语言。 - * Get the $clientLang var. - * - * @access public - * @return string - */ - public function getClientLang() - { - return $this->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 - * @access public - * @return void - */ - public function setClientTheme($theme = '') - { - if(!empty($theme)) - { - $this->clientTheme = $theme; - } - elseif(isset($_COOKIE['theme'])) - { - $this->clientTheme = $_COOKIE['theme']; - } - elseif(isset($this->config->client->theme)) - { - $this->clientTheme = $this->config->client->theme; - } - - if(!empty($this->clientTheme)) - { - $this->clientTheme = strtolower($this->clientTheme); - if(!isset($this->config->themes[$this->clientTheme])) $this->clientTheme = $this->config->default->theme; - } - else - { - $this->clientTheme = $this->config->default->theme; - } - setcookie('theme', $this->clientTheme, $this->config->cookieLife, $this->config->webRoot); - if(!isset($_COOKIE['theme'])) $_COOKIE['theme'] = $this->clientTheme; - } - - /** - * 获取$clientTheme变量。 - * Get the $clientTheme var. - * - * @access public - * @return string - */ - public function getClientTheme() - { - return $this->config->webRoot . 'theme/' . $this->clientTheme . '/'; - } - - /** - * 获取$webRoot,即应用的路径。 - * Get the $webRoot var. - * - * @access public - * @return string - */ - public function getWebRoot() - { - return $this->config->webRoot; - } - - //-------------------- 请求相关的方法(Request related methods) --------------------// - - /** - * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。 - * The entrance of parseing request. According to the requestType, call related methods. - * - * @access public - * @return void - */ - public function parseRequest() - { - 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(); - } - elseif($this->config->requestType == 'GET') - { - $this->parseGET(); - $this->setRouteByGET(); - } - else - { - $this->triggerError("The request type {$this->config->requestType} not supported", __FILE__, __LINE__, $exit = true); - } - } - - /** - * PATH_INFO方式解析,获取$URI和$viewType。 - * Parse PATH_INFO, get the $URI and $viewType. - * - * @access public - * @return void - */ - public function parsePathInfo() - { - $pathInfo = $this->getPathInfo(); - if(trim($pathInfo, '/') == trim($this->config->webRoot, '/')) $pathInfo = ''; - if(!empty($pathInfo)) - { - $dotPos = strrpos($pathInfo, '.'); - if($dotPos) - { - $this->URI = substr($pathInfo, 0, $dotPos); - $this->viewType = substr($pathInfo, $dotPos + 1); - if(strpos($this->config->views, ',' . $this->viewType . ',') === false) - { - $this->viewType = $this->config->default->view; - } - } - else - { - $this->URI = $pathInfo; - $this->viewType = $this->config->default->view; - } - } - else - { - $this->viewType = $this->config->default->view; - } - } - - /** - * 从$_SERVER或者$_ENV全局变量根据pathinfo变量名获取$PATH_INFO值。 - * PATH_INFO的变量名几乎都是'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() - { - 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 public - * @return void - */ - 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; - } - else - { - $this->viewType = $this->config->default->view; - } - $this->URI = $_SERVER['REQUEST_URI']; - } - - /** - * 获取$URL。 - * Get the $URL. - * - * @param bool $full true, the URI contains the webRoot, else only hte URI. - * @access public - * @return string - */ - public function getURI($full = false) - { - if($full and $this->config->requestType == 'PATH_INFO') - { - if($this->URI) return $this->config->webRoot . $this->URI . '.' . $this->viewType; - return $this->config->webRoot; - } - return $this->URI; - } - - /** - * 获取$vewType变量。 - * Get the $viewType var. - * - * @access public - * @return string - */ - public function getViewType() - { - return $this->viewType; - } - - //-------------------- 路由相关方法(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 loaded. - * - * @access public - * @return object|bool the common control object or false if not exits. - */ public function loadCommon() { $this->setModuleName('common'); @@ -1193,10 +11,14 @@ 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 @@ -1206,564 +28,6 @@ class router } } - /** - * 设置要被调用的模块名。 - * Set the name of the module to be called. - * - * @param string $moduleName the module name - * @access public - * @return void - */ - public function setModuleName($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 没有找到该控制器文件的情况:如果该参数为true,则终止程序;如果为false,则打印错误日志 - * If control file not foundde, how to do. True, die the whole app. false, log error. - * @access public - * @return bool - */ - public function setControlFile($exitIfNone = true) - { - $this->controlFile = $this->moduleRoot . $this->moduleName . DS . 'control.php'; - if(!is_file($this->controlFile)) - { - $this->triggerError("the control file $this->controlFile not found.", __FILE__, __LINE__, $exitIfNone); - return false; - } - return true; - } - - /** - * 设置要被调用的方法名。 - * Set the name of the method calling. - * - * @param string $methodName - * @access public - * @return void - */ - public function setMethodName($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($appName = '', $moduleName = '') - { - if($moduleName == '') $moduleName = $this->moduleName; - 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($appName, $moduleName, $ext) - { - 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 - * @return bool - */ - public function setActionExtFile() - { - $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. - * - * @access public - * @return void - */ - public function setRouteByPathInfo() - { - if(!empty($this->URI)) - { - /* - * 根据$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. - **/ - else - { - $this->setModuleName($this->URI); - $this->setMethodName($this->config->default->method); - } - } - else - { - $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. - * - * @access public - * @return void - */ - public function setRouteByGET() - { - $moduleName = isset($_GET[$this->config->moduleVar]) ? strtolower($_GET[$this->config->moduleVar]) : $this->config->default->module; - $methodName = isset($_GET[$this->config->methodVar]) ? strtolower($_GET[$this->config->methodVar]) : $this->config->default->method; - $this->setModuleName($moduleName); - $this->setControlFile(); - $this->setMethodName($methodName); - } - - /** - * 加载一个模块: - * 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. - * 4. call the method by call_user_function_array - * - * @access public - * @return bool|object if the module object of die. - */ - public function loadModule() - { - $moduleName = $this->moduleName; - $methodName = $this->methodName; - - /* - * 引入该模块的control文件。 - * Include the control file of the module. - **/ - $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile; - chdir(dirname($file2Included)); - include $file2Included; - - /* - * 设置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); - - /* - * 创建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; - - /* include default value for module*/ - $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php"); - if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file; - - /* - * 使用反射机制获取函数参数的默认值。 - * 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])) - { - $default = $paramDefaultValue[$className][$methodName][$name]; - } - elseif($param->isDefaultValueAvailable()) - { - $default = $param->getDefaultValue(); - } - - $defaultParams[$name] = $default; - } - - /** - * 根据PATH_INFO或者GET方式设置请求的参数。 - * Set params according PATH_INFO or GET. - */ - if($this->config->requestType != 'GET') - { - $this->setParamsByPathInfo($defaultParams); - } - else - { - $this->setParamsByGET($defaultParams); - } - - /* 调用该方法 Call the method. */ - call_user_func_array(array($module, $methodName), $this->params); - return $module; - } - - /** - * 设置请求的参数(PATH_INFO 方式)。 - * Set the params by PATH_INFO. - * - * @param array $defaultParams the default settings of the params. - * @access public - * @return void - */ - public function setParamsByPathInfo($defaultParams = array()) - { - /* 分割URI。 Spit the URI. */ - $items = explode($this->config->requestFix, $this->URI); - $itemCount = count($items); - $params = array(); - - /** - * 前两项为模块名和方法名,参数从下标2开始。 - * 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); - } - - $this->params = $this->mergeParams($defaultParams, $params); - } - - /** - * 设置请求的参数(GET 方式)。 - * Set the params by GET. - * - * @param array $defaultParams the default settings of the params. - * @access public - * @return void - */ - 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]); - unset($_GET[$this->config->viewVar]); - unset($_GET[$this->config->sessionVar]); - $this->params = $this->mergeParams($defaultParams, $_GET); - } - - /** - * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。 - * 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 public - * @return array the merged params. - */ - public function mergeParams($defaultParams, $passedParams) - { - /* Check params from URL. */ - foreach($passedParams as $param => $value) - { - if(preg_match('/[^a-zA-Z0-9_\.]/', $param)) die('Bad Request!'); - if(preg_match('/[^a-zA-Z0-9=_,`#+\/\.%\|\x7f-\xff]/', trim($value))) die('Bad Request!'); - } - - unset($passedParams['onlybody']); - $passedParams = array_values($passedParams); - $i = 0; - foreach($defaultParams as $key => $defaultValue) - { - if(isset($passedParams[$i])) - { - $defaultParams[$key] = strip_tags(urldecode($passedParams[$i])); - } - else - { - 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 - * @return string - */ - public function getModuleName() - { - return $this->moduleName; - } - - /** - * 获取$controlFile变量。 - * Get the $controlFile var. - * - * @access public - * @return string - */ - public function getControlFile() - { - return $this->controlFile; - } - - /** - * 获取$methodName变量。 - * Get the $methodName var. - * - * @access public - * @return string - */ - public function getMethodName() - { - return $this->methodName; - } - - /** - * 获取$param变量。 - * Get the $param var. - * - * @access public - * @return string - */ - public function getParams() - { - return $this->params; - } - - //-------------------- 常用的工具方法(Tool methods) ------------------// - - /** - * 从类库中加载一个类文件。 - * - * Load a class file. - * - * @param string $className the class name - * @param bool $static statis class or not - * @access public - * @return object|bool the instance of the class or just true. - */ - public function loadClass($className, $static = false) - { - $className = strtolower($className); - - /* 搜索$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($static) return true; - - /* 实例化该类(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(); - return $$className; - } - - /** - * 加载模块的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 string $appName app name - * @param bool $exitIfNone exit or not - * @access public - * @return object|bool the config object or false. - */ - public function loadConfig($moduleName, $appName = '', $exitIfNone = true) - { - global $config; - if(!is_object($config)) $config = new config(); - if(!isset($config->$moduleName)) $config->$moduleName = new stdclass(); - - $extConfigFiles = array(); - - /* - * 设置主配置文件和扩展配置文件。 - * 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($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) */ - if(!is_file($mainConfigFile)) - { - if($exitIfNone) self::triggerError("config file $mainConfigFile not found", __FILE__, __LINE__, true); - if(empty($extConfigFiles) and !isset($config->system->$moduleName)) return false; // and no extension file or extension in db, exit. - $configFiles = $extConfigFiles; - } - else - { - $configFiles = array_merge(array($mainConfigFile), $extConfigFiles); - } - - static $loadedConfigs = array(); - foreach($configFiles as $configFile) - { - if(in_array($configFile, $loadedConfigs)) continue; - include $configFile; - $loadedConfigs[] = $configFile; - } - - if($moduleName == 'common') - { - $this->config = $config; - $this->setSiteCode(); - if(!isset($config->site)) $config->site = new stdclass(); - $config->site->code = $this->siteCode; - - if(!empty($config->multi)) - { - $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 - * @return void - */ - public function exportConfig() - { - $view = new stdclass(); - $view->version = $this->config->version; - $view->requestType = $this->config->requestType; - $view->requestFix = $this->config->requestFix; - $view->moduleVar = $this->config->moduleVar; - $view->methodVar = $this->config->methodVar; - $view->viewVar = $this->config->viewVar; - $view->sessionVar = $this->config->sessionVar; - - $this->session->set('rand', mt_rand(0, 10000)); - $view->sessionName = session_name(); - $view->sessionID = session_id(); - $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, $appName = '') { $modulePath = $this->getModulePath($appName, $moduleName); @@ -1773,10 +37,10 @@ class router $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php'); $extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles); - /* 设置引用的文件(Set the files to include). */ + /* Set the files to includ. */ if(!is_file($mainLangFile)) { - if(empty($extLangFiles)) return false; // 没有扩展文件,返回false(Return false if no extension file). + if(empty($extLangFiles)) return false; // also no extension file. $langFiles = $extLangFiles; } else @@ -1787,6 +51,22 @@ 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) { @@ -1811,428 +91,4 @@ class router $this->lang = $lang; return $lang; } - - /** - * 连接数据库。 - * Connect to database. - * - * @access public - * @return void - */ - public function connectDB() - { - global $config, $dbh, $slaveDBH; - if(!isset($config->installed) or !$config->installed) return; - - if(isset($config->db->host)) $this->dbh = $dbh = $this->connectByPDO($config->db); - if(isset($config->slaveDB->host)) $this->slaveDBH = $slaveDBH = $this->connectByPDO($config->slaveDB); - } - - /** - * 使用PDO连接数据库。 - * Connect database by PDO. - * - * @param object $params the database params. - * @access public - * @return object|bool - */ - 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; - if($params->driver == 'mysql') - { - $dsn = "mysql:host={$params->host}; port={$params->port}; dbname={$params->name}"; - } - try - { - $dbh = new PDO($dsn, $params->user, $params->password, array(PDO::ATTR_PERSISTENT => $params->persistant)); - $dbh->exec("SET NAMES {$params->encoding}"); - - /* - * 如果系统是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; - - $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); - $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - if(isset($params->strictMode) and $params->strictMode == false) $dbh->exec("SET @@sql_mode= ''"); - if(isset($params->emulatePrepare)) $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $params->emulatePrepare); - if(isset($params->bufferQuery)) $dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $params->bufferQuery); - - return $dbh; - } - catch (PDOException $exception) - { - self::triggerError($exception->getMessage(), __FILE__, __LINE__, $exit = true); - } - } - - //-------------------- 错误处理方法(Error methods) ------------------// - - /** - * 程序停止时执行的函数。 - * The shutdown handler. - * - * @access public - * @return void - */ - public function shutdown() - { - /* 如果debug模式开启,保存sql语句(If debug on, save sql queries) */ - if(!empty($this->config->debug)) $this->saveSQL(); - - /* - * 发现错误,保存到日志中。 - * 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']); - } - - /** - * 触发一个错误。 - * 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 - * @access public - * @return void - */ - public function triggerError($message, $file, $line, $exit = false) - { - /* 设置错误信息(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(); - extract($trace[0]); - extract($trace[1]); - $log .= ", last called by $file on line $line through function $function.\n"; - - /* 触发错误(Trigger the error) */ - trigger_error($log, $exit ? E_USER_ERROR : E_USER_WARNING); - } - - /** - * 保存错误信息。 - * Save error info. - * - * @param int $level - * @param string $message - * @param string $file - * @param int $line - * @access public - * @return void - */ - public function saveError($level, $message, $file, $line) - { - if(empty($this->config->debug)) return true; - - /* - * 删除设定时间之前的日志。 - * Delete the log before the set time. - **/ - if(mt_rand(0, 1) == 1) - { - $logDays = isset($this->config->framework->logDays) ? $this->config->framework->logDays : 14; - $dayTime = time() - $logDays * 24 * 3600; - foreach(glob($this->getLogRoot() . '*') as $logFile) - { - if(filemtime($logFile) <= $dayTime) unlink($logFile); - } - } - - /* - * 忽略该错误:Redefining already defined constructor。 - * Skip the error: Redefining already defined constructor. - **/ - if(strpos($message, 'Redefining') !== false) return true; - - /* - * 设置错误信息。 - * 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(!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) */ - $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); - - /* - * 如果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) - { - $cmd = "vim +$line $file"; - $size = strlen($cmd); - echo "
$message: ";
-                echo "
"; - } - } - - /* - * 如果是严重错误,停止程序。 - * 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(); - if(PHP_SAPI == 'cli') die($errorLog); - - $htmlError = ""; - $htmlError .= "" . nl2br($errorLog) . ""; - die($htmlError); - } - } - - /** - * 保存sql语句。 - * Save the sql. - * - * @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'; - if(!is_file($sqlLog)) file_put_contents($sqlLog, "\n"); - - $fh = @fopen($sqlLog, 'a'); - if(!$fh) return false; - fwrite($fh, date('Ymd H:i:s') . ": " . $this->getURI() . "\n"); - foreach(dao::$querys as $query) fwrite($fh, " $query\n"); - fwrite($fh, "\n"); - fclose($fh); - } -} - -/** - * config类。 - * The config class. - * - * @package framework - */ -class config -{ - /** - * 设置成员变量,成员可以是'db.user'类似的格式。 - * Set the value of a member. the member can be the format like db.user. - * - * - * set('db.user', 'wwccss'); - * ?> - * - * @param string $key the key of the member - * @param mixed $value the value - * @access public - * @return void - */ - public function set($key, $value) - { - helper::setMember('config', $key, $value); - } -} - -/** - * lang类。 - * The lang class. - * - * @package framework - */ -class language -{ - /** - * 设置成员变量,成员可以是'db.user'类似的格式。 - * Set the value of a member. the member can be the foramt like db.user. - * - * - * set('version', '1.0); - * ?> - * - * @param string $key 成员的键名,可以是father.child的形式。 - * the key of the member, can be father.child - * @param mixed $value the value - * @access public - * @return void - */ - public function set($key, $value) - { - helper::setMember('lang', $key, $value); - } - - /** - * 显示一个成员的值。 - * Show a member. - * - * @param object $obj the object - * @param string $key the key - * @access public - * @return void - */ - public function show($obj, $key) - { - $obj = (array)$obj; - echo isset($obj[$key]) ? $obj[$key] : ''; - } -} - -/** - * 超级对象类,转化超级全局变量。 - * The super object class. - * - * @package framework - */ -class super -{ - /** - * 构造函数,设置超级变量名。 - * Construct, set the var scope. - * - * @param string $scope the scope, can be server, post, get, cookie, session, global - * @access public - * @return void - */ - public function __construct($scope) - { - $this->scope = $scope; - } - - /** - * 设置超级变量的成员值。 - * Set one member value. - * - * @param string the key - * @param mixed $value the value - * @access public - * @return void - */ - public function set($key, $value) - { - if($this->scope == 'post') - { - $_POST[$key] = $value; - } - elseif($this->scope == 'get') - { - $_GET[$key] = $value; - } - elseif($this->scope == 'server') - { - $_SERVER[$key] = $value; - } - elseif($this->scope == 'cookie') - { - $_COOKIE[$key] = $value; - } - elseif($this->scope == 'session') - { - $_SESSION[$key] = $value; - } - elseif($this->scope == 'env') - { - $_ENV[$key] = $value; - } - elseif($this->scope == 'global') - { - $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. - */ - public function __get($key) - { - if($this->scope == 'post') - { - if(isset($_POST[$key])) return $_POST[$key]; - return false; - } - elseif($this->scope == 'get') - { - if(isset($_GET[$key])) return $_GET[$key]; - return false; - } - elseif($this->scope == 'server') - { - if($key == 'ajax') return isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? true : false; - if(isset($_SERVER[$key])) return $_SERVER[$key]; - $key = strtoupper($key); - if(isset($_SERVER[$key])) return $_SERVER[$key]; - return false; - } - elseif($this->scope == 'cookie') - { - if(isset($_COOKIE[$key])) return $_COOKIE[$key]; - return false; - } - elseif($this->scope == 'session') - { - if(isset($_SESSION[$key])) return $_SESSION[$key]; - return false; - } - elseif($this->scope == 'env') - { - if(isset($_ENV[$key])) return $_ENV[$key]; - return false; - } - elseif($this->scope == 'global') - { - if(isset($GLOBALS[$key])) return $GLOBALS[$key]; - return false; - } - else - { - return false; - } - } - - /** - * 打印变量的详细结构。 - * Print the structure. - * - * @access public - * @return void - */ - public function a() - { - if($this->scope == 'post') a($_POST); - if($this->scope == 'get') a($_GET); - if($this->scope == 'server') a($_SERVER); - if($this->scope == 'cookie') a($_COOKIE); - if($this->scope == 'session') a($_SESSION); - if($this->scope == 'env') a($_ENV); - if($this->scope == 'global') a($GLOBALS); - } } diff --git a/lib/dao/dao.class.php b/lib/dao/dao.class.php index f0b73eaf75..9d9783ad8e 100644 --- a/lib/dao/dao.class.php +++ b/lib/dao/dao.class.php @@ -258,14 +258,7 @@ class dao $this->setAlias(''); $this->setMode(''); $this->setMethod(''); - if(defined('LANG_CREATED') and LANG_CREATED == false) - { - $this->setAutoLang(false); - } - else - { - $this->setAutoLang(true); - } + $this->setAutoLang(isset($this->config->framework->autoLang) and $this->config->framework->autoLang); } //-----根据请求的方式,调用sql类相应的方法(Call according method of sql class by query method. -----// diff --git a/www/index.php b/www/index.php index 1c50a20499..17f4fe35ed 100644 --- a/www/index.php +++ b/www/index.php @@ -18,8 +18,7 @@ error_reporting(0); ob_start(); /* Load the framework. */ -//include '../framework/router.class.php'; -include '../framework/myrouter.class.php'; +include '../framework/router.class.php'; include '../framework/control.class.php'; include '../framework/model.class.php'; include '../framework/helper.class.php'; @@ -28,7 +27,7 @@ include '../framework/helper.class.php'; $startTime = getTime(); /* Instance the app. */ -$app = router::createApp('pms', dirname(dirname(__FILE__)), 'myrouter'); +$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); /* installed or not. */ if(!isset($config->installed) or !$config->installed) die(header('location: install.php')); diff --git a/www/install.php b/www/install.php index 24c1c3a67f..04596f2d31 100644 --- a/www/install.php +++ b/www/install.php @@ -14,13 +14,13 @@ session_start(); define('IN_INSTALL', true); /* Load the framework. */ -include '../framework/myrouter.class.php'; +include '../framework/router.class.php'; include '../framework/control.class.php'; include '../framework/model.class.php'; include '../framework/helper.class.php'; /* Instance the app. */ -$app = router::createApp('pms', dirname(dirname(__FILE__)), 'myrouter'); +$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); /* Check installed or not. */ if(!isset($_SESSION['installing']) and isset($config->installed) and $config->installed) die(header('location: index.php')); diff --git a/www/upgrade.php b/www/upgrade.php index d43d078bf0..b9060a929a 100644 --- a/www/upgrade.php +++ b/www/upgrade.php @@ -22,13 +22,13 @@ if(!file_exists($myConfig)) error_reporting(0); /* Load the framework. */ -include '../framework/myrouter.class.php'; +include '../framework/router.class.php'; include '../framework/control.class.php'; include '../framework/model.class.php'; include '../framework/helper.class.php'; /* Instance the app. */ -$app = router::createApp('pms', dirname(dirname(__FILE__)), 'myrouter'); +$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); $common = $app->loadCommon(); /* Reset the config params to make sure the install program will be lauched. */