Files
SkinbaseNova/app/Services/Sitemaps/PublishedSitemapResolver.php

77 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Sitemaps;
final class PublishedSitemapResolver
{
public function __construct(private readonly SitemapReleaseManager $releases)
{
}
/**
* @return array{content: string, release_id: string, document_name: string}|null
*/
public function resolveIndex(): ?array
{
return $this->resolveDocumentName(SitemapCacheService::INDEX_DOCUMENT);
}
/**
* @return array{content: string, release_id: string, document_name: string}|null
*/
public function resolveNamed(string $requestedName): ?array
{
$manifest = $this->releases->activeManifest();
if ($manifest === null) {
return null;
}
$documentName = $this->canonicalDocumentName($requestedName, $manifest);
return $documentName !== null ? $this->resolveDocumentName($documentName) : null;
}
private function resolveDocumentName(string $documentName): ?array
{
$releaseId = $this->releases->activeReleaseId();
if ($releaseId === null) {
return null;
}
$content = $this->releases->getDocument($releaseId, $documentName);
return is_string($content) && $content !== ''
? ['content' => $content, 'release_id' => $releaseId, 'document_name' => $documentName]
: null;
}
private function canonicalDocumentName(string $requestedName, array $manifest): ?string
{
$documents = (array) ($manifest['documents'] ?? []);
if (isset($documents[$requestedName])) {
return $requestedName;
}
foreach ((array) ($manifest['families'] ?? []) as $familyName => $family) {
$entryName = (string) ($family['entry_name'] ?? '');
if ($requestedName === $familyName && $entryName !== '') {
return $entryName;
}
if (preg_match('/^' . preg_quote((string) $familyName, '/') . '-([0-9]+)$/', $requestedName, $matches)) {
$number = (int) $matches[1];
$candidate = sprintf('%s-%04d', $familyName, $number);
if (in_array($candidate, (array) ($family['shards'] ?? []), true)) {
return $candidate;
}
}
}
return null;
}
}