Files
2026-04-01 10:30:52 +09:00

405 lines
11 KiB
PHP

<?php
/**
* 입력값 검증 함수
*
* 그누보드7 웹 인스톨러의 입력값 검증 기능을 제공합니다.
*/
/**
* 검증 에러 메시지를 다국어로 반환
*
* @param string $key 번역 키
* @param string $lang 언어 코드
* @param array $replacements 치환할 플레이스홀더 배열
* @return string 번역된 메시지
*/
function getValidationMessage(string $key, string $lang, array $replacements = []): string
{
$langFile = __DIR__ . "/../lang/{$lang}.php";
if (!file_exists($langFile)) {
return $key;
}
$translations = require $langFile;
$message = $translations[$key] ?? $key;
foreach ($replacements as $placeholder => $value) {
$message = str_replace(":{$placeholder}", $value, $message);
}
return $message;
}
/**
* 입력값 검증
*
* 주어진 규칙에 따라 입력값을 검증합니다.
*
* @param string $field 필드명
* @param mixed $value 검증할 값
* @param array $rules 검증 규칙 배열 (예: ['required', 'email', 'min:8'])
* @param array $data 전체 데이터 배열 (confirmed 규칙에 필요)
* @param string $lang 언어 코드 (ko 또는 en)
* @return array 검증 에러 배열 (빈 배열이면 검증 성공)
*/
function validateInput(string $field, $value, array $rules, array $data = [], string $lang = 'ko'): array
{
$errors = [];
foreach ($rules as $rule) {
// 규칙과 파라미터 분리 (예: 'min:8' => ['min', '8'])
$ruleParts = explode(':', $rule, 2);
$ruleName = $ruleParts[0];
$ruleParam = $ruleParts[1] ?? null;
// 각 규칙 검증
$errorMessage = null;
switch ($ruleName) {
case 'required':
$errorMessage = validateRequired($field, $value, $lang);
break;
case 'email':
$errorMessage = validateEmail($field, $value, $lang);
break;
case 'min':
$errorMessage = validateMin($field, $value, $ruleParam, $lang);
break;
case 'max':
$errorMessage = validateMax($field, $value, $ruleParam, $lang);
break;
case 'url':
$errorMessage = validateUrl($field, $value, $lang);
break;
case 'alpha_num':
$errorMessage = validateAlphaNum($field, $value, $lang);
break;
case 'confirmed':
$errorMessage = validateConfirmed($field, $value, $data, $lang);
break;
case 'numeric':
$errorMessage = validateNumeric($field, $value, $lang);
break;
case 'integer':
$errorMessage = validateInteger($field, $value, $lang);
break;
case 'in':
$allowedValues = $ruleParam ? explode(',', $ruleParam) : [];
$errorMessage = validateIn($field, $value, $allowedValues, $lang);
break;
default:
// 알 수 없는 규칙은 무시
break;
}
// 에러 메시지가 있으면 배열에 추가
if ($errorMessage !== null) {
$errors[] = $errorMessage;
}
}
return $errors;
}
/**
* 필수 입력 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateRequired(string $field, $value, string $lang): ?string
{
$isEmpty = $value === null
|| $value === ''
|| (is_array($value) && empty($value));
if ($isEmpty) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_required', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 이메일 형식 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateEmail(string $field, $value, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_email', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 최소 길이 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string|int $min 최소 길이
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateMin(string $field, $value, $min, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
$length = is_string($value) ? mb_strlen($value) : (is_numeric($value) ? $value : 0);
if ($length < (int) $min) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_min', $lang, ['field' => $fieldLabel, 'min' => $min]);
}
return null;
}
/**
* 최대 길이 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string|int $max 최대 길이
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateMax(string $field, $value, $max, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
$length = is_string($value) ? mb_strlen($value) : (is_numeric($value) ? $value : 0);
if ($length > (int) $max) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_max', $lang, ['field' => $fieldLabel, 'max' => $max]);
}
return null;
}
/**
* URL 형식 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateUrl(string $field, $value, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
if (!filter_var($value, FILTER_VALIDATE_URL)) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_url', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 영문자와 숫자만 허용 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateAlphaNum(string $field, $value, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
if (!ctype_alnum((string) $value)) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_alpha_num', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 확인 필드 일치 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param array $data 전체 데이터
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateConfirmed(string $field, $value, array $data, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
$confirmField = $field . '_confirmation';
$confirmValue = $data[$confirmField] ?? null;
if ($value !== $confirmValue) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_confirmed', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 숫자 형식 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateNumeric(string $field, $value, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
if (!is_numeric($value)) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_numeric', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 정수 형식 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateInteger(string $field, $value, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
if (!filter_var($value, FILTER_VALIDATE_INT)) {
$fieldLabel = getFieldLabel($field, $lang);
return getValidationMessage('validation_integer', $lang, ['field' => $fieldLabel]);
}
return null;
}
/**
* 허용된 값 목록 검증
*
* @param string $field 필드명
* @param mixed $value 값
* @param array $allowedValues 허용된 값 목록
* @param string $lang 언어
* @return string|null 에러 메시지 (성공 시 null)
*/
function validateIn(string $field, $value, array $allowedValues, string $lang): ?string
{
// 빈 값은 required 규칙에서 처리
if ($value === null || $value === '') {
return null;
}
if (!in_array($value, $allowedValues, true)) {
$fieldLabel = getFieldLabel($field, $lang);
$allowedList = implode(', ', $allowedValues);
return getValidationMessage('validation_in', $lang, ['field' => $fieldLabel, 'values' => $allowedList]);
}
return null;
}
/**
* 필드 라벨 반환
*
* 다국어 파일에서 필드 라벨을 가져옵니다.
*
* @param string $field 필드명
* @param string $lang 언어 코드 (ko 또는 en)
* @return string 필드 라벨
*/
function getFieldLabel(string $field, string $lang): string
{
// 다국어 파일 경로
$langFile = __DIR__ . "/../lang/{$lang}.php";
// 다국어 파일이 존재하지 않으면 필드명 반환
if (!file_exists($langFile)) {
return $field;
}
$translations = require $langFile;
// fields 키에서 해당 필드 반환 (없으면 필드명 반환)
return $translations['fields'][$field] ?? $field;
}
/**
* 여러 필드 일괄 검증
*
* @param array $data 검증할 데이터
* @param array $rules 필드별 검증 규칙 (예: ['email' => ['required', 'email']])
* @param string $lang 언어 코드
* @return array 필드별 에러 배열 (빈 배열이면 검증 성공)
*/
function validateMultiple(array $data, array $rules, string $lang = 'ko'): array
{
$errors = [];
foreach ($rules as $field => $fieldRules) {
$value = $data[$field] ?? null;
$fieldErrors = validateInput($field, $value, $fieldRules, $data, $lang);
if (!empty($fieldErrors)) {
$errors[$field] = $fieldErrors;
}
}
return $errors;
}