Save workspace changes
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\News;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Services\News\NewsService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
use cPad\Plugins\News\Models\NewsArticle;
|
||||
use cPad\Plugins\News\Models\NewsCategory;
|
||||
use cPad\Plugins\News\Models\NewsTag;
|
||||
use cPad\Plugins\News\Models\NewsView;
|
||||
|
||||
class NewsController extends Controller
|
||||
{
|
||||
public function __construct(private readonly NewsService $news)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Homepage — /news
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$perPage = config('news.articles_per_page', 12);
|
||||
|
||||
$featured = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->editorialOrder()
|
||||
->first();
|
||||
|
||||
$highlightQuery = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->editorialOrder();
|
||||
|
||||
if ($featured) {
|
||||
$highlightQuery->where('id', '!=', $featured->id);
|
||||
}
|
||||
|
||||
$highlights = $highlightQuery->limit(3)->get();
|
||||
$excludedIds = collect([$featured?->id])->merge($highlights->pluck('id'))->filter()->all();
|
||||
|
||||
$articles = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->when($excludedIds !== [], fn ($query) => $query->whereNotIn('id', $excludedIds))
|
||||
->editorialOrder()
|
||||
->paginate($perPage);
|
||||
|
||||
return view('news.index', [
|
||||
'featured' => $featured,
|
||||
'highlights' => $highlights,
|
||||
'articles' => $articles,
|
||||
] + $this->sidebarData());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Category page — /news/category/{slug}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public function category(Request $request, string $slug): View
|
||||
{
|
||||
$category = NewsCategory::where('slug', $slug)->where('is_active', true)->firstOrFail();
|
||||
$perPage = config('news.articles_per_page', 12);
|
||||
|
||||
$articles = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->byCategory($category->id)
|
||||
->editorialOrder()
|
||||
->paginate($perPage);
|
||||
|
||||
return view('news.category', [
|
||||
'category' => $category,
|
||||
'articles' => $articles,
|
||||
] + $this->sidebarData());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Tag page — /news/tag/{slug}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public function tag(Request $request, string $slug): View
|
||||
{
|
||||
$tag = NewsTag::where('slug', $slug)->firstOrFail();
|
||||
$perPage = config('news.articles_per_page', 12);
|
||||
|
||||
$articles = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->whereHas('tags', fn ($q) => $q->where('news_tags.slug', $slug))
|
||||
->editorialOrder()
|
||||
->paginate($perPage);
|
||||
|
||||
return view('news.tag', [
|
||||
'tag' => $tag,
|
||||
'articles' => $articles,
|
||||
] + $this->sidebarData());
|
||||
}
|
||||
|
||||
public function archive(Request $request, int $year, int $month): View
|
||||
{
|
||||
abort_unless($month >= 1 && $month <= 12, 404);
|
||||
|
||||
$perPage = config('news.articles_per_page', 12);
|
||||
$articles = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->whereYear('published_at', $year)
|
||||
->whereMonth('published_at', $month)
|
||||
->editorialOrder()
|
||||
->paginate($perPage);
|
||||
|
||||
return view('news.archive', [
|
||||
'archiveDate' => now()->setDate($year, $month, 1),
|
||||
'articles' => $articles,
|
||||
] + $this->sidebarData());
|
||||
}
|
||||
|
||||
public function author(Request $request, string $username): View
|
||||
{
|
||||
$author = User::query()->with('profile')->where('username', $username)->firstOrFail();
|
||||
$perPage = config('news.articles_per_page', 12);
|
||||
$articles = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->where('author_id', $author->id)
|
||||
->editorialOrder()
|
||||
->paginate($perPage);
|
||||
|
||||
return view('news.author', [
|
||||
'author' => $author,
|
||||
'articles' => $articles,
|
||||
] + $this->sidebarData());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Article page — /news/{slug}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public function show(Request $request, string $slug): View
|
||||
{
|
||||
$article = NewsArticle::with('author.profile', 'category', 'tags', 'relatedEntities')
|
||||
->published()
|
||||
->where('slug', $slug)
|
||||
->firstOrFail();
|
||||
|
||||
// Track view (once per session / IP)
|
||||
$this->trackView($request, $article);
|
||||
|
||||
// Related articles (same category, excluding current)
|
||||
$related = NewsArticle::with('author', 'category')
|
||||
->published()
|
||||
->when($article->category_id, fn ($q) => $q->where('category_id', $article->category_id))
|
||||
->where('id', '!=', $article->id)
|
||||
->editorialOrder()
|
||||
->limit(config('news.related_limit', 4))
|
||||
->get();
|
||||
|
||||
return view('news.show', [
|
||||
'article' => $article,
|
||||
'related' => $related,
|
||||
'relatedEntities' => $this->news->resolveRelatedEntities($article, $request->user()),
|
||||
] + $this->sidebarData());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
private function trackView(Request $request, NewsArticle $article): void
|
||||
{
|
||||
$ip = $request->ip();
|
||||
$userId = Auth::id();
|
||||
$session = 'news_view_' . $article->id;
|
||||
|
||||
if ($request->session()->has($session)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NewsView::create([
|
||||
'article_id' => $article->id,
|
||||
'user_id' => $userId,
|
||||
'ip' => $ip,
|
||||
'created_at' => now(),
|
||||
]);
|
||||
|
||||
$article->incrementViews();
|
||||
|
||||
$request->session()->put($session, true);
|
||||
}
|
||||
|
||||
private function sidebarData(): array
|
||||
{
|
||||
return $this->news->sidebarData();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user