Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
151 lines
4.9 KiB
PHP
151 lines
4.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\Seo;
|
|
|
|
use App\Models\Article;
|
|
use App\Settings\GeneralSettings;
|
|
use App\Settings\SeoSettings;
|
|
|
|
class SeoPresenter
|
|
{
|
|
public function __construct(
|
|
protected GeneralSettings $generalSettings,
|
|
protected SeoSettings $seoSettings,
|
|
) {}
|
|
|
|
public function title(?string $title = null): string
|
|
{
|
|
$suffix = $this->seoSettings->meta_title_suffix;
|
|
|
|
if ($title === null || $title === '') {
|
|
return $this->generalSettings->site_name;
|
|
}
|
|
|
|
return $suffix
|
|
? "{$title} {$suffix}"
|
|
: "{$title} - {$this->generalSettings->site_name}";
|
|
}
|
|
|
|
public function description(?string $description = null): string
|
|
{
|
|
return $description
|
|
?: ($this->seoSettings->default_description
|
|
?: ($this->generalSettings->site_description ?? ''));
|
|
}
|
|
|
|
public function keywords(?string $keywords = null): ?string
|
|
{
|
|
return $keywords ?: $this->seoSettings->default_keywords;
|
|
}
|
|
|
|
/**
|
|
* @return array{title: string, description: string, keywords: ?string, canonical: string, og: array<string, string>, twitter: array<string, string>, jsonld: array<string, mixed>}
|
|
*/
|
|
public function forHome(): array
|
|
{
|
|
$canonical = rtrim($this->generalSettings->site_url ?: url('/'), '/') ?: url('/');
|
|
|
|
return [
|
|
'title' => $this->title(),
|
|
'description' => $this->description(),
|
|
'keywords' => $this->keywords(),
|
|
'canonical' => $canonical,
|
|
'og' => $this->openGraph(),
|
|
'twitter' => $this->twitterCards(),
|
|
'jsonld' => $this->jsonLd(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array{title: string, description: string, keywords: ?string, canonical: string, og: array<string, string>, twitter: array<string, string>, jsonld: array<string, mixed>}
|
|
*/
|
|
public function forArticle(Article $article): array
|
|
{
|
|
$canonical = url('/show-'.$article->id.'.shtml');
|
|
|
|
return [
|
|
'title' => $this->title($article->title),
|
|
'description' => $this->description($article->description),
|
|
'keywords' => $this->keywords($article->keywords),
|
|
'canonical' => $canonical,
|
|
'og' => $this->openGraph($article),
|
|
'twitter' => $this->twitterCards($article),
|
|
'jsonld' => $this->jsonLd($article),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function openGraph(?Article $article = null): array
|
|
{
|
|
$title = $this->title($article?->title);
|
|
$description = $this->description($article?->description);
|
|
$url = $article
|
|
? url('/show-'.$article->id.'.shtml')
|
|
: ($this->generalSettings->site_url ?: url('/'));
|
|
|
|
return array_filter([
|
|
'og:title' => $title,
|
|
'og:description' => $description,
|
|
'og:url' => $url,
|
|
'og:type' => $article ? 'article' : 'website',
|
|
'og:site_name' => $this->generalSettings->site_name,
|
|
'og:locale' => 'zh_CN',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function twitterCards(?Article $article = null): array
|
|
{
|
|
return array_filter([
|
|
'twitter:card' => 'summary',
|
|
'twitter:title' => $this->title($article?->title),
|
|
'twitter:description' => $this->description($article?->description),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function jsonLd(?Article $article = null): array
|
|
{
|
|
if (! $this->seoSettings->json_ld_enabled) {
|
|
return [];
|
|
}
|
|
|
|
if ($article === null) {
|
|
return [
|
|
'@context' => 'https://schema.org',
|
|
'@type' => 'WebSite',
|
|
'name' => $this->generalSettings->site_name,
|
|
'url' => $this->generalSettings->site_url ?: url('/'),
|
|
'description' => $this->description(),
|
|
'potentialAction' => [
|
|
'@type' => 'SearchAction',
|
|
'target' => url('/search.shtml').'?keywords={search_term_string}',
|
|
'query-input' => 'required name=search_term_string',
|
|
],
|
|
];
|
|
}
|
|
|
|
return [
|
|
'@context' => 'https://schema.org',
|
|
'@type' => 'BlogPosting',
|
|
'headline' => $article->title,
|
|
'description' => $this->description($article->description),
|
|
'datePublished' => optional($article->published_at)?->toIso8601String(),
|
|
'dateModified' => optional($article->updated_at)?->toIso8601String(),
|
|
'author' => [
|
|
'@type' => 'Person',
|
|
'name' => $article->user?->name ?? $article->user?->username,
|
|
],
|
|
'mainEntityOfPage' => url('/show-'.$article->id.'.shtml'),
|
|
];
|
|
}
|
|
}
|