You are here

function botcha_form_alter_botcha in BOTCHA Spam Prevention 7

Same name and namespace in other branches
  1. 6 botcha.botcha.inc \botcha_form_alter_botcha()

Main BOTCHA worker - process the form and apply BOTCHA protection

1 call to botcha_form_alter_botcha()
botcha_form_alter in ./botcha.module
Implements hook_form_alter().

File

./botcha.botcha.inc, line 565
Implementation of botcha form logic.

Code

function botcha_form_alter_botcha(&$form, &$form_state, $form_id, $botcha) {

  // When we are altering a form, there are one or two build IDs.
  // $form['#build_id'] is for the new form (always present)
  // $_POST['form_build_id'] is for previous form submission (only if the form is being submitted)
  // Herein lies the problem - we need to build new form based on form's build_id to present
  // to the user, but check the BOTCHA fields in previous form submission based on post's build_id.
  $build_id = $form['#build_id'];
  $build_id_subm = isset($_POST['form_build_id']) ? $_POST['form_build_id'] : FALSE;
  $form_state['botcha_submit_values'] = array();
  if ($build_id_subm) {

    // Generate Secret for submitted build id
    $secret = md5($build_id_subm . BOTCHA_SECRET);
    $recipes = _botcha_recipes($form, $botcha, $secret);

    // Save submitted values in our stash for later use in _validate, as we have to reset them here at _form_alter stage.
    // It won't be possible to reset after validation as there is no reliable mechanism in Form API,
    // i.e. form_set_value() does not change rendered form and form errors disable whole 'rebuild' business.
    foreach ($recipes as $recipe) {
      if (isset($recipe->form_elements)) {
        foreach ($recipe->form_elements as $field => $value) {
          if (isset($_POST[$field])) {
            $form_state['botcha_submit_values'][$field] = $_POST[$field];
          }
        }
      }
    }

    // Save recipes for later use in _validate
    $form_state['#botcha_recipes_subm'] = $recipes;
  }

  // Generate Secret for this build id
  $secret = md5($build_id . BOTCHA_SECRET);
  $recipes = _botcha_recipes($form, $botcha, $secret);

  // Save recipes for later use in _validate
  $form_state['#botcha_recipes'] = $recipes;

  // Common javascript?
  //  drupal_add_js(drupal_get_path('module', 'botcha') . '/botcha.js');
  $added_botchas = array();
  $jss = array();
  $csss = array();
  foreach ($recipes as $recipe) {
    if (isset($recipe->form_elements)) {
      foreach ($recipe->form_elements as $field => $value) {
        unset($value['!valid_token']);
        $form[$field] = $value;
        if ($build_id_subm && isset($value['#default_value'])) {

          // Reset our controls to defaults here (as explained above).
          $form[$field]['#value'] = $value['#default_value'];
          $form_state['post'][$field] = $value['#default_value'];
          $_POST[$field] = $value['#default_value'];
        }
      }
    }
    if (isset($recipe->js)) {
      drupal_add_js($recipe->js, array(
        'type' => 'inline',
        'preprocess' => FALSE,
      ));
      $jss[] = $recipe->js;
    }
    if (isset($recipe->css)) {
      drupal_add_css('' . $recipe->css . '', array(
        'type' => 'inline',
      ));
      $csss[] = $recipe->css;
    }
    $added_botchas[] = $recipe->name;
  }

  // user_login forms open session in validate hooks instead of submit
  // we should be the first to validate - add our hook to the beginning
  if (is_array($form['#validate'])) {
    array_unshift($form['#validate'], '_botcha_form_validate');
  }
  else {
    $form['#validate'] = array(
      '_botcha_form_validate',
    );
  }
  $form_state['#botcha'] = $botcha;

  //  // Add a submit handler to remove form state storage.
  //  $form['#submit'][] = '_botcha_form_submit';
  if (BOTCHA_LOGLEVEL >= 4) {
    watchdog(BOTCHA_LOG, '%form_id form prepared by BOTCHA: added recipes - !botchas!more', array(
      '%form_id' => $form_id,
      '!botchas' => join(', ', $added_botchas),
      '!more' => '' . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'POST=<pre>' . print_r(_botcha_filter_value($_POST), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'GET=<pre>' . print_r(_botcha_filter_value($_GET), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'SERVER=<pre>' . print_r($_SERVER, 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'form=<pre>' . print_r(_botcha_filter_form_log($form), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 && count($jss) ? '<br /><br />' . 'JS=<pre>' . join("\n", $jss) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 && count($csss) ? '<br /><br />' . 'CSS=<pre>' . join("\n", $csss) . '</pre>' : ''),
    ), WATCHDOG_NOTICE);
  }
  if ($build_id_subm != $build_id) {
    $form_state['post']['form_build_id'] = $build_id;

    // Issue the client a new build_id, make sure that the form has it set in the hidden field
  }
  _botcha_set_form_cache($build_id);

  // Save build id
}