|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* Defines the multi-page ingest form and any relevant hooks and functions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the given configuration can be used to display the ingest form.
|
|
|
|
*
|
|
|
|
* @param array $configuration
|
|
|
|
* The list of key/value pairs of configuration.
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
* TRUE if the give configuration defines one or more form steps, FALSE
|
|
|
|
* otherwise.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_can_display_ingest_form(array $configuration) {
|
|
|
|
$form_state = array();
|
|
|
|
islandora_ingest_form_init_form_state_storage($form_state, $configuration);
|
|
|
|
$form_steps = islandora_ingest_form_get_form_steps($form_state);
|
|
|
|
// Forget the stubbed steps for the remainder of this request.
|
|
|
|
drupal_static_reset('islandora_ingest_form_get_steps');
|
|
|
|
return count($form_steps) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ingest form build function.
|
|
|
|
*
|
|
|
|
* Initializes the form state, and builds the initial list of steps, excutes
|
|
|
|
* the current step.
|
|
|
|
*
|
|
|
|
* @param array $form
|
|
|
|
* The Drupal form.
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
* @param array $configuration
|
|
|
|
* An associative array of configuration values that are used to build the
|
|
|
|
* list of steps to be executed, including:
|
|
|
|
* - id: The PID with which the object should be created.
|
|
|
|
* - namespace: The PID namespace in which the object should be created.
|
|
|
|
* (id is used first, if it is given).
|
|
|
|
* - label: The initial label for the object. Defaults to "New Object".
|
|
|
|
* - collections: An array of collection PIDs, to which the new object should
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form(array $form, array &$form_state, array $configuration) {
|
|
|
|
try {
|
|
|
|
islandora_ingest_form_init_form_state_storage($form_state, $configuration);
|
|
|
|
return islandora_ingest_form_execute_step($form, $form_state);
|
|
|
|
}
|
|
|
|
catch (Exception $e) {
|
|
|
|
watchdog(
|
|
|
|
'islandora',
|
|
|
|
'Exception during ingest form processing with Message: "@exception", and Trace: @trace',
|
|
|
|
array('@exception' => $e->getMessage(), '@trace' => $e->getTraceAsString()),
|
|
|
|
WATCHDOG_ERROR
|
|
|
|
);
|
|
|
|
drupal_set_message($e->getMessage(), 'error');
|
|
|
|
return array(array(
|
|
|
|
'#markup' => l(t('Back'), 'javascript:window.history.back();', array('external' => TRUE))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes the form_state storage for use in the ingest multi-page forms.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
* @param array $configuration
|
|
|
|
* A list of key value pairs that are used to build the list of steps to be
|
|
|
|
* executed.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_init_form_state_storage(array &$form_state, array $configuration) {
|
|
|
|
if (empty($form_state['islandora'])) {
|
|
|
|
$configuration['models'] = isset($configuration['models']) ? $configuration['models'] : array();
|
|
|
|
// Make sure the models actually exist.
|
|
|
|
foreach ($configuration['models'] as $key => $model) {
|
|
|
|
if (!islandora_object_load($model)) {
|
|
|
|
unset($configuration['models'][$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Required for step hooks.
|
|
|
|
$form_state['islandora'] = array(
|
|
|
|
'step_id' => NULL,
|
|
|
|
'objects' => $configuration['objects'],
|
|
|
|
'shared_storage' => $configuration,
|
|
|
|
'step_storage' => array(),
|
|
|
|
);
|
|
|
|
// No need to persist the 'objects' within the configuration.
|
|
|
|
unset($configuration['objects']);
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the given/current 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 current step is returned if no step ID is given.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The given/current step if found, NULL otherwise.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_get_step(array &$form_state, $step_id = NULL) {
|
|
|
|
$step_id = isset($step_id) ? $step_id : islandora_ingest_form_get_current_step_id($form_state);
|
|
|
|
$steps = islandora_ingest_form_get_steps($form_state);
|
|
|
|
if (isset($step_id) && isset($steps[$step_id])) {
|
|
|
|
return $steps[$step_id];
|
|
|
|
}
|
|
|
|
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 array $step
|
|
|
|
* The step relative to the result, if not provided the current step is used.
|
|
|
|
*
|
|
|
|
* @return array|null
|
|
|
|
* 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 array $step
|
|
|
|
* The step relative to the result, if not provided the current step is used.
|
|
|
|
*
|
|
|
|
* @return array|null
|
|
|
|
* 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 the current step is not defined it's assumed that all steps have executed.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
* The step ID.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_get_current_step_id(array &$form_state) {
|
|
|
|
return $form_state['islandora']['step_id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the ID of 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_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 = NULL) {
|
|
|
|
$step_id = isset($step_id) ? $step_id : islandora_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);
|
|
|
|
if ($index !== FALSE && ++$index < $count) {
|
|
|
|
return $step_ids[$index];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the ID of the previous 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 = 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) {
|
|
|
|
return $step_ids[$index];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Increments the current step if possible.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_increment_step(array &$form_state) {
|
|
|
|
// When going to the next step rebuild the list of steps as the submit
|
|
|
|
// 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);
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal 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;
|
|
|
|
islandora_ingest_form_grab_info($form_state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Executes the current step.
|
|
|
|
*
|
|
|
|
* Builds the form definition and appends on any additonal elements required
|
|
|
|
* for the step to function.
|
|
|
|
*
|
|
|
|
* @param array $form
|
|
|
|
* The Drupal form.
|
|
|
|
* @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 array
|
|
|
|
* The form definition of the current step.
|
|
|
|
*/
|
|
|
|
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 = isset($step_id) ? islandora_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':
|
|
|
|
return islandora_ingest_form_execute_form_step($form, $form_state, $step);
|
|
|
|
|
|
|
|
case 'batch':
|
|
|
|
// @todo Implement if possible.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
* @param array $step
|
|
|
|
* The step we are executing.
|
|
|
|
*
|
|
|
|
* @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;
|
|
|
|
$shared_storage = islandora_ingest_form_get_shared_storage($form_state);
|
|
|
|
// Build the form step.
|
|
|
|
$form = call_user_func_array($step['form_id'], $args);
|
|
|
|
// Since the list of steps depends on the shared storage we will rebuild the
|
|
|
|
// list of steps if the shared storage has changed. This must be done before
|
|
|
|
// stepifying, so the prev/next buttons get updated.
|
|
|
|
if ($shared_storage != islandora_ingest_form_get_shared_storage($form_state)) {
|
|
|
|
drupal_static_reset('islandora_ingest_form_get_steps');
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
* @param array $step
|
|
|
|
* The step that execution begins from.
|
|
|
|
*/
|
|
|
|
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.
|
|
|
|
* @param array $step
|
|
|
|
* The step currently being executed.
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
if (isset($step['do_function']['file'])) {
|
|
|
|
require_once drupal_get_path('module', $step['module']) . "/" . $step['do_function']['file'];
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
* @param array $step
|
|
|
|
* The step that execution begins from.
|
|
|
|
*/
|
|
|
|
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.
|
|
|
|
* @param array $step
|
|
|
|
* The step which the undo callback is being called on.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_undo_callback_step(array $form, array &$form_state, array $step) {
|
|
|
|
if (isset($step['undo_function'])) {
|
|
|
|
$args = array(&$form_state);
|
|
|
|
$args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args;
|
|
|
|
if (isset($step['undo_function']['file'])) {
|
|
|
|
require_once drupal_get_path('module', $step['module']) . "/" . $step['undo_function']['file'];
|
|
|
|
}
|
|
|
|
call_user_func_array($step['undo_function']['function'], $args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append Prev/Next buttons submit/validation handlers etc.
|
|
|
|
*
|
|
|
|
* @param array $form
|
|
|
|
* The Drupal form.
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
* @param array $step
|
|
|
|
* An array defining a ingest step.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The stepified Drupal form definition for the given step.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_stepify(array $form, array &$form_state, array $step) {
|
|
|
|
$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['form_step_id'] = array(
|
|
|
|
'#type' => 'hidden',
|
|
|
|
'#value' => islandora_ingest_form_get_current_step_id($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);
|
|
|
|
// Duplicate next button and hide it at the top of the form so that the form
|
|
|
|
// always triggers "next" if the user submits the form with the enter key.
|
|
|
|
if (!is_null($form['prev'])) {
|
|
|
|
$form['hidden_next'] = $form['next'];
|
|
|
|
$form['hidden_next']['#weight'] = -99;
|
|
|
|
$form['hidden_next']['#prefix'] = '<div style="display:none;">';
|
|
|
|
$form['hidden_next']['#suffix'] = '</div>';
|
|
|
|
}
|
|
|
|
// 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 form step.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
* TRUE if we are currently on the first step, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
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 form step.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
* TRUE if we are currently on the last step, FALSE otherwise.
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Defines the previous button for the ingest form.
|
|
|
|
*
|
|
|
|
* Adds submit handlers for the form step if they exist.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* 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 steps
|
|
|
|
// to undo whatever its submit handler did.
|
|
|
|
$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('islandora_ingest_form_previous_submit', $submit_callback) : array('islandora_ingest_form_previous_submit');
|
|
|
|
return array(
|
|
|
|
'#type' => 'submit',
|
|
|
|
'#value' => t('Previous'),
|
|
|
|
'#name' => 'prev',
|
|
|
|
'#submit' => $submit,
|
|
|
|
// #limit_validation_errors, is why when the previous button is pressed no
|
|
|
|
// values persisted in the form_state, but its also what allows us to go
|
|
|
|
// back when validation errors occur. To have a better solution going
|
|
|
|
// forward we can either limit validation only on required fields, or we can
|
|
|
|
// convert all required fields to use #element_validation functions, and
|
|
|
|
// Remove the need for #limit_validation_errors. Or maybe there is some
|
|
|
|
// other solution, regardless of what it is, it won't be standard.
|
|
|
|
'#limit_validation_errors' => array(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The submit handler for the ingest form previous button.
|
|
|
|
*
|
|
|
|
* Stores the current form steps values in the form storage.
|
|
|
|
* Moves the focus of the multi-page ingest form back one step.
|
|
|
|
* Restores the form values for the previous step.
|
|
|
|
*
|
|
|
|
* @param array $form
|
|
|
|
* The Drupal form.
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Defines the next button for the ingest form.
|
|
|
|
*
|
|
|
|
* Adds submit/validate handlers for the form step if they exist.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The next button for the ingest form.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_next_button(array &$form_state) {
|
|
|
|
$step = islandora_ingest_form_get_step($form_state);
|
|
|
|
$form_id = $step['form_id'];
|
|
|
|
$validate_callback = $form_id . '_validate';
|
|
|
|
$validate = function_exists($validate_callback) ? array($validate_callback) : NULL;
|
|
|
|
$submit_callback = $form_id . '_submit';
|
|
|
|
$submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_next_submit') : array('islandora_ingest_form_next_submit');
|
|
|
|
return array(
|
|
|
|
'#type' => 'submit',
|
|
|
|
'#value' => t('Next'),
|
|
|
|
'#name' => 'next',
|
|
|
|
'#validate' => $validate,
|
|
|
|
'#submit' => $submit,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The submit handler for the ingest form next button.
|
|
|
|
*
|
|
|
|
* Stores the current form steps values in the form storage.
|
|
|
|
* Moves the focus of the multi-page ingest form forward one step.
|
|
|
|
* Restores the form values for the next step if present.
|
|
|
|
*
|
|
|
|
* @param array $form
|
|
|
|
* The Drupal form.
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_next_submit(array $form, array &$form_state) {
|
|
|
|
islandora_ingest_form_increment_step($form_state);
|
|
|
|
$form_state['rebuild'] = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Push current info into the current step's storage.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_stash_info(array &$form_state) {
|
|
|
|
$storage = &islandora_ingest_form_get_step_storage($form_state);
|
|
|
|
if ($storage && isset($form_state['values'])) {
|
|
|
|
$storage['values'] = $form_state['values'];
|
|
|
|
unset($form_state['values']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pops the info for the given step from storage into the form_state.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_grab_info(array &$form_state) {
|
|
|
|
$storage = islandora_ingest_form_get_step_storage($form_state);
|
|
|
|
$form_state['values'] = isset($storage['values']) ? $storage['values'] : array();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Defines the ingest button for the ingest form.
|
|
|
|
*
|
|
|
|
* This button is only shown on the last page of the multi-page ingest form.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The ingest button for the ingest form.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_ingest_button(array &$form_state) {
|
|
|
|
$step = islandora_ingest_form_get_step($form_state);
|
|
|
|
$form_id = $step['form_id'];
|
|
|
|
$validate_callback = $form_id . '_validate';
|
|
|
|
$validate = function_exists($validate_callback) ? array($validate_callback) : NULL;
|
|
|
|
$submit_callback = $form_id . '_submit';
|
|
|
|
$submit = function_exists($submit_callback) ? array(
|
|
|
|
$submit_callback,
|
|
|
|
'islandora_ingest_form_pre_submit',
|
|
|
|
'islandora_ingest_form_submit',
|
|
|
|
) : array('islandora_ingest_form_pre_submit', 'islandora_ingest_form_submit');
|
|
|
|
return array(
|
|
|
|
'#type' => 'submit',
|
|
|
|
'#name' => 'ingest',
|
|
|
|
'#value' => t('Ingest'),
|
|
|
|
'#process' => array('islandora_ingest_form_ingest_button_process'),
|
|
|
|
'#validate' => $validate,
|
|
|
|
'#submit' => $submit,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process hook for the ingest button, adds the please wait spinning icon.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_ingest_button_process(array $element) {
|
|
|
|
$settings['spinner'][$element['#id']] = array(
|
|
|
|
'message' => t('Please be patient while the the page loads.'),
|
|
|
|
'options' => array(
|
|
|
|
'lines' => 10,
|
|
|
|
'length' => 20,
|
|
|
|
'width' => 10,
|
|
|
|
'radius' => 30,
|
|
|
|
'corners' => 1,
|
|
|
|
'rotate' => 0,
|
|
|
|
'direction' => 1,
|
|
|
|
'color' => '#000',
|
|
|
|
'speed' => 1,
|
|
|
|
'trail' => 60,
|
|
|
|
'shadow' => FALSE,
|
|
|
|
'hwaccel' => FALSE,
|
|
|
|
'className' => 'spinner',
|
|
|
|
'zIndex' => 2000000000,
|
|
|
|
'top' => 'auto',
|
|
|
|
'left' => 'auto',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
drupal_add_js($settings, 'setting');
|
|
|
|
$islandora_path = drupal_get_path('module', 'islandora');
|
|
|
|
$element['#attached'] = array(
|
|
|
|
'js' => array(
|
|
|
|
"$islandora_path/js/spin/spin.min.js",
|
|
|
|
"$islandora_path/js/spinner.js",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
$element['#attributes']['class'][] = 'islandora-spinner-submit';
|
|
|
|
return $element;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The submit handler for the ingest form.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
$set_redirect = isset($form_state['redirect']) ? FALSE : TRUE;
|
|
|
|
foreach ($form_state['islandora']['objects'] as &$object) {
|
|
|
|
try {
|
|
|
|
islandora_add_object($object);
|
|
|
|
// We want to redirect to the first object as it's considered to be the
|
|
|
|
// primary object.
|
|
|
|
if ($set_redirect) {
|
|
|
|
$form_state['redirect'] = "islandora/object/{$object->id}";
|
|
|
|
$set_redirect = FALSE;
|
|
|
|
}
|
|
|
|
drupal_set_message(
|
|
|
|
t('"@label" (ID: @pid) has been ingested.', array('@label' => $object->label, '@pid' => $object->id)),
|
|
|
|
'status');
|
|
|
|
}
|
|
|
|
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',
|
|
|
|
'Exception during ingest with Message: "@exception", and Trace: @trace',
|
|
|
|
array('@exception' => $e->getMessage(), '@trace' => $e->getTraceAsString()),
|
|
|
|
WATCHDOG_ERROR
|
|
|
|
);
|
|
|
|
drupal_set_message(
|
|
|
|
t('A problem occured while ingesting "@label" (ID: @pid), please notify 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a reference to the stored NewFedoraObject's.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* A reference to the stored NewFedoraObjects to be ingested when the final
|
|
|
|
* step submits.
|
|
|
|
*/
|
|
|
|
function &islandora_ingest_form_get_objects(array &$form_state) {
|
|
|
|
return $form_state['islandora']['objects'];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a single object from the stored NewFedoraObject's.
|
|
|
|
*
|
|
|
|
* @note In our current use case we are only dealing with a single object
|
|
|
|
* ingest, this makes it convenient to access it. Ideally the steps
|
|
|
|
* implementations will be abstracted to be indifferent to what object it's
|
|
|
|
* currently working on. This will act as a placeholder for such
|
|
|
|
* functionality.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return NewFedoraObject
|
|
|
|
* Returns the 'current' object in the array of NewFedoraObjects, generally
|
|
|
|
* this is only used when there is one object in the list of objects.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_get_object(array &$form_state) {
|
|
|
|
$objects = &islandora_ingest_form_get_objects($form_state);
|
|
|
|
return reset($objects);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get general storage for the given/current step.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
* @param array $step_id
|
|
|
|
* The ID of the step.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The given/current step storage if found, NULL otherwise.
|
|
|
|
*/
|
|
|
|
function &islandora_ingest_form_get_step_storage(array &$form_state, $step_id = NULL) {
|
|
|
|
$step_id = isset($step_id) ? $step_id : islandora_ingest_form_get_current_step_id($form_state);
|
|
|
|
if (isset($step_id)) {
|
|
|
|
if (!isset($form_state['islandora']['step_storage'][$step_id])) {
|
|
|
|
$form_state['islandora']['step_storage'][$step_id] = array();
|
|
|
|
}
|
|
|
|
return $form_state['islandora']['step_storage'][$step_id];
|
|
|
|
}
|
|
|
|
$undefined_step_storage = array();
|
|
|
|
return $undefined_step_storage;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the configuration used to create the multi-page ingest form.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The configuration used to generate the multi-page ingest forms.
|
|
|
|
*/
|
|
|
|
function &islandora_ingest_form_get_shared_storage(array &$form_state) {
|
|
|
|
return $form_state['islandora']['shared_storage'];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call form_load_include, for the current step if it defines a required file.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_load_include(array &$form_state) {
|
|
|
|
form_load_include($form_state, 'inc', 'islandora', 'includes/ingest.form');
|
|
|
|
$step = islandora_ingest_form_get_step($form_state);
|
|
|
|
// Load include files.
|
|
|
|
if (isset($step['file']) && isset($step['module'])) {
|
|
|
|
$matches = array();
|
|
|
|
preg_match('/^(.*)\.(.*)$/', $step['file'], $matches);
|
|
|
|
list($file, $name, $type) = $matches;
|
|
|
|
form_load_include($form_state, $type, $step['module'], $name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Buildes the initial list of ingest steps.
|
|
|
|
*
|
|
|
|
* Sorted by weight expected range between -50 to 50.
|
|
|
|
*
|
|
|
|
* The sort order is undefined for steps which have the same weight.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The list of sorted ingest steps as defined by all implementers
|
|
|
|
* of ISLANDORA_INGEST_STEP_HOOK.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_get_steps(array &$form_state) {
|
|
|
|
module_load_include('inc', 'islandora', 'includes/utilities');
|
|
|
|
$steps = &drupal_static(__FUNCTION__);
|
|
|
|
if (isset($steps)) {
|
|
|
|
return $steps;
|
|
|
|
}
|
|
|
|
$steps = array();
|
|
|
|
$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);
|
|
|
|
$steps = array_merge($steps, $module_steps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$steps = array_filter($steps);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filter the ingest steps to only steps of type 'form'.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The list of sorted ingest form steps as defined by all implementers
|
|
|
|
* of ISLANDORA_INGEST_STEP_HOOK.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_get_form_steps(array &$form_state) {
|
|
|
|
$steps = islandora_ingest_form_get_steps($form_state);
|
|
|
|
$form_step_filter = function($o) {
|
|
|
|
return $o['type'] == 'form';
|
|
|
|
};
|
|
|
|
return array_filter($steps, $form_step_filter);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filter the ingest steps to only steps of type 'form'.
|
|
|
|
*
|
|
|
|
* @param array $form_state
|
|
|
|
* The Drupal form state.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
* The list of sorted ingest callback steps as defined by all implementers
|
|
|
|
* of ISLANDORA_INGEST_STEP_HOOK.
|
|
|
|
*/
|
|
|
|
function islandora_ingest_form_get_callback_steps(array &$form_state) {
|
|
|
|
$steps = islandora_ingest_form_get_steps($form_state);
|
|
|
|
$callback_step_filter = function($o) {
|
|
|
|
return $o['type'] == 'callback';
|
|
|
|
};
|
|
|
|
return array_filter($steps, $callback_step_filter);
|
|
|
|
}
|