Files
Gnuboard7/app/Console/Commands/MigrateSettingsToJsonCommand.php
T
2026-05-11 11:29:41 +09:00

212 lines
6.7 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Console\Commands\Traits\HasUnifiedConfirm;
use App\Models\SystemConfig;
use App\Repositories\JsonConfigRepository;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Schema;
/**
* 기존 DB 설정을 JSON 파일로 마이그레이션하는 커맨드
*/
class MigrateSettingsToJsonCommand extends Command
{
use HasUnifiedConfirm;
/**
* 커맨드 시그니처
*
* @var string
*/
protected $signature = 'settings:migrate-to-json
{--force : 기존 JSON 파일이 있어도 덮어쓰기}';
/**
* 커맨드 설명
*
* @var string
*/
protected $description = 'DB의 system_configs 테이블 데이터를 JSON 파일로 마이그레이션합니다.';
/**
* 설정 키와 카테고리 매핑
*
* @var array<string, string>
*/
private array $categoryMap = [
// general
'site_name' => 'general',
'site_url' => 'general',
'site_description' => 'general',
'admin_email' => 'general',
'timezone' => 'general',
'language' => 'general',
'currency' => 'general',
'maintenance_mode' => 'general',
'description' => 'general',
'keywords' => 'general',
// security
'force_https' => 'security',
'login_attempt_enabled' => 'security',
'auth_token_lifetime' => 'security',
'max_login_attempts' => 'security',
'login_lockout_time' => 'security',
'two_factor_auth' => 'security',
'password_min_length' => 'security',
'require_password_special_char' => 'security',
// mail
'mailer' => 'mail',
'mail_host' => 'mail',
'mail_port' => 'mail',
'mail_username' => 'mail',
'mail_password' => 'mail',
'mail_encryption' => 'mail',
'mail_from_address' => 'mail',
'mail_from_name' => 'mail',
// upload
'max_file_size' => 'upload',
'allowed_extensions' => 'upload',
'image_max_width' => 'upload',
'image_max_height' => 'upload',
'image_quality' => 'upload',
// seo
'meta_title_suffix' => 'seo',
'meta_description' => 'seo',
'meta_keywords' => 'seo',
'google_analytics_id' => 'seo',
'google_site_verification' => 'seo',
'naver_site_verification' => 'seo',
// cache
'cache_enabled' => 'cache',
'layout_cache_enabled' => 'cache',
'layout_cache_ttl' => 'cache',
'stats_cache_enabled' => 'cache',
'stats_cache_ttl' => 'cache',
'seo_cache_enabled' => 'cache',
'seo_cache_ttl' => 'cache',
// debug
'debug_mode' => 'debug',
'sql_query_log' => 'debug',
'log_level' => 'debug',
];
/**
* 키 이름 변환 매핑 (DB 키 -> JSON 키)
*
* @var array<string, string>
*/
private array $keyMapping = [
'mail_host' => 'host',
'mail_port' => 'port',
'mail_username' => 'username',
'mail_password' => 'password',
'mail_encryption' => 'encryption',
'mail_from_address' => 'from_address',
'mail_from_name' => 'from_name',
'cache_enabled' => 'enabled',
'layout_cache_enabled' => 'layout_enabled',
'layout_cache_ttl' => 'layout_ttl',
'stats_cache_enabled' => 'stats_enabled',
'stats_cache_ttl' => 'stats_ttl',
'seo_cache_enabled' => 'seo_enabled',
'seo_cache_ttl' => 'seo_ttl',
'debug_mode' => 'mode',
];
/**
* 커맨드를 실행합니다.
*
* DI 컨테이너 바인딩 시점 문제로 직접 인스턴스화합니다.
*/
public function handle(): int
{
$this->info('설정 마이그레이션을 시작합니다...');
// system_configs 테이블 존재 확인
if (! Schema::hasTable('system_configs')) {
$this->warn('system_configs 테이블이 존재하지 않습니다. 기본값으로 초기화합니다.');
$configRepository = new JsonConfigRepository;
$configRepository->initialize();
$this->info('기본 설정 파일이 생성되었습니다.');
return Command::SUCCESS;
}
// JsonConfigRepository 직접 인스턴스화 (DI 컨테이너 바인딩 전 실행 가능)
$configRepository = new JsonConfigRepository;
// 기존 JSON 파일 존재 확인
if (file_exists(storage_path('app/settings/general.json')) && ! $this->option('force')) {
if (! $this->unifiedConfirm('기존 JSON 설정 파일이 존재합니다. 덮어쓰시겠습니까?', false)) {
$this->info('마이그레이션이 취소되었습니다.');
return Command::SUCCESS;
}
}
// 기존 설정 조회
$configs = SystemConfig::all();
if ($configs->isEmpty()) {
$this->warn('마이그레이션할 설정이 없습니다. 기본값으로 초기화합니다.');
$configRepository->initialize();
$this->info('기본 설정 파일이 생성되었습니다.');
return Command::SUCCESS;
}
$this->info("총 {$configs->count()}개의 설정을 발견했습니다.");
// 카테고리별로 그룹화
$grouped = [];
foreach ($configs as $config) {
$category = $this->categoryMap[$config->key] ?? 'general';
$jsonKey = $this->keyMapping[$config->key] ?? $config->key;
$grouped[$category][$jsonKey] = $this->parseValue($config->value, $config->type);
}
// JSON 파일로 저장
$defaults = $configRepository->getDefaults();
foreach ($defaults as $category => $defaultSettings) {
$categorySettings = array_merge(
$defaultSettings,
$grouped[$category] ?? []
);
$configRepository->saveCategory($category, $categorySettings);
$this->info(" ✓ {$category} 카테고리 저장 완료");
}
$this->newLine();
$this->info('마이그레이션이 완료되었습니다!');
$this->info('설정 파일 위치: storage/app/settings/');
return Command::SUCCESS;
}
/**
* 문자열 값을 원래 타입으로 파싱합니다.
*/
private function parseValue(string $value, string $type): mixed
{
return match ($type) {
'boolean' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
'integer' => (int) $value,
'float' => (float) $value,
'json', 'array' => json_decode($value, true) ?: [],
default => $value,
};
}
}