From 28b3deedccf63a3b66de38699d4ce807122a95ad Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Fri, 20 Dec 2013 22:24:50 +0000 Subject: [PATCH 1/4] Add derivative regeneration to the UI. --- includes/datastream.inc | 2 +- includes/object_properties.form.inc | 24 ++++ includes/regenerate_derivatives.form.inc | 163 +++++++++++++++++++++++ islandora.module | 30 ++++- theme/theme.inc | 31 ++++- 5 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 includes/regenerate_derivatives.form.inc diff --git a/includes/datastream.inc b/includes/datastream.inc index 1d506e3d..c9976cad 100644 --- a/includes/datastream.inc +++ b/includes/datastream.inc @@ -312,7 +312,7 @@ function islandora_edit_datastream(AbstractDatastream $datastream) { case 0: // No edit implementations. drupal_set_message(t('There are no edit methods specified for this datastream.')); - drupal_goto("islandora/object/{$object->id}/manage/datastreams"); + drupal_goto("islandora/object/{$datastream->parent->id}/manage/datastreams"); break; case 1: 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..917154ea --- /dev/null +++ b/includes/regenerate_derivatives.form.inc @@ -0,0 +1,163 @@ + $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}/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) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $object = $form_state['object']; + $batch = islandora_regenerate_object_derivatives_batch($object); + batch_set($batch); + $form_state['redirect'] = "islandora/object/{$object}/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) { + return array( + 'title' => t('Regenerating all derivatives for @label', array('@label' => $object->label)), + 'operations' => array( + array('islandora_regenerate_object_derivatives_batch_operation', array($object)), + ), + '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', + ); +} + +/** + * Defines the regenerate object derivatives batch operation. + * + * @param AbstractObject $object + * A AbstractObject representing an object within Fedora. + * @param array $context + * An array containing the context of the current batch. + */ +function islandora_regenerate_object_derivatives_batch_operation(AbstractObject $object, &$context) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $logging_results = islandora_do_derivatives($object, array( + 'force' => TRUE, + )); + islandora_derivative_logging($logging_results); +} + +/** + * 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) { + return array( + 'title' => t('Regenerating derivatives for the @dsid datastream', array('@dsid' => $datastream->id)), + 'operations' => array( + array('islandora_regenerate_datastream_derivative_batch_operation', array($datastream)), + ), + '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', + ); +} + +/** + * Defines the regenerate datastream derivative batch operation. + * + * @param AbstractDatastream $datastream + * A AbstractDatastream representing a datastream on an object within Fedora. + * @param array $context + * An array containing the context of the current batch. + */ +function islandora_regenerate_datastream_derivative_batch_operation(AbstractDatastream $datastream, &$context) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $logging_results = islandora_do_derivatives($datastream->parent, array( + 'force' => TRUE, + 'destination_dsid' => $datastream->id, + )); + islandora_derivative_logging($logging_results); +} 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..e057771c 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(); @@ -79,6 +79,14 @@ function islandora_preprocess_islandora_default_edit(array &$variables) { 'datastream' => $ds, )), ); + if (user_access(ISLANDORA_REGENERATE_DERIVATIVES)) { + $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(). */ From 6405a453ce2306ec1744f68e51c03fc575ba8e37 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Fri, 10 Jan 2014 20:24:20 +0000 Subject: [PATCH 2/4] Batch each derivative operation individually. --- includes/derivatives.inc | 57 +++++++++++++++++++++++ includes/regenerate_derivatives.form.inc | 59 +++++++++++++++++++++--- 2 files changed, 110 insertions(+), 6 deletions(-) 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/regenerate_derivatives.form.inc b/includes/regenerate_derivatives.form.inc index 917154ea..e9c1b986 100644 --- a/includes/regenerate_derivatives.form.inc +++ b/includes/regenerate_derivatives.form.inc @@ -97,13 +97,12 @@ function islandora_regenerate_object_derivatives_form_submit(array $form, array function islandora_regenerate_object_derivatives_batch(AbstractObject $object) { return array( 'title' => t('Regenerating all derivatives for @label', array('@label' => $object->label)), - 'operations' => array( - array('islandora_regenerate_object_derivatives_batch_operation', array($object)), - ), + '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', ); } @@ -135,13 +134,15 @@ function islandora_regenerate_object_derivatives_batch_operation(AbstractObject function islandora_regenerate_datastream_derivative_batch(AbstractDatastream $datastream) { return array( 'title' => t('Regenerating derivatives for the @dsid datastream', array('@dsid' => $datastream->id)), - 'operations' => array( - array('islandora_regenerate_datastream_derivative_batch_operation', array($datastream)), - ), + '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', ); } @@ -161,3 +162,49 @@ function islandora_regenerate_datastream_derivative_batch_operation(AbstractData )); islandora_derivative_logging($logging_results); } + +/** + * 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']); + } +} From 6c340bfbecf1467ba95b33625342e1e1366e4baf Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Mon, 13 Jan 2014 12:50:44 +0000 Subject: [PATCH 3/4] Remove superfluous functions. --- includes/regenerate_derivatives.form.inc | 33 ------------------------ 1 file changed, 33 deletions(-) diff --git a/includes/regenerate_derivatives.form.inc b/includes/regenerate_derivatives.form.inc index e9c1b986..5c0dcef7 100644 --- a/includes/regenerate_derivatives.form.inc +++ b/includes/regenerate_derivatives.form.inc @@ -106,22 +106,6 @@ function islandora_regenerate_object_derivatives_batch(AbstractObject $object) { ); } -/** - * Defines the regenerate object derivatives batch operation. - * - * @param AbstractObject $object - * A AbstractObject representing an object within Fedora. - * @param array $context - * An array containing the context of the current batch. - */ -function islandora_regenerate_object_derivatives_batch_operation(AbstractObject $object, &$context) { - module_load_include('inc', 'islandora', 'includes/derivatives'); - $logging_results = islandora_do_derivatives($object, array( - 'force' => TRUE, - )); - islandora_derivative_logging($logging_results); -} - /** * Creates a batch to go out and re-create the derivative for a datastream. * @@ -146,23 +130,6 @@ function islandora_regenerate_datastream_derivative_batch(AbstractDatastream $da ); } -/** - * Defines the regenerate datastream derivative batch operation. - * - * @param AbstractDatastream $datastream - * A AbstractDatastream representing a datastream on an object within Fedora. - * @param array $context - * An array containing the context of the current batch. - */ -function islandora_regenerate_datastream_derivative_batch_operation(AbstractDatastream $datastream, &$context) { - module_load_include('inc', 'islandora', 'includes/derivatives'); - $logging_results = islandora_do_derivatives($datastream->parent, array( - 'force' => TRUE, - 'destination_dsid' => $datastream->id, - )); - islandora_derivative_logging($logging_results); -} - /** * Wrapper to call out to batch operations. * From 63ce9e2b633f02086311e94c33b355bee13e1811 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Mon, 13 Jan 2014 19:03:36 +0000 Subject: [PATCH 4/4] Changes based on code review. --- includes/regenerate_derivatives.form.inc | 7 ++++--- theme/theme.inc | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/includes/regenerate_derivatives.form.inc b/includes/regenerate_derivatives.form.inc index 5c0dcef7..a7ef147c 100644 --- a/includes/regenerate_derivatives.form.inc +++ b/includes/regenerate_derivatives.form.inc @@ -62,7 +62,7 @@ function islandora_regenerate_object_derivatives_form(array $form, array &$form_ $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}/manage/properties", + "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') @@ -78,11 +78,10 @@ function islandora_regenerate_object_derivatives_form(array $form, array &$form_ * The Drupal form state. */ function islandora_regenerate_object_derivatives_form_submit(array $form, array &$form_state) { - module_load_include('inc', 'islandora', 'includes/derivatives'); $object = $form_state['object']; $batch = islandora_regenerate_object_derivatives_batch($object); batch_set($batch); - $form_state['redirect'] = "islandora/object/{$object}/manage/properties"; + $form_state['redirect'] = "islandora/object/{$object->id}/manage/properties"; } /** @@ -95,6 +94,7 @@ function islandora_regenerate_object_derivatives_form_submit(array $form, 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)), @@ -116,6 +116,7 @@ function islandora_regenerate_object_derivatives_batch(AbstractObject $object) { * 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( diff --git a/theme/theme.inc b/theme/theme.inc index e057771c..0e62f0d7 100644 --- a/theme/theme.inc +++ b/theme/theme.inc @@ -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,7 +79,7 @@ function islandora_preprocess_islandora_default_edit(array &$variables) { 'datastream' => $ds, )), ); - if (user_access(ISLANDORA_REGENERATE_DERIVATIVES)) { + if (islandora_datastream_access(ISLANDORA_REGENERATE_DERIVATIVES, $ds)) { $row[] = array( 'class' => 'datastream-regenerate', 'data' => theme('islandora_datastream_regenerate_link', array(