Files
2026-10-06 15:15:53 +01:00

66 lines
2.1 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use InvalidArgumentException;
final class IndexNowService
{
/** @param array<int, string> $urls */
public function submit(array $urls): ?Response
{
if (! config('indexnow.enabled')) {
Log::info('IndexNow submission skipped: disabled.');
return null;
}
$key = trim((string) config('indexnow.key'));
if ($key === '') {
throw new InvalidArgumentException('INDEXNOW_KEY is not configured.');
}
$urls = collect($urls)
->filter(fn ($url) => is_string($url) && filter_var($url, FILTER_VALIDATE_URL))
->unique()
->values()
->all();
if ($urls === []) {
throw new InvalidArgumentException('No valid URLs were supplied to IndexNow.');
}
$host = parse_url($urls[0], PHP_URL_HOST);
if (! is_string($host) || $host === '') {
throw new InvalidArgumentException('Could not determine the IndexNow host.');
}
foreach ($urls as $url) {
if (parse_url($url, PHP_URL_HOST) !== $host) {
throw new InvalidArgumentException('All IndexNow URLs must use the same host.');
}
}
$response = Http::asJson()
->acceptJson()
->timeout(10)
->retry(2, 500)
->post((string) config('indexnow.endpoint'), [
'host' => $host,
'key' => $key,
'keyLocation' => 'https://'.$host.'/'.$key.'.txt',
'urlList' => $urls,
]);
if ($response->successful()) {
Log::info('IndexNow URLs submitted.', ['host' => $host, 'count' => count($urls), 'status' => $response->status()]);
} else {
Log::warning('IndexNow submission failed.', ['host' => $host, 'count' => count($urls), 'status' => $response->status(), 'body' => $response->body()]);
}
return $response;
}
}