projectbase/app/Controllers/AbstractWebController.php
2026-02-10 15:00:16 +09:00

142 lines
4.0 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;
/**
* CommonController
*
* 이 클래스를 상속받는 모든 자식 클래스(UserController 등)는
* 반드시 'PATH' 상수를 가지고 있음을 IDE에 알려줍니다.
* * @property-read string PATH // ⭐ 이 부분이 핵심입니다.
*/
abstract class AbstractWebController extends Controller
{
use LogTrait;
private array $_action_paths = [];
private array $_viewDatas = [];
private ?string $_title = null;
protected $layouts = [];
protected $service = 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, array $formDatas = []): void
{
$this->addViewDatas('action', $action);
$this->addViewDatas('authContext', $this->getAuthContext());
$this->addViewDatas('classPath', $this->service->getClassPaths(false));
$this->addViewDatas('uri', $this->request->getUri());
}
/**
* 액션 성공 후 모달을 닫고 부모 창을 리로드하는 스크립트를 반환합니다.
*/
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()->back()->withInput()->with('message', $message);
break;
case 'debug':
case 'info':
case 'notice':
default:
$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(
string $view_file,
array $viewDatas,
?string $template_path = null
): string {
helper(['form', 'utility']);
/**
* 🔥 핵심:
* View name은 항상 슬래시 기반
*/
$baseViewPath = trim($viewDatas['layout']['path'], '/');
if ($template_path) {
$baseViewPath .= '/' . trim($template_path, '/');
}
$viewName = $baseViewPath . '/' . ltrim($view_file, '/');
return view($viewName, [
'viewDatas' => [
...$viewDatas,
'forms' => [
'attributes' => ['method' => 'post'],
'hiddens' => [],
],
],
]);
}
}