Browse Source

Merge branch '7.x' into 7.x-add-ds-history

pull/374/head
jonathangreen 11 years ago
parent
commit
be4b33cf14
  1. 3
      .travis.yml
  2. 225
      includes/admin.form.inc
  3. 1
      includes/dublin_core.inc
  4. 5
      includes/ingest.form.inc
  5. 199
      includes/solution_packs.inc
  6. 30
      includes/tuque_wrapper.inc
  7. 45
      includes/utilities.inc
  8. 142
      islandora.drush.inc
  9. 30
      islandora.module
  10. 30
      tests/hooks.test
  11. 6
      tests/scripts/travis_setup.sh
  12. 13
      xml/strip_newlines_and_whitespace.xsl

3
.travis.yml

@ -4,9 +4,10 @@ php:
- 5.4
branches:
only:
- 7.x
- /^7.x/
env:
- FEDORA_VERSION="3.5"
- FEDORA_VERSION="3.6.2"
before_install:
- export ISLANDORA_DIR=$TRAVIS_BUILD_DIR
- $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh

225
includes/admin.form.inc

@ -19,139 +19,111 @@
function islandora_repository_admin(array $form, array &$form_state) {
module_load_include('inc', 'islandora', 'includes/utilities');
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
$url = islandora_system_settings_form_default_value('islandora_base_url', 'http://localhost:8080/fedora', $form_state);
$restrict_namespaces = islandora_system_settings_form_default_value('islandora_namespace_restriction_enforced', FALSE, $form_state);
$confirmation_message = islandora_admin_settings_form_repository_access_message($url);
$form = array(
'islandora_tabs' => array(
'#type' => 'vertical_tabs',
'islandora_general' => array(
'#type' => 'fieldset',
'#title' => t('General Configuarion'),
'wrapper' => array(
'#prefix' => '<div id="islandora-url">',
'#suffix' => '</div>',
'#type' => 'markup',
'islandora_base_url' => array(
'#type' => 'textfield',
'#title' => t('Fedora base URL'),
'#default_value' => variable_get('islandora_base_url', 'http://localhost:8080/fedora'),
'#description' => t('The URL to use for REST connections <br/> !confirmation_message', array(
'!confirmation_message' => $confirmation_message)),
'#required' => TRUE,
'#ajax' => array(
'callback' => 'islandora_update_url_div',
'wrapper' => 'islandora-url',
'effect' => 'fade',
'event' => 'blur',
'progress' => array('type' => 'throbber'),
),
),
),
'islandora_repository_pid' => array(
'#type' => 'textfield',
'#title' => t('Root Collection PID'),
'#default_value' => variable_get('islandora_repository_pid', 'islandora:root'),
'#description' => t('The PID of the Root Collection Object'),
'#required' => TRUE,
),
),
'islandora_namespace' => array(
'#type' => 'fieldset',
'#title' => t('Namespaces'),
'islandora_namespace_restriction_enforced' => array(
'#type' => 'checkbox',
'#title' => t('Enforce namespace restrictions'),
'#description' => t("Allow administrator to restrict user's access to the PID namepaces listed below"),
'#default_value' => $restrict_namespaces,
),
'islandora_pids_allowed' => array(
'#type' => 'textfield',
'#title' => t('PID namespaces allowed in this Drupal install'),
'#description' => t('A list of PID namespaces, separated by spaces, that users are permitted to access from this Drupal installation. <br /> This could be more than a simple namespace, e.g. <b>demo:mydemos</b>. <br /> The namespace <b>islandora:</b> is reserved, and is always allowed.'),
'#default_value' => variable_get('islandora_pids_allowed', 'default: demo: changeme: ilives: islandora-book: books: newspapers: '),
'#states' => array(
'invisible' => array(
':input[name="islandora_namespace_restriction_enforced"]' => array('checked' => FALSE),
),
),
),
),
),
);
return system_settings_form($form);
}
$form = array();
if (isset($form_state['values']['islandora_base_url'])) {
$url = $form_state['values']['islandora_base_url'];
}
else {
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora');
}
/**
* Gets a message which describes if the repository is accessible.
*
* Also describes if the user is considered an authenticated user by the
* repository.
*
* @param string $url
* The url to the Fedora Repository.
*
* @return string
* A message describing the accessibility of the repository at the given url.
*/
function islandora_admin_settings_form_repository_access_message($url) {
$info = $dc = FALSE;
$connection = islandora_get_tuque_connection(NULL, $url);
if (!$connection) {
return;
}
try {
$info = $connection->api->a->describeRepository();
}
catch (RepositoryException $e) {
$info = FALSE;
}
if ($info) {
if ($connection) {
try {
$info = $connection->api->a->describeRepository();
// If we are able to successfully call API-M::getDatastream, assume we are
// an authenticated user, as API-M is usally locked down.
$dc = $connection->api->m->getDatastream('fedora-system:ContentModel-3.0', 'DC');
}
catch (RepositoryException $e) {
$dc = FALSE;
// Ignore, we only testing to see what is accessible.
}
}
if ($info) {
if ($dc) {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array()));
$confirmation_message .= t('Successfully connected to Fedora Server (Version !version).', array(
'!version' => $info['repositoryVersion']));
}
else {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-warning.png', 'attributes' => array()));
$confirmation_message .= t('Unable to authenticate when connecting to to Fedora Server (Version !version). Please configure the !filter.',
array('!version' => $info['repositoryVersion'], '!filter' => 'Drupal Filter'));
}
if ($info && $dc) {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array()));
$confirmation_message .= t('Successfully connected to Fedora Server (Version !version).', array(
'!version' => $info['repositoryVersion']));
}
elseif ($info) {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-warning.png', 'attributes' => array()));
$confirmation_message .= t('Unable to authenticate when connecting to to Fedora Server (Version !version). Please configure the !filter.', array(
'!version' => $info['repositoryVersion'], '!filter' => 'Drupal Filter'));
}
else {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array()));
$confirmation_message .= t('Unable to connect to Fedora server at !islandora_url', array(
'!islandora_url' => $url));
}
$form['islandora_tabs'] = array(
'#type' => 'vertical_tabs',
);
$form['islandora_tabs']['islandora_general'] = array(
'#type' => 'fieldset',
'#title' => t('General Configuarion'),
);
// Ajax wrapper for url checking.
$form['islandora_tabs']['islandora_general']['wrapper'] = array(
'#prefix' => '<div id="islandora-url">',
'#suffix' => '</div>',
'#type' => 'markup',
);
$form['islandora_tabs']['islandora_general']['wrapper']['islandora_base_url'] = array(
'#type' => 'textfield',
'#title' => t('Fedora base URL'),
'#default_value' => variable_get('islandora_base_url', 'http://localhost:8080/fedora'),
'#description' => t('The URL to use for REST connections <br /> !confirmation_message', array(
'!confirmation_message' => $confirmation_message,
)),
'#required' => TRUE,
'#ajax' => array(
'callback' => 'islandora_update_url_div',
'wrapper' => 'islandora-url',
'effect' => 'fade',
'event' => 'blur',
'progress' => array('type' => 'throbber'),
),
);
$form['islandora_tabs']['islandora_general']['islandora_repository_pid'] = array(
'#type' => 'textfield',
'#title' => t('Root Collection PID'),
'#default_value' => variable_get('islandora_repository_pid', 'islandora:root'),
'#description' => t('The PID of the Root Collection Object'),
'#required' => TRUE,
);
$form['islandora_tabs']['islandora_namespace'] = array(
'#type' => 'fieldset',
'#title' => t('Namespaces'),
);
$form['islandora_tabs']['islandora_namespace']['wrapper'] = array(
'#type' => 'markup',
'#prefix' => '<div id="islandora-namespace">',
'#suffix' => '</div>',
);
$form['islandora_tabs']['islandora_namespace']['wrapper']['islandora_namespace_restriction_enforced'] = array(
'#weight' => -1,
'#type' => 'checkbox',
'#title' => t('Enforce namespace restrictions'),
'#description' => t("Allow administrator to restrict user's access to the PID namepaces listed below"),
'#default_value' => variable_get('islandora_namespace_restriction_enforced', FALSE),
'#ajax' => array(
'callback' => 'islandora_update_namespace_div',
'wrapper' => 'islandora-namespace',
'effect' => 'fade',
'event' => 'change',
'progress' => array('type' => 'throbber'),
),
);
if (isset($form_state['values']['islandora_namespace_restriction_enforced'])) {
$namespaces = $form_state['values']['islandora_namespace_restriction_enforced'];
}
else {
$namespaces = variable_get('islandora_namespace_restriction_enforced', FALSE);
}
if ($namespaces) {
$form['islandora_tabs']['islandora_namespace']['wrapper']['islandora_pids_allowed'] = array(
'#type' => 'textfield',
'#title' => t('PID namespaces allowed in this Drupal install'),
'#default_value' => variable_get('islandora_pids_allowed', 'default: demo: changeme: ilives: islandora-book: books: newspapers: '),
'#description' => t('A list of PID namespaces, separated by spaces, that users are permitted to access from this Drupal installation. <br /> This could be more than a simple namespace, e.g. <b>demo:mydemos</b>. <br /> The namespace <b>islandora:</b> is reserved, and is always allowed.'),
'#weight' => 0,
);
}
return system_settings_form($form);
return $confirmation_message;
}
/**
@ -168,18 +140,3 @@ function islandora_repository_admin(array $form, array &$form_state) {
function islandora_update_url_div(array $form, array $form_state) {
return $form['islandora_tabs']['islandora_general']['wrapper'];
}
/**
* Get the element to render for the AJAX event that triggered this callback.
*
* @param array $form
* The Drupal form definition.
* @param array $form_state
* The Drupal form state.
*
* @return array
* The form element to render.
*/
function islandora_update_namespace_div(array $form, array $form_state) {
return $form['islandora_tabs']['islandora_namespace']['wrapper'];
}

1
includes/dublin_core.inc

@ -133,6 +133,7 @@ class DublinCore {
$dc_array[$field]['label'] = $element_label;
$dc_array[$field]['value'] = $value;
$dc_array[$field]['class'] = drupal_strtolower(preg_replace('/[^A-Za-z0-9]/', '-', $field));
$dc_array[$field]['dcterms'] = preg_replace('/^dc/', 'dcterms', $field);
}
}
}

5
includes/ingest.form.inc

@ -703,7 +703,7 @@ function islandora_ingest_form_submit(array $form, array &$form_state) {
islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
}
// Ingest the objects.
foreach ($form_state['islandora']['objects'] as $object) {
foreach ($form_state['islandora']['objects'] as &$object) {
try {
islandora_add_object($object);
$form_state['redirect'] = "islandora/object/{$object->id}";
@ -715,6 +715,9 @@ function islandora_ingest_form_submit(array $form, array &$form_state) {
drupal_set_message(t('A problem occured while ingesting "@label" (ID: @pid), please notifiy the administrator.', array('@label' => $object->label, '@pid' => $object->id)), 'error');
}
}
// XXX: Foreaching with references can be weird... The reference exists in
// the scope outside.
unset($object);
}
/**

199
includes/solution_packs.inc

@ -5,11 +5,55 @@
* Admin and callback functions for solution pack management.
*/
/**
* Get the information about required object.
*
* @param string $module
* An optional string, identifying a module for which to get the required
* object information.
*
* @return array
* An associative array of info describing the required objects. If $module
* is not provided (or is NULL), then we provide the info for all modules. If
* $module is provided and we have info for the given module, only the info
* for that module is provided. If $module is provided and we have no info
* for the given module, we throw an exception.
*/
function islandora_solution_packs_get_required_objects($module = NULL) {
// Should make this statically cache, after figuring out how exactly it
// should be called... We occasionally load a module and attempt to install
// it's object right away (in the same request)... This would require
// resetting of the cache. Let's just not cache for now...
$required_objects = array();
if (!$required_objects) {
$connection = islandora_get_tuque_connection();
$required_objects = module_invoke_all('islandora_required_objects', $connection);
}
if ($module !== NULL) {
if (isset($required_objects[$module])) {
return $required_objects[$module];
}
else {
watchdog('islandora', 'Attempted to get required objects for %module... %module does not appear to have any required objects. Clear caches?', array(
'%module' => $module,
));
throw new Exception(t('Module "@module" has no required objects!', array(
'@module' => $module,
)));
}
}
else {
return $required_objects;
}
}
/**
* Solution pack admin page callback.
*
* @return string
* The html repersentation of all solution pack forms for required objects.
* @return array
* Renderable array of all solution pack forms for required objects.
*/
function islandora_solution_packs_admin() {
module_load_include('inc', 'islandora', 'includes/utilities');
@ -18,17 +62,15 @@ function islandora_solution_packs_admin() {
return '';
}
$connection = islandora_get_tuque_connection();
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
$output = '';
$enabled_solution_packs = module_invoke_all('islandora_required_objects', $connection);
$output = array();
$enabled_solution_packs = islandora_solution_packs_get_required_objects();
foreach ($enabled_solution_packs as $solution_pack_module => $solution_pack_info) {
// @todo We should probably get the title of the solution pack from the
// systems table for consistency in the interface.
$solution_pack_name = $solution_pack_info['title'];
$objects = array_filter($solution_pack_info['objects']);
$form = drupal_get_form('islandora_solution_pack_form_' . $solution_pack_module, $solution_pack_module, $solution_pack_name, $objects);
$output .= drupal_render($form);
$output[$solution_pack_module] = drupal_get_form('islandora_solution_pack_form_' . $solution_pack_module, $solution_pack_module, $solution_pack_name, $objects);
}
return $output;
}
@ -161,20 +203,38 @@ function islandora_solution_pack_form(array $form, array &$form_state, $solution
*/
function islandora_solution_pack_form_submit(array $form, array &$form_state) {
$solution_pack_module = $form_state['values']['solution_pack_module'];
$objects = $form_state['values']['objects'];
$batch = islandora_solution_pack_get_batch($solution_pack_module);
batch_set($batch);
// Hook to let solution pack objects be modified.
// Not using module_invoke so solution packs can be expanded by other modules.
// @todo shouldn't we send the object list along as well?
module_invoke_all('islandora_postprocess_solution_pack', $solution_pack_module);
}
/**
* Get the batch definition to reinstall all the objects for a given module.
*
* @param string $module
* The name of the modules of which to grab the required objects for to setup
* the batch.
*
* @return array
* An array defining a batch which can be passed on to batch_set().
*/
function islandora_solution_pack_get_batch($module) {
$batch = array(
'title' => t('Installing / Updating solution pack objects'),
'file' => drupal_get_path('module', 'islandora') . '/includes/solution_packs.inc',
'operations' => array(),
);
foreach ($objects as $object) {
$info = islandora_solution_packs_get_required_objects($module);
foreach ($info['objects'] as $object) {
$batch['operations'][] = array('islandora_solution_pack_batch_operation_reingest_object', array($object));
}
batch_set($batch);
// Hook to let solution pack objects be modified.
// Not using module_invoke so solution packs can be expanded by other modules.
// @todo shouldn't we send the object list along as well?
module_invoke_all('islandora_postprocess_solution_pack', $solution_pack_module);
return $batch;
}
/**
@ -245,14 +305,16 @@ function islandora_solution_pack_batch_operation_reingest_object(AbstractObject
* install/unistall hooks.
* @param string $op
* The operation to perform, either install or uninstall.
* @param bool $force
* Force the (un)installation of object.
*
* @todo Implement hook_modules_installed/hook_modules_uninstalled instead of
* calling this function directly.
* @todo Remove the second parameter and have two seperate functions.
*/
function islandora_install_solution_pack($module, $op = 'install') {
function islandora_install_solution_pack($module, $op = 'install', $force = FALSE) {
if ($op == 'uninstall') {
islandora_uninstall_solution_pack($module);
islandora_uninstall_solution_pack($module, $force);
return;
}
@ -267,9 +329,9 @@ function islandora_install_solution_pack($module, $op = 'install') {
'!admin_link' => $admin_link,
);
module_load_include('module', 'islandora', 'islandora');
drupal_load('module', 'islandora');
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('module', $module, $module);
drupal_load('module', $module);
$info_file = drupal_get_path('module', $module) . "/{$module}.info";
$info_array = drupal_parse_info_file($info_file);
$module_name = $info_array['name'];
@ -279,8 +341,8 @@ function islandora_install_solution_pack($module, $op = 'install') {
return;
}
$connection = islandora_get_tuque_connection();
$required_objects = module_invoke($module, 'islandora_required_objects', $connection);
$objects = $required_objects[$module]['objects'];
$required_objects = islandora_solution_packs_get_required_objects($module);
$objects = $required_objects['objects'];
$status_messages = array(
'up_to_date' => $t('The object already exists and is up-to-date.', $t_params),
'missing_datastream' => $t('The object already exists but is missing a datastream. Please reinstall the object on the !admin_link page.', $t_params),
@ -288,26 +350,41 @@ function islandora_install_solution_pack($module, $op = 'install') {
'modified_datastream' => $t('The object already exists but datastreams are modified. Please reinstall the object on the !admin_link page.', $t_params),
);
foreach ($objects as $object) {
$query = $connection->api->a->findObjects('query', 'pid=' . $object->id);
$already_exists = !empty($query['results']);
$already_exists = islandora_object_load($object->id);
$label = $object->label;
$object_link = l($label, "islandora/object/{$object->id}");
$deleted = FALSE;
if ($already_exists) {
$object_status = islandora_check_object_status($object);
$here_params = array(
'!summary' => $t("@module: Did not install !object_link.", array(
'!object_link' => $object_link,
) + $t_params),
'!description' => $status_messages[$object_status['status']],
);
drupal_set_message(filter_xss(format_string('!summary !description', $here_params)), 'warning');
if (!$force) {
$object_status = islandora_check_object_status($object);
$here_params = array(
'!summary' => $t("@module: Did not install !object_link.", array(
'!object_link' => $object_link,
) + $t_params),
'!description' => $status_messages[$object_status['status']],
);
drupal_set_message(filter_xss(format_string('!summary !description', $here_params)), 'warning');
continue;
}
else {
$deleted = islandora_delete_object($already_exists);
}
}
else {
if ($already_exists && $deleted || !$already_exists) {
$object = islandora_add_object($object);
if ($object) {
drupal_set_message(filter_xss($t('@module: Successfully installed. !object_link.', array(
'!object_link' => $object_link,
) + $t_params)), 'status');
if ($deleted) {
drupal_set_message(filter_xss($t('@module: Successfully reinstalled. !object_link.', array(
'!object_link' => $object_link,
) + $t_params)), 'status');
}
else {
drupal_set_message(filter_xss($t('@module: Successfully installed. !object_link.', array(
'!object_link' => $object_link,
) + $t_params)), 'status');
}
}
else {
drupal_set_message($t('@module: Failed to install. @label.', array(
@ -315,6 +392,11 @@ function islandora_install_solution_pack($module, $op = 'install') {
) + $t_params), 'warning');
}
}
else {
drupal_set_message($t('@module: "@label" already exists and failed to be deleted.', array(
'@label' => $label,
) + $t_params), 'warning');
}
}
}
@ -323,15 +405,17 @@ function islandora_install_solution_pack($module, $op = 'install') {
*
* @param string $module
* The solution pack to uninstall.
* @param bool $force
* Force the objects to be removed.
*
* @todo Implement hook_modules_uninstalled instead of calling this function
* directly for each solution pack.
*/
function islandora_uninstall_solution_pack($module) {
function islandora_uninstall_solution_pack($module, $force = FALSE) {
$t = get_t();
module_load_include('module', 'islandora', 'islandora');
drupal_load('module', 'islandora');
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('module', $module, $module);
drupal_load('module', $module);
$config_link = l($t('Islandora configuration'), 'admin/islandora/configure');
$info_file = drupal_get_path('module', $module) . "/{$module}.info";
$info_array = drupal_parse_info_file($info_file);
@ -345,22 +429,35 @@ function islandora_uninstall_solution_pack($module) {
return;
}
$connection = islandora_get_tuque_connection();
$required_objects = module_invoke($module, 'islandora_required_objects', $connection);
$objects = $required_objects[$module]['objects'];
$required_objects = islandora_solution_packs_get_required_objects($module);
$objects = $required_objects['objects'];
$filter = function($o) use($connection) {
$param = "pid={$o->id}";
$query = $connection->api->a->findObjects('query', $param);
return !empty($query['results']);
};
$existing_objects = array_filter($objects, $filter);
foreach ($existing_objects as $object) {
$object_link = l($object->label, "islandora/object/{$object->id}");
$msg = $t('@module: Did not remove !object_link. It may be used by other sites.', array(
'!object_link' => $object_link,
'@module' => $module_name,
));
drupal_set_message(filter_xss($msg), 'warning');
if (!$force) {
foreach ($existing_objects as $object) {
$object_link = l($object->label, "islandora/object/{$object->id}");
$msg = $t('@module: Did not remove !object_link. It may be used by other sites.', array(
'!object_link' => $object_link,
'@module' => $module_name,
));
drupal_set_message(filter_xss($msg), 'warning');
}
}
else {
foreach ($existing_objects as $object) {
$params = array(
'@id' => $object->id,
'@module' => $module_name,
);
islandora_delete_object($object);
drupal_set_message($t('@module: Deleted @id.', $params));
}
}
}
@ -430,13 +527,21 @@ function islandora_check_object_status(AbstractObject $object_definition) {
// be equal as Fedora does some XML mangling. In order for C14N to work
// we need to replace the info:fedora namespace, as C14N hates it.
// C14N also doesn't normalize whitespace at the end of lines and Fedora
// may add some whitespace on some lines.
// will sometimes replace new-lines with white-space. So first we strip
// leading/tailing white-space and replace all new-lines within the xml
// document to account for Fedora's weird formatting.
$xsl = new DOMDocument();
$xsl->load(drupal_get_path('module', 'islandora') . '/xml/strip_newlines_and_whitespace.xsl');
$xslt = new XSLTProcessor();
$xslt->importStyleSheet($xsl);
$object_definition_dom = new DOMDocument();
$object_definition_dom->preserveWhiteSpace = FALSE;
$object_definition_dom->loadXML(str_replace('info:', 'http://', $ds->content));
$object_definition_dom = $xslt->transformToDoc($object_definition_dom);
$object_actual_dom = new DOMDocument();
$object_actual_dom->preserveWhiteSpace = FALSE;
$object_actual_dom->loadXML(str_replace('info:', 'http://', $existing_object[$ds->id]->content));
$object_actual_dom = $xslt->transformToDoc($object_actual_dom);
// Fedora changes the xml structure so we need to cannonize it.
if ($object_actual_dom->C14N() != $object_definition_dom->C14N()) {

30
includes/tuque_wrapper.inc

@ -82,13 +82,26 @@ class IslandoraFedoraRepository extends FedoraRepository {
* @see FedoraRepository::ingestObject()
*/
public function ingestObject(NewFedoraObject &$object) {
$context = array(
'action' => 'ingest',
'block' => FALSE,
);
islandora_alter_object($object, $context);
try {
if ($context['block']) {
foreach ($object as $dsid => $datastream) {
$datastream_context = array(
'action' => 'ingest',
'block' => FALSE,
);
islandora_alter_datastream($object, $datastream, $datastream_context);
if ($datastream_context['block']) {
throw new Exception(t('Object ingest blocked due to ingest of @dsid being blocked.', array(
'@dsid' => $dsid,
)));
}
}
$object_context = array(
'action' => 'ingest',
'block' => FALSE,
);
islandora_alter_object($object, $object_context);
if ($object_context['block']) {
throw new Exception('Ingest Object was blocked.');
}
$ret = parent::ingestObject($object);
@ -194,6 +207,9 @@ class IslandoraFedoraApiM extends FedoraApiM {
'params' => $params,
);
islandora_alter_datastream($object, $datastream, $context);
if (isset($params['lastModifiedDate'])) {
$params['lastModifiedDate'] = (string) $object[$dsid]->createdDate;
}
try {
if ($context['block']) {
throw new Exception('Modify Datastream was blocked.');
@ -269,7 +285,6 @@ class IslandoraFedoraApiM extends FedoraApiM {
switch ($action) {
case 'block':
throw new Exception('Purge Datastream was blocked.');
break;
case 'delete':
$object[$dsid]->state = 'D';
@ -313,7 +328,6 @@ class IslandoraFedoraApiM extends FedoraApiM {
switch ($action) {
case 'block':
throw new Exception('Purge object was blocked.');
break;
case 'delete':
$object->state = 'D';

45
includes/utilities.inc

@ -865,3 +865,48 @@ function islandora_deprecated($release, $solution = NULL) {
}
return $message;
}
/**
* Transform recursively-merged array of strings to renderable arrays.
*
* Renderable arrays are passed-through as-is.
*
* Previously, functions/hooks like islandora_view_object would return an
* associative array with string values containing markup. These values were
* then imploded into one large piece of markup. Here, we transform this older
* structure which was generated into a renderable array, because renderable
* arrays are awesome!
*
* @param array $markup_array
* An associative array of which the values are either a string or an array
* of strings, which we transform to renderable markup elements (by
* reference).
*/
function islandora_as_renderable_array(&$markup_array) {
foreach ($markup_array as &$value) {
if (!is_array($value)) {
// Not a renderable array, just a string. Let's convert it to a
// renderable '#markup' element.
$value = array(
'#markup' => $value,
);
}
elseif (!isset($value['#type']) && !isset($value['#markup'])) {
// A simple array--possibly the result of a recursive merge? Let's
// look at each, to possibly convert them to a renderable '#markup'
// elements.
foreach ($value as &$inner) {
if (!is_array($inner)) {
// If it is an array at this level, we can assume that it is a
// renderable array. If it is not an array, convert to a renderable
// '#markup' element.
$inner = array(
'#markup' => $inner,
);
}
}
unset($inner);
}
}
unset($value);
}

142
islandora.drush.inc

@ -0,0 +1,142 @@
<?php
/**
* @file
* Drush command/hook implementation.
*/
/**
* Implements hook_drush_command().
*/
function islandora_drush_command() {
$commands = array();
$commands['islandora-solution-pack-install-required-objects'] = array(
'description' => dt('Install Solution Pack objects.'),
'options' => array(
'module' => array(
'description' => dt('The module for which to install the required objects.'),
'required' => TRUE,
),
'force' => array(
'description' => dt('Force reinstallation of the objects.'),
),
),
'aliases' => array('ispiro'),
'drupal dependencies' => array(
'islandora',
),
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
);
$commands['islandora-solution-pack-uninstall-required-objects'] = array(
'description' => dt('Uninstall Solution Pack objects.'),
'options' => array(
'module' => array(
'description' => dt('The module for which to uninstall the required objects.'),
'required' => TRUE,
),
'force' => array(
'description' => dt('Force reinstallation of the objects.'),
),
),
'aliases' => array('ispuro'),
'drupal dependencies' => array(
'islandora',
),
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
);
$commands['islandora-solution-pack-required-objects-status'] = array(
'description' => dt('Get Solution Pack object status.'),
'options' => array(
'module' => array(
'description' => dt('The module for which to get the status of the required objects.'),
),
),
'aliases' => array('ispros'),
'drupal dependencies' => array(
'islandora',
),
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
);
return $commands;
}
/**
* Command callback to install required objects.
*/
function drush_islandora_solution_pack_install_required_objects() {
module_load_include('inc', 'islandora', 'includes/solution_packs');
$module = drush_get_option('module');
if (module_exists($module)) {
islandora_install_solution_pack(
$module,
'install',
drush_get_option('force', FALSE)
);
}
else {
drush_log(dt('"@module" is not installed/enabled?...', array(
'@module' => $module,
)));
}
}
/**
* Command callback to uninstall required objects.
*/
function drush_islandora_solution_pack_uninstall_required_objects() {
module_load_include('inc', 'islandora', 'includes/solution_packs');
$module = drush_get_option('module');
if (module_exists($module)) {
islandora_uninstall_solution_pack(
$module,
drush_get_option('force', FALSE)
);
}
else {
drush_log(dt('"@module" is not installed/enabled?...', array(
'@module' => $module,
)));
}
}
/**
* Command callback for object status.
*/
function drush_islandora_solution_pack_required_objects_status() {
module_load_include('inc', 'islandora', 'includes/solution_packs');
$module = drush_get_option('module', FALSE);
$required_objects = array();
if ($module && module_exists($module)) {
$required_objects[$module] = islandora_solution_packs_get_required_objects($module);
}
elseif ($module === FALSE) {
$required_objects = islandora_solution_packs_get_required_objects();
}
else {
drush_log(dt('"@module" is not installed/enabled?...', array(
'@module' => $module,
)));
return;
}
$header = array('PID', 'Machine Status', 'Readable Status');
$widths = array(30, 20, 20);
foreach ($required_objects as $module => $info) {
$rows = array();
drush_print($info['title']);
foreach ($info['objects'] as $object) {
$status = islandora_check_object_status($object);
$rows[] = array(
$object->id,
$status['status'],
$status['status_friendly'],
);
}
drush_print_table($rows, $header, $widths);
}
}

30
islandora.module

@ -668,6 +668,7 @@ function islandora_manage_overview_object(AbstractObject $object) {
$output = array();
foreach (islandora_build_hook_list(ISLANDORA_OVERVIEW_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object);
islandora_as_renderable_array($temp);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
}
@ -678,7 +679,8 @@ function islandora_manage_overview_object(AbstractObject $object) {
}
arsort($output);
drupal_alter(ISLANDORA_OVERVIEW_HOOK, $object, $output);
return implode('', $output);
islandora_as_renderable_array($output);
return $output;
}
/**
@ -693,7 +695,11 @@ function islandora_manage_overview_object(AbstractObject $object) {
*/
function islandora_default_islandora_manage_overview_object(AbstractObject $object) {
$output = theme('islandora_default_overview', array('islandora_object' => $object));
return array('Default overview output' => $output);
return array(
'Default overview output' => array(
'#markup' => $output,
),
);
}
/**
@ -719,6 +725,7 @@ function islandora_edit_object(AbstractObject $object) {
$output = array();
foreach (islandora_build_hook_list(ISLANDORA_EDIT_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object);
islandora_as_renderable_array($temp);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
}
@ -729,7 +736,8 @@ function islandora_edit_object(AbstractObject $object) {
}
arsort($output);
drupal_alter(ISLANDORA_EDIT_HOOK, $object, $output);
return implode('', $output);
islandora_as_renderable_array($output);
return $output;
}
/**
@ -744,7 +752,11 @@ function islandora_edit_object(AbstractObject $object) {
*/
function islandora_default_islandora_edit_object(AbstractObject $object) {
$output = theme('islandora_default_edit', array('islandora_object' => $object));
return array('Default Edit output' => $output);
return array(
'Default Edit output' => array(
'#markup' => $output,
),
);
}
/**
@ -787,6 +799,7 @@ function islandora_view_object(AbstractObject $object) {
// @todo Remove page number and size from this hook, implementers of the
// hook should use drupal page handling directly.
$temp = module_invoke_all($hook, $object, $page_number, $page_size);
islandora_as_renderable_array($temp);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
}
@ -797,7 +810,8 @@ function islandora_view_object(AbstractObject $object) {
}
arsort($output);
drupal_alter($hooks, $object, $output);
return implode('', $output);
islandora_as_renderable_array($output);
return $output;
}
@ -830,7 +844,11 @@ function islandora_drupal_title(AbstractObject $object) {
*/
function islandora_default_islandora_view_object($object) {
$output = theme('islandora_default', array('islandora_object' => $object));
return array('Default output' => $output);
return array(
'Default output' => array(
'#markup' => $output,
),
);
}
/**

30
tests/hooks.test

@ -75,6 +75,8 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
/**
* Test ALL THE HOOKS!.
*
* Covers the majority of cases...
*/
public function testHooks() {
// Test ingesting with FedoraRepository::ingestObject().
@ -85,6 +87,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called "hook_islandora_object_alter" when ingesting via FedoraRepository::ingestObject.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called ISLANDORA_OBJECT_INGESTED_HOOK when ingesting via FedoraRepository::ingestObject.');
$this->repository->purgeObject($object->id);
// Test blocking the ingest.
$object = $this->repository->constructObject('test:testIngestedObjectHook');
$object->label = 'block';
@ -100,6 +103,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called "hook_islandora_object_alter" when blocking ingesting via FedoraRepository::ingestObject.');
$this->assertFalse($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Did not called ISLANDORA_OBJECT_INGESTED_HOOK when blocking ingesting via FedoraRepository::ingestObject.');
}
// Test modifying via set magic functions.
$object = $this->repository->constructObject('test:testModifiedObjectHook');
$this->repository->ingestObject($object);
@ -108,6 +112,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$object->label = "New Label!";
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called "hook_islandora_object_alter" when modifying via set magic functions.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called ISLANDORA_OBJECT_MODIFIED_HOOK when modifying via set magic functions.');
// Test blocking the modification.
try {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
@ -122,6 +127,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assertFALSE($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called ISLANDORA_OBJECT_MODIFIED_HOOK when blocking modifying via set magic functions.');
}
$this->repository->purgeObject($object->id);
// Test purging with FedoraRepository::purgeObject().
$object = $this->repository->constructObject('test:testPurgedObjectHook');
$this->repository->ingestObject($object);
@ -130,6 +136,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->repository->purgeObject($object->id);
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when purging via FedoraRepository::purgeObject.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when purging via FedoraRepository::purgeObject.');
// Test deleting.
$object = $this->repository->constructObject('test:testPurgedObjectHook');
$this->repository->ingestObject($object);
@ -139,6 +146,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when deleting via FedoraObject::delete.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when purging via FedoraObject::delete.');
$this->repository->purgeObject($object->id);
// Test alter blocking.
$object = $this->repository->constructObject('test:testPurgedObjectHook');
$this->repository->ingestObject($object);
@ -154,6 +162,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when blocking purge via FedoraRepository::purgeObject.');
$this->assertFalse($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when blocking purge via FedoraRepository::purgeObject.');
}
// Test alter delete.
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
@ -164,6 +173,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when preventing purge and deleting.');
$object->label = 'Something other than delete';
$this->repository->purgeObject($object->id);
// Test ingesting with FedoraRepository::ingestObject().
$object = $this->repository->constructObject('test:testIngestedDatastreamHook');
$this->repository->ingestObject($object);
@ -174,6 +184,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK], 'Called "hook_islandora_datastream_alter" when ingesting via FedoraObject::ingestDatastream.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK], 'Called ISLANDORA_DATASTREAM_INGESTED_HOOK when ingesting via FedoraObject::ingestDatastream.');
$this->repository->purgeObject($object->id);
// Test modifying a datastream.
$object = $this->repository->constructObject('test:testModifiedDatastreamHook');
$this->repository->ingestObject($object);
@ -184,6 +195,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$ds->label = "New Label!";
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called "hook_islandora_datastream_alter" when modifying via set magic functions.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when modifying via set magic functions.');
// Test blocking modifying.
try {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
@ -197,6 +209,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->assertFALSE($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when blocking modifying via set magic functions.');
}
$this->repository->purgeObject($object->id);
// Test purging with FedoraRepository::purgeObject().
$object = $this->repository->constructObject('test:testPurgedDatastreamHook');
$this->repository->ingestObject($object);
@ -210,4 +223,21 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->repository->purgeObject($object->id);
}
/**
* Test ALL THE HOOKS!.
*
* Ensure hooks are triggered properly in "New" objects.
*/
public function testNewIngestHooks() {
// Test ingesting with FedoraRepository::ingestObject().
$object = $this->repository->constructObject('test:testIngestedDatastreamHook');
$ds = $object->constructDatastream('TEST');
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = FALSE;
$object->ingestDatastream($ds);
$this->repository->ingestObject($object);
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK], 'Called "hook_islandora_datastream_alter" when ingesting via FedoraObject::ingestDatastream.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK], 'Called ISLANDORA_DATASTREAM_INGESTED_HOOK when ingesting via FedoraObject::ingestDatastream.');
$this->repository->purgeObject($object->id);
}
}

6
tests/scripts/travis_setup.sh

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash
mysql -u root -e 'create database drupal;'
mysql -u root -e "create database fedora;"
@ -11,8 +11,8 @@ cd islandora_tomcat
export CATALINA_HOME='.'
./bin/startup.sh
cd $HOME
pear upgrade force Console_Getopt
pear upgrade force pear
pear upgrade --force Console_Getopt
pear upgrade --force pear
pear upgrade-all
pear channel-discover pear.drush.org
pear channel-discover pear.drush.org

13
xml/strip_newlines_and_whitespace.xsl

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" media-type="text/xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="translate(., '&#xA;', ' ')"/>
</xsl:template>
</xsl:stylesheet>
Loading…
Cancel
Save