From 95333c25342c62f631fde52e53b824d810a1b5d7 Mon Sep 17 00:00:00 2001 From: Alan Stanley Date: Mon, 19 Aug 2013 09:10:33 -0300 Subject: [PATCH] added management of deleted files --- css/islandora.theme.css | 18 +- includes/manage_deleted_objects.inc | 297 ++++++++++++++++++++++++++++ includes/object_properties.form.inc | 82 +++++++- includes/utilities.inc | 8 +- islandora.api.php | 12 ++ islandora.module | 62 +++--- 6 files changed, 421 insertions(+), 58 deletions(-) create mode 100644 includes/manage_deleted_objects.inc diff --git a/css/islandora.theme.css b/css/islandora.theme.css index 29f14e66..4ac4fddc 100644 --- a/css/islandora.theme.css +++ b/css/islandora.theme.css @@ -1,4 +1,4 @@ -/* +/* Document : islandora_basic_collection.theme Created on : May 23, 2012, 11:23:56 AM Description: @@ -11,16 +11,16 @@ dl.islandora-object-tn { float: left; - width: 20.8333%; - padding: 0 10px 0 0; margin: 1.5em 0; + padding: 0 10px 0 0; + width: 20.8333%; } dl.islandora-object-fields { + border-top: 0px solid #ddd; float: right; - width:79.1666%; - border-top:0px solid #ddd; margin: 1.5em 0; + width: 79.1666%; } .islandora-object-fields dt { @@ -28,16 +28,16 @@ dl.islandora-object-fields { } .islandora-object-fields dt.first { - border-top:0; + border-top: 0; } .islandora-object-fields dt, .islandora-object-fields dd { - padding:6px 2% 4px; - border-top:1px solid #ddd; + border-top: 1px solid #ddd; + padding: 6px 2% 4px; } .islandora-object-fields dt.first, .islandora-object-fields dd.first { border-top: 0; -} \ No newline at end of file +} diff --git a/includes/manage_deleted_objects.inc b/includes/manage_deleted_objects.inc new file mode 100644 index 00000000..b04b38c5 --- /dev/null +++ b/includes/manage_deleted_objects.inc @@ -0,0 +1,297 @@ +models); + foreach ($hooks as $hook) { + $temp = module_invoke_all($hook, $fedora_object); + if (!empty($temp)) { + $pids_to_restore = array_merge_recursive($pids_to_restore, $temp); + } + } + } + } + $batch = array( + 'title' => t('@descriptor selected objects', array('@descriptor' => $descriptor)), + 'file' => drupal_get_path('module', 'islandora') . '/includes/manage_deleted_objects.inc', + 'operations' => array(), + ); + + foreach ($pids_to_restore as $pid) { + $batch['operations'][] = array( + $action, + array($pid), + ); + } + batch_set($batch); +} + +/** + * The first form in the deletion managemnt process. + * + * @param array $form + * The Drupal form definition. + * @param array $form_state + * The Drupal form state. + * + * @return array + * The Drupal form definition. + */ +function islandora_delete_form_select_objects(array $form, array &$form_state) { + $form['previous'] = array( + '#type' => 'submit', + '#value' => t('Previous'), + '#attributes' => array('source' => 'previous'), + ); + $content_models = $form_state['values']['content_models']; + $chosen_contentmodels = array_filter($content_models); + $options = islandora_get_deleted_objects($chosen_contentmodels); + if (empty($options)) { + $form['message'] = array( + '#type' => 'markup', + '#markup' => t("There are no deleted objects with the selected content models in this repository."), + ); + return $form; + } + $form['propogate'] = array( + '#title' => t('Apply changes to related objects?'), + '#default_value' => TRUE, + '#description' => t("Objects associated with selected objects will also be restored. ie page objects associated with a book object."), + '#type' => 'checkbox', + ); + $form['chosen'] = array( + '#type' => 'hidden', + '#value' => $chosen_contentmodels, + ); + $form['objects_to_process'] = array( + '#type' => 'tableselect', + '#header' => array( + 'title' => t('Name'), + 'pid' => t('PID'), + 'content_model' => t('Content Model'), + ), + '#multiple' => TRUE, + '#options' => $options, + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Restore selected objects'), + '#attributes' => array('source' => 'restore'), + ); + + if (user_access(FEDORA_PURGE)) { + $form['purge'] = array( + '#type' => 'submit', + '#value' => t('Irrevocably purge selected objects'), + '#attributes' => array('source' => 'purge'), + ); + } + + return $form; +} + +/** + * The first form in the deletion management process. + * + * @param array $form + * The Drupal form definition. + * @param array $form_state + * The Drupal form state. + * + * @return array + * The Drupal form definition. + */ +function islandora_delete_form_contentmodels(array $form, array &$form_state) { + module_load_include('inc', 'islandora', 'includes/utilities'); + $contentmodels_with_deleted_members = islandora_get_contentmodels_with_deleted_members(); + if (empty($contentmodels_with_deleted_members)) { + $form['message'] = array( + '#type' => 'markup', + '#markup' => t("There are no deleted objects in this repository."), + ); + return $form; + } + $form['message'] = array( + '#type' => 'markup', + '#markup' => t("Select content models of deleted objects."), + ); + $table_element = islandora_content_model_select_table_form_element(NULL); + + foreach ($table_element['#options'] as $option) { + if (!in_array($option['pid'], $contentmodels_with_deleted_members)) { + unset($table_element['#options'][$option['pid']]); + } + } + if (isset($form_state['values']['chosen'])) { + $chosen_contentmodels = $form_state['values']['chosen']; + foreach ($table_element['#options'] as $option) { + if (in_array($option['pid'], $chosen_contentmodels)) { + $table_element['#default_value'][$option['pid']] = TRUE; + } + } + } + $form['content_models'] = $table_element; + $form['next'] = array( + '#type' => 'submit', + '#value' => t('Next'), + ); + + return $form; +} + +/** + * Gets PIDS of all deleted objects. + * + * @return array + * array of pids + */ +function islandora_get_deleted_objects($content_models) { + $qualifier = ''; + $last_content_model = key(array_slice($content_models, -1, 1, TRUE)); + foreach ($content_models as $content_model) { + $qualifier .= "\$subject "; + if ($content_model != $last_content_model) { + $qualifier .= ' or '; + } + } + $tuque = new IslandoraTuque(); + $repository = $tuque->repository; + $query = << +where ($qualifier) +and \$subject +and \$subject \$object +and \$subject \$title +STRING; + $objects = $repository->ri->itqlQuery($query, 'unlimited'); + $deleted_objects = array(); + foreach ($objects as $object) { + if ($object['object']['value'] != "fedora-system:FedoraObject-3.0") { + $pid = $object['subject']['value']; + $title = $object['title']['value']; + $content_model = islandora_object_load($object['object']['value']); + $deleted_objects[$pid] = array( + 'title' => $title, 'pid' => $pid, + 'content_model' => $content_model->label, + ); + } + } + return $deleted_objects; +} + +/** + * Gets PIDS of all content models associated with deleted objects. + * + * @return array + * array of content model pids + */ +function islandora_get_contentmodels_with_deleted_members() { + + $tuque = new IslandoraTuque(); + $repository = $tuque->repository; + $query = << +where \$subject +and \$subject \$object + +STRING; + $objects = $repository->ri->itqlQuery($query, 'unlimited'); + $content_models = array(); + foreach ($objects as $object) { + if ($object['object']['value'] != "fedora-system:FedoraObject-3.0") { + $content_models[] = $object['object']['value']; + } + } + return $content_models; +} + +/** + * Restores deleted object. + * + * @param String $pid + * PID of object to be restored + */ +function islandora_restore_object($pid) { + $fedora_object = islandora_object_load($pid); + $fedora_object->state = 'A'; +} + +/** + * Purges deleted object. + * + * @param String $pid + * PID of object to be restored + */ +function islandora_purge_object($pid) { + $fedora_object = islandora_object_load($pid); + $fedora_object->repository->purgeObject($pid); +} diff --git a/includes/object_properties.form.inc b/includes/object_properties.form.inc index 44d016b7..b42ccda8 100644 --- a/includes/object_properties.form.inc +++ b/includes/object_properties.form.inc @@ -21,6 +21,14 @@ function islandora_object_properties_form(array $form, array &$form_state, AbstractObject $object) { drupal_set_title($object->label); $form_state['object'] = $object; + $hooks = islandora_build_hook_list(ISLANDORA_UPDATE_RELATED_OBJECTS_PROPERTIES_HOOK, $object->models); + $related_objects_pids = array(); + foreach ($hooks as $hook) { + $temp = module_invoke_all($hook, $object); + if (!empty($temp)) { + $related_objects_pids = array_merge_recursive($related_objects_pids, $temp); + } + } return array( 'pid' => array( '#type' => 'hidden', @@ -54,6 +62,18 @@ function islandora_object_properties_form(array $form, array &$form_state, Abstr '#type' => 'select', '#options' => array('A' => 'Active', 'I' => 'Inactive', 'D' => 'Deleted'), ), + 'propogate' => array( + '#title' => t('Apply changes to related objects?'), + '#default_value' => TRUE, + '#description' => t("Changes to owner and state will applied to associated objects. ie page objects associated with a book object."), + '#type' => 'checkbox', + '#access' => count($related_objects_pids), + ), + 'related_pids' => array( + '#value' => $related_objects_pids, + '#type' => 'hidden', + '#access' => count($related_objects_pids), + ), 'submit' => array( '#type' => 'submit', '#value' => 'Update Properties', @@ -81,32 +101,54 @@ function islandora_object_properties_form_submit(array $form, array &$form_state $owner = $form_state['values']['object_owner']; $state = $form_state['values']['object_state']; $label = $form_state['values']['object_label']; + $propogate = $form_state['values']['propogate']; + $update_owners = FALSE; + $update_states = FALSE; if (isset($owner) && $owner != $object->owner) { try { $object->owner = $owner; + $update_owners = TRUE; drupal_set_message(t('Successfully updated owner %s', array('%s' => $owner))); } catch (Exception $e) { form_set_error('object_owner', t('Error updating owner %s', array('%s' => $e->getMessage()))); } } + + if (isset($label) && $label != $object->label) { + try { + $object->label = $label; + drupal_set_message(t('Successfully updated label %s', array('%s' => check_plain($label)))); + } + catch (Exception $e) { + form_set_error(t('Error updating label %s', array('%s' => $e->getMessage()))); + } + } if (isset($state) && $state != $object->state) { try { $object->state = $state; + $update_states = TRUE; drupal_set_message(t('Successfully updated state %s', array('%s' => $state))); } catch (Exception $e) { form_set_error('object_state', t('Error updating state %s', array('%s' => $e->getMessage()))); } } - if (isset($label) && $label != $object->label) { - try { - $object->label = $label; - drupal_set_message(t('Successfully updated label %s', array('%s' => check_plain($label)))); - } - catch (Exception $e) { - form_set_error(t('Error updating label %s', array('%s' => $e->getMessage()))); + if ($propogate && ($update_states || $update_owners)) { + $related_objects_pids = $form_state['values']['related_pids']; + $batch = array( + 'title' => t('Updating related objects'), + 'file' => drupal_get_path('module', 'islandora') . '/includes/object_properties.form.inc', + 'operations' => array(), + ); + + foreach ($related_objects_pids as $pid) { + $batch['operations'][] = array( + 'islandora_update_object_properties', + array($pid, $update_states, $state, $update_owners, $owner), + ); } + batch_set($batch); } } @@ -121,3 +163,29 @@ function islandora_object_properties_form_submit(array $form, array &$form_state function islandora_object_properties_form_delete(array $form, array &$form_state) { drupal_goto("islandora/object/{$form_state['values']['pid']}/delete"); } + +/** + * Updates object state. + * + * @param String $pid + * PID of object to be updated + * @param Boolean $update_states + * If TRUE, update object state + * @param String $state + * Desired object state + * @param Boolean $update_owners + * If TRUE, update Owner + * @param String $owner + * New Owner + */ +function islandora_update_object_properties($pid, $update_states, $state, $update_owners, $owner) { + $fedora_object = islandora_object_load($pid); + if ($fedora_object) { + if ($update_states) { + $fedora_object->state = $state; + } + if ($update_owners) { + $fedora_object->owner = $owner; + } + } +} diff --git a/includes/utilities.inc b/includes/utilities.inc index c8d1ae5e..3aed5e01 100644 --- a/includes/utilities.inc +++ b/includes/utilities.inc @@ -889,9 +889,7 @@ function islandora_as_renderable_array(&$markup_array) { if (!is_array($value)) { // Not a renderable array, just a string. Let's convert it to a // renderable '#markup' element. - $value = array( - '#markup' => $value, - ); + $value = array('#markup' => $value); } elseif (!isset($value['#type']) && !isset($value['#markup'])) { // A simple array--possibly the result of a recursive merge? Let's @@ -902,9 +900,7 @@ function islandora_as_renderable_array(&$markup_array) { // 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, - ); + $inner = array('#markup' => $inner); } } unset($inner); diff --git a/islandora.api.php b/islandora.api.php index 4d54a00f..478f41d4 100644 --- a/islandora.api.php +++ b/islandora.api.php @@ -541,3 +541,15 @@ function hook_islandora_datastream_access($op, $object, $user) { */ function hook_CMODEL_PID_islandora_datastream_access($op, $object, $user) { } + +/** + * Content model specific function to update related objects. + * + * @param FedoraObject $object + * FedoraObject representing original object. + * + * @return array + * Array of pids representing objects associated with original object. + */ +function islandora_book_islandora_bookCModel_islandora_update_related_objects($object) { +} diff --git a/islandora.module b/islandora.module index 7d2c0acb..a6a5956d 100644 --- a/islandora.module +++ b/islandora.module @@ -34,6 +34,7 @@ define('FEDORA_INGEST', 'ingest fedora objects'); define('FEDORA_PURGE', 'delete fedora objects and datastreams'); define('FEDORA_MANAGE_PROPERTIES', 'manage object properties'); define('ISLANDORA_VIEW_DATASTREAM_HISTORY', 'view old datastream versions'); +define('ISLANDORA_MANAGE_DELETED_OBJECTS', 'manage deleted objects'); // Hooks. define('ISLANDORA_VIEW_HOOK', 'islandora_view_object'); @@ -44,6 +45,7 @@ define('ISLANDORA_PRE_INGEST_HOOK', 'islandora_ingest_pre_ingest'); define('ISLANDORA_POST_INGEST_HOOK', 'islandora_ingest_post_ingest'); define('ISLANDORA_PRE_PURGE_OBJECT_HOOK', 'islandora_pre_purge_object'); define('ISLANDORA_POST_PURGE_OBJECT_HOOK', 'islandora_post_purge_object'); +define('ISLANDORA_UPDATE_RELATED_OBJECTS_PROPERTIES_HOOK', 'islandora_update_related_objects_properties'); // @todo Add Documentation. define('ISLANDORA_OBJECT_INGESTED_HOOK', 'islandora_object_ingested'); @@ -289,6 +291,15 @@ function islandora_menu() { 'access arguments' => array('administer site configuration'), 'type' => MENU_CALLBACK, ); + $items['restore/islandora'] = array( + 'title' => 'Manage Deleted Objects', + 'file' => 'includes/manage_deleted_objects.inc', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('islandora_deleted_objects_form'), + 'type' => MENU_NORMAL_ITEM, + 'access arguments' => array(ISLANDORA_MANAGE_DELETED_OBJECTS), + ); + return $items; } @@ -427,9 +438,7 @@ function islandora_permission() { function islandora_forms($form_id) { $forms = array(); if (strpos($form_id, 'islandora_solution_pack_form_') !== FALSE) { - $forms[$form_id] = array( - 'callback' => 'islandora_solution_pack_form', - ); + $forms[$form_id] = array('callback' => 'islandora_solution_pack_form'); } return $forms; } @@ -698,11 +707,7 @@ 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' => array( - '#markup' => $output, - ), - ); + return array('Default overview output' => array('#markup' => $output)); } /** @@ -755,11 +760,7 @@ 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' => array( - '#markup' => $output, - ), - ); + return array('Default Edit output' => array('#markup' => $output)); } /** @@ -797,13 +798,12 @@ function islandora_view_object(AbstractObject $object) { drupal_add_js(array( 'islandora' => array( 'print_img' => $path . '/images/print-icon.png'), - ), array( - 'type' => 'setting')); + ), array( + 'type' => 'setting')); drupal_add_js(array( 'islandora' => array( - 'print_link' => '/islandora/object/' . $object->id . '/print')), - array('type' => 'setting')); + 'print_link' => '/islandora/object/' . $object->id . '/print')), array('type' => 'setting')); drupal_add_js($path . '/js/add_print.js'); drupal_set_title($object->label); @@ -887,6 +887,7 @@ function islandora_drupal_title(AbstractObject $object) { return $object->label; } + /** * Renders the default view object page for the given object. * @@ -898,11 +899,7 @@ 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' => array( - '#markup' => $output, - ), - ); + return array('Default output' => array('#markup' => $output)); } /** @@ -940,11 +937,7 @@ function islandora_default_islandora_printer_object($object, $alter) { 'dc_array' => $variables, 'islandora_content' => $alter)); - return array( - 'Default output' => array( - '#markup' => $output, - ), - ); + return array('Default output' => array('#markup' => $output)); } /** @@ -1163,9 +1156,7 @@ function islandora_islandora_required_objects(IslandoraTuque $connection) { return array( 'islandora' => array( 'title' => 'Islandora', - 'objects' => array( - $root_collection, - ), + 'objects' => array($root_collection), ), ); } @@ -1341,6 +1332,7 @@ function islandora_entity_property_info() { return $info; } + /** * Menu callback downloads the given clip. */ @@ -1471,9 +1463,9 @@ function islandora_datastream_access($op, $datastream, $user = NULL) { // The datastream check returned FALSE, and one in the object or datastream // checks returned TRUE. $cache[$op][$datastream->parent->id][$datastream->id][$user->uid] = ( - !in_array(FALSE, $datastream_results, TRUE) && - (in_array(TRUE, $object_results, TRUE) || in_array(TRUE, $datastream_results, TRUE)) - ); + !in_array(FALSE, $datastream_results, TRUE) && + (in_array(TRUE, $object_results, TRUE) || in_array(TRUE, $datastream_results, TRUE)) + ); } return $cache[$op][$datastream->parent->id][$datastream->id][$user->uid]; @@ -1487,8 +1479,6 @@ function islandora_islandora_basic_collection_get_query_filters() { if ($enforced) { $namespace_array = islandora_get_allowed_namespaces(); $namespace_sparql = implode('|', $namespace_array); - return format_string('regex(str(?object), "info:fedora/(!namespaces):")', array( - '!namespaces' => $namespace_sparql, - )); + return format_string('regex(str(?object), "info:fedora/(!namespaces):")', array('!namespaces' => $namespace_sparql)); } }