You are here

webform_calculator.module in Webform Calculator 7.2

Same filename and directory in other branches
  1. 7 webform_calculator.module

File

webform_calculator.module
View source
<?php

define('WEBFORM_CALCULATOR_REGEX', '/\\{\\w+\\}/');

/**
 * Implements of hook_webform_component_info().
 */
function webform_calculator_webform_component_info() {
  $components = array();
  $components['formula'] = array(
    'label' => t('Formula'),
    'description' => t('Computes values of other fields.'),
    'features' => array(
      'required' => FALSE,
    ),
    'file' => 'components/formula.inc',
    'conditional_type' => 'numeric',
  );
  return $components;
}

/**
 * Implements hook_webform_submission_presave().
 */
function webform_calculator_webform_submission_presave($node, &$submission) {
  foreach ($node->webform['components'] as $component) {
    if ($component['type'] == 'formula') {
      $submission->data[$component['cid']][0] = webform_calculator_replace_formula_values($component, $node, $submission);
    }
  }

  // Do the exact same thing again, in case we missed any calculated fields that were dependent on other calculated fields.
  foreach ($node->webform['components'] as $component) {
    if ($component['type'] == 'formula') {
      $submission->data[$component['cid']][0] = webform_calculator_replace_formula_values($component, $node, $submission);
    }
  }
}

/**
 * Evaluate math formula and format result.
 *
 * @param $formula
 *   Mathematical formula (without tokens).
 * @param int $precision
 *   Round precision.
 * @param string $separator
 * @param string $point
 *
 * @return float Calculated value for given formula.
 * Calculated value for given formula.
 */
function webform_calculator_eval($formula, $precision = 1, $separator = '', $point = '.') {
  module_load_include('php', 'webform_calculator', 'matheval.class');
  $parser = new WebformEvalMath();
  $result = $parser
    ->evaluate($formula);
  $result = (string) round($result, $precision);
  if ($separator || $point != '.') {
    $pieces = explode($point, $result);
    $pieces[0] = number_format($pieces[0], 0, '.', $separator);
    $result = implode($point, $pieces);
  }
  return $result;
}

/**
 * Implements hook_theme().
 */
function webform_calculator_theme() {
  return array(
    webform_component_invoke('formula', 'theme'),
  );
}

/**
 * Get list of component names inside formula.
 *
 * @param $formula
 *   Formula to be searched in (with tokens).
 *
 * @return array
 *   Names of components that are used in formula as tokens.
 */
function webform_calculator_get_components_from_formula($formula) {
  $components = array();
  if (preg_match_all(WEBFORM_CALCULATOR_REGEX, $formula, $matches)) {
    foreach ((array) $matches[0] as $match) {
      $components[] = str_replace(array(
        '{',
        '}',
      ), array(
        '',
        '',
      ), $match);
    }
  }
  return $components;
}

/**
 * Replace tokens in formula with values of components and evaluate formula.
 *
 * @param $formula_component
 *   Formula compont.
 * @param $webform_node
 *   Webform's node.
 * @param $submission
 *   Webform submission.
 *
 * @return float|int
 *   Value of evaluated formula.
 */
function webform_calculator_replace_formula_values($formula_component, $webform_node, $submission) {
  $formula = $formula_component['value'];
  $components_from_formula = webform_calculator_get_components_from_formula($formula);

  // Get webform components keyed by form key.
  $components_by_key = array();
  foreach ($webform_node->webform['components'] as $component) {
    $components_by_key[$component['form_key']] = $component;
  }
  foreach ($components_from_formula as $component_key) {
    if (isset($components_by_key[$component_key])) {
      $component = $components_by_key[$component_key];
      $values = $submission->data[$component['cid']];
      $sum = 0;
      foreach ($values as $value) {
        $sum += $value;
      }
      $formula = str_replace('{' . $component_key . '}', '(' . $sum . ')', $formula);
    }
  }
  try {
    return webform_calculator_eval($formula, $formula_component['extra']['precision']);
  } catch (Exception $e) {
    watchdog_exception('webform_calculator', $e);
    return 0;
  }
}

/**
 * Implements hook_form_builder_element_types().
 * @param string $form_type
 * @param int $form_id
 * @return array
 */
function webform_calculator_form_builder_element_types($form_type, $form_id) {
  if ($form_type == 'webform') {
    drupal_add_css(drupal_get_path('module', 'webform_calculator') . '/formula.css');
    $fields = array(
      'formula' => array(
        'title' => t('Formula'),
        'weight' => -30,
        'properties' => array(
          'title',
          'value',
          'description',
          'field_prefix',
          'field_suffix',
          'hidden',
          'size',
          'title_display',
          'error_message',
          'precision',
        ),
      ),
    );
    if (function_exists('_form_builder_webform_default')) {
      $fields['formula']['default'] = _form_builder_webform_default('formula', array(), array(
        'name' => t('New formula'),
      ));
    }
    return $fields;
  }
}

/**
 * Implements hook_form_builder_preview_alter().
 */
function webform_calculator_form_builder_preview_alter(&$element, $form_type, $form_id) {
  if ($form_type == 'webform' && $element['#webform_component']['type'] == 'formula') {
    $element['#attributes']['placeholder'] = $element['#webform_component']['value'];
  }
}