diff --git a/includes/imageserver.inc b/includes/imageserver.inc new file mode 100644 index 00000000..6f400488 --- /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 cc0cc49f..9d89bae8 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 3e53ebac..a7f8347b 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; +}