Experimental project

This is a sandbox project, which contains experimental code for developer use only.

This module replaces and supercedes the Webform Computed Component project at http://drupal.org/sandbox/vernond/1301484

This module provides a way to calculate values for Webform components and/or to add custom validation code without the need for creating custom modules that implement hooks. It offers a PHP-like macro scripting language to use instead.

Differs from Webform PHP in that there is no eval() evil and macro code has no direct access to Drupal environment or functions, i.e. macro code is contextually jailed.

Differs also from Webform Calculator in that it permits logic-driven calculations and also integrates with the Webform Validation module.

Requirements

PHP 5.2
Drupal 6.26 or 7.14
Webform (required)
Webform Validation (optional)
PHP-Parser external library (required - see installation instructions in README.txt)

Try out a simple demo here: http://www.webformcookbook.com/content/demo-webform-macro

There is no real limit to the amount of code a macro may contain, but anything over 15 lines of code probably indicates that you would be better off with a separate custom module.

Once the stability and usefulness/demand of the module is reasonably established, some effort will be made to attempt bringing the functionality client-side (see future plans on module help page).

Lexing and parsing of the macro language is performed by the required external library called PHP Parser, made available by github user nikic.

The Webform Macro programming language is a mimicry of the PHP programming language. Code as you would in PHP (with some limitations), although they are two very separate languages.

Aspects of PHP that are supported:

  • Variables
  • Arrays
  • IF, ELSEIF and ELSE
  • SWITCH, CASE and DEFAULT
  • FOR loops
  • FOREACH loops
  • WHILE loops
  • DO-WHILE loops
  • String concatenation
  • Most operators:
    • Arithmetic (e.g. +, -, /, *, %)
    • Logic (e.g. &&, ||)
    • Assignment (e.g. =, +=, .=)
  • User-defined functions
  • Comments
  • Some built in PHP functions are supported:
    • count() - count values in an array
    • date() - get a formatted date
    • exit - end script execution
    • is_numeric() - determine whether a variable value is numeric
    • number_format() - format a numeric variable output
    • pow() - raise a number to the power of second argument
    • str_replace() - replace a substring in a string with another substring
    • strlen() - determine the length of a string
    • strpos() - determine the position of a substring within a string
    • substr() - retrun a substring of a string
    • time() - return UNIX timestamp
    • trim() - remove leading and trailing spaces from a string

Computing values for Webform components

Authorised users can add macro code to calculate a component value on the component edit page - a fieldset has been added at the bottom of the component edit form.

Macro code is executed after a Webform has been submitted and validated, therefore components with macro code cannot be made mandatory, nor can they be validated.

Submitted form values are accessible in the $values array. The values can be accessed, or set, via the form key.

// Setting a component value.
$values['fieldset_form_key']['component_form_key'][0] = 'my new value';
if ($values['fieldset_form_key']['component_form_key'][0] == 'my new value') {
$values['fieldset_form_key']['different_component'][0] == 'my new value' . ' has been set');
}

Although you can change any component value in a macro script, only the component containing the macro will have its value updated in the submitted data.

Macros are executed in the order that the components appear on the form. The computed values of earlier components are available in the $values array to scripts executing later.

Please note that all calculation macros defined for a Webform will execute on each step of a multi-page form (each time that Next Page is clicked) when "Automatically save as draft between pages" is enabled. This is currently the only way to have a calculated value be pre-populated on subsequent pages.

Validating submitted data

If the Webform Validation module is installed and active, authorised users can use macro code to validate submitted data.

Validation macros can be added by selecting the Macro validation rule option on the Form validation sub-tab.

Submitted form values for the selected components are accessible in the $values array. The values can be accessed by form key.

/**
* Validating a component value.
*/
if ($values['fieldset_form_key']['component_form_key'][0] >= 255) {
$some_variable = $values['fieldset_form_key']['component_form_key'][0] / 10;
if ($some_variable < 50) {
$values['fieldset_form_key']['component_form_key'][0] = false;
}
}

Trigger the corresponding error message by setting the required component value to FALSE when an error is found. This does not cause the submitted value to change.

Be aware that Webform Validation only makes available values for components on the current page of a multi-step form.

Known problems

  1. You can break your site with faulty macro code. For example, a situation that leads to an infinite loop will cause a White Screen Of Death.
  2. There is no validation of data types being passed to the built in functions, so you may find PHP warnings and notices appearing.
  3. I cannot imagine that I have successfully tested every possible logic path in the course of development, so one may find unexpected errors cropping up.
  4. Test macro code thoroughly on a development environment before applying to a live site.

Project information