diff --git a/common/lang/en.php b/common/lang/en.php index 45c06ec9d..cce0402b5 100644 --- a/common/lang/en.php +++ b/common/lang/en.php @@ -297,6 +297,7 @@ $lang->column_type_list['date'] = 'date(yyyy/mm/dd)'; $lang->column_name = 'Column Name'; $lang->column_title = 'Column Title'; $lang->default_value = 'Default Value'; +$lang->default_folder = 'Default Folder'; $lang->is_active = 'Active'; $lang->is_required = 'Required Field'; $lang->eid = 'Name of user defined'; diff --git a/common/lang/ko.php b/common/lang/ko.php index 3f5697d9d..b5571ba87 100644 --- a/common/lang/ko.php +++ b/common/lang/ko.php @@ -296,7 +296,8 @@ $lang->column_type_list['kr_zip'] = '한국주소(zip)'; $lang->column_type_list['date'] = '일자(연월일)'; $lang->column_name = '입력항목 이름'; $lang->column_title = '입력항목 제목'; -$lang->default_value = '기본 값'; +$lang->default_value = '기본값'; +$lang->default_folder = '기본 폴더'; $lang->is_active = '활성'; $lang->is_required = '필수항목'; $lang->eid = '사용자 정의 이름'; diff --git a/modules/member/conf/module.xml b/modules/member/conf/module.xml index f1230cda2..dced1ca9e 100644 --- a/modules/member/conf/module.xml +++ b/modules/member/conf/module.xml @@ -46,6 +46,10 @@ + + + + diff --git a/modules/member/lang/en.php b/modules/member/lang/en.php index 725155d3b..7d5dcd4a5 100644 --- a/modules/member/lang/en.php +++ b/modules/member/lang/en.php @@ -121,6 +121,9 @@ $lang->cmd_view_saved_document = 'Saved Articles'; $lang->cmd_send_email = 'Send Mail'; $lang->msg_email_not_exists = 'You have entered an invalid email address.'; $lang->msg_alreay_scrapped = 'This article is already scrapped.'; +$lang->msg_folder_alreay_exists = 'A folder with the same name already exists.'; +$lang->msg_folder_is_default = 'The default folder cannot be renamed or deleted.'; +$lang->msg_folder_not_empty = 'The folder is not empty.'; $lang->msg_cart_is_null = 'Please select the target.'; $lang->msg_checked_file_is_deleted = '%d attached file(s) is(are) deleted.'; $lang->msg_find_account_title = 'Account Info'; @@ -309,3 +312,6 @@ $lang->msg_spammer_complete = 'Completed.'; $lang->cmd_login_browser_info = 'Browser Information'; $lang->cmd_initial_login = 'First Login'; $lang->cmd_recent_visit = 'Recent Visit'; +$lang->scrap_folder_create = 'New Folder'; +$lang->scrap_folder_rename = 'Rename'; +$lang->scrap_folder_delete = 'Delete'; diff --git a/modules/member/lang/ko.php b/modules/member/lang/ko.php index bbf2e0bef..53475f3ac 100644 --- a/modules/member/lang/ko.php +++ b/modules/member/lang/ko.php @@ -125,6 +125,9 @@ $lang->cmd_modify_nickname_log = '닉네임 변경 기록'; $lang->cmd_member_profile_view = '회원 프로필사진 보이기'; $lang->msg_email_not_exists = '이메일 주소가 존재하지 않습니다.'; $lang->msg_alreay_scrapped = '이미 스크랩된 게시물입니다.'; +$lang->msg_folder_alreay_exists = '이미 존재하는 폴더 이름입니다.'; +$lang->msg_folder_is_default = '기본 폴더는 이름을 변경하거나 삭제할 수 없습니다.'; +$lang->msg_folder_not_empty = '폴더가 비어 있지 않습니다.'; $lang->msg_cart_is_null = '대상을 선택해주세요.'; $lang->msg_checked_file_is_deleted = '%d개의 첨부 파일이 삭제되었습니다.'; $lang->msg_find_account_title = '아이디/비밀번호 정보입니다.'; @@ -329,3 +332,6 @@ $lang->nick_name_after_changing = '닉네임 변경 후'; $lang->cmd_login_browser_info = '브라우저 정보'; $lang->cmd_initial_login = '최초 로그인'; $lang->cmd_recent_visit = '최근 방문'; +$lang->scrap_folder_create = '폴더 추가'; +$lang->scrap_folder_rename = '이름 변경'; +$lang->scrap_folder_delete = '삭제'; diff --git a/modules/member/member.class.php b/modules/member/member.class.php index 499362b61..a318adb59 100644 --- a/modules/member/member.class.php +++ b/modules/member/member.class.php @@ -207,7 +207,10 @@ class member extends ModuleObject { // Check autologin table if(!$oDB->isColumnExists("member_autologin", "security_key")) return true; - + + // Check scrap folder table + if(!$oDB->isColumnExists("member_scrap", "folder_srl")) return true; + $oModuleModel = getModel('module'); $config = $oModuleModel->getModuleConfig('member'); // check signup form ordering info @@ -328,6 +331,13 @@ class member extends ModuleObject { $oDB->createTableByXmlFile($this->module_path . '/schemas/member_autologin.xml'); } + // Check scrap folder table + if(!$oDB->isColumnExists("member_scrap", "folder_srl")) + { + $oDB->addColumn("member_scrap", "folder_srl", "number", 11); + $oDB->addIndex("member_scrap","idx_folder_srl", array("folder_srl")); + } + $oModuleModel = getModel('module'); $config = $oModuleModel->getModuleConfig('member'); $oModuleController = getController('module'); diff --git a/modules/member/member.controller.php b/modules/member/member.controller.php index 32ab709ba..289acca05 100644 --- a/modules/member/member.controller.php +++ b/modules/member/member.controller.php @@ -159,10 +159,25 @@ class memberController extends member return new Object(-1, 'msg_not_permitted'); } + // Find default scrap folder + $args = new stdClass(); + $args->member_srl = $logged_info->member_srl; + $args->name = '/DEFAULT/'; + $output = executeQuery('member.getScrapFolderList', $args); + if($output->toBool() && is_object($output->data) && $output->data->folder_srl) + { + $default_folder_srl = $output->data->folder_srl; + } + else + { + $default_folder_srl = null; + } + // Variables $args = new stdClass(); $args->document_srl = $document_srl; $args->member_srl = $logged_info->member_srl; + $args->folder_srl = $default_folder_srl; $args->user_id = $oDocument->get('user_id'); $args->user_name = $oDocument->get('user_name'); $args->nick_name = $oDocument->get('nick_name'); @@ -204,6 +219,206 @@ class memberController extends member return executeQuery('member.deleteScrapDocument', $args); } + /** + * Move a scrap to another folder + * + * @return void|Object (void : success, Object : fail) + */ + function procMemberMoveScrapFolder() + { + // Check login information + if(!Context::get('is_logged')) return new Object(-1, 'msg_not_logged'); + $logged_info = Context::get('logged_info'); + + $document_srl = (int)Context::get('document_srl'); + $folder_srl = (int)Context::get('folder_srl'); + if(!$document_srl || !$folder_srl) + { + return new Object(-1,'msg_invalid_request'); + } + + // Check that the target folder exists and belongs to member + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->folder_srl = $folder_srl; + $output = executeQueryArray('member.getScrapFolderList', $args); + if(!count($output->data)) + { + return new Object(-1, 'msg_invalid_request'); + } + + // Move + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->document_srl = $document_srl; + $args->folder_srl = $folder_srl; + return executeQuery('member.updateScrapDocumentFolder', $args); + } + + /** + * Create a scrap folder + * + * @return void|Object (void : success, Object : fail) + */ + function procMemberInsertScrapFolder() + { + // Check login information + if(!Context::get('is_logged')) return new Object(-1, 'msg_not_logged'); + $logged_info = Context::get('logged_info'); + + // Get new folder name + $folder_name = Context::get('name'); + $folder_name = escape(trim(utf8_normalize_spaces($folder_name))); + if(!$folder_name) + { + return new Object(-1, 'msg_invalid_request'); + } + + // Check existing folder with same name + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->name = $folder_name; + $output = executeQueryArray('member.getScrapFolderList', $args); + if(count($output->data) || $folder_name === lang('default_folder')) + { + return new Object(-1, 'msg_folder_alreay_exists'); + } + + // Create folder + $args = new stdClass; + $args->folder_srl = getNextSequence(); + $args->member_srl = $logged_info->member_srl; + $args->name = $folder_name; + $args->list_order = $args->folder_srl; + $this->add('folder_srl', $args->folder_srl); + return executeQuery('member.insertScrapFolder', $args); + } + + /** + * Rename a scrap folder + * + * @return void|Object (void : success, Object : fail) + */ + function procMemberRenameScrapFolder() + { + // Check login information + if(!Context::get('is_logged')) return new Object(-1, 'msg_not_logged'); + $logged_info = Context::get('logged_info'); + + // Get new folder name + $folder_srl = intval(Context::get('folder_srl')); + $folder_name = Context::get('name'); + $folder_name = escape(trim(utf8_normalize_spaces($folder_name))); + if(!$folder_srl || !$folder_name) + { + return new Object(-1, 'msg_invalid_request'); + } + + // Check that the original folder exists and belongs to member + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->folder_srl = $folder_srl; + $output = executeQueryArray('member.getScrapFolderList', $args); + if(!count($output->data)) + { + return new Object(-1, 'msg_invalid_request'); + } + if(array_first($output->data)->name === '/DEFAULT/') + { + return new Object(-1, 'msg_folder_is_default'); + } + + // Check existing folder with same name + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->not_folder_srl = $folder_srl; + $args->name = $folder_name; + $output = executeQueryArray('member.getScrapFolderList', $args); + if(count($output->data) || $folder_name === lang('default_folder')) + { + return new Object(-1, 'msg_folder_alreay_exists'); + } + + // Rename folder + $args = new stdClass; + $args->folder_srl = $folder_srl; + $args->name = $folder_name; + return executeQuery('member.updateScrapFolder', $args); + } + + /** + * Delete a scrap folder + * + * @return void|Object (void : success, Object : fail) + */ + function procMemberDeleteScrapFolder() + { + // Check login information + if(!Context::get('is_logged')) return new Object(-1, 'msg_not_logged'); + $logged_info = Context::get('logged_info'); + + // Get folder_srl to delete + $folder_srl = intval(Context::get('folder_srl')); + if(!$folder_srl) + { + return new Object(-1, 'msg_invalid_request'); + } + + // Check that the folder exists and belongs to member + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->folder_srl = $folder_srl; + $output = executeQueryArray('member.getScrapFolderList', $args); + if(!count($output->data)) + { + return new Object(-1, 'msg_invalid_request'); + } + if(array_first($output->data)->name === '/DEFAULT/') + { + return new Object(-1, 'msg_folder_is_default'); + } + + // Check that the folder is empty + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $args->folder_srl = $folder_srl; + $output = executeQueryArray('member.getScrapDocumentList', $args); + if(count($output->data)) + { + return new Object(-1, 'msg_folder_not_empty'); + } + + // Delete folder + $args = new stdClass; + $args->folder_srl = $folder_srl; + return executeQuery('member.deleteScrapFolder', $args); + } + + /** + * Migrate a member's scrapped documents to the new folder system. + * + * @param int $member_srl + * @return void|Object (void : success, Object : fail) + */ + function migrateMemberScrappedDocuments($member_srl) + { + $args = new stdClass; + $args->folder_srl = getNextSequence(); + $args->member_srl = $member_srl; + $args->name = '/DEFAULT/'; + $args->list_order = $args->folder_srl; + $output = executeQuery('member.insertScrapFolder', $args); + if(!$output->toBool()) + { + return $output; + } + $output = executeQuery('member.updateScrapFolderFromNull', $args); + if(!$output->toBool()) + { + return $output; + } + } + /** * Save posts * @deprecated - instead Document Controller - procDocumentTempSave method use diff --git a/modules/member/member.view.php b/modules/member/member.view.php index 9fa7a5475..0372be448 100644 --- a/modules/member/member.view.php +++ b/modules/member/member.view.php @@ -410,16 +410,60 @@ class memberView extends member if(!$oMemberModel->isLogged()) return $this->stop('msg_not_logged'); $logged_info = Context::get('logged_info'); + + // Check folders + $args = new stdClass; + $args->member_srl = $logged_info->member_srl; + $output = executeQueryArray('member.getScrapFolderList', $args); + $folders = $output->data; + if(!count($folders)) + { + $output = getController('member')->migrateMemberScrappedDocuments($logged_info->member_srl); + if($output && !$output->toBool()) + { + return $output; + } + + $output = executeQueryArray('member.getScrapFolderList', $args); + $folders = $output->data; + } + + // Get default folder if no folder is selected + $folder_srl = (int)Context::get('folder_srl'); + if($folder_srl && !array_filter($folders, function($folder) use($folder_srl) { return $folder->folder_srl == $folder_srl; })) + { + return new Object(-1, 'msg_invalid_request'); + } + if(!$folder_srl && count($folders)) + { + $folder_srl = array_first($folders)->folder_srl; + } + + // Get folder info + $folder_info = new stdClass; + foreach($folders as $folder) + { + if($folder->folder_srl == $folder_srl) + { + $folder_info = $folder; + break; + } + } + + // Get scrapped documents in selected folder $args = new stdClass(); $args->member_srl = $logged_info->member_srl; + $args->folder_srl = $folder_srl; $args->page = (int)Context::get('page'); - - $output = executeQuery('member.getScrapDocumentList', $args); + $output = executeQueryArray('member.getScrapDocumentList', $args); Context::set('total_count', $output->total_count); Context::set('total_page', $output->total_page); Context::set('page', $output->page); Context::set('document_list', $output->data); Context::set('page_navigation', $output->page_navigation); + Context::set('scrap_folders', $folders); + Context::set('folder_info', $folder_info); + Context::set('folder_srl', $folder_srl); $security = new Security($output->data); $security->encodeHTML('..nick_name'); diff --git a/modules/member/queries/addScrapDocument.xml b/modules/member/queries/addScrapDocument.xml index 9d8045350..a873a4ef4 100644 --- a/modules/member/queries/addScrapDocument.xml +++ b/modules/member/queries/addScrapDocument.xml @@ -5,6 +5,7 @@ + diff --git a/modules/member/queries/deleteScrapFolder.xml b/modules/member/queries/deleteScrapFolder.xml new file mode 100644 index 000000000..b890a1639 --- /dev/null +++ b/modules/member/queries/deleteScrapFolder.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/modules/member/queries/getScrapDocumentList.xml b/modules/member/queries/getScrapDocumentList.xml index 33969197d..9df3439e2 100644 --- a/modules/member/queries/getScrapDocumentList.xml +++ b/modules/member/queries/getScrapDocumentList.xml @@ -7,6 +7,7 @@ + diff --git a/modules/member/queries/getScrapFolderList.xml b/modules/member/queries/getScrapFolderList.xml new file mode 100644 index 000000000..a8005a88a --- /dev/null +++ b/modules/member/queries/getScrapFolderList.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/member/queries/insertScrapFolder.xml b/modules/member/queries/insertScrapFolder.xml new file mode 100644 index 000000000..46955b7d9 --- /dev/null +++ b/modules/member/queries/insertScrapFolder.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/modules/member/queries/updateScrapDocumentFolder.xml b/modules/member/queries/updateScrapDocumentFolder.xml new file mode 100644 index 000000000..bb2547c50 --- /dev/null +++ b/modules/member/queries/updateScrapDocumentFolder.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/member/queries/updateScrapFolder.xml b/modules/member/queries/updateScrapFolder.xml new file mode 100644 index 000000000..773823233 --- /dev/null +++ b/modules/member/queries/updateScrapFolder.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/modules/member/queries/updateScrapFolderFromNull.xml b/modules/member/queries/updateScrapFolderFromNull.xml new file mode 100644 index 000000000..2048d4e10 --- /dev/null +++ b/modules/member/queries/updateScrapFolderFromNull.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/member/schemas/member_scrap.xml b/modules/member/schemas/member_scrap.xml index 5ea197c20..11ca1cfa6 100644 --- a/modules/member/schemas/member_scrap.xml +++ b/modules/member/schemas/member_scrap.xml @@ -1,6 +1,7 @@ + diff --git a/modules/member/schemas/member_scrap_folders.xml b/modules/member/schemas/member_scrap_folders.xml new file mode 100644 index 000000000..20fdc5460 --- /dev/null +++ b/modules/member/schemas/member_scrap_folders.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/modules/member/skins/default/js/member.js b/modules/member/skins/default/js/member.js index 41c8e720c..25d7998b0 100644 --- a/modules/member/skins/default/js/member.js +++ b/modules/member/skins/default/js/member.js @@ -131,7 +131,7 @@ function doDeleteImageMark(member_srl) { function doDeleteScrap(document_srl) { var params = new Array(); params['document_srl'] = document_srl; - exec_xml('member', 'procMemberDeleteScrap', params, function() { location.reload(); }); + exec_json('member.procMemberDeleteScrap', params, function() { location.reload(); }); } /* 비밀번호 찾기 후 */ @@ -154,10 +154,57 @@ function doDeleteSavedDocument(document_srl, confirm_message) { var params = new Array(); params['document_srl'] = document_srl; - exec_xml('member', 'procMemberDeleteSavedDocument', params, function() { location.reload(); }); + exec_json('member.procMemberDeleteSavedDocument', params, function() { location.reload(); }); } function insertSelectedModule(id, module_srl, mid, browser_title) { location.href = current_url.setQuery('selected_module_srl',module_srl); } +/* 스크랩 폴더 이동 */ +jQuery(function($) { + $("#scrap_folder_create").on("click", function() { + var input = $(this).siblings("input.folder_name").first(); + if (!input.is(":visible")) { + input.show(); + } else { + if (!input.val()) return; + var params = { name: input.val() }; + exec_json('member.procMemberInsertScrapFolder', params, function(data) { + window.location.href = current_url.setQuery("folder_srl", data.folder_srl); + }); + } + }); + $("#scrap_folder_rename").on("click", function() { + var folder_srl = $(this).data("folder-srl"); + var input = $(this).siblings("input.folder_name").first(); + if (!input.is(":visible")) { + input.show(); + } else { + if (!input.val()) return; + var params = { folder_srl: folder_srl, name: input.val() }; + exec_json('member.procMemberRenameScrapFolder', params, function() { + window.location.reload(); + }); + } + }); + $("#scrap_folder_delete").on("click", function() { + var folder_srl = $(this).data("folder-srl"); + var params = { folder_srl: folder_srl }; + exec_json('member.procMemberDeleteScrapFolder', params, function() { + window.location.href = current_url.setQuery("folder_srl", ""); + }); + }); + $("#scrap_folder_list").on("change", function() { + window.location.href = current_url.setQuery("folder_srl", $(this).val()); + }); + $(".scrap_folder_move").on("change", function() { + var document_srl = $(this).data('document-srl'); + var folder_srl = $(this).val(); + if (!folder_srl) return; + var params = { document_srl: document_srl, folder_srl: folder_srl }; + exec_json('member.procMemberMoveScrapFolder', params, function() { + window.location.reload(); + }); + }); +}); diff --git a/modules/member/skins/default/scrapped_list.html b/modules/member/skins/default/scrapped_list.html index 6da285f2f..4579961b1 100644 --- a/modules/member/skins/default/scrapped_list.html +++ b/modules/member/skins/default/scrapped_list.html @@ -1,7 +1,27 @@ {$member_title = $lang->cmd_view_scrapped_document} + + + + + + folder_srl">{$folder->name == '/DEFAULT/' ? $lang->default_folder : $folder->name} + + + + + {$lang->scrap_folder_rename} + {$lang->scrap_folder_delete} + + + + + {$lang->scrap_folder_create} + + + + - Total: {number_format($total_count)}, Page: {number_format($page)}/{number_format($total_page)} {$lang->no} @@ -9,6 +29,7 @@ {$lang->writer} {$lang->date} {$lang->cmd_delete} + {$lang->cmd_move} @@ -18,9 +39,18 @@ {$val->nick_name} {zdate($val->regdate, "Y-m-d")} {$lang->cmd_delete} + + + {$lang->cmd_move} + + {$folder->name == '/DEFAULT/' ? $lang->default_folder : $folder->name} + + + + « {$lang->first_page} diff --git a/modules/member/skins/simple_world/js/member.js b/modules/member/skins/simple_world/js/member.js index 41c8e720c..81eb06b0f 100644 --- a/modules/member/skins/simple_world/js/member.js +++ b/modules/member/skins/simple_world/js/member.js @@ -161,3 +161,50 @@ function insertSelectedModule(id, module_srl, mid, browser_title) { location.href = current_url.setQuery('selected_module_srl',module_srl); } +/* 스크랩 폴더 이동 */ +jQuery(function($) { + $("#scrap_folder_create").on("click", function() { + var input = $(this).siblings("input.folder_name").first(); + if (!input.is(":visible")) { + input.show(); + } else { + if (!input.val()) return; + var params = { name: input.val() }; + exec_json('member.procMemberInsertScrapFolder', params, function(data) { + window.location.href = current_url.setQuery("folder_srl", data.folder_srl); + }); + } + }); + $("#scrap_folder_rename").on("click", function() { + var folder_srl = $(this).data("folder-srl"); + var input = $(this).siblings("input.folder_name").first(); + if (!input.is(":visible")) { + input.show(); + } else { + if (!input.val()) return; + var params = { folder_srl: folder_srl, name: input.val() }; + exec_json('member.procMemberRenameScrapFolder', params, function() { + window.location.reload(); + }); + } + }); + $("#scrap_folder_delete").on("click", function() { + var folder_srl = $(this).data("folder-srl"); + var params = { folder_srl: folder_srl }; + exec_json('member.procMemberDeleteScrapFolder', params, function() { + window.location.href = current_url.setQuery("folder_srl", ""); + }); + }); + $("#scrap_folder_list").on("change", function() { + window.location.href = current_url.setQuery("folder_srl", $(this).val()); + }); + $(".scrap_folder_move").on("change", function() { + var document_srl = $(this).data('document-srl'); + var folder_srl = $(this).val(); + if (!folder_srl) return; + var params = { document_srl: document_srl, folder_srl: folder_srl }; + exec_json('member.procMemberMoveScrapFolder', params, function() { + window.location.reload(); + }); + }); +}); diff --git a/modules/member/skins/simple_world/scrapped_list.html b/modules/member/skins/simple_world/scrapped_list.html index 2984a3f10..76ea1ece9 100644 --- a/modules/member/skins/simple_world/scrapped_list.html +++ b/modules/member/skins/simple_world/scrapped_list.html @@ -1,7 +1,20 @@ {$member_title = lang('member.cmd_view_scrapped_document')} - {lang('common.total')}: {number_format($total_count)} + + + + + folder_srl">{$folder->name == '/DEFAULT/' ? $lang->default_folder : $folder->name} + + + + + {$lang->scrap_folder_rename} + {$lang->scrap_folder_delete} + + + @@ -31,4 +44,8 @@ {$lang->last_page} › +