[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/webform/includes/ -> webform.report.inc (source)

   1  <?php
   2  
   3  /**
   4   * @file
   5   * This file includes helper functions for creating reports for webform.module
   6   *
   7   * @author Nathan Haug <nate@lullabot.com>
   8   */
   9  
  10  // All functions within this file need the webform.submissions.inc.
  11  module_load_include('inc', 'webform', 'includes/webform.submissions');
  12  
  13  /**
  14   * Retrieve lists of submissions for a given webform.
  15   */
  16  function webform_results_submissions($node, $user_filter, $pager_count) {
  17    global $user;
  18  
  19    if (isset($_GET['results']) && is_numeric($_GET['results'])) {
  20      $pager_count = $_GET['results'];
  21    }
  22  
  23    $header = theme('webform_results_submissions_header', $node);
  24    if ($user_filter) {
  25      if ($user->uid) {
  26        drupal_set_title(t('Submissions for %user', array('%user' => $user->name)));
  27      }
  28      else {
  29        drupal_set_title(t('Your submissions'));
  30        webform_disable_page_cache();
  31      }
  32      webform_set_breadcrumb($node);
  33      $submissions = webform_get_submissions(array('nid' => $node->nid, 'uid' => $user->uid), $header, $pager_count);
  34      $count = webform_get_submission_count($node->nid, $user->uid);
  35    }
  36    else {
  37      $submissions = webform_get_submissions($node->nid, $header, $pager_count);
  38      $count = webform_get_submission_count($node->nid);
  39    }
  40  
  41    $operation_column = end($header);
  42    $operation_total = $operation_column['colspan'];
  43  
  44    $rows = array();
  45    foreach ($submissions as $sid => $submission) {
  46      $row = array(
  47        $submission->is_draft ? t('@sid (draft)', array('@sid' => $sid)) : $sid,
  48        format_date($submission->submitted, 'small'),
  49      );
  50      if (webform_results_access($node, $user)) {
  51        $row[] = theme('username', $submission);
  52        $row[] = $submission->remote_addr;
  53      }
  54      $row[] = l(t('View'), "node/$node->nid/submission/$sid");
  55      $operation_count = 1;
  56      // No need to call this multiple times, just reference this in a variable.
  57      $destination = drupal_get_destination();
  58      if (webform_submission_access($node, $submission, 'edit', $user)) {
  59        $row[] = l(t('Edit'), "node/$node->nid/submission/$sid/edit", array('query' => $destination));
  60        $operation_count++;
  61      }
  62      if (webform_submission_access($node, $submission, 'delete', $user)) {
  63        $row[] = l(t('Delete'), "node/$node->nid/submission/$sid/delete", array('query' => $destination));
  64        $operation_count++;
  65      }
  66      if ($operation_count < $operation_total) {
  67        $row[count($row) - 1] = array('data' => $row[count($row) - 1], 'colspan' => $operation_total - $operation_count + 1);
  68      }
  69      $rows[] = $row;
  70    }
  71  
  72    $element['#theme'] = 'webform_results_submissions';
  73    $element['#node'] = $node;
  74    $element['#submissions'] = $submissions;
  75    $element['#total_count'] = $count;
  76    $element['#pager_count'] = $pager_count;
  77  
  78    $element['table']['#theme'] = 'table';
  79    $element['table']['#header'] = $header;
  80    $element['table']['#rows'] = $rows;
  81    $element['table']['#operation_total'] = $operation_total;
  82  
  83    return drupal_render($element);
  84  }
  85  
  86  /**
  87   * Theme the list of links for selecting the number of results per page.
  88   *
  89   * @param $total_count
  90   *   The total number of results available.
  91   * @param $pager_count
  92   *   The current number of results displayed per page.
  93   */
  94  function theme_webform_results_per_page($total_count, $pager_count) {
  95    $output = '';
  96  
  97    // Create a list of results-per-page options.
  98    $counts = array(
  99      '20' => '20',
 100      '50' => '50',
 101      '100' => '100',
 102      '200' => '200',
 103      '500' => '500',
 104      '1000' => '1000',
 105      '0' => t('All'),
 106    );
 107  
 108    $count_links = array();
 109  
 110    foreach ($counts as $number => $text) {
 111      if ($number < $total_count) {
 112        $count_links[] = l($text, $_GET['q'], array('query' => 'results=' . $number, 'attributes' => array('class' => $pager_count == $number ? 'selected' : '')));
 113      }
 114    }
 115  
 116    $output .= '<div class="webform-results-per-page">';
 117    if (count($count_links) > 1) {
 118      $output .= t('Show !count results per page.', array('!count' => implode(' | ', $count_links)));
 119    }
 120    else {
 121      $output .= t('Showing all results.');
 122    }
 123    if ($total_count > 1) {
 124      $output .= ' ' . t('@total results total.', array('@total' => $total_count));
 125    }
 126    $output .= '</div>';
 127  
 128    return $output;
 129  }
 130  
 131  /**
 132   * Theme the header of the submissions table.
 133   *
 134   * This is done in it's own function so that webform can retrieve the header and
 135   * use it for sorting the results.
 136   */
 137  function theme_webform_results_submissions_header($node) {
 138    $columns = array(
 139      array('data' => t('#'), 'field' => 'sid', 'sort' => 'desc'),
 140      array('data' => t('Submitted'), 'field' => 'submitted'),
 141    );
 142    if (webform_results_access($node)) {
 143      $columns[] = array('data' => t('User'), 'field' => 'name');
 144      $columns[] = array('data' => t('IP Address'), 'field' => 'remote_addr');
 145    }
 146    $columns[] = array('data' => t('Operations'), 'colspan' => module_exists('print') ? 5 : 3);
 147  
 148    return $columns;
 149  }
 150  
 151  /**
 152   * Preprocess function for webform-results-submissions.tpl.php
 153   */
 154  function template_preprocess_webform_results_submissions(&$vars) {
 155    $vars['node'] = $vars['element']['#node'];
 156    $vars['submissions'] = $vars['element']['#submissions'];
 157    $vars['table'] = $vars['element']['table'];
 158    $vars['total_count'] = $vars['element']['#total_count'];
 159    $vars['pager_count'] = $vars['element']['#pager_count'];
 160    $vars['is_submissions'] = (arg(2) == 'submissions')? 1 : 0;
 161  
 162    unset($vars['element']);
 163  }
 164  
 165  /**
 166   * Create a table containing all submitted values for a webform node.
 167   */
 168  function webform_results_table($node, $pager_count = 0) {
 169    if (isset($_GET['results']) && is_numeric($_GET['results'])) {
 170      $pager_count = $_GET['results'];
 171    }
 172  
 173    // Get all the submissions for the node.
 174    $header = theme('webform_results_table_header', $node);
 175    $submissions = webform_get_submissions($node->nid, $header, $pager_count);
 176    $total_count = webform_get_submission_count($node->nid);
 177  
 178    $output = theme('webform_results_table', $node, $node->webform['components'], $submissions, $total_count, $pager_count);
 179    if ($pager_count) {
 180      $output .= theme('pager', NULL, $pager_count, 0);
 181    }
 182    return $output;
 183  }
 184  
 185  function theme_webform_results_table_header($node) {
 186    return array(
 187      array('data' => t('#'), 'field' => 'sid', 'sort' => 'desc'),
 188      array('data' => t('Submitted'), 'field' => 'submitted'),
 189      array('data' => t('User'), 'field' => 'name'),
 190      array('data' => t('IP Address'), 'field' => 'remote_addr'),
 191    );
 192  }
 193  
 194  /**
 195   * Theme the results table displaying all the submissions for a particular node.
 196   *
 197   * @param $node
 198   *   The node whose results are being displayed.
 199   * @param $components
 200   *   An associative array of the components for this webform.
 201   * @param $submissions
 202   *   An array of all submissions for this webform.
 203   * @param $total_count
 204   *   The total number of submissions to this webform.
 205   * @param $pager_count
 206   *   The number of results to be shown per page.
 207   */
 208  function theme_webform_results_table($node, $components, $submissions, $total_count, $pager_count) {
 209    drupal_add_css(drupal_get_path('module', 'webform') . '/css/webform-admin.css', 'theme', 'all', FALSE);
 210  
 211    $header = array();
 212    $rows = array();
 213    $cell = array();
 214  
 215    // This header has to be generated seperately so we can add the SQL necessary.
 216    // to sort the results.
 217    $header = theme('webform_results_table_header', $node);
 218  
 219    // Generate a row for each submission.
 220    foreach ($submissions as $sid => $submission) {
 221      $cell[] = l($sid, 'node/' . $node->nid . '/submission/' . $sid);
 222      $cell[] = format_date($submission->submitted, 'small');
 223      $cell[] = theme('username', $submission);
 224      $cell[] = $submission->remote_addr;
 225      $component_headers = array();
 226  
 227      // Generate a cell for each component.
 228      foreach ($node->webform['components'] as $component) {
 229        $data = isset($submission->data[$component['cid']]['value']) ? $submission->data[$component['cid']]['value'] : NULL;
 230        $submission_output = webform_component_invoke($component['type'], 'table', $component, $data);
 231        if ($submission_output !== NULL) {
 232          $component_headers[] = check_plain($component['name']);
 233          $cell[] = $submission_output;
 234        }
 235      }
 236  
 237      $rows[] = $cell;
 238      unset($cell);
 239    }
 240    if (!empty($component_headers)) {
 241      $header = array_merge($header, $component_headers);
 242    }
 243  
 244    if (count($rows) == 0) {
 245      $rows[] = array(array('data' => t('There are no submissions for this form. <a href="!url">View this form</a>.', array('!url' => url('node/' . $node->nid))), 'colspan' => 4));
 246    }
 247  
 248  
 249    $output = '';
 250    $output .= theme('webform_results_per_page', $total_count, $pager_count);
 251    $output .= theme('table', $header, $rows);
 252    return $output;
 253  }
 254  
 255  /**
 256   * Delete all submissions for a node.
 257   *
 258   * @param $nid
 259   *   The node id whose submissions will be deleted.
 260   */
 261  function webform_results_clear($nid) {
 262    $node = node_load($nid);
 263    $submissions = webform_get_submissions($nid);
 264    foreach ($submissions as $submission) {
 265      webform_submission_delete($node, $submission);
 266    }
 267  }
 268  
 269  /**
 270   * Confirmation form to delete all submissions for a node.
 271   *
 272   * @param $nid
 273   *   ID of node for which to clear submissions.
 274   */
 275  function webform_results_clear_form($form_state, $node) {
 276    drupal_set_title(t('Clear Form Submissions'));
 277  
 278    $form = array();
 279    $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
 280    $question = t('Are you sure you want to delete all submissions for this form?');
 281  
 282    return confirm_form($form, $question, 'node/' . $node->nid . '/webform-results', NULL, t('Clear'), t('Cancel'));
 283  }
 284  
 285  function webform_results_clear_form_submit($form, &$form_state) {
 286    webform_results_clear($form_state['values']['nid']);
 287    $node = node_load($form_state['values']['nid']);
 288    $title = $node->title;
 289  
 290    $message = t('Webform %title entries cleared.', array('%title' => $title));
 291    drupal_set_message($message);
 292    watchdog('webform', $message);
 293    $form_state['redirect'] = 'node/' . $form_state['values']['nid'] . '/webform-results';
 294  }
 295  
 296  /**
 297   * Form to configure the download of CSV files.
 298   */
 299  function webform_results_download_form(&$form_state, $node) {
 300    module_load_include('inc', 'webform', 'includes/webform.export');
 301    module_load_include('inc', 'webform', 'includes/webform.components');
 302  
 303    $form = array();
 304  
 305    $form['node'] = array(
 306      '#type' => 'value',
 307      '#value' => $node,
 308    );
 309  
 310    $form['format'] = array(
 311      '#type' => 'radios',
 312      '#title' => t('Export format'),
 313      '#options' => webform_export_list(),
 314      '#default_value' => isset($form_state['values']['format']) ? $form_state['values']['format'] : variable_get('webform_export_format', 'delimited'),
 315    );
 316  
 317    $form['delimiter'] = array(
 318      '#type' => 'select',
 319      '#title' => t('Delimited text format'),
 320      '#description' => t('This is the delimiter used in the CSV/TSV file when downloading Webform results. Using tabs in the export is the most reliable method for preserving non-latin characters. You may want to change this to another character depending on the program with which you anticipate importing results.'),
 321      '#default_value' => isset($form_state['values']['delimiter']) ? $form_state['values']['delimiter'] : variable_get('webform_csv_delimiter', '\t'),
 322      '#options' => array(
 323        ','  => t('Comma (,)'),
 324        '\t' => t('Tab (\t)'),
 325        ';'  => t('Semicolon (;)'),
 326        ':'  => t('Colon (:)'),
 327        '|'  => t('Pipe (|)'),
 328        '.'  => t('Period (.)'),
 329        ' '  => t('Space ( )'),
 330      ),
 331    );
 332  
 333    $form['select_options'] = array(
 334      '#type' => 'fieldset',
 335      '#title' => t('Select list options'),
 336      '#collapsible' => TRUE,
 337      '#collapsed' => TRUE,
 338    );
 339  
 340    $form['select_options']['select_keys'] = array(
 341      '#type' => 'radios',
 342      '#title' => t('Select keys'),
 343      '#options' => array(
 344        0 => t('Full, human-readable options (values)'),
 345        1 => t('Short, raw options (keys)'),
 346      ),
 347      '#default_value' => isset($form_state['values']['select_options']['select_keys']) ? $form_state['values']['select_options']['select_keys'] : 0,
 348      '#description' => t('Choose which part of options should be displayed from key|value pairs.'),
 349    );
 350  
 351    $form['select_options']['select_format'] = array(
 352      '#type' => 'radios',
 353      '#title' => t('Select list format'),
 354      '#options' => array(
 355        'separate' => t('Separate'),
 356        'compact' => t('Compact'),
 357      ),
 358      '#default_value' => isset($form_state['values']['select_options']['select_format']) ? $form_state['values']['select_options']['select_format'] : 'separate',
 359      '#attributes' => array('class' => 'webform-select-list-format'),
 360      '#theme' => 'webform_results_download_select_format',
 361    );
 362  
 363    $csv_components = array(
 364      'info' => t('Submission information'),
 365      'serial' => '-' . t('Submission Number'),
 366      'sid' => '-' . t('Submission ID'),
 367      'time' => '-' . t('Time'),
 368      'draft' => '-' . t('Draft'),
 369      'ip_address' => '-' . t('IP Address'),
 370      'uid' => '-' . t('User ID'),
 371      'username' => '-' . t('Username'),
 372    );
 373    $csv_components += webform_component_list($node, 'csv', TRUE);
 374  
 375    $form['components'] = array(
 376      '#type' => 'select',
 377      '#title' => t('Included export components'),
 378      '#options' => $csv_components,
 379      '#default_value' => isset($form_state['values']['components']) ? $form_state['values']['components'] : array_keys($csv_components),
 380      '#multiple' => TRUE,
 381      '#size' => 10,
 382      '#description' => t('The selected components will be included in the export.'),
 383      '#process' => array('webform_component_select'),
 384    );
 385  
 386    $form['range'] = array(
 387      '#type' => 'fieldset',
 388      '#title' => t('Download range options'),
 389      '#collapsible' => TRUE,
 390      '#collapsed' => TRUE,
 391      '#tree' => TRUE,
 392      '#theme' => 'webform_results_download_range',
 393      '#element_validate' => array('webform_results_download_range_validate'),
 394      '#after_build' => array('webform_results_download_range_after_build'),
 395    );
 396  
 397    $form['range']['range_type'] = array(
 398      '#type' => 'radios',
 399      '#options' => array(
 400        'all' => t('All submissions'),
 401        'new' => t('Only new submissions since your last download'),
 402        'latest' => t('Only the latest'),
 403        'range' => t('All submissions starting from'),
 404      ),
 405      '#default_value' => 'all',
 406    );
 407    $form['range']['latest'] = array(
 408      '#type' => 'textfield',
 409      '#size' => 5,
 410      '#maxlength' => 8,
 411      '#default_value' => '',
 412    );
 413    $form['range']['start'] = array(
 414      '#type' => 'textfield',
 415      '#size' => 5,
 416      '#maxlength' => 8,
 417      '#default_value' => '',
 418    );
 419    $form['range']['end'] = array(
 420      '#type' => 'textfield',
 421      '#size' => 5,
 422      '#maxlength' => 8,
 423      '#default_value' => '',
 424      '#description' => '',
 425    );
 426  
 427    // By default results are downloaded. User can override this value if
 428    // programmatically submitting this form.
 429    $form['download'] = array(
 430      '#type' => 'value',
 431      '#default_value' => TRUE
 432    );
 433  
 434    $form['submit'] = array(
 435      '#type' => 'submit',
 436      '#value' => t('Download'),
 437    );
 438  
 439    return $form;
 440  }
 441  
 442  /**
 443   * FormAPI element validate function for the range fieldset.
 444   */
 445  function webform_results_download_range_validate($element, $form_state) {
 446    switch ($element['range_type']['#value']) {
 447      case 'latest':
 448        // Download latest x submissions.
 449        if ($element['latest']['#value'] == '') {
 450          form_error($element['latest'], t('Latest number of submissions field is required.'));
 451        }
 452        else{
 453          if (!is_numeric($element['latest']['#value'])) {
 454            form_error($element['latest'], t('Latest number of submissions must be numeric.'));
 455          }
 456          else{
 457            if ($element['latest']['#value'] <= 0) {
 458              form_error($element['latest'], t('Latest number of submissions must be greater than 0.'));
 459            }
 460          }
 461        }
 462        break;
 463      case 'range':
 464        // Download Start-End range of submissions.
 465        // Start submission number.
 466        if ($element['start']['#value'] == '') {
 467          form_error($element['start'], t('Start submission number is required.'));
 468        }
 469        else{
 470          if (!is_numeric($element['start']['#value'])) {
 471            form_error($element['start'], t('Start submission number must be numeric.'));
 472          }
 473          else{
 474            if ($element['start']['#value'] <= 0) {
 475              form_error($element['start'], t('Start submission number must be greater than 0.'));
 476            }
 477          }
 478        }
 479        // End submission number.
 480        if ($element['end']['#value'] != '') {
 481          if (!is_numeric($element['end']['#value'])) {
 482            form_error($element['end'], t('End submission number must be numeric.'));
 483          }
 484          else{
 485            if ($element['end']['#value'] <= 0) {
 486              form_error($element['end'], t('End submission number must be greater than 0.'));
 487            }
 488            else{
 489              if ($element['end']['#value'] < $element['start']['#value']) {
 490                form_error($element['end'], t('End submission number may not be less than Start submission number.'));
 491              }
 492            }
 493          }
 494        }
 495        break;
 496    }
 497  
 498  }
 499  
 500  /**
 501   * Validate handler for webform_results_download_form().
 502   */
 503  function webform_results_download_form_submit(&$form, &$form_state) {
 504    $options = array(
 505      'delimiter' => $form_state['values']['delimiter'],
 506      'components' => array_keys(array_filter($form_state['values']['components'])),
 507      'select_keys' => $form_state['values']['select_keys'],
 508      'select_format' => $form_state['values']['select_format'],
 509      'range_type' => $form_state['values']['range']['range_type'],
 510      'download' => $form_state['values']['download'],
 511    );
 512  
 513    // Retrieve the list of required SIDs.
 514    if ($options['range_type'] != 'all') {
 515      $options['sids'] = webform_download_sids($form_state['values']['node']->nid, $form_state['values']['range']);
 516    }
 517  
 518    $export_info = webform_results_export($form_state['values']['node'], $form_state['values']['format'], $options);
 519  
 520    // If webform result file should be downloaded, send the file to the browser,
 521    // otherwise save information about the created file in $form_state.
 522    if ($options['download']) {
 523      webform_results_download($form_state['values']['node'], $export_info);
 524    }
 525    else {
 526      $form_state['export_info'] = $export_info;
 527    }
 528  }
 529  
 530  /**
 531   * FormAPI after build function for the download range fieldset.
 532   */
 533  function webform_results_download_range_after_build($element, &$form_state) {
 534    $node = $form_state['values']['node'];
 535  
 536    // Build a list of counts of new and total submissions.
 537    $count = webform_get_submission_count($node->nid);
 538    $sids = webform_download_sids($node->nid, array('range_type' => 'new'));
 539  
 540    $last_download = webform_download_last_download_info($node->nid);
 541  
 542    $element['#webform_download_info']['sid'] = $last_download ? $last_download['sid'] : 0;
 543    $element['#webform_download_info']['requested'] = $last_download ? $last_download['requested'] : $node->created;
 544    $element['#webform_download_info']['total'] = $count;
 545    $element['#webform_download_info']['new'] = count($sids);
 546  
 547    return $element;
 548  }
 549  
 550  /**
 551   * Theme the output of the export range fieldset.
 552   */
 553  function theme_webform_results_download_range($element) {
 554    drupal_add_css(drupal_get_path('module', 'webform') . '/css/webform-admin.css', 'theme', 'all', FALSE);
 555    drupal_add_js(drupal_get_path('module', 'webform') . '/js/webform-admin.js', 'module', 'header', FALSE, TRUE, FALSE);
 556  
 557    $download_info = $element['#webform_download_info'];
 558  
 559    // Set description for total of all submissions.
 560    $element['range_type']['all']['#description'] = '(' . t('@count total', array('@count' => $download_info['total'])) . ')';
 561    $element['range_type']['all']['#prefix'] = '<div class="webform-container-inline">';
 562    $element['range_type']['all']['#suffix'] = '</div>';
 563  
 564    // Set description for "New submissions since last download".
 565    $format = webform_date_format('short');
 566    $requested_date = format_date($download_info['requested'], 'custom', $format);
 567    $element['range_type']['new']['#description'] = '(' . t('@count new since @date', array('@count' => $download_info['new'], '@date' => $requested_date)) . ')';
 568    $element['range_type']['new']['#prefix'] = '<div class="webform-container-inline">';
 569    $element['range_type']['new']['#suffix'] = '</div>';
 570  
 571    // Disable option if there are no new submissions.
 572    if ($download_info['new'] == 0) {
 573      $element['range_type']['new']['#attributes']['disabled'] = 'disabled';
 574    }
 575  
 576    // Render latest x submissions option.
 577    $element['latest']['#attributes']['class'] = 'webform-set-active';
 578    $element['range_type']['latest']['#title'] = t('Only the latest !number submissions', array('!number' => drupal_render($element['latest'])));
 579    $element['range_type']['latest']['#prefix'] = '<div class="webform-container-inline">';
 580    $element['range_type']['latest']['#suffix'] = '</div>';
 581  
 582    // Render Start-End submissions option.
 583    $element['start']['#attributes']['class'] = 'webform-set-active';
 584    $element['end']['#attributes']['class'] = 'webform-set-active';
 585    $element['range_type']['range']['#title'] = t('All submissions starting from: !start and optionally to: !end', array('!start' => drupal_render($element['start']), '!end' => drupal_render($element['end'])));
 586    $element['range_type']['range']['#prefix'] = '<div class="webform-container-inline">';
 587    $element['range_type']['range']['#suffix'] = '</div>';
 588  
 589  
 590    $last_sid = $download_info['sid'] ? $download_info['sid'] : theme('placeholder', t('none'));
 591    $element['range_type']['range']['#description'] = '(' . t('Use submission IDs for the range. Last downloaded end SID: !sid.', array('!sid' => $last_sid)) . ')';
 592  
 593    return drupal_render($element);
 594  }
 595  
 596  /**
 597   * Theme the output of the select list format radio buttons.
 598   */
 599  function theme_webform_results_download_select_format($element) {
 600    drupal_add_css(drupal_get_path('module', 'webform') . '/css/webform-admin.css', 'theme', 'all', FALSE);
 601  
 602    $output = '';
 603  
 604    // Build an example table for the separate option.
 605    $header = array(t('Option A'), t('Option B'), t('Option C'));
 606    $rows = array(
 607      array('X', '', ''),
 608      array('X', '', 'X'),
 609      array('', 'X', 'X'),
 610    );
 611  
 612    $element['separate']['#attributes']['class'] = '';
 613    $element['separate']['#description'] = theme('table', $header, $rows);
 614    $element['separate']['#description'] .= t('Separate options are more suitable for building reports, graphs, and statistics in a spreadsheet application.');
 615    $output .= drupal_render($element['separate']);
 616  
 617    // Build an example table for the compact option.
 618    $header = array(t('My select list'));
 619    $rows = array(
 620      array('Option A'),
 621      array('Option A,Option C'),
 622      array('Option B,Option C'),
 623    );
 624  
 625    $element['separate']['#attributes']['class'] = '';
 626    $element['compact']['#description'] = theme('table', $header, $rows);
 627    $element['compact']['#description'] .= t('Compact options are more suitable for importing data into other systems.');
 628    $output .= drupal_render($element['compact']);
 629  
 630    return $output;
 631  }
 632  
 633  /**
 634   * Generate a Excel-readable CSV file containing all submissions for a Webform.
 635   *
 636   * The CSV requires that the data be presented in a flat file.  In order
 637   * to maximize usability to the Excel community and minimize subsequent
 638   * stats or spreadsheet programming this program extracts data from the
 639   * various records for a given session and presents them as a single file
 640   * where each row represents a single record.
 641   * The structure of the file is:
 642   *   Heading Line 1: Gives group overviews padded by empty cells to the
 643   *                   next group.  A group may be a question and corresponds
 644   *                   to a component in the webform philosophy. Each group
 645   *                   overview will have a fixed number of columns beneath it.
 646   *   Heading line 2: gives column headings
 647   *   Data line 1 .....
 648   *   Data line 2 .....
 649   *
 650   * An example of this format is given below.  Note the columns have had spaces
 651   * added so the columns line up.  This is not the case with actual file where
 652   * a column may be null.  Note also, that multiple choice questions as produced
 653   * by checkboxes or radio buttons have been presented as "yes" or "no" and the
 654   * actual choice text is retained only in the header line 2.
 655   * Data from text boxes and input fields are written out in the body of the table.
 656   *
 657   *   Submission Details,    ,   ,      ,Question 1,        ,        ,..,        ,Question 2,        ,        ,..,        ,Question n
 658   *   timestamp         ,time,SID,userid,Choice 1  ,Choice 2,Choice 3,..,Choice n,Choice 1  ,Choice 2,Choice 3,..,Choice n,Comment
 659   *   21 Feb 2005       ,1835,23 ,34    ,X         ,        ,        ,..,       ,X          ,X       ,X       ,..,X       ,My comment
 660   *   23 Feb 2005       ,1125,24 ,89    ,X         ,X       ,        ,..,       ,X          ,X       ,X       ,..,X       ,Hello
 661   *   .................................................................................................................................
 662   *   27 Feb 2005       ,1035,56 ,212   ,X         ,        ,        ,..,       ,X          ,X       ,X       ,..,X       ,How is this?
 663   *
 664   */
 665  function webform_results_export($node, $format = 'delimited', $options = array()) {
 666    global $user;
 667    module_load_include('inc', 'webform', 'includes/webform.export');
 668    module_load_include('inc', 'webform', 'includes/webform.components');
 669  
 670    $submission_information = array(
 671      'serial' => t('Serial'),
 672      'sid' => t('SID'),
 673      'time' => t('Time'),
 674      'draft' => t('Draft'),
 675      'ip_address' => t('IP Address'),
 676      'uid' => t('UID'),
 677      'username' => t('Username'),
 678    );
 679  
 680    if (empty($options)) {
 681      $options = array(
 682        'delimiter' => variable_get('webform_csv_delimiter', '\t'),
 683        'components' => array_keys($submission_information) + array_keys(webform_component_list($node, 'csv', TRUE)),
 684        'components' => array_merge(array_keys($submission_information), array_keys(webform_component_list($node, 'csv', TRUE))),
 685        'select_display' => 'value',
 686        'select_format' => 'separate',
 687        'range_type' => 'all',
 688      );
 689    }
 690    else {
 691      foreach ($submission_information as $key => $label) {
 692        if (!in_array($key, $options['components'])) {
 693          unset($submission_information[$key]);
 694        }
 695      }
 696    }
 697  
 698    // Open a new Webform exporter object.
 699    $exporter = webform_export_create_handler($format, $options);
 700  
 701    $file_name = tempnam(variable_get('file_directory_temp', file_directory_temp()), 'webform');
 702    $handle = @fopen($file_name, 'w'); // The @ suppresses errors.
 703    $exporter->bof($handle);
 704  
 705    // Fill in the header for the submission information (if any).
 706    $header[2] = $header[1] = $header[0] = count($submission_information) ? array_fill(0, count($submission_information), '') : array();
 707    if (count($submission_information)) {
 708      $header[0][0] = $node->title;
 709      $header[1][0] = t('Submission Details');
 710      foreach (array_values($submission_information) as $column => $label) {
 711        $header[2][$column] = $label;
 712      }
 713    }
 714  
 715    // Compile header information for components.
 716    foreach ($options['components'] as $cid) {
 717      if (isset($node->webform['components'][$cid])) {
 718        $component = $node->webform['components'][$cid];
 719  
 720        // Let each component determine its headers.
 721        if (webform_component_feature($component['type'], 'csv')) {
 722          $component_header = (array) webform_component_invoke($component['type'], 'csv_headers', $component, $options);
 723          $header[0] = array_merge($header[0], (array) $component_header[0]);
 724          $header[1] = array_merge($header[1], (array) $component_header[1]);
 725          $header[2] = array_merge($header[2], (array) $component_header[2]);
 726        }
 727      }
 728    }
 729  
 730    // Add headers to the file.
 731    foreach ($header as $row) {
 732      $exporter->add_row($handle, $row);
 733    }
 734  
 735    // Get all the submissions for the node.
 736    $filters['nid'] = $node->nid;
 737    if (!empty($options['sids'])){
 738      $filters['sid'] = $options['sids'];
 739    }
 740    $submissions = webform_get_submissions($filters);
 741  
 742    // Generate a row for each submission.
 743    $row_count = 0;
 744    foreach ($submissions as $sid => $submission) {
 745      $row_count++;
 746  
 747      $row = array();
 748      if (isset($submission_information['serial'])) {
 749        $row[] = $row_count;
 750      }
 751      if (isset($submission_information['sid'])) {
 752        $row[] = $sid;
 753      }
 754      if (isset($submission_information['time'])) {
 755        $row[] = format_date($submission->submitted, 'small');
 756      }
 757      if (isset($submission_information['draft'])) {
 758        $row[] = $submission->is_draft;
 759      }
 760      if (isset($submission_information['ip_address'])) {
 761        $row[] =  $submission->remote_addr;
 762      }
 763      if (isset($submission_information['uid'])) {
 764        $row[] = $submission->uid;
 765      }
 766      if (isset($submission_information['username'])) {
 767        $row[] = $submission->name;
 768      }
 769  
 770      foreach ($options['components'] as $cid) {
 771        if (isset($node->webform['components'][$cid])) {
 772          $component = $node->webform['components'][$cid];
 773          // Let each component add its data.
 774          $raw_data = isset($submission->data[$cid]['value']) ? $submission->data[$cid]['value'] : NULL;
 775          if (webform_component_feature($component['type'], 'csv')) {
 776            $data = webform_component_invoke($component['type'], 'csv_data', $component, $options, $raw_data);
 777            if (is_array($data)) {
 778              $row = array_merge($row, array_values($data));
 779            }
 780            else {
 781              $row[] = isset($data) ? $data : '';
 782            }
 783          }
 784        }
 785      }
 786  
 787      // Write data from submissions.
 788      $data = $exporter->add_row($handle, $row);
 789    }
 790  
 791    // Add the closing bytes.
 792    $exporter->eof($handle);
 793  
 794    // Close the file.
 795    @fclose($handle);
 796  
 797    $export_info['options'] = $options;
 798    $export_info['file_name'] = $file_name;
 799    $export_info['exporter'] = $exporter;
 800    $export_info['row_count'] = $row_count;
 801    $export_info['last_sid'] = $sid;
 802  
 803    return $export_info;
 804  }
 805  
 806  /**
 807   * Send a generated webform results file to the user's browser.
 808   *
 809   * @param $node
 810   *   The webform node.
 811   * @param $export_info
 812   *   Export information array retrieved from webform_results_export().
 813   */
 814  function webform_results_download($node, $export_info) {
 815    global $user;
 816  
 817    // $exporter, $file_name, $row_count
 818    $export_name = _webform_safe_name($node->title);
 819    $export_info['exporter']->set_headers($export_name);
 820    @readfile($export_info['file_name']);  // The @ makes it silent.
 821    @unlink($export_info['file_name']);  // Clean up, the @ makes it silent.
 822  
 823    // Update user last downloaded sid if required.
 824    if ($export_info['options']['range_type'] != 'range' && $export_info['row_count'] > 0) {
 825      // Delete existing record.
 826      db_query('DELETE FROM {webform_last_download} WHERE nid = %d AND uid = %d', $node->nid, $user->uid);
 827      // Write new record.
 828      db_query('INSERT INTO {webform_last_download} (nid, uid, sid, requested) VALUES (%d, %d, %d, %d)', $node->nid, $user->uid, $export_info['last_sid'], time());
 829    }
 830  
 831    exit();
 832  }
 833  
 834  /**
 835   * Provides a simple analysis of all submissions to a webform.
 836   *
 837   * @param $node
 838   *   The webform node on which to generate the analysis.
 839   * @param $sids
 840   *   An array of submission IDs to which this analysis may be filtered. May be
 841   *   used to generate results that are per-user or other groups of submissions.
 842   * @param $analysis_component
 843   *   A webform component. If passed in, additional information may be returned
 844   *   relating specifically to that component's analysis, such as a list of
 845   *   "Other" values within a select list.
 846   */
 847  function webform_results_analysis($node, $sids = array(), $analysis_component = NULL) {
 848    if (!is_array($sids)) {
 849      $sids = array();
 850    }
 851  
 852    // If showing a component's details, we don't want to loose the menu tabs.
 853    if ($analysis_component) {
 854      $item = menu_get_item('node/' . $node->nid . '/webform-results/analysis');
 855      menu_set_item(NULL, $item);
 856    }
 857  
 858    $components = isset($analysis_component) ? array($analysis_component['cid'] => $analysis_component) : $node->webform['components'];
 859    $data = array();
 860    foreach ($components as $cid => $component) {
 861      // Do component specific call.
 862      if ($row_data = webform_component_invoke($component['type'], 'analysis', $component, $sids, isset($analysis_component))) {
 863        $data[$cid] = $row_data;
 864      }
 865    }
 866  
 867    return theme('webform_results_analysis', $node, $data, $sids, $analysis_component);
 868  }
 869  
 870  /**
 871   * Output the content of the Analysis page.
 872   *
 873   * @see webform_results_analysis()
 874   */
 875  function theme_webform_results_analysis($node, $data, $sids = array(), $analysis_component = NULL) {
 876  
 877    $rows = array();
 878    $question_number = 0;
 879    $single = isset($analysis_component);
 880  
 881    $header = array(
 882      $single ? $analysis_component['name'] : t('Q'),
 883      array('data' => $single ? '&nbsp;' : t('responses'), 'colspan' => '10')
 884    );
 885  
 886    foreach ($data as $cid => $row_data) {
 887      $question_number++;
 888  
 889      if (is_array($row_data)) {
 890        $row = array();
 891        if (!$single) {
 892          $row['data'][] = array('data' => '<strong>' . $question_number . '</strong>', 'rowspan' => count($row_data) + 1, 'valign' => 'top');
 893          $row['data'][] = array('data' => '<strong>' . check_plain($node->webform['components'][$cid]['name']) . '</strong>', 'colspan' => '10');
 894          $row['class'] = 'webform-results-question';
 895        }
 896        $rows = array_merge($rows, array_merge(array($row), $row_data));
 897      }
 898    }
 899  
 900    if (count($rows) == 0) {
 901      $rows[] = array(array('data' => t('There are no submissions for this form. <a href="!url">View this form</a>.', array('!url' => url('node/' . $node->nid))), 'colspan' => 20));
 902    }
 903  
 904    return theme('table', $header, $rows, array('class' => 'webform-results-analysis'));
 905  }
 906  
 907  /**
 908   * Given a set of range options, retrieve a set of SIDs for a webform node.
 909   */
 910  function webform_download_sids($nid, $range_options, $uid = NULL) {
 911    $query = 'SELECT sid FROM {webform_submissions} WHERE nid = %d';
 912    $args = array($nid);
 913  
 914    switch ($range_options['range_type']) {
 915      case 'all':
 916        // All Submissions.
 917        $query .= ' ORDER BY sid ASC';
 918        break;
 919      case 'new':
 920        // All Since Last Download.
 921        $download_info = webform_download_last_download_info($nid, $uid);
 922        $last_sid = $download_info ? $download_info['sid'] : 0;
 923        $query .= ' AND sid > %d ORDER BY sid ASC';
 924        $args[] = $last_sid;
 925        break;
 926      case 'latest':
 927        // Last x Submissions.
 928        $query .= ' ORDER BY sid DESC LIMIT 0, %d';
 929        $args[] = $range_options['latest'];
 930        break;
 931      case 'range':
 932        // Submissions Start-End.
 933        $query .=' AND sid >= %d';
 934        $args[] = $range_options['start'];
 935        if ($range_options['end']) {
 936          $query .= ' AND sid <= %d';
 937          $args[] = $range_options['end'];
 938        }
 939        $query .= ' ORDER BY sid ASC';
 940        break;
 941    }
 942    $result = db_query($query, $args);
 943    $sids = array();
 944    while ($row = db_fetch_object($result)) {
 945      $sids[] = $row->sid;
 946    }
 947  
 948    // The last x submissions option has SIDs that are in reverse order.
 949    if ($range_options['range_type'] == 'latest') {
 950      $sids = array_reverse($sids);
 951    }
 952  
 953    return $sids;
 954  }
 955  
 956  /**
 957   * Get this user's last download information, including the SID and timestamp.
 958   *
 959   * This function provides an array of information about the last download that
 960   * a user had for a particular Webform node. Currently it only returns an array
 961   * with two keys:
 962   *  - sid: The last submission ID that was downloaded.
 963   *  - requested: The timestamp of the last download request.
 964   *
 965   * @param $nid
 966   *   The Webform NID.
 967   * @param $uid
 968   *   The user account ID for which to retrieve download information.
 969   * @return
 970   *   An array of download information or FALSE if this user has never downloaded
 971   *   results for this particular node.
 972   */
 973  function webform_download_last_download_info($nid, $uid = NULL) {
 974    $uid = isset($uid) ? $uid : $GLOBALS['user']->uid;
 975    $result = db_query("SELECT * FROM {webform_last_download} WHERE nid = %d AND uid = %d", $nid, $uid);
 976    $info = db_fetch_array($result);
 977  
 978    return $info;
 979  }


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7