fedi-feed-router/app/Livewire/Feeds.php

135 lines
3.8 KiB
PHP

<?php
namespace App\Livewire;
use App\Actions\CreateFeedAction;
use App\Models\Feed;
use App\Models\Language;
use Illuminate\Contracts\View\View;
use InvalidArgumentException;
use Livewire\Component;
class Feeds extends Component
{
public bool $showCreateModal = false;
public string $newName = '';
public string $newProvider = '';
public ?int $newLanguageId = null;
public string $newDescription = '';
public ?int $editingFeedId = null;
public string $editName = '';
public string $editDescription = '';
public function toggle(int $feedId): void
{
$feed = Feed::findOrFail($feedId);
$feed->is_active = ! $feed->is_active;
$feed->save();
}
public function openCreateModal(): void
{
$this->reset(['newName', 'newProvider', 'newLanguageId', 'newDescription']);
$this->resetErrorBag();
$this->showCreateModal = true;
}
public function closeCreateModal(): void
{
$this->showCreateModal = false;
}
public function createFeed(CreateFeedAction $action): void
{
$providers = array_keys($this->activeProviders());
$this->validate([
'newName' => 'required|string|max:255',
'newProvider' => ['required', 'string', 'in:'.implode(',', $providers)],
'newLanguageId' => 'required|integer|exists:languages,id',
]);
try {
$action->execute(
$this->newName,
$this->newProvider,
$this->newLanguageId,
// Blade textarea binds an empty string when blank; the action expects null for "no description".
$this->newDescription !== '' ? $this->newDescription : null,
);
} catch (InvalidArgumentException $e) {
$this->addError('newProvider', 'This provider is not available for the selected language.');
return;
}
$this->closeCreateModal();
}
public function openEditModal(int $feedId): void
{
$feed = Feed::findOrFail($feedId);
$this->resetErrorBag();
$this->editingFeedId = $feedId;
$this->editName = $feed->name;
$this->editDescription = $feed->description ?? '';
}
public function closeEditModal(): void
{
$this->editingFeedId = null;
}
// Provider and language are deliberately not editable: CreateFeedAction derives the unique
// feeds.url from that pair, so changing either re-points the feed and orphans its articles.
public function updateFeed(): void
{
if ($this->editingFeedId === null) {
return;
}
$this->validate([
'editName' => 'required|string|max:255',
]);
Feed::findOrFail($this->editingFeedId)->update([
'name' => $this->editName,
'description' => $this->editDescription !== '' ? $this->editDescription : null,
]);
$this->closeEditModal();
}
/**
* @return array<string, array<string, mixed>>
*/
private function activeProviders(): array
{
/** @var array<string, array<string, mixed>> $providers */
$providers = config('feed.providers', []);
return array_filter($providers, fn (array $provider): bool => ($provider['is_active'] ?? false) === true);
}
public function render(): View
{
$feeds = Feed::orderBy('name')->get();
return view('livewire.feeds', [
'feeds' => $feeds,
'providers' => $this->activeProviders(),
'languages' => Language::where('is_active', true)->orderBy('name')->get(),
'editingFeed' => $this->editingFeedId !== null
? Feed::with('language')->find($this->editingFeedId)
: null,
])->layout('layouts.app');
}
}