From 434ce7f04cd55411e2ec3fe0c66b727edc7882ed Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Thu, 22 Aug 2019 22:36:23 -0500 Subject: [PATCH 1/7] Add core image server settings Fix update hook, change imageserver filename --- includes/imageserver.inc | 260 +++++++++++++++++++++++++++++++++++++++ islandora.install | 70 +++++++++++ islandora.module | 98 +++++++++++++++ 3 files changed, 428 insertions(+) create mode 100644 includes/imageserver.inc diff --git a/includes/imageserver.inc b/includes/imageserver.inc new file mode 100644 index 000000000..6f4004884 --- /dev/null +++ b/includes/imageserver.inc @@ -0,0 +1,260 @@ + array( + '#type' => 'select', + '#title' => t('Image Server'), + '#description' => t('Select the image server to configure, used by the Paged Content, OpenSeadragon, & Internet Archive Bookreader modules.'), + '#default_value' => $settings['type'], + '#options' => array( + 'none' => t('No image server configured'), + 'iiif' => t('IIIF image server'), + 'djatoka' => t('Adore-Djatoka image server'), + ), + ), + 'url' => array( + '#prefix' => '
', + '#suffix' => '
', + '#type' => 'textfield', + '#title' => t('Image Server Base URL'), + '#title_display' => 'invisible', + '#default_value' => $settings['url'], + '#description' => t('The location of the image server.
!confirmation_message', array( + '!confirmation_message' => islandora_imageserver_admin_form_access_message($form_state), + )), + '#ajax' => array( + 'callback' => 'islandora_imageserver_admin_ajax_url', + 'wrapper' => 'islandora-imageserver-path-wrapper', + ), + ), + 'iiif' => array( + '#type' => 'fieldset', + '#title' => t('IIIF Image Server Settings'), + '#description' => t('Settings for IIIF Image Server'), + '#states' => array( + 'visible' => array( + ':input[name="type"]' => array('value' => 'iiif'), + ), + ), + 'iiif_token_header' => array( + '#type' => 'checkbox', + '#title' => t('Add token as header'), + '#default_value' => $settings['iiif_token_header'], + '#description' => t('Instead of sending the token as a query parameter, it will be sent in the X-ISLANDORA-TOKEN header.'), + ), + 'iiif_identifier' => array( + '#type' => 'textfield', + '#title' => t('IIIF Identifier'), + '#default_value' => $settings['iiif_identifier'], + '#element_validate' => array('token_element_validate'), + '#token_types' => array('islandora'), + ), + 'islandora_imageserver_iiif_token_tree' => array( + '#type' => 'fieldset', + '#title' => t('Replacement patterns'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#description' => theme('token_tree', array( + 'token_types' => array('islandora'), + 'global_types' => FALSE, + )), + ), + ), + 'actions' => array( + '#type' => 'actions', + 'save' => array( + '#type' => 'submit', + '#value' => t('Save configuration'), + '#weight' => 0, + ), + 'reset' => array( + '#type' => 'submit', + '#value' => t('Reset to defaults'), + '#weight' => 1, + '#submit' => array('islandora_imageserver_admin_submit_reset'), + ), + ), + ); + return $form; +} + +/** + * Delete configured settings, returning us to default settings. + */ +function islandora_imageserver_admin_submit_reset() { + variable_del('islandora_imageserver_settings'); + drupal_set_message('Settings reset.', 'status'); +} + + +/** + * Implements hook_form_submit(). + */ +function islandora_imageserver_admin_form_submit(array $form, array &$form_state) { + $type = $form_state['values']['type']; + if ($type == 'none') { + variable_del('islandora_imageserver_settings'); + } + else { + $settings = islandora_imageserver_get_settings(); + $settings['type'] = $type; + $settings['url'] = rtrim($form_state['values']['url'], '/'); + if ($type == 'iiif') { + $settings['iiif_token_header'] = (bool) $form_state['values']['iiif_token_header']; + $settings['iiif_identifier'] = $form_state['values']['iiif_identifier']; + } + else { + $settings['iiif_token_header'] = FALSE; + $settings['iiif_identifier'] = ISLANDORA_IMAGESERVER_DEFAULT_TOKEN; + } + variable_set('islandora_imageserver_settings', $settings); + } + drupal_set_message("Settings saved successfully.", 'status'); +} + +/** + * Callback to check URL. + * + * @param array $form + * Drupal form. + * @param array $form_state + * Drupal form state. + * + * @return mixed + * The form element. + */ +function islandora_imageserver_admin_ajax_url(array $form, array $form_state) { + return $form['url']; +} + +/** + * Gets a message which describes if Adore-Djatoka is accessible. + * + * @param array $settings + * The image server settings. + * + * @see islandora_imageserver_get_settings(). + * + * @return string + * A message describing the accessibility of the Adore-Djatoka image resolver. + */ +function islandora_imageserver_admin_form_access_message(array &$form_state) { + $confirmation_message = ''; + + $type = islandora_imageserver_get_default_value($form_state, 'type'); + $url = islandora_imageserver_get_default_value($form_state, 'url'); + + if ($type == 'djatoka') { + $url = url("{$url}", array( + 'absolute' => TRUE, + 'query' => array( + 'url_ver' => 'Z39.88-2004', + 'rft_id' => 'http://memory.loc.gov/gmd/gmd433/g4330/g4330/np000066.jp2', + 'svc_id' => 'info:lanl-repo/svc/getRegion', + 'svc_val_fmt' => 'info:ofi/fmt:kev:mtx:jpeg2000', + 'svc.format' => 'image/jpeg', + 'svc.level' => '1', + ), + )); + } + elseif ($type == 'iiif') { + $url = url(rtrim($url, '/') + , array( + 'absolute' => TRUE, + ) + ); + } + + if (isset($url) && !empty($url)) { + $result = drupal_http_request($url); + if ($result->code == 200) { + $confirmation_message = theme_image(array( + 'path' => 'misc/watchdog-ok.png', + 'attributes' => array() + )); + $confirmation_message .= t('Successfully connected to image server.'); + } + else { + $confirmation_message = theme_image(array( + 'path' => 'misc/watchdog-error.png', + 'attributes' => array() + )); + $confirmation_message .= t('Unable to connect to image server at !path', array( + '!path' => $url, + )); + } + } + return $confirmation_message; +} + +/** + * Get image server settings. + * + * @return array + * Configuration to access the image server. + */ +function islandora_imageserver_get_settings() { + $defaults = array( + 'type' => 'none', + 'url' => '', + 'iiif_token_header' => FALSE, + 'iiif_identifier' => ISLANDORA_IMAGESERVER_DEFAULT_TOKEN, + ); + + $settings = variable_get('islandora_imageserver_settings', array()) + $defaults; + + return $settings; +} + +/** + * Utility to check form_state or return the default. + * + * @param array $form_state + * Drupal form state. + * @param $name + * Name of the form element/settings key. + * @return mixed + * The Form value or currently saved value. + */ +function islandora_imageserver_get_default_value(array &$form_state, $name) { + $settings = islandora_imageserver_get_settings(); + return isset($form_state['values'][$name]) ? $form_state['values'][$name] : $settings[$name]; +} + +/** + * Generate a replacement string using tokens. + * + * @param string $string_token + * The replacement token to generate. + * @param string $pid + * The pid of the object. + * @param string $dsid + * The dsid to return. + * @param string $authtoken + * The authentication token. + * @return mixed + * The token replaced string. + */ +function islandora_imageserver_get_identifier($string_token, $pid, $dsid, $authtoken) { + $settings = islandora_imageserver_get_settings(); + if ($settings['type'] == 'djatoka') { + // We use the token_replace to generate the rft_id. + $string_token = '[islandora:url_token]'; + } + $parts = array( + 'islandora' => array( + 'pid' => $pid, + 'dsid' => $dsid, + 'token' => $authtoken, + ), + ); + return token_replace($string_token, $parts); +} diff --git a/islandora.install b/islandora.install index cc0cc49fc..9d89bae86 100644 --- a/islandora.install +++ b/islandora.install @@ -61,6 +61,7 @@ function islandora_uninstall() { 'islandora_breadcrumbs_backends', 'islandora_render_context_ingeststep', 'islandora_deny_inactive_and_deleted', + 'islandora_imageserver_settings', ); array_walk($variables, 'variable_del'); } @@ -144,3 +145,72 @@ function islandora_update_7002() { // Removing as the deprecation has been removed. variable_del('islandora_deprecation_return_false_when_datastream_exists'); } + +/** + * Implements hook_update_N(). + * + * Try to auto-configure the image server settings in core based on + * the Internet Archive Bookreader and/or Openseadragon settings. + */ +function islandora_update_7003() { + module_load_include('inc', 'islandora', 'includes/imageserver'); + if (islandora_imageserver_get_settings()['type'] != 'none') { + return t('Settings have already been configured manually.'); + } + if (module_exists('islandora_openseadragon')) { + $openseadragon_settings = array( + 'type' => variable_get('islandora_openseadragon_tilesource', 'djatoka'), + ); + if ($openseadragon_settings['type'] == 'djatoka') { + $openseadragon_settings['url'] = variable_get('islandora_openseadragon_djatoka_url', 'adore-djatoka/resolver'); + } + else { + $openseadragon_settings['url'] = variable_get('islandora_openseadragon_iiif_url', 'iiif'); + $openseadragon_settings['iiif_token_header'] = variable_get('islandora_openseadragon_iiif_token_header', FALSE); + $openseadragon_settings['iiif_identifier'] = explode(":", variable_get('islandora_openseadragon_iiif_identifier', '[islandora_openseadragon:url_token]'))[1]; + } + } + if (module_exists('islandora_internet_archive_bookreader')) { + $iabv_settings = array( + 'type' => variable_get('islandora_internet_archive_bookreader_pagesource', 'djatoka'), + ); + if ($iabv_settings['type'] == 'djatoka') { + $iabv_settings['url'] = variable_get('islandora_paged_content_djatoka_url', 'http://localhost:8080/adore-djatoka'); + } + else { + $iabv_settings['url'] = variable_get('islandora_internet_archive_bookreader_iiif_url', 'iiif'); + $iabv_settings['iiif_token_header'] = variable_get('islandora_internet_archive_bookreader_iiif_token_header', FALSE); + $iabv_settings['iiif_identifier'] = explode(":", variable_get('islandora_internet_archive_bookreader_iiif_identifier', '[islandora_iareader:url_token]'))[1]; + } + } + if (isset($openseadragon_settings) && isset($iabv_settings)) { + if (count(array_diff($openseadragon_settings, $iabv_settings)) == 0) { + // Settings are the same, use for core imageserver variables. + $new_settings = $openseadragon_settings; + } + else { + // We could not migrate your settings to the new place. This stops the other + // two modules from deleting your settings. + throw new DrupalUpdateException('Islandora image server settings could NOT be configured automatically, please set them manually at Admin -> Islandora -> Image Server configuration and then run updates again.'); + } + } + elseif (isset($openseadragon_settings)) { + $new_settings = $openseadragon_settings; + } + elseif (isset($iabv_settings)) { + $new_settings = $iabv_settings; + } + if (isset($new_settings)) { + if (isset($new_settings['iiif_identifer']) && !empty($new_settings['iiif_identifer'])) { + // This will only have the back half of the token, prepend islandora to it. + $new_settings['iiif_identifer'] = "[islandora:" + $new_settings['iiif_identifer']; + } + if ($new_settings['type'] == 'djatoka' && !preg_match('~resolver$~', $new_settings['url'])) { + // IABV javascript added resolver to URL, Openseadragon did not. + $new_settings['url'] = rtrim($new_settings['url'], '/') . '/resolver'; + } + // We have migrated your settings to the new place. + variable_set('islandora_imageserver_settings', $new_settings); + return t("Islandora image server settings configured automatically."); + } +} diff --git a/islandora.module b/islandora.module index 3e53ebac0..a7f8347be 100644 --- a/islandora.module +++ b/islandora.module @@ -72,6 +72,8 @@ define('ISLANDORA_MIME_TYPES_AUTOCOMPLETE', 'islandora/autocomplete/mime-types') const ISLANDORA_BREADCRUMB_LEGACY_BACKEND = 'islandora_breadcrumbs_legacy_sparql'; +const ISLANDORA_IMAGESERVER_DEFAULT_TOKEN = "[islandora:url_token]"; + /** * Implements hook_menu(). * @@ -417,6 +419,15 @@ function islandora_menu() { 'type' => MENU_SUGGESTED_ITEM, 'access arguments' => array(ISLANDORA_MANAGE_DELETED_OBJECTS), ); + $items['admin/islandora/image_server'] = array( + 'title' => 'Image server configuration', + 'description' => 'Define the settings for your local image server', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('islandora_imageserver_admin_form'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_NORMAL_ITEM, + 'file' => 'includes/imageserver.inc', + ); return $items; } @@ -2230,3 +2241,90 @@ function islandora_islandora_solution_pack_child_relationships($cmodels) { // exist when the hook is called, even if no module responds. return array('predicate' => array(), 'prefix' => array()); } + +/** + * Implements hook_token_info(). + */ +function islandora_token_info() { + $info = array(); + + $info['types']['islandora'] = array( + 'name' => t('Islandora'), + 'description' => t('Tokens for building IIIF identifer in Islandora.'), + 'needs-data' => 'islandora', + ); + + $info['tokens']['islandora']['pid'] = array( + 'name' => t('PID'), + 'description' => t('The objects PID.'), + ); + + $info['tokens']['islandora']['dsid'] = array( + 'name' => t('DSID'), + 'description' => t('The objects DSID.'), + ); + + $info['tokens']['islandora']['url'] = array( + 'name' => t('URL'), + 'description' => t('The URL to the object in Islandora.'), + ); + + $info['tokens']['islandora']['url_token'] = array( + 'name' => t('URL with Token'), + 'description' => t('The URL to the object in Islandora with token in the query string.'), + ); + + $info['tokens']['islandora']['token'] = array( + 'name' => t('Token'), + 'description' => t('The token that can be used to access the object in Islandora.'), + ); + + return $info; +} + +/** + * Implements hook_tokens(). + */ +function islandora_tokens($type, $tokens, array $data = array(), array $options = array()) { + $replacements = array(); + + if ($type != 'islandora' || !isset($data['islandora'])) { + return $replacements; + } + + $pid = $data['islandora']['pid']; + $dsid = $data['islandora']['dsid']; + $token = $data['islandora']['token']; + + foreach ($tokens as $name => $original) { + if ($name == 'pid') { + $replacements[$original] = $pid; + } + elseif ($name == 'dsid') { + $replacements[$original] = $dsid; + } + elseif ($name == 'token') { + $replacements[$original] = $token; + } + elseif ($name == 'url' || $name == 'url_token') { + $options = array( + 'absolute' => TRUE, + 'language' => language_default(), + 'https' => (function_exists('drupal_is_https') ? + drupal_is_https() : + (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') + ), + ); + + if ($name == 'url_token') { + $options['query'] = array( + 'token' => $token, + ); + } + + $replacements[$original] = url("islandora/object/{$pid}/datastream/{$dsid}/view", $options); + } + } + + return $replacements; +} From df8edb465eab47189dc6cdfdf471e2aa7dd84fdf Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Sun, 25 Aug 2019 21:55:46 -0500 Subject: [PATCH 2/7] Coder --- README.md | 42 ++++++++++++++++++++++++- includes/dublin_core.inc | 11 +++++++ includes/imageserver.inc | 37 +++++++++++++++------- includes/mime_detect.inc | 12 ++++++++ includes/tuque_wrapper.inc | 60 ++++++++++++++++++++++++++++++++++++ includes/utilities.inc | 12 ++++---- islandora.install | 8 ++--- tests/includes/utilities.inc | 20 ++++++++++++ 8 files changed, 180 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 28908c694..7397d91be 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,47 @@ By default, objects with the [Fedora state](https://wiki.duraspace.org/display/F * A [detailed tutorial](https://github.com/Islandora/islandora/wiki/Multi-paged-Ingest-Forms) on extending the multi-page ingest forms is available on the Github (developers') Wiki. * Additional modules developed by members of the Islandora community to extend Islandora can be found on the curated [Islandora Awesome](https://github.com/Islandora-Labs/islandora_awesome) list. -## Documentation +### Image Server configuration + + +#### Drupal + +In Administration ยป Islandora ยป Image Server configuration + +Choose the type of image server (Djatoka or IIIF). + +Set the URL. + +#### Djatoka + +![Configuration](https://user-images.githubusercontent.com/2857697/63660444-1a24c400-c77c-11e9-831d-5f3fc71b085e.png) + +#### IIIF + +![Configuration](https://user-images.githubusercontent.com/2857697/63660476-43455480-c77c-11e9-8460-c3d2639e7575.png) + +If using IIIF choose to send token as a header and choose the token to use. + +Any [IIIF](http://iiif.io) image server can be used the the IIIF tile source. The IIIF tile source provides a full URL to the datastream to be displayed as the IIIF `identifier`. The IIIF server needs to be configured to resolve this full URL to retrieve the image. + +The [Cantaloupe ๐Ÿˆ](https://medusa-project.github.io/cantaloupe/) IIIF image server can be configured to resolve these identifiers using the [`HttpResolver`](https://medusa-project.github.io/cantaloupe/manual/3.3/resolvers.html#HttpResolver) with no prefix specified. + +#### Apache Reverse Proxy + +Reverse proxy config: We make the assumption that we (reverse) proxy Djatoka, to fix the same-origin issue. + +For Apache, with Drupal running on the same box as Apache, a couple lines like: + +``` +ProxyPass /adore-djatoka http://localhost:8080/adore-djatoka +ProxyPassReverse /adore-djatoka http://localhost:8080/adore-djatoka +``` + +in the Apache config somewhere (either the main apache.conf, httpd.conf, or in and arbitrarily named `*.conf` in your Apache's conf.d directory should suffice to establish the reverse proxy. + +In Debian derived systems one will need to create location entries for each proxy or remove the Deny from All in mod_proxy's conf file. + +# Documentation Further documentation for this module is available at [our documentation wiki](https://wiki.duraspace.org/display/ISLANDORA/Islandora+Core+Module). diff --git a/includes/dublin_core.inc b/includes/dublin_core.inc index cff1bebed..924d97067 100644 --- a/includes/dublin_core.inc +++ b/includes/dublin_core.inc @@ -13,6 +13,11 @@ */ class DublinCore { + /** + * Dublin Core fields. + * + * @var array|\DublinCore + */ public $dc = array( 'dc:title' => array(), 'dc:creator' => array(), @@ -30,6 +35,12 @@ class DublinCore { 'dc:coverage' => array(), 'dc:rights' => array(), ); + + /** + * Owner name. + * + * @var string + */ public $owner; /** diff --git a/includes/imageserver.inc b/includes/imageserver.inc index 6f4004884..251001b04 100644 --- a/includes/imageserver.inc +++ b/includes/imageserver.inc @@ -1,9 +1,23 @@ TRUE, ) ); @@ -178,14 +191,14 @@ function islandora_imageserver_admin_form_access_message(array &$form_state) { if ($result->code == 200) { $confirmation_message = theme_image(array( 'path' => 'misc/watchdog-ok.png', - 'attributes' => array() + 'attributes' => array(), )); $confirmation_message .= t('Successfully connected to image server.'); } else { $confirmation_message = theme_image(array( 'path' => 'misc/watchdog-error.png', - 'attributes' => array() + 'attributes' => array(), )); $confirmation_message .= t('Unable to connect to image server at !path', array( '!path' => $url, @@ -219,8 +232,9 @@ function islandora_imageserver_get_settings() { * * @param array $form_state * Drupal form state. - * @param $name + * @param string $name * Name of the form element/settings key. + * * @return mixed * The Form value or currently saved value. */ @@ -240,6 +254,7 @@ function islandora_imageserver_get_default_value(array &$form_state, $name) { * The dsid to return. * @param string $authtoken * The authentication token. + * * @return mixed * The token replaced string. */ diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc index 818e150be..289715fb9 100644 --- a/includes/mime_detect.inc +++ b/includes/mime_detect.inc @@ -59,7 +59,19 @@ class MimeDetect { * $this->get_extension('image/jpeg') will always return 'jpg'. */ protected $protectedMimeTypes = array(); + /** + * Protected file extensions. + * + * @var array + */ protected $protectedFileExtensions; + /** + * Extension exceptions. + * + * @deprecated + * + * @var array + */ protected $extensionExceptions = array( // XXX: Deprecated... Only here due to old 'tif' => 'image/tif' mapping... // The correct MIMEtype is 'image/tiff'. diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc index 3b08a9fda..43eb54cbb 100644 --- a/includes/tuque_wrapper.inc +++ b/includes/tuque_wrapper.inc @@ -80,8 +80,20 @@ function islandora_invoke_datastream_hooks($hook, array $models, $dsid) { * Implementation of the FedoraRepository class. */ class IslandoraFedoraRepository extends FedoraRepository { + /** + * Class name. + * @var string + */ protected $queryClass = 'IslandoraRepositoryQuery'; + /** + * Class name. + * @var string + */ protected $newObjectClass = 'IslandoraNewFedoraObject'; + /** + * Class name. + * @var string + */ protected $objectClass = 'IslandoraFedoraObject'; /** @@ -179,8 +191,20 @@ class IslandoraRepositoryQuery extends RepositoryQuery {} * Implementation of NewFedoraObject class. */ class IslandoraNewFedoraObject extends NewFedoraObject { + /** + * Class name. + * @var string + */ protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream'; + /** + * Class name. + * @var string + */ protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream'; + /** + * Class name. + * @var string + */ protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt'; } @@ -188,8 +212,20 @@ class IslandoraNewFedoraObject extends NewFedoraObject { * Implementation, magic functions for a FedoraObject class. */ class IslandoraFedoraObject extends FedoraObject { + /** + * Class name. + * @var string + */ protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream'; + /** + * Class name. + * @var string + */ protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream'; + /** + * Class name. + * @var string + */ protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt'; /** @@ -568,7 +604,15 @@ class IslandoraSimpleCache extends SimpleCache {} * Implementation of NewFedoraDatastream class. */ class IslandoraNewFedoraDatastream extends NewFedoraDatastream { + /** + * Class name. + * @var string + */ protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; + /** + * Class name. + * @var string + */ protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; } @@ -576,7 +620,15 @@ class IslandoraNewFedoraDatastream extends NewFedoraDatastream { * Implementation and magic functions for FedoraDatastream class. */ class IslandoraFedoraDatastream extends FedoraDatastream { + /** + * Class name. + * @var string + */ protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; + /** + * Class name. + * @var string + */ protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; /** @@ -650,7 +702,15 @@ class IslandoraFedoraDatastream extends FedoraDatastream { * Implementation of FedoraDatastreamVersion class. */ class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion { + /** + * Class name. + * @var string + */ protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; + /** + * Class name. + * @var string + */ protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; } diff --git a/includes/utilities.inc b/includes/utilities.inc index b14053304..10ac2d1f3 100644 --- a/includes/utilities.inc +++ b/includes/utilities.inc @@ -267,9 +267,9 @@ function islandora_escape_pid_for_function($pid) { * below are fine. * * @code - * 'islandora', - * 'islandora:', - * 'islandora:1234', + * 'islandora', + * 'islandora:', + * 'islandora:1234', * @endcode * * @return string @@ -291,9 +291,9 @@ function islandora_get_namespace($id) { * below are fine. * * @code - * 'islandora', - * 'islandora:', - * 'islandora:1234', + * 'islandora', + * 'islandora:', + * 'islandora:1234', * @endcode * * @return bool diff --git a/islandora.install b/islandora.install index 9d89bae86..db01f1a52 100644 --- a/islandora.install +++ b/islandora.install @@ -189,8 +189,8 @@ function islandora_update_7003() { $new_settings = $openseadragon_settings; } else { - // We could not migrate your settings to the new place. This stops the other - // two modules from deleting your settings. + // We could not migrate your settings to the new place. This stops the + // other two modules from deleting your settings. throw new DrupalUpdateException('Islandora image server settings could NOT be configured automatically, please set them manually at Admin -> Islandora -> Image Server configuration and then run updates again.'); } } @@ -202,8 +202,8 @@ function islandora_update_7003() { } if (isset($new_settings)) { if (isset($new_settings['iiif_identifer']) && !empty($new_settings['iiif_identifer'])) { - // This will only have the back half of the token, prepend islandora to it. - $new_settings['iiif_identifer'] = "[islandora:" + $new_settings['iiif_identifer']; + // This will only have the back half of the token, prepend islandora. + $new_settings['iiif_identifer'] = "[islandora:" . $new_settings['iiif_identifer']; } if ($new_settings['type'] == 'djatoka' && !preg_match('~resolver$~', $new_settings['url'])) { // IABV javascript added resolver to URL, Openseadragon did not. diff --git a/tests/includes/utilities.inc b/tests/includes/utilities.inc index 2549d21b5..c90291390 100644 --- a/tests/includes/utilities.inc +++ b/tests/includes/utilities.inc @@ -19,12 +19,32 @@ */ class IslandoraTestUtilities extends IslandoraTestUtilityClass { + /** + * The test configuration. + * + * @var array + */ protected $configuration; + /** + * The parameters. + * + * @var array + */ protected $params; + /** + * Test results. + * + * @var array + */ public $results = array(); + /** + * A repository object. + * + * @var \FedoraRepository + */ protected $repository; /** From 937ca980e2cdce2c8fd2f80aa830de4c76ccd5c5 Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Mon, 26 Aug 2019 08:26:24 -0500 Subject: [PATCH 3/7] More coder --- includes/imageserver.inc | 1 + includes/mime_detect.inc | 2 -- includes/tuque_wrapper.inc | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/includes/imageserver.inc b/includes/imageserver.inc index 251001b04..7f831a2bd 100644 --- a/includes/imageserver.inc +++ b/includes/imageserver.inc @@ -15,6 +15,7 @@ * * @return array * Drupal form. + * * @throws \Exception * Thrown by theme() function. */ diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc index 289715fb9..9baedbc2a 100644 --- a/includes/mime_detect.inc +++ b/includes/mime_detect.inc @@ -68,8 +68,6 @@ class MimeDetect { /** * Extension exceptions. * - * @deprecated - * * @var array */ protected $extensionExceptions = array( diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc index 43eb54cbb..285cecfa9 100644 --- a/includes/tuque_wrapper.inc +++ b/includes/tuque_wrapper.inc @@ -82,16 +82,19 @@ function islandora_invoke_datastream_hooks($hook, array $models, $dsid) { class IslandoraFedoraRepository extends FedoraRepository { /** * Class name. + * * @var string */ protected $queryClass = 'IslandoraRepositoryQuery'; /** * Class name. + * * @var string */ protected $newObjectClass = 'IslandoraNewFedoraObject'; /** * Class name. + * * @var string */ protected $objectClass = 'IslandoraFedoraObject'; @@ -193,16 +196,19 @@ class IslandoraRepositoryQuery extends RepositoryQuery {} class IslandoraNewFedoraObject extends NewFedoraObject { /** * Class name. + * * @var string */ protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream'; /** * Class name. + * * @var string */ protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream'; /** * Class name. + * * @var string */ protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt'; @@ -214,16 +220,19 @@ class IslandoraNewFedoraObject extends NewFedoraObject { class IslandoraFedoraObject extends FedoraObject { /** * Class name. + * * @var string */ protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream'; /** * Class name. + * * @var string */ protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream'; /** * Class name. + * * @var string */ protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt'; @@ -606,11 +615,13 @@ class IslandoraSimpleCache extends SimpleCache {} class IslandoraNewFedoraDatastream extends NewFedoraDatastream { /** * Class name. + * * @var string */ protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; /** * Class name. + * * @var string */ protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; @@ -622,11 +633,13 @@ class IslandoraNewFedoraDatastream extends NewFedoraDatastream { class IslandoraFedoraDatastream extends FedoraDatastream { /** * Class name. + * * @var string */ protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; /** * Class name. + * * @var string */ protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; @@ -704,11 +717,13 @@ class IslandoraFedoraDatastream extends FedoraDatastream { class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion { /** * Class name. + * * @var string */ protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; /** * Class name. + * * @var string */ protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; From c815bd674ec832791223f88bb017c963c38e6382 Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Wed, 28 Aug 2019 10:51:18 -0500 Subject: [PATCH 4/7] Re-usable selectbox, reset confirmation, store none type --- README.md | 2 +- includes/imageserver.inc | 109 ++++++++++++++++++++++++++++++--------- islandora.install | 4 +- islandora.module | 9 ++++ 4 files changed, 96 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7397d91be..ed2716ef3 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Set the URL. If using IIIF choose to send token as a header and choose the token to use. -Any [IIIF](http://iiif.io) image server can be used the the IIIF tile source. The IIIF tile source provides a full URL to the datastream to be displayed as the IIIF `identifier`. The IIIF server needs to be configured to resolve this full URL to retrieve the image. +Any [IIIF](http://iiif.io) image server can be used the the IIIF tile source. The IIIF tile source provides an templated identifier which the IIIF server must be configured to resolve. This could be the full URL to the datastream to be displayed or something more complex. The IIIF server needs to be configured to resolve this full URL to retrieve the image. The [Cantaloupe ๐Ÿˆ](https://medusa-project.github.io/cantaloupe/) IIIF image server can be configured to resolve these identifiers using the [`HttpResolver`](https://medusa-project.github.io/cantaloupe/manual/3.3/resolvers.html#HttpResolver) with no prefix specified. diff --git a/includes/imageserver.inc b/includes/imageserver.inc index 7f831a2bd..f907487fc 100644 --- a/includes/imageserver.inc +++ b/includes/imageserver.inc @@ -24,17 +24,7 @@ function islandora_imageserver_admin_form(array $form, array &$form_state) { $settings = islandora_imageserver_get_settings(); $form = array( - 'type' => array( - '#type' => 'select', - '#title' => t('Image Server'), - '#description' => t('Select the image server to configure, used by the Paged Content, OpenSeadragon, & Internet Archive Bookreader modules.'), - '#default_value' => $settings['type'], - '#options' => array( - 'none' => t('No image server configured'), - 'iiif' => t('IIIF image server'), - 'djatoka' => t('Adore-Djatoka image server'), - ), - ), + 'type' => islandora_imageserver_get_type_selectbox(FALSE), 'url' => array( '#prefix' => '
', '#suffix' => '
', @@ -89,12 +79,13 @@ function islandora_imageserver_admin_form(array $form, array &$form_state) { '#type' => 'submit', '#value' => t('Save configuration'), '#weight' => 0, + '#name' => 'save_config', ), 'reset' => array( '#type' => 'submit', '#value' => t('Reset to defaults'), '#weight' => 1, - '#submit' => array('islandora_imageserver_admin_submit_reset'), + '#name' => 'reset_config', ), ), ); @@ -102,22 +93,50 @@ function islandora_imageserver_admin_form(array $form, array &$form_state) { } /** - * Delete configured settings, returning us to default settings. + * Settings reset confirmation form. + * + * @param array $form + * The Drupal form. + * @param array $form_state + * The Drupal $form_state. + * + * @return mixed + * The created form. + */ +function islandora_imageserver_admin_reset_confirm_form(array $form, array &$form_state) { + $form = array( + 'reset_confirm' => array( + '#type' => 'hidden', + '#value' => 1, + ), + ); + return confirm_form( + $form, + t("Do you really want to reset the Image Server settings?"), + 'admin/islandora/image_server', + t("This action cannot be undone."), + t("Reset") + ); +} + +/** + * Implements hook_form_submit(). */ -function islandora_imageserver_admin_submit_reset() { - variable_del('islandora_imageserver_settings'); +function islandora_imageserver_admin_reset_confirm_form_submit(array $form, array &$form_state) { + variable_set('islandora_imageserver_settings', islandora_imageserver_get_default_settings()); drupal_set_message(t('Settings reset.'), 'status'); + drupal_goto('admin/islandora/image_server'); } /** * Implements hook_form_submit(). */ function islandora_imageserver_admin_form_submit(array $form, array &$form_state) { - $type = $form_state['values']['type']; - if ($type == 'none') { - variable_del('islandora_imageserver_settings'); + if (isset($form_state['triggering_element']) && $form_state['triggering_element']['#name'] == 'reset_config') { + drupal_goto('admin/islandora/image_server/reset'); } else { + $type = $form_state['values']['type']; $settings = islandora_imageserver_get_settings(); $settings['type'] = $type; $settings['url'] = rtrim($form_state['values']['url'], '/'); @@ -130,8 +149,8 @@ function islandora_imageserver_admin_form_submit(array $form, array &$form_state $settings['iiif_identifier'] = ISLANDORA_IMAGESERVER_DEFAULT_TOKEN; } variable_set('islandora_imageserver_settings', $settings); + drupal_set_message(t("Settings saved successfully."), 'status'); } - drupal_set_message(t("Settings saved successfully."), 'status'); } /** @@ -167,7 +186,7 @@ function islandora_imageserver_admin_form_access_message(array &$form_state) { $url = islandora_imageserver_get_default_value($form_state, 'url'); if ($type == 'djatoka') { - $url = url("{$url}", array( + $url = url($url, array( 'absolute' => TRUE, 'query' => array( 'url_ver' => 'Z39.88-2004', @@ -186,6 +205,10 @@ function islandora_imageserver_admin_form_access_message(array &$form_state) { ) ); } + else { + // None, so don't confirm. + return ""; + } if (isset($url) && !empty($url)) { $result = drupal_http_request($url); @@ -216,16 +239,26 @@ function islandora_imageserver_admin_form_access_message(array &$form_state) { * Configuration to access the image server. */ function islandora_imageserver_get_settings() { - $defaults = array( + $defaults = islandora_imageserver_get_default_settings(); + + $settings = variable_get('islandora_imageserver_settings', array()) + $defaults; + + return $settings; +} + +/** + * Return the default image server settings. + * + * @return array + * The settings. + */ +function islandora_imageserver_get_default_settings() { + return array( 'type' => 'none', 'url' => '', 'iiif_token_header' => FALSE, 'iiif_identifier' => ISLANDORA_IMAGESERVER_DEFAULT_TOKEN, ); - - $settings = variable_get('islandora_imageserver_settings', array()) + $defaults; - - return $settings; } /** @@ -274,3 +307,29 @@ function islandora_imageserver_get_identifier($string_token, $pid, $dsid, $autht ); return token_replace($string_token, $parts); } + +/** + * Create the select box form element with the currently configured type. + * + * @param bool $disabled + * Whether the element should be disabled. + * + * @return array + * The form element. + */ +function islandora_imageserver_get_type_selectbox($disabled = TRUE) { + $settings = islandora_imageserver_get_settings(); + $description = $disabled ? t("Configured at Admin โ‰ซ Islandora โ‰ซ Image server configuration.") : t("Select the image server to configure."); + return array( + '#type' => 'select', + '#title' => t('Image Server'), + '#description' => $description, + '#default_value' => $settings['type'], + '#disabled' => $disabled, + '#options' => array( + 'none' => t('No image server configured'), + 'iiif' => t('IIIF image server'), + 'djatoka' => t('Adore-Djatoka image server'), + ), + ); +} diff --git a/islandora.install b/islandora.install index db01f1a52..d7c844133 100644 --- a/islandora.install +++ b/islandora.install @@ -167,7 +167,7 @@ function islandora_update_7003() { else { $openseadragon_settings['url'] = variable_get('islandora_openseadragon_iiif_url', 'iiif'); $openseadragon_settings['iiif_token_header'] = variable_get('islandora_openseadragon_iiif_token_header', FALSE); - $openseadragon_settings['iiif_identifier'] = explode(":", variable_get('islandora_openseadragon_iiif_identifier', '[islandora_openseadragon:url_token]'))[1]; + $openseadragon_settings['iiif_identifier'] = str_replace('[islandora_openseadragon:', '[islandora:', variable_get('islandora_openseadragon_iiif_identifier', '[islandora_openseadragon:url_token]')); } } if (module_exists('islandora_internet_archive_bookreader')) { @@ -180,7 +180,7 @@ function islandora_update_7003() { else { $iabv_settings['url'] = variable_get('islandora_internet_archive_bookreader_iiif_url', 'iiif'); $iabv_settings['iiif_token_header'] = variable_get('islandora_internet_archive_bookreader_iiif_token_header', FALSE); - $iabv_settings['iiif_identifier'] = explode(":", variable_get('islandora_internet_archive_bookreader_iiif_identifier', '[islandora_iareader:url_token]'))[1]; + $iabv_settings['iiif_identifier'] = str_replace('[islandora_iareader:', '[islandora:', variable_get('islandora_internet_archive_bookreader_iiif_identifier', '[islandora_iareader:url_token]')); } } if (isset($openseadragon_settings) && isset($iabv_settings)) { diff --git a/islandora.module b/islandora.module index a7f8347be..0e8b3d12e 100644 --- a/islandora.module +++ b/islandora.module @@ -428,6 +428,15 @@ function islandora_menu() { 'type' => MENU_NORMAL_ITEM, 'file' => 'includes/imageserver.inc', ); + $items['admin/islandora/image_server/reset'] = array( + 'title' => 'Image server configuration reset confirmation', + 'description' => 'Image server configuration reset confirmation', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('islandora_imageserver_admin_reset_confirm_form'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_CALLBACK, + 'file' => 'includes/imageserver.inc', + ); return $items; } From 629098a3041c9c34aa242524fbc725513241c055 Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Tue, 3 Sep 2019 09:28:13 -0500 Subject: [PATCH 5/7] Use form_state redirects --- README.md | 2 +- includes/imageserver.inc | 50 ++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ed2716ef3..caf380265 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Set the URL. If using IIIF choose to send token as a header and choose the token to use. -Any [IIIF](http://iiif.io) image server can be used the the IIIF tile source. The IIIF tile source provides an templated identifier which the IIIF server must be configured to resolve. This could be the full URL to the datastream to be displayed or something more complex. The IIIF server needs to be configured to resolve this full URL to retrieve the image. +Any [IIIF](http://iiif.io) image server can be used with the IIIF tile source. The IIIF tile source provides a templated identifier which the IIIF server must be configured to resolve. This could be the full URL to the datastream to be displayed or something more complex. The [Cantaloupe ๐Ÿˆ](https://medusa-project.github.io/cantaloupe/) IIIF image server can be configured to resolve these identifiers using the [`HttpResolver`](https://medusa-project.github.io/cantaloupe/manual/3.3/resolvers.html#HttpResolver) with no prefix specified. diff --git a/includes/imageserver.inc b/includes/imageserver.inc index f907487fc..3dda1b5ed 100644 --- a/includes/imageserver.inc +++ b/includes/imageserver.inc @@ -79,19 +79,30 @@ function islandora_imageserver_admin_form(array $form, array &$form_state) { '#type' => 'submit', '#value' => t('Save configuration'), '#weight' => 0, - '#name' => 'save_config', ), 'reset' => array( '#type' => 'submit', '#value' => t('Reset to defaults'), '#weight' => 1, - '#name' => 'reset_config', + '#submit' => array('islandora_imageserver_admin_submit_reset'), ), ), ); return $form; } +/** + * Redirect to Reset form. + * + * @param array $form + * Drupal form. + * @param array $form_state + * Drupal form state. + */ +function islandora_imageserver_admin_submit_reset(array $form, array &$form_state) { + $form_state['redirect'] = 'admin/islandora/image_server/reset'; +} + /** * Settings reset confirmation form. * @@ -104,12 +115,6 @@ function islandora_imageserver_admin_form(array $form, array &$form_state) { * The created form. */ function islandora_imageserver_admin_reset_confirm_form(array $form, array &$form_state) { - $form = array( - 'reset_confirm' => array( - '#type' => 'hidden', - '#value' => 1, - ), - ); return confirm_form( $form, t("Do you really want to reset the Image Server settings?"), @@ -125,32 +130,27 @@ function islandora_imageserver_admin_reset_confirm_form(array $form, array &$for function islandora_imageserver_admin_reset_confirm_form_submit(array $form, array &$form_state) { variable_set('islandora_imageserver_settings', islandora_imageserver_get_default_settings()); drupal_set_message(t('Settings reset.'), 'status'); - drupal_goto('admin/islandora/image_server'); + $form_state['redirect'] = 'admin/islandora/image_server'; } /** * Implements hook_form_submit(). */ function islandora_imageserver_admin_form_submit(array $form, array &$form_state) { - if (isset($form_state['triggering_element']) && $form_state['triggering_element']['#name'] == 'reset_config') { - drupal_goto('admin/islandora/image_server/reset'); + $type = $form_state['values']['type']; + $settings = islandora_imageserver_get_settings(); + $settings['type'] = $type; + $settings['url'] = rtrim($form_state['values']['url'], '/'); + if ($type == 'iiif') { + $settings['iiif_token_header'] = (bool) $form_state['values']['iiif_token_header']; + $settings['iiif_identifier'] = $form_state['values']['iiif_identifier']; } else { - $type = $form_state['values']['type']; - $settings = islandora_imageserver_get_settings(); - $settings['type'] = $type; - $settings['url'] = rtrim($form_state['values']['url'], '/'); - if ($type == 'iiif') { - $settings['iiif_token_header'] = (bool) $form_state['values']['iiif_token_header']; - $settings['iiif_identifier'] = $form_state['values']['iiif_identifier']; - } - else { - $settings['iiif_token_header'] = FALSE; - $settings['iiif_identifier'] = ISLANDORA_IMAGESERVER_DEFAULT_TOKEN; - } - variable_set('islandora_imageserver_settings', $settings); - drupal_set_message(t("Settings saved successfully."), 'status'); + $settings['iiif_token_header'] = FALSE; + $settings['iiif_identifier'] = ISLANDORA_IMAGESERVER_DEFAULT_TOKEN; } + variable_set('islandora_imageserver_settings', $settings); + drupal_set_message(t("Settings saved successfully."), 'status'); } /** From 483ac71e13d0cf5f83f82acec2d89d2fa94e99a7 Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Tue, 3 Sep 2019 09:42:30 -0500 Subject: [PATCH 6/7] Update install hook --- islandora.install | 4 ---- 1 file changed, 4 deletions(-) diff --git a/islandora.install b/islandora.install index d7c844133..357c8c1fd 100644 --- a/islandora.install +++ b/islandora.install @@ -201,10 +201,6 @@ function islandora_update_7003() { $new_settings = $iabv_settings; } if (isset($new_settings)) { - if (isset($new_settings['iiif_identifer']) && !empty($new_settings['iiif_identifer'])) { - // This will only have the back half of the token, prepend islandora. - $new_settings['iiif_identifer'] = "[islandora:" . $new_settings['iiif_identifer']; - } if ($new_settings['type'] == 'djatoka' && !preg_match('~resolver$~', $new_settings['url'])) { // IABV javascript added resolver to URL, Openseadragon did not. $new_settings['url'] = rtrim($new_settings['url'], '/') . '/resolver'; From 33bf7b48283efee01b1d973a8e0260480b0a7b1e Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Tue, 3 Sep 2019 10:56:33 -0500 Subject: [PATCH 7/7] Reset deletes the settings variable --- includes/imageserver.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/imageserver.inc b/includes/imageserver.inc index 3dda1b5ed..f1d55ccfc 100644 --- a/includes/imageserver.inc +++ b/includes/imageserver.inc @@ -128,7 +128,7 @@ function islandora_imageserver_admin_reset_confirm_form(array $form, array &$for * Implements hook_form_submit(). */ function islandora_imageserver_admin_reset_confirm_form_submit(array $form, array &$form_state) { - variable_set('islandora_imageserver_settings', islandora_imageserver_get_default_settings()); + variable_del('islandora_imageserver_settings'); drupal_set_message(t('Settings reset.'), 'status'); $form_state['redirect'] = 'admin/islandora/image_server'; }