dbmsv4 init...4

This commit is contained in:
최준흠 2026-01-30 14:38:57 +09:00
parent 897ddeab23
commit 316df8be6f
49 changed files with 279 additions and 226 deletions

View File

@ -11,7 +11,7 @@ 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']]);
//서비스별 서버리스트
@ -19,8 +19,8 @@ class ServiceCell extends CustomerCell
$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,

View File

@ -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,

View File

@ -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,8 +35,8 @@ 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'],

View File

@ -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(),
]
]);

View File

@ -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(),
],
]);

View File

@ -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,
]

View File

@ -312,8 +312,8 @@ define("ROLE", [
//Default값 정의
define('DEFAULTS', [
'DELIMITER_FILE' => "||",
'DELIMITER_ROLE' => ",",
'DELIMITER_PIPE' => "||",
'DELIMITER_COMMA' => ",",
'INDEX_PERPAGE' => 20,
'STATUS' => STATUS['AVAILABLE']
]);

View File

@ -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) {

View File

@ -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());
}
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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)) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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 = [];

View File

@ -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 = [];

View File

@ -10,7 +10,7 @@ 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 = [
'category',
@ -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;

View File

@ -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 ?? '');
$sanitize($value, $currentField);
continue;
}
} catch (\Throwable $e) {
throw new RuntimeException("데이터 정제 중 오류 발생 (필드: {$currentField}): " . $e->getMessage());
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;
// 너의 상세 디버깅 로직은 그대로 둬도 됨 (생략 가능)
throw new RuntimeException("검증 도중 타입 오류 발생: " . $e->getMessage());
}
}
};
$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}");
}
// 검증 성공 시 추가 로직 없이 종료
} 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());
}
}

View File

@ -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',

View File

@ -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",
@ -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;

View File

@ -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 = [

View File

@ -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 = [

View File

@ -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 = [

View File

@ -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",
@ -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;

View File

@ -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",

View File

@ -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]) {

View File

@ -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",
@ -93,10 +93,12 @@ class ServerPartForm extends EquipmentForm
$tempOptions = [];
foreach (SERVERPART['ALL_PARTTYPES'] as $type) {
$partService = $this->getPartService($type);
$tempOptions[$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;

View File

@ -10,7 +10,7 @@ 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'];

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",
@ -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;

View File

@ -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;

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -10,7 +10,7 @@ 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 = [
"serviceinfo_uid",
@ -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;

View File

@ -10,7 +10,7 @@ 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 = [
'id',

View File

@ -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) {

View File

@ -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 .= '<label class="me-3">';
$form .= form_checkbox('role[]', $key, $checked, ['id' => "role_{$key}", ...$extras]);
$form .= " {$label}";
$form .= '</label>';
}
// dd($form);
break;
default:
$form = parent::getFieldForm($field, $value, $viewDatas, $extras);

View File

@ -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()

View File

@ -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 사용와의 연결 확인

View File

@ -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) {

View File

@ -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__);
}

View File

@ -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;
}
}

View File

@ -10,7 +10,9 @@
</tr>
<?php foreach ($viewDatas['formFields'] as $field => $label): ?>
<tr>
<th nowrap class="text-end bg-light" width="20%"><?= $viewDatas['helper']->getFieldLabel($field, $label, $viewDatas) ?></th>
<th nowrap class="text-end bg-light" width="20%">
<?= $viewDatas['helper']->getFieldLabel($field, $label, $viewDatas) ?>
</th>
<td nowrap class="text-start">
<?= $viewDatas['helper']->getFieldForm($field, old($field) ?? ($viewDatas['entity']->$field ?? null), $viewDatas) ?>
<div><?= validation_show_error($field); ?></div>