la_bloger/app/Http/Controllers/Admin/PostController.php
2026-05-20 13:01:33 +02:00

190 lines
7.3 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Admin\Concerns\ResolvesActiveChannel;
use App\Http\Controllers\Controller;
use App\Models\Channel;
use App\Models\Post;
use App\Models\Publication;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
use Illuminate\View\View;
class PostController extends Controller
{
use ResolvesActiveChannel;
public function index(Request $request): View
{
$channel = $this->activeChannel();
$channel->load('prefixes');
$activePrefix = null;
if ($request->filled('prefix')) {
$activePrefix = $channel->prefixes->firstWhere('slug', $request->prefix);
}
$publications = Publication::with(['post.author', 'prefix'])
->forChannel($channel)
->when($activePrefix, fn ($q) => $q->forPrefix($activePrefix))
->latest('updated_at')
->paginate(25)
->withQueryString();
return view('admin::posts.index', compact('publications', 'channel', 'activePrefix'));
}
public function create(): View
{
$channel = $this->activeChannel();
$channel->load('prefixes');
$publication = new Publication(['status' => 'draft']);
return view('admin::posts.create', compact('channel', 'publication'));
}
public function store(Request $request): RedirectResponse
{
$channel = $this->activeChannel();
$request->validate([
'title' => ['required', 'string', 'max:255'],
'prefix_id' => ['required', Rule::exists('channel_prefix', 'prefix_id')->where('channel_id', $channel->id)],
'status' => ['required', 'in:draft,published,scheduled'],
]);
$post = Post::create(['user_id' => Auth::id()]);
$publication = $post->publications()->create([
'channel_id' => $channel->id,
'prefix_id' => $request->prefix_id,
'title' => $request->title,
'status' => $request->status,
]);
return redirect()->route('admin.posts.edit', $publication)
->with('success', 'Post created. Add content and save.');
}
public function edit(Publication $post): View
{
abort_if($post->channel_id !== $this->activeChannel()->id, 403);
$post->load(['blocks', 'post.publications', 'taxonomyTerms', 'prefix', 'channel.prefixes', 'channel.taxonomyTerms']);
$channel = $post->channel;
$channelTerms = $channel->taxonomyTerms;
$prefixes = $channel->prefixes;
$allChannels = Channel::with('prefixes')->get();
return view('admin::posts.edit', compact('post', 'channel', 'channelTerms', 'prefixes', 'allChannels'));
}
public function update(Request $request, Publication $post): RedirectResponse
{
$channel = $this->activeChannel();
abort_if($post->channel_id !== $channel->id, 403);
$request->validate([
'title' => ['required', 'string', 'max:255'],
'prefix_id' => ['required', Rule::exists('channel_prefix', 'prefix_id')->where('channel_id', $channel->id)],
'slug' => ['nullable', 'string', 'max:255'],
'status' => ['required', 'in:draft,published,scheduled'],
'published_at' => ['nullable', 'date'],
'excerpt' => ['nullable', 'string'],
'meta_title' => ['nullable', 'string', 'max:255'],
'meta_description' => ['nullable', 'string'],
'og_image' => ['nullable', 'string', 'max:255'],
'canonical_url' => ['nullable', 'string', 'max:255'],
'taxonomy_terms' => ['nullable', 'array'],
'taxonomy_terms.*' => [Rule::exists('taxonomy_terms', 'id')->where('channel_id', $channel->id)],
'blocks' => ['nullable', 'array'],
'blocks.*.type' => ['required_with:blocks', 'string', 'in:rich_text,image,video,taxonomy_list'],
'blocks.*.content' => ['required_with:blocks', 'array'],
]);
$post->update([
'prefix_id' => $request->prefix_id,
'title' => $request->title,
'excerpt' => $request->excerpt,
'slug' => $request->slug ?: null,
'status' => $request->status,
'published_at' => $request->status === 'published' && !$request->published_at
? now()
: $request->published_at,
'meta_title' => $request->meta_title,
'meta_description' => $request->meta_description,
'og_image' => $request->og_image,
'canonical_url' => $request->canonical_url,
]);
$post->taxonomyTerms()->sync($request->input('taxonomy_terms', []));
$post->blocks()->delete();
foreach ($request->input('blocks', []) as $i => $block) {
$post->blocks()->create([
'type' => $block['type'],
'content' => $block['content'],
'order' => $i,
]);
}
return back()->with('success', 'Post saved.');
}
public function duplicate(Request $request, Publication $post): RedirectResponse
{
abort_if($post->channel_id !== $this->activeChannel()->id, 403);
$request->validate([
'channel_id' => ['required', 'exists:channels,id'],
'prefix_id' => ['required', 'exists:prefixes,id'],
]);
$post->load(['blocks', 'taxonomyTerms']);
$newPost = Post::create(['user_id' => Auth::id()]);
$newPublication = $newPost->publications()->create([
'channel_id' => $request->channel_id,
'prefix_id' => $request->prefix_id,
'title' => $post->title,
'excerpt' => $post->excerpt,
'slug' => $post->slug,
'status' => 'draft',
'published_at' => null,
'meta_title' => $post->meta_title,
'meta_description' => $post->meta_description,
'og_image' => $post->og_image,
'canonical_url' => null,
]);
foreach ($post->blocks as $block) {
$newPublication->blocks()->create([
'type' => $block->type,
'content' => $block->content,
'order' => $block->order,
]);
}
if ((int) $request->channel_id === $post->channel_id) {
$newPublication->taxonomyTerms()->sync($post->taxonomyTerms->pluck('id'));
}
session(['admin.active_channel_id' => (int) $request->channel_id]);
return redirect()->route('admin.posts.edit', $newPublication)
->with('success', 'Post duplicated as draft.');
}
public function destroy(Publication $post): RedirectResponse
{
abort_if($post->channel_id !== $this->activeChannel()->id, 403);
$parentPost = $post->post;
$post->delete();
if ($parentPost->publications()->doesntExist()) {
$parentPost->delete();
}
return redirect()->route('admin.posts.index')
->with('success', 'Post deleted.');
}
}