Files

197 lines
5.7 KiB
PHP
Raw Permalink Normal View History

2026-04-04 02:14:57 +03:00
<?php
namespace App\Services;
2026-05-01 03:14:52 +03:00
use App\Models\Article;
2026-04-04 02:14:57 +03:00
use App\Models\Job;
use App\Models\JobCategory;
use Illuminate\Support\Facades\URL;
class SitemapService
{
/**
* Generate XML sitemap
*/
public function generateSitemap(): string
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
// Add homepage
$this->addUrl($xml, route('home'), now(), 'daily', '1.0');
// Add jobs index
$this->addUrl($xml, route('jobs.index'), now(), 'daily', '0.9');
// Add remote jobs
$this->addUrl($xml, route('jobs.remote'), now(), 'daily', '0.9');
// Add categories
$categories = JobCategory::all();
foreach ($categories as $category) {
$this->addUrl(
$xml,
route('jobs.category', $category->slug),
$category->updated_at,
'daily',
'0.8'
);
}
// Add active jobs
$jobs = Job::where(function ($query) {
$query->whereNull('expires_at')
->orWhere('expires_at', '>', now());
})
->orderBy('posted_at', 'desc')
->limit(10000) // Limit to 10k most recent jobs
2026-04-04 18:19:34 +03:00
->get(['id', 'slug', 'posted_at', 'updated_at']);
2026-04-04 02:14:57 +03:00
foreach ($jobs as $job) {
$this->addUrl(
$xml,
2026-04-04 18:19:34 +03:00
route('jobs.show', $job),
2026-04-04 02:14:57 +03:00
$job->updated_at ?? $job->posted_at,
'weekly',
'0.7'
);
}
return $xml->asXML();
}
/**
* Add URL to sitemap
*/
private function addUrl(
\SimpleXMLElement $xml,
string $url,
?\DateTimeInterface $lastmod = null,
string $changefreq = 'weekly',
string $priority = '0.5'
): void {
$urlElement = $xml->addChild('url');
$urlElement->addChild('loc', htmlspecialchars($url));
if ($lastmod) {
$urlElement->addChild('lastmod', $lastmod->format('Y-m-d'));
}
$urlElement->addChild('changefreq', $changefreq);
$urlElement->addChild('priority', $priority);
}
/**
* Generate sitemap index for large sites
*/
public function generateSitemapIndex(): string
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></sitemapindex>');
// Add main sitemap
$this->addSitemapToIndex($xml, route('sitemap.main'), now());
// Add jobs sitemap
$this->addSitemapToIndex($xml, route('sitemap.jobs'), now());
2026-05-01 03:14:52 +03:00
// Add blog sitemap
$this->addSitemapToIndex($xml, route('sitemap.blog'), now());
2026-04-04 02:14:57 +03:00
return $xml->asXML();
}
/**
* Add sitemap to index
*/
private function addSitemapToIndex(\SimpleXMLElement $xml, string $url, \DateTimeInterface $lastmod): void
{
$sitemapElement = $xml->addChild('sitemap');
$sitemapElement->addChild('loc', htmlspecialchars($url));
$sitemapElement->addChild('lastmod', $lastmod->format('Y-m-d'));
}
2026-05-01 03:14:52 +03:00
/**
* Generate blog sitemap
*/
public function generateBlogSitemap(): string
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
$this->addUrl($xml, route('blog.index'), now(), 'daily', '0.8');
Article::published()
->orderByDesc('published_at')
->get(['slug', 'published_at', 'updated_at'])
->each(function (Article $article) use ($xml) {
$this->addUrl(
$xml,
route('blog.show', $article),
$article->updated_at,
'monthly',
'0.7'
);
});
return $xml->asXML();
}
2026-04-04 02:14:57 +03:00
/**
* Generate main sitemap (static pages and categories)
*/
public function generateMainSitemap(): string
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
// Add homepage
$this->addUrl($xml, route('home'), now(), 'daily', '1.0');
// Add jobs index
$this->addUrl($xml, route('jobs.index'), now(), 'daily', '0.9');
// Add remote jobs
$this->addUrl($xml, route('jobs.remote'), now(), 'daily', '0.9');
// Add categories
$categories = JobCategory::all();
foreach ($categories as $category) {
$this->addUrl(
$xml,
route('jobs.category', $category->slug),
$category->updated_at,
'daily',
'0.8'
);
}
return $xml->asXML();
}
/**
* Generate jobs sitemap
*/
public function generateJobsSitemap(): string
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
// Add active jobs
$jobs = Job::where(function ($query) {
$query->whereNull('expires_at')
->orWhere('expires_at', '>', now());
})
->orderBy('posted_at', 'desc')
->limit(50000) // Sitemap limit
2026-04-04 18:19:34 +03:00
->get(['id', 'slug', 'posted_at', 'updated_at']);
2026-04-04 02:14:57 +03:00
foreach ($jobs as $job) {
$this->addUrl(
$xml,
2026-04-04 18:19:34 +03:00
route('jobs.show', $job),
2026-04-04 02:14:57 +03:00
$job->updated_at ?? $job->posted_at,
'weekly',
'0.7'
);
}
return $xml->asXML();
}
}