190 lines
7.3 KiB
PHP
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.');
|
|
}
|
|
}
|