diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 2f601d5..885e815 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -74,6 +74,18 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin', 'filter' => 'au $routes->get('toggle/(:num)/(:hash)', 'LoggerController::toggle/$1/$2', ['filter' => 'authFilter:master,director']); $routes->post('batchjob', 'LoggerController::batchjob', ['filter' => 'authFilter:master']); }); + $routes->group('board', static function ($routes) { + $routes->get('', 'BoardController::index'); + $routes->get('excel', 'BoardController::excel'); + $routes->get('insert', 'BoardController::insert_form', ['filter' => 'authFilter:master,director']); + $routes->post('insert', 'BoardController::insert', ['filter' => 'authFilter:master,director']); + $routes->get('update/(:num)', 'BoardController::update_form/$1'); + $routes->post('update/(:num)', 'BoardController::update/$1'); + $routes->get('view/(:num)', 'BoardController::view/$1'); + $routes->get('delete/(:num)', 'BoardController::delete/$1', ['filter' => 'authFilter:master,director']); + $routes->get('toggle/(:num)/(:hash)', 'BoardController::toggle/$1/$2', ['filter' => 'authFilter:master,director']); + $routes->post('batchjob', 'BoardController::batchjob', ['filter' => 'authFilter:master,director']); + }); $routes->group('hpilo', static function ($routes) { $routes->get('', 'HPILOController::index'); $routes->get('excel', 'HPILOController::excel'); @@ -82,12 +94,12 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin', 'filter' => 'au $routes->get('update/(:num)', 'HPILOController::update_form/$1'); $routes->post('update/(:num)', 'HPILOController::update/$1'); $routes->get('view/(:num)', 'HPILOController::view/$1'); - $routes->get('delete/(:num)', 'HPILOController::delete/$1', ['filter' => 'authFilter:master']); + $routes->get('delete/(:num)', 'HPILOController::delete/$1', ['filter' => 'authFilter:master,director']); $routes->get('toggle/(:num)/(:hash)', 'HPILOController::toggle/$1/$2', ['filter' => 'authFilter:master,director']); - $routes->post('batchjob', 'HPILOController::batchjob', ['filter' => 'authFilter:master']); - $routes->get('console/(:num)', 'HPILOController::console/$1', ['filter' => 'authFilter:master']); - $routes->get('reset/(:num)/(:alpha)', 'HPILOController::reset/$1/$2', ['filter' => 'authFilter:master']); - $routes->get('reload/(:num)', 'HPILOController::reload/$1', ['filter' => 'authFilter:master']); + $routes->post('batchjob', 'HPILOController::batchjob', ['filter' => 'authFilter:master,director']); + $routes->post('console/(:num)', 'HPILOController::console/$1', ['filter' => 'authFilter:master,director']); + $routes->post('reset/(:num)/(:alpah)', 'HPILOController::reset/$1/$2', ['filter' => 'authFilter:master,director']); + $routes->post('reload/(:num)', 'HPILOController::reload/$1', ['filter' => 'authFilter:master,director']); }); }); /* diff --git a/app/Controllers/Admin/BoardController.php b/app/Controllers/Admin/BoardController.php new file mode 100644 index 0000000..953d5ac --- /dev/null +++ b/app/Controllers/Admin/BoardController.php @@ -0,0 +1,133 @@ +_className .= '/Board'; + $this->_model = new BoardModel(); + $this->_defines = [ + 'insert' => [ + 'fields' => ['board_category', 'title', 'content', 'passwd', 'confirmpassword', 'status'], + 'fieldFilters' => ['board_category', 'user_uid', 'status'], + 'fieldRules' => [ + 'board_category' => 'required|string', + 'title' => 'required|string', + 'content' => 'required|string', + 'passwd' => 'if_exist|trim|string', + 'confirmpassword' => 'if_exist|trim|matches[passwd]', + 'view_cnt' => 'if_exist|numeric', + 'status' => 'if_exist|string', + ] + ], + 'update' => [ + 'fields' => ['board_category', 'title', 'content', 'passwd', 'confirmpassword', 'status'], + 'fieldFilters' => ['board_category', 'user_uid', 'status'], + 'fieldRules' => [ + 'board_category' => 'required|string', + 'title' => 'required|string', + 'content' => 'required|string', + 'passwd' => 'if_exist|trim|string', + 'confirmpassword' => 'if_exist|trim|matches[passwd]', + 'view_cnt' => 'if_exist|numeric', + 'status' => 'if_exist|string', + ] + ], + 'view' => [ + 'fields' => ['board_category', 'user_uid', 'title', 'view_cnt', 'status', 'updated_at', 'created_at', 'content'], + 'fieldFilters' => ['board_category', 'user_uid', 'status'], + 'fieldRules' => ['board_category', 'user_uid', 'status'], + ], + 'index' => [ + 'fields' => ['board_category', 'user_uid', 'title', 'view_cnt', 'status', 'updated_at', 'created_at'], + 'fieldFilters' => ['board_category', 'user_uid', 'status'], + 'batchjobFilters' => ['board_category', 'user_uid', 'status'], + ], + 'excel' => [ + 'fields' => ['board_category', 'user_uid', 'title', 'view_cnt', 'status', 'updated_at', 'created_at'], + 'fieldFilters' => ['board_category', 'user_uid', 'status'], + ], + ]; + helper($this->_className); + $this->_viewPath = strtolower($this->_className); + $this->_viewDatas['title'] = lang($this->_className . '.title'); + $this->_viewDatas['className'] = $this->_className; + } + + private function getUserModel(): UserModel + { + return is_null($this->_userModel) ? new UserModel() : $this->_userModel; + } + + //Field별 Form Option용 + protected function getFieldFormOption(string $field): array + { + switch ($field) { + case 'user_uid': + if (is_null($this->_user_uids)) { + //모든 필요한 FormOption등 조기화작업 필요 + $this->_user_uids = $this->getUserModel()->getFieldFormOptions( + ['status' => 'use'], + [DEFAULTS['EMPTY'] => lang($this->_className . '.label.' . $field) . ' 선택'] + ); + } + return $this->_user_uids; + default: + return parent::getFieldFormOption($field); + break; + } + } + + ////Action 모음 + //Insert관련 + final public function insert() + { + return $this->insert_procedure(); + } + //Update관련 + final public function update($uid) + { + return $this->update_procedure($uid); + } + //Toggle관련 + final public function toggle($uid, string $field) + { + return $this->toggle_procedure($uid, $field); + } + //Batchjob 관련 + final public function batchjob() + { + return $this->batchjob_procedure(); + } + //Delete 관련 + final public function delete($uid) + { + return $this->delete_procedure($uid); + } + //View 관련 + final public function view($uid) + { + return $this->view_procedure($uid); + } + //Index 관련 + final public function index() + { + return $this->index_procedure(); + } + //Excel 관련 + final public function excel() + { + return $this->excel_procedure(); + } +} diff --git a/app/Controllers/BaseController.php b/app/Controllers/BaseController.php index ad29e00..961e8f5 100644 --- a/app/Controllers/BaseController.php +++ b/app/Controllers/BaseController.php @@ -165,6 +165,8 @@ abstract class BaseController extends Controller $this->insert_process(); $message = __FUNCTION__ . " 완료하였습니다."; Log::save("{$this->_viewDatas['title']} {$message}"); + //session->setTempdata의 기능은 3초간 success에 message를 보관후 사라짐 + //$this->_session->setTempdata('success', 'Page updated successfully', 3); return alert_CommonHelper($message, $this->_session->get(SESSION_NAMES['RETURN_URL'])); } catch (\Exception $e) { $message = __FUNCTION__ . " 실패하였습니다."; @@ -545,4 +547,10 @@ abstract class BaseController extends Controller return alert_CommonHelper($e->getMessage(), 'back'); } } + + //File Download관련 + protected function download_process($path, string $real_filename, string $download_filename = 'download') + { + return $this->response->download($path . "/" . $real_filename, null)->setFileName($download_filename); + } } diff --git a/app/Database/board.sql b/app/Database/board.sql new file mode 100644 index 0000000..8d0bf02 --- /dev/null +++ b/app/Database/board.sql @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS tw_board; +-- 1. 게시물 추가전 grpno에 해당하는 기존게시물의 grpord를 +1씩증가 작업 +-- update tw_board set grpord=grpord+1 where grpno=그룹번호 and grpord > 선택한 grpno +-- 2. 게시물 추가시 작업 +-- insert tw_board grpno=그룹번호,grpord=grpord+1,grpdpt=grpdpt+1 +-- 3. 게시물 조회시 작업 +-- select * from tw_board order by grpno desc,grpord asc +CREATE TABLE tw_board ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + grpno int(5) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Group번호: 상위가없을시 기본 uid와 같음', + grpord int(5) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Group순서: 상위가없을시 0부터시작', + grpdpt int(3) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Group깊이: 상위가없을시 1부터시작 , 상위 grpdpt+1씩 추가필요', + board_category varchar(10) NOT NULL COMMENT '게시판구분', + user_uid varchar(36) NULL COMMENT '작성자 정보', + title varchar(255) NOT NULL COMMENT '제목', + content text NOT NULL COMMENT '내용', + passwd varchar(20) NULL COMMENT '작성자 암호', + view_cnt int(5) NOT NULL DEFAULT 0 COMMENT '조회수', + status varchar(10) NOT NULL DEFAULT 'use' COMMENT 'use: 사용, unuse: 사용않함 등등', + updated_at timestamp NULL DEFAULT NULL, + created_at timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (uid), + CONSTRAINT FOREIGN KEY (user_uid) REFERENCES tw_user (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT ='게시판 정보'; \ No newline at end of file diff --git a/app/Entities/BoardEntity.php b/app/Entities/BoardEntity.php new file mode 100644 index 0000000..22befdf --- /dev/null +++ b/app/Entities/BoardEntity.php @@ -0,0 +1,29 @@ +attributes['uid']; + } + public function getTitle() + { + return $this->attributes['title']; + } + public function getPassword() + { + return $this->attributes['passwd']; + } + public function getViews() + { + return $this->attributes['view_cnt']; + } +} diff --git a/app/Helpers/Admin/Board_helper.php b/app/Helpers/Admin/Board_helper.php new file mode 100644 index 0000000..a1e9dea --- /dev/null +++ b/app/Helpers/Admin/Board_helper.php @@ -0,0 +1,82 @@ +%s", implode(" ", $attributes), lang("Admin/Board.label.{$field}")); + break; + } +} + +//header.php에서 getFieldForm_Helper사용 +function getFieldForm_BoardHelper($field, $value, array $formOptions, array $attributes = array()) +{ + $value = is_null($value) ? DEFAULTS['EMPTY'] : $value; + switch ($field) { + case 'board_category': + case 'user_uid': + case 'status': + return form_dropdown($field, $formOptions[$field], $value, $attributes); + break; + case 'updated_at': + case 'created_at': + return form_input($field, $value, [...$attributes, 'class' => 'calender']); + break; + case 'passwd': + case 'confirmpassword': + return form_password($field, DEFAULTS['EMPTY'], $attributes); + break; + case 'content': + return form_textarea($field, html_entity_decode($value), [...$attributes, 'class' => 'editor', 'rows' => '20', 'cols' => '100']); + break; + default: + return form_input($field, $value, [...$attributes, 'size' => '80']); + break; + } +} // + +function getFieldView_BoardHelper($field, $entity, array $fieldFilters, array $fieldFormOptions, array $attributes = array()) +{ + switch ($field) { + case 'content': + return html_entity_decode($entity->$field); + break; + default: + if (in_array($field, $fieldFilters)) { + return getFieldForm_BoardHelper($field, $entity->$field, $fieldFormOptions, $attributes); + } + return $entity->$field; + break; + } +} // + +function getFieldIndex_Column_BoardHelper($field, $order_field, $order_value, array $attributes = array()) +{ + $label = lang("Admin/Board.label.{$field}"); + $label = $field == $order_field ? sprintf('%s ', $label, $order_value == 'ASC' ? "up" : "down") : $label; + $order_value = $order_value == 'DESC' ? "ASC" : "DESC"; + return anchor(current_url() . "?order_field={$field}&order_value={$order_value}", $label, $attributes); +} // + +function getFieldIndex_Row_BoardHelper($field, array $row, array $fieldFilters, $fieldFormOptions, $attributes = array()): string +{ + switch ($field) { + case 'title': + return anchor(current_url() . '/view/' . $row['uid'], $row[$field], ["target" => "_self"]); + break; + case 'updated_at': + case 'created_at': + return isset($row[$field]) ? str_split($row[$field], 10)[0] : ""; + break; + default: + if (in_array($field, $fieldFilters)) { + $attributes["onChange"] = sprintf('location.href="%s/toggle/%s/%s?%s="+this.options[this.selectedIndex].value', current_url(), $row['uid'], $field, $field); + return getFieldForm_BoardHelper($field, $row[$field], $fieldFormOptions, $attributes); + } + return $row[$field]; + break; + } +} // \ No newline at end of file diff --git a/app/Helpers/Admin/Logger_helper.php b/app/Helpers/Admin/Logger_helper.php index 16ad303..adb8e80 100644 --- a/app/Helpers/Admin/Logger_helper.php +++ b/app/Helpers/Admin/Logger_helper.php @@ -22,8 +22,7 @@ function getFieldForm_LoggerHelper($field, $value, array $formOptions, array $at break; case 'updated_at': case 'created_at': - $attributes["class"] = !array_key_exists("class", $attributes) ? "calender" : $attributes["class"] . " calender"; - return form_input($field, $value, $attributes); + form_input($field, $value, [...$attributes, 'class' => 'calender']); break; default: return form_input($field, $value, $attributes); @@ -34,14 +33,8 @@ function getFieldForm_LoggerHelper($field, $value, array $formOptions, array $at function getFieldView_LoggerHelper($field, $entity, array $fieldFilters, array $fieldFormOptions, array $attributes = array()) { switch ($field) { - case 'user_uid': - return $fieldFormOptions[$field][$entity->$field]; - break; - case 'status': - return lang("Admin/Logger." . strtoupper($field) . "." . $entity->$field); - break; case 'content': - return nl2br($entity->$field); + return html_entity_decode($entity->$field); break; default: if (in_array($field, $fieldFilters)) { diff --git a/app/Helpers/Admin/UserSNS_helper.php b/app/Helpers/Admin/UserSNS_helper.php index cc727a1..3bd3303 100644 --- a/app/Helpers/Admin/UserSNS_helper.php +++ b/app/Helpers/Admin/UserSNS_helper.php @@ -22,8 +22,7 @@ function getFieldForm_UserSNSHelper($field, $value, array $formOptions, array $a break; case 'updated_at': case 'created_at': - $attributes["class"] = !array_key_exists("class", $attributes) ? "calender" : $attributes["class"] . " calender"; - return form_input($field, $value, $attributes); + return form_input($field, $value, [...$attributes, 'class' => 'calender']); break; default: return form_input($field, $value, $attributes); @@ -34,12 +33,6 @@ function getFieldForm_UserSNSHelper($field, $value, array $formOptions, array $a function getFieldView_UserSNSHelper($field, $entity, array $fieldFilters, array $fieldFormOptions, array $attributes = array()) { switch ($field) { - case 'status': - return lang("Admin/UserSNS." . strtoupper($field) . "." . $entity->$field); - break; - case 'content': - return nl2br($entity->$field); - break; default: if (in_array($field, $fieldFilters)) { return getFieldForm_UserSNSHelper($field, $entity->$field, $fieldFormOptions, $attributes); diff --git a/app/Helpers/Admin/User_helper.php b/app/Helpers/Admin/User_helper.php index d1ec451..7ed18ee 100644 --- a/app/Helpers/Admin/User_helper.php +++ b/app/Helpers/Admin/User_helper.php @@ -22,8 +22,7 @@ function getFieldForm_UserHelper($field, $value, array $formOptions, array $attr break; case 'updated_at': case 'created_at': - $attributes["class"] = !array_key_exists("class", $attributes) ? "calender" : $attributes["class"] . " calender"; - return form_input($field, $value, $attributes); + return form_input($field, $value, [...$attributes, 'class' => 'calender']); break; case 'passwd': case 'confirmpassword': @@ -38,10 +37,6 @@ function getFieldForm_UserHelper($field, $value, array $formOptions, array $attr function getFieldView_UserHelper($field, $entity, array $fieldFilters, array $fieldFormOptions, array $attributes = array()) { switch ($field) { - case 'role': - case 'status': - return lang("Admin/User." . strtoupper($field) . "." . $entity->$field); - break; default: if (in_array($field, $fieldFilters)) { return getFieldForm_UserHelper($field, $entity->$field, $fieldFormOptions, $attributes); diff --git a/app/Language/en/Admin/Board.php b/app/Language/en/Admin/Board.php new file mode 100644 index 0000000..531f6b7 --- /dev/null +++ b/app/Language/en/Admin/Board.php @@ -0,0 +1,28 @@ + "게시판정보", + 'label' => [ + 'uid' => "번호", + 'grpno' => "그룹번호", + 'grpord' => "부모번호", + 'grpdpt' => "그룸Depth", + 'board_category' => "게시판구분", + 'user_uid' => "작성자", + 'title' => "제목", + 'content' => "내용", + 'passwd' => "암호", + 'confirmpassword' => "암호확인", + 'view_cnt' => "조회수", + 'status' => "상태", + 'updated_at' => "수정일", + 'created_at' => "작성일" + ], + "BOARD_CATEGORY" => [ + 'notice' => '공지사항', + 'faq' => 'FAQ', + 'qna' => '1:1문의', + 'data' => '자료실' + ], + "USER_UID" => [], + "STATUS" => [...STATUS], +]; diff --git a/app/Models/BoardModel.php b/app/Models/BoardModel.php new file mode 100644 index 0000000..655ef18 --- /dev/null +++ b/app/Models/BoardModel.php @@ -0,0 +1,88 @@ + 'if_exist|numeric', + 'grpord' => 'if_exist|numeric', + 'grpdpt' => 'if_exist|numeric', + 'board_category' => 'required|string', + 'user_uid' => 'if_exist|regex_match[/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/]', + 'title' => 'required|string', + 'content' => 'required|string', + 'passwd' => 'if_exist|trim|string', + 'view_cnt' => 'if_exist|numeric', + 'status' => 'if_exist|string', + 'updated_at' => 'if_exist|valid_date', + 'created_at' => 'if_exist|valid_date', + ]; + + public function getEntityByField($field, $value): ?BoardEntity + { + $entity = $this->asObject(BoardEntity::class)->where($field, $value)->first(); + if (is_null($entity)) { + throw new \Exception("해당 데이터가 없습니다.\n {$field}->{$value}"); + } + return $entity; + } + public function getEntity($uid): ?BoardEntity + { + return $this->getEntityByField($this->primaryKey, $uid); + } + public function getFieldFormOptions(array $wheres = array(), $temps = array()): array + { + foreach ($this->asObject(BoardEntity::class)->where($wheres)->findAll() as $entity) { + $temps[$entity->getPrimaryKey()] = $entity->getTitle(); + } + return $temps; + } + private function changeFormData($field, $value) + { + switch ($field) { + case 'passwd': + return password_hash($value, PASSWORD_DEFAULT); + break; + case 'content': + return htmlentities($value); + break; + } + return $value; + } + public function create(array $formDatas): BoardEntity + { + $entity = new BoardEntity($formDatas); + foreach ($formDatas as $field => $value) { + $entity->$field = $this->changeFormData($field, $value); + } + return parent::create_process($entity); + } + public function modify(BoardEntity $entity, array $formDatas): BoardEntity + { + foreach ($formDatas as $field => $value) { + $entity->$field = $this->changeFormData($field, $value); + } + return parent::modify_process($entity); + } + + //Index관련 + public function setIndexWordFilter(string $word) + { + parent::setIndexWordFilter($word); + $this->orLike('title', $word, 'both'); + $this->orLike('content', $word, 'both'); //befor , after , both + } + public function setIndexOrderBy($field, $order = 'DESC') + { + $this->orderBy("grpno", "DESC"); + $this->orderBy("grpord", "ASC"); + parent::setIndexOrderBy($field, $order); + } +} diff --git a/app/Views/admin/board/index.php b/app/Views/admin/board/index.php new file mode 100644 index 0000000..4827a70 --- /dev/null +++ b/app/Views/admin/board/index.php @@ -0,0 +1,49 @@ +extend('layouts/admin') ?> +section('content') ?> +include('templates/admin/header'); ?> +
+
+ "get")) ?> + + +
+
+ + + + + + + + + + onClick="indexRowCheckBoxToggle(this);"> + + + + + + + + +
번호작업
+ "checkbox_uid_{$row['uid']}", "name" => "batchjob_uids[]", "value" => $row['uid'], "class" => "batchjobuids_checkboxs"]); ?> + "_self"]) ?> + "btn btn-sm btn-danger btn-circle", "target" => "_self"]) ?>
+ + +
+
+ +
+
+include('templates/admin/footer'); ?> +endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/board/insert.php b/app/Views/admin/board/insert.php new file mode 100644 index 0000000..537bb58 --- /dev/null +++ b/app/Views/admin/board/insert.php @@ -0,0 +1,31 @@ +extend('layouts/admin') ?> +section('content') ?> +include('templates/admin/header'); ?> + + + + + + + + + + + +
+ + + + +
"btn btn-outline btn-primary")); ?>
+ +getFlashdata('error')) : ?>getFlashdata('error') ?> + + +endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/board/update.php b/app/Views/admin/board/update.php new file mode 100644 index 0000000..f187aee --- /dev/null +++ b/app/Views/admin/board/update.php @@ -0,0 +1,32 @@ +extend('layouts/admin') ?> +section('content') ?> +include('templates/admin/header'); ?> + + + + + + + + + + + +
+ + + $field : old($field), $fieldFormOptions) ?> + +
"btn btn-outline btn-primary")); ?>
+ +getFlashdata('error')) : ?>getFlashdata('error') ?> + + +include('templates/admin/footer'); ?> +endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/board/view.php b/app/Views/admin/board/view.php new file mode 100644 index 0000000..2e2d8f7 --- /dev/null +++ b/app/Views/admin/board/view.php @@ -0,0 +1,15 @@ +extend('layouts/admin') ?> +section('content') ?> +include('templates/admin/header'); ?> + + + + + + + +
+ +
+include('templates/admin/footer'); ?> +endSection() ?> \ No newline at end of file diff --git a/app/Views/layouts/admin/left_menu.php b/app/Views/layouts/admin/left_menu.php index 9c78b96..7a0f090 100644 --- a/app/Views/layouts/admin/left_menu.php +++ b/app/Views/layouts/admin/left_menu.php @@ -5,6 +5,7 @@
include($layout['path'] . '/left_menu/base'); ?> - include($layout['path'] . '/left_menu/hpilo'); ?> + include($layout['path'] . '/left_menu/board'); ?> + include($layout['path'] . '/left_menu/hpilo'); ?>
\ No newline at end of file diff --git a/app/Views/layouts/admin/left_menu/board.php b/app/Views/layouts/admin/left_menu/board.php new file mode 100644 index 0000000..95df6ed --- /dev/null +++ b/app/Views/layouts/admin/left_menu/board.php @@ -0,0 +1,3 @@ +
+

게시판 관리

+
\ No newline at end of file diff --git a/app/Views/layouts/admin/top_menu.php b/app/Views/layouts/admin/top_menu.php index 6e3d8ac..fda71bd 100644 --- a/app/Views/layouts/admin/top_menu.php +++ b/app/Views/layouts/admin/top_menu.php @@ -1,7 +1,7 @@