You are here

grid.inc in Webform 6.2

Webform module grid component.

File

components/grid.inc
View source
<?php

/**
 * @file
 *   Webform module grid component.
 */

/**
 * Create a default grid component.
 */
function _webform_defaults_grid() {
  return array(
    'name' => '',
    'form_key' => NULL,
    'email' => 1,
    'mandatory' => 0,
    'pid' => 0,
    'weight' => 0,
    'extra' => array(
      'options' => '',
      'questions' => '',
      'optrand' => 0,
      'qrand' => 0,
      'description' => '',
    ),
  );
}

/**
 * Create a set of form items to be displayed on the form for editing this component.
 * Use care naming the form items, as this correlates directly to the database schema.
 * The component "Name" and "Description" fields are added to every component type and
 * are not necessary to specify here (although they may be overridden if desired).
 * @return
 *   An array of form items to be displayed on the edit component page
 */
function _webform_edit_grid($currfield) {
  $edit_fields = array();
  $edit_fields['extra']['options'] = array(
    '#type' => 'textarea',
    '#title' => t('Options'),
    '#default_value' => $currfield['extra']['options'],
    '#description' => t('Options to select across the top. One option per line. Key-value pairs may be entered seperated by pipes. i.e. safe_key|Some readable option') . theme('webform_token_help'),
    '#cols' => 60,
    '#rows' => 5,
    '#weight' => -3,
    '#required' => TRUE,
  );
  $edit_fields['extra']['questions'] = array(
    '#type' => 'textarea',
    '#title' => t('Questions'),
    '#default_value' => $currfield['extra']['questions'],
    '#description' => t('Questions list down the left side. One question per line.') . theme('webform_token_help'),
    '#cols' => 60,
    '#rows' => 5,
    '#weight' => -2,
    '#required' => TRUE,
  );
  $edit_fields['extra']['optrand'] = array(
    '#type' => 'checkbox',
    '#title' => t('Randomize Options'),
    '#default_value' => $currfield['extra']['optrand'],
    '#description' => t('Randomizes the order of options on the top when they are displayed in the form.'),
  );
  $edit_fields['extra']['qrand'] = array(
    '#type' => 'checkbox',
    '#title' => t('Randomize Questions'),
    '#default_value' => $currfield['extra']['qrand'],
    '#description' => t('Randomize the order of the questions on the side when they are displayed in the form.'),
  );
  return $edit_fields;
}
function _webform_edit_validate_grid($form_values) {

  // Currently no validation for selects.
  return TRUE;
}
function _webform_render_grid($component, $random = TRUE) {
  $form_item = array(
    '#title' => $component['name'],
    '#required' => $component['mandatory'],
    '#weight' => $component['weight'],
    '#theme' => 'webform_grid',
    '#description' => _webform_filter_descriptions($component['extra']['description']),
  );
  $questions = _webform_grid_options($component['extra']['questions']);
  $options = _webform_grid_options($component['extra']['options']);
  if ($component['extra']['optrand'] && $random) {

    // This maneuver shuffles the array keys, then uses them as
    // the basis for ordering the options.
    $aux = array();
    $keys = array_keys($options);
    shuffle($keys);
    foreach ($keys as $key) {
      $aux[$key] = $options[$key];
      unset($options[$key]);
    }
    $options = $aux;
  }
  if ($component['extra']['qrand'] && $random) {
    $aux = array();
    $keys = array_keys($questions);
    shuffle($keys);
    foreach ($keys as $key) {
      $aux[$key] = $questions[$key];
      unset($questions[$key]);
    }
    $questions = $aux;
  }
  foreach ($questions as $question) {
    if ($question != '') {

      // Remove quotes from keys to prevent HTML breakage.
      $form_item[str_replace(array(
        '"',
        "'",
      ), '', $question)] = array(
        '#title' => $question,
        '#required' => $component['mandatory'],
        '#prefix' => '<div class="webform-component-' . $component['type'] . '" id="webform-component-' . $component['form_key'] . '">',
        '#suffix' => '</div>',
        '#options' => $options,
        '#type' => 'radios',
      );
    }
  }
  return $form_item;
}

/**
 * Display the result of a grid submission. The output of this function will be
 * displayed under the "results" tab then "submissions"
 * @param $data
 *   An array of information containing the submission result, directly
 *   correlating to the webform_submitted_data database schema
 * @param $component
 *   An array of information describing the component, directly correlating to
 *   the webform_component database schema
 * @param $enabled
 *   If enabled, the value may be changed. Otherwise it will set to readonly.
 * @return
 *   Textual output formatted for human reading.
 */
function _webform_submission_display_grid($data, $component, $enabled = FALSE) {
  $form_item = _webform_render_grid($component, FALSE);
  $cid = 0;
  foreach (element_children($form_item) as $key) {
    $form_item[$key]['#default_value'] = $data['value'][$cid++];
    $form_item[$key]['#disabled'] = !$enabled;
  }
  return $form_item;
}

/**
 * Translates the submitted 'safe' form values back into their un-edited
 * original form.
 *
 * @param $data
 *   The POST data associated with the component
 * @param $component
 *   An array of information describing the component, directly correlating to
 *   the webform_component database schema
 * @return
 *   Nothing
 */
function _webform_submit_grid(&$data, $component) {
  $options = drupal_map_assoc(array_flip(_webform_grid_options($component['extra']['options'])));

  // Questions are a bit more tricky, since quotes were removed from them in
  // _webform_render_grid(). Build a list of no_quotes => with_qoutes questions.
  $questions = array();
  foreach (_webform_grid_options($component['extra']['questions']) as $key => $question) {
    $safe_question = str_replace(array(
      '"',
      "'",
    ), '', $question);
    $questions[$safe_question] = $question;
  }
  if (is_array($data)) {
    foreach ($data as $key => $value) {
      if ($value !== '') {
        $data[$key] = $options[$value];
      }
    }
  }
  elseif ($data !== '') {
    $data = $options[$data];
  }

  // Put the form in the original option order before saving.
  // Return the final data with the quotes back in place.
  $ordered_data = array();
  foreach ($questions as $safe_question => $question) {
    if (isset($data[$safe_question])) {
      $ordered_data[$question] = $data[$safe_question];
    }
  }
  $data = $ordered_data;
}

/**
 * Format the output of emailed data for this component.
 *
 * @param $data
 *   A string or array of the submitted data.
 * @param $component
 *   An array of information describing the component, directly correlating to
 *   the webform_component database schema.
 * @return
 *   Textual output to be included in the email.
 */
function theme_webform_mail_grid($data, $component) {
  $questions = _webform_grid_options($component['extra']['questions']);
  $output = $component['name'] . ":\n";
  foreach ($questions as $key => $question) {
    $output .= '  - ' . $question . ':' . ($data[$question] == '' ? '' : ' ' . $data[$question]) . "\n";
  }
  return $output;
}

/**
 * function _webform_help_select
 * Module specific instance of hook_help().
 */
function _webform_help_grid($section) {
  switch ($section) {
    case 'admin/settings/webform#grid_description':
      return t('Allows creation of grid questions, denoted by radio buttons.');
  }
}

/**
 * Module specific instance of hook_theme().
 */
function _webform_theme_grid() {
  return array(
    'webform_grid' => array(
      'arguments' => array(
        'grid_element' => NULL,
      ),
    ),
    'webform_mail_grid' => array(
      'arguments' => array(
        'data' => NULL,
        'component' => NULL,
      ),
    ),
  );
}

/**
 * Calculate and returns statistics about results for this component from all
 * submission to this webform. The output of this function will be displayed
 * under the "results" tab then "analysis".
 *
 * @param $component
 *   An array of information describing the component, directly correlating to
 *   the webform_component database schema.
 * @param $sids
 *   An optional array of submission IDs (sid). If supplied, the analysis will be limited
 *   to these sids.
 * @return
 *   An array of data rows, each containing a statistic for this component's
 *   submissions.
 */
function _webform_analysis_rows_grid($component, $sids = array()) {

  // Generate the list of options and questions.
  $options = _webform_grid_options($component['extra']['options']);
  $questions = array_values(_webform_grid_options($component['extra']['questions']));

  // Generate a lookup table of results.
  $placeholders = count($sids) ? array_fill(0, count($sids), "'%s'") : array();
  $sidfilter = count($sids) ? " AND sid in (" . implode(",", $placeholders) . ")" : "";
  $query = 'SELECT no, data, count(data) as datacount ' . ' FROM {webform_submitted_data} ' . ' WHERE nid = %d ' . ' AND cid = %d ' . " AND data != '' " . $sidfilter . ' GROUP BY no, data';
  $result = db_query($query, array_merge(array(
    $component['nid'],
    $component['cid'],
  ), $sids));
  $counts = array();
  while ($data = db_fetch_object($result)) {
    $counts[$data->no][$data->data] = $data->datacount;
  }

  // Create an entire table to be put into the returned row.
  $rows = array();
  $header = array(
    '',
  );

  // Add options as a header row.
  foreach ($options as $option) {
    $header[] = $option;
  }

  // Add questions as each row.
  foreach ($questions as $qkey => $question) {
    $row = array(
      $question,
    );
    foreach ($options as $okey => $option) {
      $row[] = !empty($counts[$qkey][$okey]) ? $counts[$qkey][$okey] : 0;
    }
    $rows[] = $row;
  }
  $output = theme('table', $header, $rows, array(
    'class' => 'webform-grid',
  ));
  return array(
    array(
      array(
        'data' => $output,
        'colspan' => 2,
      ),
    ),
  );
}

/**
 * function _webform_table_data_select
 * Return the result of this component's submission for display in a table. The output of this function will be displayed under the "results" tab then "table"
 * @param $data An array of information containing the submission result, directly correlating to the webform_submitted_data database schema
 * @returns Textual output formatted for human reading.
 */
function _webform_table_data_grid($data, $component) {
  $questions = array_values(_webform_grid_options($component['extra']['questions']));
  $output = '';

  // Set the value as a single string.
  if (is_array($data['value'])) {
    foreach ($data['value'] as $item => $value) {
      if ($value !== '') {
        $output .= $questions[$item] . ': ' . check_plain($value) . '<br />';
      }
    }
  }
  else {
    $output = check_plain(!isset($data['value']['0']) ? '' : $data['value']['0']);
  }
  return $output;
}

/**
 * Return the header information for this component to be displayed in a comma
 * seperated value file. The output of this function will be displayed under
 * the "results" tab then "download".
 *
 * @param $component
 *   An array of information describing the component, directly correlating to
 *   the webform_component database schema.
 * @return
 *   An array of data to be displayed in the first three rows of a CSV file, not
 *   including either prefixed or trailing commas.
 */
function _webform_csv_headers_grid($component) {
  $header = array();
  $header[0] = array(
    '',
  );
  $header[1] = array(
    $component['name'],
  );
  $items = _webform_grid_options($component['extra']['questions']);
  $count = 0;
  foreach ($items as $key => $item) {

    // Empty column per sub-field in main header.
    if ($count != 0) {
      $header[0][] = '';
      $header[1][] = '';
    }

    // The value for this option.
    $header[2][] = $item;
    $count++;
  }
  return $header;
}

/**
 * Return the result of a textfield submission. The output of this function will
 * be displayed under the "results" tab then "submissions".
 *
 * @param $data
 *   An array of information containing the submission result, directly
 *   correlating to the webform_submitted_data database schema.
 * @return
 *   Textual output formatted for CSV, not including either prefixed or trailing
 *   commas.
 */
function _webform_csv_data_grid($data, $component) {
  $questions = array_keys(_webform_grid_options($component['extra']['questions']));
  $return = array();
  foreach ($questions as $key => $question) {
    $return[] = isset($data['value'][$key]) ? $data['value'][$key] : '';
  }
  return $return;
}
function theme_webform_grid($grid_element) {
  $rows = array();
  $header = array(
    '',
  );
  $first = TRUE;
  foreach (element_children($grid_element) as $key) {
    $question_element = $grid_element[$key];

    // Set the header for the table.
    if ($first) {
      foreach ($question_element['#options'] as $option) {
        $header[] = $option;
      }
      $first = FALSE;
    }

    // Create a row with the question title.
    $row = array(
      check_plain($question_element['#title']),
    );

    // Render each radio button in the row.
    $radios = expand_radios($question_element);
    foreach (element_children($radios) as $key) {
      unset($radios[$key]['#title']);
      $row[] = drupal_render($radios[$key]);
    }
    $rows[] = $row;
  }
  return theme('form_element', $grid_element, theme('table', $header, $rows, array(
    'class' => 'webform-grid',
  )));
}

/**
 * Utility function to split user-entered values from new-line separated
 * text into an array of options.
 */
function _webform_grid_options($text) {
  $options = array();
  $rows = array_filter(explode("\n", _webform_filter_values(trim($text))));
  foreach ($rows as $option) {
    $option = trim($option);
    if (preg_match('/^([^|]+)\\|(.*)$/', $option, $matches)) {
      $options[$matches[1]] = $matches[2];
    }
    else {
      $options[$option] = $option;
    }
  }
  return $options;
}

Functions

Namesort descending Description
theme_webform_grid
theme_webform_mail_grid Format the output of emailed data for this component.
_webform_analysis_rows_grid Calculate and returns statistics about results for this component from all submission to this webform. The output of this function will be displayed under the "results" tab then "analysis".
_webform_csv_data_grid Return the result of a textfield submission. The output of this function will be displayed under the "results" tab then "submissions".
_webform_csv_headers_grid Return the header information for this component to be displayed in a comma seperated value file. The output of this function will be displayed under the "results" tab then "download".
_webform_defaults_grid Create a default grid component.
_webform_edit_grid Create a set of form items to be displayed on the form for editing this component. Use care naming the form items, as this correlates directly to the database schema. The component "Name" and "Description" fields are added to every…
_webform_edit_validate_grid
_webform_grid_options Utility function to split user-entered values from new-line separated text into an array of options.
_webform_help_grid function _webform_help_select Module specific instance of hook_help().
_webform_render_grid
_webform_submission_display_grid Display the result of a grid submission. The output of this function will be displayed under the "results" tab then "submissions"
_webform_submit_grid Translates the submitted 'safe' form values back into their un-edited original form.
_webform_table_data_grid function _webform_table_data_select Return the result of this component's submission for display in a table. The output of this function will be displayed under the "results" tab then "table"
_webform_theme_grid Module specific instance of hook_theme().