Jonathan Green
11 years ago
54 changed files with 4284 additions and 331 deletions
@ -0,0 +1,64 @@ |
|||||||
|
/** |
||||||
|
* @file |
||||||
|
* Print styling |
||||||
|
* |
||||||
|
* We provide some sane print styling for Drupal, hiding most visuals. |
||||||
|
*/ |
||||||
|
|
||||||
|
#content a[href^="javascript:"]:after, |
||||||
|
#content a[href^="#"]:after { /* Only display useful links. */ |
||||||
|
/* content: ""; */ |
||||||
|
} |
||||||
|
|
||||||
|
#content abbr[title]:after { /* Add visible title after abbreviations. */ |
||||||
|
/* content: " (" attr(title) ")"; */ |
||||||
|
} |
||||||
|
|
||||||
|
#content { |
||||||
|
left: 0 !important; |
||||||
|
width: 100% !important; |
||||||
|
} |
||||||
|
uncomment when ready to test printing |
||||||
|
#header { |
||||||
|
display: none !important; |
||||||
|
} |
||||||
|
|
||||||
|
#content { /* Un-float the content */ |
||||||
|
float: none !important; |
||||||
|
width: 100% !important; |
||||||
|
margin: 0 !important; |
||||||
|
padding: 0 !important; |
||||||
|
} |
||||||
|
|
||||||
|
body, |
||||||
|
#page, |
||||||
|
#main, |
||||||
|
#content { /* Turn off any background colors or images */ |
||||||
|
color: #000; |
||||||
|
background-color: transparent !important; |
||||||
|
background-image: none !important; |
||||||
|
} |
||||||
|
|
||||||
|
body.sidebar-first { |
||||||
|
left: 0 !important; |
||||||
|
width: 100% !important; |
||||||
|
} |
||||||
|
#skip-link, |
||||||
|
#toolbar, |
||||||
|
#navigation, |
||||||
|
/* .region-sidebar-first, */ |
||||||
|
/* .region-sidebar-second, */ |
||||||
|
#header, |
||||||
|
#footer, |
||||||
|
.breadcrumb, |
||||||
|
.tabs, |
||||||
|
.action-links, |
||||||
|
.links, |
||||||
|
.book-navigation, |
||||||
|
.forum-topic-navigation, |
||||||
|
.pager, |
||||||
|
.contextual-links-region, |
||||||
|
.feed-icons { /* Hide sidebars and nav elements */ |
||||||
|
visibility: hidden !important; |
||||||
|
display: none !important; |
||||||
|
} |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,268 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* The form displayed that shows the datastream version history. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Function that returns markup for the datastream versions page. |
||||||
|
*/ |
||||||
|
function islandora_datastream_version_table($datastream) { |
||||||
|
module_load_include('inc', 'islandora', 'includes/datastream'); |
||||||
|
module_load_include('inc', 'islandora', 'includes/utilities'); |
||||||
|
$parent = $datastream->parent; |
||||||
|
drupal_set_title(t("@dsid Previous Versions", array('@dsid' => $datastream->id))); |
||||||
|
$audit_values = islandora_get_audit_trail($parent->id, $datastream->id); |
||||||
|
|
||||||
|
$header = array(); |
||||||
|
$header[] = array('data' => t('Created Date')); |
||||||
|
$header[] = array('data' => t('Size')); |
||||||
|
$header[] = array('data' => t('Label')); |
||||||
|
$header[] = array('data' => t('Responsibility')); |
||||||
|
$header[] = array('data' => t('Mime type')); |
||||||
|
$header[] = array('data' => t('Operations'), 'colspan' => '2'); |
||||||
|
$rows = array(); |
||||||
|
|
||||||
|
foreach ($datastream as $version => $datastream_version) { |
||||||
|
$row = array(); |
||||||
|
$reponsibility = $parent->owner; |
||||||
|
foreach ($audit_values as $audit_value) { |
||||||
|
$internal = $datastream_version->createdDate; |
||||||
|
if ($audit_value['date'] == $datastream_version->createdDate) { |
||||||
|
$reponsibility = $audit_value['responsibility']; |
||||||
|
} |
||||||
|
} |
||||||
|
$user = user_load_by_name($reponsibility); |
||||||
|
if ($user) { |
||||||
|
$user_id = $user->uid; |
||||||
|
$user_val = l($reponsibility, "user/$user_id"); |
||||||
|
} |
||||||
|
else { |
||||||
|
$user_val = $reponsibility; |
||||||
|
} |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-date', |
||||||
|
'data' => theme('islandora_datastream_view_link', array( |
||||||
|
'datastream' => $datastream, |
||||||
|
'label' => $datastream_version->createdDate->format(DATE_RFC850), |
||||||
|
'version' => $version, |
||||||
|
)), |
||||||
|
); |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-size', |
||||||
|
'data' => islandora_datastream_get_human_readable_size($datastream_version), |
||||||
|
); |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-label', |
||||||
|
'data' => $datastream_version->label, |
||||||
|
); |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-responsibility', |
||||||
|
'data' => $user_val, |
||||||
|
); |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-mime', |
||||||
|
'data' => $datastream_version->mimeType, |
||||||
|
); |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-delete', |
||||||
|
'data' => theme('islandora_datastream_delete_link', array( |
||||||
|
'datastream' => $datastream, |
||||||
|
'version' => $version, |
||||||
|
)), |
||||||
|
); |
||||||
|
$row[] = array( |
||||||
|
'class' => 'datastream-revert', |
||||||
|
'data' => theme('islandora_datastream_revert_link', array( |
||||||
|
'datastream' => $datastream, |
||||||
|
'version' => $version, |
||||||
|
)), |
||||||
|
); |
||||||
|
$rows[] = $row; |
||||||
|
} |
||||||
|
|
||||||
|
return theme('table', array('header' => $header, 'rows' => $rows)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The admin delete datastream form. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The Drupal form. |
||||||
|
* @param array $form_state |
||||||
|
* The Drupal form state. |
||||||
|
* @param AbstractDatastream $datastream |
||||||
|
* The datastream to be deleted. |
||||||
|
* @param string $version |
||||||
|
* The version number of the datastream we are trying to delete. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* The drupal form definition. |
||||||
|
*/ |
||||||
|
function islandora_delete_datastream_version_form(array $form, array &$form_state, AbstractDatastream $datastream, $version) { |
||||||
|
if (!isset($datastream[$version]) || count($datastream) < 2) { |
||||||
|
return drupal_not_found(); |
||||||
|
} |
||||||
|
|
||||||
|
$form_state['datastream'] = $datastream; |
||||||
|
$form_state['version'] = $version; |
||||||
|
return confirm_form($form, |
||||||
|
t('Are you sure you want to delete version @version of the @dsid datastream?', array('@dsid' => $datastream->id, '@version' => $version)), |
||||||
|
"islandora/object/{$datastream->parent->id}", |
||||||
|
t('This action cannot be undone.'), |
||||||
|
t('Delete'), |
||||||
|
t('Cancel') |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit handler for the delete datastream form. |
||||||
|
* |
||||||
|
* Purges/Delete's the given AbstractDatastream if possible. |
||||||
|
* |
||||||
|
* The ISLANDORA_PRE_PURGE_DATASTREAM_HOOK will query other modules as to |
||||||
|
* whether the given FedoraDatastream |
||||||
|
* should be: blocked from purging; state set to 'Deleted'; or purged. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The Drupal form. |
||||||
|
* @param array $form_state |
||||||
|
* The Drupal form state. |
||||||
|
*/ |
||||||
|
function islandora_delete_datastream_version_form_submit(array $form, array &$form_state) { |
||||||
|
$datastream = $form_state['datastream']; |
||||||
|
$version = $form_state['version']; |
||||||
|
|
||||||
|
$datastream_id = $datastream->id; |
||||||
|
$object = $datastream->parent; |
||||||
|
|
||||||
|
try { |
||||||
|
unset($datastream[$version]); |
||||||
|
} |
||||||
|
catch (Exception $e) { |
||||||
|
drupal_set_message(t('Error deleting version %v of %s datastream from object %o %e', array( |
||||||
|
'%v' => $version, |
||||||
|
'%s' => $datastream_id, |
||||||
|
'%o' => $object->label, |
||||||
|
'%e' => $e->getMessage())), 'error'); |
||||||
|
} |
||||||
|
|
||||||
|
drupal_set_message(t('%d datastream version successfully deleted from Islandora object %o', array( |
||||||
|
'%d' => $datastream_id, |
||||||
|
'%o' => $object->label))); |
||||||
|
|
||||||
|
$form_state['redirect'] = "islandora/object/{$object->id}/datastream/{$datastream->id}/version"; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The admin revert datastream form. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The Drupal form. |
||||||
|
* @param array $form_state |
||||||
|
* The Drupal form state. |
||||||
|
* @param AbstractDatastream $datastream |
||||||
|
* The datastream to be deleted. |
||||||
|
* @param string $version |
||||||
|
* The version number of the datastream we are trying to revert to. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* The drupal form definition. |
||||||
|
*/ |
||||||
|
function islandora_revert_datastream_version_form(array $form, array &$form_state, AbstractDatastream $datastream, $version) { |
||||||
|
if (!isset($datastream[$version]) || count($datastream) < 2) { |
||||||
|
return drupal_not_found(); |
||||||
|
} |
||||||
|
|
||||||
|
$form_state['dsid'] = $datastream->id; |
||||||
|
$form_state['object_id'] = $datastream->parent->id; |
||||||
|
$form_state['version'] = $version; |
||||||
|
|
||||||
|
return confirm_form($form, |
||||||
|
t('Are you sure you want to revert to version @version of the @dsid datastream?', array('@dsid' => $datastream->id, '@version' => $version)), |
||||||
|
"islandora/object/{$datastream->parent->id}", |
||||||
|
"", |
||||||
|
t('Revert'), |
||||||
|
t('Cancel') |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit handler for the revert datastream form. |
||||||
|
* |
||||||
|
* Reverts the given AbstractDatastream if possible. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The Drupal form. |
||||||
|
* @param array $form_state |
||||||
|
* The Drupal form state. |
||||||
|
*/ |
||||||
|
function islandora_revert_datastream_version_form_submit(array $form, array &$form_state) { |
||||||
|
$islandora_object = islandora_object_load($form_state['object_id']); |
||||||
|
|
||||||
|
$datastream_to_revert = $islandora_object[$form_state['dsid']]; |
||||||
|
$version = $form_state['version']; |
||||||
|
|
||||||
|
// Create file holding specified datastream version, and set datastream to it. |
||||||
|
$datastream_to_revert_to = $datastream_to_revert[$version]; |
||||||
|
if (in_array($datastream_to_revert->controlGroup, array('R', 'E'))) { |
||||||
|
$datastream_to_revert->url = $datastream_to_revert_to->url; |
||||||
|
} |
||||||
|
else { |
||||||
|
$filename = file_create_filename('datastream_temp_file', 'temporary://'); |
||||||
|
$datastream_to_revert_to->getContent($filename); |
||||||
|
$datastream_to_revert->setContentFromFile($filename); |
||||||
|
file_unmanaged_delete($filename); |
||||||
|
} |
||||||
|
|
||||||
|
if ($datastream_to_revert->mimeType != $datastream_to_revert_to->mimeType) { |
||||||
|
$datastream_to_revert->mimeType = $datastream_to_revert_to->mimeType; |
||||||
|
} |
||||||
|
if ($datastream_to_revert->label != $datastream_to_revert_to->label) { |
||||||
|
$datastream_to_revert->label = $datastream_to_revert_to->label; |
||||||
|
} |
||||||
|
|
||||||
|
drupal_set_message(t('%d datastream successfully reverted to version %v for Islandora object %o', array( |
||||||
|
'%d' => $datastream_to_revert->id, |
||||||
|
'%v' => $version, |
||||||
|
'%o' => $islandora_object->label))); |
||||||
|
|
||||||
|
$form_state['redirect'] = "islandora/object/{$islandora_object->id}/datastream/{$datastream_to_revert->id}/version"; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets Audit datastream values from foxml. |
||||||
|
* |
||||||
|
* @param String $pid |
||||||
|
* PID of parent object |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* Array of audit values |
||||||
|
*/ |
||||||
|
function islandora_get_audit_trail($pid, $dsid) { |
||||||
|
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora'); |
||||||
|
$connection = islandora_get_tuque_connection(NULL, $url); |
||||||
|
$xml = $connection->api->m->getObjectXml($pid); |
||||||
|
$simple_xml = simplexml_load_string($xml); |
||||||
|
$fox_ns = "info:fedora/fedora-system:def/foxml#"; |
||||||
|
$audit_ns = 'info:fedora/fedora-system:def/audit#'; |
||||||
|
$foxml_nodes = $simple_xml->children($fox_ns); |
||||||
|
foreach ($foxml_nodes as $node) { |
||||||
|
if ($node->attributes()->ID == "AUDIT") { |
||||||
|
$content = $node->datastreamVersion->xmlContent; |
||||||
|
$audit_nodes = $content->children($audit_ns); |
||||||
|
} |
||||||
|
} |
||||||
|
$audit_values = array(); |
||||||
|
if (isset($audit_nodes)) { |
||||||
|
foreach ($audit_nodes->auditTrail->record as $record) { |
||||||
|
if ($dsid == $record->componentID) { |
||||||
|
$values['responsibility'] = $record->responsibility; |
||||||
|
$values['date'] = $record->date; |
||||||
|
$audit_values[] = $values; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $audit_values; |
||||||
|
} |
@ -0,0 +1,123 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Defines functions used when constructing derivatives. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Kicks off derivative functions based upon hooks and conditions. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a FedoraObject. |
||||||
|
* @param array $options |
||||||
|
* An array of parameters containing: |
||||||
|
* - force: Bool denoting whether we are forcing the generation of |
||||||
|
* derivatives. |
||||||
|
* - source_dsid: (Optional) String of the datastream id we are generating |
||||||
|
* from or NULL if it's the object itself. |
||||||
|
* - destination_dsid: (Optional) String of the datastream id that is being |
||||||
|
* created. To be used in the UI. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* An array of messages describing the outcome of the derivative events. |
||||||
|
* Each individual message array has the following structure: |
||||||
|
* - success: Bool denoting whether the operation was successful. |
||||||
|
* - messages: An array structure containing: |
||||||
|
* - message: A string passed through t() describing the |
||||||
|
* outcome of the operation. |
||||||
|
* - message_sub: (Optional) Substitutions to be passed along to t() or |
||||||
|
* watchdog. |
||||||
|
* - type: A string denoting whether the output is to be |
||||||
|
* drupal_set_messaged (dsm) or watchdogged (watchdog). |
||||||
|
* - severity: (Optional) A severity level / status to be used when |
||||||
|
* logging messages. Uses the defaults of drupal_set_message and |
||||||
|
* watchdog if not defined. |
||||||
|
*/ |
||||||
|
function islandora_do_derivatives(AbstractObject $object, array $options) { |
||||||
|
module_load_include('inc', 'islandora', 'includes/utilities'); |
||||||
|
$options += array( |
||||||
|
'force' => FALSE, |
||||||
|
); |
||||||
|
$hooks = islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array($object)); |
||||||
|
uasort($hooks, 'drupal_sort_weight'); |
||||||
|
$results = array(); |
||||||
|
|
||||||
|
if (array_key_exists('source_dsid', $options)) { |
||||||
|
$hooks = array_filter($hooks, function($filter_hook) use($options) { |
||||||
|
return array_key_exists('source_dsid', $filter_hook) && |
||||||
|
$filter_hook['source_dsid'] == $options['source_dsid']; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
if (array_key_exists('destination_dsid', $options)) { |
||||||
|
$hooks = array_filter($hooks, function($filter_hook) use($options) { |
||||||
|
return array_key_exists('destination_dsid', $filter_hook) && |
||||||
|
$filter_hook['destination_dsid'] == $options['destination_dsid']; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
foreach ($hooks as $hook) { |
||||||
|
if (isset($hook['file'])) { |
||||||
|
require_once $hook['file']; |
||||||
|
} |
||||||
|
foreach ($hook['function'] as $function) { |
||||||
|
if (function_exists($function)) { |
||||||
|
$logging = call_user_func($function, $object, $options['force']); |
||||||
|
if (!empty($logging)) { |
||||||
|
$results[] = $logging; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
watchdog('islandora', 'Unable to call derivative function @function as it was not found!', array('@function' => $function), WATCHDOG_ERROR); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Handles the logging of derivative messages. |
||||||
|
* |
||||||
|
* @param array $logging_results |
||||||
|
* An array of messages describing the outcome of the derivative events. |
||||||
|
* Each individual message array has the following structure: |
||||||
|
* - success: Bool denoting whether the operation was successful. |
||||||
|
* - messages: An array structure containing: |
||||||
|
* - message: A string passed through t() describing the |
||||||
|
* outcome of the operation. |
||||||
|
* - message_sub: (Optional) Substitutions to be passed along to t() or |
||||||
|
* watchdog. |
||||||
|
* - type: A string denoting whether the output is to be |
||||||
|
* drupal_set_messaged (dsm) or watchdogged (watchdog). |
||||||
|
* - severity: (Optional) A severity level / status to be used when |
||||||
|
* logging messages. Uses the defaults of drupal_set_message and |
||||||
|
* watchdog if not defined. |
||||||
|
*/ |
||||||
|
function islandora_derivative_logging(array $logging_results) { |
||||||
|
foreach ($logging_results as $result) { |
||||||
|
foreach ($result['messages'] as $message) { |
||||||
|
if ($message['type'] === 'dsm') { |
||||||
|
if (isset($message['severity']) && $message['severity'] != 'status') { |
||||||
|
drupal_set_message(filter_xss(format_string($message['message'], isset($message['message_sub']) ? $message['message_sub'] : array())), $message['severity']); |
||||||
|
} |
||||||
|
else { |
||||||
|
if (!isset($_SESSION['islandora_event_messages'])) { |
||||||
|
$_SESSION['islandora_event_messages'] = array(); |
||||||
|
} |
||||||
|
$_SESSION['islandora_event_messages'][] = array( |
||||||
|
'message' => filter_xss(format_string($message['message'], isset($message['message_sub']) ? $message['message_sub'] : array())), |
||||||
|
'severity' => 'status', |
||||||
|
); |
||||||
|
drupal_set_message(l(t('Derivatives successfully created.'), 'islandora/event-status'), 'status', FALSE); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
// We know what we are doing here. Passing through the translated |
||||||
|
// message and the substitutions needed. We are using |
||||||
|
// call_user_func until such time as the @ignore changes |
||||||
|
// are merged into the standard release for Coder. |
||||||
|
call_user_func('watchdog', 'islandora_derivatives', $message['message'], isset($message['message_sub']) ? $message['message_sub'] : array(), isset($message['severity']) ? $message['severity'] : WATCHDOG_NOTICE); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,340 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Handles the management of deleted objects. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* The deletion management prep form. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The Drupal form definition. |
||||||
|
* @param array $form_state |
||||||
|
* The Drupal form state. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* The Drupal form definition. |
||||||
|
*/ |
||||||
|
function islandora_deleted_objects_prep_form($form, $form_state, $serialized_chosen = NULL) { |
||||||
|
module_load_include('inc', 'islandora', 'includes/utilities'); |
||||||
|
$chosen_contentmodels = array(); |
||||||
|
if ($serialized_chosen) { |
||||||
|
$chosen_contentmodels = unserialize($serialized_chosen); |
||||||
|
} |
||||||
|
$contentmodels_with_deleted_members = islandora_get_contentmodels_with_deleted_members(); |
||||||
|
$elegible_contentmodels = array_keys($contentmodels_with_deleted_members); |
||||||
|
if (empty($contentmodels_with_deleted_members)) { |
||||||
|
$form['message'] = array( |
||||||
|
'#type' => 'markup', |
||||||
|
'#markup' => t("There are no deleted objects in this repository."), |
||||||
|
); |
||||||
|
return $form; |
||||||
|
} |
||||||
|
$form['message'] = array( |
||||||
|
'#type' => 'markup', |
||||||
|
'#markup' => t("Select content models of deleted objects."), |
||||||
|
); |
||||||
|
$form['mapped_contentmodels'] = array( |
||||||
|
'#type' => 'hidden', |
||||||
|
'#value' => $contentmodels_with_deleted_members, |
||||||
|
); |
||||||
|
$table_element = islandora_content_model_select_table_form_element(NULL); |
||||||
|
|
||||||
|
foreach ($table_element['#options'] as $option) { |
||||||
|
if (!in_array($option['pid'], $elegible_contentmodels)) { |
||||||
|
unset($table_element['#options'][$option['pid']]); |
||||||
|
} |
||||||
|
if (array_key_exists($option['pid'], $chosen_contentmodels)) { |
||||||
|
$table_element['#default_value'][$option['pid']] = TRUE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$form['contentmodels'] = $table_element; |
||||||
|
$form['next'] = array( |
||||||
|
'#type' => 'submit', |
||||||
|
'#value' => t('Next'), |
||||||
|
); |
||||||
|
|
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit handler for deletion management prep form. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The form. |
||||||
|
* @param array $form_state |
||||||
|
* The form state. |
||||||
|
*/ |
||||||
|
function islandora_deleted_objects_prep_form_submit($form, $form_state) { |
||||||
|
$content_models = $form_state['values']['contentmodels']; |
||||||
|
$chosen = function($element) { |
||||||
|
return $element; |
||||||
|
}; |
||||||
|
$serialized_contentmodels = serialize(array_filter($content_models, $chosen)); |
||||||
|
drupal_goto("admin/islandora/restore/manage/$serialized_contentmodels"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The deletion management prep form. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The Drupal form definition. |
||||||
|
* @param array $form_state |
||||||
|
* The Drupal form state. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* The Drupal form definition. |
||||||
|
*/ |
||||||
|
function islandora_deleted_objects_manage_form($form, $form_state, $serialized_chosen = NULL) { |
||||||
|
$form['previous'] = array( |
||||||
|
'#type' => 'submit', |
||||||
|
'#value' => t('Previous'), |
||||||
|
'#attributes' => array('source' => 'previous'), |
||||||
|
); |
||||||
|
|
||||||
|
$chosen_contentmodels = unserialize($serialized_chosen); |
||||||
|
$content_models_with_deleted = islandora_get_contentmodels_with_deleted_members(); |
||||||
|
foreach ($chosen_contentmodels as $contentmodel) { |
||||||
|
if (!array_key_exists($contentmodel, $content_models_with_deleted)) { |
||||||
|
unset($chosen_contentmodels[$contentmodel]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (empty($chosen_contentmodels)) { |
||||||
|
$form['message'] = array( |
||||||
|
'#type' => 'markup', |
||||||
|
'#markup' => t("There are no deleted objects with the selected content models in this repository."), |
||||||
|
); |
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
if (is_array($chosen_contentmodels)) { |
||||||
|
foreach ($chosen_contentmodels as $key => $value) { |
||||||
|
if (in_array($key, $content_models_with_deleted)) { |
||||||
|
$chosen_contentmodels[$key] = $content_models_with_deleted[$key]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$tuque = islandora_get_tuque_connection(); |
||||||
|
$repository = $tuque->repository; |
||||||
|
// Query brings back fedora-system:FedoraObject-3.0, doubling the results. |
||||||
|
$total = $repository->ri->countQuery(islandora_get_deleted_query($chosen_contentmodels), 'sparql') / 2; |
||||||
|
$limit = 25; |
||||||
|
if ($total < 28) { |
||||||
|
$limit = $total; |
||||||
|
} |
||||||
|
$current_page = pager_default_initialize($total, $limit); |
||||||
|
$query_limit = $limit * 2; |
||||||
|
$offset = $current_page * $query_limit; |
||||||
|
$options = islandora_get_deleted_objects($chosen_contentmodels, $query_limit, $offset); |
||||||
|
|
||||||
|
foreach ($options as &$option) { |
||||||
|
$option['content_model'] = $content_models_with_deleted[$option['content_model']]; |
||||||
|
} |
||||||
|
$form['serialized_chosen'] = array( |
||||||
|
'#type' => 'hidden', |
||||||
|
'#value' => $serialized_chosen, |
||||||
|
); |
||||||
|
$form['pager'] = array( |
||||||
|
'#type' => 'markup', |
||||||
|
'#markup' => theme('pager', array('quantity', count($options))), |
||||||
|
); |
||||||
|
$form['propogate'] = array( |
||||||
|
'#title' => t('Apply changes to related objects?'), |
||||||
|
'#default_value' => TRUE, |
||||||
|
'#description' => t("Objects associated with selected objects will also be purged/restored. ie page objects associated with a book object."), |
||||||
|
'#type' => 'checkbox', |
||||||
|
); |
||||||
|
$form['chosen'] = array( |
||||||
|
'#type' => 'hidden', |
||||||
|
'#value' => $chosen_contentmodels, |
||||||
|
); |
||||||
|
$form['objects_to_process'] = array( |
||||||
|
'#type' => 'tableselect', |
||||||
|
'#header' => array( |
||||||
|
'title' => t('Name'), |
||||||
|
'pid' => t('PID'), |
||||||
|
'content_model' => t('Content Model'), |
||||||
|
), |
||||||
|
'#multiple' => TRUE, |
||||||
|
'#options' => $options, |
||||||
|
); |
||||||
|
|
||||||
|
$form['submit'] = array( |
||||||
|
'#type' => 'submit', |
||||||
|
'#value' => t('Restore selected objects'), |
||||||
|
'#attributes' => array('source' => 'restore'), |
||||||
|
); |
||||||
|
if (user_access(ISLANDORA_PURGE)) { |
||||||
|
$form['purge'] = array( |
||||||
|
'#type' => 'submit', |
||||||
|
'#value' => t('Irrevocably purge selected objects'), |
||||||
|
'#attributes' => array('source' => 'purge'), |
||||||
|
); |
||||||
|
} |
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit handler for deletion management form. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* The form. |
||||||
|
* @param array $form_state |
||||||
|
* The form state. |
||||||
|
*/ |
||||||
|
function islandora_deleted_objects_manage_form_submit($form, $form_state) { |
||||||
|
module_load_include('inc', 'islandora', 'includes/utilities'); |
||||||
|
$serialized_chosen = isset($form_state['values']['serialized_chosen']) ? $form_state['values']['serialized_chosen'] : NULL; |
||||||
|
|
||||||
|
if (isset($form_state['clicked_button']['#attributes']['source']) && $form_state['clicked_button']['#attributes']['source'] == 'previous') { |
||||||
|
drupal_goto("admin/islandora/restore/prep/$serialized_chosen"); |
||||||
|
} |
||||||
|
if ($form_state['clicked_button']['#attributes']['source'] == 'restore') { |
||||||
|
$descriptor = "Restoring"; |
||||||
|
$action = 'islandora_restore_object_by_pid'; |
||||||
|
} |
||||||
|
if ($form_state['clicked_button']['#attributes']['source'] == 'purge') { |
||||||
|
$descriptor = "Purging"; |
||||||
|
$action = 'islandora_purge_object_by_pid'; |
||||||
|
} |
||||||
|
$objects_to_process = array_filter($form_state['values']['objects_to_process']); |
||||||
|
$pids_to_restore = $objects_to_process; |
||||||
|
if ($form_state['values']['propogate']) { |
||||||
|
foreach ($objects_to_process as $pid) { |
||||||
|
$fedora_object = islandora_object_load($pid); |
||||||
|
$temp = islandora_invoke_hook_list(ISLANDORA_UPDATE_RELATED_OBJECTS_PROPERTIES_HOOK, $fedora_object->models, array($fedora_object)); |
||||||
|
if (!empty($temp)) { |
||||||
|
$pids_to_restore = array_merge_recursive($pids_to_restore, $temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
$batch = array( |
||||||
|
'title' => t('@descriptor selected objects', array('@descriptor' => $descriptor)), |
||||||
|
'file' => drupal_get_path('module', 'islandora') . '/includes/manage_deleted_objects.inc', |
||||||
|
'operations' => array(), |
||||||
|
); |
||||||
|
|
||||||
|
foreach ($pids_to_restore as $pid) { |
||||||
|
$batch['operations'][] = array( |
||||||
|
$action, |
||||||
|
array($pid), |
||||||
|
); |
||||||
|
} |
||||||
|
batch_set($batch); |
||||||
|
batch_process("admin/islandora/restore/manage/$serialized_chosen"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets PIDS of all deleted objects. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* PIDS of deleted objects |
||||||
|
*/ |
||||||
|
function islandora_get_deleted_objects($content_models, $limit, $offset) { |
||||||
|
$tuque = islandora_get_tuque_connection(); |
||||||
|
$repository = $tuque->repository; |
||||||
|
$query = islandora_get_deleted_query($content_models, $offset); |
||||||
|
$objects = $repository->ri->sparqlQuery($query, $limit); |
||||||
|
$deleted_objects = array(); |
||||||
|
foreach ($objects as $object) { |
||||||
|
if ($object['object']['value'] != "fedora-system:FedoraObject-3.0") { |
||||||
|
$pid = $object['subject']['value']; |
||||||
|
$cm_pid = $object['object']['value']; |
||||||
|
$title = $object['label']['value']; |
||||||
|
$deleted_objects[$pid] = array( |
||||||
|
'title' => $title, 'pid' => $pid, |
||||||
|
'content_model' => $content_models[$cm_pid], |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
return $deleted_objects; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets PIDS of all content models associated with deleted objects. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* array of content model pids |
||||||
|
*/ |
||||||
|
function islandora_get_contentmodels_with_deleted_members() { |
||||||
|
$tuque = new IslandoraTuque(); |
||||||
|
$repository = $tuque->repository; |
||||||
|
$query = "PREFIX fm: <info:fedora/fedora-system:def/model#> |
||||||
|
SELECT DISTINCT ?object ?label FROM <#ri> |
||||||
|
WHERE { |
||||||
|
{?subject fm:state fm:Deleted; |
||||||
|
fm:hasModel ?object; |
||||||
|
} |
||||||
|
OPTIONAL{ |
||||||
|
?object fm:label ?label |
||||||
|
} |
||||||
|
}"; |
||||||
|
|
||||||
|
$objects = $repository->ri->sparqlQuery($query, -1); |
||||||
|
$content_models = array(); |
||||||
|
foreach ($objects as $object) { |
||||||
|
if ($object['object']['value'] != "fedora-system:FedoraObject-3.0") { |
||||||
|
$content_models[$object['object']['value']] = $object['label']['value']; |
||||||
|
} |
||||||
|
} |
||||||
|
return $content_models; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Restores deleted object. |
||||||
|
* |
||||||
|
* @param String $pid |
||||||
|
* PID of object to be restored |
||||||
|
*/ |
||||||
|
function islandora_restore_object_by_pid($pid) { |
||||||
|
$fedora_object = islandora_object_load($pid); |
||||||
|
$fedora_object->state = 'A'; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Purges deleted object. |
||||||
|
* |
||||||
|
* @param String $pid |
||||||
|
* PID of object to be restored |
||||||
|
*/ |
||||||
|
function islandora_purge_object_by_pid($pid) { |
||||||
|
$fedora_object = islandora_object_load($pid); |
||||||
|
$fedora_object->repository->purgeObject($pid); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get query to find all deleted objects by content type. |
||||||
|
* |
||||||
|
* @param array $content_models |
||||||
|
* Content models to restrict search |
||||||
|
* @param int $offset |
||||||
|
* offset to be added to search |
||||||
|
* |
||||||
|
* @return String |
||||||
|
* Sparql query |
||||||
|
*/ |
||||||
|
function islandora_get_deleted_query($content_models, $offset = 0) { |
||||||
|
$candidates = array_keys($content_models); |
||||||
|
$first_contentmodel = array_shift($candidates); |
||||||
|
$prefix = "PREFIX fm: <" . FEDORA_MODEL_URI . "> "; |
||||||
|
$select = "SELECT DISTINCT ?subject ?label ?object FROM <#ri> WHERE { "; |
||||||
|
$where_clause = "{?subject fm:hasModel <info:fedora/$first_contentmodel>; |
||||||
|
fm:state fm:Deleted; |
||||||
|
fm:hasModel ?object; |
||||||
|
}"; |
||||||
|
$suffix = "} ORDER BY ?subject OFFSET $offset"; |
||||||
|
$unions = ''; |
||||||
|
foreach ($candidates as $contentmodel) { |
||||||
|
$unions .= "UNION {?subject fm:hasModel <info:fedora/$contentmodel>; |
||||||
|
fm:state fm:Deleted; |
||||||
|
fm:hasModel ?object; |
||||||
|
} |
||||||
|
"; |
||||||
|
} |
||||||
|
$optional = "OPTIONAL{?subject fm:label ?label}"; |
||||||
|
return "$prefix $select $where_clause $unions $optional $suffix"; |
||||||
|
} |
@ -0,0 +1,171 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Defines functions used when viewing metadata displays on Islandora objects. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieves the metadata display markup for an Islandora object. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing an object within Fedora. |
||||||
|
* @param bool $print |
||||||
|
* Whether the object is being printed. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
* Markup to be rendered for display on Islandora object pages. |
||||||
|
*/ |
||||||
|
function islandora_retrieve_metadata_markup(AbstractObject $object, $print = FALSE) { |
||||||
|
$viewers = module_invoke_all('islandora_metadata_display_info'); |
||||||
|
$viewer = variable_get('islandora_metadata_display', 'dublin_core'); |
||||||
|
$markup = ''; |
||||||
|
if (isset($viewers[$viewer]['metadata callback'])) { |
||||||
|
$markup = call_user_func($viewers[$viewer]['metadata callback'], $object, $print); |
||||||
|
// The callback doesn't have any markup provided for this particular object, |
||||||
|
// default back to the dublin_core display. |
||||||
|
if ($markup === FALSE) { |
||||||
|
$markup = call_user_func($viewers['dublin_core']['metadata callback'], $object, $print); |
||||||
|
} |
||||||
|
} |
||||||
|
return $markup; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieves the metadata display description for an Islandora object. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing an object within Fedora. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
* Markup to be rendered for description on Islandora object pages. |
||||||
|
*/ |
||||||
|
function islandora_retrieve_description_markup(AbstractObject $object) { |
||||||
|
$viewers = module_invoke_all('islandora_metadata_display_info'); |
||||||
|
$viewer = variable_get('islandora_metadata_display', 'dublin_core'); |
||||||
|
$markup = ''; |
||||||
|
if (isset($viewers[$viewer]['description callback'])) { |
||||||
|
$markup = call_user_func($viewers[$viewer]['description callback'], $object); |
||||||
|
// The callback doesn't have any markup provided for this particular object, |
||||||
|
// default back to the dublin_core display. |
||||||
|
if ($markup === FALSE) { |
||||||
|
$markup = call_user_func($viewers['dublin_core']['description callback'], $object); |
||||||
|
} |
||||||
|
} |
||||||
|
return $markup; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Form used for choosing which default metadata display to use for viewing. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* An array representing a Drupal form. |
||||||
|
* @param array $form_state |
||||||
|
* An array containing the Drupal form state. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* An array representing the metadata display viewer form. |
||||||
|
*/ |
||||||
|
function islandora_metadata_display_form($form, $form_state) { |
||||||
|
module_load_include('inc', 'islandora', 'includes/solution_packs.inc'); |
||||||
|
$form = array(); |
||||||
|
$defined_displays = module_invoke_all('islandora_metadata_display_info'); |
||||||
|
if (!empty($defined_displays)) { |
||||||
|
$no_viewer = array(); |
||||||
|
$no_viewer['none'] = array( |
||||||
|
'label' => t('None'), |
||||||
|
'description' => t("Don't show any metadata for displaying"), |
||||||
|
); |
||||||
|
$viewers = array_merge_recursive($no_viewer, $defined_displays); |
||||||
|
|
||||||
|
$form['viewers'] = array( |
||||||
|
'#type' => 'item', |
||||||
|
'#title' => t('Select a viewer'), |
||||||
|
'#description' => t('Preferred metadata display for Islandora. These may be provided by third-party modules.'), |
||||||
|
'#tree' => TRUE, |
||||||
|
'#theme' => 'islandora_viewers_table', |
||||||
|
); |
||||||
|
|
||||||
|
foreach ($viewers as $name => $profile) { |
||||||
|
$options[$name] = ''; |
||||||
|
$form['viewers']['name'][$name] = array( |
||||||
|
'#type' => 'hidden', |
||||||
|
'#value' => $name, |
||||||
|
); |
||||||
|
$form['viewers']['label'][$name] = array( |
||||||
|
'#type' => 'item', |
||||||
|
'#markup' => $profile['label'], |
||||||
|
); |
||||||
|
$form['viewers']['description'][$name] = array( |
||||||
|
'#type' => 'item', |
||||||
|
'#markup' => $profile['description'], |
||||||
|
); |
||||||
|
$form['viewers']['configuration'][$name] = array( |
||||||
|
'#type' => 'item', |
||||||
|
'#markup' => (isset($profile['configuration']) AND $profile['configuration'] != '') ? l(t('configure'), $profile['configuration']) : '', |
||||||
|
); |
||||||
|
} |
||||||
|
$form['viewers']['default'] = array( |
||||||
|
'#type' => 'radios', |
||||||
|
'#options' => isset($options) ? $options : array(), |
||||||
|
'#default_value' => variable_get('islandora_metadata_display', 'dublin_core'), |
||||||
|
); |
||||||
|
} |
||||||
|
else { |
||||||
|
$form['viewers']['no_viewers'] = array( |
||||||
|
'#markup' => t('No viewers detected.'), |
||||||
|
); |
||||||
|
} |
||||||
|
$form['submit'] = array( |
||||||
|
'#type' => 'submit', |
||||||
|
'#value' => t('Save configuration'), |
||||||
|
); |
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Submit handler for the metadata display form which sets the default viewer. |
||||||
|
* |
||||||
|
* @param array $form |
||||||
|
* An array representing a Drupal form. |
||||||
|
* @param array $form_state |
||||||
|
* An array containing the Drupal form state. |
||||||
|
*/ |
||||||
|
function islandora_metadata_display_form_submit($form, $form_state) { |
||||||
|
variable_set('islandora_metadata_display', $form_state['values']['viewers']['default']); |
||||||
|
drupal_set_message(t('The configuration options have been saved.')); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Metadata display callback for rendering Dublin Core metadata. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing an object within Fedora. |
||||||
|
* @param bool $print |
||||||
|
* Whether the display is being printed or not. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
* Markup representing the rendered metadata from Dublin Core. |
||||||
|
*/ |
||||||
|
function islandora_metadata_display_callback(AbstractObject $object, $print = FALSE) { |
||||||
|
$elements = array( |
||||||
|
'islandora_object' => $object, |
||||||
|
'print' => $print, |
||||||
|
); |
||||||
|
return theme('islandora_dublin_core_display', $elements); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Metadata description callback for rendering Dublin Core description. |
||||||
|
* |
||||||
|
* @param AbstractObject $islandora_object |
||||||
|
* An AbstractObject representing an object within Fedora. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
* Markup representing the rendered metadata from Dublin Core. |
||||||
|
*/ |
||||||
|
function islandora_metadata_description_callback(AbstractObject $islandora_object) { |
||||||
|
$elements = array( |
||||||
|
'islandora_object' => $islandora_object, |
||||||
|
); |
||||||
|
return theme('islandora_dublin_core_description', $elements); |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
/** |
||||||
|
* @file |
||||||
|
* JavaScript file responsable for the print button behaviour. |
||||||
|
*
|
||||||
|
* The print button is added automatically to every view, as metadata |
||||||
|
* can be printed from every object. |
||||||
|
* |
||||||
|
*/ |
||||||
|
(function ($) { |
||||||
|
$(document).ready(function() { |
||||||
|
$('.tabs .primary').append('<img id="print_btn" title="Print" src="' + Drupal.settings.basePath + Drupal.settings.islandora.print_img + '"></img>'); |
||||||
|
$('#print_btn').css("cursor","pointer"); |
||||||
|
$('#print_btn').click(function() { |
||||||
|
window.location=Drupal.settings.basePath + Drupal.settings.islandora.print_link; |
||||||
|
}); |
||||||
|
}); |
||||||
|
})(jQuery); |
||||||
|
|
@ -0,0 +1,21 @@ |
|||||||
|
The MIT License |
||||||
|
|
||||||
|
Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de] |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in |
||||||
|
all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||||
|
THE SOFTWARE. |
@ -0,0 +1,11 @@ |
|||||||
|
CONTENTS OF THIS FILE |
||||||
|
--------------------- |
||||||
|
|
||||||
|
* summary |
||||||
|
|
||||||
|
SUMMARY |
||||||
|
------- |
||||||
|
|
||||||
|
This directory contains the spin.js library: http://fgnass.github.io/spin.js/ |
||||||
|
downloaded from http://fgnass.github.io/spin.js/dist/spin.min.js on Sept 27th |
||||||
|
2013. This project is under version control: https://github.com/fgnass/spin.js. |
@ -0,0 +1 @@ |
|||||||
|
(function(t,e){if(typeof exports=="object")module.exports=e();else if(typeof define=="function"&&define.amd)define(e);else t.Spinner=e()})(this,function(){"use strict";var t=["webkit","Moz","ms","O"],e={},i;function o(t,e){var i=document.createElement(t||"div"),o;for(o in e)i[o]=e[o];return i}function n(t){for(var e=1,i=arguments.length;e<i;e++)t.appendChild(arguments[e]);return t}var r=function(){var t=o("style",{type:"text/css"});n(document.getElementsByTagName("head")[0],t);return t.sheet||t.styleSheet}();function s(t,o,n,s){var a=["opacity",o,~~(t*100),n,s].join("-"),f=.01+n/s*100,l=Math.max(1-(1-t)/o*(100-f),t),u=i.substring(0,i.indexOf("Animation")).toLowerCase(),d=u&&"-"+u+"-"||"";if(!e[a]){r.insertRule("@"+d+"keyframes "+a+"{"+"0%{opacity:"+l+"}"+f+"%{opacity:"+t+"}"+(f+.01)+"%{opacity:1}"+(f+o)%100+"%{opacity:"+t+"}"+"100%{opacity:"+l+"}"+"}",r.cssRules.length);e[a]=1}return a}function a(e,i){var o=e.style,n,r;i=i.charAt(0).toUpperCase()+i.slice(1);for(r=0;r<t.length;r++){n=t[r]+i;if(o[n]!==undefined)return n}if(o[i]!==undefined)return i}function f(t,e){for(var i in e)t.style[a(t,i)||i]=e[i];return t}function l(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var o in i)if(t[o]===undefined)t[o]=i[o]}return t}function u(t){var e={x:t.offsetLeft,y:t.offsetTop};while(t=t.offsetParent)e.x+=t.offsetLeft,e.y+=t.offsetTop;return e}function d(t,e){return typeof t=="string"?t:t[e%t.length]}var p={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",direction:1,speed:1,trail:100,opacity:1/4,fps:20,zIndex:2e9,className:"spinner",top:"auto",left:"auto",position:"relative"};function c(t){if(typeof this=="undefined")return new c(t);this.opts=l(t||{},c.defaults,p)}c.defaults={};l(c.prototype,{spin:function(t){this.stop();var e=this,n=e.opts,r=e.el=f(o(0,{className:n.className}),{position:n.position,width:0,zIndex:n.zIndex}),s=n.radius+n.length+n.width,a,l;if(t){t.insertBefore(r,t.firstChild||null);l=u(t);a=u(r);f(r,{left:(n.left=="auto"?l.x-a.x+(t.offsetWidth>>1):parseInt(n.left,10)+s)+"px",top:(n.top=="auto"?l.y-a.y+(t.offsetHeight>>1):parseInt(n.top,10)+s)+"px"})}r.setAttribute("role","progressbar");e.lines(r,e.opts);if(!i){var d=0,p=(n.lines-1)*(1-n.direction)/2,c,h=n.fps,m=h/n.speed,y=(1-n.opacity)/(m*n.trail/100),g=m/n.lines;(function v(){d++;for(var t=0;t<n.lines;t++){c=Math.max(1-(d+(n.lines-t)*g)%m*y,n.opacity);e.opacity(r,t*n.direction+p,c,n)}e.timeout=e.el&&setTimeout(v,~~(1e3/h))})()}return e},stop:function(){var t=this.el;if(t){clearTimeout(this.timeout);if(t.parentNode)t.parentNode.removeChild(t);this.el=undefined}return this},lines:function(t,e){var r=0,a=(e.lines-1)*(1-e.direction)/2,l;function u(t,i){return f(o(),{position:"absolute",width:e.length+e.width+"px",height:e.width+"px",background:t,boxShadow:i,transformOrigin:"left",transform:"rotate("+~~(360/e.lines*r+e.rotate)+"deg) translate("+e.radius+"px"+",0)",borderRadius:(e.corners*e.width>>1)+"px"})}for(;r<e.lines;r++){l=f(o(),{position:"absolute",top:1+~(e.width/2)+"px",transform:e.hwaccel?"translate3d(0,0,0)":"",opacity:e.opacity,animation:i&&s(e.opacity,e.trail,a+r*e.direction,e.lines)+" "+1/e.speed+"s linear infinite"});if(e.shadow)n(l,f(u("#000","0 0 4px "+"#000"),{top:2+"px"}));n(t,n(l,u(d(e.color,r),"0 0 1px rgba(0,0,0,.1)")))}return t},opacity:function(t,e,i){if(e<t.childNodes.length)t.childNodes[e].style.opacity=i}});function h(){function t(t,e){return o("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',e)}r.addRule(".spin-vml","behavior:url(#default#VML)");c.prototype.lines=function(e,i){var o=i.length+i.width,r=2*o;function s(){return f(t("group",{coordsize:r+" "+r,coordorigin:-o+" "+-o}),{width:r,height:r})}var a=-(i.width+i.length)*2+"px",l=f(s(),{position:"absolute",top:a,left:a}),u;function p(e,r,a){n(l,n(f(s(),{rotation:360/i.lines*e+"deg",left:~~r}),n(f(t("roundrect",{arcsize:i.corners}),{width:o,height:i.width,left:i.radius,top:-i.width>>1,filter:a}),t("fill",{color:d(i.color,e),opacity:i.opacity}),t("stroke",{opacity:0}))))}if(i.shadow)for(u=1;u<=i.lines;u++)p(u,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(u=1;u<=i.lines;u++)p(u);return n(e,l)};c.prototype.opacity=function(t,e,i,o){var n=t.firstChild;o=o.shadow&&o.lines||0;if(n&&e+o<n.childNodes.length){n=n.childNodes[e+o];n=n&&n.firstChild;n=n&&n.firstChild;if(n)n.opacity=i}}}var m=f(o("group"),{behavior:"url(#default#VML)"});if(!a(m,"transform")&&m.adj)h();else i=a(m,"animation");return c}); |
@ -0,0 +1,58 @@ |
|||||||
|
/** |
||||||
|
* @file |
||||||
|
* Triggers the display of a spinning icon when the form is submitted. |
||||||
|
*/ |
||||||
|
(function ($) { |
||||||
|
|
||||||
|
Drupal.behaviors.spinner = { |
||||||
|
attach: function(context, settings) { |
||||||
|
// Store what triggered the submit.
|
||||||
|
$('form').once('submit-resolver', function() { |
||||||
|
$(this).click(function(event) { |
||||||
|
$(this).data('clicked', $(event.target)); |
||||||
|
}); |
||||||
|
$(this).keypress(function(event) { |
||||||
|
// On enter the first submit button is assumed as is most often the
|
||||||
|
// case and this is part of the HTML 5 specification, although some
|
||||||
|
// Browsers may choose the button with the lowest tab-index.
|
||||||
|
if (event.which == 13) { |
||||||
|
$(this).data('clicked', $(':submit', this).first()); |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
for (var base in settings.spinner) { |
||||||
|
var id = '#' + base; |
||||||
|
$(id, context).once('spinner', function () { |
||||||
|
var spinner = new Spinner(settings.spinner[base].opts); |
||||||
|
$(id).parents('form').one('submit', function(event) { |
||||||
|
if ($(this).data('clicked').is(id)) { |
||||||
|
event.preventDefault(); |
||||||
|
// Add Message.
|
||||||
|
var message = $('<div/>').text(settings.spinner[base].message); |
||||||
|
$(id).after(message); |
||||||
|
// Make UI changes.
|
||||||
|
spinner.spin(this); |
||||||
|
$('#edit-next').hide(); |
||||||
|
$('#edit-prev').hide();
|
||||||
|
// Submit the form after a set timeout, this handles problems with
|
||||||
|
// safari, in that safari submit's immediately..
|
||||||
|
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||||
|
$(':submit').attr('disabled', 'disabled'); |
||||||
|
} |
||||||
|
setTimeout(function() { |
||||||
|
// Allow for the button to be clicked, then click it then
|
||||||
|
// prevent the default behavoir.
|
||||||
|
$(id).removeAttr('disabled') |
||||||
|
.click() |
||||||
|
.click(function(event) { |
||||||
|
event.preventDefault(); |
||||||
|
}); |
||||||
|
}, 500); |
||||||
|
} |
||||||
|
return true; |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
})(jQuery); |
@ -0,0 +1,160 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Tests to verify the cache headers we provide. |
||||||
|
*/ |
||||||
|
|
||||||
|
class IslandoraDatastreamCacheTestCase extends IslandoraWebTestCase { |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets info to display to describe this test. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::getInfo() |
||||||
|
*/ |
||||||
|
public static function getInfo() { |
||||||
|
return array( |
||||||
|
'name' => 'Datastream Cache Headers', |
||||||
|
'description' => 'Check our headers work as we expect them to.', |
||||||
|
'group' => 'Islandora', |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates an admin user and a connection to a fedora repository. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::setUp() |
||||||
|
*/ |
||||||
|
public function setUp() { |
||||||
|
parent::setUp(); |
||||||
|
$this->repository = $this->admin->repository; |
||||||
|
$this->purgeTestObjects(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Free any objects/resources created for this test. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::tearDown() |
||||||
|
*/ |
||||||
|
public function tearDown() { |
||||||
|
$this->purgeTestObjects(); |
||||||
|
parent::tearDown(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Purge any objects created by the test's in this class. |
||||||
|
*/ |
||||||
|
public function purgeTestObjects() { |
||||||
|
$objects = array( |
||||||
|
'test:test', |
||||||
|
); |
||||||
|
foreach ($objects as $object) { |
||||||
|
try { |
||||||
|
$object = $this->repository->getObject($object); |
||||||
|
$this->repository->purgeObject($object->id); |
||||||
|
} |
||||||
|
catch (Exception $e) { |
||||||
|
// Meh... Either it didn't exist or the purge failed. |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create our test object. |
||||||
|
*/ |
||||||
|
protected function createTestObject() { |
||||||
|
$object = $this->repository->constructObject('test:test'); |
||||||
|
$object->label = 'Test object'; |
||||||
|
$object->models = 'test:model'; |
||||||
|
$datastream = $object->constructDatastream('asdf', 'M'); |
||||||
|
$datastream->label = 'datastream of doom'; |
||||||
|
$datastream->mimetype = 'text/plain'; |
||||||
|
$datastream->content = 'And then things happened.'; |
||||||
|
$datastream->checksumType = 'SHA-1'; |
||||||
|
$object->ingestDatastream($datastream); |
||||||
|
$this->repository->ingestObject($object); |
||||||
|
return $object; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Test HTTP cache headers. |
||||||
|
*/ |
||||||
|
public function testCacheHeaders() { |
||||||
|
$object = $this->createTestObject(); |
||||||
|
$datastream = $object['asdf']; |
||||||
|
|
||||||
|
$user = $this->drupalCreateUser(array(ISLANDORA_VIEW_OBJECTS)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
|
||||||
|
// Test If-Modified-Since. |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Modified-Since: ' . $datastream->createdDate->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
)); |
||||||
|
$this->assertResponse(304); |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Modified-Since: ' . $datastream->createdDate->sub(new DateInterval('P1M'))->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
)); |
||||||
|
$this->assertResponse(200); |
||||||
|
|
||||||
|
// Test If-Unmodified-Since. |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Unmodified-Since: ' . $datastream->createdDate->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
)); |
||||||
|
$this->assertResponse(200); |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Unmodified-Since: ' . $datastream->createdDate->sub(new DateInterval('P1M'))->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
)); |
||||||
|
$this->assertResponse(412); |
||||||
|
|
||||||
|
// Test If-Match. |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
format_string('If-Match: "!checksum"', array( |
||||||
|
'!checksum' => $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(200); |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
format_string('If-Match: "!checksum"', array( |
||||||
|
'!checksum' => 'dont-match' . $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(412); |
||||||
|
|
||||||
|
// Test If-None-Match. |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
format_string('If-None-Match: "!checksum"', array( |
||||||
|
'!checksum' => $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(304); |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
format_string('If-None-Match: "!checksum"', array( |
||||||
|
'!checksum' => 'dont-match' . $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(200); |
||||||
|
|
||||||
|
// Test combination of If-None-Match and If-Modified-Since |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Modified-Since: ' . $datastream->createdDate->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
format_string('If-None-Match: "!checksum"', array( |
||||||
|
'!checksum' => $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(304); |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Modified-Since: ' . $datastream->createdDate->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
format_string('If-None-Match: "!checksum"', array( |
||||||
|
'!checksum' => 'dont-match' . $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(200); |
||||||
|
$result = $this->drupalGet("islandora/object/{$object->id}/datastream/{$datastream->id}/view", array(), array( |
||||||
|
'If-Modified-Since: ' . $datastream->createdDate->sub(new DateInterval('P1M'))->format('D, d M Y H:i:s \G\M\T'), |
||||||
|
format_string('If-None-Match: "!checksum"', array( |
||||||
|
'!checksum' => $datastream->checksum, |
||||||
|
)), |
||||||
|
)); |
||||||
|
$this->assertResponse(200); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,473 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Assertions for various datastream types. |
||||||
|
* |
||||||
|
* For a datastream validator to work correctly with IslandoraWebTestCase:: |
||||||
|
* validateDatastreams(), it needs to return an array of results, each entry of |
||||||
|
* which contains two values: first, TRUE or FALSE, depending on whether or not |
||||||
|
* that particular result passed or failed, and second, a string containing a |
||||||
|
* message to accompany the result. |
||||||
|
* |
||||||
|
* It also should contain three parameters, all of which may use any label, but |
||||||
|
* must be organized in the following order: |
||||||
|
* $object - an object that the datastream can be loaded from. |
||||||
|
* $datastream - a DSID to pull from $object. |
||||||
|
* $optional_params - a parameter for any data the function requires. |
||||||
|
* |
||||||
|
* When IslandoraWebTestCase::validateDatastreams() is called, it is passed an |
||||||
|
* array of datastreams, each of which is itself an array containing the DSID of |
||||||
|
* the datastream, the middle of the function name (image, pdf, tiff, etc.), and |
||||||
|
* (optional) data to be passed to that third parameter. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* A function to pass assertions to and receive results from. |
||||||
|
* |
||||||
|
* @param bool $assertion |
||||||
|
* The if/then statement to validate against. |
||||||
|
* @param array $results |
||||||
|
* An array of results to append the generated result to. |
||||||
|
* @param string $pass |
||||||
|
* A message to return if the assertion turns up true. |
||||||
|
* @param string $fail |
||||||
|
* An optional message to return if the assertion turns up false. |
||||||
|
* If left empty, the $pass message will be returned. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A result that can be made useful in the validation functions below. |
||||||
|
*/ |
||||||
|
function islandora_assert_valid($assertion, $results, $pass, $fail = NULL) { |
||||||
|
if ($assertion) { |
||||||
|
$result = array(TRUE, $pass); |
||||||
|
} |
||||||
|
else { |
||||||
|
if (isset($fail)) { |
||||||
|
$result = array(FALSE, $fail); |
||||||
|
} |
||||||
|
else { |
||||||
|
$result = array(FALSE, $pass); |
||||||
|
} |
||||||
|
} |
||||||
|
array_push($results, $result); |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Converts a hexidecimal string to an integer. |
||||||
|
* |
||||||
|
* This is useful for running checks on values that appear in the binary |
||||||
|
* of a datastream. Returns FALSE if the hex value contains non-hex characters |
||||||
|
* or if the string would not return a 16- or 32-bit formatted big-endian |
||||||
|
* signed integer. |
||||||
|
* |
||||||
|
* @param string $hex |
||||||
|
* The hexidecimal string. |
||||||
|
* |
||||||
|
* @return bool|int |
||||||
|
* FALSE on failure, or the integer on success. |
||||||
|
*/ |
||||||
|
function islandora_hex2int($hex) { |
||||||
|
|
||||||
|
// A couple of quick string checks. |
||||||
|
if (!ctype_xdigit($hex)) { |
||||||
|
drupal_set_message(t('String passed to islandora_hex2int() contains non-hexidecimal characters.'), 'error'); |
||||||
|
return FALSE; |
||||||
|
} |
||||||
|
if (!strlen($hex) === 4 || !strlen($hex) === 8) { |
||||||
|
drupal_set_message(t('String passed to islandora_hex2int() cannot create a 16- or 32-bit little-endian signed integer'), 'error'); |
||||||
|
return FALSE; |
||||||
|
} |
||||||
|
|
||||||
|
// The actual conversion. |
||||||
|
try { |
||||||
|
$reverse_hex = implode('', array_reverse(str_split($hex, 2))); |
||||||
|
$int = hexdec($reverse_hex); |
||||||
|
return $int; |
||||||
|
} |
||||||
|
catch (Exception $e) { |
||||||
|
throw new Exception('An error occurred during the conversion of hexidecimal to integer.', 0, $e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts that an object's given datastreams are common-type image files. |
||||||
|
* |
||||||
|
* Uses PHPGD to run the assertion check. This means that only certain kinds |
||||||
|
* of image files can be checked. Please check the documentation for the PHPGD |
||||||
|
* imagecreatefromstring() function to determine what filetypes are valid. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID to check that corresponds to a PHPGD-valid image datastream. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_image_datastream($object, $datastream) { |
||||||
|
$datastream_string = $object[$datastream]->content; |
||||||
|
$results = array(); |
||||||
|
$pass = "Image datastream {$datastream} is valid."; |
||||||
|
$fail = "Image datastream {$datastream} is either invalid or corrupt."; |
||||||
|
$results = islandora_assert_valid(imagecreatefromstring($datastream_string), $results, $pass, $fail); |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts the validity of any .tif/.tiff datastream. |
||||||
|
* |
||||||
|
* Does not use the islandora_assert_valid() function, as this is not a simple |
||||||
|
* true/false. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID to check that corresponds to a .tif/.tiff datastream. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_tiff_datastream($object, $datastream) { |
||||||
|
$datastream_string = $object[$datastream]->content; |
||||||
|
$datastream_header_hex = substr(bin2hex($datastream_string), 0, 8); |
||||||
|
$results = array(); |
||||||
|
if ($datastream_header_hex == "49492a00") { |
||||||
|
// In this case, the ingested TIFF is designated as using the "Intel |
||||||
|
// byte-order" (e.g. little-endian) by starting with the characters "II" |
||||||
|
// (repeated so that byte order does not yet need to be significant). |
||||||
|
// The number that follows is '42' in little-endian hex, a number of |
||||||
|
// 'deep philosophical significance' to the TIFF format creators. |
||||||
|
array_push($results, array(TRUE, "{$datastream} datastream asserts that it is a valid Intel-byte-orderded TIF/TIFF file.")); |
||||||
|
} |
||||||
|
elseif ($datastream_header_hex == "4d4d002a") { |
||||||
|
// In this case, the ingested TIFF is designated as using the "Motorola |
||||||
|
// byte-order" (e.g. big-endian) by starting with the characters "MM" |
||||||
|
// instead. 42 follows once again, this time in big-endian hex. |
||||||
|
array_push($results, array(TRUE, "{$datastream} datastream asserts that it is a valid Motorola-byte-ordered TIF/TIFF file.")); |
||||||
|
} |
||||||
|
else { |
||||||
|
array_push($results, array(FALSE, "{$datastream} datastream does not assert that it is a valid TIF/TIFF file.")); |
||||||
|
} |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts the validity of any .jp2 datastream. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID to check that corresponds to a .jp2 datastream. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_jp2_datastream($object, $datastream) { |
||||||
|
$datastream_hex = bin2hex($object[$datastream]->content); |
||||||
|
$results = array(); |
||||||
|
// JP2 files begin with an offset header at the second 32-bit integer, |
||||||
|
// 0x6A502020. This header is in all .jp2s, and we check for it here. |
||||||
|
$pass = "{$datastream} datastream begins correctly with the appropriate .jp2 header."; |
||||||
|
$fail = "{$datastream} datastream does not begin with the appropriate .jp2 header."; |
||||||
|
$results = islandora_assert_valid(substr($datastream_hex, 8, 8) == '6a502020', $results, $pass, $fail); |
||||||
|
// JP2 files have their codestream capped with a marker, 0xFFD9. We're |
||||||
|
// just checking for it here to see if the .jp2 encoder finished okay. |
||||||
|
$pass = "{$datastream} datastream ends correctly with the appropriate .jp2 marker."; |
||||||
|
$fail = "{$datastream} datastream does not end with a .jp2 marker; derivative generation was likely interrupted."; |
||||||
|
$results = islandora_assert_valid(substr($datastream_hex, strlen($datastream_hex) - 4, 4) == 'ffd9', $results, $pass, $fail); |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts the validity of any .pdf datastream. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID to check that corresponds to a .pdf datastream. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_pdf_datastream($object, $datastream) { |
||||||
|
$pdf = $object[$datastream]->content; |
||||||
|
$pdf_version = substr($pdf, 5, 3); |
||||||
|
$results = array(); |
||||||
|
$pass = "{$datastream} datastream asserts that it is a valid PDF file using PDF version {$pdf_version}"; |
||||||
|
$fail = "{$datastream} datastream binary header appears to be corrupt and missing a valid PDF signature."; |
||||||
|
$results = islandora_assert_valid(substr($pdf, 0, 5) == '%PDF-', $results, $pass, $fail); |
||||||
|
|
||||||
|
$pdf_streams = substr_count(bin2hex($pdf), '0a73747265616d0a'); |
||||||
|
$pass = "{$datastream} datastream reports the existence of {$pdf_streams} PDF streams. Note that an extremely low number could still indicate corruption."; |
||||||
|
$fail = "{$datastream} datastream contains zero PDF streams, and is likely not a PDF file."; |
||||||
|
$results = islandora_assert_valid($pdf_streams, $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream reports the existence of the closing 'EOF' tag required at the end of PDFs"; |
||||||
|
$fail = "{$datastream} datastream does not contain the closing 'EOF' tag. If this is the only PDF validation that failed, it is likely that derivative generation was interrupted."; |
||||||
|
$results = islandora_assert_valid(strpos(bin2hex($pdf), '0a2525454f460a'), $results, $pass, $fail); |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts that a string of text shows up inside a datastream. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID to check that corresponds to a datastream containing text. |
||||||
|
* @param array $text |
||||||
|
* An array of strings/the number of times it should appear in the datastream. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_text_datastream($object, $datastream, array $text) { |
||||||
|
$results = array(); |
||||||
|
$content = $object[$datastream]->content; |
||||||
|
$string_count = substr_count($content, $text[0]); |
||||||
|
$pass = "{$datastream} datastream contains the word(s) '{$text[0]}' repeated {$string_count} time(s) (expected: {$text[1]})."; |
||||||
|
$fail = "{$datastream} datastream contains the word(s) '{$text[0]}' repeated {$string_count} time(s) (expected: {$text[1]})."; |
||||||
|
$results = islandora_assert_valid($string_count == $text[1], $results, $pass, $fail); |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts the validity of any .wav datastraeam. |
||||||
|
* |
||||||
|
* WAV files contain a rigidly detailed header that contains all sorts of fun |
||||||
|
* information we can use to validate things against other things. So, we check |
||||||
|
* rigorously that the header contains properly constructed data by looking to |
||||||
|
* see if certain values are at their expected byte offset. We also compare |
||||||
|
* declared chunk sizes against actual sizes. If any of these are off, WAV |
||||||
|
* players will fail to function. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID to check that corresponds to a datastream generated via OCR or HOCR. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_wav_datastream($object, $datastream) { |
||||||
|
$results = array(); |
||||||
|
$wav = bin2hex($object['OBJ']->content); |
||||||
|
$wav_subchunk2size = islandora_hex2int(substr($wav, 80, 8)); |
||||||
|
$wav_samplerate = islandora_hex2int(substr($wav, 48, 8)); |
||||||
|
$wav_numchannels = islandora_hex2int(substr($wav, 44, 4)); |
||||||
|
$wav_bytespersample = islandora_hex2int(substr($wav, 68, 4)) / 8; |
||||||
|
$wav_numsamples = strlen(substr($wav, 88)) / $wav_numchannels / $wav_bytespersample / 2; |
||||||
|
$magic_number = str_split(substr($wav, 0, 24), 8); |
||||||
|
|
||||||
|
$pass = "Header of the {$datastream} datastream contains correct file signature"; |
||||||
|
$fail = "Header of the {$datastream} datastream contains corrupt file signature"; |
||||||
|
$results = islandora_assert_valid($magic_number[0] = '52494646' && $magic_number[2] = '57415645', $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream chunksize in WAV header is correct"; |
||||||
|
$fail = "{$datastream} datastream chunksize in WAV header does not match actual chunksize."; |
||||||
|
$results = islandora_assert_valid(islandora_hex2int(substr($wav, 8, 8)) === 36 + $wav_subchunk2size, $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream contains a 'fmt' subchunk."; |
||||||
|
$fail = "{$datastream} datastream is missing the required 'fmt' subchunk."; |
||||||
|
$results = islandora_assert_valid(substr($wav, 24, 8) === '666d7420', $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream byterate in the WAV header is correct."; |
||||||
|
$fail = "{$datastream} datastream byterate in the WAV header does not match actual calculated byterate."; |
||||||
|
$results = islandora_assert_valid(islandora_hex2int(substr($wav, 56, 8)) === $wav_samplerate * $wav_numchannels * $wav_bytespersample, $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream block alignment is set correctly."; |
||||||
|
$fail = "{$datastream} datastream block alignment is off."; |
||||||
|
$results = islandora_assert_valid(islandora_hex2int(substr($wav, 64, 4)) === $wav_numchannels * $wav_bytespersample, $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream contains 'data' subchunk."; |
||||||
|
$fail = "{$datastream} datastream is missing the 'data' subchunk."; |
||||||
|
$results = islandora_assert_valid(substr($wav, 72, 8) === '64617461', $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream 'data' chunk is the correct size."; |
||||||
|
$fail = "{$datastream} datastream 'data' chunk is sized incorrectly."; |
||||||
|
$results = islandora_assert_valid($wav_subchunk2size === $wav_numsamples * $wav_numchannels * $wav_bytespersample, $results, $pass, $fail); |
||||||
|
|
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Asserts the validity of any .mp3 datastream. |
||||||
|
* |
||||||
|
* Our default setup tries to create an MP3 using VBR, but we do some extra |
||||||
|
* checks in case someone turns that off. If the header contains the characters |
||||||
|
* 'Xing', it is flagged as VBR, and we can do an in-depth check on each of the |
||||||
|
* VBR settings. Otherwise, we look for the basic MP3 signature 'fffa' or 'fffb' |
||||||
|
* at the start of the binary. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID of a datastream corresponding to an mp3 file. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_mp3_datastream($object, $datastream) { |
||||||
|
$results = array(); |
||||||
|
$mp3 = bin2hex($object[$datastream]->content); |
||||||
|
$mp3_size = strlen($mp3) / 2; |
||||||
|
|
||||||
|
// Looks to see if VBR was set properly by LAME. If so, MATH TIME! |
||||||
|
if (strpos($mp3, '58696e67')) { |
||||||
|
$mp3_vbrheader = substr($mp3, strpos($mp3, '58696e67'), 240); |
||||||
|
|
||||||
|
// Check the field flags. VBR-formatted MP3 files contain a 32-bit |
||||||
|
// integer (stored as $mp3_flag_value) that is a combination of four |
||||||
|
// bits, each one indicating the on-off status of a VBR setting, via |
||||||
|
// logical OR. Rather than disassembling this value into individual |
||||||
|
// bits, we use the algorithm "if (binary_total+bit_value*2)/bit_value*2 |
||||||
|
// is greater than or equal to bit_value, that bit is turned on" to find |
||||||
|
// the status of each bit, so we know whether to offset the rest. |
||||||
|
$mp3_field_offset = array(0, 0, 0); |
||||||
|
$mp3_flag_value = hexdec(substr($mp3_vbrheader, 8, 8)); |
||||||
|
|
||||||
|
// We can't use the first flag, but we still need to offset the rest. |
||||||
|
if (($mp3_flag_value + 1) % 2 == 0) { |
||||||
|
$mp3_field_offset[0] += 8; |
||||||
|
$mp3_field_offset[1] += 8; |
||||||
|
$mp3_field_offset[2] += 8; |
||||||
|
} |
||||||
|
|
||||||
|
// The second flag leads us to filesize data, which we can verify. |
||||||
|
if (($mp3_flag_value + 4) % 4 > 1) { |
||||||
|
$mp3_field_bytes = hexdec(substr($mp3_vbrheader, $mp3_field_offset[0] + 16, 8)); |
||||||
|
$pass = "{$datastream} datastream reported filesize of {$mp3_size} bytes matches size field value of {$mp3_field_bytes}"; |
||||||
|
$fail = "{$datastream} datastream reported filesize of {$mp3_size} bytes does not match size field value of {$mp3_field_bytes}"; |
||||||
|
$results = islandora_assert_valid($mp3_size == $mp3_field_bytes, $results, $pass, $fail); |
||||||
|
$mp3_field_offset[1] += 8; |
||||||
|
$mp3_field_offset[2] += 8; |
||||||
|
} |
||||||
|
|
||||||
|
// We can't use the third flag for anything either. |
||||||
|
if (($mp3_flag_value + 8) % 8 > 3) { |
||||||
|
$mp3_field_offset[2] += 200; |
||||||
|
} |
||||||
|
|
||||||
|
// The fourth flag leads us to VBR quality data, which we can validate. |
||||||
|
if ($mp3_flag_value > 7) { |
||||||
|
$mp3_field_quality = hexdec(substr($mp3_vbrheader, $mp3_field_offset[2] + 16, 8)); |
||||||
|
$pass = "{$datastream} datastream reports valid VBR quality of {$mp3_field_quality} (expected: between 0-100)"; |
||||||
|
$fail = "{$datastream} datastream reports invalid VBR quality of {$mp3_field_quality} (expected: between 0-100)"; |
||||||
|
$results = islandora_assert_valid($mp3_field_quality <= 100 && $mp3_field_quality >= 0, $results, $pass, $fail); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Otherwise, just forget everything and check the file signature. |
||||||
|
elseif (strpos($mp3, '58696e67') == FALSE && substr($mp3, 0, 4) == 'fffa') { |
||||||
|
$results = array(array(TRUE, "{$datastream} datastream is encoded as a valid MPEG-1 Layer 3 file with CRC protection")); |
||||||
|
} |
||||||
|
elseif (strpos($mp3, '58696e67') == FALSE && substr($mp3, 0, 4) == 'fffb') { |
||||||
|
$results = array(array(TRUE, "{$datastream} datastream is encoded as a valid unprotected MPEG-1 Layer 3 file")); |
||||||
|
} |
||||||
|
else { |
||||||
|
$results = array(array(FALSE, "{$datastream} datastream is corrupt and does not identify as a valid MP3.")); |
||||||
|
} |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Attempts to validate an .mp4 datastream. |
||||||
|
* |
||||||
|
* MP4 files are a subset of the ISO file format specification, and as such need |
||||||
|
* to contain a 64-bit declaration of type within the first eight eight bytes of |
||||||
|
* the file. This declaration is comprised of the characters 'ftyp', followed by |
||||||
|
* a four-character filetype code. Below, we look for 'ftyp', and then pass the |
||||||
|
* filetype code to the test message. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID of a datastream corresponding to an mp4 file. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_mp4_datastream($object, $datastream) { |
||||||
|
$results = array(); |
||||||
|
$mp4 = $object[$datastream]->content; |
||||||
|
if (strpos($mp4, 'ftyp')) { |
||||||
|
$mp4_ftyp = substr(strpos($mp4, 'ftyp'), 4, 4); |
||||||
|
} |
||||||
|
$pass = "{$datastream} datastream asserts that it is a valid ISO-formatted video file using ftyp {$mp4_ftyp}"; |
||||||
|
$fail = "{$datastream} datastream is not a valid ISO-formatted video"; |
||||||
|
$results = islandora_assert_valid(strpos($mp4, 'ftyp'), $results, $pass, $fail); |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Attempts to validate an .ogg/ogv datastream using Vorbis and Theora encoding. |
||||||
|
* |
||||||
|
* OGG files are made up of several 'pages' of OGG data, each prefaced with an |
||||||
|
* OGG marker - the letters 'OggS'. The file header also contains information on |
||||||
|
* what encoders were used to create the file. Here, we're looking for at least |
||||||
|
* one OGG page, and confirming that the file asserts the Theora and Vorbis |
||||||
|
* codecs were used to create the file. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID of a datastream corresponding to an ogg file. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_ogg_datastream($object, $datastream) { |
||||||
|
$results = array(); |
||||||
|
$ogg = $object[$datastream]->content; |
||||||
|
$ogg_pages = substr_count($ogg, 'OggS'); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream asserts that it contains {$ogg_pages} Ogg pages (even a very small file should contain several)."; |
||||||
|
$fail = "{$datastream} datastream contains no Ogg pages."; |
||||||
|
$results = islandora_assert_valid(substr_count($ogg, 'OggS'), $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream asserts that it contains Theora-encoded video data."; |
||||||
|
$fail = "{$datastream} datastream contains no marker indicating the presence of Theora-encoded video data."; |
||||||
|
$results = islandora_assert_valid(substr_count($ogg, 'theora'), $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream asserts that it contains Vorbis-encoded audio data"; |
||||||
|
$fail = "{$datastream} datastream contains no marker indicating the presence of Vorbis-encoded audio data."; |
||||||
|
$results = islandora_assert_valid(substr_count($ogg, 'vorbis'), $results, $pass, $fail); |
||||||
|
|
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Attempts to validate an .mkv datastream. |
||||||
|
* |
||||||
|
* There's not much we can do to check an MKV file, since the format is really, |
||||||
|
* really loose. We do know a couple of things though - first, since MKV is an |
||||||
|
* EBML format, the first four characters will always be the same. Since they're |
||||||
|
* non-standard characters, we're looking at their hex values instead. And |
||||||
|
* second, we know that the file will contain the declaration 'matroska' soon |
||||||
|
* after. We could look for this in the binary, but we already have the hex- |
||||||
|
* translated version, so we just look for 'matroska' in hex. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* The PID of the object. |
||||||
|
* @param string $datastream |
||||||
|
* A DSID of a datastream corresponding to an MKV file. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* A series of TRUE(pass)/FALSE(fail) results paired with result messages. |
||||||
|
*/ |
||||||
|
function islandora_validate_mkv_datastream($object, $datastream) { |
||||||
|
$results = array(); |
||||||
|
$mkv = bin2hex($object[$datastream]->content); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream asserts that it is an EBML-formatted file"; |
||||||
|
$fail = "{$datastream} datastream is not an EBML-formatted file."; |
||||||
|
$results = islandora_assert_valid(substr($mkv, 0, 8) == '1a45dfa3', $results, $pass, $fail); |
||||||
|
|
||||||
|
$pass = "{$datastream} datastream asserts that its EBML DocType is Matroska"; |
||||||
|
$fail = "{$datastream} datastream does not contain a Matroska EBML DocType marker."; |
||||||
|
$results = islandora_assert_valid(substr_count($mkv, '6d6174726f736b61') == 1, $results, $pass, $fail); |
||||||
|
|
||||||
|
return $results; |
||||||
|
} |
@ -0,0 +1,198 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Tests that datastream versions code works as intended |
||||||
|
*/ |
||||||
|
|
||||||
|
class IslandoraDatastreamVersionTestCase extends IslandoraWebTestCase { |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets info to display to describe this test. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::getInfo() |
||||||
|
*/ |
||||||
|
public static function getInfo() { |
||||||
|
return array( |
||||||
|
'name' => 'Islandora Datastream Versions', |
||||||
|
'description' => 'Tests the functionality related to datastream versions in Islandora.', |
||||||
|
'group' => 'Islandora', |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create an object with many datastram versions. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::setUp() |
||||||
|
*/ |
||||||
|
public function setUp() { |
||||||
|
parent::setUp(); |
||||||
|
|
||||||
|
$this->pid = $this->randomName() . ":" . $this->randomName(); |
||||||
|
$tuque = islandora_get_tuque_connection(); |
||||||
|
$object = $tuque->repository->constructObject($this->pid); |
||||||
|
$object = $tuque->repository->ingestObject($object); |
||||||
|
$this->dsid = $this->randomName(); |
||||||
|
$ds = $object->constructDatastream($this->dsid); |
||||||
|
$ds->label = 'Test'; |
||||||
|
$ds->content = 'test'; |
||||||
|
$object->ingestDatastream($ds); |
||||||
|
|
||||||
|
// Create three versions. |
||||||
|
$ds->mimetype = 'application/pdf'; |
||||||
|
$ds->label = 'jaaaaa maaaan'; |
||||||
|
$ds->content = 'Tests... are the bests.'; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Free any objects/resources created for this test. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::tearDown() |
||||||
|
*/ |
||||||
|
public function tearDown() { |
||||||
|
$tuque = islandora_get_tuque_connection(); |
||||||
|
$tuque->repository->purgeObject($this->pid); |
||||||
|
|
||||||
|
parent::tearDown(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if the user can see datastream versions in the datastream table. |
||||||
|
*/ |
||||||
|
public function testSeeDatastreamVersions() { |
||||||
|
$user = $this->drupalCreateUser(array( |
||||||
|
'view fedora repository objects', |
||||||
|
'ingest fedora objects', |
||||||
|
'view old datastream versions', |
||||||
|
'add fedora datastreams', |
||||||
|
)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/manage/datastreams"); |
||||||
|
$this->assertLink($this->dsid); |
||||||
|
$this->assertLink("4"); |
||||||
|
$encoded_pid = urlencode($this->pid); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check that users without permission cannot see datastream versions. |
||||||
|
*/ |
||||||
|
public function testNotSeeDatastreamVersions() { |
||||||
|
$user = $this->drupalCreateUser(array( |
||||||
|
'view fedora repository objects', |
||||||
|
'ingest fedora objects', |
||||||
|
'add fedora datastreams', |
||||||
|
)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/manage/datastreams"); |
||||||
|
$this->assertLink($this->dsid); |
||||||
|
$this->assertNoLink("4"); |
||||||
|
$encoded_pid = urlencode($this->pid); |
||||||
|
$this->assertNoLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check that users without permission cannot see datastream version pages. |
||||||
|
*/ |
||||||
|
public function testDatastreamVersionPermissions() { |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version"); |
||||||
|
$this->assertResponse(403); |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/0/view"); |
||||||
|
$this->assertResponse(403); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check that the proper infomration is displayed on the ds version page. |
||||||
|
*/ |
||||||
|
public function testDatastreamVersionPage() { |
||||||
|
$user = $this->drupalCreateUser(array( |
||||||
|
'view old datastream versions', |
||||||
|
)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version"); |
||||||
|
$this->assertNoLink("Delete"); |
||||||
|
$this->assertText("text/xml"); |
||||||
|
$this->assertText("application/pdf"); |
||||||
|
$this->assertText("jaaaaa maaaan"); |
||||||
|
$this->assertText("Test"); |
||||||
|
|
||||||
|
$encoded_pid = urlencode($this->pid); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/0/view"); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/1/view"); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/2/view"); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/3/view"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Make sure the correct content is displayed for each datastream version. |
||||||
|
*/ |
||||||
|
public function testDatastreamVersionContent() { |
||||||
|
$user = $this->drupalCreateUser(array( |
||||||
|
'view old datastream versions', |
||||||
|
)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/3/view"); |
||||||
|
$content = $this->drupalGetContent(); |
||||||
|
if ($content != 'test') { |
||||||
|
$this->fail("Incorrect datastream content"); |
||||||
|
} |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/2/view"); |
||||||
|
$content = $this->drupalGetContent(); |
||||||
|
if ($content != 'test') { |
||||||
|
$this->fail("Incorrect datastream content"); |
||||||
|
} |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/1/view"); |
||||||
|
$content = $this->drupalGetContent(); |
||||||
|
if ($content != 'test') { |
||||||
|
$this->fail("Incorrect datastream content"); |
||||||
|
} |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/0/view"); |
||||||
|
$content = $this->drupalGetContent(); |
||||||
|
if ($content != 'Tests... are the bests.') { |
||||||
|
$this->fail("Incorrect datastream content"); |
||||||
|
} |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/5/view"); |
||||||
|
$this->assertResponse(404); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Make sure you can delete datastream versions. |
||||||
|
*/ |
||||||
|
public function testDatastreamVersionDelete() { |
||||||
|
$user = $this->drupalCreateUser(array( |
||||||
|
'view old datastream versions', |
||||||
|
'delete fedora objects and datastreams', |
||||||
|
)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version"); |
||||||
|
$this->assertLink("delete"); |
||||||
|
$this->assertText('text/xml'); |
||||||
|
|
||||||
|
$encoded_pid = urlencode($this->pid); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/0/delete"); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/1/delete"); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/2/delete"); |
||||||
|
$this->assertLinkByHref("islandora/object/$encoded_pid/datastream/{$this->dsid}/version/3/delete"); |
||||||
|
|
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/3/delete"); |
||||||
|
$this->drupalPost(NULL, array(), t('Delete')); |
||||||
|
$this->assertNoText('text/xml'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Make sure you can't delete versions that don't exist/have only 1 version. |
||||||
|
*/ |
||||||
|
public function testDatastreamVersionDeleteEdgeCase() { |
||||||
|
$user = $this->drupalCreateUser(array( |
||||||
|
'view old datastream versions', |
||||||
|
'delete fedora objects and datastreams', |
||||||
|
)); |
||||||
|
$this->drupalLogin($user); |
||||||
|
|
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/{$this->dsid}/version/6/delete"); |
||||||
|
$this->assertResponse(404); |
||||||
|
|
||||||
|
$this->drupalGet("islandora/object/{$this->pid}/datastream/DC/version/0/delete"); |
||||||
|
$this->assertResponse(404); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,296 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Tests to see if the hooks get called when appropriate. |
||||||
|
* |
||||||
|
* In the test module 'islandora_derivatives_test' there are implementations |
||||||
|
* of hooks being tested. These implementations modifies the session, and |
||||||
|
* that's how we test if the hook gets called. |
||||||
|
* |
||||||
|
* To make sense of these tests reference islandora_derivatives_test.module. |
||||||
|
*/ |
||||||
|
|
||||||
|
class IslandoraDerivativesTestCase extends IslandoraWebTestCase { |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets info to display to describe this test. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::getInfo() |
||||||
|
*/ |
||||||
|
public static function getInfo() { |
||||||
|
return array( |
||||||
|
'name' => 'Islandora Derivative Generation', |
||||||
|
'description' => 'Ensure that the derivative generation hooks return appropriate results.', |
||||||
|
'group' => 'Islandora', |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates an admin user and a connection to a fedora repository. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::setUp() |
||||||
|
*/ |
||||||
|
public function setUp() { |
||||||
|
parent::setUp( |
||||||
|
array( |
||||||
|
'islandora_derivatives_test', |
||||||
|
) |
||||||
|
); |
||||||
|
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora'); |
||||||
|
$this->connection = new RepositoryConnection($url, $this->admin->name, $this->admin->pass); |
||||||
|
$this->connection->reuseConnection = TRUE; |
||||||
|
$this->api = new FedoraApi($this->connection); |
||||||
|
$this->cache = new SimpleCache(); |
||||||
|
$this->repository = new FedoraRepository($this->api, $this->cache); |
||||||
|
$this->pid = $this->randomName() . ":" . $this->randomName(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Free any objects/resources created for this test. |
||||||
|
* |
||||||
|
* @see IslandoraWebTestCase::tearDown() |
||||||
|
*/ |
||||||
|
public function tearDown() { |
||||||
|
$tuque = islandora_get_tuque_connection(); |
||||||
|
parent::tearDown(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests that the islandora_islandora_object_ingested hook gets fired. |
||||||
|
*/ |
||||||
|
public function testDerivativeOnIngest() { |
||||||
|
global $_islandora_derivative_test_ingest_method; |
||||||
|
$_islandora_derivative_test_ingest_method = 'modifyDatastream'; |
||||||
|
$tuque = islandora_get_tuque_connection(); |
||||||
|
$object = $tuque->repository->constructObject($this->pid); |
||||||
|
$object->models = array( |
||||||
|
'some:cmodel', |
||||||
|
); |
||||||
|
$dsid = 'OBJ'; |
||||||
|
$ds = $object->constructDatastream($dsid); |
||||||
|
$ds->label = 'Test'; |
||||||
|
$ds->content = 'test'; |
||||||
|
$object->ingestDatastream($ds); |
||||||
|
$tuque->repository->ingestObject($object); |
||||||
|
$this->assertDatastreams($object, array( |
||||||
|
'RELS-EXT', |
||||||
|
'DC', |
||||||
|
'OBJ', |
||||||
|
'DERIV', |
||||||
|
'NOSOURCE', |
||||||
|
)); |
||||||
|
$this->assertEqual('ingestDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "ingestDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); |
||||||
|
$this->assertEqual('test some string', $object['DERIV']->content, 'The expected content of the DERIV datastream is "test some string", got "' . $object['DERIV']->content . '".'); |
||||||
|
$this->assertEqual('NOSOURCE', $object['NOSOURCE']->content, 'The expected content of the NOSOURCE datastream is "NOSOURCE", got "' . $object['NOSOURCE']->content . '".'); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests the ingest method when when forcing on existing datastreams. |
||||||
|
*/ |
||||||
|
public function testDerivativeOnForceExistingDatastream() { |
||||||
|
global $_islandora_derivative_test_ingest_method; |
||||||
|
$_islandora_derivative_test_ingest_method = 'ingestDatastream'; |
||||||
|
$object = $this->constructBaseObject(); |
||||||
|
$object = $this->constructDERIVDatastream($object); |
||||||
|
$this->constructNOSOURCEDatastream($object); |
||||||
|
$islandora_object = islandora_object_load($this->pid); |
||||||
|
islandora_do_derivatives($islandora_object, array( |
||||||
|
'force' => TRUE, |
||||||
|
)); |
||||||
|
$this->assertEqual('modifyDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "modifyDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); |
||||||
|
$this->assertEqual('FORCEFULLY APPENDING CONTENT TO test', $islandora_object['DERIV']->content, 'The expected content of the DERIV datastream is "FORCEFULLY APPENDING CONTENT TO test", got "' . $islandora_object['DERIV']->content . '".'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests the ingest method when forcing on non-existing datastreams. |
||||||
|
*/ |
||||||
|
public function testDerivativeOnForceNonExistingDatastream() { |
||||||
|
global $_islandora_derivative_test_ingest_method; |
||||||
|
$_islandora_derivative_test_ingest_method = 'modifyDatastream'; |
||||||
|
$this->constructBaseObject(); |
||||||
|
$object = islandora_object_load($this->pid); |
||||||
|
islandora_do_derivatives($object, array( |
||||||
|
'force' => TRUE, |
||||||
|
)); |
||||||
|
$this->assertEqual('ingestDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "ingestDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); |
||||||
|
$this->assertEqual('test some string', $object['DERIV']->content, 'The expected content of the DERIV datastream is "test some string", got "' . $object['DERIV']->content . '".'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests the islandora_datastream_modified hook when there are existing DSes. |
||||||
|
*/ |
||||||
|
public function testDerivativeOnModifyExistingDatastream() { |
||||||
|
global $_islandora_derivative_test_ingest_method; |
||||||
|
$_islandora_derivative_test_ingest_method = 'ingestDatastream'; |
||||||
|
$object = $this->constructBaseObject(); |
||||||
|
$this->constructDERIVDatastream($object); |
||||||
|
// Need to do this as Tuque caches. |
||||||
|
$connection = islandora_get_tuque_connection(); |
||||||
|
$connection->cache->resetCache(); |
||||||
|
$islandora_object = islandora_object_load($this->pid); |
||||||
|
$changed_content = 'islandora beast'; |
||||||
|
$islandora_object['OBJ']->content = $changed_content; |
||||||
|
$this->assertEqual('modifyDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "modifyDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); |
||||||
|
$this->assertEqual('FORCEFULLY APPENDING CONTENT TO ' . $changed_content, $islandora_object['DERIV']->content, 'The expected content of the DERIV datastream is "FORCEFULLY APPENDING CONTENT TO islandora beast", got "' . $islandora_object['DERIV']->content . '".'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests islandora_datastream_modified hook when there are no existing DSes. |
||||||
|
*/ |
||||||
|
public function testDerivativeOnModifyNonExistingDatastream() { |
||||||
|
global $_islandora_derivative_test_ingest_method; |
||||||
|
$_islandora_derivative_test_ingest_method = 'modifyDatastream'; |
||||||
|
$this->constructBaseObject(); |
||||||
|
// Need to do this as Tuque caches. |
||||||
|
$connection = islandora_get_tuque_connection(); |
||||||
|
$connection->cache->resetCache(); |
||||||
|
$islandora_object = islandora_object_load($this->pid); |
||||||
|
$changed_content = 'islandora beast'; |
||||||
|
$islandora_object['OBJ']->content = $changed_content; |
||||||
|
$this->assertEqual('ingestDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "ingestDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); |
||||||
|
$this->assertEqual($changed_content . ' some string', $islandora_object['DERIV']->content, 'The expected content of the DERIV datastream is "islandora beast string", got "' . $islandora_object['DERIV']->content . '".'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests derivative hook filtering based upon source_dsid. |
||||||
|
*/ |
||||||
|
public function testDerivativeFilteringOnSourceDSID() { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
$_islandora_derivative_test_derivative_functions = array(); |
||||||
|
$this->constructBaseObject(); |
||||||
|
$object = islandora_object_load($this->pid); |
||||||
|
islandora_do_derivatives($object, array( |
||||||
|
'source_dsid' => 'OBJ', |
||||||
|
)); |
||||||
|
$this->assertEqual(1, count($_islandora_derivative_test_derivative_functions), 'Expected 1 derivative function for the source_dsid of "OBJ", got ' . count($_islandora_derivative_test_derivative_functions) . '.'); |
||||||
|
$called_function = (string) reset($_islandora_derivative_test_derivative_functions); |
||||||
|
$this->assertEqual('islandora_derivatives_test_create_deriv_datastream', $called_function, 'Expected derivative function is "islandora_derivatives_test_create_deriv_datastream", got "' . $called_function . '".'); |
||||||
|
|
||||||
|
// Reset the derivative functions array as we are going to use it again. |
||||||
|
$_islandora_derivative_test_derivative_functions = array(); |
||||||
|
islandora_do_derivatives($object, array( |
||||||
|
'source_dsid' => 'SOMEWEIRDDATASTREAM', |
||||||
|
)); |
||||||
|
$this->assertEqual(1, count($_islandora_derivative_test_derivative_functions), 'Expected 1 derivative function for the source_dsid of "SOMEWEIRDDATASTREAM", got ' . count($_islandora_derivative_test_derivative_functions) . '.'); |
||||||
|
$called_function = (string) reset($_islandora_derivative_test_derivative_functions); |
||||||
|
$this->assertEqual('islandora_derivatives_test_create_some_weird_datastream', $called_function, 'Expected derivative function is "islandora_derivatives_test_create_some_weird_datastream", got "' . $called_function . '".'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests that only functions were the source_dsid is NULL are fired. |
||||||
|
*/ |
||||||
|
public function testNULLSourceDSID() { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
$_islandora_derivative_test_derivative_functions = array(); |
||||||
|
$this->constructBaseObject(); |
||||||
|
$object = islandora_object_load($this->pid); |
||||||
|
islandora_do_derivatives($object, array( |
||||||
|
'source_dsid' => NULL, |
||||||
|
)); |
||||||
|
$this->assertDatastreams($object, array( |
||||||
|
'DC', |
||||||
|
'RELS-EXT', |
||||||
|
'OBJ', |
||||||
|
'NOSOURCE', |
||||||
|
)); |
||||||
|
$this->assertEqual(1, count($_islandora_derivative_test_derivative_functions), 'Expected 1 derivative function for the source_dsid of "NULL", got ' . count($_islandora_derivative_test_derivative_functions) . '.'); |
||||||
|
$called_function = (string) reset($_islandora_derivative_test_derivative_functions); |
||||||
|
$this->assertEqual('islandora_derivatives_test_create_nosource_datastream', $called_function, 'Expected derivative function is "islandora_derivatives_test_create_nosource_datastream", got "' . $called_function . '".'); |
||||||
|
$this->assertEqual('NOSOURCE', $object['NOSOURCE']->content, 'The expected content of the NOSOURCE datastream is "NOSOURCE", got "' . $object['NOSOURCE']->content . '".'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests that when no source_dsid all derivative functions are called. |
||||||
|
*/ |
||||||
|
public function testNoSourceDSIDNoForce() { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
$_islandora_derivative_test_derivative_functions = array(); |
||||||
|
$this->constructBaseObject(); |
||||||
|
$object = islandora_object_load($this->pid); |
||||||
|
islandora_do_derivatives($object, array()); |
||||||
|
$this->assertDatastreams($object, array( |
||||||
|
'DC', |
||||||
|
'RELS-EXT', |
||||||
|
'OBJ', |
||||||
|
'DERIV', |
||||||
|
'NOSOURCE', |
||||||
|
)); |
||||||
|
$this->assertEqual(3, count($_islandora_derivative_test_derivative_functions), 'Expected 3 derivative functions when there is no source_dsid, got ' . count($_islandora_derivative_test_derivative_functions) . '.'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests that when no source_dsid all derivative functions are called. |
||||||
|
*/ |
||||||
|
public function testNoSourceDSIDForce() { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
$_islandora_derivative_test_derivative_functions = array(); |
||||||
|
$this->constructBaseObject(); |
||||||
|
$object = islandora_object_load($this->pid); |
||||||
|
islandora_do_derivatives($object, array( |
||||||
|
'force' => TRUE, |
||||||
|
)); |
||||||
|
$this->assertDatastreams($object, array( |
||||||
|
'DC', |
||||||
|
'RELS-EXT', |
||||||
|
'OBJ', |
||||||
|
'DERIV', |
||||||
|
'NOSOURCE', |
||||||
|
)); |
||||||
|
$this->assertEqual(3, count($_islandora_derivative_test_derivative_functions), 'Expected 3 derivative functions when there is no source_dsid, got ' . count($_islandora_derivative_test_derivative_functions) . '.'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper function that will construct a base object. |
||||||
|
*/ |
||||||
|
public function constructBaseObject() { |
||||||
|
$object = $this->repository->constructObject($this->pid); |
||||||
|
$object->models = array( |
||||||
|
'some:cmodel', |
||||||
|
); |
||||||
|
$dsid = 'OBJ'; |
||||||
|
$ds = $object->constructDatastream($dsid); |
||||||
|
$ds->label = 'Test'; |
||||||
|
$ds->content = 'test'; |
||||||
|
$object->ingestDatastream($ds); |
||||||
|
$this->repository->ingestObject($object); |
||||||
|
return $object; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper function to construct the DERIV datastream without firing hooks. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a FedoraObject. |
||||||
|
* |
||||||
|
* @return AbstractObject |
||||||
|
* The modified AbstractObject. |
||||||
|
*/ |
||||||
|
public function constructDERIVDatastream(AbstractObject $object) { |
||||||
|
$dsid = 'DERIV'; |
||||||
|
$ds = $object->constructDatastream($dsid); |
||||||
|
$ds->label = 'Test'; |
||||||
|
$ds->content = 'test some string'; |
||||||
|
$object->ingestDatastream($ds); |
||||||
|
return $object; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper function to construct the NOSOURCE datastream without firing hooks. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a FedoraObject. |
||||||
|
* |
||||||
|
* @return AbstractObject |
||||||
|
* The modified AbstractObject. |
||||||
|
*/ |
||||||
|
public function constructNOSOURCEDatastream(AbstractObject $object) { |
||||||
|
$dsid = 'NOSOURCE'; |
||||||
|
$ds = $object->constructDatastream($dsid); |
||||||
|
$ds->label = 'Test'; |
||||||
|
$ds->content = 'NOSOURCE'; |
||||||
|
$object->ingestDatastream($ds); |
||||||
|
return $object; |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 2.9 MiB |
@ -0,0 +1,7 @@ |
|||||||
|
name = Islandora Derivatives Generation testing |
||||||
|
description = Tests derivative generation hooks. Do not enable. |
||||||
|
core = 7.x |
||||||
|
package = Testing |
||||||
|
hidden = TRUE |
||||||
|
files[] = islandora_derivatives_test.module |
||||||
|
dependencies[] = islandora |
@ -0,0 +1,202 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* Tests for derivative generation. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Implements hook_islandora_CMODEL_PID_derivative(). |
||||||
|
*/ |
||||||
|
function islandora_derivatives_test_some_cmodel_islandora_derivative() { |
||||||
|
return array( |
||||||
|
array( |
||||||
|
'source_dsid' => 'OBJ', |
||||||
|
'destination_dsid' => 'DERIV', |
||||||
|
'weight' => '0', |
||||||
|
'function' => array( |
||||||
|
'islandora_derivatives_test_create_deriv_datastream', |
||||||
|
), |
||||||
|
), |
||||||
|
array( |
||||||
|
'source_dsid' => 'SOMEWEIRDDATASTREAM', |
||||||
|
'destination_dsid' => 'STANLEY', |
||||||
|
'weight' => '-1', |
||||||
|
'function' => array( |
||||||
|
'islandora_derivatives_test_create_some_weird_datastream', |
||||||
|
), |
||||||
|
), |
||||||
|
array( |
||||||
|
'source_dsid' => NULL, |
||||||
|
'destination_dsid' => 'NOSOURCE', |
||||||
|
'weight' => '-3', |
||||||
|
'function' => array( |
||||||
|
'islandora_derivatives_test_create_nosource_datastream', |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates the DERIV datastream for use in testing. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a Fedora object. |
||||||
|
* @param bool $force |
||||||
|
* Whether or not derivative generation is to be forced. |
||||||
|
* @return array |
||||||
|
* An array detailing the success of the operation. |
||||||
|
* |
||||||
|
* @see hook_islandora_derivative() |
||||||
|
*/ |
||||||
|
function islandora_derivatives_test_create_deriv_datastream(AbstractObject $object, $force = FALSE) { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
$_islandora_derivative_test_derivative_functions[] = 'islandora_derivatives_test_create_deriv_datastream'; |
||||||
|
$return = ''; |
||||||
|
if (!isset($object['DERIV']) || (isset($object['DERIV']) && $force === TRUE)) { |
||||||
|
if ($force !== TRUE || !isset($object['DERIV'])) { |
||||||
|
$deriv_string = $object['OBJ']->content . ' some string'; |
||||||
|
} |
||||||
|
else { |
||||||
|
$deriv_string = "FORCEFULLY APPENDING CONTENT TO " . $object['OBJ']->content; |
||||||
|
} |
||||||
|
$added_successfully = islandora_derivatives_test_add_datastream($object, 'DERIV', $deriv_string); |
||||||
|
if ($added_successfully !== TRUE) { |
||||||
|
$return = islandora_derivatives_test_failed_adding($added_successfully); |
||||||
|
} |
||||||
|
else { |
||||||
|
$return = array( |
||||||
|
'success' => TRUE, |
||||||
|
'messages' => array( |
||||||
|
array( |
||||||
|
'message' => t('The DERIV datastream was added successfully for @pid!'), |
||||||
|
'message_sub' => array('@pid' => $object->id), |
||||||
|
'type' => 'dsm', |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
return $return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Stub function that used only for datastream filtering counts. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a Fedora object. |
||||||
|
* @param bool $force |
||||||
|
* Whether the derivatives are being forcefully generated or not. |
||||||
|
*/ |
||||||
|
function islandora_derivatives_test_create_some_weird_datastream(AbstractObject $object, $force = FALSE) { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
// Add to the global that we got to this function. |
||||||
|
$_islandora_derivative_test_derivative_functions[] = 'islandora_derivatives_test_create_some_weird_datastream'; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates the NOSOURCE datastream for use in testing. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a Fedora object. |
||||||
|
* @param bool $force |
||||||
|
* Whether or not derivative generation is to be forced. |
||||||
|
* @return array |
||||||
|
* An array detailing the success of the operation. |
||||||
|
* |
||||||
|
* @see hook_islandora_derivative() |
||||||
|
*/ |
||||||
|
function islandora_derivatives_test_create_nosource_datastream(AbstractObject $object, $force = FALSE) { |
||||||
|
global $_islandora_derivative_test_derivative_functions; |
||||||
|
$_islandora_derivative_test_derivative_functions[] = 'islandora_derivatives_test_create_nosource_datastream'; |
||||||
|
$return = ''; |
||||||
|
if (!isset($object['NOSOURCE']) || (isset($object['NOSOURCE']) && $force === TRUE)) { |
||||||
|
if ($force !== TRUE || !isset($object['NOSOURCE'])) { |
||||||
|
$deriv_string = 'NOSOURCE'; |
||||||
|
} |
||||||
|
else { |
||||||
|
$deriv_string = "FORCEFULLY APPENDING CONTENT TO " . $object['NOSOURCE']->content; |
||||||
|
} |
||||||
|
$added_successfully = islandora_derivatives_test_add_datastream($object, 'NOSOURCE', $deriv_string); |
||||||
|
if ($added_successfully !== TRUE) { |
||||||
|
$return = islandora_derivatives_test_failed_adding($added_successfully); |
||||||
|
} |
||||||
|
else { |
||||||
|
$return = array( |
||||||
|
'success' => TRUE, |
||||||
|
'messages' => array( |
||||||
|
array( |
||||||
|
'message' => t('The DERIV datastream was added successfully for @pid!'), |
||||||
|
'message_sub' => array('@pid' => $object->id), |
||||||
|
'type' => 'dsm', |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
return $return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper function that adds/modifies the datastream to the object in testing. |
||||||
|
* |
||||||
|
* @param AbstractObject $object |
||||||
|
* An AbstractObject representing a Fedora object. |
||||||
|
* @param string $dsid |
||||||
|
* The datastream id for which we are adding/modifying. |
||||||
|
* @param string $deriv_string |
||||||
|
* The content of the datastream we are adding. |
||||||
|
* |
||||||
|
* @return bool|string |
||||||
|
* A bool if the operation was successfully, the error message otherwise. |
||||||
|
*/ |
||||||
|
function islandora_derivatives_test_add_datastream(AbstractObject $object, $dsid, $deriv_string) { |
||||||
|
global $_islandora_derivative_test_ingest_method; |
||||||
|
try { |
||||||
|
$ingest = !isset($object[$dsid]); |
||||||
|
if ($ingest) { |
||||||
|
$ds = $object->constructDatastream($dsid, 'M'); |
||||||
|
$ds->label = $dsid; |
||||||
|
} |
||||||
|
else { |
||||||
|
$ds = $object[$dsid]; |
||||||
|
} |
||||||
|
$ds->content = $deriv_string; |
||||||
|
if ($ingest) { |
||||||
|
$_islandora_derivative_test_ingest_method = 'ingestDatastream'; |
||||||
|
$object->ingestDatastream($ds); |
||||||
|
} |
||||||
|
else { |
||||||
|
$_islandora_derivative_test_ingest_method = 'modifyDatastream'; |
||||||
|
} |
||||||
|
return TRUE; |
||||||
|
} |
||||||
|
catch (exception $e) { |
||||||
|
$message = $e->getMessage(); |
||||||
|
return $message; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a message if we failed to add a derivative. |
||||||
|
* |
||||||
|
* @see hook_islandora_derivative() |
||||||
|
* |
||||||
|
* @param string $message |
||||||
|
* The error message to be returned back. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
* An array describing the outcome of our failure. |
||||||
|
*/ |
||||||
|
function islandora_derivatives_test_failed_adding($message) { |
||||||
|
return array( |
||||||
|
'success' => FALSE, |
||||||
|
'messages' => array( |
||||||
|
array( |
||||||
|
'message' => $message, |
||||||
|
'type' => 'watchdog', |
||||||
|
'severity' => WATCHDOG_ERROR, |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @file |
||||||
|
* This is the template file for the Dublin Core metadata description. |
||||||
|
* |
||||||
|
* Available variables: |
||||||
|
* - $islandora_object: The Islandora object rendered in this template file |
||||||
|
* $dc_array: The DC datastream object values as a sanitized array. This |
||||||
|
* includes label, value and class name. |
||||||
|
* |
||||||
|
* @see template_preprocess_islandora_dublin_core_description() |
||||||
|
* @see theme_islandora_dublin_core_description() |
||||||
|
*/ |
||||||
|
?> |
||||||
|
<div class="islandora-metadata-sidebar"> |
||||||
|
<?php if (!empty($dc_array['dc:description']['value'])): ?> |
||||||
|
<h2><?php print $dc_array['dc:description']['label']; ?></h2>
|
||||||
|
<p property="description"><?php print $dc_array['dc:description']['value']; ?></p>
|
||||||
|
<?php endif; ?> |
||||||
|
</div> |
@ -0,0 +1,33 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @file |
||||||
|
* This is the template file for the object page for large image |
||||||
|
* |
||||||
|
* Available variables: |
||||||
|
* - $islandora_object: The Islandora object rendered in this template file |
||||||
|
* - $islandora_dublin_core: The DC datastream object |
||||||
|
* - $dc_array: The DC datastream object values as a sanitized array. This |
||||||
|
* includes label, value and class name. |
||||||
|
* - $islandora_object_label: The sanitized object label. |
||||||
|
* |
||||||
|
* @see template_preprocess_islandora_dublin_core_display() |
||||||
|
* @see theme_islandora_dublin_core_display() |
||||||
|
*/ |
||||||
|
?> |
||||||
|
<fieldset <?php $print ? print('class="islandora islandora-metadata"') : print('class="islandora islandora-metadata collapsible collapsed"');?>>
|
||||||
|
<legend><span class="fieldset-legend"><?php print t('Details'); ?></span></legend>
|
||||||
|
<div class="fieldset-wrapper"> |
||||||
|
<dl xmlns:dcterms="http://purl.org/dc/terms/" class="islandora-inline-metadata islandora-metadata-fields"> |
||||||
|
<?php $row_field = 0; ?> |
||||||
|
<?php foreach($dc_array as $key => $value): ?> |
||||||
|
<dt property="<?php print $value['dcterms']; ?>" content="<?php print filter_xss($value['value']); ?>" class="<?php print $value['class']; ?><?php print $row_field == 0 ? ' first' : ''; ?>">
|
||||||
|
<?php print filter_xss($value['label']); ?> |
||||||
|
</dt> |
||||||
|
<dd class="<?php print $value['class']; ?><?php print $row_field == 0 ? ' first' : ''; ?>">
|
||||||
|
<?php print filter_xss($value['value']); ?> |
||||||
|
</dd> |
||||||
|
<?php $row_field++; ?> |
||||||
|
<?php endforeach; ?> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</fieldset> |
@ -0,0 +1,18 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* The default view to theme an image of an object. |
||||||
|
* |
||||||
|
* This view is passed into 'islandora-object-print' theme file |
||||||
|
* and is rendred as an image. Allows for seperate theming of image |
||||||
|
* and metadata. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
?> |
||||||
|
<?php if (isset($islandora_content)): ?> |
||||||
|
<div> |
||||||
|
<?php print $islandora_content; ?> |
||||||
|
</div> |
||||||
|
<?php endif; ?> |
@ -0,0 +1,14 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* @file |
||||||
|
* The default view to print objects. |
||||||
|
* |
||||||
|
*/ |
||||||
|
?> |
||||||
|
<div> |
||||||
|
<div> |
||||||
|
<?php print $islandora_content; ?> |
||||||
|
</div> |
||||||
|
<?php print $metadata; ?> |
||||||
|
</div> |
Loading…
Reference in new issue