@ -26,6 +26,8 @@
* be related.
* - models: An array of content model PIDs, to which the new object might
* subscribe
* - parent: The parent of the child to be ingested. This is needed for XACML
* to correctly apply the parent's POLICY to children.
*
* @return array
* The form definition of the current step.
@ -82,9 +84,42 @@ function islandora_ingest_form_init_form_state_storage(array &$form_state, array
'shared_storage' => $configuration,
'step_storage' => array(),
);
// Must be called after $form_state['islandora'] is initialized, otherwise,
// the values in 'islandora' would not be availible to the step hooks.
$form_state['islandora']['step_id'] = islandora_ingest_form_get_first_step_id($form_state);
}
}
/**
* Get the first step ID.
*
* @param array $form_state
* The Drupal form state.
*
* @return string
* The 'id' of the very first step.
*/
function islandora_ingest_form_get_first_step_id(array & $form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
$keys = array_keys($steps);
return array_shift($keys);
}
/**
* Get the last step ID.
*
* @param array $form_state
* The Drupal form state.
*
* @return string
* The 'id' of the very last step.
*/
function islandora_ingest_form_get_last_step_id(array & $form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
$keys = array_keys($steps);
return array_pop($keys);
}
/**
* Prepares a new object based on the given configuration.
*
@ -113,13 +148,12 @@ function islandora_ingest_form_prepare_new_object(array $configuration) {
/**
* Gets the given/current step.
*
* The current step is returned if no step ID is given. If the current step is
* not defined it's assume to be the first step.
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step_id
* The ID of the step.
* The ID of the step. The current step is returned if no step ID is given.
*
* @return array
* The given/current step if found, NULL otherwise.
@ -133,10 +167,48 @@ function islandora_ingest_form_get_step(array &$form_state, $step_id = NULL) {
return NULL;
}
/**
* Gets the next step.
*
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step
* The step relative to the result, if not provided the current step is used.
*
* @return string
* The next step if found, NULL otherwise.
*/
function islandora_ingest_form_get_next_step(array & $form_state, array $step = NULL) {
$step = isset($step) ? $step : islandora_ingest_form_get_step($form_state);
$next_step_id = islandora_ingest_form_get_next_step_id($form_state, $step['id']);
return isset($next_step_id) ? islandora_ingest_form_get_step($form_state, $next_step_id) : NULL;
}
/**
* Gets the previous step.
*
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step
* The step relative to the result, if not provided the current step is used.
*
* @return string
* The next step if found, NULL otherwise.
*/
function islandora_ingest_form_get_previous_step(array & $form_state, array $step = NULL) {
$step = isset($step) ? $step : islandora_ingest_form_get_step($form_state);
$previous_step_id = islandora_ingest_form_get_previous_step_id($form_state, $step['id']);
return isset($previous_step_id) ? islandora_ingest_form_get_step($form_state, $previous_step_id) : NULL;
}
/**
* Gets the ID of the current step.
*
* If a current step is not defined, its assumed to be the first step.
* If the current step is not defined it's assumed that all steps have executed .
*
* @param array $form_state
* The Drupal form state.
@ -145,27 +217,25 @@ function islandora_ingest_form_get_step(array &$form_state, $step_id = NULL) {
* The step ID.
*/
function islandora_ingest_form_get_current_step_id(array & $form_state) {
if (empty($form_state['islandora']['step_id'])) {
$steps = islandora_ingest_form_get_steps($form_state);
$keys = array_keys($steps);
return array_shift($keys);
}
return $form_state['islandora']['step_id'];
}
/**
* Gets the ID of the next step.
*
* If a current step is not defined, its assumed to be the first step .
* If the current step is not defined it's assumed that all steps have executed .
*
* @param array $form_state
* The Drupal form state.
* @param string $step_id
* The ID of the step relative to the result, if not provided the current
* step_id is used.
*
* @return string
* The next step ID if found, NULL otherwise.
*/
function islandora_ingest_form_get_next_step_id(array & $form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
function islandora_ingest_form_get_next_step_id(array & $form_state, $step_id = NULL ) {
$step_id = isset($step_id) ? $step_id : is landora_ingest_form_get_current_step_id($form_state);
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
$index = array_search($step_id, $step_ids);
$count = count($step_ids);
@ -178,16 +248,25 @@ function islandora_ingest_form_get_next_step_id(array &$form_state) {
/**
* Gets the ID of the previous step.
*
* If a current step is not defined, its assumed to be the first step.
* If the current step is not defined it's assumed that all steps have executed.
* In such cases the last step will be returned.
*
* @param array $form_state
* The Drupal form state.
* @param string $step_id
* The ID of the step relative to the result, if not provided the current
* step_id is used.
*
* @return string
* The previous step ID if found, NULL otherwise.
*/
function islandora_ingest_form_get_previous_step_id(array & $form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
function islandora_ingest_form_get_previous_step_id(array & $form_state, $step_id = NULL) {
$step_id = isset($step_id) ? $step_id : islandora_ingest_form_get_current_step_id($form_state);
// If the current step is not defined it's assumed that all steps have
// executed. So return the very last step.
if ($step_id == NULL) {
return islandora_ingest_form_get_last_step_id($form_state);
}
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
$index = array_search($step_id, $step_ids);
if ($index !== FALSE & & --$index >= 0) {
@ -207,12 +286,10 @@ function islandora_ingest_form_increment_step(array &$form_state) {
// of the current step could have added/removed a step.
drupal_static_reset('islandora_ingest_form_get_steps');
$next_step_id = islandora_ingest_form_get_next_step_id($form_state);
if (isset($next_step_id)) {
islandora_ingest_form_stash_info($form_state);
$form_state['islandora']['step_id'] = $next_step_id;
islandora_ingest_form_grab_info($form_state);
}
}
/**
* Decrement the current step if possible.
@ -222,6 +299,7 @@ function islandora_ingest_form_increment_step(array &$form_state) {
*/
function islandora_ingest_form_decrement_step(array & $form_state) {
$previous_step_id = islandora_ingest_form_get_previous_step_id($form_state);
// Don't decrement passed the first step.
if (isset($previous_step_id)) {
islandora_ingest_form_stash_info($form_state);
$form_state['islandora']['step_id'] = $previous_step_id;
@ -233,13 +311,15 @@ function islandora_ingest_form_decrement_step(array &$form_state) {
* Build a list of steps given only configuration.
*
* XXX: This is used to give an indication of whether there are any steps for a
* given list of content models .
* given configuration .
*
* @param array $configuration
* The list of key/value pairs of configuration.
*/
function islandora_ingest_get_approximate_steps(array $configuration) {
try {
// @todo, we need to expand the configuration before we can validate it?
// I think this need some thinking.
islandora_ingest_form_validate_configuration($configuration);
}
catch (InvalidArgumentException $e) {
@ -270,16 +350,19 @@ function islandora_ingest_get_approximate_steps(array $configuration) {
* @return array
* The form definition of the current step.
*/
function islandora_ingest_form_execute_step(array $form, array & $form_state) {
function islandora_ingest_form_execute_step(array $form, array & $form_state, $step_id = NULL ) {
// Load any required files for the current step.
islandora_ingest_form_load_include($form_state);
$step = islandora_ingest_form_get_step($form_state);
$step = isset($step_id) ? is landora_ingest_form_get_step($form_state) : islandora_ingest_form_get_step($form_state, $step_id );
switch ($step['type']) {
case 'callback':
// Execute all the consecutive callbacks, and move then attempt to process
// the next step.
islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
return islandora_ingest_form_execute_step($form, $form_state);
case 'form':
$args = array($form, &$form_state);
$args = isset($step['args']) ? array_merge($args, $step['args']) : $args;
$form = call_user_func_array($step['form_id'], $args);
return islandora_ingest_form_stepify($form, $form_state, $step);
return islandora_ingest_form_execute_form_step($form, $form_state, $step);
case 'batch':
// @todo Implement if possible.
@ -288,6 +371,94 @@ function islandora_ingest_form_execute_step(array $form, array &$form_state) {
return array();
}
/**
* Execute the given 'form' step.
*
* Assumes the given step is a 'form' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*
* @return array
* The form definition of the given step.
*/
function islandora_ingest_form_execute_form_step(array $form, array & $form_state, array $step) {
$args = array($form, &$form_state);
$args = isset($step['args']) ? array_merge($args, $step['args']) : $args;
$form = call_user_func_array($step['form_id'], $args);
return islandora_ingest_form_stepify($form, $form_state, $step);
}
/**
* Execute the given 'callback' step and any consecutive 'callback' steps.
*
* Assumes the given step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_execute_consecutive_callback_steps(array $form, array & $form_state, array $step) {
do {
islandora_ingest_form_execute_callback_step($form, $form_state, $step);
islandora_ingest_form_increment_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
} while (isset($step) & & $step['type'] == 'callback');
}
/**
* Execute the given 'callback' step.
*
* Assumes the given step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_execute_callback_step(array $form, array & $form_state, array $step) {
$args = array(&$form_state);
$args = isset($step['do_function']['args']) ? array_merge($args, $step['do_function']['args']) : $args;
call_user_func_array($step['do_function']['function'], $args);
}
/**
* Undo the given 'callback' step and any consecutive 'callback' steps.
*
* Assumes the given $step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_undo_consecutive_callback_steps(array $form, array & $form_state, array $step) {
do {
islandora_ingest_form_undo_callback_step($form, $form_state, $step);
islandora_ingest_form_decrement_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
} while (isset($step) & & $step['type'] == 'callback');
}
/**
* Undo the given 'callback' step.
*
* Assumes the given $step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_undo_callback_step(array $form, array & $form_state, array $step) {
$args = array(&$form_state);
$args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args;
call_user_func_array($step['undo_function']['function'], $args);
}
/**
* Append Prev/Next buttons submit/validation handlers etc.
*
@ -297,22 +468,20 @@ function islandora_ingest_form_execute_step(array $form, array &$form_state) {
* The Drupal form state.
*
* @return array
* The stepified d rupal form definition for the given step.
* The stepified D rupal form definition for the given step.
*/
function islandora_ingest_form_stepify(array $form, array & $form_state, $step) {
$first_step = islandora_ingest_form_on_first_step($form_state);
$last_step = islandora_ingest_form_on_last_step($form_state);
$form['prev'] = $first_step ? NULL : islandora_ingest_form_previous_button($form_state);
$form['next'] = $last_step ? islandora_ingest_form_ingest_button($form_state) : islandora_ingest_form_next_button($form_state);
$first_form_step = islandora_ingest_form_on_first_form_step($form_state);
$last_form_step = islandora_ingest_form_on_last_form_step($form_state);
$form['prev'] = $first_form_step ? NULL : islandora_ingest_form_previous_button($form_state);
$form['next'] = $last_form_step ? islandora_ingest_form_ingest_button($form_state) : islandora_ingest_form_next_button($form_state);
// Allow for a hook_form_FORM_ID_alter().
drupal_alter(array('form_' . $step['form_id'], 'form'), $form, $form_state, $step['form_id']);
return $form;
}
/**
* Checks if we are on the first step.
* Checks if we are on the first form step.
*
* @param array $form_state
* The Drupal form state.
@ -320,14 +489,12 @@ function islandora_ingest_form_stepify(array $form, array &$form_state, $step) {
* @return bool
* TRUE if we are currently on the first step, FALSE otherwise.
*/
function islandora_ingest_form_on_first_step(array & $form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
return array_search($step_id, $step_ids) == 0;
function islandora_ingest_form_on_first_form_step(array & $form_state) {
return !islandora_ingest_form_get_previous_form_step($form_state);
}
/**
* Checks if we are on the last step.
* Checks if we are on the last form step.
*
* @param array $form_state
* The Drupal form state.
@ -335,11 +502,42 @@ function islandora_ingest_form_on_first_step(array &$form_state) {
* @return bool
* TRUE if we are currently on the last step, FALSE otherwise.
*/
function islandora_ingest_form_on_last_step(array & $form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
$count = count($step_ids);
return array_search($step_id, $step_ids) == --$count;
function islandora_ingest_form_on_last_form_step(array & $form_state) {
return !islandora_ingest_form_get_next_form_step($form_state);
}
/**
* Get the previous form step relative to the current step.
*
* @param array $form_state
* The Drupal form state.
*
* @return array
* The previous form step if one exists, NULL otherwise.
*/
function islandora_ingest_form_get_previous_form_step(array & $form_state) {
$step = NULL;
do {
$step = islandora_ingest_form_get_previous_step($form_state, $step);
} while (isset($step) & & $step['type'] != 'form');
return $step;
}
/**
* Get the next form step relative to the current step.
*
* @param array $form_state
* The Drupal form state.
*
* @return array
* The next form step if one exists, NULL otherwise.
*/
function islandora_ingest_form_get_next_form_step(array & $form_state) {
$step = NULL;
do {
$step = islandora_ingest_form_get_next_step($form_state, $step);
} while (isset($step) & & $step['type'] != 'form');
return $step;
}
/**
@ -354,13 +552,12 @@ function islandora_ingest_form_on_last_step(array &$form_state) {
* The previous button for the ingest form.
*/
function islandora_ingest_form_previous_button(array & $form_state) {
// Before we move back to the previous step we should tell the previous step
// Before we move back to the previous step we should tell the previous steps
// to undo whatever its submit handler did.
$prev_step_id = islandora_ingest_form_get_previous_step_id($form_state);
$prev_step = islandora_ingest_form_get_step($form_state, $prev_step_id);
$form_id = $prev_step['form_id'];
$prev_form_step = islandora_ingest_form_get_previous_form_step($form_state);
$form_id = $prev_form_step['form_id'];
$submit_callback = $form_id . '_undo_submit';
$submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_previous_submit') : array('islandora_ingest_form_undo _submit');
$submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_previous_submit') : array('islandora_ingest_form_previous _submit');
return array(
'#type' => 'submit',
'#value' => t('Previous'),
@ -391,6 +588,11 @@ function islandora_ingest_form_previous_button(array &$form_state) {
*/
function islandora_ingest_form_previous_submit(array $form, array & $form_state) {
islandora_ingest_form_decrement_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
// Undo all callbacks that occured after the previous step.
if ($step['type'] == 'callback') {
islandora_ingest_form_undo_consecutive_callback_steps($form, $form_state, $step);
}
$form_state['rebuild'] = TRUE;
}
@ -446,9 +648,11 @@ function islandora_ingest_form_next_submit(array $form, array &$form_state) {
*/
function islandora_ingest_form_stash_info(array & $form_state) {
$storage = &islandora_ingest_form_get_step_storage($form_state);
if ($storage) {
$storage['values'] = $form_state['values'];
unset($form_state['values']);
}
}
/**
* Pops the info for the given step from storage into the form_state.
@ -493,12 +697,17 @@ function islandora_ingest_form_ingest_button(array &$form_state) {
*
* Attempts to ingest every object built by the previous steps.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_submit(array $form, array & $form_state) {
// Execute any remaining callbacks.
islandora_ingest_form_increment_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
if (isset($step) & & $step['type'] == 'callback') {
islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
}
// Ingest the objects.
foreach ($form_state['islandora']['objects'] as $object) {
try {
islandora_add_object($object);
@ -507,7 +716,7 @@ function islandora_ingest_form_submit(array $form, array &$form_state) {
catch (Exception $e) {
// If post hooks throws it may already exist at this point but may be
// invalid, so don't say failed.
watchdog('islandora', $e->getMessage(), NULL , WATCHDOG_ERROR);
watchdog('islandora', 'Exception Message: @exception.', array('@exception' => $e->getMessage()) , WATCHDOG_ERROR);
drupal_set_message(t('A problem occured while ingesting "@label" (ID: @pid), please notifiy the administrator.', array('@label' => $object->label, '@pid' => $object->id)), 'error');
}
}
@ -567,7 +776,8 @@ function &islandora_ingest_form_get_step_storage(array &$form_state, $step_id =
}
return $form_state['islandora']['step_storage'][$step_id];
}
return NULL;
$undefined_step_storage = array();
return $undefined_step_storage;
}
/**
@ -625,6 +835,8 @@ function islandora_ingest_form_get_steps(array &$form_state) {
$shared_storage = &islandora_ingest_form_get_shared_storage($form_state);
foreach (islandora_build_hook_list(ISLANDORA_INGEST_STEP_HOOK, $shared_storage['models']) as $hook) {
// Required for pass by reference.
// @todo Change this around so that it isn't passed by reference, there
// Is an alter below that can handle that requirement.
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
$module_steps = (array) $function($form_state);
@ -635,6 +847,10 @@ function islandora_ingest_form_get_steps(array &$form_state) {
foreach (islandora_build_hook_list(ISLANDORA_INGEST_STEP_HOOK, $shared_storage['models']) as $hook) {
drupal_alter($hook, $steps, $form_state);
}
// Add any defaults.
foreach ($steps as $key => & $step) {
$step['id'] = $key;
}
uasort($steps, 'drupal_sort_weight');
return $steps;
}