d08e280ce0
Replace the server-rendered episode upload form with a Livewire component, introducing an interactive admin experience that validates the new episode's stream path against all configured mirrors before saving. The controller-based `store` method and its route are removed, and episode creation now flows through the `AdminEpisodeForm` component with frontend upload handling and dynamic quality checks. Key changes: - Add `AdminEpisodeForm` Livewire component with file uploads, tag handling, and debounced stream/base-url validation. - Extend `CdnPathValidator::validateStream` to accept an episode number so the manifest path can point to the specific episode being added. - Remove the `store` method from `EpisodeController` and its POST route. - Delete the legacy `createEpisode` method from `EpisodeService`. - Replace the Blade upload modal with the Livewire view, including progress indicators and validation badges. - Add feature tests for the Livewire component and update unit tests for the CDN validator's episode-specific manifest check.
80 lines
2.5 KiB
PHP
80 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Enums\UserRole;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Jobs\DiscordReleaseNotification;
|
|
use App\Models\Episode;
|
|
use App\Services\DownloadService;
|
|
use App\Services\EpisodeService;
|
|
use App\Services\GalleryService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
|
|
class EpisodeController extends Controller
|
|
{
|
|
protected EpisodeService $episodeService;
|
|
|
|
protected GalleryService $galleryService;
|
|
|
|
protected DownloadService $downloadService;
|
|
|
|
public function __construct(
|
|
EpisodeService $episodeService,
|
|
GalleryService $galleryService,
|
|
DownloadService $downloadService
|
|
) {
|
|
$this->episodeService = $episodeService;
|
|
$this->galleryService = $galleryService;
|
|
$this->downloadService = $downloadService;
|
|
}
|
|
|
|
/**
|
|
* Edit Episode
|
|
*/
|
|
public function update(Request $request): RedirectResponse
|
|
{
|
|
$episode = Episode::with('hentai')->where('id', $request->input('episode_id'))->firstOrFail();
|
|
|
|
if ($request->user()->hasRole(UserRole::MODERATOR)) {
|
|
$this->episodeService->updateEpisodeModerator($request, $episode->id);
|
|
|
|
cache()->flush();
|
|
|
|
return to_route('hentai.index', [
|
|
'title' => $episode->slug,
|
|
]);
|
|
}
|
|
|
|
$studio = $this->episodeService->getOrCreateStudio(json_decode($request->input('studio'))[0]->value);
|
|
|
|
$oldinterpolated = $episode->interpolated;
|
|
$oldInterpolatedUHD = $episode->interpolated_uhd;
|
|
|
|
$episode = $this->episodeService->updateEpisode($request, $studio, $episode->id);
|
|
$this->episodeService->createOrUpdateCover($request, $episode, $episode->hentai->slug, 1);
|
|
$this->downloadService->createOrUpdateDownloads($request, $episode, 1);
|
|
$this->galleryService->createOrUpdateGallery($request, $episode->hentai, $episode, $episode->episode, true);
|
|
|
|
// Discord Alert
|
|
if ($oldinterpolated !== (int) $episode->interpolated) {
|
|
DiscordReleaseNotification::dispatch($episode->slug, 'update');
|
|
}
|
|
|
|
if ($oldInterpolatedUHD !== (int) $episode->interpolated_uhd) {
|
|
DiscordReleaseNotification::dispatch($episode->slug, 'updateUHD');
|
|
}
|
|
|
|
if ($request->has('v2')) {
|
|
DiscordReleaseNotification::dispatch($episode->slug, 'v2');
|
|
}
|
|
|
|
cache()->flush();
|
|
|
|
return to_route('hentai.index', [
|
|
'title' => $episode->slug,
|
|
]);
|
|
}
|
|
}
|