Files
Gnuboard7/app/Extension/Helpers/IdentityMessageSyncHelper.php
T
2026-05-11 11:29:41 +09:00

152 lines
5.6 KiB
PHP

<?php
namespace App\Extension\Helpers;
use App\Models\IdentityMessageDefinition;
use App\Models\IdentityMessageTemplate;
use Illuminate\Support\Facades\Log;
/**
* IDV 메시지 정의/템플릿 동기화 헬퍼.
*
* 알림 시스템(NotificationSyncHelper)과 분리된 IDV 전용 헬퍼.
* (provider_id, scope_type, scope_value) 매트릭스를 키로 사용합니다.
*
* Seeder 는 본 helper 를 호출하는 얇은 진입점이며, 모든 데이터 정합성 로직은
* helper 에 집중됩니다. 내부 upsert 는 `HasUserOverrides::syncOrCreateFromUpgrade`
* 에 위임하여 trait 공통 API 를 재활용합니다.
*/
class IdentityMessageSyncHelper
{
/**
* 메시지 정의를 동기화합니다 (user_overrides 보존 upsert).
*
* @param array<string, mixed> $data definition 데이터 (provider_id, scope_type, scope_value,
* extension_type, extension_identifier, name, description,
* channels, variables, is_active, is_default, templates 포함 가능)
* @return IdentityMessageDefinition
*/
public function syncDefinition(array $data): IdentityMessageDefinition
{
$scopeValue = (string) ($data['scope_value'] ?? '');
return IdentityMessageDefinition::syncOrCreateFromUpgrade(
[
'provider_id' => $data['provider_id'],
'scope_type' => $data['scope_type'],
'scope_value' => $scopeValue,
],
[
'extension_type' => $data['extension_type'],
'extension_identifier' => $data['extension_identifier'],
'name' => $data['name'],
'description' => $data['description'] ?? null,
'channels' => $data['channels'] ?? ['mail'],
'variables' => $data['variables'] ?? [],
'is_active' => $data['is_active'] ?? true,
'is_default' => $data['is_default'] ?? true,
]
);
}
/**
* 메시지 템플릿을 동기화합니다 (user_overrides 보존 upsert).
*
* @param int $definitionId
* @param array<string, mixed> $data template 데이터 (channel, subject, body, is_active, is_default)
* @return IdentityMessageTemplate
*/
public function syncTemplate(int $definitionId, array $data): IdentityMessageTemplate
{
return IdentityMessageTemplate::syncOrCreateFromUpgrade(
['definition_id' => $definitionId, 'channel' => $data['channel']],
[
'subject' => $data['subject'] ?? null,
'body' => $data['body'],
'is_active' => $data['is_active'] ?? true,
'is_default' => $data['is_default'] ?? true,
]
);
}
/**
* stale 메시지 정의를 삭제합니다 (완전 동기화 원칙).
*
* 정책: `user_overrides` 무관 — config/seeder 에 없는 정의는 삭제.
* FK cascade 로 연관 templates 도 자동 정리됩니다.
*
* @param string $extensionType
* @param string $extensionIdentifier
* @param array<int, array{provider_id: string, scope_type: string, scope_value: string}> $currentScopes
* @return int 삭제된 definition 수
*/
public function cleanupStaleDefinitions(
string $extensionType,
string $extensionIdentifier,
array $currentScopes,
): int {
$currentKeys = array_map(
fn (array $s) => $s['provider_id'].'|'.$s['scope_type'].'|'.((string) ($s['scope_value'] ?? '')),
$currentScopes
);
$query = IdentityMessageDefinition::query()
->where('extension_type', $extensionType)
->where('extension_identifier', $extensionIdentifier);
$targets = $query->get(['id', 'provider_id', 'scope_type', 'scope_value']);
$stale = $targets->filter(function (IdentityMessageDefinition $def) use ($currentKeys) {
$key = $def->provider_id.'|'.$def->scope_type->value.'|'.((string) $def->scope_value);
return ! in_array($key, $currentKeys, true);
});
foreach ($stale as $def) {
$def->delete();
}
$count = $stale->count();
if ($count > 0) {
Log::info('stale IDV 메시지 정의 정리 완료', [
'extension_type' => $extensionType,
'extension_identifier' => $extensionIdentifier,
'deleted' => $count,
'scopes' => $stale->map(fn ($d) => $d->provider_id.'|'.$d->scope_type->value.'|'.$d->scope_value)->all(),
]);
}
return $count;
}
/**
* 주어진 definition 의 channel 목록 기준으로 stale template 을 삭제합니다.
*
* @param int $definitionId
* @param array<int, string> $currentChannels
* @return int 삭제된 template 수
*/
public function cleanupStaleTemplates(int $definitionId, array $currentChannels): int
{
$query = IdentityMessageTemplate::query()
->where('definition_id', $definitionId)
->whereNotIn('channel', $currentChannels);
$targets = $query->get(['id', 'channel']);
foreach ($targets as $template) {
$template->delete();
}
$count = $targets->count();
if ($count > 0) {
Log::info('stale IDV 메시지 템플릿 정리 완료', [
'definition_id' => $definitionId,
'deleted' => $count,
'channels' => $targets->pluck('channel')->all(),
]);
}
return $count;
}
}