From 65dff253d8d544c07e19a02d12d4c68ca09f4986 Mon Sep 17 00:00:00 2001 From: "choi.jh" Date: Thu, 6 Nov 2025 16:51:52 +0900 Subject: [PATCH] trafficmonitor init...2 --- app/Config/Routes.php | 43 +++--- app/Config/Services.php | 11 +- app/Controllers/Admin/AdminController.php | 4 + app/Controllers/Admin/UserController.php | 13 +- app/Controllers/Auth/AuthController.php | 49 ++++--- app/Controllers/Auth/GoogleController.php | 7 +- app/Controllers/Auth/LocalController.php | 6 +- app/Controllers/CommonController.php | 163 ++++++++++++---------- app/DTOs/Auth/AuthDTO.php | 13 ++ app/DTOs/Auth/GoogleDTO.php | 25 ++++ app/DTOs/Auth/LocalDTO.php | 27 ++++ app/DTOs/AuthDTO.php | 26 ---- app/DTOs/CertificationDTO.php | 33 +++++ app/DTOs/UserDTO.php | 16 ++- app/Forms/CommonForm.php | 132 +----------------- app/Forms/TrafficForm.php | 21 --- app/Forms/UserForm.php | 13 -- app/Helpers/AuthHelper.php | 3 - app/Helpers/CommonHelper.php | 44 ++---- app/Helpers/UserHelper.php | 3 - app/Helpers/create_form_helper.php | 38 ----- app/Services/Auth/AuthService.php | 21 ++- app/Services/Auth/GoogleService.php | 39 ++++-- app/Services/Auth/LocalService.php | 51 ++++--- app/Services/CommonService.php | 20 ++- app/Services/TrafficService.php | 34 +++-- app/Services/UserService.php | 161 ++++++++++----------- app/Views/admin/user/create_form.php | 24 ++++ app/Views/admin/user/download.php | 21 +++ app/Views/admin/user/index.php | 70 ++++++++++ app/Views/admin/user/modify_form.php | 24 ++++ app/Views/admin/user/view.php | 17 +++ 32 files changed, 615 insertions(+), 557 deletions(-) create mode 100644 app/DTOs/Auth/AuthDTO.php create mode 100644 app/DTOs/Auth/GoogleDTO.php create mode 100644 app/DTOs/Auth/LocalDTO.php delete mode 100644 app/DTOs/AuthDTO.php create mode 100644 app/DTOs/CertificationDTO.php delete mode 100644 app/Helpers/create_form_helper.php create mode 100644 app/Views/admin/user/create_form.php create mode 100644 app/Views/admin/user/download.php create mode 100644 app/Views/admin/user/index.php create mode 100644 app/Views/admin/user/modify_form.php create mode 100644 app/Views/admin/user/view.php diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 7e85736..27458ef 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -28,32 +28,29 @@ $routes->group('', ['namespace' => 'App\Controllers'], function ($routes) { $routes->group('admin', ['namespace' => 'App\Controllers\Admin', 'filter' => 'authFilter:manager'], function ($routes) { $routes->get('/', 'Home::index'); $routes->group('user', ['namespace' => 'App\Controllers\Admin'], function ($routes) { - $routes->get('/', 'UserController::index', ['filter' => 'authFilter:master']); - $routes->get('create', 'UserController::create_form', ['filter' => 'authFilter:master']); - $routes->post('create', 'UserController::create', ['filter' => 'authFilter:master']); - $routes->get('modify/(:num)', 'UserController::modify_form/$1', ['filter' => 'authFilter:master']); - $routes->post('modify/(:num)', 'UserController::modify/$1', ['filter' => 'authFilter:master']); - $routes->get('view/(:num)', 'UserController::view/$1', ['filter' => 'authFilter:manager']); + $routes->get('/', 'UserController::index'); + $routes->get('create', 'UserController::create_form'); + $routes->post('create', 'UserController::create'); + $routes->get('modify/(:num)', 'UserController::modify_form/$1'); + $routes->post('modify/(:num)', 'UserController::modify/$1'); + $routes->get('view/(:num)', 'UserController::view/$1'); $routes->get('delete/(:num)', 'UserController::delete/$1', ['filter' => 'authFilter:master']); $routes->get('toggle/(:num)/(:any)', 'UserController::toggle/$1/$2', ['filter' => 'authFilter:master']); $routes->post('batchjob', 'UserController::batchjob', ['filter' => 'authFilter:master']); $routes->post('batchjob_delete', 'UserController::batchjob_delete', ['filter' => 'authFilter:master']); - $routes->get('download/(:alpha)', 'UserController::download/$1', ['filter' => 'authFilter:master']); - $routes->get('profile/(:num)', 'UserController::profile_form/$1', ['filter' => 'authFilter:manager']); - $routes->post('profile/(:num)', 'UserController::profile/$1', ['filter' => 'authFilter:manager']); - - $routes->group('traffic', ['namespace' => 'App\Controllers\Admin'], function ($routes) { - $routes->get('/', 'TrafficController::index'); - $routes->get('create', 'TrafficController::create_form'); - $routes->post('create', 'TrafficController::create'); - $routes->get('modify/(:num)', 'TrafficController::modify_form/$1'); - $routes->post('modify/(:num)', 'TrafficController::modify/$1'); - $routes->get('view/(:num)', 'TrafficController::view/$1'); - $routes->get('delete/(:num)', 'TrafficController::delete/$1'); - $routes->get('toggle/(:num)/(:any)', 'TrafficController::toggle/$1/$2'); - $routes->post('batchjob', 'TrafficController::batchjob'); - $routes->post('batchjob_delete', 'TrafficController::batchjob_delete'); - $routes->get('download/(:alpha)', 'TrafficController::download/$1'); - }); + $routes->get('download/(:alpha)', 'UserController::download/$1'); + }); + $routes->group('traffic', ['namespace' => 'App\Controllers\Admin'], function ($routes) { + $routes->get('/', 'TrafficController::index'); + $routes->get('create', 'TrafficController::create_form'); + $routes->post('create', 'TrafficController::create'); + $routes->get('modify/(:num)', 'TrafficController::modify_form/$1'); + $routes->post('modify/(:num)', 'TrafficController::modify/$1'); + $routes->get('view/(:num)', 'TrafficController::view/$1'); + $routes->get('delete/(:num)', 'TrafficController::delete/$1'); + $routes->get('toggle/(:num)/(:any)', 'TrafficController::toggle/$1/$2'); + $routes->post('batchjob', 'TrafficController::batchjob'); + $routes->post('batchjob_delete', 'TrafficController::batchjob_delete'); + $routes->get('download/(:alpha)', 'TrafficController::download/$1'); }); }); diff --git a/app/Config/Services.php b/app/Config/Services.php index 38a520d..f7bd1ae 100644 --- a/app/Config/Services.php +++ b/app/Config/Services.php @@ -40,8 +40,7 @@ class Services extends BaseService return static::getSharedInstance(__FUNCTION__); } else { return new LocalService( - new \App\Models\UserModel(), - new \App\Forms\Auth\LocalForm() + new \App\Models\UserModel() ); } } @@ -52,8 +51,7 @@ class Services extends BaseService return static::getSharedInstance(__FUNCTION__); } else { return new LocalService( - new \App\Models\UserModel(), - new \App\Forms\Auth\LocalForm() + new \App\Models\UserModel() ); } } @@ -64,7 +62,6 @@ class Services extends BaseService } return new GoogleService( new \App\Models\USerModel(), - new \App\Forms\Auth\GoogleForm(), new \App\Libraries\MySocket\GoogleSocket\CURL() ); } @@ -75,8 +72,7 @@ class Services extends BaseService return static::getSharedInstance(__FUNCTION__); } return new UserService( - new \App\Models\USerModel(), - new \App\Forms\UserForm() + new \App\Models\USerModel() ); } @@ -87,7 +83,6 @@ class Services extends BaseService } return new TrafficService( new \App\Models\TrafficModel(), - new \App\Forms\TrafficForm() ); } } diff --git a/app/Controllers/Admin/AdminController.php b/app/Controllers/Admin/AdminController.php index 426c418..b9213de 100644 --- a/app/Controllers/Admin/AdminController.php +++ b/app/Controllers/Admin/AdminController.php @@ -15,4 +15,8 @@ abstract class AdminController extends CommonController parent::initController($request, $response, $logger); $this->addActionPaths(self::PATH); } + final protected function getLayout(): string + { + return self::PATH; + } } diff --git a/app/Controllers/Admin/UserController.php b/app/Controllers/Admin/UserController.php index 71ee2e1..f9e7a66 100644 --- a/app/Controllers/Admin/UserController.php +++ b/app/Controllers/Admin/UserController.php @@ -23,9 +23,9 @@ class UserController extends AdminController { parent::initController($request, $response, $logger); if ($this->service === null) { - $this->service = service('localauth'); + $this->service = service('userservice'); } - $this->addActionPaths(self::PATH); + $this->addActionPaths($this::PATH); } protected function getFormRule(string $action, string $field, string $rule): array { @@ -37,13 +37,10 @@ class UserController extends AdminController return parent::getFormRule($action, $field, $rule); } //Index,FieldForm관련. - protected function create_process(string $action, array $viewDatas): string|RedirectResponse + protected function create_process(): UserEntity { + //요청 데이터를 DTO 객체로 변환 $dto = new UserDTO($this->request->getPost()); - $this->doValidation($action); - $entity = $this->service->create($dto); - return redirect() - ->route('admin/user/view', [$entity->getPK()]) - ->with('message', "{$entity->getTitle()} 계정이 등록되었습니다."); + return $this->service->create($dto); } } diff --git a/app/Controllers/Auth/AuthController.php b/app/Controllers/Auth/AuthController.php index 76f4197..7a66adc 100644 --- a/app/Controllers/Auth/AuthController.php +++ b/app/Controllers/Auth/AuthController.php @@ -8,6 +8,7 @@ use App\Entities\UserEntity; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; +use CodeIgniter\Validation\Exceptions\ValidationException; use Psr\Log\LoggerInterface; abstract class AuthController extends CommonController @@ -20,35 +21,44 @@ abstract class AuthController extends CommonController } abstract protected function login_process(): UserEntity; abstract protected function logout_process(): void; + //로그인화면 - public function login_form_process(array $viewDatas = []): array - { - return $viewDatas; - } - public function login_form(): string|RedirectResponse + public function login_form_process(): void {} + final public function login_form(): string|RedirectResponse { + $action = __FUNCTION__; try { //초기화 - $action = __FUNCTION__; - $viewDatas = $this->action_init_process($action); - $viewDatas = $this->login_form_process($viewDatas); - return $this->action_post_process($action, $viewDatas); + $this->action_init_process($action); + $this->login_form_process(); + $this->action_render_process($action); + // dd($this->getViewDatas()); } catch (\Exception $e) { - $viewDatas[self::ACTION_RESULT] = 'error'; - $viewDatas[self::ACTION_MESSAGE] = $e->getMessage(); - return $this->action_post_process($action, $viewDatas); + $this->addViewDatas(self::ACTION_RESULT, 'error'); + $this->addViewDatas(self::ACTION_MESSAGE, $e->getMessage()); + //오류발생시 리디렉션 대신 폼 뷰를 다시 렌더링하도록 action_view_process 호출 } + return $this->action_result_process( + $this->getActionPaths(), + $action, + $this->getViewDatas() + ); } - //로그인처리 - public function login(): RedirectResponse + final public function login(): RedirectResponse { + $action = __FUNCTION__; try { - $action = __FUNCTION__; - $viewDatas = $this->action_init_process($action); + $this->action_init_process($action); $this->login_process(); - return redirect()->to($this->authService->popPreviousUrl())->with('success', '로그인이 완료되었습니다.'); + $redirect_url = $this->authService->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); + return redirect()->to($redirect_url)->with('success', MESSAGES['LOGIN']); + } catch (ValidationException $e) { + // 검증 실패 시 폼으로 돌아가서 오류 메시지 표시 + log_message('error', $e->getMessage()); + return redirect()->back()->withInput()->with('errors', $e->getMessage()); } catch (\Exception $e) { + log_message('error', $e->getMessage()); return redirect()->back()->withInput()->with('error', $e->getMessage()); // return redirect()->to($this->getMyAuth()->popPreviousUrl())->with('error', $e->getMessage()); } @@ -59,10 +69,11 @@ abstract class AuthController extends CommonController try { $this->logout_process(); // 홈페이지로 리다이렉트 - return redirect()->route('/')->with('error', MESSAGES['LOGOUT']); + $redirect_url = $this->authService->popPreviousUrl() ?? "/"; + return redirect()->route($redirect_url)->with('error', MESSAGES['LOGOUT']); } catch (\Exception $e) { log_message("error", $e->getMessage()); - return redirect()->back()->with('error', "로그아웃 중 오류가 발생했습니다."); + return redirect()->back()->withInput()->with('error', "로그아웃 중 오류가 발생했습니다."); } } } diff --git a/app/Controllers/Auth/GoogleController.php b/app/Controllers/Auth/GoogleController.php index ade5554..118d126 100644 --- a/app/Controllers/Auth/GoogleController.php +++ b/app/Controllers/Auth/GoogleController.php @@ -22,17 +22,16 @@ class GoogleController extends AuthController } $this->addActionPaths(self::PATH); } - public function login_form_process(array $viewDatas = []): array + public function login_form_process(): void { //구글 로그인 BUTTON용 - $viewDatas['SNSButton'] = anchor($this->service->socket->createAuthUrl(), ICONS['GOOGLE'] . 'Google 로그인', ["class" => "btn-google"]); - return $viewDatas; + $this->addViewDatas('SNSButton', anchor($this->service->socket->createAuthUrl(), ICONS['GOOGLE'] . 'Google 로그인', ["class" => "btn-google"])); } //로그인처리 protected function login_process(): UserEntity { - $formDatas = $this->doValidation(__FUNCTION__); + $formDatas = $this->doValidation($this->getViewDatas('action')); if (!array_key_exists('access_code', $formDatas) || !$formDatas['access_code']) { throw new \Exception("구글 로그인 실패"); } diff --git a/app/Controllers/Auth/LocalController.php b/app/Controllers/Auth/LocalController.php index 4721503..d1c368c 100644 --- a/app/Controllers/Auth/LocalController.php +++ b/app/Controllers/Auth/LocalController.php @@ -2,6 +2,7 @@ namespace App\Controllers\Auth; +use App\DTOs\Auth\LocalDTO; use App\Entities\UserEntity; use App\Services\Auth\LocalService; use CodeIgniter\HTTP\RequestInterface; @@ -26,8 +27,9 @@ class LocalController extends AuthController //로그인처리 protected function login_process(): UserEntity { - $formDatas = $this->doValidation(__FUNCTION__); - return $this->service->login($formDatas); + //요청 데이터를 DTO 객체로 변환 + $dto = new LocalDTO($this->request->getPost()); + return $this->service->login($dto); } protected function logout_process(): void { diff --git a/app/Controllers/CommonController.php b/app/Controllers/CommonController.php index d98def7..c4f55f7 100644 --- a/app/Controllers/CommonController.php +++ b/app/Controllers/CommonController.php @@ -3,14 +3,13 @@ namespace App\Controllers; use App\Controllers\BaseController; -use App\DTOs\AuthDTO; -use App\Services\CommonService; +use App\DTOs\CertificationDTO; use App\Traits\LogTrait; use CodeIgniter\HTTP\DownloadResponse; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use CodeIgniter\Validation\Validation; +use CodeIgniter\Validation\Exceptions\ValidationException; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Reader\Html; use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf; @@ -19,30 +18,45 @@ use Psr\Log\LoggerInterface; abstract class CommonController extends BaseController { use LogTrait; - protected const ACTION_PATH = "action_path"; - protected const ACTION_VIEW_FILE = "action_view_file"; - protected const ACTION_RESULT = "action_result"; - protected const ACTION_MESSAGE = "action_message"; + const ACTION_RESULT = "action_result"; + const ACTION_MESSAGE = "action_message"; private array $_action_paths = []; - protected $authService = null; + private array $_viewDatas = []; protected $service = null; - protected $myAuth = null; + protected $authService = null; + protected $myCertification = null; public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { parent::initController($request, $response, $logger); //로그인관련 $this->authService = service('myauth'); - $this->myAuth = AuthDTO::fromByAuthService($this->authService); + $this->myCertification = CertificationDTO::fromByAuthService($this->authService); + } + protected function getLayout(): string + { + return 'empty'; } final public function addActionPaths(string $path) { $this->_action_paths[] = $path; } - final public function getActionPaths(): array + final public function getActionPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string { - return $this->_action_paths; + return $isArray ? $this->_action_paths : implode($delimeter, $this->_action_paths); } - final protected function doValidation(string $action): array + final public function addViewDatas(string $key, mixed $value) + { + $this->_viewDatas[$key] = $value; + } + final public function getViewDatas(?string $key = null): mixed + { + if ($key === null) { + return $this->_viewDatas; + } + return $this->_viewDatas[$key] ?? null; + } + //공통 필수기능 + protected function doValidation(string $action): array { $dynamicRules = []; foreach ($this->service->getFormRules($action) as $field => $rule) { @@ -58,7 +72,6 @@ abstract class CommonController extends BaseController } return $this->validator->getValidated(); } - //공통 필수기능 protected function getFormRule(string $action, string $field, string $rule): array { switch ($field) { @@ -67,85 +80,83 @@ abstract class CommonController extends BaseController } return array($field, $rule); } - protected function action_init_process(string $action, array $viewDatas = []): array + protected function action_init_process(string $action): void { - $viewDatas['action'] = $action; - $viewDatas[self::ACTION_PATH] = $this->getActionPaths(); - $viewDatas[self::ACTION_VIEW_FILE] = $this->request->getVar('ActionTemplate') ?? $viewDatas['action']; - $viewDatas['formFields'] = $this->service->getFormFields(); - $viewDatas['formFilters'] = $this->service->getFormFilters(); - $viewDatas['formRules'] = $this->service->getFormRules($viewDatas['action']); - $viewDatas['formOptions'] = $this->service->getFormOptions($viewDatas['action']); - return $viewDatas; + $this->addViewDatas('action', $action); + $this->addViewDatas('myCertification', $this->myCertification); + $this->addViewDatas('layout', $this->getLayout()); + $this->addViewDatas('serviceForm', $this->service->getFormService()); + $this->addViewDatas('formFields', $this->service->getFormFields()); + $this->addViewDatas('formFilters', $this->service->getFormFilters()); + $this->addViewDatas('formRules', $this->service->getFormRules($action)); + $this->addViewDatas('formOptions', $this->service->getFormOptions($action)); } - protected function action_post_process(string $action, array $viewDatas): string|RedirectResponse + protected function action_render_process(string $action): void + { + $this->addViewDatas('helper', $this->service->getHelper($action, $this->getViewDatas())); + } + protected function action_result_process(array $view_paths, string $view_file, array $viewDatas): string { - $view_paths = array_key_exists(self::ACTION_PATH, $viewDatas) ? $viewDatas[self::ACTION_PATH] : $this->getActionPaths(); $lastest_path = array_pop($view_paths); //paths는 마지막을 뺀 앞단까지만 남음 - switch ($action) { - case 'create_form': - case 'modify_form': - case 'login_form': - // ✅ 중간 안내 화면으로 - // return view('posts/success_redirect', [ - // 'message' => '게시글이 성공적으로 등록되었습니다.', - // 'redirectUrl' => route_to('posts_list') - // ]); - // 중요한 작업 (결제 완료, 오류 등) → “로딩 페이지(View)”로 안내 후 JS redirect - $full_path = implode(DIRECTORY_SEPARATOR, [ - ...$view_paths, - $this->request->getVar('ActionTemplate') ?? $lastest_path, - array_key_exists(self::ACTION_VIEW_FILE, $viewDatas) ? $viewDatas[self::ACTION_VIEW_FILE] : $action - ]); - $view_datas = [ - 'control' => $viewDatas, - 'forms' => ['attributes' => ['method' => "post",], 'hiddens' => []], - ]; - helper(['form', __FUNCTION__]); - $result = view($full_path, ['viewDatas' => $view_datas]); - break; - default: - // ✅ Flashdata로 성공 메시지 저장 - // 일반 CRUD (create/update/delete) → Flashdata + redirect() - $message = array_key_exists(self::ACTION_MESSAGE, $viewDatas) ?: static::class . "/{$action}이 완료되었습니다."; - session()->setFlashdata($viewDatas[self::ACTION_RESULT], $message); - $result = redirect()->route(implode(DIRECTORY_SEPARATOR, $view_paths))->with('message', $message); - break; - } - return $result; + // ✅ 중간 안내 화면으로 + // return view('posts/success_redirect', [ + // 'message' => '게시글이 성공적으로 등록되었습니다.', + // 'redirectUrl' => route_to('posts_list') + // ]); + // 중요한 작업 (결제 완료, 오류 등) → “로딩 페이지(View)”로 안내 후 JS redirect + $full_path = implode(DIRECTORY_SEPARATOR, [ + ...$view_paths, + $this->request->getVar('ActionTemplate') ?? $lastest_path, + $view_file + ]); + $view_datas = [ + 'control' => $viewDatas, + 'forms' => ['attributes' => ['method' => "post",], 'hiddens' => []], + ]; + helper(['form', __FUNCTION__]); + return view($full_path, ['viewDatas' => $view_datas]); } - protected function create_form_process(array $viewDatas): array - { - return $viewDatas; - } - public function create_form(): string|RedirectResponse + protected function create_form_process(): void {} + final public function create_form(): string|RedirectResponse { + $action = __FUNCTION__; try { //초기화 - $action = __FUNCTION__; - $viewDatas = $this->action_init_process($action); - $viewDatas = $this->create_form_process($viewDatas); - return $this->action_post_process($action, $viewDatas); + $this->action_init_process($action); + $this->create_form_process(); + $this->action_render_process($action); + // dd($this->getViewDatas()); } catch (\Exception $e) { - $viewDatas[self::ACTION_RESULT] = 'error'; - $viewDatas[self::ACTION_MESSAGE] = $e->getMessage(); - //리디렉션 대신 폼 뷰를 다시 렌더링하도록 form_post_process 호출 - return $this->action_post_process($action, $viewDatas); + log_message('error', $e->getMessage()); + $this->addViewDatas(self::ACTION_RESULT, 'error'); + $this->addViewDatas(self::ACTION_MESSAGE, $e->getMessage()); + //오류발생시 리디렉션 대신 폼 뷰를 다시 렌더링하도록 action_view_process 호출 } + return $this->action_result_process( + $this->getActionPaths(), + $action, + $this->getViewDatas() + ); } - protected function create_process(string $action, array $viewDatas): string|RedirectResponse + protected function create_process(): mixed { - $this->doValidation($action); - return $this->action_post_process($action, $viewDatas); + return $this->service->create(); } - public function create(): string|RedirectResponse + final public function create(): RedirectResponse { + $action = __FUNCTION__; try { //초기화 - $action = __FUNCTION__; - $viewDatas = $this->action_init_process($action); - return $this->create_process($action, $viewDatas); + $this->action_init_process($action); + $this->create_process(); + $redirect_url = $this->authService->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); + return redirect()->to($redirect_url)->with('success', static::class . "/{$action}이 완료되었습니다."); + } catch (ValidationException $e) { + // 검증 실패 시 폼으로 돌아가서 오류 메시지 표시 + log_message('error', $e->getMessage()); + return redirect()->back()->withInput()->with('errors', $e->getMessage()); } catch (\Exception $e) { + log_message('error', $e->getMessage()); return redirect()->back()->withInput()->with('error', $e->getMessage()); } } diff --git a/app/DTOs/Auth/AuthDTO.php b/app/DTOs/Auth/AuthDTO.php new file mode 100644 index 0000000..dc318c8 --- /dev/null +++ b/app/DTOs/Auth/AuthDTO.php @@ -0,0 +1,13 @@ + $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + public function toArray(): array + { + return [ + 'access_code' => $this->access_code, + ]; + } +} diff --git a/app/DTOs/Auth/LocalDTO.php b/app/DTOs/Auth/LocalDTO.php new file mode 100644 index 0000000..f5db587 --- /dev/null +++ b/app/DTOs/Auth/LocalDTO.php @@ -0,0 +1,27 @@ + $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + public function toArray(): array + { + return [ + 'id' => $this->id, + 'passwd' => $this->passwd, + ]; + } +} diff --git a/app/DTOs/AuthDTO.php b/app/DTOs/AuthDTO.php deleted file mode 100644 index 639cb21..0000000 --- a/app/DTOs/AuthDTO.php +++ /dev/null @@ -1,26 +0,0 @@ -isLoggedIn(), - $service->getUID(), - $service->getName(), - $service->getRole(), - ); - } -} diff --git a/app/DTOs/CertificationDTO.php b/app/DTOs/CertificationDTO.php new file mode 100644 index 0000000..e39e40c --- /dev/null +++ b/app/DTOs/CertificationDTO.php @@ -0,0 +1,33 @@ + $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + public static function fromByAuthService(AuthService $service): self + { + return new self( + [ + 'isLogin' => $service->isLoggedIn(), + 'uid' => $service->getUID(), + 'name' => $service->getName(), + 'role' => $service->getRole(), + ] + ); + } +} diff --git a/app/DTOs/UserDTO.php b/app/DTOs/UserDTO.php index 3545d5b..0a37ab0 100644 --- a/app/DTOs/UserDTO.php +++ b/app/DTOs/UserDTO.php @@ -5,24 +5,34 @@ namespace App\DTOs; class UserDTO extends CommonDTO { public ?int $uid = null; - public ?string $name = null; + public ?string $id = null; + public ?string $passwd = null; + public ?string $passwd_confirm = null; + public ?string $email = null; + public ?string $mobile = null; public ?string $role = null; + public ?string $status = null; public function __construct(array $datas = []) { + parent::__construct(); foreach ($datas as $key => $value) { if (property_exists($this, $key)) { $this->{$key} = $value; } } } - public function toArray(): array { return [ 'uid' => $this->uid, - 'title' => $this->name, + 'id' => $this->id, + 'passwd' => $this->passwd, + 'passwd_confirm' => $this->passwd_confirm, + 'email' => $this->email, + 'mobile' => $this->mobile, 'role' => $this->role, + 'status' => $this->status, ]; } } diff --git a/app/Forms/CommonForm.php b/app/Forms/CommonForm.php index 667e8fa..920cf7f 100644 --- a/app/Forms/CommonForm.php +++ b/app/Forms/CommonForm.php @@ -28,30 +28,13 @@ abstract class CommonForm } return $rules; } - final public function getFormOptions(string $class_path, string $action, array $fields, array $options = []): array + final public function getFormOptions(string $action, array $fields, array $options = []): array { foreach ($fields as $field) { - $options = $this->getFormOption($class_path, $action, $field, $options); + $options = $this->getFormOption($action, $field, $options); } return $options; } - final public function form_dropdown_common(string $field, mixed $value, array $viewDatas, array $extras = [], array $attributes = [], bool $isAll = false): string - { - // 필터 옵션이 없으면 빈 배열로 초기화 - if (!array_key_exists($field, $viewDatas['control']['formOptions'])) { - return ""; // 필터 옵션이 없으면 빈 문자열 반환 - } - $extra = ""; - foreach ($extras as $extra_tag => $extra_value) { - $extra .= sprintf(" %s=\"%s\"", $extra_tag, $extra_value); - } - // $formOptions는 필터 옵션 배열로, key는 필터 엔티티의 PK, value는 필터 엔티티 객체 - $html = sprintf("'; - return $html; - } //필수함수 public function getFormFilters(): array { @@ -119,7 +102,7 @@ abstract class CommonForm } return $rules; } - public function getFormOption(string $class_path, string $action, string $field, array $options = []): array + public function getFormOption(string $action, string $field, array $options = []): array { switch ($field) { case 'user_uid': @@ -131,118 +114,13 @@ abstract class CommonForm $option = $clientService->getEntities(); break; default: - $option = lang($class_path . "." . strtoupper($field)); + $option = lang($this->getAttribute('class_path') . "." . strtoupper($field)); break; } if (!is_array($option)) { - throw new \Exception(__FUNCTION__ . "에서 {$field}의 options 값들이 배열이 아닙니다.\n" . var_export($option, true)); + throw new \Exception(static::class . DIRECTORY_SEPARATOR . __FUNCTION__ . "에서 {$field}의 options 값들이 배열이 아닙니다.\n" . var_export($option, true)); } $options[$field] = $option; return $options; } - protected function form_dropdown_common_process(string $field, mixed $value, array $viewDatas, array $extras = [], array $attributes = [], bool $isAll = false): string - { - $html = ""; - switch ($field) { - default: - foreach ($viewDatas['control']['formOptions'][$field] as $option_key => $option_value) { - $isSelected = $option_key == $value ? ' selected' : ''; - $isDisabled = ""; - $attribute = ""; - $label = ""; - if ($option_value instanceof CommonEntity) { - if ($option_key != $value && $option_value->getStatus() != $option_value::DEFAULT_STATUS && !$isAll) { - continue; - } - foreach ($attributes as $attribute_name => $attribute_value) { - $attribute .= sprintf(" %s=\"%s\"", $attribute_name, $option_value->$attribute_value); - } - $label = $option_value->getCustomTitle(); - } else { - $label = $option_value; - } - $html .= sprintf("", $option_key, $isSelected, $isDisabled, $attribute, $label); - } - break; - } - return $html; - } - public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string - { - switch ($field) { - case 'email': - $form = form_input($field, $value ?? "", [ - "class" => "form-control", - 'style' => 'width:100%;', - "placeholder" => "예)test@example.com", - ...$extras - ]); - break; - case 'mobile': - case 'phone': - $form = form_input($field, $value ?? "", [ - "class" => "form-control", - 'style' => 'width:100%;', - "placeholder" => "예)010-0010-0010", - ...$extras - ]); - break; - case 'role': - if (!is_array($viewDatas['control']['formOptions'][$field])) { - throw new \Exception(__METHOD__ . "에서 {$field}의 field_options가 array형태가 아닙니다."); - } - // create, modify, create_form, modify_form일때 checkbox로 표시 - if (in_array($viewDatas['control']['action'], ['create_form', 'modify_form'])) { - $forms = []; - foreach ($viewDatas['control']['formOptions'][$field] as $key => $label) { - if ($key !== '') { // 빈값은 제외 - $values = is_array($value) ? $value : explode(DEFAULTS["DELIMITER_ROLE"], $value); - //form_check에는 "class" => "form-control" 쓰면 않되거나 form-check를 써야함 - $forms[] = form_checkbox("{$field}[]", $key, in_array($key, $values), $extras) . $label; - } - } - $form = implode(" ", $forms); - } else { - $form = form_dropdown($field, $value, $viewDatas, $extras); - } - break; - case 'issue_at': - case 'expired_at': - case 'billing_at': - case 'start_at': - case 'end_at': - case 'updated_at': - case 'created_at': - case 'deleted_at': - $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' calender' : 'calender'; - $form = form_input($field, $value ?? "", $extras); - break; - case 'description': - case 'content': - case 'detail': - case 'history': - $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' tinymce' : 'tinymce'; - $form = form_textarea($field, html_entity_decode($value ?? "", ENT_QUOTES, 'UTF-8'), [ - "class" => "form-control", - 'style' => 'width:100%;', - ...$extras - ]); - break; - default: - if (in_array($field, $viewDatas['control']['formFilters'])) { - if (str_contains($field, "_uid")) { - $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' select-field' : 'select-field'; - } - $form = $this->form_dropdown_common($field, $value, $viewDatas, $extras); - } else { - $form = form_input($field, $value ?? "", [ - "class" => "form-control", - 'style' => 'width:100%;', - ...$extras - ]); - } - break; - } - return $form; - } } diff --git a/app/Forms/TrafficForm.php b/app/Forms/TrafficForm.php index 26f730e..e595fd4 100644 --- a/app/Forms/TrafficForm.php +++ b/app/Forms/TrafficForm.php @@ -105,25 +105,4 @@ class TrafficForm extends CommonForm $options[$field] = $option; return $options; } - public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string - { - switch ($field) { - case 'site': - $extras['onChange'] = "$('select[name=\'clientinfo_uid\']').select2('open')"; - $form = $this->form_dropdown_common($field, $value, $viewDatas, $extras); - break; - case 'serverinfo_uid': - $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' select-field' : 'select-field'; - $attributes = ['data-price' => 'price']; - $form = $this->form_dropdown_common($field, $value, $viewDatas, $extras, $attributes); - break; - case 'amount': - $form = form_input($field, 0, ["readonly" => "readonly", ...$extras]); - break; - default: - $form = parent::getFieldForm($field, $value, $viewDatas, $extras); - break; - } - return $form; - } } diff --git a/app/Forms/UserForm.php b/app/Forms/UserForm.php index a229cea..c146a89 100644 --- a/app/Forms/UserForm.php +++ b/app/Forms/UserForm.php @@ -75,17 +75,4 @@ class UserForm extends CommonForm } return $rules; } - public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string - { - switch ($field) { - case 'passwd': - case 'confirmpassword': - $form = form_password($field, "", [...$extras]); - break; - default: - $form = parent::getFieldForm($field, $value, $viewDatas, $extras); - break; - } - return $form; - } // } diff --git a/app/Helpers/AuthHelper.php b/app/Helpers/AuthHelper.php index 56be0bc..e12d62d 100644 --- a/app/Helpers/AuthHelper.php +++ b/app/Helpers/AuthHelper.php @@ -2,14 +2,11 @@ namespace App\Helpers; -use App\Models\UserModel; - class AuthHelper extends CommonHelper { public function __construct() { parent::__construct(); - $this->setTitleField(UserModel::TITLE); } public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string { diff --git a/app/Helpers/CommonHelper.php b/app/Helpers/CommonHelper.php index 7c006a9..7bdaee4 100644 --- a/app/Helpers/CommonHelper.php +++ b/app/Helpers/CommonHelper.php @@ -4,44 +4,24 @@ namespace App\Helpers; use App\Entities\CommonEntity; use App\Traits\UtilTrait; +use RuntimeException; class CommonHelper { use UtilTrait; - private $_myAuth = null; - private $_viewDatas = []; - private $_titleField = ""; + private array $_attributes = []; protected function __construct() {} - final protected function getMyAuth(): mixed + final public function setAttributes(array $attributes): void { - if (!$this->_myAuth) { - $this->_myAuth = service('myauth'); + $this->_attributes = $attributes; + } + final public function getAttribute(string $key): string + { + if (!array_key_exists($key, $this->_attributes)) { + throw new RuntimeException(__METHOD__ . "에서 오류발생: {$key}에 해당하는 속성이 정의되지 않았습니다."); } - return $this->_myAuth; + return $this->_attributes[$key]; } - final public function setTitleField(string $field): void - { - $this->_titleField = $field; - } - final public function getTitleField(): string - { - if (!$this->_titleField) { - throw new \Exception("titleField가 지정되지 않았습니다."); - } - return $this->_titleField; - } - final public function setViewDatas(array $viewDatas): void - { - $this->_viewDatas = $viewDatas; - } - final public function getViewDatas(string $key) - { - if (!array_key_exists($key, $this->_viewDatas)) { - throw new \Exception("{$key}에 해당하는 ViewData가 존재하지 않습니다."); - } - return $this->_viewDatas[$key]; - } - final public function form_dropdown_common(string $field, mixed $value, array $viewDatas, array $extras = [], array $attributes = [], bool $isAll = false): string { // 필터 옵션이 없으면 빈 배열로 초기화 @@ -54,7 +34,7 @@ class CommonHelper } // $formOptions는 필터 옵션 배열로, key는 필터 엔티티의 PK, value는 필터 엔티티 객체 $html = sprintf("'; return $html; @@ -93,7 +73,7 @@ class CommonHelper default: // required가 있으면 class 추가 $extras = (strpos($viewDatas['control']['formRules'][$field], 'required') !== false) ? ["class" => "text-danger", "required" => "", ...$extras] : $extras; - $label = form_label($label, $field, ['class' => 'form-label-sm', ...$extras]); + $label = $label ?: form_label(lang("{$this->getAttribute('class_path')}.label.{$field}"), $field, ['class' => 'form-label-sm', ...$extras]); break; } return $label; diff --git a/app/Helpers/UserHelper.php b/app/Helpers/UserHelper.php index e669aa1..9604921 100644 --- a/app/Helpers/UserHelper.php +++ b/app/Helpers/UserHelper.php @@ -2,14 +2,11 @@ namespace App\Helpers; -use App\Models\UserModel; - class UserHelper extends CommonHelper { public function __construct() { parent::__construct(); - $this->setTitleField(UserModel::TITLE); } public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string { diff --git a/app/Helpers/create_form_helper.php b/app/Helpers/create_form_helper.php deleted file mode 100644 index 3ac34ba..0000000 --- a/app/Helpers/create_form_helper.php +++ /dev/null @@ -1,38 +0,0 @@ -getFormService(); - $html = $formHelper->getSpecificFieldHtml($field, $value, $viewDatas); - $error = validation_show_error($field); - return $html . "{$error}"; - } - - if (! function_exists('render_field_label')) { - function render_field_label(string $field, array $viewDatas): string - { - $classPath = $viewDatas['class_path']; - $baseLabel = lang("{$classPath}.label.{$field}"); - // 1. ServiceForm에서 동적 처리(예: 도움말 아이콘, 별도 클래스)를 가져옵니다. - $service = $viewDatas['service'] ?? null; - if ($service === null) { - return __FUNCTION__ . "에서 오류발생: ViewDatas에 'service'가 정의되지 않았습니다."; - } - $formHelper = $service->getFormHelper(); - $dynamicHtml = $formHelper->getSpecificLabelAdornment($field); - // 2. 공통 로직: 필수 필드 표시 (*) - // (ServiceForm이 해당 필드가 필수인지 알려줘야 함) - $isRequired = $formHelper->isFieldRequired($field); - $requiredStar = $isRequired ? '*' : ''; - return "{$baseLabel}{$requiredStar}{$dynamicHtml}"; - } - } -} diff --git a/app/Services/Auth/AuthService.php b/app/Services/Auth/AuthService.php index 13f9d4e..461b1e7 100644 --- a/app/Services/Auth/AuthService.php +++ b/app/Services/Auth/AuthService.php @@ -3,6 +3,7 @@ namespace App\Services\Auth; use App\Entities\UserEntity; +use App\Helpers\AuthHelper; use App\Models\CommonModel; use App\Services\CommonService; use CodeIgniter\Session\Session; @@ -16,13 +17,27 @@ abstract class AuthService extends CommonService protected function __construct(CommonModel $model) { parent::__construct($model); - $this->addClassPath('Auth'); + $this->addClassPaths('Auth'); + } + abstract public function login(mixed $dto): UserEntity; + final public function getHelper(): AuthHelper + { + if ($this->helperInstance === null) { + $this->helperInstance = new AuthHelper(); + $this->helperInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->helperInstance; } - abstract public function login(array $formDatas): UserEntity; //Index,FieldForm관련 final public function getSession(): Session { - if (!$this->_session) { + if ($this->_session === null) { $this->_session = \Config\Services::session(); } return $this->_session; diff --git a/app/Services/Auth/GoogleService.php b/app/Services/Auth/GoogleService.php index b502e6a..20b5bcc 100644 --- a/app/Services/Auth/GoogleService.php +++ b/app/Services/Auth/GoogleService.php @@ -2,31 +2,34 @@ namespace App\Services\Auth; +use App\DTOs\Auth\GoogleDTO; +use App\DTOs\AuthDTO; use App\Entities\UserEntity; use App\Forms\Auth\GoogleForm; use App\Libraries\MySocket\GoogleSocket\CURL; use App\Models\UserModel; use CodeIgniter\Exceptions\PageNotFoundException; +use CodeIgniter\Validation\Exceptions\ValidationException; +use RuntimeException; class GoogleService extends AuthService { - public function __construct(UserModel $model, private GoogleForm $formService, private CURL $socket) + public function __construct(UserModel $model, private CURL $socket) { parent::__construct($model); - $this->formServiceInstance = $this->formService; - // FormService에 Model 메타데이터를 설정 - $this->formServiceInstance->setAttributes([ - 'pk_field' => $this->model->getPKField(), - 'title_field' => $this->model->getTitleField(), - 'table' => $this->model->getTable(), - 'useAutoIncrement' => $this->model->useAutoIncrement(), - ]); - $this->addClassPath('Google'); + $this->addClassPaths('Google'); } public function getFormService(): GoogleForm { if ($this->formServiceInstance === null) { - throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.'); + $this->formServiceInstance = new GoogleForm(); + $this->formServiceInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); } return $this->formServiceInstance; } @@ -43,11 +46,19 @@ class GoogleService extends AuthService return []; } //기본기능 - public function login(array $formDatas): UserEntity + public function login(mixed $dto): UserEntity { try { - // Google 서비스 설정 - $this->socket->setToken($formDatas['access_code']); + if (!$dto instanceof GoogleDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생: GoogleDTO만 사용하실수 있습니다"); + } + // DTO 객체를 배열로 변환하여 검증기에 전달 + $formDatas = (array) $dto; + if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) { + // 검증 실패 시, ValidationException을 던집니다. + throw new ValidationException(service('validation')->getErrors()); + } + $this->socket->setToken($dto->access_code); $sns_entity = $this->socket->signup(); // local db 사용와의 연결 확인 $entity = $this->getEntity($sns_entity->getParent()); diff --git a/app/Services/Auth/LocalService.php b/app/Services/Auth/LocalService.php index e10e124..a8bc2fb 100644 --- a/app/Services/Auth/LocalService.php +++ b/app/Services/Auth/LocalService.php @@ -2,31 +2,31 @@ namespace App\Services\Auth; +use App\DTOs\Auth\LocalDTO; use App\Entities\UserEntity; use App\Forms\Auth\LocalForm; use App\Models\UserModel; +use CodeIgniter\Validation\Exceptions\ValidationException; +use RuntimeException; class LocalService extends AuthService { - public function __construct( - UserModel $model, - private LocalForm $formService, - ) { + public function __construct(UserModel $model) + { parent::__construct($model); - $this->formServiceInstance = $this->formService; - // FormService에 Model 메타데이터를 설정 - $this->formServiceInstance->setAttributes([ - 'pk_field' => $this->model->getPKField(), - 'title_field' => $this->model->getTitleField(), - 'table' => $this->model->getTable(), - 'useAutoIncrement' => $this->model->useAutoIncrement(), - ]); - $this->addClassPath('Local'); + $this->addClassPaths('Local'); } public function getFormService(): LocalForm { if ($this->formServiceInstance === null) { - throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.'); + $this->formServiceInstance = new LocalForm(); + $this->formServiceInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); } return $this->formServiceInstance; } @@ -43,17 +43,22 @@ class LocalService extends AuthService return []; } //기본기능 - public function login(array $formDatas): UserEntity + public function login(mixed $dto): UserEntity { - $entity = $this->getEntity([ - 'id' => $formDatas['id'], - 'status' => UserEntity::DEFAULT_STATUS - ], false); - if (!$entity instanceof UserEntity) { - throw new \Exception("{$formDatas['id']}에 대한 로그인 정보를 찾을수 없습니다."); + if (!$dto instanceof LocalDTO) { + throw new RuntimeException(__METHOD__ . "에서 오류발생: LcoalDTO만 사용하실수 있습니다"); } - if (!password_verify($formDatas['passwd'], $entity->getPassword())) { - // log_message("error", "암호: {$formDatas['passwd']}, {$entity->passwd}"); + // DTO 객체를 배열로 변환하여 검증기에 전달 + $formDatas = (array) $dto; + if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) { + // 검증 실패 시, ValidationException을 던집니다. + throw new ValidationException(implode("\n", service('validation')->getErrors())); + } + $entity = $this->getEntity(['id' => $dto->id, 'status' => STATUS['AVAILABLE']], false); + if (!$entity instanceof UserEntity) { + throw new \Exception("{$dto->id}에 대한 로그인 정보를 찾을수 없습니다."); + } + if (!password_verify($dto->passwd, $entity->getPassword())) { throw new \Exception("암호가 맞지 않습니다."); } return $this->login_process($entity); diff --git a/app/Services/CommonService.php b/app/Services/CommonService.php index e006cb1..e3c7c6a 100644 --- a/app/Services/CommonService.php +++ b/app/Services/CommonService.php @@ -2,23 +2,23 @@ namespace App\Services; -use CodeIgniter\HTTP\RedirectResponse; use App\Models\CommonModel; abstract class CommonService { - private $_logService = null; - protected array $classPaths = []; + private array $_classPaths = []; protected $formServiceInstance = null; + protected $helperInstance = null; protected function __construct(protected CommonModel $model) {} abstract public function getFormService(): mixed; - final protected function addClassPath(string $className): void + abstract public function getHelper(): mixed; + final protected function addClassPaths(string $path): void { - $this->classPaths[] = $className; + $this->_classPaths[] = $path; } - final public function getClassPath($delimeter = DIRECTORY_SEPARATOR): string + final public function getClassPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string { - return implode($delimeter, $this->classPaths); + return $isArray ? $this->_classPaths : implode($delimeter, $this->_classPaths); } final public function getEntity(string|int|array $where, ?string $message = null): mixed { @@ -76,11 +76,7 @@ abstract class CommonService } public function getFormOptions(string $action): array { - return $this->getFormService()->getFormOptions( - $this->getClassPath(), - $action, - $this->getFormFilters() - ); + return $this->getFormService()->getFormOptions($action, $this->getFormFilters()); } public function getViewFields(): array { diff --git a/app/Services/TrafficService.php b/app/Services/TrafficService.php index 01daf78..67523d7 100644 --- a/app/Services/TrafficService.php +++ b/app/Services/TrafficService.php @@ -12,26 +12,38 @@ class TrafficService extends CommonService { public function __construct( TrafficModel $model, - private TrafficForm $formService, ) { parent::__construct($model); - $this->formServiceInstance = $this->formService; - // FormService에 Model 메타데이터를 설정 - $this->formServiceInstance->setAttributes([ - 'pk_field' => $this->model->getPKField(), - 'title_field' => $this->model->getTitleField(), - 'table' => $this->model->getTable(), - 'useAutoIncrement' => $this->model->useAutoIncrement(), - ]); - $this->addClassPath('Service'); + $this->addClassPaths('Traffic'); } public function getFormService(): TrafficForm { if ($this->formServiceInstance === null) { - throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.'); + $this->formServiceInstance = new TrafficForm(); + $this->formServiceInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); } return $this->formServiceInstance; } + public function getHelper(): TrafficHelper + { + if ($this->helperInstance === null) { + $this->helperInstance = new TrafficHelper(); + $this->helperInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->helperInstance; + } //필수함수 // public function getNewServiceEntities(int $interval, string $status = ServiceEntity::DEFAULT_STATUS): array // { diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 70f671b..6935a15 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -2,114 +2,99 @@ namespace App\Services; +use App\DTOs\UserDTO; use App\Entities\UserEntity; use App\Forms\UserForm; +use App\Helpers\UserHelper; use App\Models\UserModel; +use CodeIgniter\Validation\Exceptions\ValidationException; +use RuntimeException; class UserService extends CommonService { - public function __construct( - UserModel $model, - private UserForm $formService, - ) { + public function __construct(UserModel $model) + { parent::__construct($model); - $this->formServiceInstance = $this->formService; - // FormService에 Model 메타데이터를 설정 - $this->formServiceInstance->setAttributes([ - 'pk_field' => $this->model->getPKField(), - 'title_field' => $this->model->getTitleField(), - 'table' => $this->model->getTable(), - 'useAutoIncrement' => $this->model->useAutoIncrement(), - ]); - $this->addClassPath('Service'); + $this->addClassPaths('User'); } public function getFormService(): UserForm { if ($this->formServiceInstance === null) { - throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.'); + $this->formServiceInstance = new UserForm(); + $this->formServiceInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); } return $this->formServiceInstance; } - public function getFormFields(): array + public function getHelper(): UserHelper { - return [ - 'id', - 'passwd', - 'confirmpassword', - 'name', - 'email', - 'mobile', - 'role', - 'status', - ]; - } - public function getFormFilters(): array - { - return [ - 'role', - 'status', - ]; - } - public function getIndexFields(): array - { - return [ - 'id', - 'name', - 'email', - 'mobile', - 'role', - 'status', - ]; - } - public function getBatchjobFields(): array - { - return ['status']; + if ($this->helperInstance === null) { + $this->helperInstance = new UserHelper(); + $this->helperInstance->setAttributes([ + 'pk_field' => $this->model->getPKField(), + 'title_field' => $this->model->getTitleField(), + 'table' => $this->model->getTable(), + 'useAutoIncrement' => $this->model->useAutoIncrement(), + 'class_path' => $this->getClassPaths(false) + ]); + } + return $this->helperInstance; } //기본 기능부분 - - protected function create_process(array $formDatas): UserEntity + public function create(UserDTO $dto): UserEntity { + // DTO 객체를 배열로 변환하여 검증기에 전달 + $formDatas = (array) $dto; + if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) { + // 검증 실패 시, ValidationException을 던집니다. + throw new ValidationException(implode("\n", service('validation')->getErrors())); + } $formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']); $entity = $this->model->create($formDatas); return $entity; } - protected function modify_process(mixed $entity, array $formDatas): UserEntity - { - // die(var_export($formDatas, true)); - //암호를 입력하지 않았을시는 변경하기 않게 하기위함 - if (isset($formDatas['passwd']) && $formDatas['passwd'] == "") { - unset($formDatas['passwd']); - unset($formDatas['confirmpassword']); - } - //Role을 지정이 있을경우에만 , toggle이나 batcjhjob에서는 없을수도 있으므로 - if (isset($formDatas['role'])) { - $formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']); - } - // die(var_export($formDatas, true)); - $entity = parent::modify_process($entity, $formDatas); - return $entity; - } - //List 검색용 - //FormFilter 조건절 처리 - public function index_condition_filterField(string $field, mixed $filter_value): void - { - switch ($field) { - case 'role': - $where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0"; - //FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동 - $this->model->where($where, null, false); - break; - default: - parent::index_condition_filterField($field, $filter_value); - break; - } - } - //검색어조건절처리 - public function index_condition_filterWord(string $word): void - { - $this->model->orLike($this->model->getTable() . '.id', $word, 'both'); - $this->model->orLike($this->model->getTable() . "." . $this->model::TITLE, $word, 'both'); - $this->model->orLike($this->model->getTable() . '.email', $word, 'both'); - parent::index_condition_filterWord($word); - } + // protected function modify_process(mixed $entity, array $formDatas): UserEntity + // { + // // die(var_export($formDatas, true)); + // //암호를 입력하지 않았을시는 변경하기 않게 하기위함 + // if (isset($formDatas['passwd']) && $formDatas['passwd'] == "") { + // unset($formDatas['passwd']); + // unset($formDatas['confirmpassword']); + // } + // //Role을 지정이 있을경우에만 , toggle이나 batcjhjob에서는 없을수도 있으므로 + // if (isset($formDatas['role'])) { + // $formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']); + // } + // // die(var_export($formDatas, true)); + // $entity = parent::modify_process($entity, $formDatas); + // return $entity; + // } + // //List 검색용 + // //FormFilter 조건절 처리 + // public function index_condition_filterField(string $field, mixed $filter_value): void + // { + // switch ($field) { + // case 'role': + // $where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0"; + // //FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동 + // $this->model->where($where, null, false); + // break; + // default: + // parent::index_condition_filterField($field, $filter_value); + // break; + // } + // } + // //검색어조건절처리 + // public function index_condition_filterWord(string $word): void + // { + // $this->model->orLike($this->model->getTable() . '.id', $word, 'both'); + // $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both'); + // $this->model->orLike($this->model->getTable() . '.email', $word, 'both'); + // parent::index_condition_filterWord($word); + // } } diff --git a/app/Views/admin/user/create_form.php b/app/Views/admin/user/create_form.php new file mode 100644 index 0000000..bda6804 --- /dev/null +++ b/app/Views/admin/user/create_form.php @@ -0,0 +1,24 @@ +extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?> +section('content') ?> +alertTrait(session('error')) ?> +
+
include("templates/{$viewDatas['control']['layout']}/form_content_top"); ?>
+ +
+ + + + + + + +
getFieldLabel($field, "", $viewDatas) ?> + getFieldForm($field, old($field) ?? ($viewDatas['control']['formDatas'][$field] ?? null), $viewDatas) ?> + +
+
"btn btn-outline btn-primary")); ?>
+ +
+
include("templates/{$viewDatas['control']['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/user/download.php b/app/Views/admin/user/download.php new file mode 100644 index 0000000..3f45dc2 --- /dev/null +++ b/app/Views/admin/user/download.php @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + +
getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?>
\ No newline at end of file diff --git a/app/Views/admin/user/index.php b/app/Views/admin/user/index.php new file mode 100644 index 0000000..d6224c3 --- /dev/null +++ b/app/Views/admin/user/index.php @@ -0,0 +1,70 @@ +extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?> +section('content') ?> +getHelper()->alertTrait($error) ?> +
include(LAYOUTS[$viewDatas['control']['layout']]['path'] . '/top'); ?>
+ + + + + + +
+ + include(LAYOUTS[$viewDatas['control']['layout']]['path'] . '/left_menu'); ?> + + + +
include("templates/{$viewDatas['control']['layout']}/index_header"); ?>
+
+ +
+ "get"]) ?> + + + 'batchjob_form', 'method' => "post"]) ?> + + + + + + + + + + + + + + getStatus() === $viewDatas['entity']::DEFAULT_STATUS ? "" : 'class="table-danger"' ?>> + + + + + + + + + + +
번호getHelper()->getListLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?>작업
getHelper()->getListButton('modify', $num, $viewDatas) ?>getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?> + getHelper()->getListButton('view', '', $viewDatas) ?>  + getHelper()->getListButton('delete', '', $viewDatas) ?> +
+ include("templates/{$viewDatas['control']['layout']}/index_content_bottom"); ?> + +
+
+ +
+
include(LAYOUTS[$viewDatas['control']['layout']]['path'] . '/bottom'); ?>
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/user/modify_form.php b/app/Views/admin/user/modify_form.php new file mode 100644 index 0000000..6006c52 --- /dev/null +++ b/app/Views/admin/user/modify_form.php @@ -0,0 +1,24 @@ +extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?> +section('content') ?> +getHelper()->alertTrait($error) ?> +
+
include("templates/{$viewDatas['control']['layout']}/form_content_top"); ?>
+ 'action_form', ...$viewDatas['forms']['attributes']], $viewDatas['forms']['hiddens']) ?> +
+ + + + + + + +
getHelper()->getFieldLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?> + getHelper()->getFieldForm($field, old($field) ?? $viewDatas['entity']->$field ?? null, $viewDatas) ?> +
+
+
"btn btn-outline btn-primary"]) ?>
+ +
+
include("templates/{$viewDatas['control']['layout']}/form_content_bottom"); ?>
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/admin/user/view.php b/app/Views/admin/user/view.php new file mode 100644 index 0000000..66de450 --- /dev/null +++ b/app/Views/admin/user/view.php @@ -0,0 +1,17 @@ +extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?> +section('content') ?> +getHelper()->alertTrait($error) ?> +
+ +
+ + + + + + + +
getHelper()->getFieldLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?>getHelper()->getFieldView($field, $viewDatas['entity']->$field, $viewDatas) ?>
+
+
+endSection() ?> \ No newline at end of file