[AI] add slide label, macro, and media support
This commit is contained in:
parent
addda54957
commit
3a33597bcf
|
|
@ -4,7 +4,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace ProPresenter\Parser;
|
||||
|
||||
use Rv\Data\Action;
|
||||
use Rv\Data\Action\ActionType;
|
||||
use Rv\Data\Action\MacroType;
|
||||
use Rv\Data\CollectionElementType;
|
||||
use Rv\Data\Cue;
|
||||
use Rv\Data\UUID;
|
||||
|
||||
/**
|
||||
* Read wrapper around a protobuf Cue representing a slide.
|
||||
|
|
@ -126,6 +131,122 @@ class Slide
|
|||
$textElements[1]->setPlainText($text);
|
||||
}
|
||||
|
||||
public function getLabel(): string
|
||||
{
|
||||
return $this->cue->getName();
|
||||
}
|
||||
|
||||
public function setLabel(string $label): void
|
||||
{
|
||||
$this->cue->setName($label);
|
||||
}
|
||||
|
||||
public function hasMacro(): bool
|
||||
{
|
||||
return $this->findMacroAction() !== null;
|
||||
}
|
||||
|
||||
public function getMacroName(): ?string
|
||||
{
|
||||
$macro = $this->findMacroAction();
|
||||
return $macro?->getMacro()?->getIdentification()?->getParameterName();
|
||||
}
|
||||
|
||||
public function getMacroUuid(): ?string
|
||||
{
|
||||
$macro = $this->findMacroAction();
|
||||
return $macro?->getMacro()?->getIdentification()?->getParameterUuid()?->getString();
|
||||
}
|
||||
|
||||
public function getMacroCollectionName(): ?string
|
||||
{
|
||||
$macro = $this->findMacroAction();
|
||||
return $macro?->getMacro()?->getIdentification()?->getParentCollection()?->getParameterName();
|
||||
}
|
||||
|
||||
public function getMacroCollectionUuid(): ?string
|
||||
{
|
||||
$macro = $this->findMacroAction();
|
||||
return $macro?->getMacro()?->getIdentification()?->getParentCollection()?->getParameterUuid()?->getString();
|
||||
}
|
||||
|
||||
public function setMacro(string $name, string $uuid, string $collectionName = '--MAIN--', string $collectionUuid = ''): void
|
||||
{
|
||||
$parentCollectionUuid = new UUID();
|
||||
$parentCollectionUuid->setString($collectionUuid);
|
||||
|
||||
$parentCollection = new CollectionElementType();
|
||||
$parentCollection->setParameterName($collectionName);
|
||||
$parentCollection->setParameterUuid($parentCollectionUuid);
|
||||
|
||||
$macroUuid = new UUID();
|
||||
$macroUuid->setString($uuid);
|
||||
|
||||
$identification = new CollectionElementType();
|
||||
$identification->setParameterName($name);
|
||||
$identification->setParameterUuid($macroUuid);
|
||||
$identification->setParentCollection($parentCollection);
|
||||
|
||||
$macroType = new MacroType();
|
||||
$macroType->setIdentification($identification);
|
||||
|
||||
$existingMacroAction = $this->findMacroAction();
|
||||
if ($existingMacroAction !== null) {
|
||||
$existingMacroAction->setType(ActionType::ACTION_TYPE_MACRO);
|
||||
$existingMacroAction->setMacro($macroType);
|
||||
$existingMacroAction->setIsEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
$macroAction = new Action();
|
||||
$macroAction->setUuid(new UUID());
|
||||
$macroAction->setType(ActionType::ACTION_TYPE_MACRO);
|
||||
$macroAction->setMacro($macroType);
|
||||
$macroAction->setIsEnabled(true);
|
||||
|
||||
$actions = [];
|
||||
foreach ($this->cue->getActions() as $action) {
|
||||
$actions[] = $action;
|
||||
}
|
||||
$actions[] = $macroAction;
|
||||
$this->cue->setActions($actions);
|
||||
}
|
||||
|
||||
public function removeMacro(): void
|
||||
{
|
||||
$filteredActions = [];
|
||||
foreach ($this->cue->getActions() as $action) {
|
||||
if ($action->getType() !== ActionType::ACTION_TYPE_MACRO) {
|
||||
$filteredActions[] = $action;
|
||||
}
|
||||
}
|
||||
|
||||
$this->cue->setActions($filteredActions);
|
||||
}
|
||||
|
||||
public function hasMedia(): bool
|
||||
{
|
||||
return $this->findMediaAction() !== null;
|
||||
}
|
||||
|
||||
public function getMediaUrl(): ?string
|
||||
{
|
||||
$media = $this->findMediaAction();
|
||||
return $media?->getMedia()?->getElement()?->getUrl()?->getAbsoluteString();
|
||||
}
|
||||
|
||||
public function getMediaUuid(): ?string
|
||||
{
|
||||
$media = $this->findMediaAction();
|
||||
return $media?->getMedia()?->getElement()?->getUuid()?->getString();
|
||||
}
|
||||
|
||||
public function getMediaFormat(): ?string
|
||||
{
|
||||
$media = $this->findMediaAction();
|
||||
return $media?->getMedia()?->getElement()?->getMetadata()?->getFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the underlying protobuf Cue.
|
||||
*/
|
||||
|
|
@ -143,12 +264,17 @@ class Slide
|
|||
*/
|
||||
private function getSlideElements(): iterable
|
||||
{
|
||||
$actions = $this->cue->getActions();
|
||||
if (count($actions) === 0) {
|
||||
$firstAction = null;
|
||||
foreach ($this->cue->getActions() as $action) {
|
||||
$firstAction = $action;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($firstAction === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$slideType = $actions[0]->getSlide();
|
||||
$slideType = $firstAction->getSlide();
|
||||
if ($slideType === null) {
|
||||
return [];
|
||||
}
|
||||
|
|
@ -165,4 +291,26 @@ class Slide
|
|||
|
||||
return $baseSlide->getElements();
|
||||
}
|
||||
|
||||
private function findMacroAction(): ?Action
|
||||
{
|
||||
foreach ($this->cue->getActions() as $action) {
|
||||
if ($action->getType() === ActionType::ACTION_TYPE_MACRO) {
|
||||
return $action;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function findMediaAction(): ?Action
|
||||
{
|
||||
foreach ($this->cue->getActions() as $action) {
|
||||
if ($action->getType() === ActionType::ACTION_TYPE_MEDIA) {
|
||||
return $action;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
198
php/tests/SlideExtendedTest.php
Normal file
198
php/tests/SlideExtendedTest.php
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ProPresenter\Parser\Tests;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ProPresenter\Parser\Group;
|
||||
use ProPresenter\Parser\ProFileReader;
|
||||
use ProPresenter\Parser\ProFileWriter;
|
||||
use ProPresenter\Parser\Slide;
|
||||
use ProPresenter\Parser\Song;
|
||||
|
||||
class SlideExtendedTest extends TestCase
|
||||
{
|
||||
private const TEST_WITH_MACRO = '/Users/thorsten/AI/propresenter-work/ref/TestMitMakro.pro';
|
||||
private const TEST_WITH_MEDIA_AND_MACRO = '/Users/thorsten/AI/propresenter-work/ref/TestMitBildernUndMakro.pro';
|
||||
|
||||
#[Test]
|
||||
public function testCopyrightSlideHasMacro(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'COPYRIGHT', 0);
|
||||
|
||||
$this->assertTrue($slide->hasMacro());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testMacroNameAndUuid(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'COPYRIGHT', 0);
|
||||
|
||||
$this->assertSame('Lied 1.Folie', $slide->getMacroName());
|
||||
$this->assertSame('20C1DFDE-0FB6-49E5-B90C-E6608D427212', $slide->getMacroUuid());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testMacroCollectionNameAndUuid(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'COPYRIGHT', 0);
|
||||
|
||||
$this->assertSame('--MAIN--', $slide->getMacroCollectionName());
|
||||
$this->assertSame('8D02FC57-83F8-4042-9B90-81C229728426', $slide->getMacroCollectionUuid());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testRegularSlideHasNoMacro(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'Verse 1', 0);
|
||||
|
||||
$this->assertFalse($slide->hasMacro());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testSetMacroOnSlide(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'Verse 1', 0);
|
||||
|
||||
$slide->setMacro('Macro Name', '11111111-2222-3333-4444-555555555555', 'Collection Name', 'AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE');
|
||||
|
||||
$this->assertTrue($slide->hasMacro());
|
||||
$this->assertSame('Macro Name', $slide->getMacroName());
|
||||
$this->assertSame('11111111-2222-3333-4444-555555555555', $slide->getMacroUuid());
|
||||
$this->assertSame('Collection Name', $slide->getMacroCollectionName());
|
||||
$this->assertSame('AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE', $slide->getMacroCollectionUuid());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testRemoveMacro(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'Verse 1', 0);
|
||||
|
||||
$slide->setMacro('Macro Name', '11111111-2222-3333-4444-555555555555');
|
||||
$this->assertTrue($slide->hasMacro());
|
||||
|
||||
$slide->removeMacro();
|
||||
$this->assertFalse($slide->hasMacro());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testSetAndRemoveMacroRoundTrip(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MACRO);
|
||||
$slide = self::getSlideByGroupName($song, 'Verse 1', 0);
|
||||
|
||||
$slide->setMacro('Round Trip Macro', 'AAAAAAAA-1111-2222-3333-BBBBBBBBBBBB', '--MAIN--', '8D02FC57-83F8-4042-9B90-81C229728426');
|
||||
|
||||
$tempPath = sys_get_temp_dir() . '/propresenter-slide-extended-' . uniqid('', true) . '.pro';
|
||||
try {
|
||||
ProFileWriter::write($song, $tempPath);
|
||||
|
||||
$readBack = ProFileReader::read($tempPath);
|
||||
$readBackSlide = self::getSlideByGroupName($readBack, 'Verse 1', 0);
|
||||
|
||||
$this->assertTrue($readBackSlide->hasMacro());
|
||||
$this->assertSame('Round Trip Macro', $readBackSlide->getMacroName());
|
||||
$this->assertSame('AAAAAAAA-1111-2222-3333-BBBBBBBBBBBB', $readBackSlide->getMacroUuid());
|
||||
|
||||
$readBackSlide->removeMacro();
|
||||
$this->assertFalse($readBackSlide->hasMacro());
|
||||
} finally {
|
||||
@unlink($tempPath);
|
||||
}
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testImageSlideHasMedia(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[0];
|
||||
|
||||
$this->assertTrue($slide->hasMedia());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testMediaUrlAndFormat(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[0];
|
||||
|
||||
$this->assertStringContainsString('file://', (string) $slide->getMediaUrl());
|
||||
$this->assertSame('JPG', $slide->getMediaFormat());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testImageSlideHasNoText(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[0];
|
||||
|
||||
$this->assertSame('', $slide->getPlainText());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testSlideWithLabel(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[1];
|
||||
|
||||
$this->assertSame('Seniorennachmittag März.jpg', $slide->getLabel());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testSlideWithoutLabel(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[0];
|
||||
|
||||
$this->assertSame('', $slide->getLabel());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testImageSlideWithMacro(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[1];
|
||||
|
||||
$this->assertTrue($slide->hasMacro());
|
||||
$this->assertSame('1:1 - Beamer & Stream', $slide->getMacroName());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function testSetLabel(): void
|
||||
{
|
||||
$song = self::readSong(self::TEST_WITH_MEDIA_AND_MACRO);
|
||||
$slide = $song->getSlides()[1];
|
||||
|
||||
$slide->setLabel('New Label');
|
||||
|
||||
$this->assertSame('New Label', $slide->getLabel());
|
||||
}
|
||||
|
||||
private static function readSong(string $path): Song
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
self::markTestSkipped('Reference file not found: ' . $path);
|
||||
}
|
||||
|
||||
return ProFileReader::read($path);
|
||||
}
|
||||
|
||||
private static function getSlideByGroupName(Song $song, string $groupName, int $slideIndex): Slide
|
||||
{
|
||||
$group = $song->getGroupByName($groupName);
|
||||
self::assertInstanceOf(Group::class, $group, 'Group not found: ' . $groupName);
|
||||
|
||||
$slides = $song->getSlidesForGroup($group);
|
||||
self::assertArrayHasKey($slideIndex, $slides, 'Slide index not found in group: ' . $groupName);
|
||||
|
||||
return $slides[$slideIndex];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue