trafficmonitor init...2

This commit is contained in:
choi.jh 2025-11-06 16:51:52 +09:00
parent f430183704
commit 65dff253d8
32 changed files with 615 additions and 557 deletions

View File

@ -28,32 +28,29 @@ $routes->group('', ['namespace' => 'App\Controllers'], function ($routes) {
$routes->group('admin', ['namespace' => 'App\Controllers\Admin', 'filter' => 'authFilter:manager'], function ($routes) {
$routes->get('/', 'Home::index');
$routes->group('user', ['namespace' => 'App\Controllers\Admin'], function ($routes) {
$routes->get('/', 'UserController::index', ['filter' => 'authFilter:master']);
$routes->get('create', 'UserController::create_form', ['filter' => 'authFilter:master']);
$routes->post('create', 'UserController::create', ['filter' => 'authFilter:master']);
$routes->get('modify/(:num)', 'UserController::modify_form/$1', ['filter' => 'authFilter:master']);
$routes->post('modify/(:num)', 'UserController::modify/$1', ['filter' => 'authFilter:master']);
$routes->get('view/(:num)', 'UserController::view/$1', ['filter' => 'authFilter:manager']);
$routes->get('/', 'UserController::index');
$routes->get('create', 'UserController::create_form');
$routes->post('create', 'UserController::create');
$routes->get('modify/(:num)', 'UserController::modify_form/$1');
$routes->post('modify/(:num)', 'UserController::modify/$1');
$routes->get('view/(:num)', 'UserController::view/$1');
$routes->get('delete/(:num)', 'UserController::delete/$1', ['filter' => 'authFilter:master']);
$routes->get('toggle/(:num)/(:any)', 'UserController::toggle/$1/$2', ['filter' => 'authFilter:master']);
$routes->post('batchjob', 'UserController::batchjob', ['filter' => 'authFilter:master']);
$routes->post('batchjob_delete', 'UserController::batchjob_delete', ['filter' => 'authFilter:master']);
$routes->get('download/(:alpha)', 'UserController::download/$1', ['filter' => 'authFilter:master']);
$routes->get('profile/(:num)', 'UserController::profile_form/$1', ['filter' => 'authFilter:manager']);
$routes->post('profile/(:num)', 'UserController::profile/$1', ['filter' => 'authFilter:manager']);
$routes->group('traffic', ['namespace' => 'App\Controllers\Admin'], function ($routes) {
$routes->get('/', 'TrafficController::index');
$routes->get('create', 'TrafficController::create_form');
$routes->post('create', 'TrafficController::create');
$routes->get('modify/(:num)', 'TrafficController::modify_form/$1');
$routes->post('modify/(:num)', 'TrafficController::modify/$1');
$routes->get('view/(:num)', 'TrafficController::view/$1');
$routes->get('delete/(:num)', 'TrafficController::delete/$1');
$routes->get('toggle/(:num)/(:any)', 'TrafficController::toggle/$1/$2');
$routes->post('batchjob', 'TrafficController::batchjob');
$routes->post('batchjob_delete', 'TrafficController::batchjob_delete');
$routes->get('download/(:alpha)', 'TrafficController::download/$1');
});
$routes->get('download/(:alpha)', 'UserController::download/$1');
});
$routes->group('traffic', ['namespace' => 'App\Controllers\Admin'], function ($routes) {
$routes->get('/', 'TrafficController::index');
$routes->get('create', 'TrafficController::create_form');
$routes->post('create', 'TrafficController::create');
$routes->get('modify/(:num)', 'TrafficController::modify_form/$1');
$routes->post('modify/(:num)', 'TrafficController::modify/$1');
$routes->get('view/(:num)', 'TrafficController::view/$1');
$routes->get('delete/(:num)', 'TrafficController::delete/$1');
$routes->get('toggle/(:num)/(:any)', 'TrafficController::toggle/$1/$2');
$routes->post('batchjob', 'TrafficController::batchjob');
$routes->post('batchjob_delete', 'TrafficController::batchjob_delete');
$routes->get('download/(:alpha)', 'TrafficController::download/$1');
});
});

View File

@ -40,8 +40,7 @@ class Services extends BaseService
return static::getSharedInstance(__FUNCTION__);
} else {
return new LocalService(
new \App\Models\UserModel(),
new \App\Forms\Auth\LocalForm()
new \App\Models\UserModel()
);
}
}
@ -52,8 +51,7 @@ class Services extends BaseService
return static::getSharedInstance(__FUNCTION__);
} else {
return new LocalService(
new \App\Models\UserModel(),
new \App\Forms\Auth\LocalForm()
new \App\Models\UserModel()
);
}
}
@ -64,7 +62,6 @@ class Services extends BaseService
}
return new GoogleService(
new \App\Models\USerModel(),
new \App\Forms\Auth\GoogleForm(),
new \App\Libraries\MySocket\GoogleSocket\CURL()
);
}
@ -75,8 +72,7 @@ class Services extends BaseService
return static::getSharedInstance(__FUNCTION__);
}
return new UserService(
new \App\Models\USerModel(),
new \App\Forms\UserForm()
new \App\Models\USerModel()
);
}
@ -87,7 +83,6 @@ class Services extends BaseService
}
return new TrafficService(
new \App\Models\TrafficModel(),
new \App\Forms\TrafficForm()
);
}
}

View File

@ -15,4 +15,8 @@ abstract class AdminController extends CommonController
parent::initController($request, $response, $logger);
$this->addActionPaths(self::PATH);
}
final protected function getLayout(): string
{
return self::PATH;
}
}

View File

@ -23,9 +23,9 @@ class UserController extends AdminController
{
parent::initController($request, $response, $logger);
if ($this->service === null) {
$this->service = service('localauth');
$this->service = service('userservice');
}
$this->addActionPaths(self::PATH);
$this->addActionPaths($this::PATH);
}
protected function getFormRule(string $action, string $field, string $rule): array
{
@ -37,13 +37,10 @@ class UserController extends AdminController
return parent::getFormRule($action, $field, $rule);
}
//Index,FieldForm관련.
protected function create_process(string $action, array $viewDatas): string|RedirectResponse
protected function create_process(): UserEntity
{
//요청 데이터를 DTO 객체로 변환
$dto = new UserDTO($this->request->getPost());
$this->doValidation($action);
$entity = $this->service->create($dto);
return redirect()
->route('admin/user/view', [$entity->getPK()])
->with('message', "{$entity->getTitle()} 계정이 등록되었습니다.");
return $this->service->create($dto);
}
}

View File

@ -8,6 +8,7 @@ use App\Entities\UserEntity;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Validation\Exceptions\ValidationException;
use Psr\Log\LoggerInterface;
abstract class AuthController extends CommonController
@ -20,35 +21,44 @@ abstract class AuthController extends CommonController
}
abstract protected function login_process(): UserEntity;
abstract protected function logout_process(): void;
//로그인화면
public function login_form_process(array $viewDatas = []): array
{
return $viewDatas;
}
public function login_form(): string|RedirectResponse
public function login_form_process(): void {}
final public function login_form(): string|RedirectResponse
{
$action = __FUNCTION__;
try {
//초기화
$action = __FUNCTION__;
$viewDatas = $this->action_init_process($action);
$viewDatas = $this->login_form_process($viewDatas);
return $this->action_post_process($action, $viewDatas);
$this->action_init_process($action);
$this->login_form_process();
$this->action_render_process($action);
// dd($this->getViewDatas());
} catch (\Exception $e) {
$viewDatas[self::ACTION_RESULT] = 'error';
$viewDatas[self::ACTION_MESSAGE] = $e->getMessage();
return $this->action_post_process($action, $viewDatas);
$this->addViewDatas(self::ACTION_RESULT, 'error');
$this->addViewDatas(self::ACTION_MESSAGE, $e->getMessage());
//오류발생시 리디렉션 대신 폼 뷰를 다시 렌더링하도록 action_view_process 호출
}
return $this->action_result_process(
$this->getActionPaths(),
$action,
$this->getViewDatas()
);
}
//로그인처리
public function login(): RedirectResponse
final public function login(): RedirectResponse
{
$action = __FUNCTION__;
try {
$action = __FUNCTION__;
$viewDatas = $this->action_init_process($action);
$this->action_init_process($action);
$this->login_process();
return redirect()->to($this->authService->popPreviousUrl())->with('success', '로그인이 완료되었습니다.');
$redirect_url = $this->authService->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths());
return redirect()->to($redirect_url)->with('success', MESSAGES['LOGIN']);
} catch (ValidationException $e) {
// 검증 실패 시 폼으로 돌아가서 오류 메시지 표시
log_message('error', $e->getMessage());
return redirect()->back()->withInput()->with('errors', $e->getMessage());
} catch (\Exception $e) {
log_message('error', $e->getMessage());
return redirect()->back()->withInput()->with('error', $e->getMessage());
// return redirect()->to($this->getMyAuth()->popPreviousUrl())->with('error', $e->getMessage());
}
@ -59,10 +69,11 @@ abstract class AuthController extends CommonController
try {
$this->logout_process();
// 홈페이지로 리다이렉트
return redirect()->route('/')->with('error', MESSAGES['LOGOUT']);
$redirect_url = $this->authService->popPreviousUrl() ?? "/";
return redirect()->route($redirect_url)->with('error', MESSAGES['LOGOUT']);
} catch (\Exception $e) {
log_message("error", $e->getMessage());
return redirect()->back()->with('error', "로그아웃 중 오류가 발생했습니다.");
return redirect()->back()->withInput()->with('error', "로그아웃 중 오류가 발생했습니다.");
}
}
}

View File

@ -22,17 +22,16 @@ class GoogleController extends AuthController
}
$this->addActionPaths(self::PATH);
}
public function login_form_process(array $viewDatas = []): array
public function login_form_process(): void
{
//구글 로그인 BUTTON용
$viewDatas['SNSButton'] = anchor($this->service->socket->createAuthUrl(), ICONS['GOOGLE'] . 'Google 로그인', ["class" => "btn-google"]);
return $viewDatas;
$this->addViewDatas('SNSButton', anchor($this->service->socket->createAuthUrl(), ICONS['GOOGLE'] . 'Google 로그인', ["class" => "btn-google"]));
}
//로그인처리
protected function login_process(): UserEntity
{
$formDatas = $this->doValidation(__FUNCTION__);
$formDatas = $this->doValidation($this->getViewDatas('action'));
if (!array_key_exists('access_code', $formDatas) || !$formDatas['access_code']) {
throw new \Exception("구글 로그인 실패");
}

View File

@ -2,6 +2,7 @@
namespace App\Controllers\Auth;
use App\DTOs\Auth\LocalDTO;
use App\Entities\UserEntity;
use App\Services\Auth\LocalService;
use CodeIgniter\HTTP\RequestInterface;
@ -26,8 +27,9 @@ class LocalController extends AuthController
//로그인처리
protected function login_process(): UserEntity
{
$formDatas = $this->doValidation(__FUNCTION__);
return $this->service->login($formDatas);
//요청 데이터를 DTO 객체로 변환
$dto = new LocalDTO($this->request->getPost());
return $this->service->login($dto);
}
protected function logout_process(): void
{

View File

@ -3,14 +3,13 @@
namespace App\Controllers;
use App\Controllers\BaseController;
use App\DTOs\AuthDTO;
use App\Services\CommonService;
use App\DTOs\CertificationDTO;
use App\Traits\LogTrait;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Validation\Validation;
use CodeIgniter\Validation\Exceptions\ValidationException;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Html;
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
@ -19,30 +18,45 @@ use Psr\Log\LoggerInterface;
abstract class CommonController extends BaseController
{
use LogTrait;
protected const ACTION_PATH = "action_path";
protected const ACTION_VIEW_FILE = "action_view_file";
protected const ACTION_RESULT = "action_result";
protected const ACTION_MESSAGE = "action_message";
const ACTION_RESULT = "action_result";
const ACTION_MESSAGE = "action_message";
private array $_action_paths = [];
protected $authService = null;
private array $_viewDatas = [];
protected $service = null;
protected $myAuth = null;
protected $authService = null;
protected $myCertification = null;
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
//로그인관련
$this->authService = service('myauth');
$this->myAuth = AuthDTO::fromByAuthService($this->authService);
$this->myCertification = CertificationDTO::fromByAuthService($this->authService);
}
protected function getLayout(): string
{
return 'empty';
}
final public function addActionPaths(string $path)
{
$this->_action_paths[] = $path;
}
final public function getActionPaths(): array
final public function getActionPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string
{
return $this->_action_paths;
return $isArray ? $this->_action_paths : implode($delimeter, $this->_action_paths);
}
final protected function doValidation(string $action): array
final public function addViewDatas(string $key, mixed $value)
{
$this->_viewDatas[$key] = $value;
}
final public function getViewDatas(?string $key = null): mixed
{
if ($key === null) {
return $this->_viewDatas;
}
return $this->_viewDatas[$key] ?? null;
}
//공통 필수기능
protected function doValidation(string $action): array
{
$dynamicRules = [];
foreach ($this->service->getFormRules($action) as $field => $rule) {
@ -58,7 +72,6 @@ abstract class CommonController extends BaseController
}
return $this->validator->getValidated();
}
//공통 필수기능
protected function getFormRule(string $action, string $field, string $rule): array
{
switch ($field) {
@ -67,85 +80,83 @@ abstract class CommonController extends BaseController
}
return array($field, $rule);
}
protected function action_init_process(string $action, array $viewDatas = []): array
protected function action_init_process(string $action): void
{
$viewDatas['action'] = $action;
$viewDatas[self::ACTION_PATH] = $this->getActionPaths();
$viewDatas[self::ACTION_VIEW_FILE] = $this->request->getVar('ActionTemplate') ?? $viewDatas['action'];
$viewDatas['formFields'] = $this->service->getFormFields();
$viewDatas['formFilters'] = $this->service->getFormFilters();
$viewDatas['formRules'] = $this->service->getFormRules($viewDatas['action']);
$viewDatas['formOptions'] = $this->service->getFormOptions($viewDatas['action']);
return $viewDatas;
$this->addViewDatas('action', $action);
$this->addViewDatas('myCertification', $this->myCertification);
$this->addViewDatas('layout', $this->getLayout());
$this->addViewDatas('serviceForm', $this->service->getFormService());
$this->addViewDatas('formFields', $this->service->getFormFields());
$this->addViewDatas('formFilters', $this->service->getFormFilters());
$this->addViewDatas('formRules', $this->service->getFormRules($action));
$this->addViewDatas('formOptions', $this->service->getFormOptions($action));
}
protected function action_post_process(string $action, array $viewDatas): string|RedirectResponse
protected function action_render_process(string $action): void
{
$this->addViewDatas('helper', $this->service->getHelper($action, $this->getViewDatas()));
}
protected function action_result_process(array $view_paths, string $view_file, array $viewDatas): string
{
$view_paths = array_key_exists(self::ACTION_PATH, $viewDatas) ? $viewDatas[self::ACTION_PATH] : $this->getActionPaths();
$lastest_path = array_pop($view_paths); //paths는 마지막을 뺀 앞단까지만 남음
switch ($action) {
case 'create_form':
case 'modify_form':
case 'login_form':
// ✅ 중간 안내 화면으로
// return view('posts/success_redirect', [
// 'message' => '게시글이 성공적으로 등록되었습니다.',
// 'redirectUrl' => route_to('posts_list')
// ]);
// 중요한 작업 (결제 완료, 오류 등) → “로딩 페이지(View)”로 안내 후 JS redirect
$full_path = implode(DIRECTORY_SEPARATOR, [
...$view_paths,
$this->request->getVar('ActionTemplate') ?? $lastest_path,
array_key_exists(self::ACTION_VIEW_FILE, $viewDatas) ? $viewDatas[self::ACTION_VIEW_FILE] : $action
]);
$view_datas = [
'control' => $viewDatas,
'forms' => ['attributes' => ['method' => "post",], 'hiddens' => []],
];
helper(['form', __FUNCTION__]);
$result = view($full_path, ['viewDatas' => $view_datas]);
break;
default:
// ✅ Flashdata로 성공 메시지 저장
// 일반 CRUD (create/update/delete) → Flashdata + redirect()
$message = array_key_exists(self::ACTION_MESSAGE, $viewDatas) ?: static::class . "/{$action}이 완료되었습니다.";
session()->setFlashdata($viewDatas[self::ACTION_RESULT], $message);
$result = redirect()->route(implode(DIRECTORY_SEPARATOR, $view_paths))->with('message', $message);
break;
}
return $result;
// ✅ 중간 안내 화면으로
// return view('posts/success_redirect', [
// 'message' => '게시글이 성공적으로 등록되었습니다.',
// 'redirectUrl' => route_to('posts_list')
// ]);
// 중요한 작업 (결제 완료, 오류 등) → “로딩 페이지(View)”로 안내 후 JS redirect
$full_path = implode(DIRECTORY_SEPARATOR, [
...$view_paths,
$this->request->getVar('ActionTemplate') ?? $lastest_path,
$view_file
]);
$view_datas = [
'control' => $viewDatas,
'forms' => ['attributes' => ['method' => "post",], 'hiddens' => []],
];
helper(['form', __FUNCTION__]);
return view($full_path, ['viewDatas' => $view_datas]);
}
protected function create_form_process(array $viewDatas): array
{
return $viewDatas;
}
public function create_form(): string|RedirectResponse
protected function create_form_process(): void {}
final public function create_form(): string|RedirectResponse
{
$action = __FUNCTION__;
try {
//초기화
$action = __FUNCTION__;
$viewDatas = $this->action_init_process($action);
$viewDatas = $this->create_form_process($viewDatas);
return $this->action_post_process($action, $viewDatas);
$this->action_init_process($action);
$this->create_form_process();
$this->action_render_process($action);
// dd($this->getViewDatas());
} catch (\Exception $e) {
$viewDatas[self::ACTION_RESULT] = 'error';
$viewDatas[self::ACTION_MESSAGE] = $e->getMessage();
//리디렉션 대신 폼 뷰를 다시 렌더링하도록 form_post_process 호출
return $this->action_post_process($action, $viewDatas);
log_message('error', $e->getMessage());
$this->addViewDatas(self::ACTION_RESULT, 'error');
$this->addViewDatas(self::ACTION_MESSAGE, $e->getMessage());
//오류발생시 리디렉션 대신 폼 뷰를 다시 렌더링하도록 action_view_process 호출
}
return $this->action_result_process(
$this->getActionPaths(),
$action,
$this->getViewDatas()
);
}
protected function create_process(string $action, array $viewDatas): string|RedirectResponse
protected function create_process(): mixed
{
$this->doValidation($action);
return $this->action_post_process($action, $viewDatas);
return $this->service->create();
}
public function create(): string|RedirectResponse
final public function create(): RedirectResponse
{
$action = __FUNCTION__;
try {
//초기화
$action = __FUNCTION__;
$viewDatas = $this->action_init_process($action);
return $this->create_process($action, $viewDatas);
$this->action_init_process($action);
$this->create_process();
$redirect_url = $this->authService->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths());
return redirect()->to($redirect_url)->with('success', static::class . "/{$action}이 완료되었습니다.");
} catch (ValidationException $e) {
// 검증 실패 시 폼으로 돌아가서 오류 메시지 표시
log_message('error', $e->getMessage());
return redirect()->back()->withInput()->with('errors', $e->getMessage());
} catch (\Exception $e) {
log_message('error', $e->getMessage());
return redirect()->back()->withInput()->with('error', $e->getMessage());
}
}

13
app/DTOs/Auth/AuthDTO.php Normal file
View File

@ -0,0 +1,13 @@
<?php
namespace App\DTOs\Auth;
use App\DTOs\CommonDTO;
abstract class AuthDTO extends CommonDTO
{
public function __construct()
{
parent::__construct();
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\DTOs\Auth;
class GoogleDTO extends AuthDTO
{
public $access_code = null;
public function __construct(array $datas = [])
{
parent::__construct();
foreach ($datas as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
public function toArray(): array
{
return [
'access_code' => $this->access_code,
];
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\DTOs\Auth;
class LocalDTO extends AuthDTO
{
public ?string $id = null;
public ?string $passwd = null;
public function __construct(array $datas = [])
{
parent::__construct();
foreach ($datas as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
public function toArray(): array
{
return [
'id' => $this->id,
'passwd' => $this->passwd,
];
}
}

View File

@ -1,26 +0,0 @@
<?php
namespace App\DTOs;
use App\Services\Auth\AuthService;
class AuthDTO extends CommonDTO
{
public function __construct(
public bool $isLogin,
public ?int $uid = null,
public ?string $name = null,
public ?string $role = null
) {
parent::__construct();
}
public static function fromByAuthService(AuthService $service): self
{
return new self(
$service->isLoggedIn(),
$service->getUID(),
$service->getName(),
$service->getRole(),
);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\DTOs;
use App\Services\Auth\AuthService;
class CertificationDTO extends CommonDTO
{
public bool $isLogin = false;
public ?int $uid = null;
public ?string $name = null;
public ?string $role = null;
public function __construct(array $datas = [])
{
parent::__construct();
foreach ($datas as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
public static function fromByAuthService(AuthService $service): self
{
return new self(
[
'isLogin' => $service->isLoggedIn(),
'uid' => $service->getUID(),
'name' => $service->getName(),
'role' => $service->getRole(),
]
);
}
}

View File

@ -5,24 +5,34 @@ namespace App\DTOs;
class UserDTO extends CommonDTO
{
public ?int $uid = null;
public ?string $name = null;
public ?string $id = null;
public ?string $passwd = null;
public ?string $passwd_confirm = null;
public ?string $email = null;
public ?string $mobile = null;
public ?string $role = null;
public ?string $status = null;
public function __construct(array $datas = [])
{
parent::__construct();
foreach ($datas as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
public function toArray(): array
{
return [
'uid' => $this->uid,
'title' => $this->name,
'id' => $this->id,
'passwd' => $this->passwd,
'passwd_confirm' => $this->passwd_confirm,
'email' => $this->email,
'mobile' => $this->mobile,
'role' => $this->role,
'status' => $this->status,
];
}
}

View File

@ -28,30 +28,13 @@ abstract class CommonForm
}
return $rules;
}
final public function getFormOptions(string $class_path, string $action, array $fields, array $options = []): array
final public function getFormOptions(string $action, array $fields, array $options = []): array
{
foreach ($fields as $field) {
$options = $this->getFormOption($class_path, $action, $field, $options);
$options = $this->getFormOption($action, $field, $options);
}
return $options;
}
final public function form_dropdown_common(string $field, mixed $value, array $viewDatas, array $extras = [], array $attributes = [], bool $isAll = false): string
{
// 필터 옵션이 없으면 빈 배열로 초기화
if (!array_key_exists($field, $viewDatas['control']['formOptions'])) {
return ""; // 필터 옵션이 없으면 빈 문자열 반환
}
$extra = "";
foreach ($extras as $extra_tag => $extra_value) {
$extra .= sprintf(" %s=\"%s\"", $extra_tag, $extra_value);
}
// $formOptions는 필터 옵션 배열로, key는 필터 엔티티의 PK, value는 필터 엔티티 객체
$html = sprintf("<select name=\"%s\" %s>", $field, $extra);
$html .= "<option value=\"\">" . lang("{$viewDatas['class_path']}.label.{$field}") . " 선택" . "</option>";
$html .= $this->form_dropdown_common_process($field, $value, $viewDatas, $extras, $attributes, $isAll);
$html .= '</select>';
return $html;
}
//필수함수
public function getFormFilters(): array
{
@ -119,7 +102,7 @@ abstract class CommonForm
}
return $rules;
}
public function getFormOption(string $class_path, string $action, string $field, array $options = []): array
public function getFormOption(string $action, string $field, array $options = []): array
{
switch ($field) {
case 'user_uid':
@ -131,118 +114,13 @@ abstract class CommonForm
$option = $clientService->getEntities();
break;
default:
$option = lang($class_path . "." . strtoupper($field));
$option = lang($this->getAttribute('class_path') . "." . strtoupper($field));
break;
}
if (!is_array($option)) {
throw new \Exception(__FUNCTION__ . "에서 {$field}의 options 값들이 배열이 아닙니다.\n" . var_export($option, true));
throw new \Exception(static::class . DIRECTORY_SEPARATOR . __FUNCTION__ . "에서 {$field}의 options 값들이 배열이 아닙니다.\n" . var_export($option, true));
}
$options[$field] = $option;
return $options;
}
protected function form_dropdown_common_process(string $field, mixed $value, array $viewDatas, array $extras = [], array $attributes = [], bool $isAll = false): string
{
$html = "";
switch ($field) {
default:
foreach ($viewDatas['control']['formOptions'][$field] as $option_key => $option_value) {
$isSelected = $option_key == $value ? ' selected' : '';
$isDisabled = "";
$attribute = "";
$label = "";
if ($option_value instanceof CommonEntity) {
if ($option_key != $value && $option_value->getStatus() != $option_value::DEFAULT_STATUS && !$isAll) {
continue;
}
foreach ($attributes as $attribute_name => $attribute_value) {
$attribute .= sprintf(" %s=\"%s\"", $attribute_name, $option_value->$attribute_value);
}
$label = $option_value->getCustomTitle();
} else {
$label = $option_value;
}
$html .= sprintf("<option value=\"%s\"%s%s%s>%s</option>", $option_key, $isSelected, $isDisabled, $attribute, $label);
}
break;
}
return $html;
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{
switch ($field) {
case 'email':
$form = form_input($field, $value ?? "", [
"class" => "form-control",
'style' => 'width:100%;',
"placeholder" => "예)test@example.com",
...$extras
]);
break;
case 'mobile':
case 'phone':
$form = form_input($field, $value ?? "", [
"class" => "form-control",
'style' => 'width:100%;',
"placeholder" => "예)010-0010-0010",
...$extras
]);
break;
case 'role':
if (!is_array($viewDatas['control']['formOptions'][$field])) {
throw new \Exception(__METHOD__ . "에서 {$field}의 field_options가 array형태가 아닙니다.");
}
// create, modify, create_form, modify_form일때 checkbox로 표시
if (in_array($viewDatas['control']['action'], ['create_form', 'modify_form'])) {
$forms = [];
foreach ($viewDatas['control']['formOptions'][$field] as $key => $label) {
if ($key !== '') { // 빈값은 제외
$values = is_array($value) ? $value : explode(DEFAULTS["DELIMITER_ROLE"], $value);
//form_check에는 "class" => "form-control" 쓰면 않되거나 form-check를 써야함
$forms[] = form_checkbox("{$field}[]", $key, in_array($key, $values), $extras) . $label;
}
}
$form = implode(" ", $forms);
} else {
$form = form_dropdown($field, $value, $viewDatas, $extras);
}
break;
case 'issue_at':
case 'expired_at':
case 'billing_at':
case 'start_at':
case 'end_at':
case 'updated_at':
case 'created_at':
case 'deleted_at':
$extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' calender' : 'calender';
$form = form_input($field, $value ?? "", $extras);
break;
case 'description':
case 'content':
case 'detail':
case 'history':
$extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' tinymce' : 'tinymce';
$form = form_textarea($field, html_entity_decode($value ?? "", ENT_QUOTES, 'UTF-8'), [
"class" => "form-control",
'style' => 'width:100%;',
...$extras
]);
break;
default:
if (in_array($field, $viewDatas['control']['formFilters'])) {
if (str_contains($field, "_uid")) {
$extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' select-field' : 'select-field';
}
$form = $this->form_dropdown_common($field, $value, $viewDatas, $extras);
} else {
$form = form_input($field, $value ?? "", [
"class" => "form-control",
'style' => 'width:100%;',
...$extras
]);
}
break;
}
return $form;
}
}

View File

@ -105,25 +105,4 @@ class TrafficForm extends CommonForm
$options[$field] = $option;
return $options;
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{
switch ($field) {
case 'site':
$extras['onChange'] = "$('select[name=\'clientinfo_uid\']').select2('open')";
$form = $this->form_dropdown_common($field, $value, $viewDatas, $extras);
break;
case 'serverinfo_uid':
$extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' select-field' : 'select-field';
$attributes = ['data-price' => 'price'];
$form = $this->form_dropdown_common($field, $value, $viewDatas, $extras, $attributes);
break;
case 'amount':
$form = form_input($field, 0, ["readonly" => "readonly", ...$extras]);
break;
default:
$form = parent::getFieldForm($field, $value, $viewDatas, $extras);
break;
}
return $form;
}
}

View File

@ -75,17 +75,4 @@ class UserForm extends CommonForm
}
return $rules;
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{
switch ($field) {
case 'passwd':
case 'confirmpassword':
$form = form_password($field, "", [...$extras]);
break;
default:
$form = parent::getFieldForm($field, $value, $viewDatas, $extras);
break;
}
return $form;
} //
}

View File

@ -2,14 +2,11 @@
namespace App\Helpers;
use App\Models\UserModel;
class AuthHelper extends CommonHelper
{
public function __construct()
{
parent::__construct();
$this->setTitleField(UserModel::TITLE);
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{

View File

@ -4,44 +4,24 @@ namespace App\Helpers;
use App\Entities\CommonEntity;
use App\Traits\UtilTrait;
use RuntimeException;
class CommonHelper
{
use UtilTrait;
private $_myAuth = null;
private $_viewDatas = [];
private $_titleField = "";
private array $_attributes = [];
protected function __construct() {}
final protected function getMyAuth(): mixed
final public function setAttributes(array $attributes): void
{
if (!$this->_myAuth) {
$this->_myAuth = service('myauth');
$this->_attributes = $attributes;
}
final public function getAttribute(string $key): string
{
if (!array_key_exists($key, $this->_attributes)) {
throw new RuntimeException(__METHOD__ . "에서 오류발생: {$key}에 해당하는 속성이 정의되지 않았습니다.");
}
return $this->_myAuth;
return $this->_attributes[$key];
}
final public function setTitleField(string $field): void
{
$this->_titleField = $field;
}
final public function getTitleField(): string
{
if (!$this->_titleField) {
throw new \Exception("titleField가 지정되지 않았습니다.");
}
return $this->_titleField;
}
final public function setViewDatas(array $viewDatas): void
{
$this->_viewDatas = $viewDatas;
}
final public function getViewDatas(string $key)
{
if (!array_key_exists($key, $this->_viewDatas)) {
throw new \Exception("{$key}에 해당하는 ViewData가 존재하지 않습니다.");
}
return $this->_viewDatas[$key];
}
final public function form_dropdown_common(string $field, mixed $value, array $viewDatas, array $extras = [], array $attributes = [], bool $isAll = false): string
{
// 필터 옵션이 없으면 빈 배열로 초기화
@ -54,7 +34,7 @@ class CommonHelper
}
// $formOptions는 필터 옵션 배열로, key는 필터 엔티티의 PK, value는 필터 엔티티 객체
$html = sprintf("<select name=\"%s\" %s>", $field, $extra);
$html .= "<option value=\"\">" . lang("{$viewDatas['class_path']}.label.{$field}") . " 선택" . "</option>";
$html .= "<option value=\"\">" . lang("{$this->getAttribute('class_path')}.label.{$field}") . " 선택" . "</option>";
$html .= $this->form_dropdown_common_process($field, $value, $viewDatas, $extras, $attributes, $isAll);
$html .= '</select>';
return $html;
@ -93,7 +73,7 @@ class CommonHelper
default:
// required가 있으면 class 추가
$extras = (strpos($viewDatas['control']['formRules'][$field], 'required') !== false) ? ["class" => "text-danger", "required" => "", ...$extras] : $extras;
$label = form_label($label, $field, ['class' => 'form-label-sm', ...$extras]);
$label = $label ?: form_label(lang("{$this->getAttribute('class_path')}.label.{$field}"), $field, ['class' => 'form-label-sm', ...$extras]);
break;
}
return $label;

View File

@ -2,14 +2,11 @@
namespace App\Helpers;
use App\Models\UserModel;
class UserHelper extends CommonHelper
{
public function __construct()
{
parent::__construct();
$this->setTitleField(UserModel::TITLE);
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{

View File

@ -1,38 +0,0 @@
<?php
if (! function_exists('render_field_form')) {
/**
* 필드를 렌더링하고 유효성 검사 오류를 포함합니다.
* ServiceService에서 가져오던 로직을 여기로 옮깁니다.
*/
function render_field_form(string $field, $value, array $viewDatas): string
{
$service = $viewDatas['service'] ?? null;
if ($service === null) {
return __FUNCTION__ . "에서 오류발생: ViewDatas에 'service'가 정의되지 않았습니다.";
}
$formHelper = $service->getFormService();
$html = $formHelper->getSpecificFieldHtml($field, $value, $viewDatas);
$error = validation_show_error($field);
return $html . "<span>{$error}</span>";
}
if (! function_exists('render_field_label')) {
function render_field_label(string $field, array $viewDatas): string
{
$classPath = $viewDatas['class_path'];
$baseLabel = lang("{$classPath}.label.{$field}");
// 1. ServiceForm에서 동적 처리(예: 도움말 아이콘, 별도 클래스)를 가져옵니다.
$service = $viewDatas['service'] ?? null;
if ($service === null) {
return __FUNCTION__ . "에서 오류발생: ViewDatas에 'service'가 정의되지 않았습니다.";
}
$formHelper = $service->getFormHelper();
$dynamicHtml = $formHelper->getSpecificLabelAdornment($field);
// 2. 공통 로직: 필수 필드 표시 (*)
// (ServiceForm이 해당 필드가 필수인지 알려줘야 함)
$isRequired = $formHelper->isFieldRequired($field);
$requiredStar = $isRequired ? '<span class="text-danger">*</span>' : '';
return "{$baseLabel}{$requiredStar}{$dynamicHtml}";
}
}
}

View File

@ -3,6 +3,7 @@
namespace App\Services\Auth;
use App\Entities\UserEntity;
use App\Helpers\AuthHelper;
use App\Models\CommonModel;
use App\Services\CommonService;
use CodeIgniter\Session\Session;
@ -16,13 +17,27 @@ abstract class AuthService extends CommonService
protected function __construct(CommonModel $model)
{
parent::__construct($model);
$this->addClassPath('Auth');
$this->addClassPaths('Auth');
}
abstract public function login(mixed $dto): UserEntity;
final public function getHelper(): AuthHelper
{
if ($this->helperInstance === null) {
$this->helperInstance = new AuthHelper();
$this->helperInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->helperInstance;
}
abstract public function login(array $formDatas): UserEntity;
//Index,FieldForm관련
final public function getSession(): Session
{
if (!$this->_session) {
if ($this->_session === null) {
$this->_session = \Config\Services::session();
}
return $this->_session;

View File

@ -2,31 +2,34 @@
namespace App\Services\Auth;
use App\DTOs\Auth\GoogleDTO;
use App\DTOs\AuthDTO;
use App\Entities\UserEntity;
use App\Forms\Auth\GoogleForm;
use App\Libraries\MySocket\GoogleSocket\CURL;
use App\Models\UserModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\Validation\Exceptions\ValidationException;
use RuntimeException;
class GoogleService extends AuthService
{
public function __construct(UserModel $model, private GoogleForm $formService, private CURL $socket)
public function __construct(UserModel $model, private CURL $socket)
{
parent::__construct($model);
$this->formServiceInstance = $this->formService;
// FormService에 Model 메타데이터를 설정
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
]);
$this->addClassPath('Google');
$this->addClassPaths('Google');
}
public function getFormService(): GoogleForm
{
if ($this->formServiceInstance === null) {
throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.');
$this->formServiceInstance = new GoogleForm();
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->formServiceInstance;
}
@ -43,11 +46,19 @@ class GoogleService extends AuthService
return [];
}
//기본기능
public function login(array $formDatas): UserEntity
public function login(mixed $dto): UserEntity
{
try {
// Google 서비스 설정
$this->socket->setToken($formDatas['access_code']);
if (!$dto instanceof GoogleDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생: GoogleDTO만 사용하실수 있습니다");
}
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
// 검증 실패 시, ValidationException을 던집니다.
throw new ValidationException(service('validation')->getErrors());
}
$this->socket->setToken($dto->access_code);
$sns_entity = $this->socket->signup();
// local db 사용와의 연결 확인
$entity = $this->getEntity($sns_entity->getParent());

View File

@ -2,31 +2,31 @@
namespace App\Services\Auth;
use App\DTOs\Auth\LocalDTO;
use App\Entities\UserEntity;
use App\Forms\Auth\LocalForm;
use App\Models\UserModel;
use CodeIgniter\Validation\Exceptions\ValidationException;
use RuntimeException;
class LocalService extends AuthService
{
public function __construct(
UserModel $model,
private LocalForm $formService,
) {
public function __construct(UserModel $model)
{
parent::__construct($model);
$this->formServiceInstance = $this->formService;
// FormService에 Model 메타데이터를 설정
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
]);
$this->addClassPath('Local');
$this->addClassPaths('Local');
}
public function getFormService(): LocalForm
{
if ($this->formServiceInstance === null) {
throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.');
$this->formServiceInstance = new LocalForm();
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->formServiceInstance;
}
@ -43,17 +43,22 @@ class LocalService extends AuthService
return [];
}
//기본기능
public function login(array $formDatas): UserEntity
public function login(mixed $dto): UserEntity
{
$entity = $this->getEntity([
'id' => $formDatas['id'],
'status' => UserEntity::DEFAULT_STATUS
], false);
if (!$entity instanceof UserEntity) {
throw new \Exception("{$formDatas['id']}에 대한 로그인 정보를 찾을수 없습니다.");
if (!$dto instanceof LocalDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생: LcoalDTO만 사용하실수 있습니다");
}
if (!password_verify($formDatas['passwd'], $entity->getPassword())) {
// log_message("error", "암호: {$formDatas['passwd']}, {$entity->passwd}");
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
// 검증 실패 시, ValidationException을 던집니다.
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
$entity = $this->getEntity(['id' => $dto->id, 'status' => STATUS['AVAILABLE']], false);
if (!$entity instanceof UserEntity) {
throw new \Exception("{$dto->id}에 대한 로그인 정보를 찾을수 없습니다.");
}
if (!password_verify($dto->passwd, $entity->getPassword())) {
throw new \Exception("암호가 맞지 않습니다.");
}
return $this->login_process($entity);

View File

@ -2,23 +2,23 @@
namespace App\Services;
use CodeIgniter\HTTP\RedirectResponse;
use App\Models\CommonModel;
abstract class CommonService
{
private $_logService = null;
protected array $classPaths = [];
private array $_classPaths = [];
protected $formServiceInstance = null;
protected $helperInstance = null;
protected function __construct(protected CommonModel $model) {}
abstract public function getFormService(): mixed;
final protected function addClassPath(string $className): void
abstract public function getHelper(): mixed;
final protected function addClassPaths(string $path): void
{
$this->classPaths[] = $className;
$this->_classPaths[] = $path;
}
final public function getClassPath($delimeter = DIRECTORY_SEPARATOR): string
final public function getClassPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string
{
return implode($delimeter, $this->classPaths);
return $isArray ? $this->_classPaths : implode($delimeter, $this->_classPaths);
}
final public function getEntity(string|int|array $where, ?string $message = null): mixed
{
@ -76,11 +76,7 @@ abstract class CommonService
}
public function getFormOptions(string $action): array
{
return $this->getFormService()->getFormOptions(
$this->getClassPath(),
$action,
$this->getFormFilters()
);
return $this->getFormService()->getFormOptions($action, $this->getFormFilters());
}
public function getViewFields(): array
{

View File

@ -12,26 +12,38 @@ class TrafficService extends CommonService
{
public function __construct(
TrafficModel $model,
private TrafficForm $formService,
) {
parent::__construct($model);
$this->formServiceInstance = $this->formService;
// FormService에 Model 메타데이터를 설정
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
]);
$this->addClassPath('Service');
$this->addClassPaths('Traffic');
}
public function getFormService(): TrafficForm
{
if ($this->formServiceInstance === null) {
throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.');
$this->formServiceInstance = new TrafficForm();
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->formServiceInstance;
}
public function getHelper(): TrafficHelper
{
if ($this->helperInstance === null) {
$this->helperInstance = new TrafficHelper();
$this->helperInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->helperInstance;
}
//필수함수
// public function getNewServiceEntities(int $interval, string $status = ServiceEntity::DEFAULT_STATUS): array
// {

View File

@ -2,114 +2,99 @@
namespace App\Services;
use App\DTOs\UserDTO;
use App\Entities\UserEntity;
use App\Forms\UserForm;
use App\Helpers\UserHelper;
use App\Models\UserModel;
use CodeIgniter\Validation\Exceptions\ValidationException;
use RuntimeException;
class UserService extends CommonService
{
public function __construct(
UserModel $model,
private UserForm $formService,
) {
public function __construct(UserModel $model)
{
parent::__construct($model);
$this->formServiceInstance = $this->formService;
// FormService에 Model 메타데이터를 설정
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
]);
$this->addClassPath('Service');
$this->addClassPaths('User');
}
public function getFormService(): UserForm
{
if ($this->formServiceInstance === null) {
throw new \RuntimeException('FormService는 ' . static::class . '에서 초기화되어야 합니다.');
$this->formServiceInstance = new UserForm();
$this->formServiceInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->formServiceInstance;
}
public function getFormFields(): array
public function getHelper(): UserHelper
{
return [
'id',
'passwd',
'confirmpassword',
'name',
'email',
'mobile',
'role',
'status',
];
}
public function getFormFilters(): array
{
return [
'role',
'status',
];
}
public function getIndexFields(): array
{
return [
'id',
'name',
'email',
'mobile',
'role',
'status',
];
}
public function getBatchjobFields(): array
{
return ['status'];
if ($this->helperInstance === null) {
$this->helperInstance = new UserHelper();
$this->helperInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
]);
}
return $this->helperInstance;
}
//기본 기능부분
protected function create_process(array $formDatas): UserEntity
public function create(UserDTO $dto): UserEntity
{
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
// 검증 실패 시, ValidationException을 던집니다.
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
$formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']);
$entity = $this->model->create($formDatas);
return $entity;
}
protected function modify_process(mixed $entity, array $formDatas): UserEntity
{
// die(var_export($formDatas, true));
//암호를 입력하지 않았을시는 변경하기 않게 하기위함
if (isset($formDatas['passwd']) && $formDatas['passwd'] == "") {
unset($formDatas['passwd']);
unset($formDatas['confirmpassword']);
}
//Role을 지정이 있을경우에만 , toggle이나 batcjhjob에서는 없을수도 있으므로
if (isset($formDatas['role'])) {
$formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']);
}
// die(var_export($formDatas, true));
$entity = parent::modify_process($entity, $formDatas);
return $entity;
}
//List 검색용
//FormFilter 조건절 처리
public function index_condition_filterField(string $field, mixed $filter_value): void
{
switch ($field) {
case 'role':
$where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0";
//FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동
$this->model->where($where, null, false);
break;
default:
parent::index_condition_filterField($field, $filter_value);
break;
}
}
//검색어조건절처리
public function index_condition_filterWord(string $word): void
{
$this->model->orLike($this->model->getTable() . '.id', $word, 'both');
$this->model->orLike($this->model->getTable() . "." . $this->model::TITLE, $word, 'both');
$this->model->orLike($this->model->getTable() . '.email', $word, 'both');
parent::index_condition_filterWord($word);
}
// protected function modify_process(mixed $entity, array $formDatas): UserEntity
// {
// // die(var_export($formDatas, true));
// //암호를 입력하지 않았을시는 변경하기 않게 하기위함
// if (isset($formDatas['passwd']) && $formDatas['passwd'] == "") {
// unset($formDatas['passwd']);
// unset($formDatas['confirmpassword']);
// }
// //Role을 지정이 있을경우에만 , toggle이나 batcjhjob에서는 없을수도 있으므로
// if (isset($formDatas['role'])) {
// $formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']);
// }
// // die(var_export($formDatas, true));
// $entity = parent::modify_process($entity, $formDatas);
// return $entity;
// }
// //List 검색용
// //FormFilter 조건절 처리
// public function index_condition_filterField(string $field, mixed $filter_value): void
// {
// switch ($field) {
// case 'role':
// $where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0";
// //FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동
// $this->model->where($where, null, false);
// break;
// default:
// parent::index_condition_filterField($field, $filter_value);
// break;
// }
// }
// //검색어조건절처리
// public function index_condition_filterWord(string $word): void
// {
// $this->model->orLike($this->model->getTable() . '.id', $word, 'both');
// $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both');
// $this->model->orLike($this->model->getTable() . '.email', $word, 'both');
// parent::index_condition_filterWord($word);
// }
}

View File

@ -0,0 +1,24 @@
<?= $this->extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?>
<?= $this->section('content') ?>
<?php if (session('error')): echo $viewDatas['control']['helper']->alertTrait(session('error')) ?><?php endif ?>
<div id="container" class="content">
<div class="form_top"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_top"); ?></div>
<?= form_open(current_url(), $viewDatas['forms']['attributes'], $viewDatas['forms']['hiddens']) ?>
<div class="action_form">
<table class="table table-bordered">
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<tr>
<th nowrap class="text-end"><?= $viewDatas['control']['helper']->getFieldLabel($field, "", $viewDatas) ?></th>
<td nowrap class="text-start">
<?= $viewDatas['control']['helper']->getFieldForm($field, old($field) ?? ($viewDatas['control']['formDatas'][$field] ?? null), $viewDatas) ?>
<span><?= validation_show_error($field); ?></span>
</td>
</tr>
<?php endforeach; ?>
</table>
<div class="text-center"><?= form_submit('', '입력', array("class" => "btn btn-outline btn-primary")); ?></div>
<?= form_close(); ?>
</div>
<div class="form_bottom"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_bottom"); ?></div>
</div>
<?= $this->endSection() ?>

View File

@ -0,0 +1,21 @@
<table>
<thead>
<tr>
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<th><?= lang("{$viewDatas['class_path']}.label.{$field}") ?></th>
<?php endforeach ?>
</tr>
</thead>
<tbody>
<?php $cnt = 0 ?>
<?php foreach ($viewDatas['entities'] as $entity): ?>
<?php $viewDatas['entity'] = $entity; ?>
<tr>
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<td><?= $viewDatas['service']->getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?></td>
<?php endforeach ?>
</tr>
<?php $cnt++ ?>
<?php endforeach ?>
</tbody>
</table>

View File

@ -0,0 +1,70 @@
<?= $this->extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?>
<?= $this->section('content') ?>
<?php if ($error = session('error')): echo $viewDatas['service']->getHelper()->alertTrait($error) ?><?php endif ?>
<div class="layout_top"><?= $this->include(LAYOUTS[$viewDatas['control']['layout']]['path'] . '/top'); ?></div>
<!-- Layout Middle Start -->
<table class="layout_middle">
<tr>
<td class="layout_left">
<!-- Layout Left Start -->
<?= $this->include(LAYOUTS[$viewDatas['control']['layout']]['path'] . '/left_menu'); ?>
<!-- Layout Left End -->
</td>
<td class="layout_right">
<!-- Layout Right Start -->
<div class="layout_header"><?= $this->include("templates/{$viewDatas['control']['layout']}/index_header"); ?></div>
<div id="container" class="layout_content">
<link href="/css/<?= $viewDatas['control']['layout'] ?>/index.css" media="screen" rel="stylesheet" type="text/css" />
<div class="index_body">
<?= form_open(current_url(), ["method" => "get"]) ?>
<nav class="index_top navbar navbar-expand-lg">
<div class="container-fluid">
<nav class="condition nav">
조건:
<?php foreach ($viewDatas['control']['formFilters'] as $field): ?>
<?= $viewDatas['service']->getHelper()->getListFilter($field, $viewDatas['control']['index_filters'][$field] ?? old($field), $viewDatas) ?>&nbsp;
<?php endforeach ?>
</nav>
<?= $this->include("templates/{$viewDatas['control']['layout']}/index_content_top"); ?>
</div>
</nav>
<?= form_close() ?>
<?= form_open(current_url(), ['id' => 'batchjob_form', 'method' => "post"]) ?>
<table class="index_table data table table-bordered table-hover table-striped" data-rtc-resizable-table="reisze_table">
<thead>
<tr>
<th class="index_head_short_column">번호</th>
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<th data-rtc-resizable="<?= $field ?>"><?= $viewDatas['service']->getHelper()->getListLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?></th>
<?php endforeach ?>
<th class="index_head_short_column">작업</th>
</thead>
<tbody>
<?php $cnt = 0 ?>
<?php foreach ($viewDatas['entities'] as $entity): ?>
<?php $viewDatas['entity'] = $entity; ?>
<tr <?= $viewDatas['entity']->getStatus() === $viewDatas['entity']::DEFAULT_STATUS ? "" : 'class="table-danger"' ?>>
<?php $num = $viewDatas['total_count'] - (($viewDatas['page'] - 1) * $viewDatas['per_page'] + $cnt); ?>
<td nowrap><?= $viewDatas['service']->getHelper()->getListButton('modify', $num, $viewDatas) ?></td>
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<td><?= $viewDatas['service']->getHelper()->getFieldView($field, $entity->$field, $viewDatas) ?></td>
<?php endforeach ?>
<td nowrap>
<?= $viewDatas['service']->getHelper()->getListButton('view', '', $viewDatas) ?>&nbsp;
<?= $viewDatas['service']->getHelper()->getListButton('delete', '', $viewDatas) ?>
</td>
</tr>
<?php $cnt++ ?>
<?php endforeach ?>
</tbody>
</table>
<?= $this->include("templates/{$viewDatas['control']['layout']}/index_content_bottom"); ?>
<?= form_close() ?>
</div>
</div>
<div class="layout_footer"><?= $this->include("templates/{$viewDatas['control']['layout']}/index_footer"); ?></div>
</td>
</tr>
</table>
<div class="layout_bottom"><?= $this->include(LAYOUTS[$viewDatas['control']['layout']]['path'] . '/bottom'); ?></div>
<?= $this->endSection() ?>

View File

@ -0,0 +1,24 @@
<?= $this->extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?>
<?= $this->section('content') ?>
<?php if ($error = session('error')): echo $viewDatas['service']->getHelper()->alertTrait($error) ?><?php endif ?>
<div id="container" class="content">
<div class="form_top"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_top"); ?></div>
<?= form_open(current_url(), ['id' => 'action_form', ...$viewDatas['forms']['attributes']], $viewDatas['forms']['hiddens']) ?>
<div class="action_form">
<table class="table table-bordered">
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<tr>
<th nowrap class="text-end"><?= $viewDatas['service']->getHelper()->getFieldLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?></th>
<td nowrap class="text-start">
<?= $viewDatas['service']->getHelper()->getFieldForm($field, old($field) ?? $viewDatas['entity']->$field ?? null, $viewDatas) ?>
<div><?= validation_show_error($field); ?></div>
</td>
</tr>
<?php endforeach; ?>
</table>
<div class="text-center"><?= form_submit("", '수정', ["class" => "btn btn-outline btn-primary"]) ?></div>
<?= form_close(); ?>
</div>
<div class="form_bottom"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_bottom"); ?></div>
</div>
<?= $this->endSection() ?>

View File

@ -0,0 +1,17 @@
<?= $this->extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?>
<?= $this->section('content') ?>
<?php if ($error = session('error')): echo $viewDatas['service']->getHelper()->alertTrait($error) ?><?php endif ?>
<div id="container" class="content">
<link href="/css/<?= $viewDatas['control']['layout'] ?>/form.css" media="screen" rel="stylesheet" type="text/css" />
<div class="action_form">
<table class="table table-bordered">
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
<tr>
<th nowrap class="text-end" width="20%"><?= $viewDatas['service']->getHelper()->getFieldLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?></th>
<td nowrap class="text-start"><?= $viewDatas['service']->getHelper()->getFieldView($field, $viewDatas['entity']->$field, $viewDatas) ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
<?= $this->endSection() ?>