Automation/app/Models/CommonModel.php
2024-09-10 18:04:49 +09:00

207 lines
7.5 KiB
PHP

<?php
namespace App\Models;
use CodeIgniter\Model;
abstract class CommonModel extends Model
{
protected $table = '';
protected $primaryKey = '';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = false;
protected $protectFields = true;
protected $allowedFields = [];
protected bool $allowEmptyInserts = false;
protected bool $updateOnlyChanged = true;
protected array $casts = [];
protected array $castHandlers = [];
// Dates
protected $useTimestamps = false;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
// Validation
protected $validationRules = [];
protected $validationMessages = [];
protected $skipValidation = false;
protected $cleanValidationRules = true;
// Callbacks
protected $allowCallbacks = true;
protected $beforeInsert = [];
protected $afterInsert = [];
protected $beforeUpdate = [];
protected $afterUpdate = [];
protected $beforeFind = [];
protected $afterFind = [];
protected $beforeDelete = [];
protected $afterDelete = [];
private $_action = DB_ACTION["CREATE"];
protected function __construct()
{
parent::__construct();
}
abstract public function getTitleField(): string;
final public function getPKField(): string
{
return $this->primaryKey;
}
final public function getAction(): string
{
return $this->_action;
}
final public function setAction(string $action): string
{
return $this->_action = $action;
}
final public function getFields(array $options = []): array
{
if (isset($options['except'])) {
return array_diff_key($this->allowedFields, array_flip($options['except']));
} elseif (isset($options['only'])) {
return array_intersect_key($this->allowedFields, array_flip($options['only']));
}
return $this->allowedFields;
}
final public function getFieldRules(array $fields, array $rules = []): array
{
foreach ($fields as $field) {
$rules = $this->getFieldRule($field, $rules);
}
return $rules;
}
public function getFieldRule(string $field, array $rules): array
{
switch ($field) {
case $this->getPKField():
//수동입력인경우
if (!$this->useAutoIncrement) {
$rules[$field] = "required|regex_match[/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/]";
$rules[$field] .= $this->getAction() == DB_ACTION["CREATE"] ? "|is_unique[{$this->table}.{$field}]" : "";
} else {
$rules[$field] = "required|numeric";
};
break;
case $this->getTitleField():
$rules[$field] = "required|string";
break;
case "passwd":
$rules[$field] = $this->getAction() == DB_ACTION["CREATE"] ? "required|trim|string" : "if_exist|trim|string";
$rules["confirmpassword"] = $this->getAction() == DB_ACTION["CREATE"] ? "required|trim|string|matches[passwd]" : "if_exist|trim|string|matches[passwd]";
break;
case "email":
$rules[$field] = "if_exist|trim|valid_email";
break;
case 'image':
$rules[$field] = "is_image[{$field}]|mime_in[{$field},image/jpg,image/jpeg,image/gif,image/png,image/webp]|max_size[{$field},300]|max_dims[{$field},2048,768]";
break;
case "updated_at":
case "created_at":
case "deleted_at":
$rules[$field] = "if_exist|valid_date";
break;
default:
$rules[$field] = "if_exist|string";
break;
}
return $rules;
}
final public function getEntity(): array|object|null
{
return $this->asObject($this->returnType)->first();
}
final public function getEntitys(): array
{
return $this->asObject($this->returnType)->findAll();
}
//create , modify 직전 작업용 작업
protected function convertEntityData($entity, $field): mixed
{
if ($entity->$field === null) {
return $entity;
}
switch ($field) {
case $this->getPKField():
if ($entity->$field === null) {
$randomBytes = bin2hex(random_bytes(32));
$entity->$field = sprintf(
'%08s-%04s-%04x-%04x-%12s',
substr($randomBytes, 0, 8),
substr($randomBytes, 8, 4),
substr($randomBytes, 12, 4),
substr($randomBytes, 16, 4),
substr($randomBytes, 20, 12)
);
}
break;
case "passwd":
$entity->$field = password_hash($entity->$field, PASSWORD_DEFAULT);
break;
case "content":
$entity->$field = htmlentities($entity->$field, ENT_QUOTES);
break;
}
return $entity;
}
private function save_process($entity): mixed
{
//변경이 필요한 Field 재정의
foreach ($this->getFields() as $field) {
$entity = $this->convertEntityData($entity, $field);
}
//최종 변경사항이 있으면 저장
if ($entity->hasChanged()) {
if (!$this->save($entity)) {
log_message("error", __FUNCTION__ . "에서 호출:" . $this->getLastQuery());
log_message("error", implode("\n", $this->errors()));
throw new \Exception(__FUNCTION__ . " 오류 발생.\n" . $this->getLastQuery() . "\n" . var_dump($this->errors(), true));
}
} else {
throw new \Exception(__FUNCTION__ . " 오류 발생.\n 기존정보와 동일하여 수정되지 않았습니다.");
}
return $entity;
}
final protected function create_process($entity): mixed
{
$this->setAction(DB_ACTION['CREATE']);
//Field에 맞는 Validation Rule 재정의
$this->setValidationRules($this->getFieldRules($this->getFields()));
//primaryKey가 수동입력이면
$pkField = $this->getPKField();
if (!$this->useAutoIncrement && $entity->$pkField === null) {
//PrimayKey Field를 allowedFields의 맨앞에 넣기 -> array_unshif
array_unshift($this->allowedFields, $this->getPKField());
$entity = $this->convertEntityData($entity, $this->getPKField());
}
$entity = $this->save_process($entity);
//primaryKey가 자동입력이면
if ($this->useAutoIncrement) {
$entity->$pkField = $this->getInsertID();
}
// log_message("debug", $this->getTable() . " CREATE 작업 완료");
return $entity;
}
final protected function modify_process($entity): mixed
{
$this->setAction(DB_ACTION['MODIFY']);
//Field에 맞는 Validation Rule 재정의
$this->setValidationRules($this->getFieldRules($this->getFields()));
$this->save_process($entity);
// log_message("debug", $this->getTable() . " MODIFY 작업 완료");
return $entity;
}
}