From 3d61ed75c168a9725b3ffe2d6c533adbbb45ae83 Mon Sep 17 00:00:00 2001 From: zero Date: Wed, 14 Feb 2007 04:55:29 +0000 Subject: [PATCH] git-svn-id: http://xe-core.googlecode.com/svn/trunk@13 201d5d3c-b55e-5fd7-737f-ddc643e51545 --- admin.php | 47 +- classes/addon/AddOnHandler.class.php | 91 ++- classes/context/Context.class.php | 1045 +++++++++++++----------- classes/db/DB.class.php | 454 +++++----- classes/db/DBMysql.class.php | 722 ++++++++-------- classes/module/Module.class.php | 312 +++---- classes/module/ModuleHandler.class.php | 138 ++-- config/config.inc.php | 71 +- config/func.inc.php | 196 +++-- index.php | 60 +- 10 files changed, 1686 insertions(+), 1450 deletions(-) diff --git a/admin.php b/admin.php index 23dfe47ee..da9ca8285 100644 --- a/admin.php +++ b/admin.php @@ -1,25 +1,36 @@ - * @desc : 관리자 페이지 - * admin은 ModuleHandler를 이용하지 않는다. + * @file ./admin.php + * @author zero + * @brief 관리자 페이지 + * 추가되는 모듈의 관리를 위해 소스코드의 변경을 피하기 위해 + * 관리자 페이지는 각 모듈의 admin action을 호출하여 구성을 한다. **/ - // 필요한 설정 파일들을 include + /** + * @brief 필요한 설정 파일들을 include + **/ require_once("./config/config.inc.php"); - // Request Method와 설정값들을 세팅 + /** + * @brief Context 객체를 생성하여 초기화\n + * 모든 Request Argument/ 환경변수등을 세팅 + **/ $oContext = &Context::getInstance(); $oContext->init(); - // 설치가 안되어 있다면 index.php로 이동 + /** + * @brief 설치가 안되어 있다면 index.php로 이동 + * ModuleHandler를 이용하지 않기에 별도로 체크를 해주어야 함 + **/ if(!Context::isInstalled()) { header("location:./index.php"); exit(); } - // sid 검사 + /** + * @brief 관리자페이지에서 모듈의 선택은 sid로 한다. + **/ $sid = Context::get('sid'); if($sid) { $oModule = module_manager::getAdminModuleObject($sid); @@ -30,20 +41,28 @@ } } - // 관리자(admin) 모듈 객체 생성 + /** + * @brief 관리자(admin) 모듈 객체 생성 + **/ $oAdmin = getModule('admin'); $oAdmin->moduleInit(null); - // act검사 + /** + * @brief 역시 ModuleHandler를 이용하지 않기에 직접 act 검사 + **/ $act = Context::get('act'); if(!$sid&&!$oAdmin->isExistsAct($act)) $act = 'dispAdminIndex'; - // 관리자 모듈의 실행 결과가 있으면 해당 실행결과를 출력 + /** + * @brief 관리자 모듈의 실행 결과가 있으면 해당 실행결과를 출력 + **/ if($oAdmin->proc($act)) { $oModule = &$oAdmin; - // 관리자 모듈의 실행 결과가 없으면 호출된 다른 모듈의 관리자를 확인 + /** + * @brief 관리자 모듈의 실행 결과가 없으면 호출된 다른 모듈의 관리자를 확인 + **/ } else { $oModule = module_manager::getAdminModuleObject($sid); if($oModule) { @@ -56,7 +75,9 @@ } } - // DisplayHandler로 컨텐츠 출력 + /** + * @brief DisplayHandler 객체를 생성하여 모듈의 처리 결과를 출력 + **/ $oDisplayHandler = new DisplayHandler(); $oDisplayHandler->printContent($oModule); ?> diff --git a/classes/addon/AddOnHandler.class.php b/classes/addon/AddOnHandler.class.php index 0afd95235..b6f4ba72d 100644 --- a/classes/addon/AddOnHandler.class.php +++ b/classes/addon/AddOnHandler.class.php @@ -1,51 +1,60 @@ - * @desc : addon 실행 - **/ + /** + * @class AddOnHandler + * @author zero (zero@nzeo.com) + * @brief addon을 호출하여 실행 + **/ - class AddOnHandler { + class AddOnHandler { - var $addon_name; + var $addon_name; ///< 실행하고자 하는 addon의 이름 - function callAddOns(&$oModule, $oModuleInfo, $status) { - if(!$oModuleInfo->isAddOnExists($status, ContextHandler::get('act'))) return; + /** + * @brief 모듈에 등록된 애드온을 act값에 맞추어 정리 + **/ + function callAddOns(&$oModule, $oModuleInfo, $status) { + if(!$oModuleInfo->isAddOnExists($status, ContextHandler::get('act'))) return; - $addon_list = $oModuleInfo->getAddOnList($status, ContextHandler::get('act')); - $addon_cnt = count($addon_list); - if(!$addon_cnt) return; - for($i=0; $i<$addon_cnt; $i++) { - $addon_name = $addon_list[$i]; + $addon_list = $oModuleInfo->getAddOnList($status, ContextHandler::get('act')); + $addon_cnt = count($addon_list); + if(!$addon_cnt) return; - $oAddOn = new AddOnHandler($addon_name); - $oAddOn->proc($oModule, $oModuleInfo); - } + for($i=0; $i<$addon_cnt; $i++) { + $addon_name = $addon_list[$i]; + + $oAddOn = new AddOnHandler($addon_name); + $oAddOn->proc($oModule, $oModuleInfo); + } + } + + /** + * @brief constructor + **/ + function AddOnHandler($addon_name) { + $this->addon_name = $addon_name; + } + + /** + * @brief 애드온의 실행 + **/ + function proc(&$oModule, $oModuleInfo) { + // 해당 모듈을 읽어서 객체를 만듬 + $addon_file = sprintf('./addons/%s/%s.addon.php', $this->addon_name, $this->addon_name); + + // 모듈 파일이 없으면 에러 + if(!file_exists($addon_file)) return; + + // 모듈 파일을 include + require_once($addon_file); + + // 선택된 모듈의 instance는 eval string으로 처리 + $eval_str = sprintf('$oAddOn = new %s();', $this->addon_name); + eval($eval_str); + + // 애드온 실행 + $oAddOn->proc($oModule, $oModuleInfo); + } } - function AddOnHandler($addon_name) { - $this->addon_name = $addon_name; - } - - function proc(&$oModule, $oModuleInfo) { - // 해당 모듈을 읽어서 객체를 만듬 - $addon_file = sprintf('./addons/%s/%s.addon.php', $this->addon_name, $this->addon_name); - - // 모듈 파일이 없으면 에러 - if(!file_exists($addon_file)) return; - - // 모듈 파일을 include - require_once($addon_file); - - // 선택된 모듈의 instance는 eval string으로 처리 - $eval_str = sprintf('$oAddOn = new %s();', $this->addon_name); - eval($eval_str); - - // 애드온 실행 - $oAddOn->proc($oModule, $oModuleInfo); - } - - } - ?> diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index f650f426d..541892487 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -1,547 +1,622 @@ - * @desc : Request Argument/Module Config/ Layout-AddOn-Plugin과 - * 결과물까지 모두 처리 - **/ - - class Context { - - // GET/POST/XMLRPC 중 어떤 방식으로 요청이 왔는지에 대한 값이 세팅 - var $request_method = 'GET'; - - // request parameter 를 정리하여 담을 변수 - var $context = NULL; - - // DB 정보 - var $db_info = NULL; - - // js file - var $js_files = array(); - - // css file - var $css_files = array(); - - // html header 정보 - var $html_header = NULL; - - // 언어정보 - var $lang_type = 'ko'; - var $lang = NULL; - var $loaded_lang_files = array(); - - // 현 사이트의 title - var $site_title = ''; - - // 현재 요청 들어온 $_GET을 별도로 정리/보관 ( set method에 의해 값 변경 적용) - var $get_vars = NULL; - - // 업로드 유무 체크 - var $is_uploaded = false; - /** - * Context 객체 생성 및 초기화 - **/ - // public object getInstance()/*{{{*/ - // Context는 어디서든 객체 선언없이 사용하기 위해서 static 하게 사용 - function &getInstance() { - if(!$GLOBALS['__ContextInstance__']) $GLOBALS['__ContextInstance__'] = new Context(); - return $GLOBALS['__ContextInstance__']; - }/*}}}*/ + * @class Context + * @author zero (zero@nzeo.com) + * @brief Request Argument/환경변수등의 모든 Context를 관리 + * + * Context 클래스는 Context::methodname() 처럼 쉽게 사용하기 위해 만들어진 객체를 받아서\n + * 호출하는 구조를 위해 이중 method 구조를 가지고 있다.\n + * php5에서 static variables를 사용하게 된다면 불필요한 구조를 제거할 수 있다.\n + * php5 쓰고 싶어라.. ㅡ.ㅜ + **/ - // public void init()/*{{{*/ - // DB정보, Request Argument등을 세팅 - function init() { - // context 변수를 $GLOBALS의 변수로 지정 - $this->context = &$GLOBALS['__Context__']; - $this->context->lang = &$GLOBALS['lang']; + class Context { - // 인증관련 데이터를 Context에 설정 - $oMember = getModule('member'); - if($oMember->isLogged()) { - $this->_set('is_logged', true); - $this->_set('logged_info', $_SESSION['logged_info']); - } + var $request_method = 'GET'; ///< @brief GET/POST/XMLRPC 중 어떤 방식으로 요청이 왔는지에 대한 값이 세팅. GET/POST/XML 3가지가 있음 - // 기본적인 DB정보 세팅 - $this->_loadDBInfo(); + var $context = NULL; ///< @brief request parameter 및 각종 환경 변수등을 정리하여 담을 변수 - // 기본 언어파일 로드 - $this->lang = &$GLOBALS['lang']; - $this->_loadLang("./common/lang/"); + var $db_info = NULL; ///< @brief DB 정보 - // Request Method 설정 - $this->_setRequestMethod(); + var $js_files = array(); ///< @brief display시에 사용하게 된 js files의 목록 - // Request Argument 설정 - $this->_setXmlRpcArgument(); - $this->_setRequestArgument(); - $this->_setUploadedArgument(); - }/*}}}*/ + var $css_files = array(); ///< @brief display시에 사용하게 된 css files의 목록 - /** - * DB 정보를 설정하고 DB Type과 DB 정보를 return - **/ - // private void _loadDBInfo()/*{{{*/ - // 설정파일을 통해 DB정보를 로드 - function _loadDBInfo() { - if(!$this->isInstalled()) return; + var $html_header = NULL; ///< @brief display시에 사용하게 된 ..내의 스크립트. 거의 사용할 일은 없음 - // db 정보 설정 - $db_config_file = $this->getConfigFile(); - if(file_exists($db_config_file)) { - include $db_config_file; - } - $this->_setDBInfo($db_info); - }/*}}}*/ + /** + * @brief 언어 정보 + * + * 기본으로 ko. HTTP_USER_AGENT나 사용자의 직접 세팅(쿠키이용)등을 통해 변경됨 + **/ + var $lang_type = 'ko'; ///< 언어 종류 + var $lang = NULL; ///< 언어 데이터를 담고 있는 변수 + var $loaded_lang_files = array(); ///< 로딩된 언어파일의 목록 (재로딩을 피하기 위함) - // public string getDBType()/*{{{*/ - // DB의 db_type을 return - function getDBType() { - $oContext = &Context::getInstance(); - return $oContext->_getDBType(); - }/*}}}*/ + var $site_title = ''; ///< @brief 현 사이트의 browser title. Context::setBrowserTitle() 로 변경 가능 - // private string _getDBType()/*{{{*/ - function _getDBType() { - return $this->db_info->db_type; - }/*}}}*/ + var $get_vars = NULL; ///< @brief form이나 get으로 요청이 들어온 변수만 별도로 관리 - // public object setDBInfo($db_info) /*{{{*/ - // DB 정보가 담긴 object를 return - function setDBInfo($db_info) { - $oContext = &Context::getInstance(); - $oContext->_setDBInfo($db_info); - }/*}}}*/ + var $is_uploaded = false; ///< @brief 첨부파일이 업로드 된 요청이였는지에 대한 체크 플래그 - // private string _setDBInfo($db_info)/*{{{*/ - function _setDBInfo($db_info) { - $this->db_info = $db_info; - }/*}}}*/ - - // public object getDBInfo() /*{{{*/ - // DB 정보가 담긴 object를 return - function getDBInfo() { - $oContext = &Context::getInstance(); - return $oContext->_getDBInfo(); - }/*}}}*/ - - // private string _getDBInfo()/*{{{*/ - function _getDBInfo() { - return $this->db_info; - }/*}}}*/ - - /** - * 사이트 title - **/ - // public void setBrowserTitle($site_title)/*{{{*/ - function setBrowserTitle($site_title) { - $oContext = &Context::getInstance(); - $oContext->_setBrowserTitle($site_title); - }/*}}}*/ - - // private void _setBrowserTitle($site_title)/*{{{*/ - function _setBrowserTitle($site_title) { - $this->site_title = $site_title; - }/*}}}*/ - - // public string getBrowserTitle()/*{{{*/ - function getBrowserTitle() { - $oContext = &Context::getInstance(); - return $oContext->_getBrowserTitle(); - }/*}}}*/ - - // private string _getBrowserTitle() /*{{{*/ - function _getBrowserTitle() { - return $this->site_title; - }/*}}}*/ - - /** - * 언어관련 - **/ - // public void loadLang($path)/*{{{*/ - // 지정된 언어파일 로드 - function loadLang($path) { - $oContext = &Context::getInstance(); - $oContext->_loadLang($path); - }/*}}}*/ - - // private void _loadLang($path)/*{{{*/ - // 지정된 언어파일 로드 - function _loadLang($path) { - global $lang; - if(substr($path,-1)!='/') $path .= '/'; - $filename = sprintf('%s%s.lang.php', $path, $this->lang_type); - if(!file_exists($filename)) $filename = sprintf('%slang/%s.lang.php', $path, $this->lang_type); - if(!file_exists($filename)) return; - if(in_array($filename, $this->loaded_lang_files)) return; - $this->loaded_lang_files[] = $filename; - include ($filename); - }/*}}}*/ - - // public void setLangType($lang_type = 'ko')/*{{{*/ - function setLangType($lang_type = 'ko') { - $oContext = &Context::getInstance(); - $oContext->_setLangType($lang); - }/*}}}*/ - - // private void _setLangType($lang_type = 'ko')/*{{{*/ - function _setLangType($lang_type = 'ko') { - $this->lang_type = $lang_type; - }/*}}}*/ - - // public string getLangType()/*{{{*/ - function getLangType() { - $oContext = &Context::getInstance(); - return $oContext->_getLangType(); - }/*}}}*/ - - // private string _getLangType()/*{{{*/ - function _getLangType() { - return $this->lang_type; - }/*}}}*/ - - // public string getLang($code)/*{{{*/ - function getLang($code) { - if($GLOBALS['lang']->{$code}) return $GLOBALS['lang']->{$code}; - return $code; - }/*}}}*/ - - // public string setLang($code, $val)/*{{{*/ - function setLang($code, $val) { - $GLOBALS['lang']->{$code} = $val; - }/*}}}*/ - - // public obj convertEncoding($obj) - // obj내의 문자들을 utf8로 변경 - function convertEncoding($source_obj) {/*{{{*/ - $charset_list = array( - 'UTF-8', 'EUC-KR', 'CP949', 'ISO-8859-1', 'EUC-JP', 'SHIFT_JIS', 'CP932', - 'EUC-CN', 'HZ', 'GBK', 'GB18030', 'EUC-TW', 'BIG5', 'CP950', 'BIG5-HKSCS', - 'ISO-2022-CN', 'ISO-2022-CN-EXT', 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', - 'ISO-8859-6', 'ISO-8859-8', 'JOHAB', 'ISO-2022-KR', 'CP1255', 'CP1256', 'CP862', - 'ASCII', 'ISO-8859-1', 'ISO-8850-2', 'ISO-8850-3', 'ISO-8850-4', 'ISO-8850-5', - 'ISO-8850-7', 'ISO-8850-9', 'ISO-8850-10', 'ISO-8850-13', 'ISO-8850-14', - 'ISO-8850-15', 'ISO-8850-16', 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254', - 'CP1257', 'CP850', 'CP866', - ); - - $obj = clone($source_obj); - - for($i=0;$i$val) { - if(!$val) continue; - if($val && !iconv($charset,'UTF-8',$val)) $flag = false; + /** + * @brief Context 객체를 GLOBALS 변수에 생성 + * + * Context는 어디서든 객체 선언없이 사용하기 위해서 static 하게 사용\n + * php5라면 GLOBALS가 아닌 static으로 처리 가능 + **/ + function &getInstance() { + if(!$GLOBALS['__ContextInstance__']) $GLOBALS['__ContextInstance__'] = new Context(); + return $GLOBALS['__ContextInstance__']; } - if($flag == true) { - foreach($obj as $key => $val) $obj->{$key} = iconv($charset,'UTF-8',$val); - return $obj; + /** + * @brief DB정보, Request Argument등을 세팅 + * + * Context::init()은 단 한번만 호출되어야 하며 init()시에 + * Request Argument, DB/언어/세션정보등의 모든 정보를 세팅한다 + **/ + function init() { + // context 변수를 $GLOBALS의 변수로 지정 + $this->context = &$GLOBALS['__Context__']; + $this->context->lang = &$GLOBALS['lang']; + + // 인증관련 데이터를 Context에 설정 + $oMember = getModule('member'); + if($oMember->isLogged()) { + $this->_set('is_logged', true); + $this->_set('logged_info', $_SESSION['logged_info']); + } + + // 기본적인 DB정보 세팅 + $this->_loadDBInfo(); + + // 기본 언어파일 로드 + $this->lang = &$GLOBALS['lang']; + $this->_loadLang("./common/lang/"); + + // Request Method 설정 + $this->_setRequestMethod(); + + // Request Argument 설정 + $this->_setXmlRpcArgument(); + $this->_setRequestArgument(); + $this->_setUploadedArgument(); } - } - }/*}}}*/ - /** - * Request Method 및 Argument의 설정 및 return - **/ - // private void _setRequestMethod()/*{{{*/ - // request method가 어떤것인지 판단하여 저장 (GET/POST/XMLRPC) - function _setRequestMethod() { - if($GLOBALS['HTTP_RAW_POST_DATA']) $this->request_method = "XMLRPC"; - else $this->request_method = $_SERVER['REQUEST_METHOD']; - }/*}}}*/ + /** + * @brief DB 정보를 설정하고 DB Type과 DB 정보를 return + **/ + function _loadDBInfo() { + if(!$this->isInstalled()) return; - // private void _setRequestArgument();/*{{{*/ - // GET/POST방식일 경우 처리 - function _setRequestArgument() { - if($this->_getRequestMethod() == 'XMLRPC') return; - if(!count($_REQUEST)) return; - foreach($_REQUEST as $key => $val) { - if(is_array($val)) { - for($i=0;$igetConfigFile(); + if(file_exists($db_config_file)) include $db_config_file; + + $this->_setDBInfo($db_info); } - if(!$val) continue; - if($this->_getRequestMethod()=='GET'&&$_GET[$key]) $set_to_vars = true; - elseif($this->_getRequestMethod()=='POST'&&$_POST[$key]) $set_to_vars = true; - else $set_to_vars = false; - $this->_set($key, $val, $set_to_vars); - } - }/*}}}*/ + /** + * @brief DB의 db_type을 return + **/ + function getDBType() { + $oContext = &Context::getInstance(); + return $oContext->_getDBType(); + } - // private void _setXmlRpcArgument()/*{{{*/ - // XML RPC일때역시 - function _setXmlRpcArgument() { - if($this->_getRequestMethod() != 'XMLRPC') return; - $oXml = new XmlParser(); - $xml_obj = $oXml->parse(); + /** + * @brief DB의 db_type을 return + **/ + function _getDBType() { + return $this->db_info->db_type; + } - $method_name = $xml_obj->methodcall->methodname->body; - $params = $xml_obj->methodcall->params; - unset($params->node_name); + /** + * @brief DB 정보가 담긴 object를 return + **/ + function setDBInfo($db_info) { + $oContext = &Context::getInstance(); + $oContext->_setDBInfo($db_info); + } - unset($params->attrs); - if(!count($params)) return; - foreach($params as $key => $obj) { - $val = trim($obj->body); - $this->_set($key, $val, true); - } - }/*}}}*/ + /** + * @brief DB 정보가 담긴 object를 return + **/ + function _setDBInfo($db_info) { + $this->db_info = $db_info; + } - // public boolean isUploaded() /*{{{*/ - // 업로드 되었을 경우 return true - function isUploaded() { - $oContext = &Context::getInstance(); - return $oContext->_isUploaded(); - }/*}}}*/ + /** + * @brief DB 정보가 담긴 object를 return + **/ + function getDBInfo() { + $oContext = &Context::getInstance(); + return $oContext->_getDBInfo(); + } - // private boolean isUploaded() /*{{{*/ - // 업로드 되었을 경우 return true - function _isUploaded() { - return $this->is_uploaded; - }/*}}}*/ + /** + * @brief DB 정보가 담긴 object를 return + **/ + function _getDBInfo() { + return $this->db_info; + } - // private void _setUploadedArgument()/*{{{*/ - // 업로드된 파일이 있을 경우도 역시 context에 통합 처리 (단 정상적인 업로드인지 체크) - function _setUploadedArgument() { - if($this->_getRequestMethod() != 'POST') return; - if(!eregi("^multipart\/form-data", $_SERVER['CONTENT_TYPE'])) return; - if(!$_FILES) return; + /** + * @brief 사이트 title setting + **/ + function setBrowserTitle($site_title) { + $oContext = &Context::getInstance(); + $oContext->_setBrowserTitle($site_title); + } - foreach($_FILES as $key => $val) { - $tmp_name = $val['tmp_name']; - if(!$tmp_name || !is_uploaded_file($tmp_name)) continue; - $this->_set($key, $val, true); - $this->is_uploaded = true; - } - }/*}}}*/ + /** + * @brief 사이트 title setting + **/ + function _setBrowserTitle($site_title) { + $this->site_title = $site_title; + } - // public string getRequestMethod()/*{{{*/ - // Request Method값을 return (GET/POST/XMLRPC); - function getRequestMethod() { - $oContext = &Context::getInstance(); - return $oContext->_getRequestMethod(); - }/*}}}*/ + /** + * @brief 사이트 title return + **/ + function getBrowserTitle() { + $oContext = &Context::getInstance(); + return $oContext->_getBrowserTitle(); + } - // private string _getRequestMethod()/*{{{*/ - function _getRequestMethod() { - return $this->request_method; - }/*}}}*/ + /** + * @brief 사이트 title return + **/ + function _getBrowserTitle() { + return $this->site_title; + } - // public string getUrl($num_args, $args_list)/*{{{*/ - // 요청받은 url에 args_list를 적용하여 return - function getUrl($num_args, $args_list) { - $oContext = &Context::getInstance(); - return $oContext->_getUrl($num_args, $args_list); - }/*}}}*/ + /** + * @brief 지정된 언어파일 로드 + **/ + function loadLang($path) { + $oContext = &Context::getInstance(); + $oContext->_loadLang($path); + } - // private string _getUrl($num_args, $args_list)/*{{{*/ - // 요청받은 url에 args_list를 적용하여 return - function _getUrl($num_args, $args_list) { - if(!is_object($this->get_vars)) $get_vars = null; - else $get_vars = clone($this->get_vars); - for($i=0;$i<$num_args;$i=$i+2) { - $key = $args_list[$i]; - $val = $args_list[$i+1]; - $get_vars->{$key} = trim($val); - } + /** + * @brief 지정된 언어파일 로드 + * + * loaded_lang_files 변수를 이용하여 한번 로드된 파일을 다시 로드하지 않음 + **/ + function _loadLang($path) { + global $lang; + if(substr($path,-1)!='/') $path .= '/'; + $filename = sprintf('%s%s.lang.php', $path, $this->lang_type); + if(!file_exists($filename)) $filename = sprintf('%slang/%s.lang.php', $path, $this->lang_type); + if(!file_exists($filename)) return; + if(in_array($filename, $this->loaded_lang_files)) return; + $this->loaded_lang_files[] = $filename; + include ($filename); + } - $var_count = count(get_object_vars($get_vars)); - if(!$var_count) return; - foreach($get_vars as $key => $val) { - if(!$val) continue; - $url_list[] = sprintf("%s=%s",$key, $val); - } + /** + * @brief lang_type을 세팅 (기본 ko) + **/ + function setLangType($lang_type = 'ko') { + $oContext = &Context::getInstance(); + $oContext->_setLangType($lang); + } - preg_match("/([a-zA-Z\_]+)\.php/i", $_SERVER['PHP_SELF'], $match); - $filename = $match[0]; - if($filename == 'index.php') $filename = ''; + /** + * @brief lang_type을 세팅 (기본 ko) + **/ + function _setLangType($lang_type = 'ko') { + $this->lang_type = $lang_type; + } - return './'.$filename.'?'.htmlspecialchars(implode('&', $url_list)); - }/*}}}*/ + /** + * @brief lang_type을 return + **/ + function getLangType() { + $oContext = &Context::getInstance(); + return $oContext->_getLangType(); + } - // public string getRequestUri() /*{{{*/ - function getRequestUri() { - $hostname = $_SERVER['SERVER_NAME']; - $port = $_SERVER['SERVER_PORT']; - if($port!=80) $hostname .= ":{$port}"; - $path = $_SERVER['REDIRECT_URL']; - $path = $_SERVER['REDIRECT_URL']?$_SERVER['REDIRECT_URL']:preg_replace('/([a-zA-Z0-9\_]+).php/i','',$_SERVER['PHP_SELF']); - return sprintf("http://%s%s",$hostname,$path); - }/*}}}*/ + /** + * @brief lang_type을 return + **/ + function _getLangType() { + return $this->lang_type; + } - /** - * Request Argument외의 데이터 set/get - **/ - // public void set($key, $val, $set_to_get_vars = false)/*{{{*/ - // key/val 로 데이터 세팅 - function set($key, $val, $set_to_get_vars = false) { - $oContext = &Context::getInstance(); - $oContext->_set($key, $val, $set_to_get_vars); - }/*}}}*/ + /** + * @brief code에 해당하는 문자열을 return + * + * 만약 code에 해당하는 문자열이 없다면 code를 그대로 리턴 + **/ + function getLang($code) { + if($GLOBALS['lang']->{$code}) return $GLOBALS['lang']->{$code}; + return $code; + } - // private void _set($key, $val, $set_to_get_vars = false)/*{{{*/ - function _set($key, $val, $set_to_get_vars = false) { - $this->context->{$key} = $val; - if($set_to_get_vars || $this->get_vars->{$key}) $this->get_vars->{$key} = $val; - }/*}}}*/ + /** + * @brief 직접 lang 변수에 데이터를 추가 + **/ + function setLang($code, $val) { + $GLOBALS['lang']->{$code} = $val; + } - // public object get($key)/*{{{*/ - // key값에 해당하는 값을 return - function get($key) { - $oContext = &Context::getInstance(); - return $oContext->_get($key); - }/*}}}*/ + /** + * @brief object내의 variables의 문자열을 utf8로 변경 + **/ + function convertEncoding($source_obj) { + $charset_list = array( + 'UTF-8', 'EUC-KR', 'CP949', 'ISO-8859-1', 'EUC-JP', 'SHIFT_JIS', 'CP932', + 'EUC-CN', 'HZ', 'GBK', 'GB18030', 'EUC-TW', 'BIG5', 'CP950', 'BIG5-HKSCS', + 'ISO-2022-CN', 'ISO-2022-CN-EXT', 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', + 'ISO-8859-6', 'ISO-8859-8', 'JOHAB', 'ISO-2022-KR', 'CP1255', 'CP1256', 'CP862', + 'ASCII', 'ISO-8859-1', 'ISO-8850-2', 'ISO-8850-3', 'ISO-8850-4', 'ISO-8850-5', + 'ISO-8850-7', 'ISO-8850-9', 'ISO-8850-10', 'ISO-8850-13', 'ISO-8850-14', + 'ISO-8850-15', 'ISO-8850-16', 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254', + 'CP1257', 'CP850', 'CP866', + ); - // private object _get($key)/*{{{*/ - function _get($key) { - return $this->context->{$key}; - }/*}}}*/ + $obj = clone($source_obj); - // public object gets(void)/*{{{*/ - // 받고자 하는 변수만 object에 입력하여 받음 - function gets() { - $num_args = func_num_args(); - if($num_args<1) return; - $args_list = func_get_args(); + for($i=0;$i$val) { + if(!$val) continue; + if($val && !iconv($charset,'UTF-8',$val)) $flag = false; + } + if($flag == true) { + foreach($obj as $key => $val) $obj->{$key} = iconv($charset,'UTF-8',$val); + return $obj; + } + } + } - $oContext = &Context::getInstance(); - return $oContext->_gets($num_args, $args_list); - }/*}}}*/ + /** + * @brief request method가 어떤것인지 판단하여 저장 (GET/POST/XMLRPC) + **/ + function _setRequestMethod() { + if($GLOBALS['HTTP_RAW_POST_DATA']) $this->request_method = "XMLRPC"; + else $this->request_method = $_SERVER['REQUEST_METHOD']; + } - // private object _gets($args_list)/*{{{*/ - function _gets($num_args, $args_list) { - for($i=0;$i<$num_args;$i++) { - $args = $args_list[$i]; - $output->{$args} = $this->_get($args); - } - return $output; - }/*}}}*/ + /** + * @brief GET/POST방식일 경우 처리 + **/ + function _setRequestArgument() { + if($this->_getRequestMethod() == 'XMLRPC') return; + if(!count($_REQUEST)) return; + foreach($_REQUEST as $key => $val) { + if(is_array($val)) { + for($i=0;$i_getAll(); - }/*}}}*/ + if($this->_getRequestMethod()=='GET'&&$_GET[$key]) $set_to_vars = true; + elseif($this->_getRequestMethod()=='POST'&&$_POST[$key]) $set_to_vars = true; + else $set_to_vars = false; + $this->_set($key, $val, $set_to_vars); + } + } - // private object _getAll()/*{{{*/ - function _getAll() { - return $this->context; - }/*}}}*/ + /** + * @brief XML RPC일때역시 + **/ + function _setXmlRpcArgument() { + if($this->_getRequestMethod() != 'XMLRPC') return; + $oXml = new XmlParser(); + $xml_obj = $oXml->parse(); - // public object getRequestVars()/*{{{*/ - // GET/POST/XMLRPC에서 넘어온 변수값을 return - function getRequestVars() { - $oContext = &Context::getInstance(); - return $oContext->_getRequestVars(); - }/*}}}*/ + $method_name = $xml_obj->methodcall->methodname->body; + $params = $xml_obj->methodcall->params; + unset($params->node_name); - // private object _getRequestVars()/*{{{*/ - function _getRequestVars() { - return clone($this->get_vars); - }/*}}}*/ + unset($params->attrs); + if(!count($params)) return; - /** - * CSS/JS/HeaderText 등 html을 출력할때 사용할 값들 - **/ - // public void addJsFile($file)/*{{{*/ - // js file 추가 - function addJsFile($file) { - $oContext = &Context::getInstance(); - return $oContext->_addJsFile($file); - }/*}}}*/ + foreach($params as $key => $obj) { + $val = trim($obj->body); + $this->_set($key, $val, true); + } + } - // private void _addJsFile($file)/*{{{*/ - function _addJsFile($file) { - if(in_array($file, $this->js_files)) return; - $this->js_files[] = $file; - }/*}}}*/ + /** + * @brief 업로드 되었을 경우 return true + **/ + function isUploaded() { + $oContext = &Context::getInstance(); + return $oContext->_isUploaded(); + } - // public array getJsFile()/*{{{*/ - function getJsFile() { - $oContext = &Context::getInstance(); - return $oContext->_getJsFile(); - }/*}}}*/ + /** + * @brief 업로드 되었을 경우 return true + **/ + function _isUploaded() { + return $this->is_uploaded; + } - // private array _getJsFile()/*{{{*/ - function _getJsFile() { - return $this->js_files; - }/*}}}*/ + /** + * @brief 업로드된 파일이 있을 경우도 역시 context에 통합 처리 (단 정상적인 업로드인지 체크) + **/ + function _setUploadedArgument() { + if($this->_getRequestMethod() != 'POST') return; + if(!eregi("^multipart\/form-data", $_SERVER['CONTENT_TYPE'])) return; + if(!$_FILES) return; - // public void addCSSFile($file)/*{{{*/ - // CSS file 추가 - function addCSSFile($file) { - $oContext = &Context::getInstance(); - return $oContext->_addCSSFile($file); - }/*}}}*/ + foreach($_FILES as $key => $val) { + $tmp_name = $val['tmp_name']; + if(!$tmp_name || !is_uploaded_file($tmp_name)) continue; + $this->_set($key, $val, true); + $this->is_uploaded = true; + } + } - // private void _addCSSFile($file)/*{{{*/ - function _addCSSFile($file) { - if(in_array($file, $this->css_files)) return; - $this->css_files[] = $file; - }/*}}}*/ + /** + * @brief Request Method값을 return (GET/POST/XMLRPC); + **/ + function getRequestMethod() { + $oContext = &Context::getInstance(); + return $oContext->_getRequestMethod(); + } - // public array getCSSFile()/*{{{*/ - // CSS file 추가 - function getCSSFile() { - $oContext = &Context::getInstance(); - return $oContext->_getCSSFile(); - }/*}}}*/ + /** + * @brief Request Method값을 return (GET/POST/XMLRPC); + **/ + function _getRequestMethod() { + return $this->request_method; + } - // private array _getCSSFile()/*{{{*/ - function _getCSSFile() { - return $this->css_files; - }/*}}}*/ + /** + * @brief 요청받은 url에 args_list를 적용하여 return + **/ + function getUrl($num_args, $args_list) { + $oContext = &Context::getInstance(); + return $oContext->_getUrl($num_args, $args_list); + } - // public void addHtmlHeader($file)/*{{{*/ - // HtmlHeader 추가 - function addHtmlHeader($file) { - $oContext = &Context::getInstance(); - return $oContext->_addHtmlHeader($file); - }/*}}}*/ + /** + * @brief 요청받은 url에 args_list를 적용하여 return + **/ + function _getUrl($num_args, $args_list) { + if(!is_object($this->get_vars)) $get_vars = null; + else $get_vars = clone($this->get_vars); - // private void _addHtmlHeader($file)/*{{{*/ - function _addHtmlHeader($file) { - $this->HtmlHeader .= ($this->HtmlHeader?"\n":"").$file; - }/*}}}*/ + for($i=0;$i<$num_args;$i=$i+2) { + $key = $args_list[$i]; + $val = $args_list[$i+1]; + $get_vars->{$key} = trim($val); + } - // public string getHtmlHeader()/*{{{*/ - // HtmlHeader 추가 - function getHtmlHeader() { - $oContext = &Context::getInstance(); - return $oContext->_getHtmlHeader(); - }/*}}}*/ + $var_count = count(get_object_vars($get_vars)); + if(!$var_count) return; - // private string _getHtmlHeader()/*{{{*/ - function _getHtmlHeader() { - return $this->HtmlHeader; - }/*}}}*/ + foreach($get_vars as $key => $val) { + if(!$val) continue; + $url_list[] = sprintf("%s=%s",$key, $val); + } - /** - * 인스톨 관련 - **/ - // public String getConfigFile()/*{{{*/ - // db설정내용이 저장되어 있는 config file의 path를 return - function getConfigFile() { - return "./files/config/db.config.php"; - }/*}}}*/ - - // public boolean isInstalled()/*{{{*/ - // 설치가 되어 있는지에 대한 체크 - function isInstalled() { - return file_exists(Context::getConfigFile()); - }/*}}}*/ + preg_match("/([a-zA-Z\_]+)\.php/i", $_SERVER['PHP_SELF'], $match); + $filename = $match[0]; + if($filename == 'index.php') $filename = ''; - } + return './'.$filename.'?'.htmlspecialchars(implode('&', $url_list)); + } + + /** + * @brief 요청이 들어온 URL에서 argument를 제거하여 return + **/ + function getRequestUri() { + $hostname = $_SERVER['SERVER_NAME']; + $port = $_SERVER['SERVER_PORT']; + if($port!=80) $hostname .= ":{$port}"; + $path = $_SERVER['REDIRECT_URL']; + $path = $_SERVER['REDIRECT_URL']?$_SERVER['REDIRECT_URL']:preg_replace('/([a-zA-Z0-9\_]+).php/i','',$_SERVER['PHP_SELF']); + return sprintf("http://%s%s",$hostname,$path); + } + + /** + * @brief key/val로 context vars 세팅 + **/ + function set($key, $val, $set_to_get_vars = false) { + $oContext = &Context::getInstance(); + $oContext->_set($key, $val, $set_to_get_vars); + } + + /** + * @brief key/val로 context vars 세팅 + **/ + function _set($key, $val, $set_to_get_vars = false) { + $this->context->{$key} = $val; + if($set_to_get_vars || $this->get_vars->{$key}) $this->get_vars->{$key} = $val; + } + + /** + * @brief key값에 해당하는 값을 return + **/ + function get($key) { + $oContext = &Context::getInstance(); + return $oContext->_get($key); + } + + /** + * @brief key값에 해당하는 값을 return + **/ + function _get($key) { + return $this->context->{$key}; + } + + /** + * @brief 받고자 하는 변수만 object에 입력하여 받음 + * + * key1, key2, key3 .. 등의 인자를 주어 여러개의 변수를 object vars로 세팅하여 받을 수 있음 + **/ + function gets() { + $num_args = func_num_args(); + if($num_args<1) return; + $args_list = func_get_args(); + + $oContext = &Context::getInstance(); + return $oContext->_gets($num_args, $args_list); + } + + /** + * @brief 받고자 하는 변수만 object에 입력하여 받음 + * + * key1, key2, key3 .. 등의 인자를 주어 여러개의 변수를 object vars로 세팅하여 받을 수 있음 + **/ + function _gets($num_args, $args_list) { + for($i=0;$i<$num_args;$i++) { + $args = $args_list[$i]; + $output->{$args} = $this->_get($args); + } + return $output; + } + + /** + * @brief 모든 데이터를 return + **/ + function getAll() { + $oContext = &Context::getInstance(); + return $oContext->_getAll(); + } + + /** + * @brief 모든 데이터를 return + **/ + function _getAll() { + return $this->context; + } + + /** + * @brief GET/POST/XMLRPC에서 넘어온 변수값을 return + **/ + function getRequestVars() { + $oContext = &Context::getInstance(); + return $oContext->_getRequestVars(); + } + + /** + * @brief GET/POST/XMLRPC에서 넘어온 변수값을 return + **/ + function _getRequestVars() { + return clone($this->get_vars); + } + + /** + * @brief js file을 추가 + **/ + function addJsFile($file) { + $oContext = &Context::getInstance(); + return $oContext->_addJsFile($file); + } + + /** + * @brief js file을 추가 + **/ + function _addJsFile($file) { + if(in_array($file, $this->js_files)) return; + $this->js_files[] = $file; + } + + /** + * @brief js file 목록을 return + **/ + function getJsFile() { + $oContext = &Context::getInstance(); + return $oContext->_getJsFile(); + } + + /** + * @brief js file 목록을 return + **/ + function _getJsFile() { + return $this->js_files; + } + + /** + * @brief CSS file 추가 + **/ + function addCSSFile($file) { + $oContext = &Context::getInstance(); + return $oContext->_addCSSFile($file); + } + + /** + * @brief CSS file 추가 + **/ + function _addCSSFile($file) { + if(in_array($file, $this->css_files)) return; + $this->css_files[] = $file; + } + + /** + * @brief CSS file 목록 return + **/ + function getCSSFile() { + $oContext = &Context::getInstance(); + return $oContext->_getCSSFile(); + } + + /** + * @brief CSS file 목록 return + **/ + function _getCSSFile() { + return $this->css_files; + } + + /** + * @brief HtmlHeader 추가 + **/ + function addHtmlHeader($file) { + $oContext = &Context::getInstance(); + return $oContext->_addHtmlHeader($file); + } + + /** + * @brief HtmlHeader 추가 + **/ + function _addHtmlHeader($file) { + $this->HtmlHeader .= ($this->HtmlHeader?"\n":"").$file; + } + + /** + * @brief HtmlHeader return + **/ + function getHtmlHeader() { + $oContext = &Context::getInstance(); + return $oContext->_getHtmlHeader(); + } + + /** + * @brief HtmlHeader return + **/ + function _getHtmlHeader() { + return $this->HtmlHeader; + } + + /** + * @brief db설정내용이 저장되어 있는 config file의 path를 return + **/ + function getConfigFile() { + return "./files/config/db.config.php"; + } + + /** + * @brief 설치가 되어 있는지에 대한 체크 + * + * 단순히 db config 파일의 존재 유무로 설치 여부를 체크한다 + **/ + function isInstalled() { + return file_exists(Context::getConfigFile()); + } + + } ?> diff --git a/classes/db/DB.class.php b/classes/db/DB.class.php index 59dffa7b9..3f301f08c 100644 --- a/classes/db/DB.class.php +++ b/classes/db/DB.class.php @@ -1,237 +1,249 @@ - * @desc : DB*의 상위 클래스 - **/ - - class DB { - - // connector resource or file description - var $fd = NULL; - - // result - var $result = NULL; - - // errno, errstr - var $errno = 0; - var $errstr = ''; - var $query = ''; - - // isconnected - var $is_connected = false; - - // 지원하는 DB의 종류 - var $supported_list = array(); - - // public Object &getInstance($db_type)/*{{{*/ - // DB를 상속받는 특정 db type의 instance를 생성 후 return - function &getInstance($db_type = NULL) { - if(!$db_type) $db_type = Context::getDBType(); - if(!$db_type) return new Output(-1, 'msg_db_not_setted'); - - if(!$GLOBALS['__DB__']) { - $class_name = sprintf("DB%s%s", strtoupper(substr($db_type,0,1)), strtolower(substr($db_type,1))); - $class_file = sprintf("./classes/db/%s.class.php", $class_name); - if(!file_exists($class_file)) new Output(-1, 'msg_db_not_setted'); - - require_once($class_file); - $eval_str = sprintf('$GLOBALS[\'__DB__\'] = new %s();', $class_name); - eval($eval_str); - } - - return $GLOBALS['__DB__']; - }/*}}}*/ - /** - * 지원 가능한 DB 목록을 return - **/ - // public array getSupportedList()/*{{{*/ - // 지원하는 DB의 종류 return - function getSupportedList() { - $oDB = new DB(); - return $oDB->_getSupportedList(); - }/*}}}*/ + * @class DB + * @author zero (zero@nzeo.com) + * @brief DB*의 상위 클래스 + * + * 제로보드5의 DB 사용은 xml을 이용하여 이루어짐을 원칙으로 한다.\n + * xml의 종류에는 query xml, schema xml이 있다.\n + * query xml의 경우 DB::executeQuery() method를 이용하여 xml파일을\n + * php code로 compile한 후에 실행이 된다.\n + * query xml은 고유한 query id를 가지며 생성은 module에서 이루어진다.\n + * \n + * queryid = 모듈.쿼리명\n + * \n + * 으로 된다.\n + **/ - // private array _getSupportedList()/*{{{*/ - function _getSupportedList() { - if(!count($this->supported_list)) { - $db_classes_path = "./classes/db/"; - $filter = "/^DB([^\.]+)\.class\.php/i"; - $this->supported_list = FileHandler::readDir($db_classes_path, $filter, true); - } - return $this->supported_list; - }/*}}}*/ + class DB { - // public boolean isSupported($db_type) /*{{{*/ - // 지원하는 DB인지에 대한 check - function isSupported($db_type) { - $supported_list = DB::getSupportedList(); - return in_array($db_type, $supported_list); - }/*}}}*/ + var $fd = NULL; ///< connector resource or file description - /** - * 에러 남기기 - **/ - // public void setError($errno, $errstr) /*{{{*/ - function setError($errno, $errstr) { - $this->errno = $errno; - $this->errstr = $errstr; + var $result = NULL; ///< result - if(__DEBUG__ && $this->errno!=0) debugPrint(sprintf("Query Fail\t#%05d : %s - %s\n\t\t%s", $GLOBALS['__dbcnt'], $errno, $errstr, $this->query)); - }/*}}}*/ + var $errno = 0; ///< 에러 발생시 에러 코드 (0이면 에러가 없다고 정의) + var $errstr = ''; ///< 에러 발생시 에러 메세지 + var $query = ''; ///< 가장 최근에 수행된 query string - /** - * 각종 bool 값 return - **/ - // public boolean isConnected()/*{{{*/ - // 접속되었는지 return - function isConnected() { - return $this->is_connected; - }/*}}}*/ + var $is_connected = false; ///< DB에 접속이 되었는지에 대한 flag - // public boolean isError()/*{{{*/ - // 오류가 발생하였는지 return - function isError() { - return $error===0?true:false; - }/*}}}*/ + var $supported_list = array(); ///< 지원하는 DB의 종류, classes/DB/DB***.class.php 를 이용하여 동적으로 작성됨 - // public object getError()/*{{{*/ - function getError() { - return new Output($this->errno, $this->errstr); - }/*}}}*/ + /** + * @brief DB를 상속받는 특정 db type의 instance를 생성 후 return + **/ + function &getInstance($db_type = NULL) { + if(!$db_type) $db_type = Context::getDBType(); + if(!$db_type) return new Output(-1, 'msg_db_not_setted'); - /** - * query execute - **/ - // public object executeQuery($query_id, $args = NULL)/*{{{*/ - // query_id = module.queryname - // query_id에 해당하는 xml문(or 캐싱파일)을 찾아서 실행 - function executeQuery($query_id, $args = NULL) { - if(!$query_id) return new Output(-1, 'msg_invalid_queryid'); + if(!$GLOBALS['__DB__']) { + $class_name = sprintf("DB%s%s", strtoupper(substr($db_type,0,1)), strtolower(substr($db_type,1))); + $class_file = sprintf("./classes/db/%s.class.php", $class_name); + if(!file_exists($class_file)) new Output(-1, 'msg_db_not_setted'); - list($module, $id) = explode('.',$query_id); - if(!$module||!$id) return new Output(-1, 'msg_invalid_queryid'); + require_once($class_file); + $eval_str = sprintf('$GLOBALS[\'__DB__\'] = new %s();', $class_name); + eval($eval_str); + } - $xml_file = sprintf('./modules/%s/queries/%s.xml', $module, $id); - if(!file_exists($xml_file)) { - $xml_file = sprintf('./files/modules/%s/queries/%s.xml', $module, $id); - if(!file_exists($xml_file)) return new Output(-1, 'msg_invalid_queryid'); - } - - // 일단 cache 파일을 찾아본다 - $cache_file = sprintf('./files/queries/%s.cache.php', $query_id); - - // 없으면 원본 쿼리 xml파일을 찾아서 파싱을 한다 - if(!file_exists($cache_file)||filectime($cache_file)parse($query_id, $xml_file, $cache_file); - } - - // 쿼리를 실행한다 - return $this->_executeQuery($cache_file, $args, $query_id); - }/*}}}*/ - - // private object _executeQuery($cache_file, $args)/*{{{*/ - // 쿼리문을 실행하고 결과를 return한다 - function _executeQuery($cache_file, $source_args, $query_id) { - global $lang; - - if(!file_exists($cache_file)) return new Output(-1, 'msg_invalid_queryid'); - - if(__DEBUG__) $query_start = getMicroTime(); - - if($source_args) $args = clone($source_args); - $output = include($cache_file); - - if( (is_a($output, 'Output')||is_subclass_of($output,'Output'))&&!$output->toBool()) return $output; - - // action값에 따라서 쿼리 생성으로 돌입 - switch($action) { - case 'insert' : - $output = $this->_executeInsertAct($tables, $column, $pass_quotes); - break; - case 'update' : - $output = $this->_executeUpdateAct($tables, $column, $condition, $pass_quotes); - break; - case 'delete' : - $output = $this->_executeDeleteAct($tables, $condition, $pass_quotes); - break; - case 'select' : - $output = $this->_executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $group_script, $pass_quotes); - break; - } - - if(__DEBUG__) { - $query_end = getMicroTime(); - $elapsed_time = $query_end - $query_start; - $GLOBALS['__db_elapsed_time__'] += $elapsed_time; - $GLOBALS['__db_queries__'] .= sprintf("\t%02d. %s (%0.4f sec)\n\t %s\n", ++$GLOBALS['__dbcnt'], $query_id, $elapsed_time, $this->query); - } - - if($this->errno!=0) return new Output($this->errno, $this->errstr); - if(is_a($output, 'Output') || is_subclass_of($output, 'Output')) return $output; - return new Output(); - }/*}}}*/ - - // private object _checkFilter($key, $val, $filter_type, $minlength, $maxlength) /*{{{*/ - // $val을 $filter_type으로 검사 - function _checkFilter($key, $val, $filter_type, $minlength, $maxlength) { - global $lang; - - $length = strlen($val); - if($minlength && $length < $minlength) return new Output(-1, sprintf($lang->filter->outofrange, $lang->{$key}?$lang->{$key}:$key)); - if($maxlength && $length > $maxlength) return new Output(-1, sprintf($lang->filter->outofrange, $lang->{$key}?$lang->{$key}:$key)); - - switch($filter_type) { - case 'email' : - case 'email_adderss' : - if(!eregi('^[_0-9a-z-]+(\.[_0-9a-z-]+)*@[0-9a-z-]+(\.[0-9a-z-]+)*$', $val)) return new Output(-1, sprintf($lang->filter->invalid_email, $lang->{$key}?$lang->{$key}:$key)); - break; - case 'homepage' : - if(!eregi('^(http|https)+(:\/\/)+[0-9a-z_-]+\.[^ ]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_homepage, $lang->{$key}?$lang->{$key}:$key)); - break; - case 'userid' : - case 'user_id' : - if(!eregi('^[a-zA-Z]+([_0-9a-zA-Z]+)*$', $val)) return new Output(-1, sprintf($lang->filter->invalid_userid, $lang->{$key}?$lang->{$key}:$key)); - break; - case 'number' : - if(!eregi('^[0-9]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_number, $lang->{$key}?$lang->{$key}:$key)); - break; - case 'alpha' : - if(!eregi('^[a-z]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_alpha, $lang->{$key}?$lang->{$key}:$key)); - break; - case 'alpha_number' : - if(!eregi('^[0-9a-z]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_alpha_number, $lang->{$key}?$lang->{$key}:$key)); - break; - } - - return new Output(); - }/*}}}*/ - - // private string _combineCondition($cond_group, $group_pipe) /*{{{*/ - function _combineCondition($cond_group, $group_pipe) { - if(!is_array($cond_group)) return; - $cond_query = ''; - foreach($cond_group as $group_idx => $group) { - if(!is_array($group)) continue; - - $buff = ''; - foreach($group as $key => $val) { - $pipe = key($val); - $cond = array_pop($val); - if($buff) $buff .= $pipe.' '.$cond; - else $buff = $cond; + return $GLOBALS['__DB__']; } - $g_pipe = $group_pipe[$group_idx]; - if(!$g_pipe) $g_pipe = 'and'; - if($cond_query) $cond_query .= sprintf(' %s ( %s )', $g_pipe, $buff); - else $cond_query = '('.$buff.')'; - } - return $cond_query; - }/*}}}*/ + /** + * @brief 지원 가능한 DB 목록을 return + **/ + function getSupportedList() { + $oDB = new DB(); + return $oDB->_getSupportedList(); + } - } + /** + * @brief 지원 가능한 DB 목록을 return + **/ + function _getSupportedList() { + if(!count($this->supported_list)) { + $db_classes_path = "./classes/db/"; + $filter = "/^DB([^\.]+)\.class\.php/i"; + $this->supported_list = FileHandler::readDir($db_classes_path, $filter, true); + } + return $this->supported_list; + } + + /** + * @brief 지원하는 DB인지에 대한 check + **/ + function isSupported($db_type) { + $supported_list = DB::getSupportedList(); + return in_array($db_type, $supported_list); + } + + /** + * @brief 에러발생시 에러 메세지를 남기고 debug 모드일때는 GLOBALS 변수에 에러 로깅 + **/ + function setError($errno, $errstr) { + $this->errno = $errno; + $this->errstr = $errstr; + + if(__DEBUG__ && $this->errno!=0) debugPrint(sprintf("Query Fail\t#%05d : %s - %s\n\t\t%s", $GLOBALS['__dbcnt'], $errno, $errstr, $this->query)); + } + + /** + * @brief 접속되었는지 return + **/ + function isConnected() { + return $this->is_connected; + } + + /** + * @brief 오류가 발생하였는지 return + **/ + function isError() { + return $error===0?true:false; + } + + /** + * @brief 에러결과를 Output 객체로 return + **/ + function getError() { + return new Output($this->errno, $this->errstr); + } + + /** + * @brief query xml 파일을 실행하여 결과를 return + * + * query_id = module.queryname + * query_id에 해당하는 xml문(or 캐싱파일)을 찾아서 컴파일 후 실행 + **/ + function executeQuery($query_id, $args = NULL) { + if(!$query_id) return new Output(-1, 'msg_invalid_queryid'); + + list($module, $id) = explode('.',$query_id); + if(!$module||!$id) return new Output(-1, 'msg_invalid_queryid'); + + $xml_file = sprintf('./modules/%s/queries/%s.xml', $module, $id); + if(!file_exists($xml_file)) { + $xml_file = sprintf('./files/modules/%s/queries/%s.xml', $module, $id); + if(!file_exists($xml_file)) return new Output(-1, 'msg_invalid_queryid'); + } + + // 일단 cache 파일을 찾아본다 + $cache_file = sprintf('./files/queries/%s.cache.php', $query_id); + + // 없으면 원본 쿼리 xml파일을 찾아서 파싱을 한다 + if(!file_exists($cache_file)||filectime($cache_file)parse($query_id, $xml_file, $cache_file); + } + + // 쿼리를 실행한다 + return $this->_executeQuery($cache_file, $args, $query_id); + } + + /** + * @brief 쿼리문을 실행하고 결과를 return한다 + **/ + function _executeQuery($cache_file, $source_args, $query_id) { + global $lang; + + if(!file_exists($cache_file)) return new Output(-1, 'msg_invalid_queryid'); + + if(__DEBUG__) $query_start = getMicroTime(); + + if($source_args) $args = clone($source_args); + $output = include($cache_file); + + if( (is_a($output, 'Output')||is_subclass_of($output,'Output'))&&!$output->toBool()) return $output; + + // action값에 따라서 쿼리 생성으로 돌입 + switch($action) { + case 'insert' : + $output = $this->_executeInsertAct($tables, $column, $pass_quotes); + break; + case 'update' : + $output = $this->_executeUpdateAct($tables, $column, $condition, $pass_quotes); + break; + case 'delete' : + $output = $this->_executeDeleteAct($tables, $condition, $pass_quotes); + break; + case 'select' : + $output = $this->_executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $group_script, $pass_quotes); + break; + } + + if(__DEBUG__) { + $query_end = getMicroTime(); + $elapsed_time = $query_end - $query_start; + $GLOBALS['__db_elapsed_time__'] += $elapsed_time; + $GLOBALS['__db_queries__'] .= sprintf("\t%02d. %s (%0.4f sec)\n\t %s\n", ++$GLOBALS['__dbcnt'], $query_id, $elapsed_time, $this->query); + } + + if($this->errno!=0) return new Output($this->errno, $this->errstr); + if(is_a($output, 'Output') || is_subclass_of($output, 'Output')) return $output; + return new Output(); + } + + /** + * @brief $val을 $filter_type으로 검사 + **/ + function _checkFilter($key, $val, $filter_type, $minlength, $maxlength) { + global $lang; + + $length = strlen($val); + if($minlength && $length < $minlength) return new Output(-1, sprintf($lang->filter->outofrange, $lang->{$key}?$lang->{$key}:$key)); + if($maxlength && $length > $maxlength) return new Output(-1, sprintf($lang->filter->outofrange, $lang->{$key}?$lang->{$key}:$key)); + + switch($filter_type) { + case 'email' : + case 'email_adderss' : + if(!eregi('^[_0-9a-z-]+(\.[_0-9a-z-]+)*@[0-9a-z-]+(\.[0-9a-z-]+)*$', $val)) return new Output(-1, sprintf($lang->filter->invalid_email, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'homepage' : + if(!eregi('^(http|https)+(:\/\/)+[0-9a-z_-]+\.[^ ]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_homepage, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'userid' : + case 'user_id' : + if(!eregi('^[a-zA-Z]+([_0-9a-zA-Z]+)*$', $val)) return new Output(-1, sprintf($lang->filter->invalid_userid, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'number' : + if(!eregi('^[0-9]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_number, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'alpha' : + if(!eregi('^[a-z]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_alpha, $lang->{$key}?$lang->{$key}:$key)); + break; + case 'alpha_number' : + if(!eregi('^[0-9a-z]+$', $val)) return new Output(-1, sprintf($lang->filter->invalid_alpha_number, $lang->{$key}?$lang->{$key}:$key)); + break; + } + + return new Output(); + } + + /** + * @brief 조건문들 정리 + **/ + function _combineCondition($cond_group, $group_pipe) { + if(!is_array($cond_group)) return; + $cond_query = ''; + + foreach($cond_group as $group_idx => $group) { + if(!is_array($group)) continue; + + $buff = ''; + foreach($group as $key => $val) { + $pipe = key($val); + $cond = array_pop($val); + if($buff) $buff .= $pipe.' '.$cond; + else $buff = $cond; + } + + $g_pipe = $group_pipe[$group_idx]; + if(!$g_pipe) $g_pipe = 'and'; + if($cond_query) $cond_query .= sprintf(' %s ( %s )', $g_pipe, $buff); + else $cond_query = '('.$buff.')'; + } + return $cond_query; + } + + } ?> diff --git a/classes/db/DBMysql.class.php b/classes/db/DBMysql.class.php index bac4ae71a..72c151366 100644 --- a/classes/db/DBMysql.class.php +++ b/classes/db/DBMysql.class.php @@ -1,375 +1,405 @@ - * @desc : db(mysql, cubrid, sqlite..)를 이용하기 위한 db class의 abstract class - **/ + /** + * @class DBMysql + * @author zero (zero@nzeo.com) + * @brief mysql handling class + **/ - class DBMysql extends DB { + class DBMysql extends DB { - // db info - var $hostname = '127.0.0.1'; - var $userid = NULL; - var $password = NULL; - var $database = NULL; - var $prefix = 'zb'; + var $hostname = '127.0.0.1'; ///< hostname + var $userid = NULL; ///< user id + var $password = NULL; ///< password + var $database = NULL; ///< database + var $prefix = 'zb'; ///< 제로보드에서 사용할 테이블들의 prefix (한 DB에서 여러개의 제로보드 설치 가능) - // mysql에서 사용될 column type - var $column_type = array( - 'number' => 'int', - 'varchar' => 'varchar', - 'char' => 'char', - 'text' => 'text', - 'date' => 'varchar(14)', + /** + * @brief mysql에서 사용될 column type + * + * column_type은 schema/query xml에서 공통 선언된 type을 이용하기 때문에 + * 각 DBMS에 맞게 replace 해주어야 한다 + **/ + var $column_type = array( + 'number' => 'int', + 'varchar' => 'varchar', + 'char' => 'char', + 'text' => 'text', + 'date' => 'varchar(14)', ); - // public void DBMysql()/*{{{*/ - function DBMysql() { - $this->_setDBInfo(); - $this->_connect(); - }/*}}}*/ - - /** - * DB정보 설정 및 connect/ close - **/ - // public boolean _setDBInfo()/*{{{*/ - function _setDBInfo() { - $db_info = Context::getDBInfo(); - $this->hostname = $db_info->db_hostname; - $this->userid = $db_info->db_userid; - $this->password = $db_info->db_password; - $this->database = $db_info->db_database; - $this->prefix = $db_info->db_table_prefix; - if(!substr($this->prefix,-1)!='_') $this->prefix .= '_'; - }/*}}}*/ - - // public boolean _connect()/*{{{*/ - function _connect() { - // db 정보가 없으면 무시 - if(!$this->hostname || !$this->userid || !$this->password || !$this->database) return; - - // 접속시도 - $this->fd = @mysql_connect($this->hostname, $this->userid, $this->password); - if(mysql_error()) { - $this->setError(mysql_errno(), mysql_error()); - return; - } - - // db 선택 - @mysql_select_db($this->database, $this->fd); - if(mysql_error()) { - $this->setError(mysql_errno(), mysql_error()); - return; - } - - // 접속체크 - $this->is_connected = true; - - // mysql의 경우 utf8임을 지정 - $this->_query("SET NAMES 'utf8'"); - }/*}}}*/ - - // public boolean close()/*{{{*/ - function close() { - if(!$this->isConnected()) return; - @mysql_close($this->fd); - }/*}}}*/ - - /** - * add quotation - **/ - // public string addQuotes(string $string)/*{{{*/ - function addQuotes($string) { - if(get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); - if(!is_numeric($string)) $string = @mysql_escape_string($string); - return $string; - }/*}}}*/ - - /** - * query : query문 실행하고 result return - * fetch : reutrn 된 값이 없으면 NULL - * rows이면 array object - * row이면 object - * return - * getNextSequence : 1씩 증가되는 sequence값을 return (mysql의 auto_increment는 sequence테이블에서만 사용) - */ - // private object _query(string $query) /*{{{*/ - function _query($query) { - if(!$this->isConnected()) return; - $this->query = $query; - - $this->setError(0,'success'); - - $result = @mysql_query($query, $this->fd); - - if(mysql_error()) { - $this->setError(mysql_errno(), mysql_error()); - return; - } - - return $result; - }/*}}}*/ - - // private object _fetch($result) /*{{{*/ - function _fetch($result) { - if($this->errno!=0 || !$result) return; - while($tmp = mysql_fetch_object($result)) { - $output[] = $tmp; - } - if(count($output)==1) return $output[0]; - return $output; - }/*}}}*/ - - // public int getNextSequence() /*{{{*/ - // sequence값을 받음 - function getNextSequence() { - $query = sprintf("insert into `%ssequence` (seq) values ('')", $this->prefix); - $this->_query($query); - return mysql_insert_id(); - }/*}}}*/ - - /** - * Table의 Create/Drop/Alter/Rename/Truncate/Dump... - **/ - // public boolean isTableExists(string $table_name)/*{{{*/ - function isTableExists($target_name) { - $query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name)); - $result = $this->_query($query); - $tmp = $this->_fetch($result); - if(!$tmp) return false; - return true; - }/*}}}*/ - - // public boolean createTableByXml($xml) /*{{{*/ - // xml 을 받아서 테이블을 생성 - function createTableByXml($xml_doc) { - return $this->_createTable($xml_doc); - }/*}}}*/ - - // public boolean createTableByXmlFile($file_name) /*{{{*/ - // xml 을 받아서 테이블을 생성 - function createTableByXmlFile($file_name) { - if(!file_exists($file_name)) return; - // xml 파일을 읽음 - $buff = FileHandler::readFile($file_name); - return $this->_createTable($buff); - }/*}}}*/ - - // private boolean _createTable($xml)/*{{{*/ - // type : number, varchar, text, char, date, - // opt : notnull, default, size - // index : primary key, index, unique - function _createTable($xml_doc) { - // xml parsing - $oXml = new XmlParser(); - $xml_obj = $oXml->parse($xml_doc); - - // 테이블 생성 schema 작성 - $table_name = $xml_obj->table->attrs->name; - if($this->isTableExists($table_name)) return; - $table_name = $this->prefix.$table_name; - - if(!is_array($xml_obj->table->column)) $columns[] = $xml_obj->table->column; - else $columns = $xml_obj->table->column; - foreach($columns as $column) { - $name = $column->attrs->name; - $type = $column->attrs->type; - $size = $column->attrs->size; - $notnull = $column->attrs->notnull; - $primary_key = $column->attrs->primary_key; - $index = $column->attrs->index; - $unique = $column->attrs->unique; - $default = $column->attrs->default; - $auto_increment = $column->attrs->auto_increment; - - $column_schema[] = sprintf('`%s` %s%s %s %s %s', - $name, - $this->column_type[$type], - $size?'('.$size.')':'', - $default?"default '".$default."'":'', - $notnull?'not null':'', - $auto_increment?'auto_increment':'' - ); - - if($primary_key) $primary_list[] = $name; - else if($unique) $unique_list[$unique][] = $name; - else if($index) $index_list[$index][] = $name; - } - - if(count($primary_list)) { - $column_schema[] = sprintf("primary key (%s)", '`'.implode($primary_list,'`,`').'`'); - } - - if(count($unique_list)) { - foreach($unique_list as $key => $val) { - $column_schema[] = sprintf("unique %s (%s)", $key, '`'.implode($val,'`,`').'`'); + /** + * @brief constructor + **/ + function DBMysql() { + $this->_setDBInfo(); + $this->_connect(); } - } - if(count($index_list)) { - foreach($index_list as $key => $val) { - $column_schema[] = sprintf("index %s (%s)", $key, '`'.implode($val,'`,`').'`'); + /** + * @brief DB정보 설정 및 connect/ close + **/ + function _setDBInfo() { + $db_info = Context::getDBInfo(); + $this->hostname = $db_info->db_hostname; + $this->userid = $db_info->db_userid; + $this->password = $db_info->db_password; + $this->database = $db_info->db_database; + $this->prefix = $db_info->db_table_prefix; + if(!substr($this->prefix,-1)!='_') $this->prefix .= '_'; } - } - $schema = sprintf('create table `%s` (%s%s);', $this->addQuotes($table_name), "\n", implode($column_schema,",\n")); - $output = $this->_query($schema); - if(!$output) return false; - }/*}}}*/ + /** + * @brief DB 접속 + **/ + function _connect() { + // db 정보가 없으면 무시 + if(!$this->hostname || !$this->userid || !$this->password || !$this->database) return; - // public boolean dropTable($target_name) /*{{{*/ - // 테이블 삭제 - function dropTable($target_name) { - $query = sprintf('drop table `%s%s`;', $this->prefix, $this->addQuotes($target_name)); - $this->_query($query); - }/*}}}*/ + // 접속시도 + $this->fd = @mysql_connect($this->hostname, $this->userid, $this->password); + if(mysql_error()) { + $this->setError(mysql_errno(), mysql_error()); + return; + } - // public boolean renameTable($source_name, $targe_name) /*{{{*/ - // 테이블의 이름 변경 - function renameTable($source_name, $targe_name) { - $query = sprintf("alter table `%s%s` rename `%s%s`;", $this->prefix, $this->addQuotes($source_name), $this->prefix, $this->addQuotes($targe_name)); - $this->_query($query); - }/*}}}*/ + // db 선택 + @mysql_select_db($this->database, $this->fd); + if(mysql_error()) { + $this->setError(mysql_errno(), mysql_error()); + return; + } - // public boolean truncateTable($target_name) /*{{{*/ - // 테이블을 비움 - function truncateTable($target_name) { - $query = sprintf("truncate table `%s%s`;", $this->prefix, $this->addQuotes($target_name)); - $this->_query($query); - }/*}}}*/ + // 접속체크 + $this->is_connected = true; - // public boolean dumpTable($target_name) 미완성 /*{{{*/ - // 테이블 데이터 Dump - function dumpTable($target_name) { - }/*}}}*/ - - /** - * insert/update/delete/select 구현 - **/ - // private string _executeInsertAct($tables, $column, $pass_quotes)/*{{{*/ - function _executeInsertAct($tables, $column, $pass_quotes) { - $table = array_pop($tables); - - foreach($column as $key => $val) { - $key_list[] = $key; - if(in_array($key, $pass_quotes)) $val_list[] = $this->addQuotes($val); - else $val_list[] = '\''.$this->addQuotes($val).'\''; - } - - $query = sprintf("insert into `%s%s` (%s) values (%s);", $this->prefix, $table, '`'.implode('`,`',$key_list).'`', implode(',', $val_list)); - return $this->_query($query); - }/*}}}*/ - - // private string _executeUpdateAct($tables, $column, $condition, $pass_quotes)/*{{{*/ - function _executeUpdateAct($tables, $column, $condition, $pass_quotes) { - $table = array_pop($tables); - - foreach($column as $key => $val) { - if(in_array($key, $pass_quotes)) $update_list[] = sprintf('`%s` = %s', $key, $this->addQuotes($val)); - else $update_list[] = sprintf('`%s` = \'%s\'', $key, $this->addQuotes($val)); - } - if(!count($update_list)) return; - $update_query = implode(',',$update_list); - - if($condition) $condition = ' where '.$condition; - - $query = sprintf("update `%s%s` set %s %s;", $this->prefix, $table, $update_query, $condition); - return $this->_query($query); - }/*}}}*/ - - // private string _executeDeleteAct($tables, $condition, $pass_quotes)/*{{{*/ - function _executeDeleteAct($tables, $condition, $pass_quotes) { - $table = array_pop($tables); - - if($condition) $condition = ' where '.$condition; - - $query = sprintf("delete from `%s%s` %s;", $this->prefix, $table, $condition); - return $this->_query($query); - }/*}}}*/ - - // private string _executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $pass_quotes)/*{{{*/ - // 네비게이션 변수 정리를 해야함 - function _executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $group_script, $pass_quotes) { - if(!count($tables)) $table = $this->prefix.array_pop($tables); - else { - foreach($tables as $key => $val) $table_list[] = sprintf('%s%s as %s', $this->prefix, $key, $val); - } - $table = implode(',',$table_list); - - if(!$column) $columns = '*'; - else { - foreach($invert_columns as $key => $val) { - $column_list[] = sprintf('%s as %s',$val, $key); + // mysql의 경우 utf8임을 지정 + $this->_query("SET NAMES 'utf8'"); } - $columns = implode(',', $column_list); - } - if($condition) $condition = ' where '.$condition; - - if($navigation->list_count) return $this->_getNavigationData($table, $columns, $condition, $navigation); - - $query = sprintf("select %s from %s %s", $columns, $table, $condition); - - $query .= ' '.$group_script; - - if($navigation->index) { - foreach($navigation->index as $index_obj) { - $index_list[] = sprintf('%s %s', $index_obj[0], $index_obj[1]); + /** + * @brief DB접속 해제 + **/ + function close() { + if(!$this->isConnected()) return; + @mysql_close($this->fd); } - if(count($index_list)) $query .= ' order by '.implode(',',$index_list); - } + /** + * @brief 쿼리에서 입력되는 문자열 변수들의 quotation 조절 + **/ + function addQuotes($string) { + if(get_magic_quotes_gpc()) $string = stripslashes(str_replace("\\","\\\\",$string)); + if(!is_numeric($string)) $string = @mysql_escape_string($string); + return $string; + } - $result = $this->_query($query); - if($this->errno!=0) return; - $data = $this->_fetch($result); + /** + * @brief : 쿼리문의 실행 및 결과의 fetch 처리 + * + * query : query문 실행하고 result return\n + * fetch : reutrn 된 값이 없으면 NULL\n + * rows이면 array object\n + * row이면 object\n + * return\n + **/ + function _query($query) { + if(!$this->isConnected()) return; + $this->query = $query; - $buff = new Output(); - $buff->data = $data; - return $buff; - }/*}}}*/ + $this->setError(0,'success'); - // private function _getNavigationData($query)/*{{{*/ - // query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다 - // 그닥 좋지는 않은 구조이지만 편리하다.. -_-; - function _getNavigationData($table, $columns, $condition, $navigation) { - // 전체 개수를 구함 - $count_query = sprintf("select count(*) as count from %s %s", $table, $condition); - $result = $this->_query($count_query); - $count_output = $this->_fetch($result); - $total_count = (int)$count_output->count; + $result = @mysql_query($query, $this->fd); - // 전체 페이지를 구함 - $total_page = (int)(($total_count-1)/$navigation->list_count) +1; + if(mysql_error()) { + $this->setError(mysql_errno(), mysql_error()); + return; + } - // 페이지 변수를 체크 - if($navigation->page > $total_page) $page = $navigation->page; - else $page = $navigation->page; - $start_count = ($page-1)*$navigation->list_count; + return $result; + } - foreach($navigation->index as $index_obj) { - $index_list[] = sprintf('%s %s', $index_obj[0], $index_obj[1]); - } + /** + * @brief 결과를 fetch + **/ + function _fetch($result) { + if($this->errno!=0 || !$result) return; + while($tmp = mysql_fetch_object($result)) { + $output[] = $tmp; + } + if(count($output)==1) return $output[0]; + return $output; + } - $index = implode(',',$index_list); - $query = sprintf('select %s from %s %s order by %s limit %d, %d', $columns, $table, $condition, $index, $start_count, $navigation->list_count); - $result = $this->_query($query); - if($this->errno!=0) return; + /** + * @brief 1씩 증가되는 sequence값을 return (mysql의 auto_increment는 sequence테이블에서만 사용) + **/ + function getNextSequence() { + $query = sprintf("insert into `%ssequence` (seq) values ('')", $this->prefix); + $this->_query($query); + return mysql_insert_id(); + } - $virtual_no = $total_count - ($page-1)*$navigation->list_count; - while($tmp = mysql_fetch_object($result)) { - $data[$virtual_no--] = $tmp; - } + /** + * @brief 테이블 기생성 여부 return + **/ + function isTableExists($target_name) { + $query = sprintf("show tables like '%s%s'", $this->prefix, $this->addQuotes($target_name)); + $result = $this->_query($query); + $tmp = $this->_fetch($result); + if(!$tmp) return false; + return true; + } - $buff = new Output(); - $buff->total_count = $total_count; - $buff->total_page = $total_page; - $buff->page = $page; - $buff->data = $data; + /** + * @brief xml 을 받아서 테이블을 생성 + **/ + function createTableByXml($xml_doc) { + return $this->_createTable($xml_doc); + } - require_once('./classes/page/PageHandler.class.php'); - $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $navigation->page_count); - return $buff; - }/*}}}*/ - } + /** + * @brief xml 을 받아서 테이블을 생성 + **/ + function createTableByXmlFile($file_name) { + if(!file_exists($file_name)) return; + // xml 파일을 읽음 + $buff = FileHandler::readFile($file_name); + return $this->_createTable($buff); + } + + /** + * @brief schema xml을 이용하여 create table query생성 + * + * type : number, varchar, text, char, date, \n + * opt : notnull, default, size\n + * index : primary key, index, unique\n + **/ + function _createTable($xml_doc) { + // xml parsing + $oXml = new XmlParser(); + $xml_obj = $oXml->parse($xml_doc); + + // 테이블 생성 schema 작성 + $table_name = $xml_obj->table->attrs->name; + if($this->isTableExists($table_name)) return; + $table_name = $this->prefix.$table_name; + + if(!is_array($xml_obj->table->column)) $columns[] = $xml_obj->table->column; + else $columns = $xml_obj->table->column; + + foreach($columns as $column) { + $name = $column->attrs->name; + $type = $column->attrs->type; + $size = $column->attrs->size; + $notnull = $column->attrs->notnull; + $primary_key = $column->attrs->primary_key; + $index = $column->attrs->index; + $unique = $column->attrs->unique; + $default = $column->attrs->default; + $auto_increment = $column->attrs->auto_increment; + + $column_schema[] = sprintf('`%s` %s%s %s %s %s', + $name, + $this->column_type[$type], + $size?'('.$size.')':'', + $default?"default '".$default."'":'', + $notnull?'not null':'', + $auto_increment?'auto_increment':'' + ); + + if($primary_key) $primary_list[] = $name; + else if($unique) $unique_list[$unique][] = $name; + else if($index) $index_list[$index][] = $name; + } + + if(count($primary_list)) { + $column_schema[] = sprintf("primary key (%s)", '`'.implode($primary_list,'`,`').'`'); + } + + if(count($unique_list)) { + foreach($unique_list as $key => $val) { + $column_schema[] = sprintf("unique %s (%s)", $key, '`'.implode($val,'`,`').'`'); + } + } + + if(count($index_list)) { + foreach($index_list as $key => $val) { + $column_schema[] = sprintf("index %s (%s)", $key, '`'.implode($val,'`,`').'`'); + } + } + + $schema = sprintf('create table `%s` (%s%s);', $this->addQuotes($table_name), "\n", implode($column_schema,",\n")); + $output = $this->_query($schema); + if(!$output) return false; + } + + /** + * @brief 테이블 삭제 + **/ + function dropTable($target_name) { + $query = sprintf('drop table `%s%s`;', $this->prefix, $this->addQuotes($target_name)); + $this->_query($query); + } + + /** + * @brief 테이블의 이름 변경 + **/ + function renameTable($source_name, $targe_name) { + $query = sprintf("alter table `%s%s` rename `%s%s`;", $this->prefix, $this->addQuotes($source_name), $this->prefix, $this->addQuotes($targe_name)); + $this->_query($query); + } + + /** + * @brief 테이블을 비움 + **/ + function truncateTable($target_name) { + $query = sprintf("truncate table `%s%s`;", $this->prefix, $this->addQuotes($target_name)); + $this->_query($query); + } + + /** + * @brief 테이블 데이터 Dump + * + * @todo 아직 미구현 + **/ + function dumpTable($target_name) { + } + + /** + * @brief insertAct 처리 + **/ + function _executeInsertAct($tables, $column, $pass_quotes) { + $table = array_pop($tables); + + foreach($column as $key => $val) { + $key_list[] = $key; + if(in_array($key, $pass_quotes)) $val_list[] = $this->addQuotes($val); + else $val_list[] = '\''.$this->addQuotes($val).'\''; + } + + $query = sprintf("insert into `%s%s` (%s) values (%s);", $this->prefix, $table, '`'.implode('`,`',$key_list).'`', implode(',', $val_list)); + return $this->_query($query); + } + + /** + * @brief updateAct 처리 + **/ + function _executeUpdateAct($tables, $column, $condition, $pass_quotes) { + $table = array_pop($tables); + + foreach($column as $key => $val) { + if(in_array($key, $pass_quotes)) $update_list[] = sprintf('`%s` = %s', $key, $this->addQuotes($val)); + else $update_list[] = sprintf('`%s` = \'%s\'', $key, $this->addQuotes($val)); + } + if(!count($update_list)) return; + $update_query = implode(',',$update_list); + + if($condition) $condition = ' where '.$condition; + + $query = sprintf("update `%s%s` set %s %s;", $this->prefix, $table, $update_query, $condition); + return $this->_query($query); + } + + /** + * @brief deleteAct 처리 + **/ + function _executeDeleteAct($tables, $condition, $pass_quotes) { + $table = array_pop($tables); + + if($condition) $condition = ' where '.$condition; + + $query = sprintf("delete from `%s%s` %s;", $this->prefix, $table, $condition); + return $this->_query($query); + } + + /** + * @brief selectAct 처리 + * + * select의 경우 특정 페이지의 목록을 가져오는 것을 편하게 하기 위해\n + * navigation이라는 method를 제공 + **/ + function _executeSelectAct($tables, $column, $invert_columns, $condition, $navigation, $group_script, $pass_quotes) { + if(!count($tables)) $table = $this->prefix.array_pop($tables); + else { + foreach($tables as $key => $val) $table_list[] = sprintf('%s%s as %s', $this->prefix, $key, $val); + } + $table = implode(',',$table_list); + + if(!$column) $columns = '*'; + else { + foreach($invert_columns as $key => $val) { + $column_list[] = sprintf('%s as %s',$val, $key); + } + $columns = implode(',', $column_list); + } + + if($condition) $condition = ' where '.$condition; + + if($navigation->list_count) return $this->_getNavigationData($table, $columns, $condition, $navigation); + + $query = sprintf("select %s from %s %s", $columns, $table, $condition); + + $query .= ' '.$group_script; + + if($navigation->index) { + foreach($navigation->index as $index_obj) { + $index_list[] = sprintf('%s %s', $index_obj[0], $index_obj[1]); + } + if(count($index_list)) $query .= ' order by '.implode(',',$index_list); + } + + $result = $this->_query($query); + if($this->errno!=0) return; + $data = $this->_fetch($result); + + $buff = new Output(); + $buff->data = $data; + return $buff; + } + + /** + * @brief query xml에 navigation 정보가 있을 경우 페이징 관련 작업을 처리한다 + * + * 그닥 좋지는 않은 구조이지만 편리하다.. -_-; + **/ + function _getNavigationData($table, $columns, $condition, $navigation) { + // 전체 개수를 구함 + $count_query = sprintf("select count(*) as count from %s %s", $table, $condition); + $result = $this->_query($count_query); + $count_output = $this->_fetch($result); + $total_count = (int)$count_output->count; + + // 전체 페이지를 구함 + $total_page = (int)(($total_count-1)/$navigation->list_count) +1; + + // 페이지 변수를 체크 + if($navigation->page > $total_page) $page = $navigation->page; + else $page = $navigation->page; + $start_count = ($page-1)*$navigation->list_count; + + foreach($navigation->index as $index_obj) { + $index_list[] = sprintf('%s %s', $index_obj[0], $index_obj[1]); + } + + $index = implode(',',$index_list); + $query = sprintf('select %s from %s %s order by %s limit %d, %d', $columns, $table, $condition, $index, $start_count, $navigation->list_count); + $result = $this->_query($query); + if($this->errno!=0) return; + + $virtual_no = $total_count - ($page-1)*$navigation->list_count; + while($tmp = mysql_fetch_object($result)) { + $data[$virtual_no--] = $tmp; + } + + $buff = new Output(); + $buff->total_count = $total_count; + $buff->total_page = $total_page; + $buff->page = $page; + $buff->data = $data; + + require_once('./classes/page/PageHandler.class.php'); + $buff->page_navigation = new PageHandler($total_count, $total_page, $page, $navigation->page_count); + return $buff; + } + } ?> diff --git a/classes/module/Module.class.php b/classes/module/Module.class.php index 19353c085..7f0e4bffd 100644 --- a/classes/module/Module.class.php +++ b/classes/module/Module.class.php @@ -1,174 +1,180 @@ - * @desc : modules의 abstract class - **/ + /** + * @class Module + * @author zero (zero@nzeo.com) + * @brief modules 의 abstract class + **/ - // abstract class Module - class Module extends Output { + class Module extends Output { - // 현재 모듈의 실행 위치 - var $module_path = NULL; + var $module_path = NULL; ///< 현재 모듈의 실행 위치 - // skin 설정 (없을 경우도 있음) - var $skin = 'default'; + var $skin = 'default'; ///< skin 설정 (없을 경우도 있음) - // 현재 모듈 생성시 주어진 설정 정보들 - var $module_srl = NULL; - var $module_info = NULL; + var $module_srl = NULL; ///< 모듈 객체의 고유값인 module_srl + var $module_info = NULL; ///< 현재 모듈 생성시 주어진 설정 정보들 - // 모듈의 action을 정의하는 변수 설정 - var $act = NULL; - var $act_type = 'disp'; + var $act = NULL; ///< act 값 + var $act_type = 'disp'; ///< act_type (disp, proc, lib, admin 4가지 존재, act에서 type을 찾음) - // 레이아웃 path, tpl - var $layout_path = "./common/tpl/"; - var $layout_tpl = "default_layout"; + var $layout_path = "./common/tpl/"; ///< 레이아웃 파일의 path + var $layout_tpl = "default_layout"; ///< 레이아웃 파일 - // public void moduleInit($module_info)/*{{{*/ - // 모듈의 정보 세팅 - function moduleInit($module_info) { - // 브라우저 타이틀 지정 - Context::setBrowserTitle($module_info->browser_title?$module_info->browser_title:$module_info->mid); + /** + * @brief 모듈의 정보 세팅 + **/ + function moduleInit($module_info) { + // 브라우저 타이틀 지정 + Context::setBrowserTitle($module_info->browser_title?$module_info->browser_title:$module_info->mid); - // 기본 변수 설정 - $this->module_info = $module_info; - context::set('module_info', &$this->module_info); + // 기본 변수 설정 + $this->module_info = $module_info; + context::set('module_info', &$this->module_info); - $this->module_srl = $module_info->module_srl; + $this->module_srl = $module_info->module_srl; - // skin 설정 (기본으로는 default) - if($this->module_info->skin) $this->skin = $this->module_info->skin; - else $this->skin = 'default'; + // skin 설정 (기본으로는 default) + if($this->module_info->skin) $this->skin = $this->module_info->skin; + else $this->skin = 'default'; - // 템플릿 위치 설정 - if(!$this->template_path) { - $template_path = $this->module_path.'skins/'.$this->skin; - $this->setTemplatePath($template_path); - } - - $oMember = getModule('member'); - $user_id = $oMember->getUserID(); - $logged_info = $oMember->getLoggedInfo(); - $user_group = $logged_info->group_list; - $user_group_count = count($user_group); - - // 로그인되어 있다면 admin 체크 - if($oMember->isLogged() && ($logged_info->is_admin == 'Y' || in_array($user_id, $this->module_info->admin_id) )) { - $grant->is_admin = true; - } else { - $grant->is_admin = false; - } - - // 권한 설정 - if($this->grant_list) { - - foreach($this->grant_list as $grant_name) { - $grant->{$grant_name} = false; - - if($grant->is_admin || !$this->module_info->grant[$grant_name]) { - $grant->{$grant_name} = true; - continue; - } - - if($user_group_count) { - foreach($user_group as $group_srl) { - if(in_array($group_srl, $this->module_info->grant[$grant_name])) { - $grant->{$grant_name} = true; - break; - } + // 템플릿 위치 설정 + if(!$this->template_path) { + $template_path = $this->module_path.'skins/'.$this->skin; + $this->setTemplatePath($template_path); } - } + + $oMember = getModule('member'); + $user_id = $oMember->getUserID(); + $logged_info = $oMember->getLoggedInfo(); + $user_group = $logged_info->group_list; + $user_group_count = count($user_group); + + // 로그인되어 있다면 admin 체크 + if($oMember->isLogged() && ($logged_info->is_admin == 'Y' || in_array($user_id, $this->module_info->admin_id) )) { + $grant->is_admin = true; + } else { + $grant->is_admin = false; + } + + // 권한 설정 + if($this->grant_list) { + + foreach($this->grant_list as $grant_name) { + $grant->{$grant_name} = false; + + if($grant->is_admin || !$this->module_info->grant[$grant_name]) { + $grant->{$grant_name} = true; + continue; + } + + if($user_group_count) { + foreach($user_group as $group_srl) { + if(in_array($group_srl, $this->module_info->grant[$grant_name])) { + $grant->{$grant_name} = true; + break; + } + } + } + } + } + + // 권한변수 설정 + Context::set('grant',$grant); + $this->grant = $grant; + + // 모듈의 init method 실행 + $this->init(); } - } - // 권한변수 설정 - Context::set('grant',$grant); - $this->grant = $grant; - - // 모듈의 init method 실행 - $this->init(); - }/*}}}*/ - - // public boolean isExistsAct($act)/*{{{*/ - // 현재 모듈에 $act에 해당하는 method가 있는지 체크 - function isExistsAct($act) { - return method_exists($this, $act); - }/*}}}*/ - - // public String getActType()/*{{{*/ - // 현재 acT_type의 return (disp/proc) - function getActType() { - return $this->act_type; - }/*}}}*/ - - // public void setModulePath($path)/*{{{*/ - // 현재 모듈의 path를 지정 - function setModulePath($path) { - if(substr($path,-1)!='/') $path.='/'; - $this->module_path = $path; - }/*}}}*/ - - // public boolean doError($msg_code) /*{{{*/ - function doError($msg_code) { - $this->setError(-1); - if(!Context::getLang($msg_code)) $this->setMessage($msg_code); - else $this->setMessage(Context::getLang($msg_code)); - return false; - }/*}}}*/ - - // public void setLayoutPath($path)/*{{{*/ - function setLayoutPath($path) { - $this->layout_path = $path; - }/*}}}*/ - - // public void setLayoutTpl($tpl)/*{{{*/ - function setLayoutTpl($tpl) { - $this->layout_tpl = $tpl; - }/*}}}*/ - - // public void proc($act = null)/*{{{*/ - //모듈의 각 action을 실행하는 부분 - //$act값에 의해서 $action_list에 선언된 것들을 실행한다 - function proc($act = null) { - - // 별도로 요청한 act가 없으면 주어진 act를 이용 - if($act) $this->act = $act; - else $this->act = Context::get('act'); - - // act의 종류가 disp/proc인지에 대한 확인 - if($this->act&&strtolower(substr($this->act,0,4)) != 'disp') $this->act_type = 'proc'; - - // act값이 없거나 존재하지 않는 method를 호출시에 default_act를 지정 - if(!$this->act || !$this->isExistsAct($this->act)) $this->act = $this->default_act; - - // module의 *init 호출 (기본 init과 proc/disp init 2가지 있음) - if($this->act_type == 'proc') { - $output = $this->procInit(); - if((is_a($output, 'Output') || is_subclass_of($output, 'Output')) && !$output->toBool() ) { - $this->setError($output->getError()); - $this->setMessage($output->getMessage()); - return; - } elseif(!$output) { - $this->setError(-1); - $this->setMessage('fail'); - return; + /** + * @brief 현재 모듈에 $act에 해당하는 method가 있는지 체크 + **/ + function isExistsAct($act) { + return method_exists($this, $act); } - } else $this->dispInit(); - // 기본 act조차 없으면 return - if(!$this->isExistsAct($this->act)) return false; + /** + * @brief 현재 acT_type의 return (disp/proc) + **/ + function getActType() { + return $this->act_type; + } - // act값으로 method 실행 - $output = call_user_method($this->act, $this); + /** + * @brief 현재 모듈의 path를 지정 + **/ + function setModulePath($path) { + if(substr($path,-1)!='/') $path.='/'; + $this->module_path = $path; + } - if(is_a($output, 'Output') || is_subclass_of($output, 'Output')) { - $this->setError($output->getError()); - $this->setMessage($output->getMessage()); - } + /** + * @brief 에러 유발. 에러시 message module을 바로 호출하고 현재 모듈은 exit + **/ + function doError($msg_code) { + $this->setError(-1); + if(!Context::getLang($msg_code)) $this->setMessage($msg_code); + else $this->setMessage(Context::getLang($msg_code)); + return false; + } - return true; - }/*}}}*/ - } + /** + * @brief 레이아웃 경로를 지정 + **/ + function setLayoutPath($path) { + $this->layout_path = $path; + } + + /** + * @brief 레이아웃 tpl 파일을 지정 + **/ + function setLayoutTpl($tpl) { + $this->layout_tpl = $tpl; + } + + /** + * @brief 모듈의 action에 해당하는 method를 실행 + * + * $act값에 의해서 $action_list에 선언된 것들을 실행한다 + **/ + function proc($act = null) { + + // 별도로 요청한 act가 없으면 주어진 act를 이용 + if($act) $this->act = $act; + else $this->act = Context::get('act'); + + // act의 종류가 disp/proc인지에 대한 확인 + if($this->act&&strtolower(substr($this->act,0,4)) != 'disp') $this->act_type = 'proc'; + + // act값이 없거나 존재하지 않는 method를 호출시에 default_act를 지정 + if(!$this->act || !$this->isExistsAct($this->act)) $this->act = $this->default_act; + + // module의 *init 호출 (기본 init과 proc/disp init 2가지 있음) + if($this->act_type == 'proc') { + $output = $this->procInit(); + if((is_a($output, 'Output') || is_subclass_of($output, 'Output')) && !$output->toBool() ) { + $this->setError($output->getError()); + $this->setMessage($output->getMessage()); + return; + } elseif(!$output) { + $this->setError(-1); + $this->setMessage('fail'); + return; + } + } else $this->dispInit(); + + // 기본 act조차 없으면 return + if(!$this->isExistsAct($this->act)) return false; + + // act값으로 method 실행 + $output = call_user_method($this->act, $this); + + if(is_a($output, 'Output') || is_subclass_of($output, 'Output')) { + $this->setError($output->getError()); + $this->setMessage($output->getMessage()); + } + + return true; + } + } ?> diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php index 908a33b6b..34312aa63 100644 --- a/classes/module/ModuleHandler.class.php +++ b/classes/module/ModuleHandler.class.php @@ -1,87 +1,93 @@ - * @desc : mid의 값으로 모듈을 찾고 관련 정보들을 세팅 - **/ + /** + * @class ModuleHandler + * @author zero (zero@nzeo.com) + * @brief mid의 값으로 모듈을 찾아 객체 생성 & 모듈 정보 세팅 + **/ - class ModuleHandler { + class ModuleHandler { - // mid와 해당 mid의 설정 값 - var $mid = NULL; - var $module_info = NULL; + var $mid = NULL; ///< module로 생성한 instance(관리상)의 값 + var $module_info = NULL; ///< 해당 모듈의 정보 - // 모듈과 해당 모듈의 instance - var $module = NULL; - var $oModule = NULL; + var $module = NULL; ///< mid로 찾아서 생성한 모듈 class 이름 + var $oModule = NULL; ///< mid로 찾아서 생성한 모듈의 객체 - // public void ModuleHandler()/*{{{*/ - function ModuleHandler() { + /** + * @brief constructor + **/ + function ModuleHandler() { - // 설치가 안되어 있다면 설치를 위한 준비 - if(!Context::isInstalled()) return $this->_prepareInstall(); + // 설치가 안되어 있다면 설치를 위한 준비 + if(!Context::isInstalled()) return $this->_prepareInstall(); - // 설치가 되어 있다면 요청받은 mid에 해당하는 모듈 instance 생성 - // mid가 없이 document_srl만 있다면 document_srl로 mid를 찾음 - $mid = Context::get('mid'); - $document_srl = Context::get('document_srl'); + // 설치가 되어 있다면 요청받은 mid에 해당하는 모듈 instance 생성 + // mid가 없이 document_srl만 있다면 document_srl로 mid를 찾음 + $mid = Context::get('mid'); + $document_srl = Context::get('document_srl'); - // document_srl만 있다면 mid를 구해옴 - if(!$mid && $document_srl) { - $module_info = module_manager::getModuleInfoByDocument($document_srl); - if($module_info) $mid = $module_info->mid; - } + // document_srl만 있다면 mid를 구해옴 + if(!$mid && $document_srl) { + $module_info = module_manager::getModuleInfoByDocument($document_srl); + if($module_info) $mid = $module_info->mid; + } - // mid 값에 대한 모듈 정보를 추출 - if(!$module_info) $module_info = module_manager::getModuleInfo($mid); + // mid 값에 대한 모듈 정보를 추출 + if(!$module_info) $module_info = module_manager::getModuleInfo($mid); - // 모듈 정보에서 module 이름을 구해움 - $module = $module_info->module; + // 모듈 정보에서 module 이름을 구해움 + $module = $module_info->module; - $this->mid = $module_info->mid; - $this->module_info = $module_info; + $this->mid = $module_info->mid; + $this->module_info = $module_info; - Context::set('module', $module); - Context::set('mid', $this->mid, true); - Context::set('module_srl', $this->module_info->module_srl, true); + Context::set('module', $module); + Context::set('mid', $this->mid, true); + Context::set('module_srl', $this->module_info->module_srl, true); - // 만약 모듈이 없다면 오류 출력 - if(!$module) return $this->_moduleIsNotExists(); + // 만약 모듈이 없다면 오류 출력 + if(!$module) return $this->_moduleIsNotExists(); - $this->oModule = getModule($module); - $this->module = $module; - }/*}}}*/ + $this->oModule = getModule($module); + $this->module = $module; + } - // private void _prepareInstall()/*{{{*/ - // 설치를 하기 위해서 mid, module등을 강제 지정 - function _prepareInstall() { - // module로 install 모듈을 지정 - $this->module = 'install'; - Context::set('mid', NULL); - Context::set('module', $this->module); + /** + * @brief 설치를 하기 위해서 mid, module등을 강제 지정 + **/ + function _prepareInstall() { + // module로 install 모듈을 지정 + $this->module = 'install'; + Context::set('mid', NULL); + Context::set('module', $this->module); - // module_manager 호출 - $this->oModule = getModule($this->module); - }/*}}}*/ + // module_manager 호출 + $this->oModule = getModule($this->module); + } - // private void _moduleIsNotExists()/*{{{*/ - // 아무런 설정이 되어 있지 않다면 오류 표시 - function _moduleIsNotExists() { - $this->module = 'message'; - Context::set('mid', NULL); - Context::set('module', $this->module); + /** + * @brief 아무런 설정이 되어 있지 않다면 오류 표시 + **/ + function _moduleIsNotExists() { + $this->module = 'message'; + Context::set('mid', NULL); + Context::set('module', $this->module); - $this->oModule = getModule($this->module); + $this->oModule = getModule($this->module); - Context::set('error', -1); - Context::set('message', Context::getLang('msg_mid_not_exists')); - }/*}}}*/ + Context::set('error', -1); + Context::set('message', Context::getLang('msg_mid_not_exists')); + } - // public object proc()/*{{{*/ - function proc() { - $this->oModule->moduleInit($this->module_info); - $this->oModule->proc(); - return $this->oModule; - }/*}}}*/ - } + /** + * @brief mid로 생성한 모듈 객체에 모듈 정보를 세팅하고 실행 + * + * 모듈을 실행후에 그 모듈 객체를 return하여 DisplayHandler로 넘겨줌 + **/ + function proc() { + $this->oModule->moduleInit($this->module_info); + $this->oModule->proc(); + return $this->oModule; + } + } ?> diff --git a/config/config.inc.php b/config/config.inc.php index 5b9493f8c..ef1df88ce 100644 --- a/config/config.inc.php +++ b/config/config.inc.php @@ -1,37 +1,48 @@ - * @desc : 기본적으로 사용하는 class파일의 include 및 환경 설정을 함 - **/ + /** + * @file config/config.inc.php + * @author zero (zero@nzeo.com) + * @brief 기본적으로 사용하는 class파일의 include 및 환경 설정을 함 + **/ - // 기본적인 상수 선언 - // 웹에서 직접 호출되는 것을 막기 위해 체크하는 상수 선언 - define('__ZB5__', true); + /** + * brief 기본적인 상수 선언, 웹에서 직접 호출되는 것을 막기 위해 체크하는 상수 선언 + **/ + define('__ZB5__', true); - // 기본 함수 라이브러리 파일 - require_once("./config/func.inc.php"); + /** + * @brief 간단하게 사용하기 위한 함수 정의한 파일 require + **/ + require_once("./config/func.inc.php"); - // debug mode = true 일때 files/_debug_message.php 에 디버그 내용이 쌓임 - define('__DEBUG__', true); - if(__DEBUG__) define('__StartTime__', getMicroTime()); + /** + * @brief debug mode = true 일때 files/_debug_message.php 에 디버그 내용이 쌓임 + **/ + define('__DEBUG__', true); + if(__DEBUG__) define('__StartTime__', getMicroTime()); - // 세션 설정 - @session_cache_limiter('no-cache, must-revalidate'); - @session_start(); + /** + * @brief 세션 설정 + **/ + @session_cache_limiter('no-cache, must-revalidate'); + @session_start(); - // 기본적인 class 파일 include - if(__DEBUG__) define('__RequireClassStartTime__', getMicroTime()); - require_once("./classes/xml/XmlParser.class.php"); - require_once("./classes/context/Context.class.php"); - require_once("./classes/db/DB.class.php"); - require_once("./classes/file/FileHandler.class.php"); - require_once("./classes/output/Output.class.php"); - require_once("./classes/module/Module.class.php"); - require_once("./classes/display/DisplayHandler.class.php"); - require_once("./classes/module/ModuleHandler.class.php"); - require_once('./modules/module_manager/module_manager.module.php'); - //require_once("./classes/addon/AddOnHandler.class.php"); - //require_once("./classes/layout/LayoutHandler.class.php"); - if(__DEBUG__) define('__RequireClassEndTime__', getMicroTime()); + /** + * @brief 기본적인 class 파일 include + * + * php5 기반으로 바꾸게 되면 _autoload를 이용할 수 있기에 제거 대상 + **/ + if(__DEBUG__) define('__RequireClassStartTime__', getMicroTime()); + require_once("./classes/xml/XmlParser.class.php"); + require_once("./classes/context/Context.class.php"); + require_once("./classes/db/DB.class.php"); + require_once("./classes/file/FileHandler.class.php"); + require_once("./classes/output/Output.class.php"); + require_once("./classes/module/Module.class.php"); + require_once("./classes/display/DisplayHandler.class.php"); + require_once("./classes/module/ModuleHandler.class.php"); + require_once('./modules/module_manager/module_manager.module.php'); + //require_once("./classes/addon/AddOnHandler.class.php"); + //require_once("./classes/layout/LayoutHandler.class.php"); + if(__DEBUG__) define('__RequireClassEndTime__', getMicroTime()); ?> diff --git a/config/func.inc.php b/config/func.inc.php index c6ffa9637..6c05cf9ea 100644 --- a/config/func.inc.php +++ b/config/func.inc.php @@ -1,84 +1,124 @@ - * @desc : 편의 목적으로 만든 함수라이브러리 파일 - **/ + /** + * @file config/func.inc.php + * @author zero (zero@nzeo.com) + * @desc 편의 목적으로 만든 함수라이브러리 파일 + **/ - // php5에 대비하여 clone 정의/*{{{*/ - if (version_compare(phpversion(), '5.0') < 0) { - eval(' - function clone($object) { - return $object; + /** + * @brief php5에 대비하여 clone 정의 + **/ + if (version_compare(phpversion(), '5.0') < 0) { + eval(' + function clone($object) { + return $object; + } + '); } - '); - }/*}}}*/ - // function object getModule($module_name, $is_admin=false)/*{{{*/ - // module_manager::getModuleObject($module_name)을 쓰기 쉽게 함수로 선언 - function getModule($module_name, $is_admin=false) { - if($is_admin) return module_manager::getAdminModuleObject($module_name); - return module_manager::getModuleObject($module_name); - }/*}}}*/ - - // function string getUrl($args_list)/*{{{*/ - // Context::getUrl($args_list)를 쓰기 쉽게 함수로 선언 - function getUrl() { - $num_args = func_num_args(); - $args_list = func_get_args(); - - if(!$num_args) return Context::getRequestUri(); - - return Context::getUrl($num_args, $args_list); - }/*}}}*/ - - // function string cut_str($string, $cut_size, $tail = '...')/*{{{*/ - // microtime - function cut_str($string, $cut_size, $tail='...') { - if(!$string || !$cut_size) return $string; - $unicode_str = iconv("UTF-8","UCS-2",$string); - if(strlen($unicode_str) < $cut_size*2) return $string; - - $output = substr($unicode_str, 0, $cut_size*2); - return iconv("UCS-2","UTF-8",$output_str).$tail; - }/*}}}*/ - - // function string zdate($str, $format = "Y-m-d H:i:s")/*{{{*/ - // 시간 출력 - function zdate($str, $format = "Y-m-d H:i:s") { - return date($format, mktime(substr($str,8,2), substr($str,10,2), substr($str,12,2), substr($str,4,2), substr($str,6,2), substr($str,0,4))); - }/*}}}*/ - - // function void debugPrint($buff)/*{{{*/ - // 간단한 console debugging용 함수 - function debugPrint($buff, $display_line = true) { - $debug_file = "./files/_debug_message.php"; - $buff = sprintf("%s\n",print_r($buff,true)); - - if($display_line) $buff = "\n====================================\n".$buff."------------------------------------\n"; - - if(@!$fp = fopen($debug_file,"a")) return; - fwrite($fp, $buff); - fclose($fp); - }/*}}}*/ - - // function float getMicroTime()/*{{{*/ - // microtime - function getMicroTime() { - list($time1, $time2) = explode(' ', microtime()); - return (float)$time1+(float)$time2; - }/*}}}*/ - - // function string delObjectVars($target_obj, $del_obj)/*{{{*/ - // 첫번째 인자로 오는 object var에서 2번째 object의 var들을 빼낸다 - function delObjectVars($target_obj, $del_obj) { - if(count(get_object_vars($target_obj))<1) return; - if(count(get_object_vars($del_obj))<1) clone($target_obj); - - if(is_object($target_var)) $var = clone($target_var); - foreach($del_obj as $key => $val) { - unset($var->{$var_name}); + /** + * @brief module_manager::getModuleObject($module_name, $act_type)을 쓰기 쉽게 함수로 선언 + * @param module_name 모듈이름 + * @param act_type disp, proc, lib(기본), admin + * @return module instance + **/ + function getModule($module_name, $act_type = 'lib') { + return module_manager::getModuleObject($module_name, $act_type); + } + + + /** + * @brief Context::getUrl($args_list)를 쓰기 쉽게 함수로 선언 + * @param args_list 제한없는 args + * @return string + * + * getUrl()은 현재 요청된 RequestURI에 주어진 인자의 값으로 변형하여 url을 리턴한다\n + * 인자는 (key, value)... 의 형식으로 주어져야 한다.\n + * ex) getUrl('key1','val1', 'key2', '') : key1, key2를 val1과 '' 로 변형\n + * 아무런 인자가 없으면 argument를 제외한 url을 리턴 + **/ + function getUrl() { + $num_args = func_num_args(); + $args_list = func_get_args(); + + if(!$num_args) return Context::getRequestUri(); + + return Context::getUrl($num_args, $args_list); + } + + /** + * @brief 주어진 문자를 주어진 크기로 자르고 잘라졌을 경우 주어진 꼬리를 담 + * @param string 자를 원 문자열 + * @param cut_size 주어진 원 문자열을 자를 크기 + * @param tail 잘라졌을 경우 문자열의 제일 뒤에 붙을 꼬리 + * @return string + * + * 손쉽고 확실한 변환을 위해 2byte unicode로 변형한후 처리를 한다 + **/ + function cut_str($string, $cut_size, $tail='...') { + if(!$string || !$cut_size) return $string; + $unicode_str = iconv("UTF-8","UCS-2",$string); + if(strlen($unicode_str) < $cut_size*2) return $string; + + $output = substr($unicode_str, 0, $cut_size*2); + return iconv("UCS-2","UTF-8",$output_str).$tail; + } + + /** + * @brief YYYYMMDDHHIISS 형식의 시간값을 원하는 시간 포맷으로 변형 + * @param str YYYYMMDDHHIISS 형식의 시간값 + * @param format php date()함수의 시간 포맷 + * @return string + **/ + function zdate($str, $format = "Y-m-d H:i:s") { + return date($format, mktime(substr($str,8,2), substr($str,10,2), substr($str,12,2), substr($str,4,2), substr($str,6,2), substr($str,0,4))); + } + + /** + * @brief 간단한 console debugging 함수 + * @param buff 출력하고자 하는 object + * @param display_line 구분자를 출력할 것인지에 대한 플래그 (기본:true) + * @return none + * + * ./files/_debug_message.php 파일에 $buff 내용을 출력한다. + * tail -f ./files/_debug_message.php 하여 계속 살펴 볼 수 있다 + **/ + function debugPrint($buff, $display_line = true) { + $debug_file = "./files/_debug_message.php"; + $buff = sprintf("%s\n",print_r($buff,true)); + + if($display_line) $buff = "\n====================================\n".$buff."------------------------------------\n"; + + if(@!$fp = fopen($debug_file,"a")) return; + fwrite($fp, $buff); + fclose($fp); + } + + /** + * @brief microtime() return + * @return float + **/ + function getMicroTime() { + list($time1, $time2) = explode(' ', microtime()); + return (float)$time1+(float)$time2; + } + + /** + * @brief 첫번째 인자로 오는 object var에서 2번째 object의 var들을 제거 + * @param target_obj 원 object + * @param del_obj 원 object의 vars에서 del_obj의 vars를 제거한다 + * @return object + **/ + function delObjectVars($target_obj, $del_obj) { + if(count(get_object_vars($target_obj))<1) return; + if(count(get_object_vars($del_obj))<1) clone($target_obj); + + if(is_object($target_var)) $var = clone($target_var); + + foreach($del_obj as $key => $val) { + unset($var->{$var_name}); + } + + return $var; } - return $var; - }/*}}}*/ ?> diff --git a/index.php b/index.php index 98d941df2..56ae6dbd3 100644 --- a/index.php +++ b/index.php @@ -1,23 +1,49 @@ - * @desc : 모든 요청(request)의 관문으로 main() 역할을 함 - * Main class의 instance를 생성하여 constructor 실행하는 역할만 수행 - **/ + /** + * @file ./index.php + * @author zero (zero@zeroboard.com) + * @brief 시작 페이지 + * + * Request Argument에서 mid, act로 module 객체를 찾아서 생성하고 \n + * 모듈 정보를 세팅함 + * + * @mainpage 첫페이지 + * @section intro 소개 + * zeroboard5는 오픈 프로젝트로 개발되는 오픈 소스입니다.\n + * 자세한 내용은 아래 링크를 참조하세요. + * - 공식홈페이지 : http://www.zeroboard.com + * - 개발자 포험 : http://dev.zeroboard.com + * - 이슈트래킹 : http://www.zeroboard.com/trac + * + **/ - // 필요한 설정 파일들을 include - require_once("./config/config.inc.php"); + /** + * @brief 필요한 설정 파일들을 include + **/ + require_once("./config/config.inc.php"); - // Request Method와 설정값들을 세팅 - $oContext = &Context::getInstance(); - $oContext->init(); + /** + * @brief Context 객체를 생성하여 초기화\n + * 모든 Request Argument/ 환경변수등을 세팅 + **/ + $oContext = &Context::getInstance(); + $oContext->init(); - // ModuleHandler 호출하여 content 출력 - $oModuleHandler = new ModuleHandler(); - $oModule = $oModuleHandler->proc(); + /** + * @brief ModuleHandler 객체를 생성 + **/ + $oModuleHandler = new ModuleHandler(); - // DisplayHandler로 컨텐츠 출력 - $oDisplayHandler = new DisplayHandler(); - $oDisplayHandler->printContent($oModule); + /** + * @brief ModuleHandler 객체를 를 실행하여 요청받은 모듈 객체를\n + * 찾고 모듈 정보를 세팅하는 등의 역할을 한후 모듈 객체를\n + * return받음 + **/ + $oModule = $oModuleHandler->proc(); + + /** + * @brief DisplayHandler 객체를 생성하여 모듈의 처리 결과를 출력 + **/ + $oDisplayHandler = new DisplayHandler(); + $oDisplayHandler->printContent($oModule); ?>