function form_hierarchical_select_process in Hierarchical Select 7.3
Hierarchical select form element type #process callback.
1 string reference to 'form_hierarchical_select_process'
- hierarchical_select_element_info in ./
hierarchical_select.module - Implements hook_element_info().
File
- ./
hierarchical_select.module, line 753 - This module defines the "hierarchical_select" form element, which is a greatly enhanced way for letting the user select items in a hierarchy.
Code
function form_hierarchical_select_process($element, &$form_state, $complete_form) {
if (arg(0) != 'hierarchical_select_ajax') {
// Get unique identifier using parents of the field.
$cid = isset($element['#parents']) ? implode("-", $element['#parents']) : implode("-", $element['#field_parents']);
// Verify if hsid is present.
$elhsid = drupal_array_get_nested_value($element, array(
'#value',
'hsid',
));
if (!isset($elhsid)) {
// Retrieve previous element from form_state.
$cached = drupal_array_get_nested_value($form_state, array(
'storage',
'hs',
'hs_fields',
$cid,
));
}
if (empty($cached)) {
$docache = TRUE;
}
else {
// Switch current element with the "cached".
return $cached;
}
}
// Determine the HSID.
$hsid = _hs_process_determine_hsid($element, $form_state);
// Config.
$config = $element['#config'];
// Attach CSS/JS files and JS settings.
$element = _hs_process_attach_css_js($element, $hsid, $form_state, $complete_form);
// Developer mode diagnostics, return immediately in case of a config error.
if (!_hs_process_developer_mode_log_diagnostics($element)) {
return $element;
}
// Calculate the selections in both the hierarchical select and the dropbox,
// we need these before we can render anything.
$hs_selection = $db_selection = array();
list($hs_selection, $db_selection) = _hierarchical_select_process_calculate_selections($element, $hsid, $form_state);
// Developer mode logging: log selections.
_hs_process_developer_mode_log_selections($config, $hs_selection, $db_selection);
// Dynamically disable the dropbox when an exclusive item has been selected.
// When this happens, the configuration is dynamically altered. Hence, we
// need to update $config.
list($element, $hs_selection, $db_selection) = _hs_process_exclusive_lineages($element, $hs_selection, $db_selection);
$config = $element['#config'];
// Generate the $hierarchy and $dropbox objects using the selections that
// were just calculated.
$dropbox = !$config['dropbox']['status'] ? FALSE : _hierarchical_select_dropbox_generate($config, $db_selection);
$hierarchy = _hierarchical_select_hierarchy_generate($config, $hs_selection, $element['#required'], $dropbox);
// Developer mode logging: log $hierarchy and $dropbox objects.
_hs_process_developer_mode_log_hierarchy_and_dropbox($config, $hierarchy, $dropbox);
// Finally, calculate the return value of this hierarchical_select form
// element. This will be set in _hierarchical_select_validate(). (If we'd
// set it now, it would be overridden again.)
$element['#return_value'] = _hierarchical_select_process_calculate_return_value($hierarchy, $config['dropbox']['status'] ? $dropbox : FALSE, $config['module'], $config['params'], $config['save_lineage']);
if (!is_array($element['#return_value'])) {
$element['#return_value'] = array(
$element['#return_value'],
);
}
// Add a validate callback, which will:
// - validate that the dropbox limit was not exceeded.
// - set the return value of this form element.
// Also make sure it is the *first* validate callback.
$element['#element_validate'] = isset($element['#element_validate']) ? $element['#element_validate'] : array();
$element['#element_validate'] = array_merge(array(
'_hierarchical_select_validate',
), $element['#element_validate']);
// Ensure the form is cached, for AJAX to work.
$form_state['cache'] = TRUE;
//
// Rendering.
//
// Ensure that #tree is enabled!
$element['#tree'] = TRUE;
// Store the HSID in a hidden form element; when an AJAX callback comes in,
// we'll know which HS was updated.
$element['hsid'] = array(
'#type' => 'hidden',
'#value' => $hsid,
);
// If render_flat_select is enabled, render a flat select.
if ($config['render_flat_select']) {
$element['flat_select'] = _hs_process_render_flat_select($hierarchy, $dropbox, $config);
// See https://www.drupal.org/node/994820
if (empty($element['flat_select']['#options'])) {
unset($element['flat_select']);
}
}
// Render the hierarchical select.
$element['hierarchical_select'] = array(
'#theme' => 'hierarchical_select_selects_container',
);
$size = isset($element['#size']) ? $element['#size'] : 0;
$element['hierarchical_select']['selects'] = _hs_process_render_hs_selects($hsid, $hierarchy, $size);
// When the special "create_new_item" value is passed in a level, replace
// that level with an inline modal form to create a new item, and hide all
// subsequent selects.
list($element, $creating_new_item) = _hs_process_render_create_new_item($element, $hierarchy);
// Render the dropbox, if enabled.
// Automatically hides the "Add" button when creating a new item.
// Automatically disables HS' selects when reaching the dropbox limit.
// Stores the currently selected lineages of the dropbox in storage.
list($element, $form_state) = _hs_process_render_dropbox($element, $hsid, $creating_new_item, $dropbox, $form_state);
// Render the HTML that allows for graceful degradation.
$element = _hs_process_render_nojs($element, $config);
// Ensure the render order is correct.
$element['hierarchical_select']['#weight'] = 0;
$element['dropbox_limit_warning']['#weight'] = 1;
$element['dropbox']['#weight'] = 2;
$element['nojs']['#weight'] = 3;
// If the form item is marked as disabled, disable all child form items as
// well.
if (isset($element['#disabled']) && $element['#disabled']) {
_hierarchical_select_mark_as_disabled($element);
}
// This prevents values from in $form_state['input'] to be used instead of
// the generated default values (#default_value).
// For example: $element['hierarchical_select']['selects']['0']['#default_value']
// is set to 'label_0' after an "Add" operation. When $form_state['input']
// is NOT erased, the corresponding value in $form_state['input'] will be
// used instead of the default value that was set. This would result in
// undesired behavior.
// This, however, must not be called on node preview, becuase in that case
// the node will be rebuilt and we need the values inside $form_state['input']
// to recreate the edited form properly.
// @TODO: If the form is rebuilt by some other action than a node preview, we
// might lose data again, we should see if there's any way to prevent this from
// happening by setting this value after the form has been flagged to be rebuilt,
// but as far as I checked, there's not.
// Another option might be to rework the need of this function to prevent
// the undesired behaviors of not having it with some other logic that would
// work as well if the form is rebuilt.
if (empty($docache)) {
if (!isset($form_state['triggering_element']) || $form_state['triggering_element']['#value'] != t('Preview') && $form_state['triggering_element']['#value'] != t('View changes')) {
if (isset($form_state['input']) && is_array($form_state['input'])) {
drupal_array_set_nested_value($form_state['input'], $element['#array_parents'], array());
}
}
}
else {
// Store new element in cache.
$form_state['storage']['hs']['hs_fields'][$cid] = $element;
}
// Send the collected developer mode logs (by using #attached JS).
$element = _hs_process_developer_mode_send_log_js($element, $hsid);
return $element;
}