4 changed files with 179 additions and 45 deletions
@ -0,0 +1,7 @@
|
||||
services: |
||||
caption_linker.caption_linker: |
||||
class: Drupal\caption_linker\Service\CaptionLinker |
||||
arguments: |
||||
- '@entity_type.manager' |
||||
- '@islandora.utils' |
||||
- '@logger.channel.islandora' |
||||
@ -0,0 +1,67 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\caption_linker\Service; |
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface; |
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Drupal\Core\Logger\LoggerChannelInterface; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
|
||||
/** |
||||
* Service to link transcript media items to host media items as captions. |
||||
*/ |
||||
class CaptionLinker { |
||||
|
||||
/** |
||||
* Constructs a new CaptionLinker service. |
||||
* |
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager |
||||
* The entity type manager service. |
||||
* @param \Drupal\islandora\IslandoraUtils $islandoraUtils |
||||
* The Islandora utils service. |
||||
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger |
||||
* The logger for the Islandora channel. |
||||
*/ |
||||
public function __construct( |
||||
protected readonly EntityTypeManagerInterface $entityTypeManager, |
||||
protected readonly IslandoraUtils $islandoraUtils, |
||||
protected readonly LoggerChannelInterface $logger |
||||
) {} |
||||
|
||||
/** |
||||
* Links a transcript media item to a host media item as a caption. |
||||
* |
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity |
||||
* The node entity to process. |
||||
*/ |
||||
public function linkCaption(ContentEntityInterface $entity): 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(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,101 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\Tests\caption_linker\Unit\Service; |
||||
|
||||
use Drupal\caption_linker\Service\CaptionLinker; |
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Drupal\Core\Logger\LoggerChannelInterface; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
use Drupal\media\MediaInterface; |
||||
use Drupal\node\NodeInterface; |
||||
use PHPUnit\Framework\MockObject\MockObject; |
||||
use PHPUnit\Framework\TestCase; |
||||
|
||||
/** |
||||
* @coversDefaultClass \Drupal\caption_linker\Service\CaptionLinker |
||||
* @group caption_linker |
||||
*/ |
||||
class CaptionLinkerTest extends TestCase { |
||||
|
||||
/** |
||||
* The service under test. |
||||
*/ |
||||
protected CaptionLinker $captionLinker; |
||||
|
||||
protected MockObject $islandoraUtils; |
||||
protected MockObject $entityTypeManager; |
||||
protected MockObject $logger; |
||||
|
||||
protected function setUp(): void { |
||||
$this->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); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue