247 lines
8.2 KiB
PHP
247 lines
8.2 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\Label;
|
|
use App\Models\Service;
|
|
use App\Models\ServiceAgendaItem;
|
|
use App\Models\ServiceSong;
|
|
use App\Models\Slide;
|
|
use App\Models\Song;
|
|
use App\Services\PlaylistExportService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use ProPresenter\Parser\ProPlaylistReader;
|
|
use Tests\TestCase;
|
|
|
|
final class KeyVisualFallbackTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
Storage::fake('public');
|
|
}
|
|
|
|
public function test_non_song_agenda_item_without_slides_gets_ephemeral_keyvisual_fallback(): void
|
|
{
|
|
Storage::disk('public')->put('slides/keyvisual.jpg', 'keyvisual-image');
|
|
|
|
$service = Service::factory()->create([
|
|
'title' => 'Keyvisual Service',
|
|
'date' => now(),
|
|
'key_visual_filename' => 'slides/keyvisual.jpg',
|
|
]);
|
|
|
|
ServiceAgendaItem::factory()->create([
|
|
'service_id' => $service->id,
|
|
'title' => 'Begrüßung',
|
|
'service_song_id' => null,
|
|
'sort_order' => 1,
|
|
'is_before_event' => false,
|
|
]);
|
|
|
|
$slideCountBefore = Slide::count();
|
|
|
|
$result = app(PlaylistExportService::class)->generatePlaylist($service);
|
|
$playlist = ProPlaylistReader::read($result['path']);
|
|
$embeddedProFiles = $playlist->getEmbeddedProFiles();
|
|
$fallbackSong = $playlist->getEmbeddedSong('Begrüßung.pro');
|
|
|
|
$this->assertCount(1, $embeddedProFiles);
|
|
$this->assertNotNull($fallbackSong);
|
|
$this->assertSame($slideCountBefore, Slide::count());
|
|
|
|
$slides = $this->allParserSlides($fallbackSong);
|
|
$this->assertCount(1, $slides);
|
|
$this->assertTrue($slides[0]->hasBackgroundMedia());
|
|
$this->assertSame(Storage::disk('public')->path('slides/keyvisual.jpg'), $slides[0]->getBackgroundMediaUrl());
|
|
|
|
$this->cleanupTempDir($result['temp_dir']);
|
|
}
|
|
|
|
public function test_song_agenda_item_does_not_get_keyvisual_fallback(): void
|
|
{
|
|
Storage::disk('public')->put('slides/keyvisual.jpg', 'keyvisual-image');
|
|
|
|
$service = Service::factory()->create([
|
|
'title' => 'Song Service',
|
|
'date' => now(),
|
|
'key_visual_filename' => 'slides/keyvisual.jpg',
|
|
]);
|
|
$song = $this->createSongWithContent('Nur ein Lied');
|
|
$serviceSong = ServiceSong::create([
|
|
'service_id' => $service->id,
|
|
'song_id' => $song->id,
|
|
'cts_song_name' => 'Nur ein Lied',
|
|
'order' => 1,
|
|
]);
|
|
|
|
ServiceAgendaItem::factory()->create([
|
|
'service_id' => $service->id,
|
|
'title' => 'Nur ein Lied',
|
|
'service_song_id' => $serviceSong->id,
|
|
'sort_order' => 1,
|
|
'is_before_event' => false,
|
|
]);
|
|
|
|
$result = app(PlaylistExportService::class)->generatePlaylist($service);
|
|
$playlist = ProPlaylistReader::read($result['path']);
|
|
|
|
$this->assertCount(1, $playlist->getEmbeddedProFiles());
|
|
$this->assertNotNull($playlist->getEmbeddedSong('Nur ein Lied.pro'));
|
|
$this->assertNull($playlist->getEmbeddedSong('Keyvisual.pro'));
|
|
|
|
$this->cleanupTempDir($result['temp_dir']);
|
|
}
|
|
|
|
public function test_sermon_agenda_item_with_uploaded_slides_prepends_keyvisual_sequence(): void
|
|
{
|
|
Storage::disk('public')->put('slides/keyvisual.jpg', 'keyvisual-image');
|
|
Storage::disk('public')->put('slides/sermon.jpg', 'sermon-image');
|
|
|
|
$service = Service::factory()->create([
|
|
'title' => 'Slides Service',
|
|
'date' => now(),
|
|
'key_visual_filename' => 'slides/keyvisual.jpg',
|
|
'preacher_name' => 'Pastor Paul',
|
|
'preacher_name_override' => null,
|
|
]);
|
|
$agendaItem = ServiceAgendaItem::factory()->create([
|
|
'service_id' => $service->id,
|
|
'title' => 'Predigt',
|
|
'service_song_id' => null,
|
|
'sort_order' => 1,
|
|
'is_before_event' => false,
|
|
]);
|
|
|
|
Slide::factory()->create([
|
|
'service_id' => $service->id,
|
|
'service_agenda_item_id' => $agendaItem->id,
|
|
'type' => 'sermon',
|
|
'original_filename' => 'sermon.jpg',
|
|
'stored_filename' => 'slides/sermon.jpg',
|
|
'sort_order' => 0,
|
|
]);
|
|
|
|
$result = app(PlaylistExportService::class)->generatePlaylist($service);
|
|
$playlist = ProPlaylistReader::read($result['path']);
|
|
$sermonSong = $playlist->getEmbeddedSong('Predigt.pro');
|
|
|
|
$this->assertCount(2, $playlist->getEmbeddedProFiles());
|
|
$this->assertNotNull($sermonSong);
|
|
|
|
$names = array_map(fn ($entry) => $entry->getName(), $playlist->getEntries());
|
|
$this->assertContains('Keyvisual-Predigt', $names);
|
|
$this->assertLessThan(
|
|
array_search('Predigt', $names, true),
|
|
array_search('Keyvisual-Predigt', $names, true),
|
|
);
|
|
|
|
$slides = $this->allParserSlides($sermonSong);
|
|
$this->assertCount(1, $slides);
|
|
$this->assertFalse($slides[0]->hasBackgroundMedia());
|
|
|
|
$this->cleanupTempDir($result['temp_dir']);
|
|
}
|
|
|
|
public function test_without_keyvisual_empty_non_song_item_adds_no_playlist_entry(): void
|
|
{
|
|
$service = Service::factory()->create([
|
|
'title' => 'Ohne Keyvisual',
|
|
'date' => now(),
|
|
'key_visual_filename' => null,
|
|
]);
|
|
$song = $this->createSongWithContent('Vorhandenes Lied');
|
|
$serviceSong = ServiceSong::create([
|
|
'service_id' => $service->id,
|
|
'song_id' => $song->id,
|
|
'cts_song_name' => 'Vorhandenes Lied',
|
|
'order' => 1,
|
|
]);
|
|
|
|
ServiceAgendaItem::factory()->create([
|
|
'service_id' => $service->id,
|
|
'title' => 'Begrüßung ohne Folien',
|
|
'service_song_id' => null,
|
|
'sort_order' => 1,
|
|
'is_before_event' => false,
|
|
]);
|
|
ServiceAgendaItem::factory()->create([
|
|
'service_id' => $service->id,
|
|
'title' => 'Vorhandenes Lied',
|
|
'service_song_id' => $serviceSong->id,
|
|
'sort_order' => 2,
|
|
'is_before_event' => false,
|
|
]);
|
|
|
|
$result = app(PlaylistExportService::class)->generatePlaylist($service);
|
|
$playlist = ProPlaylistReader::read($result['path']);
|
|
|
|
$this->assertCount(1, $playlist->getEmbeddedProFiles());
|
|
$this->assertNotNull($playlist->getEmbeddedSong('Vorhandenes Lied.pro'));
|
|
$this->assertNull($playlist->getEmbeddedSong('Begrüßung ohne Folien.pro'));
|
|
|
|
$this->cleanupTempDir($result['temp_dir']);
|
|
}
|
|
|
|
private function createSongWithContent(string $title): Song
|
|
{
|
|
$song = Song::create([
|
|
'title' => $title,
|
|
'ccli_id' => fake()->unique()->numerify('#####'),
|
|
'author' => 'Test Author',
|
|
'copyright_text' => 'Test Publisher',
|
|
]);
|
|
|
|
$label = Label::firstOrCreate(
|
|
['name' => 'Verse 1 - '.$title],
|
|
['color' => '#2196F3'],
|
|
);
|
|
$label->songSlides()->create(['order' => 0, 'text_content' => 'Erste Zeile']);
|
|
|
|
$arrangement = $song->arrangements()->create(['name' => 'normal', 'is_default' => true]);
|
|
$arrangement->arrangementLabels()->create(['label_id' => $label->id, 'order' => 0]);
|
|
|
|
return $song;
|
|
}
|
|
|
|
private function allParserSlides(\ProPresenter\Parser\Song $parserSong): array
|
|
{
|
|
$slides = [];
|
|
|
|
foreach ($parserSong->getGroups() as $group) {
|
|
foreach ($parserSong->getSlidesForGroup($group) as $slide) {
|
|
$slides[] = $slide;
|
|
}
|
|
}
|
|
|
|
return $slides;
|
|
}
|
|
|
|
private function cleanupTempDir(string $dir): void
|
|
{
|
|
if (! is_dir($dir)) {
|
|
return;
|
|
}
|
|
|
|
$items = scandir($dir);
|
|
if ($items === false) {
|
|
return;
|
|
}
|
|
|
|
foreach ($items as $item) {
|
|
if ($item === '.' || $item === '..') {
|
|
continue;
|
|
}
|
|
|
|
$path = $dir.'/'.$item;
|
|
is_dir($path) ? $this->cleanupTempDir($path) : unlink($path);
|
|
}
|
|
|
|
rmdir($dir);
|
|
}
|
|
}
|