Initial baseline: LaraBlog core with plugin commerce surface.

Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
This commit is contained in:
ak
2026-08-12 01:15:38 +08:00
commit 263b98b218
337 changed files with 31393 additions and 0 deletions
+150
View File
@@ -0,0 +1,150 @@
<?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'),
];
}
}