Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DGIR-142 : Add thumbnail to manifest #7

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/EventSubscriber/V3/BaseImageBodyEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ protected function getBody(?string $slug, FileInterface $file, array $extra = []
$base_id = strtr($slug, [
'{identifier}' => rawurlencode($id_plugin->getIdentifier($file)),
]);

return [
'id' => "$base_id/full/full/0/default.jpg",
'type' => 'Image',
Expand Down
64 changes: 64 additions & 0 deletions src/Normalizer/V3/ContentEntityNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\file\FileInterface;
use Drupal\iiif_presentation_api\Event\V3\ContentEntityExtrasEvent;
use Drupal\iiif_presentation_api\Event\V3\ImageBodyEvent;
use Drupal\iiif_presentation_api\Normalizer\EntityUriTrait;
use Drupal\node\NodeInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
Expand Down Expand Up @@ -106,9 +108,71 @@ public function normalize($object, $format = NULL, array $context = []) {
$normalized = NestedArray::mergeDeep($normalized, $extras);
}

// It triggers for node and media. Adds thumbnail multiple time.
// Restricting it for node only.
if ($object->getEntityTypeId() == 'node') {

// Load the entity type manager.
$entity_type_manager = \Drupal::entityTypeManager();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not able to add DI for this, it throws an error for circular dependency if I add EntityTypeManagerInterface.


// Get term id for Thumbnail Image.
$term_storage = $entity_type_manager->getStorage('taxonomy_term');
$term = $term_storage->loadByProperties([
'name' => 'Thumbnail Image',
'vid' => 'islandora_media_use',
]);

// Check if the term is found.
if (!empty($term)) {
// Get the term ID.
$term_id = reset($term)->id();
}

// Get the storage handler for the media entity.
$media_storage = $entity_type_manager->getStorage('media');

// Load a single media entity by properties.
$media_entities = $media_storage->loadByProperties([
'field_media_use' => $term_id,
'field_media_of' => $object->id(),
]);

// Check if a media entity was found.
if ($media_entities) {
// Process the single media entity as needed.
$media_entity = reset($media_entities);

// Get the file ID from the file field.
$file_id = $media_entity->get('field_media_image')->target_id;
$file = $entity_type_manager->getStorage('file')->load($file_id);

$normalized['thumbnail'] = $this->generateBody($file);
}
}
Comment on lines +111 to +151
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module is not supposed to be aware of any Islandora-isms. Particular bindings to Islandora should be done in the islandora_iiif_presentation_api module.

Also, really kind of seems like this would fit as an event subscriber to the event already dispatched: https://github.com/discoverygarden/iiif_presentation_api/pull/7/files#diff-1f327eb453852f8fd88e233a026b713ce29fdbb5af1418b1f204f466a123e1f7R101-R109

Copy link
Author

@Prashant-bd Prashant-bd Jan 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adam-vessey I will try to move the implementation to the islandora_iiif_presentation_api module.
From where we can add a thumbnail to the manifest? Is it coming from a Display mode or a different implementation where we are adding required fields?

Sorry if I am not clear above, I am trying to understand the implementation. I would be happy to get on a call to discuss same.

Copy link
Contributor

@adam-vessey adam-vessey Jan 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it coming from a Display mode or a different implementation where we are adding required fields?

Unsure, that's what this ticket is (re)defining, no? Would have to go back to the reporter/project owner? Given the original notes referencing islandora_iiif (of which this module is an alternative implementation), I'm unsure of the exact intent.

Really, I'm not sure what this ticket is trying to accomplish, seeming to conflate slow manifest generation with the dereferencing of entities described within the manifest. Sure, allowing it (Mirador) to use IIIF-I to generate thumbnails might consume some cycles on the server CPU side of things; however, given anticipated usage, it could be seen as cache warming (having the Cantaloupe/IIIF-I server acquire the images from which it will be serving tiles, but the IIIF-I-derived thumbnails could also be cached). Trying to use the "Thumbnail image(s)" requires all these additional queries in order to identify the media to provide as a thumbnail, for inclusion in the manifest,

If we wanted to offer a mechanism to provide those related media/file with the http://pcdm.org/use#ThumbnailImage media use, then sure, we can; however, given the whole intent of IIIF in general, I would think instead it might make more sense to generate an explicit thumbnail entry with a IIIF Image API service reference and appropriate dimensions, somewhat similar to https://iiif.io/api/presentation/3.0/#b-example-manifest-response:

  "thumbnail": [
    {
      "id": "https://example.org/iiif/book1/page1/full/80,100/0/default.jpg",
      "type": "Image",
      "format": "image/jpeg",
      "service": [
        {
          "id": "https://example.org/iiif/book1/page1",
          "type": "ImageService3",
          "profile": "level1"
        }
      ]
    }
  ],

so, to add the thumbnail entries where appropriate, but based upon being derived via the IIIF Image API, effectively just needing to vary the dimensions in some manner:

'id' => "$base_id/full/full/0/default.jpg",

Something such as:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing code at 'id' => "$base_id/full/full/0/default.jpg", and using IIIF Image API service reference and appropriate dimensions was my first thought. But as per discussion with Chris Mac, and Luke, it should be generated using thumbnail.
https://discoverygarden.atlassian.net/browse/DGIR-142?focusedCommentId=219117

We can discuss DGIR-142 once Luke is back.

Thanks for providing code changes in feedback.

return $this->normalizeEntityFields($object, $format, $context, $normalized);
}

/**
* Generate the annotation body.
*
* @param \Drupal\file\FileInterface $file
* The file for which to generate the body.
*
* @return array
* An associative array representing the body.
*/
protected function generateBody(FileInterface $file) : array {
/** @var \Drupal\iiif_presentation_api\Event\V3\ImageBodyEvent $event */
$event = $this->eventDispatcher->dispatch(new ImageBodyEvent($file));
$bodies = $event->getBodies();
if (!$bodies) {
return [];
}
$body = reset($bodies);
$body['service'] = array_merge(...array_filter(array_column($bodies, 'service')));
return $body;
}

/**
* Normalizes all fields present on a content entity.
*
Expand Down
Loading