<?php
    /**
     * @class  documentController
     * @author zero (zero@nzeo.com)
     * @brief  document 모듈의 controller 클래스
     **/

    class documentController extends document {

        /**
         * @brief 초기화
         **/
        function init() {
        }

        /**
         * @brief 문서의 권한 부여 
         * 세션값으로 현 접속상태에서만 사용 가능
         **/
        function addGrant($document_srl) {
            $_SESSION['own_document'][$document_srl] = true;
        }

        /**
         * @brief 문서 입력
         **/
        function insertDocument($obj, $manual_inserted = false) {

            // begin transaction
            $oDB = &DB::getInstance();
            $oDB->begin();

            // 기본 변수들 정리
            if($obj->is_secret!='Y') $obj->is_secret = 'N';
            if($obj->allow_comment!='Y') $obj->allow_comment = 'N';
            if($obj->lock_comment!='Y') $obj->lock_comment = 'N';
            if($obj->allow_trackback!='Y') $obj->allow_trackback = 'N';
            if($obj->homepage &&  !eregi('^http:\/\/',$obj->homepage)) $obj->homepage = 'http://'.$obj->homepage;
            if($obj->notify_message != "Y") $obj->notify_message = "N";

            // 내용의 경우 javascript, iframe제거
            $obj->content = removeHackTag($obj->content);

            // 자동저장용 필드 제거
            unset($obj->_saved_doc_srl);
            unset($obj->_saved_doc_title);
            unset($obj->_saved_doc_content);
            unset($obj->_saved_doc_message);

            // 문서 번호가 이미 있다면 첨부파일을 확인
            if($obj->document_srl) {
                // file의 Model객체 생성
                $oFileModel = &getModel('file');

                // 첨부 파일의 갯수를 구함
                $obj->uploaded_count = $oFileModel->getFilesCount($obj->document_srl);
            // 문서 번호가 없다면 문서 번호 할당
            } else {
                $obj->document_srl = getNextSequence();
            }

            // 카테고리가 있나 검사하여 없는 카테고리면 0으로 세팅
            if($obj->category_srl) {
                $oDocumentModel = &getModel('document');
                $category_list = $oDocumentModel->getCategoryList($obj->module_srl);
                if(!$category_list[$obj->category_srl]) $obj->category_srl = 0;
            }

            // 태그 처리
            $oTagController = &getController('tag');
            $obj->tags = $oTagController->insertTag($obj->module_srl, $obj->document_srl, $obj->tags);

            // 글 입력
            if(!$obj->readed_count) $obj->readed_count = 0;
            $obj->update_order = $obj->list_order = $obj->document_srl * -1;
            if($obj->password && !$obj->password_is_hashed) $obj->password = md5($obj->password);

            // 공지사항일 경우 list_order에 무지막지한 값;;을 입력
            if($obj->is_notice=='Y') $obj->list_order = $this->notice_list_order;

            // 로그인 된 회원일 경우 회원의 정보를 입력
            if(Context::get('is_logged')&&!$manual_inserted) {
                $logged_info = Context::get('logged_info');
                $obj->member_srl = $logged_info->member_srl;
                $obj->user_id = $logged_info->user_id;
                $obj->user_name = $logged_info->user_name;
                $obj->nick_name = $logged_info->nick_name;
                $obj->email_address = $logged_info->email_address;
                $obj->homepage = $logged_info->homepage;
            }

            // DB에 입력
            $output = executeQuery('document.insertDocument', $obj);

            if(!$output->toBool()) {
                $oDB->rollback();
                return $output;
            }

            // 성공하였을 경우 category_srl이 있으면 카테고리 update
            if($obj->category_srl) $this->updateCategoryCount($obj->category_srl);

            // 첨부 파일이 있었을 경우 해당 첨부파일들의 valid값을 Y로 변경
            if($obj->uploaded_count) {
                $oFileController = &getController('file');
                $oFileController->setFilesValid($obj->document_srl);
            }

            // commit
            $oDB->commit();

            // 자동 저장 문서 삭제
            if(!$manual_inserted) {
                $oEditorController = &getController('editor');
                $oEditorController->deleteSavedDoc();
            }

            // return
            $this->addGrant($obj->document_srl);
            $output->add('document_srl',$obj->document_srl);
            $output->add('category_srl',$obj->category_srl);
            return $output;
        }

        /**
         * @brief 문서 수정
         **/
        function updateDocument($source_obj, $obj) {

            // begin transaction
            $oDB = &DB::getInstance();
            $oDB->begin();

            // 기본 변수들 정리
            if($obj->is_secret!='Y') $obj->is_secret = 'N';
            if($obj->allow_comment!='Y') $obj->allow_comment = 'N';
            if($obj->lock_comment!='Y') $obj->lock_comment = 'N';
            if($obj->allow_trackback!='Y') $obj->allow_trackback = 'N';
            if($obj->homepage &&  !eregi('^http:\/\/',$obj->homepage)) $obj->homepage = 'http://'.$obj->homepage;
            if($obj->notify_message != "Y") $obj->notify_message = "N";
            $obj->content = removeHackTag($obj->content);

            // 자동저장용 필드 제거
            unset($obj->_saved_doc_srl);
            unset($obj->_saved_doc_title);
            unset($obj->_saved_doc_content);
            unset($obj->_saved_doc_message);

            // file의 Model객체 생성
            $oFileModel = &getModel('file');

            // 첨부 파일의 갯수를 구함
            $obj->uploaded_count = $oFileModel->getFilesCount($obj->document_srl);

            // 카테고리가 변경되었으면 검사후 없는 카테고리면 0으로 세팅
            if($source_obj->get('category_srl')!=$obj->category_srl) {
                $oDocumentModel = &getModel('document');
                $category_list = $oDocumentModel->getCategoryList($obj->module_srl);
                if(!$category_list[$obj->category_srl]) $obj->category_srl = 0;
            }

            // 태그 처리
            if($source_obj->get('tags') != $obj->tags) {
                $oTagController = &getController('tag');
                $obj->tags = $oTagController->insertTag($obj->module_srl, $obj->document_srl, $obj->tags);
            }

            // 수정
            $obj->update_order = getNextSequence() * -1;

            // 공지사항일 경우 list_order에 무지막지한 값을, 그렇지 않으면 document_srl*-1값을
            if($obj->is_notice=='Y') $obj->list_order = $this->notice_list_order;
            else $obj->list_order = $obj->document_srl*-1;

            if($obj->password) $obj->password = md5($obj->password);

            // 원본 작성인과 수정하려는 수정인이 동일할 시에 로그인 회원의 정보를 입력
            if(Context::get('is_logged')) {
                $logged_info = Context::get('logged_info');
                if($source_obj->get('member_srl')==$logged_info->member_srl) {
                    $obj->member_srl = $logged_info->member_srl;
                    $obj->user_name = $logged_info->user_name;
                    $obj->nick_name = $logged_info->nick_name;
                    $obj->email_address = $logged_info->email_address;
                    $obj->homepage = $logged_info->homepage;
                }
            }

            // 로그인한 유저가 작성한 글인데 nick_name이 없을 경우
            if($source_obj->get('member_srl')&& !$obj->nick_name) {
                $obj->member_srl = $source_obj->get('member_srl');
                $obj->user_name = $source_obj->get('user_name');
                $obj->nick_name = $source_obj->get('nick_name');
                $obj->email_address = $source_obj->get('email_address');
                $obj->homepage = $source_obj->get('homepage');
            }

            // DB에 입력
            $output = executeQuery('document.updateDocument', $obj);

            if(!$output->toBool()) {
                $oDB->rollback();
                return $output;
            }

            // 성공하였을 경우 category_srl이 있으면 카테고리 update
            if($source_obj->get('category_srl')!=$obj->category_srl) {
                if($source_obj->get('category_srl')) $this->updateCategoryCount($source_obj->get('category_srl'));
                if($obj->category_srl) $this->updateCategoryCount($obj->category_srl);
            }

            // 첨부 파일이 있었을 경우 해당 첨부파일들의 valid값을 Y로 변경
            if($obj->uploaded_count) {
                $oFileController = &getController('file');
                $oFileController->setFilesValid($obj->document_srl);
            }

            // 자동 저장 문서 삭제
            $oEditorController = &getController('editor');
            $oEditorController->deleteSavedDoc();

            // commit
            $oDB->commit();

            $output->add('document_srl',$obj->document_srl);
            return $output;
        }

        /**
         * @brief 문서 삭제
         **/
        function deleteDocument($document_srl, $is_admin = false) {

            // begin transaction
            $oDB = &DB::getInstance();
            $oDB->begin();

            // document의 model 객체 생성
            $oDocumentModel = &getModel('document');

            // 기존 문서가 있는지 확인
            $oDocument = $oDocumentModel->getDocument($document_srl, $is_admin);
            if(!$oDocument->isExists() || $oDocument->document_srl != $document_srl) return new Object(-1, 'msg_invalid_document');

            // 권한이 있는지 확인
            if(!$oDocument->isGranted()) return new Object(-1, 'msg_not_permitted');

            // 글 삭제
            $args->document_srl = $document_srl;
            $output = executeQuery('document.deleteDocument', $args);
            if(!$output->toBool()) {
                $oDB->rollback();
                return $output;
            }

            // 댓글 삭제
            $oCommentController = &getController('comment');
            $output = $oCommentController->deleteComments($document_srl, $is_admin);

            // 엮인글 삭제
            $oTrackbackController = &getController('trackback');
            $output = $oTrackbackController->deleteTrackbacks($document_srl, $is_admin);

            // 태그 삭제
            $oTagController = &getController('tag');
            $oTagController->deleteTag($document_srl, $is_admin);

            // 첨부 파일 삭제
            if($oDocument->hasUploadedFiles()) {
                $oFileController = &getController('file');
                $oFileController->deleteFiles($document_srl);
            }

            // 카테고리가 있으면 카테고리 정보 변경
            if($oDocument->get('category_srl')) $this->updateCategoryCount($oDocument->get('category_srl'));

            // commit
            $oDB->commit();

            return $output;
        }

        /**
         * @brief 해당 document의 조회수 증가
         **/
        function updateReadedCount($oDocument) {
            $document_srl = $oDocument->document_srl;
            $member_srl = $oDocument->get('member_srl');
            $logged_info = Context::get('logged_info');

            // session에 정보로 조회수를 증가하였다고 생각하면 패스
            if($_SESSION['readed_document'][$document_srl]) return false;

            // 글의 작성 ip와 현재 접속자의 ip가 동일하면 패스
            if($document->ipaddress == $_SERVER['REMOTE_ADDR']) {
                $_SESSION['readed_document'][$document_srl] = true;
                return false;
            }

            // document의 작성자가 회원일때 조사
            if($member_srl) {

                // 글쓴이와 현재 로그인 사용자의 정보가 일치하면 읽었다고 생각하고 세션 등록후 패스
                if($member_srl && $logged_info->member_srl == $member_srl) {
                    $_SESSION['readed_document'][$document_srl] = true;
                    return false;
                }
            }

            // 로그인 사용자이면 member_srl, 비회원이면 ipaddress로 판단
            if($logged_info->member_srl) {
                $args->member_srl = $logged_info->member_srl;
            } else {
                $args->ipaddress = $_SERVER['REMOTE_ADDR'];
            }
            $args->document_srl = $document_srl;
            $output = executeQuery('document.getDocumentReadedLogInfo', $args);

            // 로그 정보에 조회 로그가 있으면 세션 등록후 패스
            if($output->data->count) return $_SESSION['readed_document'][$document_srl] = true;

            // 조회수 업데이트
            $output = executeQuery('document.updateReadedCount', $args);

            // 로그 남기기
            $output = executeQuery('document.insertDocumentReadedLog', $args);

            // 세션 정보에 남김
            return $_SESSION['readed_document'][$document_srl] = true;
        }

        /**
         * @brief 해당 document의 추천수 증가
         **/
        function updateVotedCount($document_srl) {
            // 세션 정보에 추천 정보가 있으면 중단
            if($_SESSION['voted_document'][$document_srl]) return new Object(-1, 'failed_voted');

            // 문서 원본을 가져옴
            $oDocumentModel = &getModel('document');
            $oDocument = $oDocumentModel->getDocument($document_srl, false, false);

            // 글의 작성 ip와 현재 접속자의 ip가 동일하면 패스
            if($oDocument->get('ipaddress') == $_SERVER['REMOTE_ADDR']) {
                $_SESSION['voted_document'][$document_srl] = true;
                return new Object(-1, 'failed_voted');
            }

            // document의 작성자가 회원일때 조사
            if($oDocument->get('member_srl')) {
                // member model 객체 생성
                $oMemberModel = &getModel('member');
                $member_srl = $oMemberModel->getLoggedMemberSrl();

                // 글쓴이와 현재 로그인 사용자의 정보가 일치하면 읽었다고 생각하고 세션 등록후 패스
                if($member_srl && $member_srl == $oDocument->get('member_srl')) {
                    $_SESSION['voted_document'][$document_srl] = true;
                    return new Object(-1, 'failed_voted');
                }
            }

            // 로그인 사용자이면 member_srl, 비회원이면 ipaddress로 판단
            if($member_srl) {
                $args->member_srl = $member_srl;
            } else {
                $args->ipaddress = $_SERVER['REMOTE_ADDR'];
            }
            $args->document_srl = $document_srl;
            $output = executeQuery('document.getDocumentVotedLogInfo', $args);

            // 로그 정보에 추천 로그가 있으면 세션 등록후 패스
            if($output->data->count) {
                $_SESSION['voted_document'][$document_srl] = true;
                return new Object(-1, 'failed_voted');
            }

            // 추천수 업데이트
            $output = executeQuery('document.updateVotedCount', $args);

            // 로그 남기기
            $output = executeQuery('document.insertDocumentVotedLog', $args);

            // 세션 정보에 남김
            $_SESSION['voted_document'][$document_srl] = true;

            // 결과 리턴
            return new Object(0, 'success_voted');
        }

        /**
         * @brief 해당 document의 댓글 수 증가
         **/
        function updateCommentCount($document_srl, $comment_count, $comment_inserted = false) {
            $args->document_srl = $document_srl;
            $args->comment_count = $comment_count;

            if($comment_inserted) $args->update_order = -1*getNextSequence();

            return executeQuery('document.updateCommentCount', $args);
        }

        /**
         * @brief 해당 document의 엮인글 수증가
         **/
        function updateTrackbackCount($document_srl, $trackback_count) {
            $args->document_srl = $document_srl;
            $args->trackback_count = $trackback_count;

            return executeQuery('document.updateTrackbackCount', $args);
        }

        /** 
         * @brief 카테고리에 문서의 숫자를 변경
         **/
        function updateCategoryCount($category_srl, $document_count = 0) {
            // document model 객체 생성
            $oDocumentModel = &getModel('document');
            if(!$document_count) $document_count = $oDocumentModel->getCategoryDocumentCount($category_srl);

            $args->category_srl = $category_srl;
            $args->document_count = $document_count;
            return executeQuery('document.updateCategoryCount', $args);
        }

        /**
         * @brief document의 20개 확장변수를 xml js filter 적용을 위해 직접 적용
         * 모듈정보를 받아서 20개의 확장변수를 체크하여 type, required등의 값을 체크하여 header에 javascript 코드 추가
         **/
        function addXmlJsFilter($module_info) {
            $extra_vars = $module_info->extra_vars;
            if(!$extra_vars) return;

            $js_code = "";

            foreach($extra_vars as $key => $val) {
                $js_code .= sprintf('alertMsg["extra_vars%d"] = "%s";', $key, $val->name);
                $js_code .= sprintf('extra_vars[extra_vars.length] = "extra_vars%d";', $key);
                $js_code .= sprintf('target_type_list["extra_vars%d"] = "%s";', $key, $val->type);
                if($val->is_required == 'Y') $js_code .= sprintf('notnull_list[notnull_list.length] = "extra_vars%s";',$key);
            }

            $js_code = "<script type=\"text/javascript\">//<![CDATA[\n".$js_code."\n//]]></script>";
            Context::addHtmlHeader($js_code);
        }
    }
?>
