$entries URL 항목 */ public function indexResource(string $type, string|int $id, string $contributor, array $entries): void { $entries = HookManager::applyFilters(self::COLLECT_FILTER, $entries, $type, $id, $contributor); if (! is_array($entries) || $entries === []) { // 색인할 항목이 없으면(모두 제외됨) 기존 색인을 제거해 정합을 유지합니다. $this->repository->removeForResource($type, (string) $id); return; } $normalized = []; foreach ($entries as $entry) { if (! is_array($entry)) { continue; } $loc = $this->resolveLoc($entry); if ($loc === null) { continue; } $normalized[] = [ 'loc' => $loc, 'lastmod' => $entry['lastmod'] ?? null, // 폐쇄 어휘로 정규화 — 비표준 값이 sitemap_urls 에 저장되는 것을 차단. 'changefreq' => SitemapChangeFreq::normalize($entry['changefreq'] ?? null), 'priority' => $entry['priority'] ?? null, 'contributor' => $contributor, ]; } if ($normalized === []) { $this->repository->removeForResource($type, (string) $id); return; } $this->repository->upsertForResource($type, (string) $id, $normalized); } /** * 비공개/삭제된 리소스의 사이트맵 URL 색인을 제거합니다. * * @param string $type 리소스 유형 * @param string|int $id 리소스 PK */ public function deindexResource(string $type, string|int $id): void { $this->repository->removeForResource($type, (string) $id); } /** * 항목의 절대 URL(loc)을 해석합니다. * * 'loc'(절대 URL)이 있으면 그대로, 없으면 'url'(상대 경로)을 url() 로 절대화합니다. * * @param array $entry URL 항목 * @return string|null 절대 URL (해석 불가 시 null) */ private function resolveLoc(array $entry): ?string { if (isset($entry['loc']) && is_string($entry['loc']) && $entry['loc'] !== '') { return $entry['loc']; } if (isset($entry['url']) && is_string($entry['url']) && $entry['url'] !== '') { return url($entry['url']); } return null; } }