<?php
// $Id: webform_php.module,v 1.1.2.1 2010/04/08 05:33:51 quicksketch Exp $

/**
 * @file
 * Enables Webform to execute PHP code upon validation or submission.
 *
 * Generally speaking, as the author of this module, I discourage actually
 * using it. Webform had this functionality in version 2 and I created this
 * module so that I could remove it from newer versions. As a responsible
 * developer, you should NEVER put code into the database. Such code is prone
 * to error, hard to update, and even harder to debug when things go wrong.
 *
 * As such, absolutely no support is provided for this module. The only good
 * use of this module should be to look at how the webform_php_form_alter()
 * function is written, then imitate this approach in your own small custom
 * module.
 */

/**
 * Implements hook_permission().
 */
function webform_php_permission() {
  return array(
    'use PHP for additional processing' => array(
      'title' => t('use PHP for additional processing'),
      'description' => t('Allows execution of PHP code for validation and submission post-processing'),
    ),
  );
}

/**
 * Implements hook_form_alter().
 */
function webform_php_form_alter(&$form, &$form_state, $form_id) {
  // Affect all Webform forms.
  if (substr($form_id, 0, 20) == 'webform_client_form_') {
    // Simply add the additional validate handler.
    $form['#validate'][] = 'webform_php_client_validate';

    // Add the submit handler after the existing Webform submit handler,
    // but before the second Webform handler. Pop off the first one and add
    // ours second.
    $first = array_shift($form['#submit']);
    array_unshift($form['#submit'], $first, 'webform_php_client_submit');
  }

  // Add the additional validation and submit fields to the form settings.
  if ($form_id == 'webform_configure_form' && user_access('use PHP for additional processing')) {
    webform_php_configure_form($form, $form_state);
  }
}

/**
 * FAPI #validate handler. Execute PHP validation handling.
 */
function webform_php_client_validate($form, &$form_state) {
  $node = node_load($form_state['values']['details']['nid']);

  if (substr($node->webform['additional_validate'], 0, 2) == '<?') {
    // Flatten trees within the submission.
    $form_state['values']['submitted_tree'] = $form_state['values']['submitted'];
    $form_state['values']['submitted'] = _webform_client_form_submit_flatten($node, $form_state['values']['submitted']);

    // Support for Drupal 5 validation code.
    $form_values = & $form_state['values'];
    // We use eval here (rather than drupal_eval) because the user needs access to local variables.
    eval('?>' . $node->webform['additional_validate']);

    // Restore the original form state so that the submit handler can reflatten.
    $form_state['values']['submitted'] = $form_state['values']['submitted_tree'];
  }
}

/**
 * FAPI #submit handler. Execute PHP submit handling.
 */
function webform_php_client_submit($form, &$form_state) {
  $node = node_load($form_state['values']['details']['nid']);

  if (substr($node->webform['additional_submit'], 0, 2) == '<?') {
    // Support for Drupal 5 validation code.
    $form_values = & $form_state['values'];
    // We use eval here (rather than drupal_eval) because the user needs access to local variables.
    eval('?>' . $node->webform['additional_submit']);
  }
}

/**
 * Form for additional validate and submission entry.
 */
function webform_php_configure_form(&$form, $form_state) {
  $node = node_load($form['nid']['#value']);

  $variables = theme('item_list', array('items' => array(
      '$node: ' . t('The complete node object for the webform.'),
      '$form_state: ' . t('The current state of the submission. Usually you will check the contents of $form_state[\'values\'][\'submitted\'] for user-entered values.'),
    )));

  $form['php'] = array(
    '#type' => 'fieldset',
    '#title' => t('Additional PHP processing'),
    '#collapsible' => TRUE,
    '#collapsed' => empty($node->webform['additional_validate']) && empty($node->webform['additional_submit']),
    '#description' => t('PHP may be used to add additional functionality to your form. The code must start with &lt;?php in order to be executed. The following variables are available in both fields:') . $variables,
    '#weight' => 10,
  );

  $form['php']['additional_validate'] = array(
    '#type' => 'textarea',
    '#title' => t('Additional validation'),
    '#description' => t('If validation fails, use the <a href="http://api.drupal.org/api/drupal/includes--form.inc/function/form_set_error/7">form_set_error()</a> function to prevent the form from being submitted. This code is executed after every page of a webform. For examples of validation code, see the <a href="http://drupal.org/handbook/modules/webform/validation-code">Webform handbook on validation code</a>.'),
    '#default_value' => $node->webform['additional_validate'],
    '#cols' => 40,
    '#rows' => 10,
  );

  $form['php']['additional_submit'] = array(
    '#type' => 'textarea',
    '#title' => t('Additional processing'),
    '#description' => t('Additional processing code can be used to save data to external sources or modify the data before it is saved. This code is only executed after all validation has passed and the entire form has been completed. For examples of processing code, see the <a href="http://drupal.org/handbook/modules/webform/submission-code">Webform handbook on submission code</a>'),
    '#default_value' => $node->webform['additional_submit'],
    '#cols' => 40,
    '#rows' => 10,
  );

  $form['#submit'][] = 'webform_php_configure_form_submit';
}

/**
 * Additional submit handler for the webform_configure_form() form.
 */
function webform_php_configure_form_submit($form, $form_state) {

  db_update('webform')
  ->fields(array(
    'additional_validate' => $form_state['values']['additional_validate'],
    'additional_submit' => $form_state['values']['additional_submit'],
  ))
  ->condition('nid', $form_state['values']['nid'])
  ->execute();
  
}
