| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file form_builder.admin.inc 5 * Administrative interface for editing forms. 6 */ 7 8 /** 9 * Main form building interface. Can be used as a menu callback. 10 * 11 * @param $form_type 12 * The type of form being edited. Usually the name of the providing module. 13 * @param $form_id 14 * The unique identifier for the form being edited with the type. 15 */ 16 function form_builder_interface($form_type, $form_id) { 17 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 18 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 19 20 // Set the current form type (used for display of the sidebar block). 21 form_builder_active_form($form_type, $form_id); 22 23 // Load the current state of the form, or create a new cache if needed. 24 $form = form_builder_cache_load($form_type, $form_id); 25 if (!$form) { 26 $form = form_builder_load_form($form_type, $form_id); 27 form_builder_cache_save($form_type, $form_id, $form); 28 } 29 30 $output = ''; 31 $output .= drupal_get_form('form_builder_preview', $form, $form_type, $form_id); 32 $output .= drupal_get_form('form_builder_positions', $form, $form_type, $form_id); 33 34 return $output; 35 } 36 37 /** 38 * Menu callback for adding a field. 39 */ 40 function form_builder_add_page($form_type, $form_id, $element_type) { 41 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 42 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 43 44 $fields = form_builder_get_form_type($form_type); 45 if (isset($fields[$element_type])) { 46 $cache = form_builder_cache_load($form_type, $form_id); 47 $element_id = isset($_REQUEST['element_id']) ? $_REQUEST['element_id'] : 'new_' . time(); 48 $element = $fields[$element_type]['default']; 49 50 // Set the element ID to a hard-coded value if a unique field type. 51 if (isset($fields[$element_type]['unique']) && $fields[$element_type]['unique']) { 52 $element_id = $element_type; 53 } 54 55 $element['#form_builder']['element_id'] = $element_id; 56 $element['#form_builder']['is_new'] = TRUE; 57 $element = form_builder_add_default_properties($element, $form_type, $element_id); 58 59 $element['#weight'] = count(element_children($cache)); 60 61 drupal_alter('form_builder_add_element', $element, $form_type, $form_id); 62 63 // Save any element ID set by the hook_form_builder_add_element_alter(). 64 $element_id = $element['#form_builder']['element_id']; 65 66 form_builder_cache_field_save($form_type, $form_id, $element); 67 68 if (isset($_REQUEST['js'])) { 69 $element = form_builder_cache_field_load($form_type, $form_id, $element_id); 70 $preview_form = form_builder_cache_load($form_type, $form_id); 71 72 $data = array( 73 'formType' => $form_type, 74 'formId' => $form_id, 75 'elementId' => $element_id, 76 'html' => form_builder_field_render($form_type, $form_id, $element_id), 77 'positionForm' => drupal_get_form('form_builder_positions', $preview_form, $form_type, $form_id), 78 ); 79 80 form_builder_json_output($data); 81 exit(); 82 } 83 } 84 85 // Otherwise return to the previous page. 86 drupal_goto(); 87 } 88 89 /** 90 * Menu callback for configuring a field. 91 */ 92 function form_builder_configure_page($form_type, $form_id, $element_id) { 93 $output = drupal_get_form('form_builder_field_configure', $form_type, $form_id, $element_id); 94 95 if (isset($_REQUEST['js'])) { 96 // Return the newly changed field. 97 if (isset($_REQUEST['return'])) { 98 form_builder_field_json($form_type, $form_id, $element_id); 99 } 100 // Display the configuration form for a field. 101 else { 102 $data = array( 103 'formType' => $form_type, 104 'formId' => $form_id, 105 'elementId' => $element_id, 106 'html' => $output, 107 'errors' => form_get_errors(), 108 ); 109 110 form_builder_json_output($data); 111 exit(); 112 } 113 } 114 115 return $output; 116 } 117 118 /** 119 * Menu callback for removing a field. 120 */ 121 function form_builder_remove_page($form_type, $form_id, $element_id) { 122 $output = drupal_get_form('form_builder_field_remove', $form_type, $form_id, $element_id); 123 124 if (isset($_REQUEST['js']) && !isset($_REQUEST['return'])) { 125 // This after build function immediately returns the form as JSON. 126 $data = array( 127 'formType' => $form_type, 128 'formId' => $form_id, 129 'elementId' => $element_id, 130 'html' => $output, 131 ); 132 133 form_builder_json_output($data); 134 exit(); 135 } 136 137 return $output; 138 } 139 140 /** 141 * Render the palette of fields to add to a form. 142 */ 143 function form_builder_field_palette() { 144 $active = form_builder_active_form(); 145 $output = NULL; 146 if (isset($active)) { 147 $fields = form_builder_get_form_type($active['form_type']); 148 $groups = module_invoke_all('form_builder_palette_groups'); 149 // TODO: We shouldn't have to clear the cache here. 150 $form = form_builder_cache_load($active['form_type'], $active['form_id'], NULL, TRUE); 151 $active_fields = form_builder_get_element_ids($form); 152 foreach ($fields as $key => $field) { 153 if ($field['unique'] && in_array($key, $active_fields)) { 154 $fields[$key]['in_use'] = TRUE; 155 } 156 if ($field['addable'] == FALSE) { 157 unset($fields[$key]); 158 } 159 } 160 $output = theme('form_builder_field_palette', $fields, $groups, $active['form_type'], $active['form_id']); 161 } 162 return $output; 163 } 164 165 /** 166 * Form. Given a form array, present it for editing in a preview. 167 */ 168 function form_builder_preview(&$form_state, $form, $form_type, $form_id) { 169 170 // Make modifications to all form elements recursively. 171 $element_ids = form_builder_preview_prepare($form, $form_type, $form_id); 172 173 // Record all the element IDs within the entire form. 174 $form['#form_builder']['element_ids'] = $element_ids; 175 $form['#form_builder']['form_type'] = $form_type; 176 $form['#form_builder']['form_id'] = $form_id; 177 178 // Add a pre_render to the entire form itself. 179 $form['#pre_render'][] = 'form_builder_pre_render_form'; 180 $form['#form_builder_wrappers'] = array('form_builder_wrapper'); 181 $form['#post_render'][] = 'form_builder_wrappers'; 182 183 return $form; 184 } 185 186 /** 187 * Form containing all the current weights and parents of elements. 188 */ 189 function form_builder_positions(&$form_state, $preview_form, $form_type, $form_id) { 190 $form = array( 191 '#tree' => TRUE, 192 '#form_builder' => array( 193 'form_type' => $form_type, 194 'form_id' => $form_id, 195 'form' => $preview_form, 196 ), 197 ); 198 199 form_builder_positions_prepare($form, $preview_form); 200 201 // Drupal MUST have a button to register submissions. 202 // Add a button even though the form is only submitted via AJAX. 203 $form['submit'] = array( 204 '#type' => 'submit', 205 '#value' => t('Update'), 206 ); 207 208 return $form; 209 } 210 211 /** 212 * Recursive helper for form_builder_positions(). Add weight fields. 213 */ 214 function form_builder_positions_prepare(&$form, &$preview_form, $parent_id = FORM_BUILDER_ROOT) { 215 foreach (element_children($preview_form) as $key) { 216 // Keep record of the current parent ID. 217 $previous_parent_id = $parent_id; 218 219 if (isset($preview_form[$key]['#form_builder']['element_id'])) { 220 // Set the parent ID for this element. 221 $preview_form[$key]['#form_builder']['parent_id'] = $parent_id; 222 $element_id = $preview_form[$key]['#form_builder']['element_id']; 223 $parent_id = $element_id; 224 225 $form[$element_id]['weight'] = array( 226 '#type' => 'hidden', 227 '#default_value' => isset($preview_form[$key]['#weight']) ? $preview_form[$key]['#weight'] : 0, 228 '#attributes' => array('class' => 'form-builder-weight form-builder-element-' . $element_id), 229 ); 230 $form[$element_id]['parent'] = array( 231 '#type' => 'hidden', 232 '#default_value' => $preview_form[$key]['#form_builder']['parent_id'], 233 '#attributes' => array('class' => 'form-builder-parent form-builder-element-' . $element_id), 234 ); 235 } 236 237 form_builder_positions_prepare($form, $preview_form[$key], $parent_id); 238 $parent_id = $previous_parent_id; 239 } 240 } 241 242 /** 243 * Submit handler for the form_builder_positions form. 244 */ 245 function form_builder_positions_submit(&$form, &$form_state) { 246 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 247 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 248 249 $form_type = $form['#form_builder']['form_type']; 250 $form_id = $form['#form_builder']['form_id']; 251 $preview_form = $form['#form_builder']['form']; 252 253 foreach (element_children($form) as $element_id) { 254 // Skip items without weight value (like the form token, build_id, etc). 255 if (!isset($form[$element_id]['weight'])) { 256 continue; 257 } 258 259 // Check for changed weights or parents. 260 $element = form_builder_get_element($preview_form, $element_id); 261 $element['#weight'] = $form_state['values'][$element_id]['weight']; 262 $element['#form_builder']['parent_id'] = $form_state['values'][$element_id]['parent']; 263 form_builder_set_element($preview_form, $element); 264 } 265 266 // Save all the changes made. 267 form_builder_cache_save($form_type, $form_id, $preview_form); 268 } 269 270 /** 271 * Output the wrapper around the form_builder preview. 272 * 273 * Optionally outputs the field palette if it is not already available as a 274 * block. 275 */ 276 function theme_form_builder_wrapper($element, $content) { 277 $output = ''; 278 $output .= '<div id="form-builder-wrapper" class="' . ($element['#show_palette'] ? 'with-palette' : 'no-palette') . '">'; 279 if ($element['#show_palette']) { 280 $output .= '<div id="form-builder-fields">'; 281 $output .= '<div class="block">'; 282 $output .= form_builder_field_palette(); 283 $output .= '</div>'; 284 $output .= '</div>'; 285 } 286 $output .= '<div id="form-builder">'; 287 if (isset($element['#title'])) { 288 $output .= '<h3 class="form-builder-title">' . $element['#title'] . '</h3>'; 289 } 290 291 // Add the contents of the form and close the wrappers. 292 $output .= $content; 293 $output .= '</div>'; // #form-builder. 294 $output .= '</div>'; // #form-builder-wrapper. 295 return $output; 296 } 297 298 /** 299 * Output the wrapper around a form_builder element with configure/remove links. 300 */ 301 function theme_form_builder_element_wrapper($element, $content) { 302 303 $removable = isset($element['#form_builder']['removable']) ? $element['#form_builder']['removable'] : TRUE; 304 $configurable = isset($element['#form_builder']['configurable']) ? $element['#form_builder']['configurable'] : TRUE; 305 306 $output = ''; 307 $output .= '<div class="form-builder-wrapper">'; 308 if ($removable || $configurable) { 309 $output .= '<div class="form-builder-title-bar">'; 310 $output .= '<span class="form-builder-links">'; 311 if ($removable) { 312 $output .= l('<span class="remove">'. t('Remove') .'</span>', 'admin/build/form-builder/remove/' . $element['#form_builder']['form_type'] . '/' . $element['#form_builder']['form_id'] . '/' . $element['#form_builder']['element_id'], array('html' => TRUE, 'attributes' => array('class' => 'remove', 'title' => t('Remove')), 'query' => drupal_get_destination())); 313 } 314 if ($removable && $configurable) { 315 $output .= ' '; 316 } 317 if ($configurable) { 318 $output .= l('<span class="configure">'. t('Configure') .'</span>', 'admin/build/form-builder/configure/' . $element['#form_builder']['form_type'] . '/' . $element['#form_builder']['form_id'] . '/' . $element['#form_builder']['element_id'], array('html' => TRUE, 'attributes' => array('class' => 'configure', 'title' => t('Configure')), 'query' => drupal_get_destination())); 319 } 320 $output .= '</span>'; 321 $output .= '</div>'; 322 } 323 $output .= '<div class="form-builder-element form-builder-element-' . $element['#type'] . '" id="form-builder-element-' . $element['#form_builder']['element_id'] . '">'; 324 // TODO: Overlay image: good idea or bad idea? Prevents any interaction with 325 // form elements in the preview. 326 //$output .= theme('image', drupal_get_path('module', 'form_builder') .'/images/blank.gif', '', '', array('width' => '1', 'height' => '1', 'class' => 'form-builder-disable')); 327 328 $output .= $content; 329 330 $output .= '</div></div>'; 331 332 return $output; 333 } 334 335 /** 336 * Placeholder for an entirely empty form before any fields are added. 337 */ 338 function theme_form_builder_empty_form() { 339 $output = ''; 340 $output .= '<div class="form-builder-empty-form form-builder-empty-placeholder">'; 341 $output .= '<span>' . t('Drag a field from the palette to add it to this form.') . '</span>'; 342 $output .= '</div>'; 343 return $output; 344 } 345 346 /** 347 * Placeholder for empty fieldsets during drag and drop. 348 */ 349 function theme_form_builder_empty_fieldset() { 350 $output = ''; 351 $output .= '<div class="form-builder-wrapper form-builder-empty-placeholder">'; 352 $output .= '<span>' . t('This fieldset is empty. Drag a form element into it.') . '</span>'; 353 $output .= '</div>'; 354 return $output; 355 } 356 357 /** 358 * Message shown in custom field configure forms when no field is selected. 359 * 360 * Note that this message is not displayed using the default field presentation. 361 * Modules or themes can set a custom field configuration form location by 362 * specifying a Drupal.settings.formBuilder.configureFormSelector value. 363 */ 364 function theme_form_builder_no_field_selected() { 365 $output = ''; 366 $output .= '<div class="field-settings-message">'; 367 $output .= t('No field selected'); 368 $output .= '</div>'; 369 return $output; 370 } 371 372 /** 373 * Message shown in custom field configure forms when a field is loading. 374 * 375 * @see theme_form_builder_no_field_selected(). 376 */ 377 function theme_form_builder_field_loading() { 378 $output = ''; 379 $output .= '<div class="field-settings-message">'; 380 $output .= t('Loading...'); 381 $output .= '</div>'; 382 return $output; 383 } 384 385 /** 386 * Block for adding new fields. 387 * 388 * @param $fields 389 * A list of all fields can be added to the current form type. 390 * @param $groups 391 * A list of groups that fields may be sorted into. Each field is assigned 392 * a 'palette_group' property which corresponds to one of these groups. 393 * @param $form_type 394 * The form type to which these blocks apply. 395 * @param $form_id 396 * The form ID that is being edited. 397 */ 398 function theme_form_builder_field_palette($fields, $groups, $form_type, $form_id) { 399 $output = ''; 400 $lists = array(); 401 foreach ($fields as $field_name => $field) { 402 $class = array('field-' . $field_name, 'form-builder-palette-element'); 403 $style = ''; 404 405 // If a field is unique, add a special class to identify it. 406 if ($field['unique']) { 407 $class[] = 'form-builder-unique'; 408 $class[] = 'form-builder-element-' . $field_name; 409 410 // If already in use, do not display it in the list. 411 if (!empty($field['in_use'])) { 412 $style = 'display: none;'; 413 } 414 } 415 416 $lists[$field['palette_group']]['#weight'] = $groups[$field['palette_group']]['weight']; 417 $lists[$field['palette_group']][] = array( 418 'data' => l($field['title'], 'admin/build/form-builder/add/' . $form_type . '/' . $form_id . '/' . $field_name, array('query' => drupal_get_destination())), 419 'class' => implode(' ', $class), 420 'style' => $style, 421 ); 422 } 423 424 // Sort the lists by weight. 425 uasort($lists, 'element_sort'); 426 427 $output .= '<div id="form-builder-field-palette">'; 428 foreach ($lists as $group => $list) { 429 unset($list['#weight']); 430 $output .= theme('item_list', $list, (count($lists) > 1) ? $groups[$group]['title'] : t('Add a field'), 'ul', array('class' => 'form-builder-fields clear-block')); 431 } 432 $output .= '</div>'; 433 434 return $output; 435 } 436 437 /** 438 * Take a form structure and add a prebuild function to every element. 439 */ 440 function form_builder_pre_render($element) { 441 $element['#form_builder_wrappers'][] = 'form_builder_element_wrapper'; 442 $element['#post_render'][] = 'form_builder_wrappers'; 443 444 if ($element['#form_builder']['element_type'] == 'fieldset') { 445 $element['#attributes']['class'] = isset($element['#attributes']['class']) ? $element['#attributes']['class'] . ' form-builder-fieldset' : 'form-builder-fieldset'; 446 } 447 448 if (isset($element['#type']) && $element['#type'] == 'fieldset' && count(element_children($element)) == 0) { 449 $element['#children'] = theme('form_builder_empty_fieldset'); 450 } 451 452 // Allow modules to make modifications to this element. 453 drupal_alter('form_builder_preview', $element, $element['#form_builder']['form_type'], $element['#form_builder']['form_id']); 454 455 return $element; 456 } 457 458 /** 459 * Pre-render function to alter the form being edited by Form builder. 460 * 461 * This function modifies the form element itself and sets a #title to label the 462 * form preview and an #show_palette property to indicate to the theme wrapper 463 * whether the field palette should be added. 464 */ 465 function form_builder_pre_render_form($form) { 466 global $theme; 467 468 jquery_ui_add(array('ui.draggable', 'ui.droppable', 'ui.sortable')); 469 drupal_add_js('misc/jquery.form.js'); 470 drupal_add_js(drupal_get_path('module', 'form_builder') .'/form_builder.js'); 471 // TODO: This JS file should be loaded dynamically as needed. 472 drupal_add_js(drupal_get_path('module', 'options_element') .'/options_element.js'); 473 drupal_add_js('misc/tabledrag.js'); 474 drupal_add_js('misc/collapse.js'); 475 476 $settings = array( 477 'emptyForm' => theme('form_builder_empty_form'), 478 'emptyFieldset' => theme('form_builder_empty_fieldset'), 479 'noFieldSelected' => theme('form_builder_no_field_selected'), 480 'fieldLoading' => theme('form_builder_field_loading'), 481 ); 482 483 drupal_add_js(array('formBuilder' => $settings), 'setting'); 484 485 drupal_add_css(drupal_get_path('module', 'form_builder') .'/form_builder.css'); 486 drupal_add_css(drupal_get_path('module', 'options_element') .'/options_element.css'); 487 488 // We can't have forms inside of forms, so change this entire form a markup. 489 $form['#type'] = 'markup'; 490 491 // Set a title for the preview if none exists. 492 $form['#title'] = !isset($form['#title']) ? t('Form preview') : $form['#title']; 493 494 // Remove unnecessary FAPI elements. 495 unset($form['form_build_id']); 496 unset($form['form_token']); 497 unset($form['form_builder_preview']); 498 499 // Check if the Form Builder block is enabled. 500 // Otherwise make our own columns. 501 if (!isset($form['#show_palette'])) { 502 if (module_exists('block')) { 503 $form['#show_palette'] = !db_result(db_query("SELECT status FROM {blocks} WHERE module = 'form_builder' AND theme = '%s'", $theme)); 504 } 505 else { 506 $form['#show_palette'] = TRUE; 507 } 508 } 509 510 if ($theme == 'garland' || $theme == 'minnelli') { 511 drupal_add_css(drupal_get_path('module', 'form_builder') .'/form_builder.garland.css', 'theme'); 512 } 513 514 return $form; 515 } 516 517 function form_builder_after_build($element) { 518 $element['#attributes']['readonly'] = 'readonly'; 519 foreach (element_children($element) as $key) { 520 $element[$key] = form_builder_after_build($element[$key]); 521 } 522 523 return $element; 524 } 525 526 /** 527 * Before editing a form, modify it slightly to add functionality used in 528 * the preview and disable use of the actual form fields in any way. 529 * 530 * @return 531 * A list of all element_ids currently used within this form. 532 */ 533 function form_builder_preview_prepare(&$form, $form_type, $form_id, $parent_id = FORM_BUILDER_ROOT) { 534 $element_ids = array(); 535 foreach (element_children($form) as $key) { 536 // Keep record of the current parent ID. 537 $previous_parent_id = $parent_id; 538 539 if (isset($form[$key]['#form_builder']['element_id'])) { 540 $element_ids[] = $form[$key]['#form_builder']['element_id']; 541 $form[$key]['#pre_render'][] = 'form_builder_pre_render'; 542 $form[$key]['#form_builder']['form_type'] = $form_type; 543 $form[$key]['#form_builder']['form_id'] = $form_id; 544 $form[$key]['#form_builder']['parent_id'] = $parent_id; 545 $parent_id = $form[$key]['#form_builder']['element_id']; 546 } 547 548 // Search within this element for further form elements. 549 $additional_ids = form_builder_preview_prepare($form[$key], $form_type, $form_id, $parent_id); 550 $element_ids = array_merge($element_ids, $additional_ids); 551 $parent_id = $previous_parent_id; 552 } 553 554 return $element_ids; 555 } 556 557 /** 558 * Form for editing a field. 559 */ 560 function form_builder_field_configure($form_state, $form_type, $form_id, $element_id) { 561 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 562 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 563 $element = form_builder_cache_field_load($form_type, $form_id, $element_id); 564 565 // Assemble a form made up of all the configurable properties that this type 566 // of form supports. 567 $form = array(); 568 foreach (form_builder_get_element_properties($form_type, $element['#form_builder']['element_type']) as $property => $property_settings) { 569 if (isset($property_settings['form']) && function_exists($property_settings['form'])) { 570 $function = $property_settings['form']; 571 // Set a default value on the property to avoid notices. 572 $element['#' . $property] = isset($element['#' . $property]) ? $element['#' . $property] : NULL; 573 $form = array_merge($form, $function($form_state, $form_type, $element, $property)); 574 } 575 } 576 577 $form['#form_type'] = $form_type; 578 $form['#form_id'] = $form_id; 579 $form['#element_id'] = $element_id; 580 $form['#element'] = $element; 581 $form['#pre_render'][] = 'form_builder_field_configure_pre_render'; 582 583 $form['form_builder_submit'] = array( 584 '#type' => 'submit', 585 '#value' => t('Save configuration'), 586 '#access' => !isset($_REQUEST['js']), 587 '#weight' => 100, 588 ); 589 590 return $form; 591 } 592 593 /** 594 * Pre-render function for the field configuration form. 595 */ 596 function form_builder_field_configure_pre_render($form) { 597 // Group the properties into separate fieldsets (converted to tabs later). 598 599 $groups = module_invoke_all('form_builder_property_groups', $form['#form_type']); 600 601 foreach (element_children($form) as $key) { 602 // If no group is specified, put the element into the default group. 603 if (!isset($form[$key]['#form_builder']['property_group']) || !isset($groups[$form[$key]['#form_builder']['property_group']])) { 604 if (!isset($form[$key]['#type']) || (isset($form[$key]['#type']) && !in_array($form[$key]['#type'], array('hidden', 'button', 'submit', 'value', 'token')))) { 605 $form[$key]['#form_builder']['property_group'] = 'default'; 606 } 607 } 608 609 if (isset($form[$key]['#form_builder']['property_group'])) { 610 $group = $form[$key]['#form_builder']['property_group']; 611 612 // We add "_property_group" to the field key to prevent conflicts of 613 // property names and group names. 614 if (!isset($form[$group . '_property_group'])) { 615 $form[$group . '_property_group'] = array( 616 '#type' => 'fieldset', 617 '#title' => $groups[$group]['title'], 618 '#weight' => $groups[$group]['weight'], 619 '#collapsible' => isset($groups[$group]['collapsible']) ? $groups[$group]['collapsible'] : FALSE, 620 '#collapsed' => isset($groups[$group]['collapsed']) ? $groups[$group]['collapsed'] : FALSE, 621 '#attributes' => array('class' => 'form-builder-group'), 622 ); 623 } 624 625 $form[$group .'_property_group'][$key] = $form[$key]; 626 unset($form[$key]); 627 } 628 } 629 630 return $form; 631 } 632 633 function form_builder_field_configure_submit(&$form, &$form_state) { 634 $form_type = $form['#form_type']; 635 $form_id = $form['#form_id']; 636 $element_id = $form['#element_id']; 637 $element = $form['#element']; 638 639 // Allow each element to do any necessary submission handling. 640 foreach (form_builder_get_element_properties($form_type, $element['#form_builder']['element_type']) as $property => $property_settings) { 641 if (isset($property_settings['submit'])) { 642 foreach ($property_settings['submit'] as $function) { 643 if (function_exists($function)) { 644 $function($form, $form_state); 645 } 646 } 647 } 648 } 649 650 // Allow the element to be updated in a hard-coded fashion by altering the 651 // $form['#element'] item. Using this approach skips the property check. 652 $element = $form['#element']; 653 654 // Update the field according to the settings in $form_state['values']. 655 $saveable = form_builder_get_saveable_properties($form_type, $element); 656 foreach ($form_state['values'] as $property => $value) { 657 if (in_array($property, $saveable)) { 658 // Remove empty properties entirely. 659 if ($value === '' || is_null($value)) { 660 unset($element['#'. $property]); 661 } 662 else { 663 $element['#'. $property] = $value; 664 } 665 } 666 } 667 668 // Update the form builder cache. 669 form_builder_cache_field_save($form_type, $form_id, $element); 670 671 if (isset($_GET['js'])) { 672 // Option A: Use the destination variable to do a drupal_goto(). Allows 673 // other submit handlers to add on extra functionality. 674 // The destination variable takes precedence over $form_state['redirect']. 675 //$_REQUEST['destination'] = 'admin/build/form-builder/json/' . $form_type . '/' . $form_id . '/' . $element_id; 676 677 // Option B: Immediately print the JSON and exit. Faster and requires only 678 // one HTTP request instead of two. Other submit handlers must be before 679 // this on. 680 form_builder_field_json($form_type, $form_id, $element_id); 681 } 682 } 683 684 /** 685 * Form for removing a field. 686 */ 687 function form_builder_field_remove($form_state, $form_type, $form_id, $element_id) { 688 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 689 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 690 $element = form_builder_cache_field_load($form_type, $form_id, $element_id); 691 692 $form = array(); 693 $form['#form_type'] = $form_type; 694 $form['#form_id'] = $form_id; 695 $form['#element_id'] = $element_id; 696 697 $question = t('Remove the field %title?', array('%title' => $element['#title'])); 698 $path = isset($_GET['destination']) ? $_GET['destination'] : NULL; 699 $description = t('Remove the field %title? This field will not be permanently removed until the form configuration is saved.', array('%title' => isset($element['#title']) ? $element['#title'] : $element['#form_builder']['element_id'])); 700 $yes = t('Remove'); 701 702 return confirm_form($form, $question, $path, $description, $yes); 703 } 704 705 function form_builder_field_remove_submit(&$form, &$form_state) { 706 $form_type = $form['#form_type']; 707 $form_id = $form['#form_id']; 708 $element_id = $form['#element_id']; 709 710 // Update the form builder cache. 711 form_builder_cache_field_delete($form_type, $form_id, $element_id); 712 713 if (isset($_GET['js'])) { 714 // See form_builder_field_configure_submit() for comparison between using 715 // redirect and immediately printing the JSON. 716 //$form_state['redirect'] = 'admin/build/form-builder/json/' . $form_type . '/' . $form_id . '/' . $element_id; 717 form_builder_field_json($form_type, $form_id, $element_id); 718 } 719 } 720 721 /** 722 * Render a single field independent of other settings. 723 */ 724 function form_builder_field_render($form_type, $form_id, $element_id, $wrapper = FALSE) { 725 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 726 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 727 728 // Load the current state of the form and prepare it for rendering. 729 $form = form_builder_cache_load($form_type, $form_id); 730 $form_state = array('submitted' => FALSE); 731 $form = drupal_retrieve_form('form_builder_preview', $form_state, $form, $form_type, $form_id); 732 drupal_prepare_form('form_builder_preview', $form, $form_state); 733 $form['#post'] = array(); 734 $form = form_builder('form_builder_preview', $form, $form_state); 735 736 // Get only the element wanted and render it. 737 $element = form_builder_get_element($form, $element_id); 738 739 if ($wrapper) { 740 $element['#form_builder_wrappers'][] = 'form_builder_element_wrapper'; 741 $element['#post_render'][] = 'form_builder_wrappers'; 742 } 743 744 return drupal_render($element); 745 } 746 747 /** 748 * Menu callback to display a field as a JSON string. 749 */ 750 function form_builder_field_json($form_type, $form_id, $element_id) { 751 module_load_include('inc', 'form_builder', 'includes/form_builder.api'); 752 module_load_include('inc', 'form_builder', 'includes/form_builder.cache'); 753 $element = form_builder_cache_field_load($form_type, $form_id, $element_id); 754 755 $data = array( 756 'formType' => $form_type, 757 'formId' => $form_id, 758 'elementId' => $element_id, 759 'html' => !empty($element) ? form_builder_field_render($form_type, $form_id, $element_id) : '', 760 'errors' => form_get_errors(), 761 ); 762 763 form_builder_json_output($data); 764 exit(); 765 } 766 767 /** 768 * Generic function for outputing Form Builder JSON return responses. 769 * 770 * Adds status messages, settings, and timestamp to a form builder JSON response 771 * and outputs it. 772 */ 773 function form_builder_json_output($data) { 774 if (!isset($data['messages'])) { 775 $data['messages'] = theme('status_messages'); 776 } 777 if (!isset($data['settings'])) { 778 $scripts = drupal_add_js(); 779 if (!empty($scripts['setting'])) { 780 $data['settings'] = call_user_func_array('array_merge_recursive', $scripts['setting']); 781 } 782 } 783 if (!isset($data['time'])) { 784 $data['time'] = time(); 785 } 786 drupal_json($data); 787 }
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 |