Generic entry point to handle forms.
We do this for consistency and to make it easy to chain forms together.
function views_ui_ajax_form($js, $key, ViewUI $view, $display_id = '') {
// Reset the cache of IDs. Drupal rather aggressively prevents ID
// duplication but this causes it to remember IDs that are no longer even
// being used.
$seen_ids_init =& drupal_static('drupal_html_id:init');
$seen_ids_init = array();
$form = views_ui_ajax_forms($key);
if (empty($form)) {
return MENU_NOT_FOUND;
}
views_include('ajax');
$args = func_get_args();
// Remove the known args
array_splice($args, 0, 4);
$form_state = $view
->buildFormState($js, $key, $display_id, $args);
// check to see if this is the top form of the stack. If it is, pop
// it off; if it isn't, the user clicked somewhere else and the stack is
// now irrelevant.
if (!empty($view->stack)) {
$identifier = $view
->buildIdentifier($key, $display_id, $args);
// Retrieve the first form from the stack without changing the integer keys,
// as they're being used for the "2 of 3" progress indicator.
reset($view->stack);
list($key, $top) = each($view->stack);
unset($view->stack[$key]);
if (array_shift($top) != $identifier) {
$view->stack = array();
}
}
// Automatically remove the form cache if it is set and the key does
// not match. This way navigating away from the form without hitting
// update will work.
if (isset($view->form_cache) && $view->form_cache['key'] != $key) {
unset($view->form_cache);
}
// With the below logic, we may end up rendering a form twice (or two forms
// each sharing the same element ids), potentially resulting in
// drupal_add_js() being called twice to add the same setting. drupal_get_js()
// is ok with that, but until ajax_render() is (http://drupal.org/node/208611),
// reset the drupal_add_js() static before rendering the second time.
$drupal_add_js_original = drupal_add_js();
$drupal_add_js =& drupal_static('drupal_add_js');
$output = views_ajax_form_wrapper($form_state['form_id'], $form_state);
if ($form_state['submitted'] && empty($form_state['rerender'])) {
// Sometimes we need to re-generate the form for multi-step type operations.
$object = NULL;
if (!empty($view->stack)) {
$drupal_add_js = $drupal_add_js_original;
$stack = $view->stack;
$top = array_shift($stack);
$top[0] = $js;
$form_state = call_user_func_array(array(
$view,
'buildFormState',
), $top);
$form_state['input'] = array();
$form_state['url'] = url(views_ui_build_form_url($form_state));
if (!$js) {
return drupal_goto(views_ui_build_form_url($form_state));
}
$output = views_ajax_form_wrapper($form_state['form_id'], $form_state);
}
elseif (!$js) {
// if nothing on the stack, non-js forms just go back to the main view editor.
return drupal_goto("admin/structure/views/view/{$view->get('name')}/edit");
}
else {
$output = array();
$output[] = views_ajax_command_dismiss_form();
$output[] = views_ajax_command_show_buttons();
$output[] = views_ajax_command_trigger_preview();
if (!empty($form_state['#page_title'])) {
$output[] = views_ajax_command_replace_title($form_state['#page_title']);
}
}
// If this form was for view-wide changes, there's no need to regenerate
// the display section of the form.
if ($display_id !== '') {
entity_form_controller('view', 'edit')
->rebuildCurrentTab($view, $output, $display_id);
}
}
return $js ? array(
'#type' => 'ajax',
'#commands' => $output,
) : $output;
}