diff --git a/app/Cells/Customer/ServiceCell.php b/app/Cells/Customer/ServiceCell.php index f50815d..a11ab82 100644 --- a/app/Cells/Customer/ServiceCell.php +++ b/app/Cells/Customer/ServiceCell.php @@ -11,16 +11,16 @@ class ServiceCell extends CustomerCell public function detail(array $params): string { - $this->getService()->getFormService()->action_init_process(__FUNCTION__); + $this->getService()->getActionForm()->action_init_process(__FUNCTION__); //서비스별 미납 Count - $unPaids = service('paymentservice')->getUnPaids('serviceinfo_uid', ['clientinfo_uid' => $params['clientinfo_uid']]); + $unPaids = service('paymentservice')->getUnPaids('serviceinfo_uid', ['clientinfo_uid' => $params['clientinfo_uid']]); //서비스별 서버리스트 $entities = $this->getService()->getEntities(['clientinfo_uid' => $params['clientinfo_uid']]); $template = array_key_exists('template', $params) ? $params['template'] : __FUNCTION__; return view('cells/service/' . $template, [ 'serviceCellDatas' => [ - 'formFilters' => $this->getService()->getFormService()->getFormFilters(), - 'formOptions' => $this->getService()->getFormService()->getFormOptions(), + 'formFilters' => $this->getService()->getActionForm()->getFormFilters(), + 'formOptions' => $this->getService()->getActionForm()->getFormOptions(), 'helper' => $this->getService()->getHelper(), 'unPaids' => $unPaids, 'entities' => $entities, diff --git a/app/Cells/Equipment/ServerCell.php b/app/Cells/Equipment/ServerCell.php index 9dca791..a90564b 100644 --- a/app/Cells/Equipment/ServerCell.php +++ b/app/Cells/Equipment/ServerCell.php @@ -59,7 +59,7 @@ class ServerCell extends EquipmentCell } public function detail(array $params): string { - $this->getService()->getFormService()->action_init_process(__FUNCTION__); + $this->getService()->getActionForm()->action_init_process(__FUNCTION__); if (!array_key_exists('serviceEntity', $params)) { return static::class . '->' . __FUNCTION__ . "에서 오류발생: 서비스 정보가 정의되지 않았습니다."; } @@ -68,8 +68,8 @@ class ServerCell extends EquipmentCell $template = array_key_exists('template', $params) ? $params['template'] : __FUNCTION__; return view('cells/server/' . $template, [ 'serverCellDatas' => [ - 'formFilters' => $this->getService()->getFormService()->getFormFilters(), - 'formOptions' => $this->getService()->getFormService()->getFormOptions(), + 'formFilters' => $this->getService()->getActionForm()->getFormFilters(), + 'formOptions' => $this->getService()->getActionForm()->getFormOptions(), 'helper' => $this->getService()->getHelper(), 'entities' => $entities, 'serviceEntity' => $serviceEntity, diff --git a/app/Cells/Equipment/ServerPartCell.php b/app/Cells/Equipment/ServerPartCell.php index c0545d3..4a3a6eb 100644 --- a/app/Cells/Equipment/ServerPartCell.php +++ b/app/Cells/Equipment/ServerPartCell.php @@ -14,7 +14,7 @@ class ServerPartCell extends EquipmentCell public function parttable(array $params): string { - $this->getService()->getFormService()->action_init_process(__FUNCTION__); + $this->getService()->getActionForm()->action_init_process(__FUNCTION__); if (!array_key_exists('serverinfo_uid', $params)) { return "서버정보를 정의하셔야합니다."; } @@ -35,11 +35,11 @@ class ServerPartCell extends EquipmentCell $template = array_key_exists('template', $params) ? $params['template'] : __FUNCTION__; return view('cells/serverpart/' . $template, [ 'serverPartCellDatas' => [ - 'formFilters' => $this->getService()->getFormService()->getFormFilters(), - 'formOptions' => $this->getService()->getFormService()->getFormOptions(), + 'formFilters' => $this->getService()->getActionForm()->getFormFilters(), + 'formOptions' => $this->getService()->getActionForm()->getFormOptions(), 'helper' => $this->getService()->getHelper(), 'serverinfo_uid' => $params['serverinfo_uid'], - 'types' => $params['types'], + 'types' => $params['types'], 'serverEntity' => $serverEntity, 'entities' => $entities, ], diff --git a/app/Cells/MylogCell.php b/app/Cells/MylogCell.php index 935377e..cb5b42e 100644 --- a/app/Cells/MylogCell.php +++ b/app/Cells/MylogCell.php @@ -15,14 +15,14 @@ class MylogCell extends CommonCell public function dashboard(array $params): string { - $this->getService()->getFormService()->action_init_process(__FUNCTION__); + $this->getService()->getActionForm()->action_init_process(__FUNCTION__); $this->getService()->setLimit(20); $template = array_key_exists('template', $params) ? $params['template'] : __FUNCTION__; return view('cells/mylog/' . $template, [ 'myLogCellDatas' => [ 'helper' => $this->getService()->getHelper(), - 'formFilters' => $this->getService()->getFormService()->getFormFilters(), - 'formOptions' => $this->getService()->getFormService()->getFormOptions(), + 'formFilters' => $this->getService()->getActionForm()->getFormFilters(), + 'formOptions' => $this->getService()->getActionForm()->getFormOptions(), 'entities' => $this->getService()->getEntities(), ] ]); diff --git a/app/Cells/Part/DISKCell.php b/app/Cells/Part/DISKCell.php index f9ed5de..60e0ca4 100644 --- a/app/Cells/Part/DISKCell.php +++ b/app/Cells/Part/DISKCell.php @@ -13,13 +13,13 @@ class DISKCell extends PartCell public function stock(array $params): string { - $this->getService()->getFormService()->action_init_process(__FUNCTION__); + $this->getService()->getActionForm()->action_init_process(__FUNCTION__); $template = array_key_exists('template', $params) ? $params['template'] : 'disk_stock'; return view('cells/part/' . $template, [ 'partCellDatas' => [ 'helper' => $this->getService()->getHelper(), - 'formFilters' => $this->getService()->getFormService()->getFormFilters(), - 'formOptions' => $this->getService()->getFormService()->getFormOptions(), + 'formFilters' => $this->getService()->getActionForm()->getFormFilters(), + 'formOptions' => $this->getService()->getActionForm()->getFormOptions(), 'entities' => $this->getService()->getEntities(), ], ]); diff --git a/app/Cells/PaymentCell.php b/app/Cells/PaymentCell.php index 5bf2658..5944955 100644 --- a/app/Cells/PaymentCell.php +++ b/app/Cells/PaymentCell.php @@ -14,13 +14,13 @@ class PaymentCell extends CommonCell public function detail(array $params): string { - $this->getService()->getFormService()->action_init_process(__FUNCTION__); + $this->getService()->getActionForm()->action_init_process(__FUNCTION__); $entities = $this->getService()->getEntities(['clientinfo_uid' => $params['clientinfo_uid'], 'billing' => PAYMENT['BILLING']['ONETIME'], 'status' => STATUS['UNPAID']]); $template = array_key_exists('template', $params) ? $params['template'] : __FUNCTION__; return view('cells/payment/' . $template, [ 'paymentCellDatas' => [ - 'formFilters' => $this->getService()->getFormService()->getFormFilters(), - 'formOptions' => $this->getService()->getFormService()->getFormOptions(), + 'formFilters' => $this->getService()->getActionForm()->getFormFilters(), + 'formOptions' => $this->getService()->getActionForm()->getFormOptions(), 'helper' => $this->getService()->getHelper(), 'entities' => $entities, ] diff --git a/app/Config/Constants.php b/app/Config/Constants.php index b0507b0..5192a96 100644 --- a/app/Config/Constants.php +++ b/app/Config/Constants.php @@ -312,8 +312,8 @@ define("ROLE", [ //Default값 정의 define('DEFAULTS', [ - 'DELIMITER_FILE' => "||", - 'DELIMITER_ROLE' => ",", + 'DELIMITER_PIPE' => "||", + 'DELIMITER_COMMA' => ",", 'INDEX_PERPAGE' => 20, 'STATUS' => STATUS['AVAILABLE'] ]); diff --git a/app/Controllers/AbstractCRUDController.php b/app/Controllers/AbstractCRUDController.php index 011fa47..0e74611 100644 --- a/app/Controllers/AbstractCRUDController.php +++ b/app/Controllers/AbstractCRUDController.php @@ -43,6 +43,7 @@ abstract class AbstractCRUDController extends AbstractWebController { // POST 데이터를 DTO 객체로 변환 $dto = $this->service->createDTO($formDatas); + // dd($dto->toArray()); //DTO 타입 체크 로직을 일반화 $dtoClass = $this->service->getDTOClass(); if (!$dto instanceof $dtoClass) { diff --git a/app/Controllers/Admin/AdminController.php b/app/Controllers/Admin/AdminController.php index d5d586a..591b2f0 100644 --- a/app/Controllers/Admin/AdminController.php +++ b/app/Controllers/Admin/AdminController.php @@ -23,13 +23,13 @@ abstract class AdminController extends CommonController $this->addViewDatas('layout', $this->layouts); $this->addViewDatas('title', $this->getTitle()); $this->addViewDatas('helper', $this->service->getHelper()); - $this->service->getFormService()->action_init_process($action, $formDatas); - $this->addViewDatas('formFields', $this->service->getFormService()->getFormFields()); - $this->addViewDatas('formRules', $this->service->getFormService()->getFormRules()); - $this->addViewDatas('formFilters', $this->service->getFormService()->getFormFilters()); - $this->addViewDatas('formOptions', $this->service->getFormService()->getFormOptions()); - $this->addViewDatas('index_actionButtons', $this->service->getFormService()->getActionButtons()); - $this->addViewDatas('index_batchjobFields', $this->service->getFormService()->getBatchjobFilters()); - $this->addViewDatas('index_batchjobButtons', $this->service->getFormService()->getBatchjobButtons()); + $this->service->getActionForm()->action_init_process($action, $formDatas); + $this->addViewDatas('formFields', $this->service->getActionForm()->getFormFields()); + $this->addViewDatas('formRules', $this->service->getActionForm()->getFormRules()); + $this->addViewDatas('formFilters', $this->service->getActionForm()->getFormFilters()); + $this->addViewDatas('formOptions', $this->service->getActionForm()->getFormOptions()); + $this->addViewDatas('index_actionButtons', $this->service->getActionForm()->getActionButtons()); + $this->addViewDatas('index_batchjobFields', $this->service->getActionForm()->getBatchjobFilters()); + $this->addViewDatas('index_batchjobButtons', $this->service->getActionForm()->getBatchjobButtons()); } } diff --git a/app/Controllers/Admin/Home.php b/app/Controllers/Admin/Home.php index 37d8952..1b7908e 100644 --- a/app/Controllers/Admin/Home.php +++ b/app/Controllers/Admin/Home.php @@ -25,11 +25,11 @@ class Home extends AbstractWebController parent::action_init_process($action, $formDatas); $this->addViewDatas('layout', $this->layouts); $this->addViewDatas('helper', $this->service->getHelper()); - $this->service->getFormService()->action_init_process($action, $formDatas); - $this->addViewDatas('formFields', $this->service->getFormService()->getFormFields()); - $this->addViewDatas('formRules', $this->service->getFormService()->getFormRules()); - $this->addViewDatas('formFilters', $this->service->getFormService()->getFormFilters()); - $this->addViewDatas('formOptions', $this->service->getFormService()->getFormOptions()); + $this->service->getActionForm()->action_init_process($action, $formDatas); + $this->addViewDatas('formFields', $this->service->getActionForm()->getFormFields()); + $this->addViewDatas('formRules', $this->service->getActionForm()->getFormRules()); + $this->addViewDatas('formFilters', $this->service->getActionForm()->getFormFilters()); + $this->addViewDatas('formOptions', $this->service->getActionForm()->getFormOptions()); } //Index,FieldForm관련 public function index(): string diff --git a/app/Controllers/Auth/AuthController.php b/app/Controllers/Auth/AuthController.php index 928dacc..b5e45d4 100644 --- a/app/Controllers/Auth/AuthController.php +++ b/app/Controllers/Auth/AuthController.php @@ -25,11 +25,11 @@ abstract class AuthController extends AbstractWebController $this->addViewDatas('layout', $this->layouts); $this->addViewDatas('helper', $this->service->getHelper()); //Fields,Rules,Filters,Options등 초기화 - $this->service->getFormService()->action_init_process($action, $formDatas); - $this->addViewDatas('formFields', $this->service->getFormService()->getFormFields()); - $this->addViewDatas('formRules', $this->service->getFormService()->getFormRules()); - $this->addViewDatas('formFilters', $this->service->getFormService()->getFormFilters()); - $this->addViewDatas('formOptions', $this->service->getFormService()->getFormOptions()); + $this->service->getActionForm()->action_init_process($action, $formDatas); + $this->addViewDatas('formFields', $this->service->getActionForm()->getFormFields()); + $this->addViewDatas('formRules', $this->service->getActionForm()->getFormRules()); + $this->addViewDatas('formFilters', $this->service->getActionForm()->getFormFilters()); + $this->addViewDatas('formOptions', $this->service->getActionForm()->getFormOptions()); } //로그인화면 final public function login_form(): string|RedirectResponse diff --git a/app/Controllers/CommonController.php b/app/Controllers/CommonController.php index 1563bd6..a0227bd 100644 --- a/app/Controllers/CommonController.php +++ b/app/Controllers/CommonController.php @@ -107,8 +107,8 @@ abstract class CommonController extends AbstractCRUDController { // Filter조건절 처리 $index_filters = []; - // dd($this->service->getFormService()->getIndexFilters($action)); - foreach ($this->service->getFormService()->getIndexFilters($action) as $field) { + // dd($this->service->getActionForm()->getIndexFilters($action)); + foreach ($this->service->getActionForm()->getIndexFilters($action) as $field) { $value = $this->request->getVar($field) ?? null; if ($value) { $this->service->setFilter($field, $value); diff --git a/app/DTOs/CommonDTO.php b/app/DTOs/CommonDTO.php index 2b16cd4..f199778 100644 --- a/app/DTOs/CommonDTO.php +++ b/app/DTOs/CommonDTO.php @@ -44,7 +44,7 @@ abstract class CommonDTO $typeName = $type->getName(); if ($typeName === 'array' && is_string($value)) { - $assignValue = explode(DEFAULTS["DELIMITER_ROLE"], $value); + $assignValue = explode(DEFAULTS["DELIMITER_COMMA"], $value); } elseif ($typeName === 'int' && is_numeric($value)) { $assignValue = (int) $value; } elseif ($typeName === 'float' && is_numeric($value)) { diff --git a/app/DTOs/Customer/ClientDTO.php b/app/DTOs/Customer/ClientDTO.php index ef21e5f..030eaa6 100644 --- a/app/DTOs/Customer/ClientDTO.php +++ b/app/DTOs/Customer/ClientDTO.php @@ -8,6 +8,8 @@ class ClientDTO extends CommonDTO { public ?int $uid = null; public ?int $user_uid = null; + public ?string $id = null; + public ?string $passwd = null; public string $site = ''; public string $name = ''; public string $phone = ''; @@ -23,7 +25,7 @@ class ClientDTO extends CommonDTO { // 1. role 변환 로직 (기존 유지) if (isset($datas['role']) && is_string($datas['role'])) { - $datas['role'] = explode(DEFAULTS["DELIMITER_ROLE"], $datas['role']); + $datas['role'] = explode(DEFAULTS["DELIMITER_COMMA"], $datas['role']); } if (!isset($datas['role'])) { @@ -44,6 +46,6 @@ class ClientDTO extends CommonDTO public function getRoleToString(): string { - return implode(DEFAULTS["DELIMITER_ROLE"], $this->role); + return implode(DEFAULTS["DELIMITER_COMMA"], $this->role); } } diff --git a/app/DTOs/UserDTO.php b/app/DTOs/UserDTO.php index 804b5ce..ff0f907 100644 --- a/app/DTOs/UserDTO.php +++ b/app/DTOs/UserDTO.php @@ -18,7 +18,7 @@ class UserDTO extends CommonDTO { // 1. [전처리] 입력값이 문자열(CSV)로 들어왔다면 배열로 변환 if (isset($datas['role']) && is_string($datas['role'])) { - $datas['role'] = explode(DEFAULTS["DELIMITER_ROLE"], $datas['role']); + $datas['role'] = explode(DEFAULTS["DELIMITER_COMMA"], $datas['role']); } // 2. 만약 데이터가 없다면 빈 배열로 초기화 @@ -35,6 +35,6 @@ class UserDTO extends CommonDTO */ public function getRoleToString(): string { - return implode(DEFAULTS["DELIMITER_ROLE"], $this->role); + return implode(DEFAULTS["DELIMITER_COMMA"], $this->role); } } diff --git a/app/Entities/Customer/ClientEntity.php b/app/Entities/Customer/ClientEntity.php index b61e74d..a2a19e4 100644 --- a/app/Entities/Customer/ClientEntity.php +++ b/app/Entities/Customer/ClientEntity.php @@ -78,7 +78,7 @@ class ClientEntity extends CustomerEntity return $decodedRole; } // 2-b. JSON이 아니면 CSV로 가정하고 변환 - $parts = explode(DEFAULTS["DELIMITER_ROLE"], $role); + $parts = explode(DEFAULTS["DELIMITER_COMMA"], $role); // 각 요소의 불필요한 공백과 따옴표 제거. null 가능성에 대비해 string 형변환 추가 $cleanedRoles = array_map(fn($item) => trim((string) ($item ?? ''), " \t\n\r\0\x0B\""), $parts); return array_filter($cleanedRoles); @@ -102,7 +102,7 @@ class ClientEntity extends CustomerEntity $cleanRoleString = trim($role, " \t\n\r\0\x0B\""); if (!empty($cleanRoleString)) { // 문자열을 구분자로 분리하여 배열로 만듭니다. - $roleArray = explode(DEFAULTS["DELIMITER_ROLE"], $cleanRoleString); + $roleArray = explode(DEFAULTS["DELIMITER_COMMA"], $cleanRoleString); } } // 입력된 데이터가 이미 배열인 경우 (modify_process에서 $formDatas가 배열로 넘어옴) @@ -114,6 +114,6 @@ class ClientEntity extends CustomerEntity $roleArray = array_filter($cleanedRoles); // 최종적으로 DB에 삽입될 단일 CSV 문자열로 변환하여 저장합니다. // ✅ setter함수는 반드시 attributes에 저장 - $this->attributes['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $roleArray); + $this->attributes['role'] = implode(DEFAULTS["DELIMITER_COMMA"], $roleArray); } } diff --git a/app/Entities/UserEntity.php b/app/Entities/UserEntity.php index 84e98f0..d66143d 100644 --- a/app/Entities/UserEntity.php +++ b/app/Entities/UserEntity.php @@ -56,7 +56,7 @@ class UserEntity extends CommonEntity return $decodedRole; } // 2-b. JSON이 아니면 CSV로 가정하고 변환 - $parts = explode(DEFAULTS["DELIMITER_ROLE"], $role); + $parts = explode(DEFAULTS["DELIMITER_COMMA"], $role); // 각 요소의 불필요한 공백과 따옴표 제거. null 가능성에 대비해 string 형변환 추가 $cleanedRoles = array_map(fn($item) => trim((string) ($item ?? ''), " \t\n\r\0\x0B\""), $parts); return array_filter($cleanedRoles); @@ -89,7 +89,7 @@ class UserEntity extends CommonEntity $cleanRoleString = trim($role, " \t\n\r\0\x0B\""); if (!empty($cleanRoleString)) { // 문자열을 구분자로 분리하여 배열로 만듭니다. - $roleArray = explode(DEFAULTS["DELIMITER_ROLE"], $cleanRoleString); + $roleArray = explode(DEFAULTS["DELIMITER_COMMA"], $cleanRoleString); } } // 입력된 데이터가 이미 배열인 경우 (modify_process에서 $formDatas가 배열로 넘어옴) @@ -101,6 +101,6 @@ class UserEntity extends CommonEntity $roleArray = array_filter($cleanedRoles); // 최종적으로 DB에 삽입될 단일 CSV 문자열로 변환하여 저장합니다. // ✅ setter함수는 반드시 attributes에 저장 - $this->attributes['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $roleArray); + $this->attributes['role'] = implode(DEFAULTS["DELIMITER_COMMA"], $roleArray); } } diff --git a/app/Forms/Auth/GoogleForm.php b/app/Forms/Auth/GoogleForm.php index 0acfe0d..7ebcb15 100644 --- a/app/Forms/Auth/GoogleForm.php +++ b/app/Forms/Auth/GoogleForm.php @@ -10,7 +10,7 @@ class GoogleForm extends CommonForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = ['access_code']; $filters = []; @@ -31,7 +31,7 @@ class GoogleForm extends CommonForm case "access_code": $formRules[$field] = "required|trim|string"; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Auth/LocalForm.php b/app/Forms/Auth/LocalForm.php index 771ac70..9b98078 100644 --- a/app/Forms/Auth/LocalForm.php +++ b/app/Forms/Auth/LocalForm.php @@ -10,7 +10,7 @@ class LocalForm extends CommonForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = ['id', 'passwd']; $filters = []; @@ -35,7 +35,7 @@ class LocalForm extends CommonForm $formRules[$field] = in_array($action, ["create", "create_form"]) ? "required|trim|string" : "permit_empty|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/BoardForm.php b/app/Forms/BoardForm.php index ca53e7c..f399bc7 100644 --- a/app/Forms/BoardForm.php +++ b/app/Forms/BoardForm.php @@ -10,22 +10,22 @@ class BoardForm extends CommonForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { - $fields = [ + $fields = [ 'category', 'worker_uid', 'title', 'status', 'content', ]; - $filters = [ + $filters = [ 'user_uid', 'worker_uid', 'category', 'status', ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['user_uid', 'category', 'status']; switch ($action) { case 'create': @@ -89,7 +89,7 @@ class BoardForm extends CommonForm $formRules[$field] = "permit_empty|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; @@ -101,7 +101,7 @@ class BoardForm extends CommonForm case 'worker_uid': foreach ($this->getFormOption_process(service('userservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; diff --git a/app/Forms/CommonForm.php b/app/Forms/CommonForm.php index 5ce8b0a..2569636 100644 --- a/app/Forms/CommonForm.php +++ b/app/Forms/CommonForm.php @@ -20,7 +20,7 @@ abstract class CommonForm { $this->_validation = service('validation'); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $actionButtons = ['view' => ICONS['SEARCH'], 'delete' => ICONS['DELETE']]; $batchjobButtons = []; @@ -141,24 +141,30 @@ abstract class CommonForm try { $dynamicRules = []; - // 0. Ensure all scalar/null inputs are strings to prevent trim() error on PHP 8.1+ - $castToString = function (&$data, $path = '') use (&$castToString) { + // ✅ 0. 데이터 정제: "배열은 절대 문자열 캐스팅 금지" + // - null만 ''로 바꿔 trim(null) 방지 + // - 배열은 그대로 유지 (role 같은 is_array 규칙 깨지지 않게) + $sanitize = function (&$data, $path = '') use (&$sanitize) { foreach ($data as $key => &$value) { $currentField = $path ? "{$path}.{$key}" : $key; - try { - if (is_array($value)) { - $castToString($value, $currentField); - } elseif ($value === null || (is_scalar($value) && !is_string($value))) { - $data[$key] = (string) ($value ?? ''); - } - } catch (\Throwable $e) { - throw new RuntimeException("데이터 정제 중 오류 발생 (필드: {$currentField}): " . $e->getMessage()); + + if (is_array($value)) { + $sanitize($value, $currentField); + continue; } + + if ($value === null) { + $data[$key] = ''; + continue; + } + + // 숫자/불리언은 그대로 둬도 됨. (trim은 문자열 규칙에서만 적용됨) + // 굳이 문자열로 바꾸고 싶으면 여기서 처리 가능하지만, 배열에는 절대 적용하지 말 것. } }; - $castToString($formDatas); + $sanitize($formDatas); - // 1. 현재 서비스의 필드 라벨 정보 로드 (언어 파일 기반) + // 1. 필드 라벨/규칙 $formFields = $this->getFormFields(); $formRules = $this->getFormRules(); @@ -166,88 +172,75 @@ abstract class CommonForm throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 지정된 Form RULE이 없습니다."); } + // ✅ 1.5 배열 원소 규칙(role.*)이 존재할 경우, 부모 필드(role)가 없으면 빈 배열로 보장 + // 이렇게 해두면 엔진 내부에서 role.* 처리 중 trim(null) 류가 재발할 확률이 확 줄어듦 + foreach ($formRules as $fieldKey => $ruleDef) { + $fieldName = is_array($ruleDef) ? $fieldKey : $fieldKey; + + // role.* 형태면 부모 role을 배열로 보장 + if (str_contains($fieldName, '.*')) { + $parent = str_replace('.*', '', $fieldName); + if (!array_key_exists($parent, $formDatas) || $formDatas[$parent] === '') { + $formDatas[$parent] = []; + } elseif (is_string($formDatas[$parent])) { + // 혹시 문자열로 들어오면 CSV → 배열 복원 (공통 방어막) + $formDatas[$parent] = ($formDatas[$parent] === '') + ? [] + : explode(DEFAULTS["DELIMITER_COMMA"], $formDatas[$parent]); + } elseif (!is_array($formDatas[$parent])) { + $formDatas[$parent] = []; + } + } + } + foreach ($formRules as $field => $rule) { try { - // 2. 필드명과 규칙 추출 + // 2. 필드명/규칙 추출 list($field, $rule) = $this->getValidationRule($field, $rule); - // 3. 라벨 결정 로직 (한글 라벨 매핑) + // 3. label 결정 if (isset($formFields[$field])) { $label = $formFields[$field]; } elseif (str_contains($field, '.*')) { - // 배열 검증(role.* 등)의 경우 부모 필드의 라벨을 활용 $parentField = str_replace('.*', '', $field); $label = ($formFields[$parentField] ?? $field) . " 항목"; } else { - $label = $field; // 언어 파일에 정의가 없는 경우 필드명 유지 + $label = $field; } - // 4. [핵심 해결책] 규칙 배열 자체에 label을 포함시킴 - // 이렇게 하면 CI4 엔진이 {field} 자리에 이 label 값을 최우선으로 사용합니다. + // 4. rules 설정 $dynamicRules[$field] = [ 'label' => $label, 'rules' => $rule ]; - // 4.5. Ensure the field exists in formDatas to prevent trim(null) in the engine + // ✅ 4.5 존재 보장 로직 수정 + // - 일반 필드: 없으면 '' 세팅 + // - 배열 원소 필드(role.*): 여기서 만들면 안 됨 (부모 role에서 처리해야 함) if (!array_key_exists($field, $formDatas) && !str_contains($field, '.*')) { $formDatas[$field] = ''; } + } catch (\Throwable $e) { throw new RuntimeException("유효성 검사 규칙 준비 중 오류 발생 (필드: {$field}): " . $e->getMessage()); } } - // 5. 검증 규칙 설정 (인자를 하나만 전달하여 설정 충돌 방지) $this->_validation->setRules($dynamicRules); - // 6. 검증 실행 try { if (!$this->_validation->run($formDatas)) { - // 한글 라벨이 적용된 에러 메시지들을 배열로 가져와 한 줄씩 합침 $errors = $this->_validation->getErrors(); throw new RuntimeException(implode("\n", $errors)); } } catch (\TypeError $e) { - // TypeError(예: trim(null) 등) 발생 시 범인(field) 찾기 시도 - $nullFields = []; - $findNulls = function ($data, $path = '') use (&$findNulls, &$nullFields) { - foreach ($data as $k => $v) { - $curr = $path ? "{$path}.{$k}" : $k; - if (is_array($v)) { - $findNulls($v, $curr); - } elseif ($v === null) { - $nullFields[] = $curr; - } - } - }; - $findNulls($formDatas); - - $culpritInfo = count($nullFields) > 0 ? implode(', ', $nullFields) : "데이터 내 null 없음 (시스템 내 필터 등에 의해 발생 가능성)"; - - $errorMsg = $e->getMessage(); - // 상세 정보 포함 - $debugInfo = "\n--- [상세 디버깅 정보] ---\n"; - $debugInfo .= "범인 의심 필드(null값): " . $culpritInfo . "\n"; - $debugInfo .= "전송된 데이터(전체): " . json_encode($formDatas, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n"; - $debugInfo .= "규칙 정보: " . json_encode($dynamicRules, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n"; - - throw new RuntimeException("검증 도중 타입 오류 발생: {$errorMsg}{$debugInfo}"); + // 너의 상세 디버깅 로직은 그대로 둬도 됨 (생략 가능) + throw new RuntimeException("검증 도중 타입 오류 발생: " . $e->getMessage()); } - // 검증 성공 시 추가 로직 없이 종료 - } catch (\Throwable $e) { - // 이미 RuntimeException으로 포장된 경우 그대로 던짐 - if ($e instanceof RuntimeException) { + if ($e instanceof RuntimeException) throw $e; - } - // 오류 발생 시 디버깅을 위해 로그 기록 - log_message('debug', '--- Validation Error Detail ---'); - log_message('debug', 'Rules: ' . var_export($this->getFormRules(), true)); - log_message('debug', 'Data: ' . var_export($formDatas, true)); - log_message('debug', 'Message: ' . $e->getMessage()); - throw new RuntimeException("유효성 검사 중 시스템 오류 발생: " . $e->getMessage()); } } diff --git a/app/Forms/Customer/ClientForm.php b/app/Forms/Customer/ClientForm.php index 8eaaded..11598b4 100644 --- a/app/Forms/Customer/ClientForm.php +++ b/app/Forms/Customer/ClientForm.php @@ -8,7 +8,7 @@ class ClientForm extends CustomerForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ 'site', @@ -22,7 +22,7 @@ class ClientForm extends CustomerForm 'role', 'status', ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['site', 'role', 'status']; switch ($action) { case 'create': @@ -85,7 +85,7 @@ class ClientForm extends CustomerForm $formRules[$field] = "permit_empty|numeric"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Customer/ServiceForm.php b/app/Forms/Customer/ServiceForm.php index 44f5906..88c2b50 100644 --- a/app/Forms/Customer/ServiceForm.php +++ b/app/Forms/Customer/ServiceForm.php @@ -8,7 +8,7 @@ class ServiceForm extends CustomerForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "site", @@ -34,7 +34,7 @@ class ServiceForm extends CustomerForm 'user_uid', 'status', ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = [ 'site', 'location', @@ -106,7 +106,7 @@ class ServiceForm extends CustomerForm $formRules[$field] = "permit_empty|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; @@ -119,7 +119,7 @@ class ServiceForm extends CustomerForm case 'serverinfo_uid': foreach ($this->getFormOption_process(service('equipment_serverservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getCustomTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; diff --git a/app/Forms/Customer/Wallet/AccountForm.php b/app/Forms/Customer/Wallet/AccountForm.php index d379bf1..e707b4e 100644 --- a/app/Forms/Customer/Wallet/AccountForm.php +++ b/app/Forms/Customer/Wallet/AccountForm.php @@ -8,7 +8,7 @@ class AccountForm extends WalletForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { parent::action_init_process($action, $formDatas); $fields = [ @@ -26,7 +26,7 @@ class AccountForm extends WalletForm "bank", "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['bank', 'status']; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = []; @@ -76,7 +76,7 @@ class AccountForm extends WalletForm $formRules[$field] = "required|valid_date"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Customer/Wallet/CouponForm.php b/app/Forms/Customer/Wallet/CouponForm.php index b7b843b..89946f4 100644 --- a/app/Forms/Customer/Wallet/CouponForm.php +++ b/app/Forms/Customer/Wallet/CouponForm.php @@ -8,7 +8,7 @@ class CouponForm extends WalletForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { parent::action_init_process($action, $formDatas); $fields = [ @@ -22,7 +22,7 @@ class CouponForm extends WalletForm "clientinfo_uid", "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = []; diff --git a/app/Forms/Customer/Wallet/PointForm.php b/app/Forms/Customer/Wallet/PointForm.php index b114de9..0248cf1 100644 --- a/app/Forms/Customer/Wallet/PointForm.php +++ b/app/Forms/Customer/Wallet/PointForm.php @@ -8,7 +8,7 @@ class PointForm extends WalletForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { parent::action_init_process($action, $formDatas); $fields = [ @@ -22,7 +22,7 @@ class PointForm extends WalletForm "clientinfo_uid", "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = []; diff --git a/app/Forms/Equipment/CHASSISForm.php b/app/Forms/Equipment/CHASSISForm.php index 7621a8e..13e5c83 100644 --- a/app/Forms/Equipment/CHASSISForm.php +++ b/app/Forms/Equipment/CHASSISForm.php @@ -8,7 +8,7 @@ class CHASSISForm extends EquipmentForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "title", @@ -28,7 +28,7 @@ class CHASSISForm extends EquipmentForm "diskinfo_uid", "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = ['batchjob' => '일괄처리']; @@ -73,7 +73,7 @@ class CHASSISForm extends EquipmentForm $formRules[$field] = "permit_empty|numeric"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; @@ -85,21 +85,21 @@ class CHASSISForm extends EquipmentForm case "cpuinfo_uid": foreach ($this->getFormOption_process(service('part_cpuservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; case "raminfo_uid": foreach ($this->getFormOption_process(service('part_ramservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; case "diskinfo_uid": foreach ($this->getFormOption_process(service('part_diskservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; diff --git a/app/Forms/Equipment/LineForm.php b/app/Forms/Equipment/LineForm.php index a01868b..21cc6fa 100644 --- a/app/Forms/Equipment/LineForm.php +++ b/app/Forms/Equipment/LineForm.php @@ -8,7 +8,7 @@ class LineForm extends EquipmentForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "type", @@ -23,7 +23,7 @@ class LineForm extends EquipmentForm "protocol", "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['type', 'protocol', 'status']; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = []; @@ -65,7 +65,7 @@ class LineForm extends EquipmentForm $formRules[$field] = "permit_empty|valid_date"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Equipment/ServerForm.php b/app/Forms/Equipment/ServerForm.php index c44620a..d9dac62 100644 --- a/app/Forms/Equipment/ServerForm.php +++ b/app/Forms/Equipment/ServerForm.php @@ -8,7 +8,7 @@ class ServerForm extends EquipmentForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "code", @@ -137,7 +137,7 @@ class ServerForm extends EquipmentForm case 'serviceinfo_uid': foreach ($this->getFormOption_process(service('customer_serviceservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; @@ -162,7 +162,7 @@ class ServerForm extends EquipmentForm case 'switchinfo_uid': foreach ($this->getFormOption_process(service('part_switchservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; // dd($options); @@ -170,7 +170,7 @@ class ServerForm extends EquipmentForm case 'ip': //key=value이 같음주의 foreach ($this->getFormOption_process(service('part_ipservice'), $action, 'ip', $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getTitle()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } //formDatas에 값이 있고, $tempOptions에 없다면 추가(VPN의 Customer IP 경우) if (array_key_exists($field, $formDatas) && $formDatas[$field]) { diff --git a/app/Forms/Equipment/ServerPartForm.php b/app/Forms/Equipment/ServerPartForm.php index 7c07c78..34d535a 100644 --- a/app/Forms/Equipment/ServerPartForm.php +++ b/app/Forms/Equipment/ServerPartForm.php @@ -10,7 +10,7 @@ class ServerPartForm extends EquipmentForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "serverinfo_uid", @@ -76,7 +76,7 @@ class ServerPartForm extends EquipmentForm $formRules[$field] = "permit_empty|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; @@ -92,11 +92,13 @@ class ServerPartForm extends EquipmentForm case 'part_uid': $tempOptions = []; foreach (SERVERPART['ALL_PARTTYPES'] as $type) { - $partService = $this->getPartService($type); - $tempOptions[$type] = ["" => [ - 'value' => "", - 'text' => lang("{$this->getAttribute('class_path')}.TYPE.{$type}") . " 선택", - ]]; + $partService = $this->getPartService($type); + $tempOptions[$type] = [ + "" => [ + 'value' => "", + 'text' => lang("{$this->getAttribute('class_path')}.TYPE.{$type}") . " 선택", + ] + ]; foreach ($this->getFormOption_process($partService, $action, $field, $formDatas) as $tempEntity) { $tempOptions[$type][$tempEntity->getPK()] = [ 'value' => $tempEntity->getPK(), @@ -111,14 +113,14 @@ class ServerPartForm extends EquipmentForm case 'serverinfo_uid': foreach ($this->getFormOption_process(service('equipment_serverservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; case 'serviceinfo_uid': foreach ($this->getFormOption_process(service('customer_clientservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; diff --git a/app/Forms/MylogForm.php b/app/Forms/MylogForm.php index 0c2fb55..c5bc3d7 100644 --- a/app/Forms/MylogForm.php +++ b/app/Forms/MylogForm.php @@ -10,11 +10,11 @@ class MylogForm extends CommonForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = ['title', 'content']; $filters = ['user_uid']; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = $filters; switch ($action) { case 'create': @@ -51,7 +51,7 @@ class MylogForm extends CommonForm $formRules[$field] = "permit_empty|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Part/CPUForm.php b/app/Forms/Part/CPUForm.php index 9d0dbbe..bce4709 100644 --- a/app/Forms/Part/CPUForm.php +++ b/app/Forms/Part/CPUForm.php @@ -8,7 +8,7 @@ class CPUForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "title", @@ -19,7 +19,7 @@ class CPUForm extends PartForm $filters = [ "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; switch ($action) { case 'create': @@ -50,7 +50,7 @@ class CPUForm extends PartForm $formRules[$field] = "required|numeric"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Part/CSForm.php b/app/Forms/Part/CSForm.php index 263062e..c9cef6f 100644 --- a/app/Forms/Part/CSForm.php +++ b/app/Forms/Part/CSForm.php @@ -8,7 +8,7 @@ class CSForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "type", @@ -23,7 +23,7 @@ class CSForm extends PartForm 'type', 'status' ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; switch ($action) { case 'create': @@ -86,7 +86,7 @@ class CSForm extends PartForm $formRules[$field] = "required|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Part/DISKForm.php b/app/Forms/Part/DISKForm.php index e65b5dd..fc75f8d 100644 --- a/app/Forms/Part/DISKForm.php +++ b/app/Forms/Part/DISKForm.php @@ -8,7 +8,7 @@ class DISKForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "title", @@ -20,7 +20,7 @@ class DISKForm extends PartForm $filters = [ "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; switch ($action) { case 'create': @@ -55,7 +55,7 @@ class DISKForm extends PartForm $formRules[$field] = "required|numeric"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Part/IPForm.php b/app/Forms/Part/IPForm.php index 34ae341..1f780ee 100644 --- a/app/Forms/Part/IPForm.php +++ b/app/Forms/Part/IPForm.php @@ -8,7 +8,7 @@ class IPForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "lineinfo_uid", @@ -24,7 +24,7 @@ class IPForm extends PartForm "lineinfo_uid", 'status', ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = ['batchjob' => '일괄처리']; @@ -102,7 +102,7 @@ class IPForm extends PartForm $formRules[$field] = "required|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; @@ -114,14 +114,14 @@ class IPForm extends PartForm case 'lineinfo_uid': foreach ($this->getFormOption_process(service('equipment_lineservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; case 'old_clientinfo_uid': foreach ($this->getFormOption_process(service('customer_clientservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } // dd($tempOptions); $options['options'] = $tempOptions; diff --git a/app/Forms/Part/PartForm.php b/app/Forms/Part/PartForm.php index f7338b5..9ef8ad1 100644 --- a/app/Forms/Part/PartForm.php +++ b/app/Forms/Part/PartForm.php @@ -42,14 +42,14 @@ abstract class PartForm extends CommonForm case 'serviceinfo_uid': foreach ($this->getFormOption_process(service('customer_serviceservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; case 'serverinfo_uid': foreach ($this->getFormOption_process(service('equipment_serverservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; diff --git a/app/Forms/Part/RAMForm.php b/app/Forms/Part/RAMForm.php index 08779a8..fed41d7 100644 --- a/app/Forms/Part/RAMForm.php +++ b/app/Forms/Part/RAMForm.php @@ -8,7 +8,7 @@ class RAMForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "title", @@ -19,7 +19,7 @@ class RAMForm extends PartForm $filters = [ "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; switch ($action) { case 'create': @@ -50,7 +50,7 @@ class RAMForm extends PartForm $formRules[$field] = "required|numeric"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Part/SOFTWAREForm.php b/app/Forms/Part/SOFTWAREForm.php index 8afaa88..9cc6370 100644 --- a/app/Forms/Part/SOFTWAREForm.php +++ b/app/Forms/Part/SOFTWAREForm.php @@ -8,7 +8,7 @@ class SOFTWAREForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "title", @@ -19,7 +19,7 @@ class SOFTWAREForm extends PartForm $filters = [ "status", ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status']; switch ($action) { case 'create': @@ -47,7 +47,7 @@ class SOFTWAREForm extends PartForm { switch ($field) { default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/Part/SWITCHForm.php b/app/Forms/Part/SWITCHForm.php index 3e6cdec..e61f1c7 100644 --- a/app/Forms/Part/SWITCHForm.php +++ b/app/Forms/Part/SWITCHForm.php @@ -8,7 +8,7 @@ class SWITCHForm extends PartForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { $fields = [ "code", @@ -20,7 +20,7 @@ class SWITCHForm extends PartForm 'serverinfo_uid', 'status' ]; - $indexFilter = $filters; + $indexFilter = $filters; $batchjobFilters = ['status',]; $actionButtons = ['view' => ICONS['SEARCH']]; $batchjobButtons = ['batchjob' => '일괄처리']; @@ -72,7 +72,7 @@ class SWITCHForm extends PartForm $formRules[$field] = "required|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Forms/PaymentForm.php b/app/Forms/PaymentForm.php index 709e565..c391695 100644 --- a/app/Forms/PaymentForm.php +++ b/app/Forms/PaymentForm.php @@ -10,9 +10,9 @@ class PaymentForm extends CommonForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { - $fields = [ + $fields = [ "serviceinfo_uid", "title", "amount", @@ -23,7 +23,7 @@ class PaymentForm extends CommonForm "content", ]; $filters = ['user_uid', 'clientinfo_uid', 'serviceinfo_uid', 'status', 'billing', 'pay']; - $indexFilter = ['clientinfo_uid', 'serviceinfo_uid', 'status', 'billing', 'pay']; + $indexFilter = ['clientinfo_uid', 'serviceinfo_uid', 'status', 'billing', 'pay']; $batchjobFilters = ['status']; $actionButtons = ['paid' => '결제', 'view' => ICONS['SEARCH']]; $batchjobButtons = ['batchjob' => '일괄결제', 'invoice' => '청구서발행']; @@ -103,7 +103,7 @@ class PaymentForm extends CommonForm $formRules[$field] = "permit_empty|trim|string"; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; @@ -116,7 +116,7 @@ class PaymentForm extends CommonForm case 'serviceinfo_uid': foreach ($this->getFormOption_process(service('customer_serviceservice'), $action, $field, $formDatas) as $tempEntity) { $tempOptions[$tempEntity->getPK()] = $tempEntity->getTitle(); - // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; + // $options['attributes'][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_COMMA'], $tempEntity->getRole())]; } $options['options'] = $tempOptions; break; diff --git a/app/Forms/UserForm.php b/app/Forms/UserForm.php index 95351a8..76a4da6 100644 --- a/app/Forms/UserForm.php +++ b/app/Forms/UserForm.php @@ -10,9 +10,9 @@ class UserForm extends CommonForm { parent::__construct(); } - public function action_init_process(string $action, array $formDatas = []): void + public function action_init_process(string $action, array &$formDatas = []): void { - $fields = [ + $fields = [ 'id', 'passwd', 'confirmpassword', @@ -21,8 +21,8 @@ class UserForm extends CommonForm 'mobile', 'role' ]; - $filters = ['role', 'status']; - $indexFilter = $filters; + $filters = ['role', 'status']; + $indexFilter = $filters; $batchjobFilters = ['status']; switch ($action) { case 'create': @@ -67,7 +67,7 @@ class UserForm extends CommonForm $formRules['role.*'] = 'trim|in_list[manager,cloudflare,firewall,security,director,master]'; break; default: - $formRules = parent::getFormRule($action, $field, $formRules); + $formRules = parent::getFormRule($action, $field, $formRules); break; } return $formRules; diff --git a/app/Helpers/CommonHelper.php b/app/Helpers/CommonHelper.php index 81cf1f8..b874dbd 100644 --- a/app/Helpers/CommonHelper.php +++ b/app/Helpers/CommonHelper.php @@ -10,7 +10,9 @@ abstract class CommonHelper { use UtilTrait; private array $_attributes = []; - protected function __construct() {} + protected function __construct() + { + } final public function setAttributes(array $attributes): void { $this->_attributes = $attributes; @@ -168,7 +170,7 @@ abstract class CommonHelper break; case 'role': if (!is_array($value)) { //배열이 아니면 - $value = explode(DEFAULTS['DELIMITER_ROLE'], $value); + $value = explode(DEFAULTS['DELIMITER_COMMA'], $value); } $roles = []; foreach ($value as $key) { diff --git a/app/Helpers/Customer/ClientHelper.php b/app/Helpers/Customer/ClientHelper.php index 250b818..47ff54b 100644 --- a/app/Helpers/Customer/ClientHelper.php +++ b/app/Helpers/Customer/ClientHelper.php @@ -21,19 +21,32 @@ class ClientHelper extends CustomerHelper $form = implode(" ", $forms); break; case 'role': - $currentRoles = is_array($value) - ? array_map('strtolower', array_map(fn($item) => trim((string) ($item ?? ''), " \t\n\r\0\x0B\""), $value)) - : []; + // 1) value가 배열이면 그대로, 문자열이면 CSV를 배열로 변환 + if (is_string($value)) { + $value = trim($value, " \t\n\r\0\x0B\""); + $value = ($value === '') ? [] : explode(DEFAULTS["DELIMITER_COMMA"], $value); + } elseif (!is_array($value)) { + $value = []; + } + + // 2) 정리 + $currentRoles = array_values(array_filter( + array_map( + fn($item) => strtolower(trim((string) ($item ?? ''), " \t\n\r\0\x0B\"")), + $value + ) + )); + $form = ''; - //Form페이지에서는 맨앞에것 제외하기 위함 array_shift($viewDatas['formOptions'][$field]['options']); foreach ($viewDatas['formOptions'][$field]['options'] as $key => $label) { - $checked = in_array(strtolower(trim($key)), $currentRoles); + $checked = in_array(strtolower(trim((string) $key)), $currentRoles, true); $form .= ''; } + // dd($form); break; default: $form = parent::getFieldForm($field, $value, $viewDatas, $extras); diff --git a/app/Libraries/AuthContext.php b/app/Libraries/AuthContext.php index 4506ed3..680bd0e 100644 --- a/app/Libraries/AuthContext.php +++ b/app/Libraries/AuthContext.php @@ -25,7 +25,7 @@ class AuthContext $this->session = \Config\Services::session(); } - private function getAuthInfo(string $key = ""): array|string|null + private function getAuthInfo(string $key = ""): array|int|string|null { $authInfo = $this->session->get(self::SESSION_AUTH_INFO); if ($key) { @@ -38,9 +38,15 @@ class AuthContext // Public Accessors (AuthService에서 이동) // ---------------------------------------------------- - public function getUID(): string|null + public function getUID(): int { - return $this->getAuthInfo('uid'); + $uid = $this->getAuthInfo('uid'); + + if ($uid === null || $uid === '') { + throw new \RuntimeException('Not logged in'); + } + + return (int) $uid; } public function getID(): string|null @@ -98,7 +104,7 @@ class AuthContext { $this->session->set(self::SESSION_IS_LOGIN, true); $this->session->set(self::SESSION_AUTH_INFO, [ - 'uid' => $entity->getPK(), + 'uid' => (int) $entity->getPK(), 'id' => $entity->getID(), 'name' => $entity->getTitle(), 'role' => $entity->getRole() diff --git a/app/Services/Auth/GoogleService.php b/app/Services/Auth/GoogleService.php index 3f628c1..ca2b909 100644 --- a/app/Services/Auth/GoogleService.php +++ b/app/Services/Auth/GoogleService.php @@ -35,7 +35,7 @@ class GoogleService extends AuthService { try { //입력값 검증 - $this->getFormService()->validate($formDatas); + $this->getActionForm()->validate($formDatas); $this->socket->setToken($formDatas['access_code']); $sns_entity = $this->socket->signup(); // local db 사용와의 연결 확인 diff --git a/app/Services/Auth/LocalService.php b/app/Services/Auth/LocalService.php index 1d30578..3beaa3e 100644 --- a/app/Services/Auth/LocalService.php +++ b/app/Services/Auth/LocalService.php @@ -31,9 +31,9 @@ class LocalService extends AuthService } protected function login_process(array $formDatas): UserEntity { - $this->getFormService()->action_init_process('login', $formDatas); + $this->getActionForm()->action_init_process('login', $formDatas); //입력값 검증 - $this->getFormService()->validate($formDatas); + $this->getActionForm()->validate($formDatas); //로그인 정보확인 $entity = $this->getEntity(['id' => $formDatas['id'], 'status' => 'AVAILABLE']); if (!$entity instanceof UserEntity) { diff --git a/app/Services/CommonService.php b/app/Services/CommonService.php index 3f73842..01f1f67 100644 --- a/app/Services/CommonService.php +++ b/app/Services/CommonService.php @@ -59,7 +59,7 @@ abstract class CommonService } } - public function getFormService(): mixed + final public function getActionForm(): mixed { if ($this->_form === null && $this->formClass) { $this->_form = new $this->formClass(); @@ -254,14 +254,14 @@ abstract class CommonService protected function create_process(array $formDatas): CommonEntity { try { - $formService = $this->getFormService(); - if ($formService) { - $formService->action_init_process('create', $formDatas); - $formService->validate($formDatas); + $actionForm = $this->getActionForm(); + if ($actionForm instanceof CommonForm) { + $actionForm->action_init_process('create', $formDatas); + $actionForm->validate($formDatas); } $entityClass = $this->getEntityClass(); $entity = new $entityClass($formDatas); - dd($entity); + // dd($entity); if (!$entity instanceof $entityClass) { throw new RuntimeException("Return Type은 {$entityClass}만 가능"); } @@ -274,30 +274,36 @@ abstract class CommonService final public function create(array $formDatas): CommonEntity { return $this->dbTransaction(function () use ($formDatas) { - $formDatas['user_uid'] = $this->getAuthContext()->getUID(); + $formDatas['user_uid'] = (int) $this->getAuthContext()->getUID(); return $this->create_process($formDatas); }, __FUNCTION__); } //수정용 + protected function modify_process_fieldhook(string $field, $value, array $formDatas): array + { + return $formDatas; + } protected function modify_process($entity, array $formDatas): CommonEntity { try { - if ($formService = $this->getFormService()) { - $formService->action_init_process('modify', $formDatas); + $actionForm = $this->getActionForm(); + if ($actionForm instanceof CommonForm) { + $actionForm->action_init_process('modify', $formDatas); + foreach ($formDatas as $field => $value) { + $formDatas = $this->modify_process_fieldhook($field, $value, $formDatas); + } + $actionForm->validate($formDatas); // ✅ 여기서 검증 } + // 검증 통과 후 엔티티 반영 $entity->fill($formDatas); if (!$entity->hasChanged()) { return $entity; } - $formService = $this->getFormService(); - if ($formService) { - $formDatas = $entity->toArray(); - $formService->validate($formDatas); - } return $this->save_process($entity); + } catch (\Throwable $e) { - throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:" . $e->getMessage() . "\n" . var_export($entity)); + throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:" . $e->getMessage() . "\n" . var_export($entity, true)); } } @@ -308,7 +314,7 @@ abstract class CommonService if (!$entity) { throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다."); } - $formDatas['user_uid'] = $this->getAuthContext()->getUID(); + $formDatas['user_uid'] = (int) $this->getAuthContext()->getUID(); return $this->modify_process($entity, $formDatas); }, __FUNCTION__); } diff --git a/app/Services/Customer/ClientService.php b/app/Services/Customer/ClientService.php index ee975b1..0a67550 100644 --- a/app/Services/Customer/ClientService.php +++ b/app/Services/Customer/ClientService.php @@ -46,4 +46,30 @@ class ClientService extends CustomerService $this->model->orderBy("site ASC,name ASC"); parent::setOrderBy($field, $value); } + + protected function modify_process_fieldhook(string $field, $value, array $formDatas): array + { + switch ($field) { + case 'role': + if (is_string($value)) { + $value = ($value === '') ? [] : explode(DEFAULTS["DELIMITER_COMMA"], $value); + } elseif (!is_array($value)) { + $value = []; + } + + $value = array_values(array_filter(array_map( + fn($v) => trim((string) ($v ?? ''), " \t\n\r\0\x0B\""), + $value + ))); + + $formDatas[$field] = $value; + break; + + default: + $formDatas = parent::modify_process_fieldhook($field, $value, $formDatas); + break; + } + return $formDatas; + } + } diff --git a/app/Views/admin/modify_form.php b/app/Views/admin/modify_form.php index 3b7ac34..5d69c56 100644 --- a/app/Views/admin/modify_form.php +++ b/app/Views/admin/modify_form.php @@ -10,7 +10,9 @@ $label): ?>