Why does this webform uploaded file via ajax throw an error in Drupal 7?

1.9k views Asked by At

I have a webform and mymodule which alters it. The webform has a field stelle which gets populated based on the url query. For instance, if ?stelle=10 the field gets populated by the title of node with nid 10. If the query ?stelle is non-existant or followed by a nid which does not exist (is not of a certain content type) or does not contain a certain string the form will be redirecting to mynode?stelle=initiativ. The form has 2 fields to upload files via ajax, works good so far. Here is my code:

<?php

/**
 * Altering the form! this will add class to the file upload/ remove buttons
 */
function mymodule_form_alter(&$form, &$form_state, $form_id) {
    $conf = mymodule_defaults();

    if ($form_id == 'webform_client_form_' . $conf['nid']) {
        if (isset($form['submitted']['field1'])) {
            $form['submitted']['field1']['#process'] = array('mymodule_my_file_element_process');
        }

        if (isset($form['submitted']['field2'])) {
            $form['submitted']['field2']['#process'] = array('mymodule_my_file_element_process');
        }

        $nid = $form['#node']->nid;
        $form['actions']['submit']['#ajax'] = array(
            'callback' => 'mymodule_webform_js_submit',
            'wrapper' => 'webform-client-form-' . $nid,
            'method' => 'replace',
            'effect' => 'fade',
        );

        $redirect_form = false;
        $maintenance = false;

        if (isset($form['submitted']['stelle']['#default_value']) && $form['submitted']['stelle']['#default_value'] !== '') {
            $hide_components = array(
                'einleitung_standard',
                'einleitung_initiativ',
            );
            $unhide_components = array();

            if ($form['submitted']['stelle']['#default_value'] == '') {
                $redirect_form = true;
            }
            elseif (is_numeric($form['submitted']['stelle']['#default_value'])) {
                $nid = $form['submitted']['stelle']['#default_value'];
                $node = node_load($nid);

                if ($node === false || (isset($node->type) && $node->type !== 'job')) {
                    $redirect_form = true;
                }
                else {
                    $type = $node->type;
                    if ($type == 'job') {
                        $form['submitted']['stelle']['#default_value'] = $node->title;
                        $form['submitted']['stelle']['#attributes']['disabled'] = 'disabled';
                        $form['submitted']['related']['#value'] = $nid;

                        $unhide_components = array(
                            'einleitung_standard'
                        );
                    }
                }
            }
            elseif ($form['submitted']['stelle']['#default_value'] == 'initiativ') {
                // unset($form['submitted']['stelle']);
                $form['submitted']['related']['#value'] = 'initiativ';
                $unhide_components = array(
                    'einleitung_initiativ'
                );
            }
        }
        else {
            // $redirect_form = true;
            // this causes an error

        }

This is the weird part:

        $redirect_form = false;
        $maintenance = false;

        if (isset($form['submitted']['stelle']['#default_value']) && $form['submitted']['stelle']['#default_value'] !== '') {
        ...
        else {
            // $redirect_form = true;
            // this causes an error

        }

When I active the line to redirect the form when the if condition is false, the button to upload a file via ajax throws an error alert on click (see bottom for error). To me, this looks like the form alter hook is being called again when the file upload button is clicked without having my field stelle available - is that right? How to fix this?

And now the rest of the module, basically just alterings:

        else {
            // $redirect_form = true;
            // this causes an error

        }

        foreach ($unhide_components as $key => $component) {
            if (is_array($component)) {
                foreach ($component as $_key => $_component) {
                    $index = array_search($_component, $hide_components[$key]);
                    if ($index !== false) {
                        unset($hide_components[$key][$index]);
                    }
                }
            }
            else {
                $index = array_search($component, $hide_components);
                if ($index !== false) {
                    unset($hide_components[$index]);
                }   
            }
        }

        // hide
        foreach ($hide_components as $k=>$hc1){
            if (is_array($hc1)) {
                foreach ($hc1 as $hc2) unset($form['submitted'][$k][$hc2]);
            } else {
                unset($form['submitted'][$hc1]);
            }
        }


        if ($redirect_form) drupal_goto('node/'.$conf['nid'], array('query'=>array('stelle'=>'initiativ')), 301);
    }
}

function mymodule_my_file_element_process($element, &$form_state, $form) {
    $element = file_managed_file_process($element, $form_state, $form);
    $element['upload_button']['#attributes'] = array('class' => array('button'));
    $prefix = '<label class="browse-slave">';
    $prefix .= '<span class="button">' . t('Choose a file') . '</span>';
    $element['upload']['#prefix'] = $prefix;
    $element['upload_button']['#prefix'] = '</label>';


    $element['remove_button']['#attributes'] = array('class' => array('button'));
    $element['remove_button']['#prefix'] = '</label>';

    return $element;
}

function mymodule_webform_js_submit($form, $form_state) {
  // define the $sid variable (submission id from webform)
  $sid = $form_state['values']['details']['sid'];
  // if we have a sid then we know the form was properly submitted, otherwise, we'll just return the existing $form array
  if ($sid) {
    // first we have to load up the webform node object
    $node = node_load($form_state['values']['details']['nid']);
    // create an array up with the confirmation message, retreived from the webform node
    $confirmation = array(
      '#type' => 'markup',
      '#markup' => check_markup($node->webform['confirmation'], $node->webform['confirmation_format'], '', TRUE),
    );
    // return the confirmation message
    return $confirmation;
  }
  else {
    // return the form
    return $form;
  }
}

The AJAX error is something like described here. Changing server/php settings didnt help it.

Thanks!

2

There are 2 answers

1
Charlie Schliesser On BEST ANSWER

The form builder (and any hook alters) will be run when a form is validated, which happens on #ajax actions.

I like to throw static custom data in $form['#someProperty'] so that it's available in the build, validate, and submit functions. Something like this should help you:

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  // ...
  if (isset($_GET['stelle'])) {
    $form['#stelle'] = $_GET['stelle']; // This will always be there.
  } 
  // ...
}

Another option would be to throw the $node that you load in the form, like $form['#stelle_node'] = node_load(...) and obviously only do that when the nid is actually available to you, so that you don't overwrite it with empty data when the form builder runs again in the future.

0
Sachin9 On

When i was working with ajax in drupal 6 the hash symbol in url or request caused an error everytime..... so i replaced url with this

         data.url.replace(/%2523/, '%23');