View source
<?php
define('WFST_PAD_CHARACTER', chr(31));
function _webform_defaults_structured_text() {
return array(
'name' => '',
'form_key' => NULL,
'mandatory' => 0,
'pid' => 0,
'weight' => 0,
'extra' => array(
'mask' => '',
'auto_skip' => TRUE,
'mask_description' => FALSE,
'mask_regex' => '',
'mask_labels' => '',
'description' => '',
'placeholders' => '',
'centred' => TRUE,
'separate_boxes' => FALSE,
'analysis_display' => FALSE,
'analysis_display_identifying' => '',
'private' => FALSE,
'unique' => FALSE,
),
);
}
function _webform_theme_structured_text() {
return array(
'webform_structured_text' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'structured_text.inc',
),
'webform_structured_text_part' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'structured_text.inc',
),
'webform_display_structured_text' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'structured_text.inc',
),
);
}
function _webform_edit_structured_text($component) {
$form = array();
$form['extra']['mask'] = array(
'#type' => 'textfield',
'#title' => t('Input mask'),
'#default_value' => $component['extra']['mask'],
'#description' => t('Enter an input mask. Use the following special characters to represent
parts of the mask.
<ul>
<li>9 - only a digit can be input</li>
<li>x - any non-blank character can be input</li>
<li>a - only letters can be input (upper or lower case)</li>
<li>r{<em>n</em>{,<em>s</em>}} - any characters with the maximum length
of the field specified by <em>n</em> where <em>n</em> is an integer
greater than 0. If <em>n</em> is omitted, the maximum length
will be 1. Optionally, a display size <em>s</em> for the
field can also be specified by following the maximum length with
a comma and an integer value greater than zero. For example,
"r20,10" creates a field maximum 20 characters long with a display
length of 10 characters. Other than for maximum length, this
mask relies completely on a regex to validate the field\'s input.
Thus, if you don\'t specify a regex expression, any characters
can be entered into the field, and the field can be left blank,
even if the component is marked as required.</li>
<li>^9 - outputs the character "9"</li>
<li>^x - outputs the character "x"</li>
<li>^a - outputs the character "a"</li>
<li>^r - outputs the character "r"</li>
<li>^^ - outputs the character "^"</li>
</ul>
all other characters in the mask will be rendered as mark-up around / between
the textboxes for the portions of the mask that are denoted by the digit nine,
or lower-case characters "x", "a", or "r". If you want a certain combination of
letters and numbers, use "x" or "r" as your mask character, and specify a RegEx
pattern(s) below to check the pattern.'),
'#weight' => -3.9,
'#required' => TRUE,
);
$form['extra']['auto_skip'] = array(
'#type' => 'checkbox',
'#title' => t('Auto-skip to next chunk'),
'#default_value' => $component['extra']['auto_skip'],
'#description' => t('Individual chunks of the field are rendered as text boxes
with markup in between for parts of the mask that are not the digit nine,
or lower-case characters "x" or "a". Check this box to have the cursor
automatically move to the next chunk in the field when the previous one
is filled.'),
'#weight' => -3.8,
);
$form['extra']['mask_description'] = array(
'#type' => 'checkbox',
'#title' => t('Include mask description'),
'#default_value' => $component['extra']['mask_description'],
'#description' => t('Check this box to show a description of the mask in the field\'s
description area. This will appear appended to the description you specify
below (if any). If you don\'t provide a description below and this box
is checked, the mask description will still show.'),
'#weight' => -3.7,
);
$form['extra']['mask_regex'] = array(
'#type' => 'textarea',
'#title' => t('Mask RegEx validation'),
'#default_value' => $component['extra']['mask_regex'],
'#description' => t('If you want to further validate the pattern of a chunk, you
can do that by specifying a RegEx expression here that will be used to
further validate the user\'s input. Each validation should be on a separate
line, in the form<br><br>
<em>chunk-number</em>|<em>error-message</em>|<em>regex-expression</em><br><br>
with each portion separated by a vertical bar / pipe character, where:<br>
- <em>chunk-number</em> is an integer corresponding to the ordinal position
of the chunk,<br>
- <em>error-message</em> is the error message to display if the user input
for that chunk doesn\'t match the RegEx expression, and<br>
- <em>regex-expression</em> is the expression to match against.<br><br>
For example, to validate a Canadian postal code, which has the format
letter-number-letter number-letter-number (eg., M5B 2J7), if you wanted
two chunks, the mask would be "xxx xxx", with validations being<br><br>
1|First part of postal code must be letter-number-letter.|/[A-Z][0-9][A-Z]/<br>
2|Second part of postal code must be number-letter-number.|/[0-9][A-Z][0-9]/<br><br>
As a second example, if you wanted a North American style phone number with optional
extension, the mask would be "(999) 999-9999 E^xt: r10,5" (note the escaped "x"
in "Ext"), with the validation being<br><br>
4|Please specify only digits for the extension.|/^[0-9]*$/<br><br>
You do not have to specify a validation for every chunk. For more on
RegEx expressions and preg_match (which is what is used), see !link.', array(
'!link' => '<a href="http://ca2.php.net/preg_match" target=_blank>http://ca2.php.net/preg_match</a>',
)),
'#weight' => -3.6,
'#element_validate' => array(
'_webform_structured_text_element_validate',
),
'#part_count' => 3,
);
$form['extra']['mask_labels'] = array(
'#type' => 'textarea',
'#title' => t('Mask labels'),
'#default_value' => $component['extra']['mask_labels'],
'#description' => t('You can specify invisible labels for each chunk using a
format similar to the RegEx validation. This can be useful for making
the form accessible using a screen reader. Use the form<br><br>
<em>chunk-number</em>|<em>label-text</em><br><br>For example<br><br>
1|Area code<br>
2|Exchange<br>
3|Number<br><br>
If you don\'t specify mask labels, generic "<em>component_title</em>,
part <em>n</em>" labels will be used, where <em>n</em> is the chunk number.'),
'#weight' => -3.55,
'#element_validate' => array(
'_webform_structured_text_element_validate',
),
'#part_count' => 2,
);
$form['extra']['placeholders'] = array(
'#type' => 'textarea',
'#title' => t('Placeholders'),
'#default_value' => $component['extra']['placeholders'],
'#description' => t('You can specify placeholders for each chunk using a
format similar to the Mask Labels. Use the form<br><br>
<em>chunk-number</em>|<em>placeholder-text</em><br><br>For example<br><br>
1|First Name<br>
2|Last Name'),
'#weight' => -3.53,
'#element_validate' => array(
'_webform_structured_text_element_validate',
),
'#part_count' => 2,
);
$form['extra']['centre'] = array(
'#type' => 'checkbox',
'#title' => t('Centre-align input'),
'#default_value' => isset($component['extra']['centre']) ? $component['extra']['centre'] : TRUE,
'#description' => t('Check to centre-align the text input in the field elements.'),
'#weight' => -3.52,
);
$form['extra']['separate_boxes'] = array(
'#type' => 'checkbox',
'#title' => t('Separate input box borders'),
'#default_value' => isset($component['extra']['separate_boxes']) ? $component['extra']['separate_boxes'] : FALSE,
'#description' => t('Check to show borders around each of the field chunks,
giving them the appearance of individual input boxes. Otherwise, they will
all appear as if in one input box, with a light yellow background
on white while the element has focus.'),
'#weight' => -3.51,
);
$form['extra']['css_classes'] = array(
'#type' => 'textfield',
'#title' => t('CSS Class(es)'),
'#default_value' => isset($component['extra']['css_classes']) ? $component['extra']['css_classes'] : '',
'#description' => t('You can specify CSS class(es) here if you like to help with theming.
Separate each class with a space. Class(es) will be applied to the highest-level
<div> for the component. Each part of the component will have classes
"structured-text" and "part-<em>n</em>" where <em>n</em> is the part of the
mask with <em>n</em> starting at zero. Markup portions of the mask also have
a class "markup".'),
'#weight' => -3.5,
'#required' => FALSE,
);
$form['extra']['analysis_display'] = array(
'#type' => 'checkbox',
'#title' => t('Show responses in analysis'),
'#default_value' => $component['extra']['analysis_display'],
'#description' => t('Show each answer in the analysis results'),
'#weight' => 3,
'#parents' => array(
'extra',
'analysis_display',
),
);
$other_components = array(
'' => t('Submission ID'),
);
$result = db_query('SELECT cid, form_key FROM {webform_component} WHERE nid = %d ORDER BY weight, form_key', $component['nid']);
while ($c = db_fetch_object($result)) {
$other_components[$c->cid] = $c->form_key;
}
$form['extra']['analysis_display_identifying'] = array(
'#type' => 'select',
'#title' => t('Identifying field'),
'#default_value' => $component['extra']['analysis_display_identifying'],
'#description' => t('Which component do you want to use to identify results?'),
'#options' => $other_components,
'#weight' => 4,
'#parents' => array(
'extra',
'analysis_display_identifying',
),
);
$form['value'] = array(
'#type' => 'textarea',
'#title' => t('Default value'),
'#default_value' => $component['value'],
'#description' => t('The default value of the field. You can specify default values for each chunk using a
format similar to the Mask Labels. Use the form<br><br>
<em>chunk-number</em>|<em>default-value</em><br><br>For example<br><br>
1|Jane<br>
2|Doe<br><br>') . theme('webform_token_help'),
'#weight' => 2,
'#element_validate' => array(
'_webform_structured_text_element_validate',
),
'#part_count' => 2,
);
$form['validation']['unique'] = array(
'#type' => 'checkbox',
'#title' => t('Unique'),
'#return_value' => 1,
'#description' => t('Check that all entered values for this field are unique. The same value is not allowed to be used twice.'),
'#weight' => 1,
'#default_value' => $component['extra']['unique'],
'#parents' => array(
'extra',
'unique',
),
);
return $form;
}
function _webform_structured_text_element_validate($element, &$form_state) {
if (!empty($element['#value'])) {
$errors = array();
$lines = array_filter(explode("\n", $element['#value']));
$is_regex = array_pop($element['#array_parents']) == 'mask_regex';
foreach ($lines as $line_number => $line) {
$parts = explode('|', $line, $element['#part_count']);
$empty_part = FALSE;
foreach ($parts as $index => $part) {
$parts[$index] = trim($part);
if (empty($parts[$index])) {
$empty_part = TRUE;
break;
}
}
if (count($parts) != $element['#part_count'] || $empty_part) {
$errors[] = t('Line !line is ill-formed. There must be !parts parts to
each line, separated by vertical bars / pipes. Please
review the instructions for the !name and try again.', array(
'!line' => $line_number + 1,
'!parts' => $element['#part_count'],
));
}
if (!is_numeric($parts[0]) || (int) $parts[0] != $parts[0] || $parts[0] < 1) {
$errors[] = t('Line !line must start with a positive integer signifying
the chunk number of the mask. "@value" is not a valid chunk number.', array(
'!line' => $line_number + 1,
'@value' => $parts[0],
));
}
if ($is_regex && !$empty_part) {
set_error_handler(function ($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
return;
}
throw new ErrorException($message, $severity, $severity, $file, $line);
});
try {
preg_match($parts[2], NULL);
} catch (Exception $ex) {
$errors[] = t('The regular expression on line !line appears to be invalid: @exception', array(
'!line' => $line_number + 1,
'@exception' => substr($ex
->GetMessage(), 14),
));
}
restore_error_handler();
}
}
if (!empty($errors)) {
$message = format_plural(count($errors), 'There is a problem with %name: !error', 'There are @count problems with %name: !errors', array(
'%name' => $element['#title'],
'!error' => $errors[0],
'!errors' => '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>',
));
form_error($element, $message);
}
}
}
function _webform_render_structured_text($component, $value = NULL, $filter = FALSE) {
$description = webform_structured_text_field_description($component);
$node = isset($component['nid']) ? node_load($component['nid']) : NULL;
$form_item = array(
'#type' => 'webform_structured_text',
'#input' => TRUE,
'#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
'#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
'#weight' => $component['weight'],
'#required' => $component['mandatory'],
'#description' => $filter ? _webform_filter_descriptions($description) : $description,
'#process' => array(
'webform_structured_text_expand_field',
),
'#pre_render' => array(
'webform_element_title_display',
),
'#post_render' => array(
'webform_element_wrapper',
),
'#prefix' => '<div class="webform-component-' . $component['type'] . (!empty($component['extra']['css_classes']) ? ' ' . check_plain($component['extra']['css_classes']) : '') . '" id="webform-component-' . $component['form_key'] . '">',
'#suffix' => '</div>',
'#theme' => 'webform_structured_text',
'#theme_wrappers' => array(
'webform_element_wrapper',
),
'#centre' => isset($component['extra']['centre']) ? $component['extra']['centre'] : TRUE,
'#separate_boxes' => isset($component['extra']['separate_boxes']) ? $component['extra']['separate_boxes'] : FALSE,
'#default_value' => $filter ? _webform_filter_values($component['value'], $node, NULL, NULL, FALSE) : $component['value'],
'#element_validate' => array(
'webform_validate_structured_text',
),
'#mask' => webform_structured_text_parse_mask($component['extra']['mask']),
'#mask_regex' => $component['extra']['mask_regex'],
'#mask_labels' => $component['extra']['mask_labels'],
'#placeholders' => $component['extra']['placeholders'],
'#auto_skip' => $component['extra']['auto_skip'],
'#translatable' => array(
'title',
'description',
'mask_labels',
'placeholders',
),
'#unique' => isset($component['extra']['unique']) ? $component['extra']['unique'] : FALSE,
);
if (isset($value)) {
$form_item['#default_value'] = webform_structured_text_parse_value($form_item['#mask'], $value[0]);
}
return $form_item;
}
function _webform_structured_text_setting_to_array($setting) {
$array = array();
if (!empty($setting)) {
$lines = array_filter(explode("\n", $setting));
foreach ($lines as $line) {
list($chunk, $value) = explode('|', $line, 2);
$array[$chunk] = $value;
}
}
return $array;
}
function webform_structured_text_expand_field($element) {
static $js_added = FALSE;
$js_ids = array();
$mask_labels = _webform_structured_text_setting_to_array($element['#mask_labels']);
$placeholders = _webform_structured_text_setting_to_array($element['#placeholders']);
$defaults = array();
if (!empty($element['#default_value']) && is_string($element['#default_value'])) {
$defaults = _webform_structured_text_setting_to_array($element['#default_value']);
$element['#default_value'] = array();
}
$chunk = 0;
foreach ($element['#mask'] as $part => $details) {
if ($details['type'] != 'markup') {
$chunk++;
$size = isset($details['size']) && $details['size'] > 0 ? $details['size'] : $details['length'];
$default_value = isset($element['#default_value'][$part]) ? $element['#default_value'][$part] : (isset($defaults[$chunk]) ? $defaults[$chunk] : '');
$element["part-{$part}"] = array(
'#title' => empty($mask_labels[$chunk]) ? t('!eltitle, part !chunk', array(
'!eltitle' => $element['#title'],
'!chunk' => $chunk,
)) : $mask_labels[$chunk],
'#title_display' => 'invisible',
'#type' => 'textfield',
'#theme' => 'webform_structured_text_part',
'#size' => $size,
'#maxlength' => $details['length'],
'#default_value' => $default_value,
'#attributes' => array(
'class' => 'structured-text part-' . $part,
),
);
if ($element['#centre']) {
$element["part-{$part}"]['#attributes']['style'] = 'text-align:center;';
}
if (!empty($placeholders[$chunk])) {
$element['part-' . $part]['#attributes']['placeholder'] = $placeholders[$chunk];
}
$js_ids[] = $part;
}
else {
$element["part-{$part}"] = array(
'#type' => 'markup',
'#value' => strip_tags(_webform_structured_text_t($element['#webform_component']['nid'] . ':' . $element['#webform_component']['cid'] . ":mask:{$part}", $details['value'])),
'#prefix' => '<div class="structured-text markup part-' . $part . '">',
'#suffix' => '</div>',
);
}
}
if (count($js_ids) > 1 && $element['#auto_skip']) {
foreach ($js_ids as $index => $id) {
if (isset($js_ids[$index + 1])) {
$element["part-{$id}"]['#attributes']['onkeyup'] = "webform_structured_text_jump(event, '{$element['#id']}-part-{$id}', '{$element['#id']}-part-{$js_ids[$index + 1]}');";
}
}
if (!$js_added) {
$script = "function webform_structured_text_jump(event, from_id, to_id) {\n if ( event.keyCode != 9 && event.keyCode != 16 ) {\n fromfield = \$('#' + from_id);\n if ( fromfield.val().length >= fromfield.attr('maxlength') ) {\n \$('#' + to_id).focus().select();\n }\n }\n }";
drupal_add_js($script, 'inline');
$js_added = TRUE;
}
}
return $element;
}
function webform_validate_structured_text($element, $form_state) {
$chunks = array();
$had_pattern_errors = FALSE;
$unique_test_array = array();
foreach ($element['#mask'] as $part => $details) {
if ($details['type'] != 'markup') {
$chunks[$part] = $unique_test_array["part-{$part}"] = $element["part-{$part}"]['#value'];
}
}
$numb_chunks = count($chunks);
$numb_not_empty = count(array_filter($chunks, 'trim'));
$numb_empty = $numb_chunks - $numb_not_empty;
$missing_chunks = $numb_chunks != $numb_not_empty && $numb_chunks != $numb_empty;
$mask_regex = array();
if (!empty($element['#mask_regex'])) {
$mask_regex_lines = array_filter(explode("\n", $element['#mask_regex']));
foreach ($mask_regex_lines as $line) {
list($chunk, $message, $regex) = explode('|', $line, 3);
$mask_regex[$chunk] = array(
'message' => $message,
'regex' => $regex,
);
}
}
$component = 0;
foreach ($chunks as $part => $value) {
$component++;
$error_1 = $error_n = '';
switch ($element['#mask'][$part]['type']) {
case '9':
if (($element['#required'] || $missing_chunks) && $value == '' || $value != '' && (preg_match('/[^0-9]/', $value) || drupal_strlen($value) < $element['#mask'][$part]['length'])) {
$error_1 = t('digit');
$error_n = t('digits');
}
break;
case 'a':
if (($element['#required'] || $missing_chunks) && $value == '' || $value != '' && (preg_match('/[^a-z]/i', $value) || drupal_strlen($value) < $element['#mask'][$part]['length'])) {
$error_1 = t('alpha character (a-z)');
$error_n = t('alpha characters (a-z)');
}
break;
case 'x':
if (($element['#required'] || $missing_chunks) && $value == '' || $value != '' && drupal_strlen($value) < $element['#mask'][$part]['length']) {
$error_1 = t('character');
$error_n = t('characters');
}
break;
case 'r':
break;
}
if ($error_1) {
$had_pattern_errors = TRUE;
$component_field = implode('][', array_merge($element['#parents'], array(
'part-' . $part,
)));
form_set_error($component_field, format_plural($element['#mask'][$part]['length'], '%element field !part part must be 1 !singular.', '%element field !part part must be @count !plural.', array(
'%element' => $element['#title'],
'!part' => t($component . _webform_structured_text_ordinal_suffix($component)),
'!singular' => $error_1,
'!plural' => $error_n,
)));
}
elseif (($element['#required'] || !$missing_chunks && $numb_not_empty != 0 || $element['#mask'][$part]['type'] == 'r') && !empty($mask_regex[$component]['regex'])) {
if (!preg_match(trim($mask_regex[$component]['regex']), $value)) {
$had_pattern_errors = TRUE;
$component_field = implode('][', array_merge($element['#parents'], array(
'part-' . $part,
)));
form_set_error($component_field, strip_tags(_webform_structured_text_t($element['#webform_component']['nid'] . ':' . $element['#webform_component']['cid'] . ":regex:{$component}:message", $mask_regex[$component]['message'])));
}
}
}
if (!$had_pattern_errors && $element['#unique']) {
$element['#value'] = _webform_structured_text_create_store_value($element['#mask'], $unique_test_array);
if ($element['#value'] !== '') {
$nid = $form_state['values']['details']['nid'];
$sid = $form_state['values']['details']['sid'];
$sql = "SELECT COUNT(sid)\n FROM {webform_submitted_data}\n WHERE\n nid = %d\n AND cid = %d\n AND data = '%s'";
if ($sid) {
$sql .= ' AND sid <> %d';
}
$count = db_result(db_query($sql, $nid, $element['#webform_component']['cid'], $element['#value'], $sid));
if ($count) {
form_error($element, t('The value %value has already been submitted once for the %title field.
You may have already submitted this form, or you need to use a different value.', array(
'%value' => webform_structured_text_format_value($element['#mask'], $element['#value'], $element['#webform_component']),
'%title' => $element['#title'],
)));
}
}
}
}
function theme_webform_structured_text($element) {
drupal_add_css(drupal_get_path('module', 'webform_structured_text') . '/webform_structured_text.css');
$has_error = form_get_error($element);
$output = '';
foreach (element_children($element) as $key) {
$output .= drupal_render($element[$key]);
}
if (!$element['#separate_boxes']) {
$output = '<div class="structured-text-one-field' . ($has_error ? ' has-error' : '') . '">' . $output . '</div>';
}
$output = '<div class="webform-container-inline">' . $output . '</div>';
return theme('form_element', $element, $output);
}
function theme_webform_structured_text_part($element) {
$size = empty($element['#size']) ? '' : ' size="' . $element['#size'] . '"';
$maxlength = empty($element['#maxlength']) ? '' : ' maxlength="' . $element['#maxlength'] . '"';
$class = array(
'form-text',
);
$extra = '';
$output = '';
if ($element['#autocomplete_path'] && menu_valid_path(array(
'link_path' => $element['#autocomplete_path'],
))) {
drupal_add_js('misc/autocomplete.js');
$class[] = 'form-autocomplete';
$extra = '<input class="autocomplete" type="hidden" id="' . $element['#id'] . '-autocomplete" value="' . check_url(url($element['#autocomplete_path'], array(
'absolute' => TRUE,
))) . '" disabled="disabled" />';
}
_form_set_class($element, $class);
if (isset($element['#field_prefix'])) {
$output .= '<span class="field-prefix">' . $element['#field_prefix'] . '</span> ';
}
$output .= '<label for="' . $element['#id'] . '" style="display:none;">' . filter_xss_admin($element['#title']) . '</label>';
unset($element['#title']);
$output .= '<input type="text"' . $maxlength . ' name="' . $element['#name'] . '" id="' . $element['#id'] . '"' . $size . ' value="' . check_plain($element['#value']) . '"' . drupal_attributes($element['#attributes']) . ' />';
if (isset($element['#field_suffix'])) {
$output .= ' <span class="field-suffix">' . $element['#field_suffix'] . '</span>';
}
return theme('form_element', $element, $output) . $extra;
}
function _webform_display_structured_text($component, $value, $format = 'html') {
return array(
'#title' => $component['name'],
'#weight' => $component['weight'],
'#theme' => 'webform_display_structured_text',
'#theme_wrappers' => $format == 'html' ? array(
'webform_element',
) : array(
'webform_element_text',
),
'#post_render' => array(
'webform_element_wrapper',
),
'#field_prefix' => isset($component['extra']['field_prefix']) ? $component['extra']['field_prefix'] : '',
'#field_suffix' => isset($component['extra']['field_suffix']) ? $component['extra']['field_suffix'] : '',
'#component' => $component,
'#format' => $format,
'#value' => $value[0] != '' ? webform_structured_text_format_value($component['extra']['mask'], $value[0], $component, $format) : '',
'#translatable' => array(
'title',
),
);
}
function _webform_submit_structured_text($component, $value) {
$mask = webform_structured_text_parse_mask($component['extra']['mask']);
return _webform_structured_text_create_store_value($mask, $value);
}
function _webform_structured_text_create_store_value($mask, $value) {
$combined_value = '';
if (is_array($value) && ($empty_test = implode('', $value)) && !empty($empty_test)) {
foreach ($value as $chunk => $input) {
$chunk = substr($chunk, 5);
if ($mask[$chunk]['type'] == 'r') {
$input = str_pad($input, $mask[$chunk]['length'], WFST_PAD_CHARACTER);
}
$combined_value .= $input;
}
}
return $combined_value;
}
function _webform_help_structured_text($section) {
switch ($section) {
case 'admin/settings/webform#structured_text':
return t('Allows creation of stuctured / input-masked text.');
}
}
function theme_webform_display_structured_text($element) {
$prefix = $element['#format'] == 'html' ? '' : $element['#field_prefix'];
$suffix = $element['#format'] == 'html' ? '' : $element['#field_suffix'];
$value = $element['#format'] == 'html' ? str_replace('&nbsp;', ' ', check_plain($element['#value'])) : $element['#value'];
return $value !== '' ? $prefix . $value . $suffix : ' ';
}
function _webform_analysis_structured_text($component, $sids = array(), $single = FALSE) {
$placeholders = count($sids) ? array_fill(0, count($sids), "'%s'") : array();
$sidfilter = count($sids) ? ' AND sid in (' . implode(',', $placeholders) . ')' : '';
$query = 'SELECT sid, data FROM {webform_submitted_data} WHERE nid = %d AND cid = %d ' . $sidfilter;
$nonblanks = 0;
$submissions = 0;
$responses = array();
$result = db_query($query, array_merge(array(
$component['nid'],
$component['cid'],
), $sids));
while ($data = db_fetch_array($result)) {
if (drupal_strlen(trim($data['data'])) > 0) {
$nonblanks++;
if ($component['extra']['analysis_display']) {
if ($component['extra']['analysis_display_identifying'] == '') {
$identifier = $data['sid'];
}
else {
$identifier = db_result(db_query("SELECT data FROM {webform_submitted_data} WHERE nid = %d AND cid = %d AND sid = %d LIMIT 1", $component['nid'], $component['extra']['analysis_display_identifying'], $data['sid']));
}
$responses[] = array(
'<div class="webform-response">' . l($identifier, "node/{$component['nid']}/submission/{$data['sid']}") . ': ' . webform_structured_text_format_value($component['extra']['mask'], $data['data'], $component) . '</div>',
'',
);
}
}
$submissions++;
}
$rows[0] = array(
t('Left Blank'),
$submissions - $nonblanks,
);
$rows[1] = array(
t('User entered value'),
$nonblanks,
);
if ($component['extra']['analysis_display']) {
$rows = array_merge($rows, $responses);
}
return $rows;
}
function _webform_table_structured_text($component, $value) {
return empty($value[0]) ? '' : webform_structured_text_format_value($component['extra']['mask'], $value[0], $component);
}
function _webform_csv_headers_structured_text($component, $export_options) {
return array(
'',
'',
$component['name'],
);
}
function _webform_csv_data_structured_text($component, $export_options, $value) {
return empty($value[0]) ? '' : webform_structured_text_format_value($component['extra']['mask'], $value[0], $component, 'text');
}
function webform_structured_text_parse_mask($mask) {
$mask_array = array();
$mask = (string) $mask;
$mask_length = drupal_strlen($mask);
$where = '';
$part = -1;
for ($i = 0; $i < $mask_length; $i++) {
$type = in_array($mask[$i], array(
'9',
'a',
'x',
'r',
)) ? $mask[$i] : 'markup';
if ($where != $type) {
$where = $type;
$mask_array[++$part] = array(
'type' => $type,
'length' => 0,
'value' => '',
);
}
if ($type == 'r') {
if (preg_match('/[1-9]/', $mask[$i + 1])) {
$i++;
while ($i < $mask_length && preg_match('/[0-9]/', $mask[$i])) {
$mask_array[$part]['length'] .= $mask[$i++];
}
$mask_array[$part]['length'] = (int) $mask_array[$part]['length'];
if ($i < $mask_length && $mask[$i] == ',' && $i + 1 < $mask_length && preg_match('/[1-9]/', $mask[$i + 1])) {
$i++;
$mask_array[$part]['size'] = '';
while ($i < $mask_length && preg_match('/[0-9]/', $mask[$i])) {
$mask_array[$part]['size'] .= $mask[$i++];
}
$mask_array[$part]['size'] = (int) $mask_array[$part]['size'];
}
$i--;
}
else {
$mask_array[$part]['length'] = 1;
}
}
else {
$mask_array[$part]['length']++;
}
if ($type == 'markup') {
if ($mask[$i] == '^') {
if ($i + 1 < $mask_length && in_array($mask[$i + 1], array(
'9',
'a',
'x',
'r',
'^',
))) {
$mask_array[$part]['value'] .= $mask[++$i];
}
}
else {
if ($mask[$i] == ' ') {
if ($i == 0 || $mask[$i - 1] != ' ') {
$space = ' ';
}
$space = $space == ' ' ? ' ' : ' ';
$mask_array[$part]['value'] .= $space;
}
else {
$mask_array[$part]['value'] .= $mask[$i];
}
}
}
}
return $mask_array;
}
function webform_structured_text_parse_value($mask, $value) {
$mask_array = is_array($mask) ? $mask : webform_structured_text_parse_mask($mask);
$value_array = array();
$start = 0;
foreach ($mask_array as $part => $details) {
if ($details['type'] != 'markup') {
$value_array[$part] = str_replace(WFST_PAD_CHARACTER, '', drupal_substr($value, $start, $details['length']));
$start += $details['length'];
}
}
return $value_array;
}
function webform_structured_text_format_value($mask, $value, $component, $format = 'html') {
$mask_array = is_array($mask) ? $mask : webform_structured_text_parse_mask($mask);
$value = webform_structured_text_parse_value($mask_array, $value);
if (($empty_test = implode('', $value)) && empty($empty_test)) {
return '';
}
$output = '';
foreach ($mask_array as $part => $details) {
if ($details['type'] != 'markup') {
$output .= $value[$part];
}
else {
$output .= _webform_structured_text_t("{$component['nid']}:{$component['cid']}:mask:{$part}", $details['value']);
}
}
return $format == 'html' ? str_replace('&nbsp;', ' ', check_plain($output)) : $output;
}
function webform_structured_text_field_description($component) {
$description = $component['extra']['description'];
if ($component['extra']['mask_description']) {
$mask_array = webform_structured_text_parse_mask($component['extra']['mask']);
$output = array();
foreach ($mask_array as $details) {
switch ($details['type']) {
case '9':
$output[] = format_plural($details['length'], '1 digit', '@count digits');
break;
case 'a':
$output[] = format_plural($details['length'], '1 alpha (a-z) character', '@count alpha (a-z) characters');
break;
case 'x':
case 'r':
$output[] = format_plural($details['length'], '1 character', '@count characters');
break;
default:
break;
}
}
if (!empty($output)) {
$last = array_pop($output);
$output = !empty($output) ? implode(', ', $output) . ', ' . t('and') . ' ' . $last : $last;
$description .= ' <strong>' . t('Input format:') . '</strong> ' . $output . '.';
}
}
return $description;
}
function _webform_structured_text_ordinal_suffix($num) {
if ($num < 4 || $num > 20) {
switch ($num % 10) {
case 1:
return 'st';
case 2:
return 'nd';
case 3:
return 'rd';
}
}
return 'th';
}
function _webform_structured_text_translate_dummy() {
t('1st');
t('2nd');
t('3rd');
t('4th');
t('5th');
t('6th');
t('7th');
t('8th');
t('9th');
t('10th');
t('11th');
t('12th');
t('13th');
t('14th');
t('15th');
t('16th');
t('17th');
t('18th');
t('19th');
t('20th');
}
function webform_structured_text_webform_component_insert($component) {
webform_structured_text_i18n_update_strings($component);
}
function webform_structured_text_webform_component_update($component) {
webform_structured_text_i18n_update_strings($component);
}
function webform_structured_text_webform_component_delete($component) {
webform_structured_text_i18n_update_strings($component, 'remove');
}