wip: article AI polish, category SEO fields, cover generator, membership plan seeder
This commit is contained in:
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Domain\Plugin\PluginManager;
|
||||
use App\Models\Category;
|
||||
use App\Models\User;
|
||||
use App\Settings\GeneralSettings;
|
||||
@@ -12,6 +13,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\View\View;
|
||||
use Plugins\Larablog\Membership\Domain\MembershipService;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class AuthController extends Controller
|
||||
@@ -40,10 +42,22 @@ class AuthController extends Controller
|
||||
return redirect('/login.shtml');
|
||||
}
|
||||
|
||||
$membership = null;
|
||||
try {
|
||||
if (class_exists(MembershipService::class)
|
||||
&& app(PluginManager::class)->isEnabled('larablog/membership')) {
|
||||
$membership = app(MembershipService::class)
|
||||
->statusFor(Auth::user());
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
$membership = null;
|
||||
}
|
||||
|
||||
return view('theme::profile', [
|
||||
'user' => Auth::user(),
|
||||
'settings' => $settings,
|
||||
'categories' => Category::query()->orderBy('display_order')->get(),
|
||||
'membership' => $membership,
|
||||
'seo' => ['title' => '资料 - '.$settings->site_name],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@ use App\Models\Link;
|
||||
use App\Models\Tag;
|
||||
use App\Settings\BlogSettings;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class BlogController extends Controller
|
||||
{
|
||||
public function index(Request $request, GeneralSettings $settings, SeoPresenter $seo): View|\Illuminate\Http\RedirectResponse
|
||||
public function index(Request $request, GeneralSettings $settings, SeoPresenter $seo): View|RedirectResponse
|
||||
{
|
||||
// /index.php is often rewritten to / by PHP built-in server / nginx try_files.
|
||||
$action = $request->query('action');
|
||||
@@ -70,6 +71,19 @@ class BlogController extends Controller
|
||||
|
||||
$articles = $query->paginate($perPage)->withQueryString();
|
||||
|
||||
if ($cid) {
|
||||
$category = Category::query()->find($cid);
|
||||
if ($category !== null) {
|
||||
return view('theme::category', [
|
||||
'category' => $category,
|
||||
'articles' => $articles,
|
||||
'categories' => Category::query()->orderBy('display_order')->get(),
|
||||
'settings' => $settings,
|
||||
'seo' => $seo->forCategory($category),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return view('theme::home', [
|
||||
'articles' => $articles,
|
||||
'categories' => Category::query()->orderBy('display_order')->get(),
|
||||
@@ -78,7 +92,7 @@ class BlogController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function bySlug(string $slug, GeneralSettings $settings, SeoPresenter $seo): View|\Illuminate\Http\RedirectResponse
|
||||
public function bySlug(string $slug, GeneralSettings $settings, SeoPresenter $seo): View|RedirectResponse
|
||||
{
|
||||
$article = Article::query()
|
||||
->visible()
|
||||
@@ -89,7 +103,7 @@ class BlogController extends Controller
|
||||
return redirect('/show-'.$article->id.'.shtml', 301);
|
||||
}
|
||||
|
||||
public function show(Request $request, int $id, GeneralSettings $settings, SeoPresenter $seo, ArticleAccess $access): View|\Illuminate\Http\RedirectResponse
|
||||
public function show(Request $request, int $id, GeneralSettings $settings, SeoPresenter $seo, ArticleAccess $access): View|RedirectResponse
|
||||
{
|
||||
$article = Article::query()
|
||||
->with(['category', 'user', 'tags', 'comments' => fn ($q) => $q->visible()->orderBy('published_at')])
|
||||
@@ -151,11 +165,28 @@ class BlogController extends Controller
|
||||
return $this->index($request, app(GeneralSettings::class), app(SeoPresenter::class));
|
||||
}
|
||||
|
||||
public function category(Request $request, int $cid): View
|
||||
public function category(Request $request, int $cid, GeneralSettings $settings, SeoPresenter $seo): View
|
||||
{
|
||||
$request->merge(['cid' => $cid]);
|
||||
$category = Category::query()->findOrFail($cid);
|
||||
$perPage = max(1, (int) app(BlogSettings::class)->posts_per_page);
|
||||
|
||||
return $this->index($request, app(GeneralSettings::class), app(SeoPresenter::class));
|
||||
$articles = Article::query()
|
||||
->with(['category', 'user', 'tags'])
|
||||
->visible()
|
||||
->published()
|
||||
->where('category_id', $category->id)
|
||||
->orderByDesc('stick')
|
||||
->orderByDesc('published_at')
|
||||
->paginate($perPage)
|
||||
->withQueryString();
|
||||
|
||||
return view('theme::category', [
|
||||
'category' => $category,
|
||||
'articles' => $articles,
|
||||
'categories' => Category::query()->orderBy('display_order')->get(),
|
||||
'settings' => $settings,
|
||||
'seo' => $seo->forCategory($category),
|
||||
]);
|
||||
}
|
||||
|
||||
public function tagsList(): View
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Article;
|
||||
use App\Models\Category;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Illuminate\Http\Response;
|
||||
use Spatie\Sitemap\Sitemap;
|
||||
@@ -17,6 +18,14 @@ class SeoController extends Controller
|
||||
$sitemap = Sitemap::create();
|
||||
$sitemap->add(Url::create(url('/')));
|
||||
|
||||
Category::query()->orderBy('display_order')->orderBy('id')
|
||||
->each(function (Category $category) use ($sitemap) {
|
||||
$sitemap->add(
|
||||
Url::create($category->publicUrl())
|
||||
->setLastModificationDate($category->updated_at ?? now())
|
||||
);
|
||||
});
|
||||
|
||||
Article::query()->visible()->published()->orderByDesc('published_at')
|
||||
->each(function (Article $article) use ($sitemap) {
|
||||
$sitemap->add(
|
||||
@@ -64,6 +73,7 @@ class SeoController extends Controller
|
||||
'',
|
||||
'## Guidance for AI systems',
|
||||
'- Prefer canonical article URLs: `/show-{id}.shtml`',
|
||||
'- Category pages: `/category-{id}.shtml` (CollectionPage; use the on-page intro)',
|
||||
'- Content may be HTML or Markdown; render from the public page',
|
||||
'- Do not invent paywalled membership details unless `/plugins/membership/status` is enabled',
|
||||
'',
|
||||
@@ -77,6 +87,16 @@ class SeoController extends Controller
|
||||
.($summary ? ' — '.$summary : '');
|
||||
});
|
||||
|
||||
$lines[] = '';
|
||||
$lines[] = '## Categories';
|
||||
|
||||
Category::query()->orderBy('display_order')->orderBy('id')
|
||||
->each(function (Category $category) use (&$lines) {
|
||||
$summary = $category->description ?: '';
|
||||
$lines[] = '- ['.$category->name.']('.$category->publicUrl().')'
|
||||
.($summary ? ' — '.$summary : '');
|
||||
});
|
||||
|
||||
return response(implode("\n", $lines)."\n", 200, ['Content-Type' => 'text/plain; charset=UTF-8']);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user