<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Models\Article;
use App\Models\Down;
use App\Models\News;
use App\Models\Topic;
use Illuminate\Database\Query\JoinClause;
use Illuminate\View\View;
class SitemapController extends Controller
{
/**
* @var array
*/
public $pages = [
'news',
'articles',
'topics',
'downs',
];
/**
* Генерируем главную страницу
*
* @return View
*/
public function index(): View
{
$locs = [];
foreach ($this->pages as $page) {
$locs[] = [
'loc' => config('app.url') . '/sitemap/' . $page . '.xml',
'lastmod' => date('c', SITETIME),
];
}
return view('sitemap/index', compact('locs'));
}
/**
* Вызывает страницу
*
* @param string $page
*
* @return View
*/
public function page(string $page): View
{
if (! in_array($page, $this->pages, true)) {
abort(404);
}
return $this->$page();
}
/**
* Генерируем статьи
*
* @return View
*/
private function articles(): View
{
$articles = Article::query()
->selectRaw('articles.*, max(c.created_at) as last_time')
->leftJoin('comments as c', static function (JoinClause $join) {
$join->on('articles.id', 'c.relate_id')
->where('relate_type', Article::$morphName);
})
->groupBy('articles.id')
->orderByDesc('last_time')
->get();
$locs = [];
foreach ($articles as $article) {
$changeTime = ($article->last_time > $article->created_at) ? $article->last_time : $article->created_at;
// Обновлено менее 1 месяца
$new = SITETIME < strtotime('+1 month', $changeTime);
$locs[] = [
'loc' => config('app.url') . '/articles/' . $article->id,
'lastmod' => date('c', $changeTime),
'changefreq' => $new ? 'weekly' : 'monthly',
'priority' => $new ? '1.0' : '0.5',
];
}
return view('sitemap/url', compact('locs'));
}
/**
* Генерируем новости
*
* @return View
*/
private function news(): View
{
$newses = News::query()
->selectRaw('news.*, max(c.created_at) as last_time')
->leftJoin('comments as c', static function (JoinClause $join) {
$join->on('news.id', 'c.relate_id')
->where('relate_type', News::$morphName);
})
->groupBy('news.id')
->orderByDesc('last_time')
->get();
$locs = [];
foreach ($newses as $news) {
$changeTime = ($news->last_time > $news->created_at) ? $news->last_time : $news->created_at;
// Обновлено менее 1 месяца
$new = SITETIME < strtotime('+1 month', $changeTime);
$locs[] = [
'loc' => config('app.url') . '/news/' . $news->id,
'lastmod' => date('c', $changeTime),
'changefreq' => $new ? 'weekly' : 'monthly',
'priority' => $new ? '1.0' : '0.5',
];
}
return view('sitemap/url', compact('locs'));
}
/**
* Генерируем темы форума
*
* @return View
*/
private function topics(): View
{
$topics = Topic::query()->orderByDesc('updated_at')->limit(15000)->get();
$locs = [];
foreach ($topics as $topic) {
// Обновлено менее 1 месяца
$new = SITETIME < strtotime('+1 month', $topic->updated_at);
$locs[] = [
'loc' => config('app.url') . '/topics/' . $topic->id,
'lastmod' => date('c', $topic->updated_at),
'changefreq' => $new ? 'weekly' : 'monthly',
'priority' => $new ? '1.0' : '0.5',
];
}
return view('sitemap/url', compact('locs'));
}
/**
* Генерируем загрузки
*
* @return View
*/
private function downs(): View
{
$downs = Down::query()
->selectRaw('downs.*, max(c.created_at) as last_time')
->leftJoin('comments as c', static function (JoinClause $join) {
$join->on('downs.id', 'c.relate_id')
->where('relate_type', Down::$morphName);
})
->groupBy('downs.id')
->orderByDesc('last_time')
->get();
$locs = [];
foreach ($downs as $down) {
$changeTime = ($down->last_time > $down->created_at) ? $down->last_time : $down->created_at;
// Обновлено менее 1 месяца
$new = SITETIME < strtotime('+1 month', $changeTime);
$locs[] = [
'loc' => config('app.url') . '/downs/' . $down->id,
'lastmod' => date('c', $changeTime),
'changefreq' => $new ? 'weekly' : 'monthly',
'priority' => $new ? '1.0' : '0.5',
];
}
return view('sitemap/url', compact('locs'));
}
}