135 lines
3.8 KiB
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');
|
|
}
|
|
}
|