pp-planer/app/Services/ProBundleExportService.php

102 lines
3.1 KiB
PHP

<?php
namespace App\Services;
use App\Models\Service;
use Illuminate\Support\Facades\Storage;
use InvalidArgumentException;
use ProPresenter\Parser\ProFileGenerator;
use RuntimeException;
use ZipArchive;
class ProBundleExportService
{
private const ALLOWED_BLOCK_TYPES = ['information', 'moderation', 'sermon'];
public function generateBundle(Service $service, string $blockType): string
{
if (! in_array($blockType, self::ALLOWED_BLOCK_TYPES, true)) {
throw new InvalidArgumentException('Ungültiger Blocktyp für .probundle Export.');
}
$slides = $service->slides()
->where('type', $blockType)
->orderBy('sort_order')
->get();
$groupName = ucfirst($blockType);
$slideData = [];
$mediaFiles = [];
foreach ($slides as $slide) {
$sourcePath = Storage::disk('public')->path('slides/'.$slide->stored_filename);
if (! file_exists($sourcePath)) {
continue;
}
$imageFilename = basename($slide->stored_filename);
$imageContent = file_get_contents($sourcePath);
if ($imageContent === false) {
continue;
}
$mediaFiles[$imageFilename] = $imageContent;
$slideData[] = [
'text' => $slide->original_filename ?? '',
'media' => $imageFilename,
'format' => 'JPG',
];
}
$groups = [
[
'name' => $groupName,
'color' => [0, 0, 0, 1],
'slides' => $slideData,
],
];
$arrangements = [
[
'name' => 'normal',
'groupNames' => [$groupName],
],
];
$song = ProFileGenerator::generate($groupName, $groups, $arrangements);
$protoBytes = $song->getPresentation()->serializeToString();
$bundlePath = sys_get_temp_dir().'/'.uniqid($blockType.'-').'.probundle';
$zip = new ZipArchive;
$openResult = $zip->open($bundlePath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
if ($openResult !== true) {
throw new InvalidArgumentException('Konnte .probundle nicht erstellen.');
}
$this->addStoredEntry($zip, 'data', $protoBytes);
foreach ($mediaFiles as $filename => $contents) {
$this->addStoredEntry($zip, $filename, $contents);
}
if (! $zip->close()) {
throw new RuntimeException('Fehler beim Finalisieren der .probundle Datei.');
}
return $bundlePath;
}
private function addStoredEntry(ZipArchive $zip, string $entryName, string $contents): void
{
if (! $zip->addFromString($entryName, $contents)) {
throw new RuntimeException(sprintf('Fehler beim Hinzufügen von %s zur .probundle Datei.', $entryName));
}
if (! $zip->setCompressionName($entryName, ZipArchive::CM_STORE)) {
throw new RuntimeException(sprintf('Fehler beim Setzen der Kompression für %s.', $entryName));
}
}
}