163 lines
5.1 KiB
PHP
163 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers;
|
|
|
|
use App\Libraries\AuthContext;
|
|
use App\Traits\LogTrait;
|
|
use CodeIgniter\Controller;
|
|
use CodeIgniter\HTTP\RedirectResponse;
|
|
use CodeIgniter\HTTP\RequestInterface;
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* AbstractWebController
|
|
* 모든 웹 컨트롤러의 최상위 추상 클래스.
|
|
* 공통 초기화, 뷰 데이터 관리, 리다이렉션/렌더링 로직을 담당합니다. (SRP: Utility & Presentation Layer)
|
|
*/
|
|
abstract class AbstractWebController extends Controller
|
|
{
|
|
use LogTrait;
|
|
|
|
protected $service = null;
|
|
private array $_action_paths = [];
|
|
private array $_viewDatas = [];
|
|
private ?string $_title = null;
|
|
|
|
// --- 초기화 및 DI ---
|
|
|
|
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
|
|
{
|
|
parent::initController($request, $response, $logger);
|
|
}
|
|
|
|
final protected function getAuthContext(): AuthContext
|
|
{
|
|
return service('myauth')->getAuthContext();
|
|
}
|
|
|
|
protected function getTitle(): string
|
|
{
|
|
if ($this->_title === null) {
|
|
// 이 로직은 하위 클래스에서 service가 초기화되었다고 가정합니다.
|
|
$this->_title = lang("{$this->service->getClassPaths(false)}.title");
|
|
}
|
|
return $this->_title;
|
|
}
|
|
|
|
// --- 경로 및 뷰 데이터 관리 ---
|
|
|
|
final protected function addActionPaths(string $path)
|
|
{
|
|
$this->_action_paths[] = $path;
|
|
}
|
|
|
|
final protected function getActionPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string
|
|
{
|
|
return $isArray ? $this->_action_paths : implode($delimeter, $this->_action_paths);
|
|
}
|
|
|
|
final protected function addViewDatas(string $key, mixed $value)
|
|
{
|
|
$this->_viewDatas[$key] = $value;
|
|
}
|
|
|
|
final protected function getViewDatas(?string $key = null): mixed
|
|
{
|
|
if ($key === null) {
|
|
return $this->_viewDatas;
|
|
}
|
|
return $this->_viewDatas[$key] ?? null;
|
|
}
|
|
|
|
// --- 공통 처리 로직 (Override 가능) ---
|
|
|
|
/**
|
|
* 모든 액션 실행 전 공통 초기화 작업
|
|
*/
|
|
protected function action_init_process(string $action): void
|
|
{
|
|
$this->addViewDatas('action', $action);
|
|
$this->addViewDatas('authContext', $this->getAuthContext());
|
|
// $this->service가 하위 클래스에서 설정되었다고 가정
|
|
$this->addViewDatas('classPath', $this->service->getClassPaths(false));
|
|
}
|
|
|
|
/**
|
|
* 액션 성공 후 모달을 닫고 부모 창을 리로드하는 스크립트를 반환합니다.
|
|
*/
|
|
protected function action_modal_process(string $message): string
|
|
{
|
|
return "
|
|
<script>
|
|
// IMPORTANT: The original alert() should be replaced with a custom modal/toast in production environment.
|
|
// alert('" . addslashes($message) . "');
|
|
|
|
// Bootstrap 5 모달 닫기
|
|
var modalEl = document.getElementById('modal_action_form');
|
|
if (modalEl) {
|
|
var modal = bootstrap.Modal.getInstance(modalEl);
|
|
if (!modal) {
|
|
modal = new bootstrap.Modal(modalEl);
|
|
}
|
|
modal.hide();
|
|
}
|
|
|
|
// 모달 닫힌 후 부모 페이지 새로고침 (애니메이션 고려)
|
|
setTimeout(function() {
|
|
if (window.parent) {
|
|
window.parent.location.reload();
|
|
} else if (window.opener && !window.opener.closed) {
|
|
window.opener.location.reload();
|
|
}
|
|
}, 500);
|
|
</script>
|
|
";
|
|
}
|
|
|
|
/**
|
|
* 액션 결과에 따라 지정된 메시지와 URL로 리다이렉션합니다.
|
|
*/
|
|
protected function action_redirect_process(string $type, string $message, ?string $redirect_url = null): RedirectResponse
|
|
{
|
|
switch ($type) {
|
|
case 'warning':
|
|
case 'error':
|
|
case 'critical':
|
|
case 'alert':
|
|
case 'emergency':
|
|
log_message($type, $message);
|
|
$result = $redirect_url ? redirect()->to($redirect_url)->with('message', $message) : redirect()->back()->withInput()->with('message', $message);
|
|
break;
|
|
case 'debug':
|
|
case 'info':
|
|
case 'notice':
|
|
default:
|
|
log_message($type, $message);
|
|
$redirect_url = $redirect_url ?? $this->getAuthContext()->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths());
|
|
$result = redirect()->to($redirect_url)->with('message', $message);
|
|
break;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 뷰 경로와 데이터를 이용하여 최종 HTML을 렌더링합니다.
|
|
*/
|
|
protected function action_render_process(array $view_paths, string $view_file, array $viewDatas): string
|
|
{
|
|
$full_path = implode(DIRECTORY_SEPARATOR, $view_paths);
|
|
$final_path = $this->request->getVar('ActionTemplate');
|
|
if ($final_path) {
|
|
$full_path .= DIRECTORY_SEPARATOR . $final_path;
|
|
}
|
|
$view_datas = [
|
|
...$viewDatas,
|
|
'forms' => ['attributes' => ['method' => "post",], 'hiddens' => []],
|
|
];
|
|
|
|
helper(['form', __FUNCTION__]);
|
|
return view($full_path . DIRECTORY_SEPARATOR . $view_file, ['viewDatas' => $view_datas]);
|
|
}
|
|
}
|