wip: article AI polish, category SEO fields, cover generator, membership plan seeder
CI / PHPUnit (PHP 8.3) (push) Failing after 4s
CI / PHPUnit (PHP 8.2) (push) Failing after 1m9s
CI / Deploy (manual gate) (push) Skipped

This commit is contained in:
2026-09-07 18:48:37 +00:00
parent 263b98b218
commit 3cec4c5e18
121 changed files with 4701 additions and 313 deletions
+59
View File
@@ -5,8 +5,10 @@ declare(strict_types=1);
namespace App\Domain\Seo;
use App\Models\Article;
use App\Models\Category;
use App\Settings\GeneralSettings;
use App\Settings\SeoSettings;
use Illuminate\Support\Str;
class SeoPresenter
{
@@ -76,6 +78,62 @@ class SeoPresenter
];
}
/**
* @return array{title: string, description: string, keywords: ?string, canonical: string, og: array<string, string>, twitter: array<string, string>, jsonld: array<string, mixed>}
*/
public function forCategory(Category $category): array
{
$canonical = $category->publicUrl();
$rawDescription = $category->description ?: Str::limit(trim(preg_replace('/\s+/', ' ', (string) $category->intro) ?: ''), 160);
$description = $this->description($rawDescription !== '' ? $rawDescription : null);
return [
'title' => $this->title($category->name),
'description' => $description,
'keywords' => $this->keywords($category->keywords),
'canonical' => $canonical,
'og' => array_filter([
'og:title' => $this->title($category->name),
'og:description' => $description,
'og:url' => $canonical,
'og:type' => 'website',
'og:site_name' => $this->generalSettings->site_name,
'og:locale' => 'zh_CN',
'og:image' => $category->coverUrl(),
]),
'twitter' => array_filter([
'twitter:card' => $category->coverUrl() ? 'summary_large_image' : 'summary',
'twitter:title' => $this->title($category->name),
'twitter:description' => $description,
'twitter:image' => $category->coverUrl(),
]),
'jsonld' => $this->jsonLdForCategory($category, $canonical, $description),
];
}
/**
* @return array<string, mixed>
*/
protected function jsonLdForCategory(Category $category, string $canonical, string $description): array
{
if (! $this->seoSettings->json_ld_enabled) {
return [];
}
return [
'@context' => 'https://schema.org',
'@type' => 'CollectionPage',
'name' => $category->name,
'description' => $description,
'url' => $canonical,
'isPartOf' => [
'@type' => 'WebSite',
'name' => $this->generalSettings->site_name,
'url' => $this->generalSettings->site_url ?: url('/'),
],
];
}
/**
* @return array<string, string>
*/
@@ -94,6 +152,7 @@ class SeoPresenter
'og:type' => $article ? 'article' : 'website',
'og:site_name' => $this->generalSettings->site_name,
'og:locale' => 'zh_CN',
'og:image' => $article?->coverUrl(),
]);
}