168 lines
4.8 KiB
PHP
168 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
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
|
|
->get(['id', 'posted_at', 'updated_at']);
|
|
|
|
foreach ($jobs as $job) {
|
|
$this->addUrl(
|
|
$xml,
|
|
route('jobs.show', $job->id),
|
|
$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());
|
|
|
|
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'));
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
->get(['id', 'posted_at', 'updated_at']);
|
|
|
|
foreach ($jobs as $job) {
|
|
$this->addUrl(
|
|
$xml,
|
|
route('jobs.show', $job->id),
|
|
$job->updated_at ?? $job->posted_at,
|
|
'weekly',
|
|
'0.7'
|
|
);
|
|
}
|
|
|
|
return $xml->asXML();
|
|
}
|
|
}
|