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:
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Blog;
|
||||
|
||||
use App\Domain\Plugin\Hook;
|
||||
use App\Models\Article;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class ArticleAccess
|
||||
{
|
||||
/**
|
||||
* Pure decision — no HTTP side effects.
|
||||
*
|
||||
* @param list<int>|null $unlockedArticleIds session unlock list; null = read from session
|
||||
*/
|
||||
public function resolve(Article $article, ?User $user = null, ?array $unlockedArticleIds = null): AccessDecision
|
||||
{
|
||||
if ($user !== null && $this->isPrivileged($article, $user)) {
|
||||
return AccessDecision::allow();
|
||||
}
|
||||
|
||||
if (filled($article->read_password)) {
|
||||
$unlocked = $unlockedArticleIds ?? (array) Session::get('unlocked_articles', []);
|
||||
if (! in_array($article->id, $unlocked, true)) {
|
||||
return AccessDecision::needPassword();
|
||||
}
|
||||
}
|
||||
|
||||
$decision = AccessDecision::allow();
|
||||
$context = [
|
||||
'article' => $article,
|
||||
'user' => $user,
|
||||
];
|
||||
|
||||
// Fold every listener result instead of letting the last one win, so a
|
||||
// plugin can only tighten access and a broken listener cannot re-open it.
|
||||
foreach (Hook::listeners('article.access') as $listener) {
|
||||
$result = $listener($decision, $context);
|
||||
|
||||
if ($result instanceof AccessDecision) {
|
||||
$decision = $decision->tightenWith($result);
|
||||
}
|
||||
}
|
||||
|
||||
return $decision;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML safe to expose for the given decision (full body or teaser/description).
|
||||
*/
|
||||
public function publicHtml(Article $article, AccessDecision $decision): string
|
||||
{
|
||||
if ($decision->isAllow()) {
|
||||
return $article->renderedHtml();
|
||||
}
|
||||
|
||||
if (filled($decision->teaserHtml)) {
|
||||
return $decision->teaserHtml;
|
||||
}
|
||||
|
||||
return e((string) ($article->description ?: ''));
|
||||
}
|
||||
|
||||
protected function isPrivileged(Article $article, User $user): bool
|
||||
{
|
||||
if ((int) $article->user_id === (int) $user->id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->hasRole('admin');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user