withHeaders([ 'User-Agent' => 'Mozilla/5.0 (compatible; SitemapMonitor/1.0)', ]) ->get($this->sitemap->url); if (!$response->successful()) { $this->sitemap->markAsInvalid( "HTTP {$response->status()}: Failed to fetch sitemap" ); $this->sendAlert("Sitemap is inaccessible (HTTP {$response->status()})"); return; } // Get the response body $xmlContent = $response->body(); // Validate XML structure using simplexml_load_string libxml_use_internal_errors(true); $xml = simplexml_load_string($xmlContent); if ($xml === false) { $errors = libxml_get_errors(); $errorMessages = array_map(fn($error) => trim($error->message), $errors); libxml_clear_errors(); $this->sitemap->markAsInvalid( 'Invalid XML: ' . implode('; ', $errorMessages) ); $this->sendAlert('Sitemap contains invalid XML'); return; } // Check if it's a valid sitemap (has urlset or sitemapindex) $namespaces = $xml->getNamespaces(true); $isUrlset = isset($xml->url) || isset($namespaces['']); $isSitemapIndex = isset($xml->sitemap); if (!$isUrlset && !$isSitemapIndex) { $this->sitemap->markAsInvalid( 'Invalid sitemap format: Missing or root element' ); $this->sendAlert('Sitemap has invalid format'); return; } // Count URLs in the sitemap $urlCount = $this->countUrls($xml); // Mark as valid $this->sitemap->markAsValid($urlCount); Log::info('Sitemap validated successfully', [ 'sitemap_id' => $this->sitemap->id, 'url' => $this->sitemap->url, 'url_count' => $urlCount, ]); } catch (\Exception $e) { Log::error('Error checking sitemap', [ 'sitemap_id' => $this->sitemap->id, 'url' => $this->sitemap->url, 'error' => $e->getMessage(), ]); $this->sitemap->markAsInvalid( 'Exception: ' . $e->getMessage() ); $this->sendAlert('Sitemap check failed: ' . $e->getMessage()); throw $e; // Re-throw to allow job retry } } /** * Count URLs in the sitemap */ protected function countUrls(\SimpleXMLElement $xml): int { $count = 0; // Register namespaces $xml->registerXPathNamespace('sm', 'http://www.sitemaps.org/schemas/sitemap/0.9'); // Check for regular sitemap $urls = $xml->xpath('//sm:url') ?: $xml->xpath('//url'); if ($urls !== false) { $count = count($urls); } // If it's a sitemap index, count the sitemaps instead if ($count === 0) { $sitemaps = $xml->xpath('//sm:sitemap') ?: $xml->xpath('//sitemap'); if ($sitemaps !== false) { $count = count($sitemaps); } } return $count; } /** * Send alert notification for invalid sitemap */ protected function sendAlert(string $message): void { Notification::create([ 'user_id' => $this->sitemap->site->user_id, 'type' => 'sitemap_invalid', 'message' => "{$message}: {$this->sitemap->url}", 'data' => json_encode([ 'sitemap_id' => $this->sitemap->id, 'site_id' => $this->sitemap->site_id, 'url' => $this->sitemap->url, 'error' => $this->sitemap->last_error, ]), 'read_at' => null, ]); } }