Files
Gnuboard7/app/Http/Resources/UserNotificationResource.php
T
2026-04-20 20:37:49 +09:00

93 lines
2.9 KiB
PHP

<?php
namespace App\Http\Resources;
use App\Contracts\Repositories\NotificationDefinitionRepositoryInterface;
use Illuminate\Http\Request;
class UserNotificationResource extends BaseApiResource
{
/**
* type 식별자 → 다국어 라벨 맵 (Collection에서 사전 주입).
*
* Collection에서 일괄 응답 시 N+1을 회피하기 위해 한 번만 로드한 맵을 주입받습니다.
* 단일 Resource로 사용될 경우 null이며, toArray() 내부에서 즉시 조회합니다.
*
* @var array<string, string>|null
*/
protected ?array $typeLabelMap = null;
/**
* 사전 주입된 type 라벨 맵을 설정합니다.
*
* @param array<string, string> $map
* @return $this
*/
public function withTypeLabelMap(array $map): static
{
$this->typeLabelMap = $map;
return $this;
}
/**
* 리소스를 배열로 변환합니다.
*
* @param Request $request
* @return array
*/
public function toArray(Request $request): array
{
$data = $this->getValue('data') ?? [];
$user = $request->user();
$timezone = $user?->getTimezone() ?? config('app.default_user_timezone', 'Asia/Seoul');
$type = $data['type'] ?? $this->getValue('type');
$typeLabel = $this->resolveTypeLabel($type, $user?->locale);
// 알림 클릭 시 이동 URL — click_url(템플릿 패턴 기반) 우선, 없으면 action_url(메일 CTA) fallback
$innerData = $data['data'] ?? [];
$url = $data['click_url'] ?? $innerData['action_url'] ?? null;
return [
'id' => $this->getValue('id'),
'type' => $type,
'type_label' => $typeLabel,
'subject' => $data['subject'] ?? null,
'body' => $data['body'] ?? null,
'url' => $url,
'data' => $data,
'read_at' => $this->resource->read_at?->setTimezone($timezone)->format('Y-m-d H:i:s'),
'created_at' => $this->resource->created_at?->setTimezone($timezone)->format('Y-m-d H:i:s'),
];
}
/**
* type 식별자에 해당하는 다국어 라벨을 해석합니다.
*
* 우선순위:
* 1. Collection에서 사전 주입한 typeLabelMap
* 2. Repository에서 즉시 조회 (단일 Resource 사용 시)
* 3. 정의 미존재 시 type 식별자 그대로 반환 (UI에 raw 키 노출 방지 fallback)
*
* @param string|null $type
* @param string|null $locale
* @return string
*/
protected function resolveTypeLabel(?string $type, ?string $locale): string
{
if (! $type) {
return '';
}
if ($this->typeLabelMap !== null) {
return $this->typeLabelMap[$type] ?? '';
}
$repository = app(NotificationDefinitionRepositoryInterface::class);
$definition = $repository->getActiveByType($type);
return $definition?->getLocalizedName($locale) ?: '';
}
}