diff --git a/module/DigLib/src/DigLib/Controller/VuDLController.php b/module/DigLib/src/DigLib/Controller/VuDLController.php
index 9951fde..05212cb 100644
--- a/module/DigLib/src/DigLib/Controller/VuDLController.php
+++ b/module/DigLib/src/DigLib/Controller/VuDLController.php
@@ -846,16 +846,16 @@ public function passthroughAction()
protected function getIdsFromManifest($data)
{
$ids = [];
- if (isset($data['sequences'][0]['canvases'])) {
- foreach ($data['sequences'][0]['canvases'] as $canvas) {
- preg_match(
- '/vudl:[0-9]+/',
- $canvas['rendering'][0]['@id'] ?? '',
- $matches
- );
- if (isset($matches[0])) {
- $ids[] = $matches[0];
- }
+
+ foreach ($data['items'] as $canvas) {
+ preg_match(
+ '/vudl:[0-9]+/',
+ $canvas['rendering'][0]['id'] ?? '',
+ $matches
+ );
+
+ if (isset($matches[0])) {
+ $ids[] = $matches[0];
}
}
return $ids;
diff --git a/module/DigLib/src/DigLib/IIIF/ManifestGenerator.php b/module/DigLib/src/DigLib/IIIF/ManifestGenerator.php
index 5dec073..d0dc5fa 100644
--- a/module/DigLib/src/DigLib/IIIF/ManifestGenerator.php
+++ b/module/DigLib/src/DigLib/IIIF/ManifestGenerator.php
@@ -50,7 +50,7 @@
*/
class ManifestGenerator
{
- public const IIIF_CONTEXT = 'http://iiif.io/api/presentation/2/context.json';
+ public const IIIF_CONTEXT = 'http://iiif.io/api/presentation/3/context.json';
/**
* Server URL helper.
@@ -201,9 +201,10 @@ protected function extractManifestMetadata($id, $details)
foreach ($details as $key => $current) {
if (!in_array($key, $skip)) {
$value = (array)$current['value'];
+ $formatValues = $this->formatManifestMetadataValues($key, $value);
$retVal[$key] = [
- 'label' => $current['title'],
- 'value' => $this->formatManifestMetadataValues($key, $value),
+ 'label' => ['en' => [$current['title']]],
+ 'value' => ['en' => [$formatValues]],
];
}
}
@@ -219,16 +220,16 @@ protected function extractManifestMetadata($id, $details)
// Add some useful links to the bottom:
$recordUrl = $this->getUri('record', ['id' => $id]);
$persistUrl = $this->getUri('vudl-record', ['id' => $id]);
- $sortedRetVal[] = [
- 'label' => 'About',
- 'value' => ''
+ $value = ''
. 'More Details
'
. 'Permanent Link'
- . '',
+ . '';
+ $sortedRetVal[] = [
+ 'label' => ['en' => ['About']],
+ 'value' => ['en' => [$value]],
];
-
return $sortedRetVal;
}
@@ -298,111 +299,158 @@ protected function getImageDetailsForCanvas($raw, $imageServerBase)
}
/**
- * Build JSON data for a single canvas.
+ * Build JSON data for a non-image canvas.
*
- * @param string $id Record ID
- * @param int $i Position of canvas in overall array (used for canvas
- * ID generation)
- * @param array $raw Raw data to format into canvas
- * @param string $type Type of list ('image' or 'audio')
+ * @param string $id Record ID
+ * @param int $i Position of canvas in overall array (used for canvas ID generation)
+ * @param array $raw Raw data to format into canvas
+ * @param string $type Type of list ('image' or 'audio')
+ * @param array $list List to check
+ * @param array $outline Outline data
*
* @return array
*/
- protected function getSingleCanvas($id, $i, $raw, $type)
+ protected function getNonImageCanvas($id, $i, $raw, $type, $list, $outline)
{
$canvasUrl = $this->getUri(
'vudl-record-canvas',
['id' => $id, 'canvas' => 'p' . $i]
);
- $canvasType = 'sc:Canvas';
- if ($type === 'image') {
- $imageServerBase = $this->config->Images->serverUrl ?? false;
- if (!$imageServerBase) {
- throw new \Exception('Must set image server base URL.');
- }
- [$width, $height, $imageUrl, $mimeType]
- = $this->getImageDetailsForCanvas($raw, $imageServerBase);
- $content = [
- 'height' => $height,
- 'width' => $width,
- 'images' => [
- [
- '@type' => 'oa:Annotation',
- 'motivation' => 'sc:painting',
- 'resource' => [
- '@id' => $imageUrl,
- '@type' => 'dctypes:Image',
- 'format' => $mimeType,
- 'service' => [
- '@context' => 'http://iiif.io/api/image/2/context.json',
- '@id' => $imageServerBase . urlencode($raw['id']),
- 'profile' => 'http://iiif.io/api/image/2/level1.json',
+
+ if ($type == 'audio') {
+ $preferredType = 'Sound';
+ $preferredRendering = 'audio/mp3';
+ } elseif ($type == 'video') {
+ $preferredType = 'MovingImage';
+ $preferredRendering = 'video/mp4';
+ } else {
+ // Format as a generic download:
+ $preferredType = 'foaf:Document';
+ $preferredRendering = 'application/pdf';
+ }
+ $url = $this->getUri(
+ 'files',
+ ['type' => 'MASTER', 'id' => $raw['id']]
+ );
+ $description = isset($raw['sizebytes_str'])
+ ? ($raw['sizebytes_str'] / 1024) . 'k'
+ : '';
+ $content = [
+ 'height' => 600,
+ 'width' => 800,
+ 'items' => [
+ [
+ 'id' => $canvasUrl . '#content',
+ 'type' => 'AnnotationPage',
+ 'items' => [
+ [
+ 'id' => $canvasUrl . '#item' . $i,
+ 'type' => 'Annotation',
+ 'motivation' => 'painting',
+ 'body' => [
+ 'id' => $url,
+ 'type' => $preferredType,
+ 'format' => $preferredRendering ?? '',
+ 'label' => ['en' => [$raw['label']]],
+ 'description' => $description,
],
- 'height' => $height,
- 'width' => $width,
+ 'target' => $canvasUrl,
+ 'thumbnail' => $this->getThumbnail($raw, $type),
],
- 'on' => $canvasUrl,
],
],
- ];
- } else {
- // Format as a generic download:
- $url = $this->getUri(
- 'files',
- ['type' => 'MASTER', 'id' => $raw['id']]
- );
- $description = isset($raw['sizebytes_str'])
- ? ($raw['sizebytes_str'] / 1024) . 'k'
- : '';
- $content = [
- 'height' => 600,
- 'width' => 800,
- 'content' => [
- [
- '@id' => $canvasUrl . '#content',
- '@type' => 'sc:AnnotationPage',
- 'items' => [
- [
- '@id' => $canvasUrl . '#item' . $i,
- '@type' => 'sc:Annotation',
- 'motivation' => 'painting',
- 'body' => [
- '@id' => $url,
- '@type' => 'sc:Document',
- 'format' => $raw['mimetype'] ?? '',
- 'label' => $raw['label'],
- 'description' => $description,
+ ],
+ ];
+
+ return [
+ 'type' => 'Canvas',
+ 'id' => $canvasUrl,
+ 'label' => ['en' => [$raw['label'] ]] ?? '-',
+ 'rendering' => $this->getSequenceRenderingData($outline, $list, $raw),
+ 'thumbnail' => $this->getThumbnail($raw, $type),
+ ] + $content;
+ }
+
+ /**
+ * Build JSON data for an image canvas.
+ *
+ * @param string $id Record ID
+ * @param int $i Position of canvas in overall array (used for canvas ID generation)
+ * @param array $raw Raw data to format into canvas
+ * @param string $type Type of list ('image' or 'audio')
+ * @param array $list List to check
+ * @param array $outline Outline data
+ *
+ * @return array
+ */
+ protected function getImageCanvas($id, $i, $raw, $type, $list, $outline)
+ {
+ $canvasUrl = $this->getUri(
+ 'vudl-record-canvas',
+ ['id' => $id, 'canvas' => 'p' . $i]
+ );
+
+ $imageServerBase = $this->config->Images->serverUrl ?? false;
+ if (!$imageServerBase) {
+ throw new \Exception('Must set image server base URL.');
+ }
+ [$width, $height, $imageUrl, $mimeType]
+ = $this->getImageDetailsForCanvas($raw, $imageServerBase);
+ $content = [
+ 'height' => $height,
+ 'width' => $width,
+ 'items' => [
+ [
+ 'id' => $this->getUri('record', ['id' => $id]),
+ 'type' => 'AnnotationPage',
+ 'items' => [
+ [
+ 'id' => $imageUrl,
+ 'type' => 'Annotation',
+ 'motivation' => 'painting',
+ 'body' => [
+ 'id' => $imageServerBase . urlencode($raw['id']),
+ 'type' => 'Image',
+ 'format' => $mimeType,
+ 'service' => [
+ [
+ 'id' => $imageServerBase . urlencode($raw['id']),
+ 'type' => 'ImageService3',
+ 'profile' => 'level1',
+ ],
],
- 'target' => $canvasUrl,
],
+ 'height' => $height,
+ 'width' => $width,
+ 'target' => $canvasUrl,
+ 'thumbnail' => $this->getThumbnail($raw, $type),
],
],
],
- ];
- }
+ ],
+ ];
+
return [
- '@type' => $canvasType,
- '@id' => $canvasUrl,
- 'label' => $raw['label'] ?? '-',
- 'rendering' => $this->getCanvasRenderingData($raw),
+ 'type' => 'Canvas',
+ 'id' => $canvasUrl,
+ 'label' => ['en' => [$raw['label'] ]] ?? '-',
+ 'rendering' => $this->getSequenceRenderingData($outline, $list, $raw),
+ 'thumbnail' => $this->getThumbnail($raw, $type),
] + $content;
}
/**
- * Build JSON data for a single canvas.
+ * Find and arrange thumbnail data for canvas.
*
- * @param string $id Record ID
- * @param int $i Position of canvas in overall array (used for canvas
- * ID generation)
* @param string $raw Raw data to format into canvas
* @param string $type Type of list ('image' or 'audio')
*
* @return array
*/
- protected function getSingleElement($id, $i, $raw, $type)
+ protected function getThumbnail($raw, $type)
{
if ($type == 'audio') {
- $elementType = 'dctypes:Sound';
+ $elementType = 'Sound';
$preferredRendering = 'audio/mp3';
} elseif ($type == 'video') {
$elementType = 'dctypes:MovingImage';
@@ -420,11 +468,11 @@ protected function getSingleElement($id, $i, $raw, $type)
}
}
$bestRendering = $foundMatch ? $i : 0;
- $id = $renderings[$bestRendering]['@id'] . '#element';
+ $id = $renderings[$bestRendering]['id'] . '#element';
$format = $renderings[$bestRendering]['format'];
- $extras = [];
+
if (in_array('THUMBNAIL', $raw['datastreams'])) {
- $extras['thumbnail'] = $this->getUri(
+ $getThumb = $this->getUri(
'files',
['type' => 'THUMBNAIL', 'id' => $raw['id']]
);
@@ -436,16 +484,17 @@ protected function getSingleElement($id, $i, $raw, $type)
} else {
$thumbFilename = 'default.png';
}
- $extras['thumbnail'] = $this->getUri('home')
+ $getThumb = $this->getUri('home')
. 'themes/vudiglib/images/vudl/' . $thumbFilename;
}
+
return [
- '@id' => $id,
- 'format' => $format,
- '@type' => $elementType,
- 'label' => $raw['label'] ?? '-',
- 'rendering' => $renderings,
- ] + $extras;
+ [
+ 'id' => $getThumb,
+ 'type' => 'Image',
+ 'format' => 'image/png',
+ ],
+ ];
}
/**
@@ -605,50 +654,6 @@ protected function getListForCanvas($outline)
return current($outline['lists']) ?: [];
}
- /**
- * Build JSON canvas data.
- *
- * @param string $id Record ID
- * @param array $list List data
- *
- * @return array
- */
- protected function getAllCanvasData($id, $list)
- {
- $retVal = [];
- foreach ($list as $i => $current) {
- $retVal[] = $this->getSingleCanvas(
- $id,
- $i,
- $current,
- $this->getListType($list)
- );
- }
- return $retVal;
- }
-
- /**
- * Build JSON element data.
- *
- * @param string $id Record ID
- * @param array $list List data
- *
- * @return array
- */
- protected function getAllElementData($id, $list)
- {
- $retVal = [];
- foreach ($list as $i => $current) {
- $retVal[] = $this->getSingleElement(
- $id,
- $i,
- $current,
- $this->getListType($list)
- );
- }
- return $retVal;
- }
-
/**
* Get the array representing a single rendering.
*
@@ -661,9 +666,10 @@ protected function getAllElementData($id, $list)
protected function getSingleRendering($url, $mime, $label = '')
{
return [
- '@id' => $url,
+ 'type' => 'rendering',
+ 'id' => $url,
'format' => $mime,
- 'label' => empty($label) ? "Download as {$mime}" : $label,
+ 'label' => ['en' => [empty($label) ? "Download as {$mime}" : $label]],
];
}
@@ -756,13 +762,13 @@ protected function getMasterRenderings($list)
*
* @param array $outline Outline data.
* @param array $canvasList List chosen as primary canvas list for manifest
+ * @param array $raw Raw data.
*
* @return array
*/
- protected function getSequenceRenderingData($outline, $canvasList)
+ protected function getSequenceRenderingData($outline, $canvasList, $raw)
{
$renderings = [];
- $hasMixedList = $hasImageList = false;
foreach ($outline['lists'] as $list) {
if ($this->isAudioList($list) && $this->isAudioList($canvasList)) {
$filtered = $this->filterAudioList($list);
@@ -771,7 +777,6 @@ protected function getSequenceRenderingData($outline, $canvasList)
$renderings,
$this->getMasterRenderings($filtered['other'])
);
- $hasMixedList = true;
}
} elseif ($this->isPdfList($list) && $this->isPdfList($canvasList)) {
$filtered = $this->filterPdfList($list);
@@ -780,34 +785,17 @@ protected function getSequenceRenderingData($outline, $canvasList)
$renderings,
$this->getMasterRenderings($filtered['other'])
);
- $hasMixedList = true;
}
} elseif (!$this->isImageList($list)) {
$renderings = array_merge(
$renderings,
$this->getMasterRenderings($list)
);
- } else {
- $hasImageList = true;
}
}
- // If we don't have an image list, we don't need alternate renderings:
- return ($hasImageList || $hasMixedList) ? $renderings : [];
- }
-
- /**
- * Get a string label for a list.
- *
- * @param array $list List
- *
- * @return string
- */
- protected function getLabelForList($list)
- {
- if ($this->isImageList($list)) {
- return 'Pages';
- }
- return 'Contents';
+ $canvasRenderings = $this->getCanvasRenderingData($raw);
+ $retVal = array_merge($canvasRenderings, $renderings);
+ return $retVal;
}
/**
@@ -825,18 +813,18 @@ protected function getPlaceholderCanvas($id)
);
$placeholderImage = 'http://digital.library.villanova.edu/placeholder.jpg';
return [
- '@type' => 'sc:Canvas',
- '@id' => $canvasUrl,
- 'label' => 'Placeholder image',
+ 'type' => 'Canvas',
+ 'id' => $canvasUrl,
+ 'label' => ['en' => ['Placeholder image']],
'height' => 600,
'width' => 600,
'images' => [
[
- '@type' => 'oa:Annotation',
- 'motivation' => 'sc:painting',
- 'resource' => [
- '@id' => $placeholderImage,
- '@type' => 'dcTypes:Image',
+ 'type' => 'AnnotationPage',
+ 'motivation' => 'painting',
+ 'items' => [
+ 'id' => $placeholderImage,
+ 'type' => 'dcTypes:Image',
'height' => 600,
'width' => 600,
],
@@ -860,67 +848,50 @@ protected function getPlaceholderSequence($id)
. 'for non-IIIF content (e.g., audio, video) and is unfortunately '
. 'incompatible with IIIF viewers.';
return [
- '@type' => 'sc:Sequence',
- 'label' => $label,
+ 'type' => 'item',
+ 'label' => ['en' => [$label]],
'compatibilityHint' => 'displayIfContentUnsupported',
'canvases' => [ $this->getPlaceholderCanvas($id) ],
];
}
/**
- * Build JSON sequence data.
+ * Build JSON items data.
*
* @param string $id Record ID
* @param array $outline Outline data
*
* @return array
*/
- protected function getSequenceData($id, $outline)
+ protected function getItems($id, $outline)
{
$list = $this->getListForCanvas($outline);
- $listType = $this->getListType($list);
- if ($listType === 'image') {
- $type = 'sc:Sequence';
- $sequenceKey = 'sequences';
- $extras = [
- 'viewingDirection' => 'left-to-right',
- 'viewingHint' => 'paged',
- 'canvases' => $this->getAllCanvasData($id, $list),
- ];
- } elseif ($listType !== 'unknown') {
- $type = 'ixif:MediaSequence';
- $sequenceKey = 'mediaSequences';
- $extras = [
- 'elements' => $this->getAllElementData($id, $list),
- ];
- } else {
- $type = 'sc:Sequence';
- $sequenceKey = 'sequences';
- $extras = [
- 'canvases' => $this->getAllCanvasData($id, $list),
- ];
- }
- $globalRenderings = $this->getSequenceRenderingData($outline, $list);
+ $type = $this->getListType($list);
- $retVal = [
- '@type' => $type,
- 'label' => $this->getLabelForList($list),
- ] + $extras;
-
- // Handle global renderings differently for image lists vs. IxIF lists:
- if ($this->isImageList($list)) {
- $retVal['rendering'] = $globalRenderings;
- } elseif (isset($retVal['elements'])) {
- foreach ($retVal['elements'] as $i => $element) {
- $retVal['elements'][$i]['rendering']
- = array_merge($element['rendering'], $globalRenderings);
+ $items = [];
+ foreach ($list as $i => $current) {
+ if ($type === 'image') {
+ $items[] = $this->getImageCanvas(
+ $id,
+ $i,
+ $current,
+ $type,
+ $list,
+ $outline
+ );
+ } else {
+ $items[] = $this->getNonImageCanvas(
+ $id,
+ $i,
+ $current,
+ $type,
+ $list,
+ $outline
+ );
}
}
- $finalArray = [ $sequenceKey => [ $retVal ] ];
- if ($sequenceKey != 'sequences') {
- $finalArray['sequences'] = $this->getPlaceholderSequence($id);
- }
- return $finalArray;
+
+ return $items;
}
/**
@@ -943,52 +914,6 @@ protected function getManifestContext($outline)
}
}
- /**
- * Format parent IDs into URIs for 'within' section.
- *
- * @param array $ids IDs to reformat
- *
- * @return array
- */
- protected function getParentData($ids)
- {
- $uris = [];
- foreach ($ids as $id) {
- $uris[] = $this->getUri('collection', ['id' => $id, 'tab' => 'IIIF']);
- }
- return count($uris) == 1 ? $uris[0] : $uris;
- }
-
- /**
- * Get data to build a IIIF canvas.
- *
- * @param string $id Record ID
- * @param int $canvas Canvas index to look up
- * @param array $outline Outline data
- *
- * @return array
- */
- public function getCanvasData($id, $canvas, $outline)
- {
- $base = ['@context' => self::IIIF_CONTEXT];
-
- // Special case: placeholder canvas:
- if ($canvas === 'Placeholder') {
- return $base + $this->getPlaceholderCanvas($id);
- }
-
- // Standard case:
- $list = $this->getListForCanvas($outline);
- return isset($list[$canvas])
- ? $base + $this->getSingleCanvas(
- $id,
- $canvas,
- $list[$canvas],
- $this->getListType($list)
- )
- : [];
- }
-
/**
* Get "related link" information pointing to record view page.
*
@@ -999,8 +924,10 @@ public function getCanvasData($id, $canvas, $outline)
protected function getRelated($id)
{
return [
- '@id' => $this->getUri('vudl-record', compact('id')),
+ 'id' => $this->getUri('vudl-record', compact('id')),
+ 'type' => 'Text',
'format' => 'text/html',
+ 'label' => ['en' => ['More Details']],
];
}
@@ -1081,14 +1008,15 @@ protected function getRequiredStatement($license)
? ''
: htmlspecialchars($licenseData['text']);
- return [
- 'label' => 'ATTRIBUTION',
- 'value' => 'Digital Library@Villanova University'
+ $value = 'Digital Library@Villanova University'
. '
Disclaimers:
'
. $this->getDisclaimers() . '
'
. 'License:
'
. '' . $linkContent . ''
- . '',
+ . '';
+ return [
+ 'label' => ['en' => ['ATTRIBUTION']],
+ 'value' => ['en' => [$value]],
];
}
@@ -1108,21 +1036,27 @@ public function getManifestData($id, $outline, $parents = [])
[$license] = $this->connector->getCopyright($id, $this->getLicenses());
return [
'@context' => $this->getManifestContext($outline),
- '@type' => 'sc:Manifest',
- '@id' => $uri,
-
- 'label' => $details['title']['value'] ?? 'Untitled',
+ 'type' => 'Manifest',
+ 'id' => $uri,
+ 'label' => [
+ 'en' => [
+ $details['title']['value'] ?? 'Untitled',
+ ],
+ ],
'metadata' => $this->extractManifestMetadata($id, $details),
- 'description' => isset($details['description']['value'])
+ 'summary' => ['en' => [
+ isset($details['description']['value'])
? '
' . str_replace( ['
| =$data['label'] ?> | -=$data['value'] ?> | -
|---|---|
| =$data['label']['en'][0] ?> | +=$data['value']['en'][0] ?> | +