diff --git a/includes/derivatives.inc b/includes/derivatives.inc index 5ba4bb56..78f00aab 100644 --- a/includes/derivatives.inc +++ b/includes/derivatives.inc @@ -121,3 +121,60 @@ function islandora_derivative_logging(array $logging_results) { } } } + +/** + * 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 operations to be called from within a batch. + */ +function islandora_do_batch_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'); + $operations = 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) { + $file = FALSE; + if (isset($hook['file'])) { + $file = $hook['file']; + } + foreach ($hook['function'] as $function) { + $operations[] = array('islandora_derivative_perform_batch_operation', array( + $function, + $file, + $object->id, + $options['force']), + ); + } + } + return $operations; +} diff --git a/includes/object_properties.form.inc b/includes/object_properties.form.inc index 676f0d0c..be31719c 100644 --- a/includes/object_properties.form.inc +++ b/includes/object_properties.form.inc @@ -26,6 +26,12 @@ function islandora_object_properties_form(array $form, array &$form_state, Abstr if (!empty($temp)) { $related_objects_pids = array_merge_recursive($related_objects_pids, $temp); } + $regenerate_derivatives_access = FALSE; + if (islandora_object_access(ISLANDORA_REGENERATE_DERIVATIVES, $object)) { + if (count(islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array($object))) > 0) { + $regenerate_derivatives_access = TRUE; + } + } return array( 'pid' => array( '#type' => 'hidden', @@ -84,6 +90,12 @@ function islandora_object_properties_form(array $form, array &$form_state, Abstr '#submit' => array('islandora_object_properties_form_delete'), '#limit_validation_errors' => array(array('pid')), ), + 'regenerate' => array( + '#type' => 'submit', + '#access' => $regenerate_derivatives_access, + '#value' => t("Regenerate all derivatives"), + '#submit' => array('islandora_object_properties_regenerate_derivatives'), + ), ); } @@ -188,3 +200,15 @@ function islandora_update_object_properties($pid, $update_states, $state, $updat } } } + +/** + * Callback function for object properties regenerate all derivatives. + * + * @param array $form + * The Drupal form. + * @param array $form_state + * The Drupal form state. + */ +function islandora_object_properties_regenerate_derivatives(array $form, array &$form_state) { + drupal_goto("islandora/object/{$form_state['object']}/regenerate"); +} diff --git a/includes/regenerate_derivatives.form.inc b/includes/regenerate_derivatives.form.inc new file mode 100644 index 00000000..a7ef147c --- /dev/null +++ b/includes/regenerate_derivatives.form.inc @@ -0,0 +1,178 @@ + $datastream->id)), + "islandora/object/{$datastream->parent->id}/manage/datastreams", + t('This will create a new version of the datastream. Please wait while this happens.'), + t('Regenerate'), + t('Cancel') + ); +} + +/** + * Submit handler for the regenerate datastream derivative form. + * + * @param array $form + * The Drupal form. + * @param array $form_state + * The Drupal form state. + */ +function islandora_regenerate_datastream_derivative_form_submit(array $form, array &$form_state) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $datastream = $form_state['datastream']; + $batch = islandora_regenerate_datastream_derivative_batch($datastream); + batch_set($batch); + $form_state['redirect'] = "islandora/object/{$datastream->parent->id}/manage/datastreams"; +} + +/** + * Regenerate all derivatives on an object. + * + * @param array $form + * The Drupal form. + * @param array $form_state + * The Drupal form state. + * @param AbstractObject $object + * The object that is having its derivatives regenerated. + * + * @return array + * The Drupal form definition. + */ +function islandora_regenerate_object_derivatives_form(array $form, array &$form_state, AbstractObject $object) { + $form_state['object'] = $object; + return confirm_form($form, + t('Are you sure you want to regenerate all the derivatives for %title?', array('%title' => $object->label)), + "islandora/object/{$object->id}/manage/properties", + t('This will create a new version for every datastream on the object. Please wait while this happens.'), + t('Regenerate'), + t('Cancel') + ); +} + +/** + * Submit handler for the regenerate object derivativse form. + * + * @param array $form + * The Drupal form. + * @param array $form_state + * The Drupal form state. + */ +function islandora_regenerate_object_derivatives_form_submit(array $form, array &$form_state) { + $object = $form_state['object']; + $batch = islandora_regenerate_object_derivatives_batch($object); + batch_set($batch); + $form_state['redirect'] = "islandora/object/{$object->id}/manage/properties"; +} + +/** + * Creates a batch to go out and re-create all of the derivatives for an object. + * + * @param AbstractObject $object + * A AbstractObject representing an object within Fedora. + * + * @return array + * An array specifying the Drupal batch. + */ +function islandora_regenerate_object_derivatives_batch(AbstractObject $object) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + return array( + 'title' => t('Regenerating all derivatives for @label', array('@label' => $object->label)), + 'operations' => islandora_do_batch_derivatives($object, array('force' => TRUE)), + 'init_message' => t('Preparing to regenerate derivatives...'), + 'progress_message' => t('Time elapsed: @elapsed
Estimated time remaning @estimate.'), + 'error_message' => t('An error has occurred.'), + 'file' => drupal_get_path('module', 'islandora') . '/includes/regenerate_derivatives.form.inc', + 'finished' => 'islandora_regenerate_derivative_batch_finished', + ); +} + +/** + * Creates a batch to go out and re-create the derivative for a datastream. + * + * @param AbstractDatastream $datastream + * A AbstractDatastream representing a datastream on an object within Fedora. + * + * @return array + * An array specifying the Drupal batch. + */ +function islandora_regenerate_datastream_derivative_batch(AbstractDatastream $datastream) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + return array( + 'title' => t('Regenerating derivatives for the @dsid datastream', array('@dsid' => $datastream->id)), + 'operations' => islandora_do_batch_derivatives($datastream->parent, array( + 'force' => TRUE, + 'destination_dsid' => $datastream->id, + )), + 'init_message' => t('Preparing to regenerate derivatives...'), + 'progress_message' => t('Time elapsed: @elapsed
Estimated time remaning @estimate.'), + 'error_message' => t('An error has occurred.'), + 'file' => drupal_get_path('module', 'islandora') . '/includes/regenerate_derivatives.form.inc', + 'finished' => 'islandora_regenerate_derivative_batch_finished', + ); +} + +/** + * Wrapper to call out to batch operations. + * + * @param string $function + * The name of the function we are calling for derivatives. + * @param bool|string $file + * FALSE if there is no file to load, the path to require otherwise + * @param string $pid + * The pid of the object we are performing. + * @param bool $force + * Whether we are forcing derivative regeneration or not. + * @param array $context + * The context of the current batch operation. + */ +function islandora_derivative_perform_batch_operation($function, $file, $pid, $force, &$context) { + if ($file) { + require_once $file; + } + if (function_exists($function)) { + $logging = call_user_func($function, islandora_object_load($pid), $force); + if (!empty($logging)) { + $context['results']['logging'][] = $logging; + } + } + else { + watchdog('islandora', 'Unable to call derivative function @function as it was not found!', array('@function' => $function), WATCHDOG_ERROR); + } +} + +/** + * Finished function for derivative batch regeneration. + * + * @param array $success + * An array of success passed from the batch. + * @param array $results + * An array of results passed from the batch. + * @param array $operations + * An array of operations passed from the batch. + */ +function islandora_regenerate_derivative_batch_finished($success, $results, $operations) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + if (!empty($results['logging'])) { + islandora_derivative_logging($results['logging']); + } +} diff --git a/islandora.module b/islandora.module index 17f13724..fb165f1e 100644 --- a/islandora.module +++ b/islandora.module @@ -36,6 +36,7 @@ define('ISLANDORA_MANAGE_PROPERTIES', 'manage object properties'); define('ISLANDORA_VIEW_DATASTREAM_HISTORY', 'view old datastream versions'); define('ISLANDORA_MANAGE_DELETED_OBJECTS', 'manage deleted objects'); define('ISLANDORA_REVERT_DATASTREAM', 'revert to old datastream'); +define('ISLANDORA_REGENERATE_DERIVATIVES', 'regenerate derivatives for an object'); // Hooks. @@ -209,6 +210,15 @@ function islandora_menu() { 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(ISLANDORA_PURGE, 2), ); + $items['islandora/object/%islandora_object/regenerate'] = array( + 'title' => 'Regenerate all derivatives on an object', + 'file' => 'includes/regenerate_derivatives.form.inc', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('islandora_regenerate_object_derivatives_form', 2), + 'type' => MENU_CALLBACK, + 'access callback' => 'islandora_object_access_callback', + 'access arguments' => array(ISLANDORA_REGENERATE_DERIVATIVES, 2), + ); $items['islandora/object/%islandora_object/manage/datastreams/add'] = array( 'title' => 'Add a datastream', 'file' => 'includes/add_datastream.form.inc', @@ -314,6 +324,16 @@ function islandora_menu() { 'access arguments' => array(ISLANDORA_VIEW_DATASTREAM_HISTORY, 4), 'load arguments' => array(2), ); + $items['islandora/object/%islandora_object/datastream/%islandora_datastream/regenerate'] = array( + 'title' => 'Regenrate datastream derivative', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('islandora_regenerate_datastream_derivative_form', 4), + 'file' => 'includes/regenerate_derivatives.form.inc', + 'type' => MENU_CALLBACK, + 'access callback' => 'islandora_datastream_access', + 'access arguments' => array(ISLANDORA_REGENERATE_DERIVATIVES, 4), + 'load arguments' => array(2), + ); $items['islandora/object/%islandora_object/download_clip'] = array( 'page callback' => 'islandora_download_clip', 'page arguments' => array(2), @@ -460,6 +480,10 @@ function islandora_theme() { 'file' => 'theme/theme.inc', 'variables' => array('datastream' => NULL), ), + 'islandora_datastream_regenerate_link' => array( + 'file' => 'theme/theme.inc', + 'variables' => array('datastream' => NULL), + ), 'islandora_dublin_core_display' => array( 'file' => 'theme/theme.inc', 'template' => 'theme/islandora-dublin-core-display', @@ -534,6 +558,10 @@ function islandora_permission() { 'title' => t('Manage deleted objects'), 'description' => t('Purge or revert deleted objects.'), ), + ISLANDORA_REGENERATE_DERIVATIVES => array( + 'title' => t('Regenerate derivatives'), + 'description' => t('Regenerate derivatives for an object or per datastream.'), + ), ); } @@ -1069,7 +1097,7 @@ function islandora_default_islandora_view_object($object) { * * @param AbstractObject $object * The fedora object to print. - * @param unknown $alter + * @param string $alter * The string representation of the themed viewable object. * * @return array diff --git a/theme/theme.inc b/theme/theme.inc index 6a80fbb6..0e62f0d7 100644 --- a/theme/theme.inc +++ b/theme/theme.inc @@ -25,7 +25,7 @@ function islandora_preprocess_islandora_default_edit(array &$variables) { $header[] = array('data' => t('Versions')); } - $header[] = array('data' => t('Operations'), 'colspan' => '3'); + $header[] = array('data' => t('Operations'), 'colspan' => '4'); $table_attributes = array('class' => array('manage-datastreams')); $rows = array(); @@ -53,7 +53,7 @@ function islandora_preprocess_islandora_default_edit(array &$variables) { 'class' => 'datastream-size', 'data' => islandora_datastream_get_human_readable_size($ds), ); - if (user_access(ISLANDORA_VIEW_DATASTREAM_HISTORY)) { + if (islandora_datastream_access(ISLANDORA_VIEW_DATASTREAM_HISTORY, $ds)) { $row[] = array( 'class' => 'datastream-versions', 'data' => theme('islandora_datastream_version_link', array( @@ -79,6 +79,14 @@ function islandora_preprocess_islandora_default_edit(array &$variables) { 'datastream' => $ds, )), ); + if (islandora_datastream_access(ISLANDORA_REGENERATE_DERIVATIVES, $ds)) { + $row[] = array( + 'class' => 'datastream-regenerate', + 'data' => theme('islandora_datastream_regenerate_link', array( + 'datastream' => $ds, + )), + ); + } $rows[] = $row; } $caption = filter_xss($islandora_object->label) . ' - ' . $islandora_object->id; @@ -424,6 +432,27 @@ function theme_islandora_datastream_version_link(array $vars) { } } +/** + * Renders a link that will re-create derivatives for a datastream. + * + * @param array $vars + * An array containing: + * - datastream: An AbstractDatastream to generate the version link from. + * + * @return string + * Markup. + */ +function theme_islandora_datastream_regenerate_link(array $vars) { + $datastream = $vars['datastream']; + $object = $datastream->parent; + $hooks = islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array($object)); + foreach ($hooks as $hook) { + if ($hook['destination_dsid'] == $datastream->id) { + return l(t('regenerate'), "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/regenerate"); + } + } +} + /** * Implements hook_preprocess(). */