From b73d0a83727fc19d67fa6e845134430227891680 Mon Sep 17 00:00:00 2001 From: astanley Date: Thu, 24 Apr 2025 14:39:38 +0000 Subject: [PATCH] Extracted logic to service --- caption_linker.services.yml | 7 ++ src/Plugin/Action/LinkCaption.php | 49 +-------- src/Service/CaptionLinker.php | 67 ++++++++++++ tests/src/Unit/Service/CaptionLinkerTest.php | 101 +++++++++++++++++++ 4 files changed, 179 insertions(+), 45 deletions(-) create mode 100644 caption_linker.services.yml create mode 100644 src/Service/CaptionLinker.php create mode 100644 tests/src/Unit/Service/CaptionLinkerTest.php diff --git a/caption_linker.services.yml b/caption_linker.services.yml new file mode 100644 index 0000000..f86d8e0 --- /dev/null +++ b/caption_linker.services.yml @@ -0,0 +1,7 @@ +services: + caption_linker.caption_linker: + class: Drupal\caption_linker\Service\CaptionLinker + arguments: + - '@entity_type.manager' + - '@islandora.utils' + - '@logger.channel.islandora' diff --git a/src/Plugin/Action/LinkCaption.php b/src/Plugin/Action/LinkCaption.php index 6228e7c..9c59546 100644 --- a/src/Plugin/Action/LinkCaption.php +++ b/src/Plugin/Action/LinkCaption.php @@ -1,16 +1,13 @@ get('entity_type.manager'), - $container->get('islandora.utils'), - $container->get('logger.channel.islandora'), + $container->get('caption_linker.caption_linker') ); } @@ -74,7 +53,6 @@ final class LinkCaption extends ActionBase implements ContainerFactoryPluginInte /** @var \Drupal\node\NodeInterface $object */ $access = $object->access('update', $account, TRUE) ->andIf($object->status->access('edit', $account, TRUE)); - return $return_as_object ? $access : $access->isAllowed(); } @@ -82,26 +60,7 @@ final class LinkCaption extends ActionBase implements ContainerFactoryPluginInte * {@inheritdoc} */ public function execute(ContentEntityInterface $entity = NULL): void { - $transcript_media = $this->getMediaByUri($entity, 'http://pcdm.org/use#Transcript'); - $host_media = $this->getMediaByUri($entity, 'http://pcdm.org/use#ServiceFile') - ?? $this->getMediaByUri($entity, 'http://pcdm.org/use#OriginalFile'); - - if ($transcript_media && $host_media - && $transcript_media->bundle() === 'able_player_caption' - && $host_media->hasField('field_ableplayer_media_caption') - && $host_media->get('field_ableplayer_media_caption')->isEmpty()) { - - $host_media->set('field_ableplayer_media_caption', ['target_id' => $transcript_media->id()]); - $host_media->save(); - } - } - - /** - * {@inheritdoc} - */ - public function getMediaByUri($entity, $uri) { - $term = $this->islandoraUtils->getTermForUri($uri); - return $this->islandoraUtils->getMediaWithTerm($entity, $term); + $this->captionLinker->linkCaption($entity); } } diff --git a/src/Service/CaptionLinker.php b/src/Service/CaptionLinker.php new file mode 100644 index 0000000..07d9a65 --- /dev/null +++ b/src/Service/CaptionLinker.php @@ -0,0 +1,67 @@ +getMediaByUri($entity, 'http://pcdm.org/use#Transcript'); + $host_media = $this->getMediaByUri($entity, 'http://pcdm.org/use#ServiceFile') + ?? $this->getMediaByUri($entity, 'http://pcdm.org/use#OriginalFile'); + + if ($transcript_media && $host_media + && $transcript_media->bundle() === 'able_player_caption' + && $host_media->hasField('field_ableplayer_media_caption') + && $host_media->get('field_ableplayer_media_caption')->isEmpty()) { + $host_media->set('field_ableplayer_media_caption', ['target_id' => $transcript_media->id()]); + $host_media->save(); + } + } + + /** + * Gets a media item from an entity by its RDF use URI. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The node or media entity. + * @param string $uri + * The RDF use URI. + * + * @return \Drupal\media\MediaInterface|null + * The matching media item or NULL if not found. + */ + protected function getMediaByUri(ContentEntityInterface $entity, string $uri) { + $term = $this->islandoraUtils->getTermForUri($uri); + return $this->islandoraUtils->getMediaWithTerm($entity, $term); + } + +} diff --git a/tests/src/Unit/Service/CaptionLinkerTest.php b/tests/src/Unit/Service/CaptionLinkerTest.php new file mode 100644 index 0000000..df4dcb2 --- /dev/null +++ b/tests/src/Unit/Service/CaptionLinkerTest.php @@ -0,0 +1,101 @@ +islandoraUtils = $this->createMock(IslandoraUtils::class); + $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class); + $this->logger = $this->createMock(LoggerChannelInterface::class); + + $this->captionLinker = new CaptionLinker( + $this->entityTypeManager, + $this->islandoraUtils, + $this->logger + ); + } + + /** + * Tests linking the caption when all conditions are met. + */ + public function testLinkCaption(): void { + $node = $this->createMock(NodeInterface::class); + $transcript = $this->createMock(MediaInterface::class); + $host = $this->createMock(MediaInterface::class); + + // Mock the Islandora methods. + $this->islandoraUtils->method('getTermForUri')->willReturn('mock_term'); + $this->islandoraUtils->method('getMediaWithTerm') + ->withConsecutive([$node, 'mock_term'], [$node, 'mock_term'], [$node, 'mock_term']) + ->willReturnOnConsecutiveCalls($transcript, $host, null); + + $transcript->method('bundle')->willReturn('able_player_caption'); + + // Field checks and save expectations. + $host->method('hasField')->with('field_ableplayer_media_caption')->willReturn(TRUE); + $host->method('get')->with('field_ableplayer_media_caption')->willReturn( + new class { + public function isEmpty() { return TRUE; } + } + ); + + $host->expects($this->once())->method('set')->with( + 'field_ableplayer_media_caption', + ['target_id' => $transcript->id()] + ); + $host->expects($this->once())->method('save'); + + $transcript->method('id')->willReturn(42); + + $this->captionLinker->linkCaption($node); + } + + /** + * Tests that no linking occurs if caption field is not empty. + */ + public function testNoLinkIfFieldPopulated(): void { + $node = $this->createMock(NodeInterface::class); + $transcript = $this->createMock(MediaInterface::class); + $host = $this->createMock(MediaInterface::class); + + $this->islandoraUtils->method('getTermForUri')->willReturn('mock_term'); + $this->islandoraUtils->method('getMediaWithTerm')->willReturnOnConsecutiveCalls($transcript, $host); + + $transcript->method('bundle')->willReturn('able_player_caption'); + $host->method('hasField')->willReturn(TRUE); + $host->method('get')->willReturn( + new class { + public function isEmpty() { return FALSE; } + } + ); + + $host->expects($this->never())->method('set'); + $host->expects($this->never())->method('save'); + + $this->captionLinker->linkCaption($node); + } + +}