[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/webform/components/ -> select.inc (source)

   1  <?php
   2  
   3  /**
   4   * @file
   5   * Webform module multiple select component.
   6   */
   7  
   8  /**
   9   * Implements _webform_defaults_component().
  10   */
  11  function _webform_defaults_select() {
  12    return array(
  13      'name' => '',
  14      'form_key' => NULL,
  15      'mandatory' => 0,
  16      'pid' => 0,
  17      'weight' => 0,
  18      'value' => '',
  19      'extra' => array(
  20        'items' => '',
  21        'multiple' => NULL,
  22        'aslist' => NULL,
  23        'optrand' => 0,
  24        'other_option' => NULL,
  25        'other_text' => t('Other...'),
  26        'title_display' => 0,
  27        'description' => '',
  28        'custom_keys' => FALSE,
  29        'options_source' => '',
  30        'private' => FALSE,
  31      ),
  32    );
  33  }
  34  
  35  /**
  36   * Implements _webform_theme_component().
  37   */
  38  function _webform_theme_select() {
  39    return array(
  40      'webform_display_select' => array(
  41        'arguments' => array('element' => NULL),
  42        'file' => 'components/select.inc',
  43      ),
  44    );
  45  }
  46  
  47  /**
  48   * Implements _webform_edit_component().
  49   */
  50  function _webform_edit_select($component) {
  51    $form = array();
  52  
  53    drupal_add_js(drupal_get_path('module', 'webform') . '/js/select-admin.js', 'module', 'header', FALSE, TRUE, FALSE);
  54    drupal_add_js(array('webform' => array('selectOptionsUrl' => url('webform/ajax/options/' . $component['nid']))), 'setting');
  55  
  56    $other = array();
  57    if ($info = _webform_select_options_info()) {
  58      $options = array('' => t('None'));
  59      foreach ($info as $name => $source) {
  60        $options[$name] = $source['title'];
  61      }
  62  
  63      $other['options_source'] = array(
  64        '#title' => t('Load a pre-built option list'),
  65        '#type' => 'select',
  66        '#options' => $options,
  67        '#default_value' => $component['extra']['options_source'],
  68        '#weight' => 1,
  69        '#description' => t('Use a pre-built list of options rather than entering options manually. Options will not be editable if using pre-built list.'),
  70        '#parents' => array('extra', 'options_source'),
  71        '#weight' => 5,
  72      );
  73    }
  74  
  75    if (module_exists('select_or_other')) {
  76      $other['other_option'] = array(
  77        '#type' => 'checkbox',
  78        '#title' => t('Allow "Other..." option'),
  79        '#default_value' => $component['extra']['other_option'],
  80        '#description' => t('Check this option if you want to allow users to enter an option not on the list.'),
  81        '#parents' => array('extra', 'other_option'),
  82        '#weight' => 2,
  83      );
  84      $other['other_text'] = array(
  85        '#type' => 'textfield',
  86        '#title' => t('Text for "Other..." option'),
  87        '#default_value' => $component['extra']['other_text'],
  88        '#description' => t('If allowing other options, enter text to be used for other-enabling option.'),
  89        '#parents' => array('extra', 'other_text'),
  90        '#weight' => 3,
  91      );
  92    }
  93  
  94    if (module_exists('options_element')) {
  95      $options = _webform_select_options($component, FALSE, FALSE);
  96  
  97      $form['items'] = array(
  98        '#type' => 'fieldset',
  99        '#title' => t('Options'),
 100        '#collapsible' => TRUE,
 101        '#attributes' => array('class' => 'webform-options-element'),
 102        '#element_validate' => array('_webform_edit_validate_options'),
 103        '#weight' => 2,
 104      );
 105  
 106      $form['items']['options'] = array(
 107        '#type' => 'options',
 108        '#limit' => 500,
 109        '#optgroups' => $component['extra']['aslist'],
 110        '#multiple' => $component['extra']['multiple'],
 111        '#multiple_toggle' => t('Multiple'),
 112        '#default_value' => $component['value'],
 113        '#options' => $options,
 114        '#options_readonly' => !empty($component['extra']['options_source']),
 115        '#key_type' => 'mixed',
 116        '#key_type_toggle' => t('Customize keys (Advanced)'),
 117        '#key_type_toggled' => $component['extra']['custom_keys'],
 118        '#default_value_pattern' => '^%.+\[.+\]$',
 119        '#weight' => 1,
 120      );
 121  
 122      $form['items']['options']['option_settings'] = $other;
 123    }
 124    else {
 125      $form['extra']['items'] = array(
 126        '#type' => 'textarea',
 127        '#title' => t('Options'),
 128        '#default_value' => $component['extra']['items'],
 129        '#description' => t('<strong>Key-value pairs MUST be specified as "safe_key|Some readable option"</strong>. Use of only alphanumeric characters and underscores is recommended in keys. One option per line. Option groups may be specified with &lt;Group Name&gt;. &lt;&gt; can be used to insert items at the root of the menu after specifying a group.') . theme('webform_token_help'),
 130        '#cols' => 60,
 131        '#rows' => 5,
 132        '#weight' => 0,
 133        '#required' => TRUE,
 134        '#wysiwyg' => FALSE,
 135        '#element_validate' => array('_webform_edit_validate_select'),
 136      );
 137  
 138      if (!empty($component['extra']['options_source'])) {
 139        $form['extra']['items']['#attributes'] = array('readonly' => 'readonly');
 140      }
 141  
 142      $form['extra'] = array_merge($form['extra'], $other);
 143      $form['value'] = array(
 144        '#type' => 'textfield',
 145        '#title' => t('Default value'),
 146        '#default_value' => $component['value'],
 147        '#description' => t('The default value of the field identified by its key. For multiple selects use commas to separate multiple defaults.') . theme('webform_token_help'),
 148        '#size' => 60,
 149        '#maxlength' => 1024,
 150        '#weight' => 0,
 151      );
 152      $form['extra']['multiple'] = array(
 153        '#type' => 'checkbox',
 154        '#title' => t('Multiple'),
 155        '#default_value' => $component['extra']['multiple'],
 156        '#description' => t('Check this option if the user should be allowed to choose multiple values.'),
 157        '#weight' => 0,
 158      );
 159    }
 160  
 161    $form['display']['aslist'] = array(
 162      '#type' => 'checkbox',
 163      '#title' => t('Listbox'),
 164      '#default_value' => $component['extra']['aslist'],
 165      '#description' => t('Check this option if you want the select component to be displayed as a select list box instead of radio buttons or checkboxes. Option groups (nested options) are only supported with listbox components.'),
 166      '#parents' => array('extra', 'aslist'),
 167    );
 168    $form['display']['optrand'] = array(
 169      '#type' => 'checkbox',
 170      '#title' => t('Randomize options'),
 171      '#default_value' => $component['extra']['optrand'],
 172      '#description' => t('Randomizes the order of the options when they are displayed in the form.'),
 173      '#parents' => array('extra', 'optrand'),
 174    );
 175  
 176    return $form;
 177  }
 178  
 179  /**
 180   * Element validation callback. Ensure keys are not duplicated.
 181   */
 182  function _webform_edit_validate_select($element, &$form_state) {
 183    // Check for duplicate key values to prevent unexpected data loss. Require
 184    // all options to include a safe_key.
 185    if (!empty($element['#value'])) {
 186      $lines = explode("\n", trim($element['#value']));
 187      $existing_keys = array();
 188      $duplicate_keys = array();
 189      $missing_keys = array();
 190      $long_keys = array();
 191      $group = '';
 192      foreach ($lines as $line) {
 193        $matches = array();
 194        $line = trim($line);
 195        if (preg_match('/^\<([^>]*)\>$/', $line, $matches)) {
 196          $group = $matches[1];
 197          $key = NULL; // No need to store group names.
 198        }
 199        elseif (preg_match('/^([^|]*)\|(.*)$/', $line, $matches)) {
 200          $key = $matches[1];
 201          if (strlen($key) > 128) {
 202            $long_keys[] = $key;
 203          }
 204        }
 205        else {
 206          $missing_keys[] = $line;
 207        }
 208  
 209        if (isset($key)) {
 210          if (isset($existing_keys[$group][$key])) {
 211            $duplicate_keys[$key] = $key;
 212          }
 213          else {
 214            $existing_keys[$group][$key] = $key;
 215          }
 216        }
 217      }
 218  
 219      if (!empty($missing_keys)) {
 220        form_error($element, t('Every option must have a key specified. Specify each option as "safe_key|Some readable option".'));
 221      }
 222  
 223      if (!empty($long_keys)) {
 224        form_error($element, t('Option keys must be less than 128 characters. The following keys exceed this limit:') . theme('item_list', $long_keys));
 225      }
 226  
 227      if (!empty($duplicate_keys)) {
 228        form_error($element, t('Options within the select list must be unique. The following keys have been used multiple times:') . theme('item_list', $duplicate_keys));
 229      }
 230  
 231      // Set the listbox option if needed.
 232      if (empty($missing_keys) && empty($long_keys) && empty($duplicate_keys)) {
 233        $options = _webform_select_options_from_text($element['#value']);
 234        _webform_edit_validate_set_aslist($options, $form_state);
 235      }
 236    }
 237  
 238    return TRUE;
 239  }
 240  
 241  /**
 242   * Set the appropriate webform values when using the options element module.
 243   */
 244  function _webform_edit_validate_options($element, &$form_state) {
 245    $key = end($element['#parents']);
 246    $element_options = $form_state['values'][$key]['options'];
 247    unset($form_state['values'][$key]);
 248  
 249    $form_state['values']['extra'][$key] = form_options_to_text($element_options['options'], 'custom');
 250  
 251    // Options saved for select components.
 252    if ($key == 'items') {
 253      $form_state['values']['extra']['multiple'] = $element_options['multiple'];
 254      $form_state['values']['extra']['custom_keys'] = $element_options['custom_keys'];
 255      $form_state['values']['value'] = is_array($element_options['default_value']) ? implode(', ', $element_options['default_value']) : $element_options['default_value'];
 256  
 257      // Set the listbox option if needed.
 258      _webform_edit_validate_set_aslist($element_options['options'], $form_state);
 259    }
 260    // Options saved for grid components.
 261    else {
 262      $form_state['values']['extra']['custom_' . rtrim($key, 's') . '_keys'] = $element_options['custom_keys'];
 263    }
 264  }
 265  
 266  /**
 267   * Ensure "aslist" is used for option groups. Called from options validations.
 268   */
 269  function _webform_edit_validate_set_aslist($options, &$form_state) {
 270    if (empty($form_state['values']['extra']['aslist']) && !empty($options)) {
 271      foreach ($options as $option) {
 272        if (is_array($option)) {
 273          $form_state['values']['extra']['aslist'] = 1;
 274          drupal_set_message(t('The component %name has automatically been set to display as a listbox in order to support option groups.', array('%name' => $form_state['values']['name'])), 'warning');
 275          break;
 276        }
 277      }
 278    }
 279  }
 280  
 281  /**
 282   * Implements _webform_render_component().
 283   */
 284  function _webform_render_select($component, $value = NULL, $filter = TRUE) {
 285    $node = isset($component['nid']) ? node_load($component['nid']) : NULL;
 286  
 287    $element = array(
 288      '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
 289      '#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
 290      '#required' => $component['mandatory'],
 291      '#weight' => $component['weight'],
 292      '#description' => $filter ? _webform_filter_descriptions($component['extra']['description'], $node) : $component['extra']['description'],
 293      '#theme_wrappers' => array('webform_element_wrapper'),
 294      '#pre_render' => array('webform_element_title_display'),
 295      '#post_render' => array('webform_element_wrapper'),
 296      '#translatable' => array('title', 'description', 'options'),
 297    );
 298  
 299    // Convert the user-entered options list into an array.
 300    $default_value = $filter ? _webform_filter_values($component['value'], $node, NULL, NULL, FALSE) : $component['value'];
 301    $options = _webform_select_options($component, !$component['extra']['aslist'], $filter);
 302  
 303    if ($component['extra']['optrand']) {
 304      _webform_shuffle_options($options);
 305    }
 306  
 307    // Add default options if using a select list with no default. This matches
 308    // Drupal 7's handling of select lists.
 309    if ($component['extra']['aslist'] && !$component['extra']['multiple'] && $default_value === '') {
 310      $options = array('' => ($component['mandatory'] ? t('- Select -') : t('- None -'))) + $options;
 311    }
 312  
 313    // Set the component options.
 314    $element['#options'] = $options;
 315  
 316    // Set the default value.
 317    if (isset($value)) {
 318      if ($component['extra']['multiple']) {
 319        // Set the value as an array.
 320        $element['#default_value'] = array();
 321        foreach ((array) $value as $key => $option_value) {
 322          $element['#default_value'][] = $option_value;
 323        }
 324      }
 325      else {
 326        // Set the value as a single string.
 327        $element['#default_value'] = '';
 328        foreach ((array) $value as $option_value) {
 329          $element['#default_value'] = $option_value;
 330        }
 331      }
 332    }
 333    elseif ($default_value !== '') {
 334      // Convert default value to a list if necessary.
 335      if ($component['extra']['multiple']) {
 336        $varray = explode(',', $default_value);
 337        foreach ($varray as $key => $v) {
 338          $v = trim($v);
 339          if ($v !== '') {
 340            $element['#default_value'][] = $v;
 341          }
 342        }
 343      }
 344      else {
 345        $element['#default_value'] = $default_value;
 346      }
 347    }
 348    elseif ($component['extra']['multiple']) {
 349      $element['#default_value'] = array();
 350    }
 351  
 352    if ($component['extra']['other_option'] && module_exists('select_or_other')) {
 353      // Set display as a select_or_other element:
 354      $element['#type'] = 'select_or_other';
 355      $element['#other'] = !empty($component['extra']['other_text']) ? check_plain($component['extra']['other_text']) : t('Other...');
 356      $element['#other_unknown_defaults'] = 'other';
 357      $element['#other_delimiter'] = ', ';
 358      $element['#process'] = array('select_or_other_process', 'webform_expand_select_or_other');
 359      if ($component['extra']['multiple']) {
 360        $element['#multiple'] = TRUE;
 361        $element['#select_type'] = 'checkboxes';
 362      }
 363      else {
 364        $element['#multiple'] = FALSE;
 365        $element['#select_type'] = 'radios';
 366      }
 367      if ($component['extra']['aslist']) {
 368        $element['#select_type'] = 'select';
 369      }
 370    }
 371    elseif ($component['extra']['aslist']) {
 372      // Set display as a select list:
 373      $element['#type'] = 'select';
 374      if ($component['extra']['multiple']) {
 375        $element['#size'] = 4;
 376        $element['#multiple'] = TRUE;
 377      }
 378    }
 379    else {
 380      if ($component['extra']['multiple']) {
 381        // Set display as a checkbox set.
 382        $element['#type'] = 'checkboxes';
 383        // Drupal 6 hack to properly render on multipage forms.
 384        $element['#process'] = array('webform_expand_checkboxes');
 385        $element['#pre_render'][] = 'webform_expand_select_ids';
 386      }
 387      else {
 388        // Set display as a radio set.
 389        $element['#type'] = 'radios';
 390        $element['#pre_render'][] = 'webform_expand_select_ids';
 391      }
 392    }
 393  
 394    return $element;
 395  }
 396  
 397  /**
 398   * Process function to ensure select_or_other elements validate properly.
 399   */
 400  function webform_expand_select_or_other($element) {
 401    // Disable validation for back-button and save draft.
 402    $element['select']['#validated'] = TRUE;
 403    $element['select']['#webform_validated'] = FALSE;
 404  
 405    $element['other']['#validated'] = TRUE;
 406    $element['other']['#webform_validated'] = FALSE;
 407  
 408    // The Drupal FAPI does not support #title_display inline so we need to move
 409    // to a supported value here to be compatible with select_or_other.
 410    $element['select']['#title_display'] = $element['#title_display'] === 'inline' ? 'before' : $element['#title_display'];
 411  
 412    // If the default value contains "select_or_other" (the key of the select
 413    // element for the "other..." choice), discard it and set the "other" value.
 414    if (is_array($element['#default_value']) && in_array('select_or_other', $element['#default_value'])) {
 415      $key = array_search('select_or_other', $element['#default_value']);
 416      unset($element['#default_value'][$key]);
 417      $element['#default_value'] = array_values($element['#default_value']);
 418      $element['other']['#default_value'] = implode(', ', $element['#default_value']);
 419    }
 420  
 421    // Sanitize the options in Select or other check boxes and radio buttons.
 422    if ($element['#select_type'] == 'checkboxes') {
 423      $element['select']['#pre_render'][] = 'webform_expand_select_ids';
 424    }
 425    elseif ($element['#select_type'] == 'radios') {
 426      $element['select']['#pre_render'][] = 'webform_expand_select_ids';
 427    }
 428  
 429    return $element;
 430  }
 431  
 432  /**
 433   * Drupal 6 hack that properly *renders* checkboxes in multistep forms. This is
 434   * different than the value hack needed in Drupal 5, which is no longer needed.
 435   */
 436  function webform_expand_checkboxes($element) {
 437    // Elements that have a value set are already in the form structure cause
 438    // them not to be written when the expand_checkboxes function is called.
 439    $default_value = array();
 440    foreach (element_children($element) as $key) {
 441      if (isset($element[$key]['#default_value'])) {
 442        $default_value[$key] = $element[$key]['#default_value'];
 443        unset($element[$key]);
 444      }
 445    }
 446  
 447    $element = expand_checkboxes($element);
 448  
 449    // Escape the values of checkboxes.
 450    foreach (element_children($element) as $key) {
 451      $element[$key]['#return_value'] = check_plain($element[$key]['#return_value']);
 452      $element[$key]['#name'] = $element['#name'] . '[' . $element[$key]['#return_value'] . ']';
 453      $element[$key]['#value_callback'] = 'webform_checkbox_value';
 454      $element[$key]['#pre_render'][] = 'webform_checkbox_prerender';
 455    }
 456  
 457    foreach ($default_value as $key => $val) {
 458      $element[$key]['#default_value'] = $val;
 459    }
 460    return $element;
 461  }
 462  
 463  /**
 464   * Helper function to ensure that the default value of "0" checkboxes renders.
 465   *
 466   * The default handling of checkboxes only checks checkboxes based on the #value
 467   * property. If a checkbox has a value of "0" (as a string), the checkbox
 468   * doesn't print out the way it should.
 469   *
 470   * @see theme_checkbox()
 471   */
 472  function webform_checkbox_prerender($element) {
 473    if ($element['#value'] === '0') {
 474      $element['#value'] = TRUE;
 475    }
 476    return $element;
 477  }
 478  
 479  /**
 480   * Helper function to determine the value for a checkbox form element.
 481   *
 482   * Drupal core cannot decern the difference between an unchecked checkbox and
 483   * a checked checkbox that has a value of '0'. This value callback will return
 484   * NULL instead of an integer 0 for checkboxes that are not checked.
 485   *
 486   * @see form_type_checkbox_value()
 487   */
 488  function webform_checkbox_value($form, $edit = FALSE) {
 489    if ($edit !== FALSE) {
 490      if (empty($form['#disabled'])) {
 491        return $edit !== NULL ? $form['#return_value'] : NULL; // 0 in core.
 492      }
 493      else {
 494        return $form['#default_value'];
 495      }
 496    }
 497  }
 498  
 499  /**
 500   * FAPI process function to rename IDs attached to checkboxes and radios.
 501   */
 502  function webform_expand_select_ids($element) {
 503    $id = $element['#id'] = str_replace('_', '-', _webform_safe_name(strip_tags($element['#id'])));
 504    $delta = 0;
 505    foreach (element_children($element) as $key) {
 506      $delta++;
 507      // Convert the #id for each child to a safe name, regardless of key.
 508      $element[$key]['#id'] = $id . '-' . $delta;
 509  
 510      // Prevent scripts or CSS in the labels for each checkbox or radio.
 511      $element[$key]['#title'] = _webform_filter_xss($element[$key]['#title']);
 512    }
 513    return $element;
 514  }
 515  
 516  /**
 517   * Implements _webform_display_component().
 518   */
 519  function _webform_display_select($component, $value, $format = 'html') {
 520    return array(
 521      '#title' => $component['name'],
 522      '#weight' => $component['weight'],
 523      '#theme' => 'webform_display_select',
 524      '#theme_wrappers' => $format == 'html' ? array('webform_element', 'webform_element_wrapper') : array('webform_element_text'),
 525      '#post_render' => array('webform_element_wrapper'),
 526      '#format' => $format,
 527      '#options' => _webform_select_options($component, !$component['extra']['aslist']),
 528      '#value' => (array) $value,
 529      '#translatable' => array('title', 'options'),
 530    );
 531  }
 532  
 533  /**
 534   * Implements _webform_submit_component().
 535   *
 536   * Convert FAPI 0/1 values into something saveable.
 537   */
 538  function _webform_submit_select($component, $value) {
 539    // Build a list of all valid keys expected to be submitted.
 540    $options = _webform_select_options($component, TRUE);
 541  
 542    $return = NULL;
 543    if (is_array($value)) {
 544      $return = array();
 545      foreach ($value as $key => $option_value) {
 546        // Handle options that are specified options.
 547        if ($option_value !== '' && isset($options[$option_value])) {
 548          // Checkboxes submit a value of FALSE when unchecked. A checkbox with
 549          // a value of '0' is valid, so we can't use empty() here.
 550          if ($option_value === FALSE && !$component['extra']['aslist'] && $component['extra']['multiple']) {
 551            unset($value[$option_value]);
 552          }
 553          else {
 554            $return[] = $option_value;
 555          }
 556        }
 557        // Handle options that are added through the "other" field. Specifically
 558        // exclude the "select_or_other" value, which is added by the select list.
 559        elseif ($component['extra']['other_option'] && module_exists('select_or_other') && $option_value != 'select_or_other') {
 560          $return[] = $option_value;
 561        }
 562      }
 563    }
 564    elseif (is_string($value)) {
 565      $return = $value;
 566    }
 567  
 568    return $return;
 569  }
 570  
 571  /**
 572   * Format the text output for this component.
 573   */
 574  function theme_webform_display_select($element) {
 575    $component = $element['#webform_component'];
 576  
 577    // Flatten the list of options so we can get values easily. These options
 578    // may be translated by hook_webform_display_component_alter().
 579    $options = array();
 580    foreach ($element['#options'] as $key => $value) {
 581      if (is_array($value)) {
 582        foreach ($value as $subkey => $subvalue) {
 583          $options[$subkey] = $subvalue;
 584        }
 585      }
 586      else {
 587        $options[$key] = $value;
 588      }
 589    }
 590  
 591    $items = array();
 592    if ($component['extra']['multiple']) {
 593      foreach ((array) $element['#value'] as $option_value) {
 594        if ($option_value !== '') {
 595          // Administer provided values.
 596          if (isset($options[$option_value])) {
 597            $items[] = $element['#format'] == 'html' ? _webform_filter_xss($options[$option_value]) : $options[$option_value];
 598          }
 599          // User-specified in the "other" field.
 600          else {
 601            $items[] = $element['#format'] == 'html' ? check_plain($option_value) : $option_value;
 602          }
 603        }
 604      }
 605    }
 606    else {
 607      if (isset($element['#value'][0]) && $element['#value'][0] !== '') {
 608        // Administer provided values.
 609        if (isset($options[$element['#value'][0]])) {
 610          $items[] = $element['#format'] == 'html' ? _webform_filter_xss($options[$element['#value'][0]]) : $options[$element['#value'][0]];
 611        }
 612        // User-specified in the "other" field.
 613        else {
 614          $items[] = $element['#format'] == 'html' ? check_plain($element['#value'][0]) : $element['#value'][0];
 615        }
 616      }
 617    }
 618  
 619    if ($element['#format'] == 'html') {
 620      $output = count($items) > 1 ? theme('item_list', $items) : (isset($items[0]) ? $items[0] : ' ');
 621    }
 622    else {
 623      if (count($items) > 1) {
 624        foreach ($items as $key => $item) {
 625          $items[$key] = ' - ' . $item;
 626        }
 627        $output = implode("\n", $items);
 628      }
 629      else {
 630        $output = isset($items[0]) ? $items[0] : ' ';
 631      }
 632    }
 633  
 634    return $output;
 635  }
 636  
 637  /**
 638   * Implements _webform_analysis_component().
 639   */
 640  function _webform_analysis_select($component, $sids = array(), $single = FALSE) {
 641    $options = _webform_select_options($component, TRUE);
 642    $show_other_results = $single;
 643  
 644    $sid_placeholders = count($sids) ? array_fill(0, count($sids), "'%s'") : array();
 645    $sid_filter = count($sids) ? " AND sid IN (" . implode(",", $sid_placeholders) . ")" : "";
 646  
 647    $option_operator = $show_other_results ? 'NOT IN' : 'IN';
 648    $placeholders = count($options) ? array_fill(0, count($options), "'%s'") : array();
 649    $query = 'SELECT data, count(data) as datacount ' .
 650      ' FROM {webform_submitted_data} ' .
 651      ' WHERE nid = %d ' .
 652      ' AND cid = %d ' .
 653      " AND data != ''" . $sid_filter .
 654      ($placeholders ? ' AND data ' . $option_operator . ' (' . implode(',', $placeholders) . ')' : '') .
 655      ' GROUP BY data ';
 656  
 657    $count_query = 'SELECT count(*) as datacount ' .
 658      ' FROM {webform_submitted_data} ' .
 659      ' WHERE nid = %d ' .
 660      ' AND cid = %d ' .
 661      " AND data != ''" . $sid_filter;
 662  
 663    $result = db_query($query, array_merge(array($component['nid'], $component['cid']), $sids, array_keys($options)));
 664    $rows = array();
 665    $normal_count = 0;
 666    while ($data = db_fetch_array($result)) {
 667      $display_option = $single ? $data['data'] : $options[$data['data']];
 668      $rows[$data['data']] = array(_webform_filter_xss($display_option), $data['datacount']);
 669      $normal_count += $data['datacount'];
 670    }
 671  
 672    if (!$show_other_results) {
 673      // Order the results according to the normal options array.
 674      $ordered_rows = array();
 675      foreach (array_intersect_key($options, $rows) as $key => $label) {
 676        $ordered_rows[] = $rows[$key];
 677      }
 678  
 679      // Add a row for any unknown or user-entered values.
 680      if ($component['extra']['other_option']) {
 681        $full_count = db_result(db_query($count_query, array_merge(array($component['nid'], $component['cid']), $sids)));
 682        $other_count = $full_count - $normal_count;
 683        $display_option = !empty($component['extra']['other_text']) ? check_plain($component['extra']['other_text']) : t('Other...');
 684        $other_text = $other_count ? $other_count . ' (' . l(t('view'), 'node/' . $component['nid'] . '/webform-results/analysis/' . $component['cid']) . ')' : $other_count;
 685        $ordered_rows[] = array($display_option, $other_text);
 686      }
 687  
 688      $rows = $ordered_rows;
 689    }
 690  
 691    return $rows;
 692  }
 693  
 694  /**
 695   * Implements _webform_table_component().
 696   */
 697  function _webform_table_select($component, $value) {
 698    // Convert submitted 'safe' values to un-edited, original form.
 699    $options = _webform_select_options($component, TRUE);
 700  
 701    $value = (array) $value;
 702    $items = array();
 703    // Set the value as a single string.
 704    foreach ($value as $option_value) {
 705      if ($option_value !== '') {
 706        if (isset($options[$option_value])) {
 707          $items[] = _webform_filter_xss($options[$option_value]);
 708        }
 709        else {
 710          $items[] = check_plain($option_value);
 711        }
 712      }
 713    }
 714  
 715    return implode('<br />', $items);
 716  }
 717  
 718  /**
 719   * Implements _webform_csv_headers_component().
 720   */
 721  function _webform_csv_headers_select($component, $export_options) {
 722    $headers = array(
 723      0 => array(),
 724      1 => array(),
 725      2 => array(),
 726    );
 727  
 728    if ($component['extra']['multiple'] && $export_options['select_format'] == 'separate') {
 729      $headers[0][] = '';
 730      $headers[1][] = $component['name'];
 731      $items = _webform_select_options($component, TRUE, FALSE);
 732      if ($component['extra']['other_option']) {
 733        $other_label = !empty($component['extra']['other_text']) ? check_plain($component['extra']['other_text']) : t('Other...');
 734        $items[$other_label] = $other_label;
 735      }
 736      $count = 0;
 737      foreach ($items as $key => $item) {
 738        // Empty column per sub-field in main header.
 739        if ($count != 0) {
 740          $headers[0][] = '';
 741          $headers[1][] = '';
 742        }
 743        if ($export_options['select_keys']) {
 744          $headers[2][] = $key;
 745        }
 746        else {
 747          $headers[2][] = $item;
 748        }
 749        $count++;
 750      }
 751    }
 752    else {
 753      $headers[0][] = '';
 754      $headers[1][] = '';
 755      $headers[2][] = $component['name'];
 756    }
 757    return $headers;
 758  }
 759  
 760  /**
 761   * Implements _webform_csv_data_component().
 762   */
 763  function _webform_csv_data_select($component, $export_options, $value) {
 764    $options = _webform_select_options($component, TRUE, FALSE);
 765    $return = array();
 766  
 767    if ($component['extra']['multiple']) {
 768      foreach ($options as $key => $item) {
 769        $index = array_search($key, (array) $value);
 770        if ($index !== FALSE) {
 771          if ($export_options['select_format'] == 'separate') {
 772            $return[] = 'X';
 773          }
 774          else {
 775            $return[] = $export_options['select_keys'] ? $key : $item;
 776          }
 777          unset($value[$index]);
 778        }
 779        elseif ($export_options['select_format'] == 'separate') {
 780          $return[] = '';
 781        }
 782      }
 783  
 784      // Any remaining items in the $value array will be user-added options.
 785      if ($component['extra']['other_option']) {
 786        $return[] = count($value) ? implode(',', $value) : '';
 787      }
 788    }
 789    else {
 790      $key = $value[0];
 791      if ($export_options['select_keys']) {
 792        $return = $key;
 793      }
 794      else {
 795        $return = isset($options[$key]) ? $options[$key] : $key;
 796      }
 797    }
 798  
 799    if ($component['extra']['multiple'] && $export_options['select_format'] == 'compact') {
 800      $return = implode(',', (array) $return);
 801    }
 802  
 803    return $return;
 804  }
 805  
 806  /**
 807   * Menu callback; Return a predefined list of select options as JSON.
 808   */
 809  function webform_select_options_ajax($source_name = '') {
 810    $info = _webform_select_options_info();
 811  
 812    $component['extra']['options_source'] = $source_name;
 813    if ($source_name && isset($info[$source_name])) {
 814      $options = _webform_select_options_to_text(_webform_select_options($component, !$component['extra']['aslist'], FALSE));
 815    }
 816    else {
 817      $options = '';
 818    }
 819  
 820    $return = array(
 821      'elementId' => module_exists('options_element') ? 'edit-items-options-options-field-widget' : 'edit-extra-items',
 822      'options' => $options,
 823    );
 824  
 825    drupal_json($return);
 826  }
 827  
 828  /**
 829   * Generate a list of options for a select list.
 830   */
 831  function _webform_select_options($component, $flat = FALSE, $filter = TRUE) {
 832    if ($component['extra']['options_source']) {
 833      $options = _webform_select_options_callback($component['extra']['options_source'], $component, $flat, $filter);
 834    }
 835    else {
 836      $options = _webform_select_options_from_text($component['extra']['items'], $flat, $filter);
 837    }
 838  
 839    return isset($options) ? $options : array();
 840  }
 841  
 842  /**
 843   * Load Webform select option info from 3rd party modules.
 844   */
 845  function _webform_select_options_info() {
 846    static $info;
 847    if (!isset($info)) {
 848      $info = array();
 849  
 850      foreach (module_implements('webform_select_options_info') as $module) {
 851        $additions = module_invoke($module, 'webform_select_options_info');
 852        foreach ($additions as $key => $addition) {
 853          $additions[$key]['module'] = $module;
 854        }
 855        $info = array_merge($info, $additions);
 856      }
 857      drupal_alter('webform_select_options_info', $info);
 858    }
 859    return $info;
 860  }
 861  
 862  /**
 863   * Execute a select option callback.
 864   *
 865   * @param $name
 866   *   The name of the options group.
 867   * @param $component
 868   *   The full Webform component.
 869   * @param $flat
 870   *   Whether the information returned should exclude any nested groups.
 871   * @param $filter
 872   *   Whether information returned should be sanitized. Defaults to TRUE.
 873   */
 874  function _webform_select_options_callback($name, $component, $flat = FALSE, $filter = TRUE) {
 875    $info = _webform_select_options_info();
 876  
 877    // Include any necessary files.
 878    if (isset($info[$name]['file'])) {
 879      $pathinfo = pathinfo($info[$name]['file']);
 880      $path = ($pathinfo['dirname'] ? $pathinfo['dirname'] . '/' : '') . basename($pathinfo['basename'], '.' . $pathinfo['extension']);
 881      module_load_include($pathinfo['extension'], $info[$name]['module'], $path);
 882    }
 883  
 884    // Execute the callback function.
 885    if (isset($info[$name]['options callback']) && function_exists($info[$name]['options callback'])) {
 886      $function = $info[$name]['options callback'];
 887  
 888      $arguments = array();
 889      if (isset($info[$name]['options arguments'])) {
 890        $arguments = $info[$name]['options arguments'];
 891      }
 892  
 893      return $function($component, $flat, $filter, $arguments);
 894    }
 895  }
 896  
 897  /**
 898   * Utility function to split user-entered values from new-line seperated
 899   * text into an array of options.
 900   *
 901   * @param $text
 902   *   Text to be converted into a select option array.
 903   * @param $flat
 904   *   Optional. If specified, return the option array and exclude any optgroups.
 905   * @param $filter
 906   *   Optional. Whether or not to filter returned values.
 907   */
 908  function _webform_select_options_from_text($text, $flat = FALSE, $filter = TRUE) {
 909    static $option_cache = array();
 910  
 911    // Keep each processed option block in an array indexed by the MD5 hash of
 912    // the option text and the value of the $flat variable.
 913    $md5 = md5($text);
 914  
 915    // Check if this option block has been previously processed.
 916    if (!isset($option_cache[$flat][$md5])) {
 917      $options = array();
 918      $rows = array_filter(explode("\n", trim($text)));
 919      $group = NULL;
 920      foreach ($rows as $option) {
 921        $option = trim($option);
 922        /**
 923         * If the Key of the option is within < >, treat as an optgroup
 924         *
 925         * <Group 1>
 926         *   creates an optgroup with the label "Group 1"
 927         *
 928         * <>
 929         *   Unsets the current group, allowing items to be inserted at the root element.
 930         */
 931        if (preg_match('/^\<([^>]*)\>$/', $option, $matches)) {
 932          if (empty($matches[1])) {
 933            unset($group);
 934          }
 935          elseif (!$flat) {
 936            $group = $filter ? _webform_filter_values($matches[1], NULL, NULL, NULL, FALSE) : $matches[1];
 937          }
 938        }
 939        elseif (preg_match('/^([^|]+)\|(.*)$/', $option, $matches)) {
 940          $key = $filter ? _webform_filter_values($matches[1], NULL, NULL, NULL, FALSE) : $matches[1];
 941          $value = $filter ? _webform_filter_values($matches[2], NULL, NULL, NULL, FALSE) : $matches[2];
 942          isset($group) ? $options[$group][$key] = $value : $options[$key] = $value;
 943        }
 944        else {
 945          $filtered_option = $filter ? _webform_filter_values($option, NULL, NULL, NULL, FALSE) : $option;
 946          isset($group) ? $options[$group][$filtered_option] = $filtered_option : $options[$filtered_option] = $filtered_option;
 947        }
 948      }
 949  
 950      $option_cache[$flat][$md5] = $options;
 951    }
 952  
 953    // Return our options from the option_cache array.
 954    return $option_cache[$flat][$md5];
 955  }
 956  
 957  /**
 958   * Convert an array of options into text.
 959   */
 960  function _webform_select_options_to_text($options) {
 961    $output = '';
 962    $previous_key = FALSE;
 963  
 964    foreach ($options as $key => $value) {
 965      // Convert groups.
 966      if (is_array($value)) {
 967        $output .= '<' . $key . '>' . "\n";
 968        foreach ($value as $subkey => $subvalue) {
 969          $output .= $subkey . '|' . $subvalue . "\n";
 970        }
 971        $previous_key = $key;
 972      }
 973      // Typical key|value pairs.
 974      else {
 975        // Exit out of any groups.
 976        if (isset($options[$previous_key]) && is_array($options[$previous_key])) {
 977          $output .= "<>\n";
 978        }
 979        // Skip empty rows.
 980        if ($options[$key] !== '') {
 981          $output .= $key . '|' . $value . "\n";
 982        }
 983        $previous_key = $key;
 984      }
 985    }
 986  
 987    return $output;
 988  }
 989  
 990  /**
 991   * Utility function to shuffle an array while preserving key-value pairs.
 992   */
 993  function _webform_shuffle_options(&$array) {
 994    // First shuffle the array keys, then use them as the basis for ordering
 995    // the options.
 996    $aux = array();
 997    $keys = array_keys($array);
 998    shuffle($keys);
 999    foreach ($keys as $key) {
1000      $aux[$key] = $array[$key];
1001    }
1002    $array = $aux;
1003  }


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