Files
Gnuboard7/app/Http/Requests/Admin/UpdatePluginSettingsRequest.php
T
HeuJung b127afcea7 fix(identity): 잔여 과제 전건 처리 + 로딩 표시 실렌더 확정
앞선 커밋이 CHANGELOG 에 주장한 "로딩 표시가 나오지 않던 문제 수정" 이 실제로
화면에 나타나는지 브라우저로 확정했다. 전달 경로부터 DOM 마운트·해제까지 측정했고,
지연·에러 응답에서도 영구 로딩이 남지 않음을 확인했다.

측정 과정에서 앞선 세션의 판단 하나가 틀렸음을 확인했다 — "오버레이 DOM 이 어느
화면에서도 관측되지 않는다" 는 관측 대상 노드를 잘못 잡은 것이었다. 스피너 방식
레이아웃은 다른 노드를 쓰며, 대조군에서도 안 보였던 이유가 이것이다.

미뤄 두었던 과제 4건을 함께 구현했다.

- 인증창을 그냥 닫고 이탈하면 그 인증 요청을 서버에도 종료로 표시한다.
 이전에는 브라우저만 알고 있어 인증 이력에 "보낸 뒤 소식 없는" 항목이 남았다
- 플러그인 설정 화면이 저장된 비밀값을 다시 내려받던 것을 가려서 표시한다.
 그 항목을 건드리지 않고 저장하면 저장된 값이 그대로 유지된다
- 언어팩 반영 누락 검사가 버전만 비교해 "버전 같고 내용 다름" 을 놓치던 사각을
 콘텐츠 비교로 닫았다
- 확장이 검증 규칙을 추가할 때 쓰는 필터 이름 6개를 표준 형태로 통일했다.
 예전 이름도 함께 발행하므로 기존 확장은 수정 없이 동작한다

정적 검사 룰 2종의 오탐·사각을 함께 고쳤고, 개명으로 검사 대상에 편입된 파일의
사전 결함 8건을 해소했다. 검수용 데이터는 전량 정리했다.
2026-07-31 00:32:48 +09:00

147 lines
4.7 KiB
PHP

<?php
namespace App\Http\Requests\Admin;
use App\Extension\HookManager;
use App\Extension\PluginManager;
use Illuminate\Foundation\Http\FormRequest;
/**
* 플러그인 설정 업데이트 요청 검증
*
* 플러그인의 설정 스키마를 기반으로 동적으로 유효성 검사 규칙을 생성합니다.
*/
class UpdatePluginSettingsRequest extends FormRequest
{
/**
* 사용자가 이 요청을 수행할 권한이 있는지 확인합니다.
*
* 권한 체크는 라우트의 permission 미들웨어에서 수행됩니다.
*
* @return bool 항상 true
*/
public function authorize(): bool
{
return true;
}
/**
* 요청에 적용할 검증 규칙을 반환합니다.
*
* 플러그인의 설정 스키마를 기반으로 동적으로 규칙을 생성합니다.
*
* @return array 검증 규칙 배열
*/
public function rules(): array
{
$identifier = $this->route('identifier');
$pluginManager = app(PluginManager::class);
$plugin = $pluginManager->getPlugin($identifier);
if (! $plugin) {
return [];
}
$schema = $plugin->getSettingsSchema();
$rules = [];
foreach ($schema as $field => $config) {
$fieldRules = [];
// 필수 여부
if ($config['required'] ?? false) {
$fieldRules[] = 'required';
} else {
$fieldRules[] = 'nullable';
}
// 타입별 규칙 추가
$type = $config['type'] ?? 'string';
switch ($type) {
case 'string':
$fieldRules[] = 'string';
if (isset($config['max'])) {
$fieldRules[] = 'max:'.$config['max'];
}
if (isset($config['min'])) {
$fieldRules[] = 'min:'.$config['min'];
}
break;
case 'integer':
$fieldRules[] = 'integer';
if (isset($config['min'])) {
$fieldRules[] = 'min:'.$config['min'];
}
if (isset($config['max'])) {
$fieldRules[] = 'max:'.$config['max'];
}
break;
case 'boolean':
$fieldRules[] = 'boolean';
break;
case 'enum':
$options = $config['options'] ?? [];
if (! empty($options)) {
$fieldRules[] = 'in:'.implode(',', $options);
}
break;
case 'url':
$fieldRules[] = 'url';
break;
case 'email':
$fieldRules[] = 'email';
break;
case 'array':
$fieldRules[] = 'array';
break;
}
$rules[$field] = $fieldRules;
}
// 표준 이름(`core.{대상}.{동작}_validation_rules`)으로 발행하되, 이미 공개돼 구독 중일 수 있는
// 구 이름(`core.plugin_settings.update_rules`)도 함께 발행한다 — 구 이름을 구독하는 제3자
// 확장이 조용히 멈추지 않도록 한다. 구 이름은 구독자가 있을 때만 1회 경고가 남는다.
//
// 3번째 인자로 이번 요청의 입력값을 함께 넘긴다. 확장이 "현재 입력한 모드에 따라
// 다른 필드를 필수로 만드는" 조건부 규칙을 만들려면 입력값이 필요한데, 그것이 없어
// 확장이 request() 를 직접 들여다보던 것을 없애기 위함이다.
// 기존 2인자 구독자는 그대로 동작한다(초과 인자는 무시된다).
return HookManager::applyFiltersWithLegacyName(
'core.plugin_settings.update_validation_rules',
'core.plugin_settings.update_rules',
$rules,
$identifier,
$this->all(),
);
}
/**
* 검증 에러 메시지를 반환합니다.
*
* @return array 에러 메시지 배열
*/
public function messages(): array
{
return [
'required' => __('validation.required'),
'string' => __('validation.string'),
'integer' => __('validation.integer'),
'boolean' => __('validation.boolean'),
'in' => __('validation.in'),
'url' => __('validation.url'),
'email' => __('validation.email'),
'array' => __('validation.array'),
'max' => __('validation.max'),
'min' => __('validation.min'),
];
}
}