diff --git a/.travis.yml b/.travis.yml
index adedf7b1..17a22707 100644
--- a/.travis.yml
+++ b/.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
diff --git a/includes/admin.form.inc b/includes/admin.form.inc
index a1f22652..d34bd5d5 100644
--- a/includes/admin.form.inc
+++ b/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' => '
',
+ '#suffix' => '
',
+ '#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
!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.
This could be more than a simple namespace, e.g. demo:mydemos.
The namespace islandora: 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' => '',
- '#suffix' => '
',
- '#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
!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' => '',
- '#suffix' => '
',
- );
-
- $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.
This could be more than a simple namespace, e.g. demo:mydemos.
The namespace islandora: 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'];
-}
diff --git a/includes/dublin_core.inc b/includes/dublin_core.inc
index 14d25392..ec058181 100644
--- a/includes/dublin_core.inc
+++ b/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);
}
}
}
diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc
index 00783934..6faa642c 100644
--- a/includes/ingest.form.inc
+++ b/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);
}
/**
diff --git a/includes/solution_packs.inc b/includes/solution_packs.inc
index 26bd77b5..e1cf9493 100644
--- a/includes/solution_packs.inc
+++ b/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()) {
diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc
index 8563070f..96f9919c 100644
--- a/includes/tuque_wrapper.inc
+++ b/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';
diff --git a/includes/utilities.inc b/includes/utilities.inc
index 66c03d26..5ce2ca14 100644
--- a/includes/utilities.inc
+++ b/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);
+}
diff --git a/islandora.drush.inc b/islandora.drush.inc
new file mode 100644
index 00000000..b2e75c47
--- /dev/null
+++ b/islandora.drush.inc
@@ -0,0 +1,142 @@
+ 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);
+ }
+}
diff --git a/islandora.module b/islandora.module
index d1f15542..8a8ee6be 100644
--- a/islandora.module
+++ b/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,
+ ),
+ );
}
/**
diff --git a/tests/hooks.test b/tests/hooks.test
index 3133d656..d08c537b 100644
--- a/tests/hooks.test
+++ b/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);
+ }
}
diff --git a/tests/scripts/travis_setup.sh b/tests/scripts/travis_setup.sh
index 45dc3ab9..19c7db78 100755
--- a/tests/scripts/travis_setup.sh
+++ b/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
diff --git a/xml/strip_newlines_and_whitespace.xsl b/xml/strip_newlines_and_whitespace.xsl
new file mode 100644
index 00000000..4d4e1057
--- /dev/null
+++ b/xml/strip_newlines_and_whitespace.xsl
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file