fn_b/app/Http/Controllers/Web/ArticlesController.php

121 lines
5.5 KiB
PHP

<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Services\ArticlesService;
use App\Services\ResourcePages;
use App\Services\Seo;
use Illuminate\Http\Request;
use App\Models\Articles;
class ArticlesController extends Controller
{
protected $oArticlesService;
public function __construct(ArticlesService $oService)
{
$this->oArticlesService = $oService;
}
public function search(Request $oRequest, string $sKeyword)
{
$page = \App\Services\Seo::page($oRequest);
$data = $this->oArticlesService->search($sKeyword, 'view');
$data['seo'] = \App\Services\Seo::listMeta('搜索:'.$data['sKeywords'], '本站文章搜索结果', '/search/'.rawurlencode($data['sKeywords']), $page, false);
return $this->listing($oRequest, $data);
}
public function like(int $iArticleId, Request $oRequest)
{
// 1. 获取/生成指纹
$sFingerprint = $oRequest->cookie('visitor_token')
?? md5($oRequest->ip() . $oRequest->userAgent());
// 2. 调用 Service
$aResult = $this->oArticlesService->like($iArticleId, $oRequest->ip(), $sFingerprint);
if (!$aResult['status']) {
return response()->json($aResult);
}
// 3. 成功后下发持久 Cookie
return response()->json($aResult)
->withCookie(cookie()->forever('visitor_token', $sFingerprint));
}
public function listByTag(Request $oRequest, string $sSlug)
{
$page = \App\Services\Seo::page($oRequest);
$data = $this->oArticlesService->getTagArticles($sSlug, 'view');
$data['seo'] = \App\Services\Seo::listMeta($data['oTag']->sName.'相关文章', '按标签浏览本站内容', '/tag/'.$sSlug, $page, false);
return $this->listing($oRequest, $data);
}
public function home(Request $oRequest)
{
if ($oRequest->filled('s')) {
abort_unless(is_string($oRequest->query('s')),404);
return redirect(\App\Services\Seo::url('/search/'.rawurlencode(trim($oRequest->query('s')))),301);
}
$page = \App\Services\Seo::page($oRequest);
if ($oRequest->has('page')) return redirect(Seo::url($page>1?ResourcePages::historyPath('freenode'):'/', $page),301);
return $this->resourceEntry($oRequest, 'freenode');
}
public function resource(Request $request, string $type)
{
$page = Seo::page($request);
if ($request->has('page')) return redirect(Seo::url($page > 1 ? ResourcePages::historyPath($type) : ResourcePages::entryPath($type), $page), 301);
if ($type === 'freenode') return redirect(Seo::url(), 301);
return $this->resourceEntry($request, $type);
}
private function resourceEntry(Request $oRequest, string $type)
{
$slug = $this->oArticlesService->getLatestResourceSlug($type);
if (!$slug) return response()->view('pages.articles.default.unavailable', ['resourceType'=>$type], 503)->header('Retry-After','3600');
$data = $this->articleData($slug, $oRequest);
$data['bIsHome'] = $type === 'freenode';
$data['bResourceEntry'] = true;
$data['seo'] = Seo::resourceEntryMeta($data['oArticle'], $type);
return view('pages.articles.default.show', $data);
}
public function history(Request $request, ?string $type = null)
{
$page = Seo::page($request);
$data = $this->oArticlesService->getResourceHistory($type);
$data['seo'] = Seo::listMeta($data['historyHeading'], '按发布时间查看往期资源记录。', ResourcePages::historyPath($type), $page, false);
return $this->listing($request, $data);
}
public function list(Request $oRequest, string $sSlug1, ?string $sSlug2 = null)
{
$page = \App\Services\Seo::page($oRequest);
$data = $this->oArticlesService->getCategoryArticles($sSlug2 ?? $sSlug1, 'view');
$category = $data['oCategory'];
$path = \App\Services\Seo::categoryPath($category);
if ($sSlug2) abort_unless($path === '/'.$sSlug1.'/'.$sSlug2, 404);
$heading = $category->sSlug === 'freenode' ? '免费节点更新记录' : \App\Services\Seo::categoryName($category);
$desc = $category->sSlug === 'freenode' ? '按发布时间查看免费节点历史记录;获取当前订阅请访问首页。' : ($category->sDescription ?: $heading.'相关文章与使用说明');
$data['seo'] = \App\Services\Seo::listMeta($heading, $desc, $path, $page, $data['oArticles']->total()>0);
if ('/'.$sSlug1 !== $path && !$sSlug2) return redirect(\App\Services\Seo::url($path,$page),301);
return $this->listing($oRequest, $data);
}
private function listing(Request $request, array $data)
{
$page = \App\Services\Seo::page($request);
abort_if($page > $data['oArticles']->lastPage(),404);
if ($request->has('page') && $page === 1) return redirect($data['seo']['canonical'],301);
$data['oArticles']->withPath(strtok($data['seo']['canonical'],'?'));
return view('pages.articles.default.index', $data);
}
private function articleData(string $slug, Request $request): array
{
return $this->oArticlesService->getArticle($slug, $request->ip(), $request->cookie('visitor_token') ?? md5($request->ip().$request->userAgent()));
}
public function show(string $sArticleSlug, Request $oRequest)
{
$data = $this->articleData($sArticleSlug,$oRequest);
$data['seo'] = \App\Services\Seo::articleMeta($data['oArticle']);
return view('pages.articles.default.show',$data);
}
}