trafficmonitor/app/Controllers/Admin/AdminController.php
2025-11-13 10:39:52 +09:00

366 lines
17 KiB
PHP

<?php
namespace App\Controllers\Admin;
use App\Controllers\CommonController;
use App\DTOs\CommonDTO;
use App\Entities\CommonEntity;
use App\Traits\LogTrait;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Validation\Exceptions\ValidationException;
use CodeIgniter\HTTP\DownloadResponse;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Html;
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf;
use Psr\Log\LoggerInterface;
abstract class AdminController extends CommonController
{
use LogTrait;
public const PATH = 'admin';
private ?string $_title = null;
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
$this->addActionPaths(self::PATH);
}
abstract protected function createDTO(array $formDatas): CommonDTO;
final protected function getLayout(): string
{
return 'admin';
}
protected function getTitle(): string
{
if ($this->_title === null) {
$this->_title = lang("{$this->service->getClassPaths(false)}.title");
}
return $this->_title;
}
protected function action_init_process(string $action): void
{
$this->addViewDatas('layout', $this->getLayout());
$this->addViewDatas('helper', $this->service->getHelper());
$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_batchjobFields', $this->service->getFormService()->getBatchjobFilters());
$this->addViewDatas('index_batchjobButtions', $this->service->getFormService()->getBatchjobButtons());
parent::action_init_process($action);
}
protected function create_form_process(array $formDatas = []): array
{
//Form Default값 설정
return $formDatas;
}
final public function create_form(): string|RedirectResponse
{
try {
$action = __FUNCTION__;
$this->action_init_process($action);
$formDatas = $this->create_form_process();
$this->addViewDatas('formDatas', $formDatas);
return $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas());
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 생성폼 오류:" . $e->getMessage());
}
}
protected function create_process(): CommonEntity
{
//요청 데이터를 DTO 객체로 변환
$dto = $this->createDTO($this->request->getPost());
return $this->service->create($dto);
}
final public function create(): string|RedirectResponse
{
try {
$this->action_init_process(__FUNCTION__);
$entity = $this->create_process();
return $this->action_modal_process("{$this->getTitle()}에서 생성이 완료되었습니다.");
} catch (ValidationException $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 생성 검증오류:" . $e->getMessage());
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 생성 오류:" . $e->getMessage());
}
}
protected function modify_form_process($uid): CommonEntity
{
if (!$uid) {
throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다.");
}
$entity = $this->service->getEntity($uid);
if (!$entity instanceof CommonEntity) {
throw new \Exception("{$uid}에 해당하는 {$this->getTitle()}을 찾을수 없습니다.");
}
return $entity;
}
final public function modify_form($uid): string|RedirectResponse
{
try {
$action = __FUNCTION__;
$this->action_init_process($action);
$entity = $this->modify_form_process($uid);
$this->addViewDatas('entity', $entity);
return $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas());
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 {$uid} 수정폼 오류:" . $e->getMessage());
}
}
protected function modify_process($uid): CommonEntity
{
//요청 데이터를 DTO 객체로 변환
$dto = $this->createDTO($this->request->getPost());
return $this->service->modify($uid, $dto);
}
final public function modify($uid): string|RedirectResponse
{
try {
$this->action_init_process(__FUNCTION__);
$entity = $this->modify_process($uid);
return $this->action_modal_process("{$this->getTitle()}에서 {$uid} 수정이 완료되었습니다.");
} catch (ValidationException $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 {$uid} 수정 검증오류:" . $e->getMessage());
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 {$uid} 수정 오류:" . $e->getMessage());
}
}
final public function batchjob(): string|RedirectResponse
{
try {
$action = __FUNCTION__;
$this->action_init_process($action);
$selectedFields = [];
$formDatas = [];
foreach ($this->service->getFormService->getBatchjobFilters() as $field) {
$value = $this->request->getPost($field);
if ($value) {
$selectedFields[] = $field;
$formDatas[$field] = $value;
}
}
if (!count($selectedFields)) {
throw new \Exception("변경할 조건항목을 선택하셔야합니다.");
}
//변경할 UIDS 정의
$uids = $this->request->getPost('batchjob_uids[]');
if (!is_array($uids) || !count($uids)) {
throw new \Exception("적용할 리스트을 선택하셔야합니다.");
}
$this->service->getFormService()->setFormFields($selectedFields);
$this->service->getFormService()->setFormRules($action, $selectedFields);
$this->service->getFormService()->setFormFilters($selectedFields);
$this->service->getFormService()->setFormOptions($selectedFields);
$entities = [];
$errors = [];
foreach ($uids as $uid) {
try {
$entities[] = $this->modify_process($uid);
} catch (ValidationException $e) {
$errors[] = "{$this->getTitle()}에서 {$uid} 수정 검증오류:" . $e->getMessage();
} catch (\Exception $e) {
$errors[] = "{$this->getTitle()}에서 {$uid} 수정 오류:" . $e->getMessage();
}
}
return $this->action_modal_process("{$this->getTitle()}에서 " . count($entities) . "개, 총:" . count($uids) . " 수정이 완료되었습니다.");
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 {$uid} 수정 오류:" . $e->getMessage());
}
}
protected function delete_process($uid): CommonEntity
{
return $this->service->delete($uid);
}
final public function delete($uid): RedirectResponse
{
try {
$entity = $this->delete_process($uid);
return $this->action_redirect_process('info', "{$this->getTitle()}에서 {$entity->getTitle()} 삭제가 완료되었습니다.");
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 {$uid} 삭제 오류:" . $e->getMessage());
}
}
protected function view_process($uid): CommonEntity
{
if (!$uid) {
throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다.");
}
$entity = $this->service->getEntity($uid);
if (!$entity instanceof CommonEntity) {
throw new \Exception("{$uid}에 해당하는 {$this->getTitle()}을 찾을수 없습니다.");
}
return $entity;
}
final public function view($uid): string|RedirectResponse
{
try {
$action = __FUNCTION__;
$this->action_init_process($action);
$entity = $this->view_process($uid);
$this->addViewDatas('entity', $entity);
return $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas());
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 {$uid} 상세보기 오류:" . $e->getMessage());
}
}
//리스트관련
//조건절 처리
protected function index_condition_process(string $action): void
{
//Filter조건절 처리
$index_filters = [];
foreach ($this->service->getFormService()->getFormFilters($action) as $field) {
$value = $this->request->getVar(index: $field) ?? null;
if ($value) {
$this->service->setFilter($field, $value);
$index_filters[$field] = $value;
}
}
$this->addViewDatas('index_filters', $index_filters);
//검색어조건절 처리
$index_word = $this->request->getVar('index_word');
if ($index_word !== null && $index_word !== '') {
$this->service->setSearchWord($index_word);
}
$this->addViewDatas('index_word', $index_word);
//날자검색
$index_start = $this->request->getVar('index_start');
$index_end = $this->request->getVar('index_end');
if ($index_start !== null && $index_start !== '' && $index_end !== null && $index_end !== '') {
$this->service->setDateFilter($index_start, $index_end);
}
$this->addViewDatas('index_start', $index_start);
$this->addViewDatas('index_end', $index_end);
//OrcerBy처리
$order_field = $this->request->getVar('order_field');
$order_value = $this->request->getVar('order_value');
$this->service->setOrderBy($order_field, $order_value);
$this->addViewDatas('order_field', $order_field);
$this->addViewDatas('order_value', $order_value);
}
//Index Option출력용
protected function pagenation_options_process(int $index_totalcount, int $perpage): array
{
$page_options = ["" => "줄수선택"];
for ($i = $perpage; $i <= $index_totalcount; $i += $perpage) {
$page_options[$i] = $i;
}
$page_options[$index_totalcount] = $index_totalcount;
return $page_options;
}
//PageNation 처리
protected function pagenation_process(int $index_totalcount, int $page, int $perpage, $pager_group = 'default', int $segment = 0, $template = 'bootstrap_full'): mixed
{
// 1.Views/Pagers/에 bootstrap_full.php,bootstrap_simple.php 생성
// 2.app/Config/Pager.php/$templates에 'bootstrap_full => 'Pagers\bootstrap_full',
// 'bootstrap_simple' => 'Pagers\bootstrap_simple', 추가
$pager = service("pager");
$pager->makeLinks($page, $perpage, $index_totalcount, $template, $segment, $pager_group);
// $page = $pager->getCurrentPage($pager_group);
$this->addViewDatas('index_totalpage', $pager->getPageCount($pager_group));
return $pager->links($pager_group, $template);
}
// //Page출력 처리
//Entities처리
protected function index_process(array $entities = []): array
{
foreach ($this->service->getEntities() as $entity) {
$entities[] = $entity;
}
return $entities;
}
public function index(): string
{
$action = __FUNCTION__;
try {
//초기화
$this->action_init_process($action);
$this->addViewDatas('uri', $this->request->getUri());
//Page, Per_page필요부분
$page = (int) $this->request->getVar('page') ?: 1;
$perpage = (int) $this->request->getVar('perpage') ?: intval(DEFAULTS['INDEX_PERPAGE']);
$this->addViewDatas('page', $page);
$this->addViewDatas('perpage', $perpage);
//index_totalcount
//조건절 처리 index_totalcount용
$this->index_condition_process($action);
$index_totalcount = $this->service->getTotalCount();
$this->addViewDatas('index_totalcount', $index_totalcount);
$this->addViewDatas('index_pagination', $this->pagenation_process($index_totalcount, $page, $perpage));
$this->addViewDatas('index_pagination_options', $this->pagenation_options_process($index_totalcount, $perpage));
//조건절 LIMIT , OFFSET 처리 List용
$this->index_condition_process($action);
$this->service->setLimit($perpage);
$this->service->setOffset(($page - 1) * $perpage);
$this->addViewDatas('entities', $this->index_process());
helper(['form']);
$this->addViewDatas('formDatas', $this->request->getGet());
} catch (\Exception $e) {
session()->setFlashdata('message', $e->getMessage());
}
//현재 URL을 세션에 저장
$this->getAuthContext()->pushCurrentUrl($this->request->getUri()->getPath() . ($this->request->getUri()->getQuery() ? "?" . $this->request->getUri()->getQuery() : ""));
return $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas());
}
//OUPUT Document 관련
protected function download_process(string $document_type, mixed $loaded_data): array
{
$full_path = WRITEPATH . DIRECTORY_SEPARATOR . "excel";
switch ($document_type) {
case 'excel':
$file_name = sprintf("%s_%s.xlsx", $this->service->getClassPaths(false, "_"), date('Y-m-d_Hm'));
$writer = IOFactory::createWriter($loaded_data, 'Xlsx');
$writer->save($full_path . DIRECTORY_SEPARATOR . $file_name);
break;
case 'pdf':
$file_name = sprintf("%s_%s.pdf", $this->service->getClassPaths(false, "_"), date('Y-m-d_Hm'));
$writer = new Mpdf($loaded_data);
$writer->save($full_path . DIRECTORY_SEPARATOR . $file_name);
break;
}
return array($full_path, $file_name);
}
// Download
public function download(string $output_type, mixed $uid = false): DownloadResponse|RedirectResponse|string
{
$action = __FUNCTION__;
try {
//초기화
$this->action_init_process($action);
switch ($output_type) {
case 'excel':
case 'pdf':
helper(['form']);
$this->index_condition_process($action);
$this->addViewDatas('entities', $this->index_process());
$html = $this->action_render_process($this->getActionPaths(), $action, $this->getViewDatas());
//data loading
$reader = new Html();
$loaded_data = $reader->loadFromString($html);
list($full_path, $file_name) = $this->download_process($output_type, $loaded_data);
$full_path .= DIRECTORY_SEPARATOR . $file_name;
break;
default:
if (!$uid) {
throw new \Exception("{$output_type}은 반드시 uid의 값이 필요합니다.");
}
$entity = $this->service->getEntity($uid);
if (!$entity) {
throw new \Exception("{$uid}에 대한 정보를 찾을수 없습니다.");
}
$this->addViewDatas('entity', $entity);
list($file_name, $uploaded_filename) = $entity->getDownlaodFile();
$full_path = WRITEPATH . DIRECTORY_SEPARATOR . "uploads" . DIRECTORY_SEPARATOR . $uploaded_filename;
break;
}
return $this->response->download($full_path, null)->setFileName($file_name);
} catch (\Exception $e) {
return $this->action_redirect_process('error', "{$this->getTitle()}에서 오류:" . $e->getMessage());
}
}
}