| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
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 <Group Name>. <> 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |