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

959 configurable width height caching #1029

Merged
merged 39 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f0912f6
Refactor IIIF, create IIIF Info Service.
alxp Oct 17, 2023
bc06fca
Islandora IIIF: Add action to retrieve image attributes from IIIF ser…
alxp Oct 17, 2023
eb235f8
Islandora IIIF: Add auth headers to IIIF Info request.
alxp Oct 17, 2023
c9bd091
Islandora IIIF: Change media action to node.
alxp Oct 18, 2023
916e343
Islandora IIIF: Update README.
alxp Oct 18, 2023
470a078
Finish rebase.
alxp Jun 8, 2024
27d7705
Islandora IIIF: Address PHPCS errors.
alxp Oct 18, 2023
6e832b5
Islandora IIIF: Address PHPCS errors.
alxp Oct 19, 2023
f68a8e9
islandora_iiif: Fix Authorization header syntax.
alxp Nov 13, 2023
dd7360d
959-iiif-width-height-caching Islandora IIIF: Add search endpoint con…
alxp Nov 20, 2023
5becfa5
959-iiif-width-height-caching Add handler for ServerException in Isla…
alxp Feb 6, 2024
c86a454
959-iiif-width-height-caching Add option to skip retrieveing TIFF and…
alxp Feb 7, 2024
8dd22c0
Checking for width/height on media first when generating IIIF manifest
dannylamb Feb 9, 2024
6b75a85
959-iiif-width-height-caching Add IIIF service function to get downla…
alxp Feb 15, 2024
885fc34
Fix redundant function from rebase.
alxp Jun 8, 2024
16f53dc
Rebase resolve conflict.
alxp Jun 10, 2024
5ed299f
WIP: Make Get dimensions from File image action target fields configu…
alxp Jun 10, 2024
f0d37c8
WIP
alxp Jun 11, 2024
c99c77d
WIP use configured height and width fields.
alxp Jun 12, 2024
e465a75
Extract TIFF and JP2 dimensions action: Make width and height field c…
alxp Jun 12, 2024
2a8976f
Islandora IIIF: Make media height and width fields configurable.
alxp Jun 13, 2024
e5b2a12
Islandora IIIF: Make media width and height fields configurable in ma…
alxp Jun 16, 2024
c316609
Islandora IIIF: Add config schema update hook.
alxp Jun 17, 2024
86586c6
Islandora IIIF: Fix warning on Views display plugin page.
alxp Jun 18, 2024
816b6b5
Remove outdated action.
alxp Jun 24, 2024
01988df
Islandora IIIF: Update the README.
alxp Jun 24, 2024
3f26b3e
Islandora IIIF: Update PHPDoc description of IIIF Dimensions complex …
alxp Jun 25, 2024
ce763f3
Islandora IIIF: Add instructions for setting up a context reaction fo…
alxp Jun 25, 2024
923157b
Update modules/islandora_iiif/config/schema/islandora_iiif.schema.yml
alxp Jun 26, 2024
773eb74
Islandora IIIF: Address PHPCS errors.
alxp Jun 28, 2024
d5f9261
Islandora IIIF: Remove unused schema entry.
alxp Jun 28, 2024
facd6fb
Islandora IIIF: Address PHPCS errors.
alxp Jun 29, 2024
a3e76c7
Islandora IIIF: Address PHPCS errors.
alxp Jun 29, 2024
923419a
Islandora IIIF: Fix PHPCS errors.
alxp Jun 29, 2024
c91cd58
Islandora IIIF: Fix PHPCS warnings.
alxp Jun 29, 2024
7508ca7
Islandora IIIF: Address code review comment.
alxp Jul 10, 2024
bdde016
Update modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php
alxp Jul 10, 2024
e30bf3d
Update modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php
alxp Jul 10, 2024
240094e
Islandora IIIF: Address PHPCS errors.
alxp Jul 11, 2024
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
45 changes: 40 additions & 5 deletions modules/islandora_iiif/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## Introduction

Provides IIIF manifests using views.
Provides [IIIF manifests](https://iiif.io) using views.

## Requirements

Expand All @@ -20,7 +20,7 @@ For a full digital repository solution, see our [installation documentation](htt
To download/enable just this module, use the following from the command line:

```bash
$ composer require islandora/islandora
$ composer require drupal/islandora
$ drush en islandora_core_feature
$ drush mim islandora_tags
$ drush en islandora_iiif
Expand All @@ -38,18 +38,53 @@ This module implements a Views Style plugin. It provides the following settings:

1. Tile Source: A field that was added to the views list of fields with the image to be served. This should be a File or Image type field on a Media.
2. Structured Text field: This lets you specify a file field where OCR text with positional data, e.g., hOCR can be found.
3. Structured Text Term: If your Islandora Object has a separate media with hOCR, point to it with this setting.
4. File Width and Height fields: If you want to use TIFF or JP2 files directly, set the fields where the files' width and height can be found with these settings.

### Media Attributes from IIIF Action

The module also provides an action that lets a site owner populate a TIFF or JP2 image's width and
height attributes into fields so the IIIF server is not bogged down trying to generate a manifest if
it doesn't have them.

It is a complex action that must be configured. Go to
Admin -> Actions UI -> Actions, choose
"Add image dimensions retrieved from the IIIF server" from the Create Action drop-down
And on the next screen, choose the width
and height fields that the action should
populate.

To use it, either:
- Add it as a derivative reaction to a node with an Original FIle as its child, or
- Use it as a batch action, such as on a Paged Content object's list of child pages.

### Setting up the action as a Context Reaction

These instructions assume a standard Islandora Starter Site, so if you have different field names or Contexts, adjust accordingly.

1. Go to admin/config/system/actions
2. Choose "Add image dimensions retrieved from the IIIF server" from the Create Complex Action drop-down and then click Create.
3. Enter Original File for the Source Media Use term.
4. Choose media -- file -- Width and Media -- File -- Height for the corresponding configuration values and click Save.
5. Go to admin/structure/context, and click Duplicate oon the Page Derivatives row.
6. Name the new context something like "Retrieve Page Dimensionss". and edit it.
7. This is the tricky bit, delete 'Original File' from the 'Media has term with URI' field and replace it with Service File. The explanation for this is that to retrieve a file from the IIIF server, it must be part of an Islandora Media that has been fully created and saved and given a URL. This hasn't happened yet when Original File derivatives are being created, so we need to hang our action onto a derivative that is created after the original one.
8. Under Reactions, deselect the existing actions and select "Add i mage dimensions from IIIF sserver" and click Save and continue.
9. Go back to your Paged Content object and add another child with a File media, to which you should upload another TIFF or JP2 file.
10. Without going to the Original File Book Manifestt, make sure that a service file has been generated, then click Edit on the Original File media.
11. Ensure that the Width and Height fields are populated with thee correct values from the file.


## Documentation

Official documentation is available on the [Islandora 8 documentation site](https://islandora.github.io/documentation/).
Official documentation is available on the [Islandora 2 documentation site](https://islandora.github.io/documentation/).

## Development

If you would like to contribute, please get involved by attending our weekly [Tech Call](https://github.com/Islandora/documentation/wiki). We love to hear from you!

If you would like to contribute code to the project, you need to be covered by an Islandora Foundation [Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_cla.pdf) or [Corporate Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_ccla.pdf). Please see the [Contributors](http://islandora.ca/resources/contributors) pages on Islandora.ca for more information.

We recommend using the [islandora-playbook](https://github.com/Islandora-Devops/islandora-playbook) to get started.

## License

[GPLv2](http://www.gnu.org/licenses/gpl-2.0.txt)
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ views.style.iiif_manifest:
structured_text_term_uri:
type: string
label: "Structured text term"
getdimensions_from_sewrver:
alxp marked this conversation as resolved.
Show resolved Hide resolved
type: boolean
label: "Retrieve image dimensions from IIIF server"
alxp marked this conversation as resolved.
Show resolved Hide resolved
search_endpoint:
type: string
label: "Search endpoint path"
43 changes: 43 additions & 0 deletions modules/islandora_iiif/islandora_iiif.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/**
* @file
* Install/update hook implementations.
*/

use Symfony\Component\Yaml\Yaml;

/**
* Update config schema.
*/
function islandora_iiif_update_92002(&$sandbox) {

/**
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
$config_factory = \Drupal::service('config.factory');
$all_configs = $config_factory->listAll();
$views_configs = array_values(array_filter($all_configs, function($config) {
return str_starts_with($config, 'views.view.');
}));

foreach ($views_configs as $views_config_name) {
$needs_save = FALSE;
$view_config = $config_factory->getEditable($views_config_name);
$displays = $view_config->get('display');
foreach ($displays as $display_name => $display) {
if ($display['display_plugin'] == 'rest_export'
&& $display['display_options']['style']['type'] == 'iiif_manifest'
&&!empty($display['display_options']['style']['options']['iiif_ocr_file_field'])) {

$display['display_options']['style']['options']['advanced']['iiif_ocr_file_field'] = $display['display_options']['style']['options']['iiif_ocr_file_field'];
unset($display['display_options']['style']['options']['iiif_ocr_file_field']);
$view_config->set('display.' . $display_name . '.display_options.style.options', $display['display_options']['style']['options']);
$needs_save = TRUE;
}
}
if ($needs_save) {
$view_config->save();
}
}
}
4 changes: 4 additions & 0 deletions modules/islandora_iiif/islandora_iiif.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
services:
islandora_iiif:
class: Drupal\islandora_iiif\IiifInfo
arguments: ['@config.factory', '@http_client', '@logger.channel.islandora', '@jwt.authentication.jwt']
154 changes: 154 additions & 0 deletions modules/islandora_iiif/src/IiifInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

namespace Drupal\islandora_iiif;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\file\FileInterface;
use Drupal\jwt\Authentication\Provider\JwtAuth;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ServerException;
use Symfony\Component\HttpKernel\Event\RequestEvent;

/**
* Get IIIF related info for a given File or Image entity.
*/
class IiifInfo {

/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;


/**
* The HTTP client.
*
* @var \GuzzleHttp\Client
*/
protected $httpClient;

/**
* This module's config.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $iiifConfig;

/**
* JWT Auth provider service.
*
* @var \Drupal\jwt\Authentication\Provider\JwtAuth
*/
protected $jwtAuth;

/**
* The logger.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $logger;

/**
* Constructs an IiifInfo object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Guzzle\Http\Client $http_client
* The HTTP Client.
* @param \Drupal\Core\Logger\LoggerChannelInterface $channel
* Logger channel.
* @param \Drupal\jwt\Authentication\Provider\JwtAuth $jwt_auth
* The JWT auth provider.
*/
public function __construct(ConfigFactoryInterface $config_factory, Client $http_client, LoggerChannelInterface $channel, JwtAuth $jwt_auth) {
$this->configFactory = $config_factory;

$this->iiifConfig = $this->configFactory->get('islandora_iiif.settings');
$this->httpClient = $http_client;
$this->logger = $channel;
$this->jwtAuth = $jwt_auth;
}

/**
* The IIIF base URL for an image.
*
* Visiting this URL will resolve to the info.json for the image.
*
* @return string
* The absolute URL on the IIIF server.
*/
public function baseUrl($image) {

if ($this->iiifConfig->get('use_relative_paths')) {
$file_url = ltrim($image->createFileUrl(TRUE), '/');
}
else {
$file_url = $image->createFileUrl(FALSE);
}

$iiif_address = $this->iiifConfig->get('iiif_server');
$iiif_url = rtrim($iiif_address, '/') . '/' . urlencode($file_url);

return $iiif_url;
}

/**
* Retrieve an image's original dimensions via the IIIF server.
*
* @param \Drupal\File\FileInterface $file
* The image file.
*
* @return array|false
* The image dimensions in an array as [$width, $height]
*/
public function getImageDimensions(FileInterface $file) {
$iiif_url = $this->baseUrl($file);
try {
$info_json = $this->httpClient->request('get', $iiif_url, [
'headers' => [
'Authorization' => 'Bearer ' . $this->jwtAuth->generateToken(),
],
])->getBody();
$resource = json_decode($info_json, TRUE);
$width = $resource['width'];
$height = $resource['height'];
if (is_numeric($width) && is_numeric($height)) {
return [intval($width), intval($height)];
}
}
catch (ClientException | ConnectException | RequestException | ServerException $e) {
$this->logger->info("Error getting image file dimensions from IIIF server: " . $e->getMessage());
}
return FALSE;
}

/**
* The IIIF base URL for an image.
*
* Visiting this URL will resolve to the full image resized to the maximum dimensions given.
*
* @see https://iiif.io/api/image/2.1/
*
* @param Drupal\file\FileInterface $image
* The image entity.
* @param int width
* The maximum width of the image to be returned. 0 for no constraint.
* @param int $height
* The maxim um height of the image to be returned. 0 for no contraint.
*
* @return string
* The IIIF URl to retrieve the full image with the given max dimensions.
*/
public function getImageWithMaxDimensions($image, $width = 0, $height = 0) {
$base_url = $this->baseUrl($image);
return $base_url . "/full/!$width,$height/0/default.jpg";

}

}
Loading
Loading