diff --git a/conditional_fields.module b/conditional_fields.module index 58a8374..f44b6bd 100644 --- a/conditional_fields.module +++ b/conditional_fields.module @@ -200,6 +200,19 @@ function conditional_fields_forms() { } /** + * Implements hook_js_alter(). + * + * Overrides core states API with a patched version that allows multiple + * conditions and OR/XOR logic. + */ +function conditional_fields_js_alter(&$javascript) { + // Since Drupal 7.14, states.js includes the OR/XOR patch. + if (isset($javascript['misc/states.js']) && version_compare(VERSION, '7.14', '<')) { + $javascript['misc/states.js']['data'] = drupal_get_path('module', 'conditional_fields') . '/js/states.js'; + } +} + +/** * Implements hook_element_info_alter(). * Adds an #after_build function to all form elements. */ @@ -245,6 +258,9 @@ function conditional_fields_element_after_build($element, &$form_state) { $entity_type = $field['#entity_type']; $bundle = $field['#bundle']; } + elseif (isset($field[0]) && isset($field[0]['#entity_type']) && $bundle = _conditional_fields_find_parent_bundle($field)) { + $entity_type = $field[0]['#entity_type']; + } elseif (isset($form['#entity_type'], $form['#bundle'])) { $entity_type = $form['#entity_type']; $bundle = $form['#bundle']; @@ -259,11 +275,13 @@ function conditional_fields_element_after_build($element, &$form_state) { return $element; } - // Attach dependent. + $field_parents_key = conditional_fields_flatten_array($field['#field_parents']); + if (isset($dependencies['dependents'][$field['#field_name']])) { + // Attach dependent. foreach ($dependencies['dependents'][$field['#field_name']] as $id => $dependency) { - if (!isset($form['#conditional_fields'][$field['#field_name']]['dependees'][$id])) { - conditional_fields_attach_dependency($form, array('#field_name' => $dependency['dependee']), $field, $dependency['options'], $id); + if (!isset($form['#conditional_fields'][$field_parents_key][$field['#field_name']]['dependees'][$id])) { + conditional_fields_attach_dependency($form, array('#field_name' => $dependency['dependee']), $field, $dependency['options'], $field_parents_key, $id); } } } @@ -274,8 +292,8 @@ function conditional_fields_element_after_build($element, &$form_state) { // define per-element sets of dependency values. if (isset($dependencies['dependees'][$field['#field_name']])) { foreach ($dependencies['dependees'][$field['#field_name']] as $id => $dependency) { - if (!isset($form['#conditional_fields'][$field['#field_name']]['dependents'][$id])) { - conditional_fields_attach_dependency($form, $field, array('#field_name' => $dependency['dependent']), $dependency['options'], $id); + if (!isset($form['#conditional_fields'][$field_parents_key][$field['#field_name']]['dependents'][$id])) { ++ conditional_fields_attach_dependency($form, $field, array('#field_name' => $dependency['dependent']), $dependency['options'], $field_parents_key, $id); } } } @@ -353,7 +371,7 @@ function conditional_fields_element_after_build($element, &$form_state) { * Note that you don't need to manually set all these options, since default * settings are always provided. */ -function conditional_fields_attach_dependency(&$form, $dependee, $dependent, $options, $id = 0) { +function conditional_fields_attach_dependency(&$form, $dependee, $dependent, $options, $field_parents_key, $id = 0) { $options += conditional_fields_dependency_default_options(); // The absence of the $id parameter identifies a custom dependency. @@ -384,8 +402,8 @@ function conditional_fields_attach_dependency(&$form, $dependee, $dependent, $op // Use the #parents property of the dependee instead of #field_parents since // we will need access to the full structure of the widget. if (isset($dependee['#parents'])) { - $form['#conditional_fields'][$dependee['#field_name']]['parents'] = $dependee['#parents']; - $form['#conditional_fields'][$dependee['#field_name']]['dependents'][$id] = array( + $form['#conditional_fields'][$field_parents_key][$dependee['#field_name']]['parents'] = $dependee['#parents']; + $form['#conditional_fields'][$field_parents_key][$dependee['#field_name']]['dependents'][$id] = array( 'dependent' => $dependent['#field_name'], 'options' => $options, ); @@ -399,8 +417,8 @@ function conditional_fields_attach_dependency(&$form, $dependee, $dependent, $op $dependent_parents = $dependent['#parents']; } if (isset($dependent_parents)) { - $form['#conditional_fields'][$dependent['#field_name']]['field_parents'] = $dependent_parents; - $form['#conditional_fields'][$dependent['#field_name']]['dependees'][$id] = array( + $form['#conditional_fields'][$field_parents_key][$dependent['#field_name']]['field_parents'] = $dependent_parents; + $form['#conditional_fields'][$field_parents_key][$dependent['#field_name']]['dependees'][$id] = array( 'dependee' => $dependee['#field_name'], 'options' => $options, ); @@ -428,13 +446,13 @@ function conditional_fields_form_after_build($form, &$form_state) { $state_handlers = conditional_fields_states_handlers(); // Cycle all dependents. - foreach ($form['#conditional_fields'] as $dependent => $dependent_info) { + foreach ($form['#conditional_fields'] as $parent_dependent_key => $parent_dependent_info) { + foreach ($parent_dependent_info as $dependent => $dependent_info) { $states = array(); if (empty($dependent_info['dependees'])) { continue; } - $dependent_location = array_merge($dependent_info['field_parents'], array($dependent)); $dependent_form_field = drupal_array_get_nested_value($form, $dependent_location); @@ -442,11 +460,11 @@ function conditional_fields_form_after_build($form, &$form_state) { foreach ($dependent_info['dependees'] as $dependency) { $dependee = $dependency['dependee']; - if (empty($form['#conditional_fields'][$dependee])) { + if (empty($form['#conditional_fields'][$parent_dependent_key][$dependee])) { continue; } - $dependee_info = $form['#conditional_fields'][$dependee]; + $dependee_info = $form['#conditional_fields'][$parent_dependent_key][$dependee]; $dependee_form_field = drupal_array_get_nested_value($form, $dependee_info['parents']); $options = $dependency['options']; @@ -535,10 +553,10 @@ function conditional_fields_form_after_build($form, &$form_state) { $handler($dependee_form_field, $dependee_form_state, $options, $state); } } + } // Add validation callback to element. _conditional_fields_element_add_property($dependent_form_field, '#element_validate', 'conditional_fields_dependent_validate', 'append'); - } // Add the $state into the correct logic group in $states. foreach ($state as $key => $constraints) { @@ -626,6 +644,7 @@ function conditional_fields_form_after_build($form, &$form_state) { $has_states = TRUE; } + } if (empty($has_states)) { return $form; @@ -1174,15 +1193,8 @@ function conditional_fields_field_behaviors($op, $options) { } /** - * Builds a jQuery selector from the name or id attribute of a field. - * - * @todo support custom selectors with %lang and %key placeholders. - * - * @param $field - * The field form element. - * - * @return - * A jQuery selector string. + * Builds a jQuery selector from the name attribute of a field. + * TODO: support custom selectors with %lang and %key placeholders. */ function conditional_fields_field_selector($field) { if (isset($field['#attributes']['name'])) { @@ -1960,7 +1972,7 @@ function conditional_fields_module_implements_alter(&$implementations, $hook) { // callback last to ensure that conditional_fields_form_validate runs after // all other validation routines. // The Features hook must be processed when the fields actually exist. - if ($hook == 'element_info_alter' || $hook == 'features_api') { + if ($hook == 'element_info_alter' || $hook = 'features_api') { $group = $implementations['conditional_fields']; unset($implementations['conditional_fields']); $implementations['conditional_fields'] = $group; @@ -1982,3 +1994,31 @@ function conditional_fields_features_api() { ), ); } + +// need to return immediate parent as the bundle +function _conditional_fields_find_parent_bundle($field) { + $field_parents = array_reverse($field[0]['#field_parents']); + foreach ($field_parents as $parent) { + if (!is_numeric($parent) && $parent != 'und') { + return $parent; + } + } + + return false; +} + +/** + * Flatten a one-dimensional array. + */ +function conditional_fields_flatten_array($array, $delta = 0, $separator = ':') { + $array_string = 'root'.$separator; + $array_count = count($array); + foreach ($array as $array_value) { + $array_string .= $array_value; + if ($delta != $array_count) { + $array_string .= $separator; + } + $delta++; + } + return $array_string; +}