diff --git a/conditional_fields.module b/conditional_fields.module index 34503a6..532959a 100644 --- a/conditional_fields.module +++ b/conditional_fields.module @@ -210,6 +210,60 @@ function conditional_fields_element_info_alter(&$types) { } /** + * Implements hook_field_group_build_pre_render_alter() + * Have to wait for the group elements to be created - unfortunately this is after after_build + */ +function conditional_fields_field_group_build_pre_render_alter(&$element) { + // Have to re-process conditional fields over again for newly created + // fieldgroup elements (and existing elements moved to fieldgroup children) + + // $form_state is added to $form['#form_state'] via conditional_fields_form_after_build() + $form_state = $element['#form_state']; + $form_state['complete form'] = $element; + $form = &$form_state['complete form']; + // Loop through fieldgroups and fieldgroup children + $new_dependents = array(); + foreach ($form['#fieldgroups'] as $group_name => $group) { + // Call element_after_build for fieldgroup children + foreach($group->children as $field_name) { + $parents = array_merge($group->array_parents, array($field_name)); + $field_element = &drupal_array_get_nested_value($form, $parents); + conditional_fields_element_after_build($field_element, $form_state, TRUE); + } + // Call element_after_build for fieldgroup element + $group_element = &drupal_array_get_nested_value($form, $group->array_parents); + $group_element['#field_name'] = $group_name; + // Make sure group element has an ID to select in drupal_process_states + $group_element['#id'] = isset($group_element['#id']) ? $group_element['#id'] : $group_name; + // Need to wrap markup type with a div with the ID, unless ID already present in prefix or markup + if (isset($group_element['#type']) && $group_element['#type'] == 'markup') { + if ((!isset($group_element['#prefix']) || !strstr($group_element['#prefix'], '#' . $group_element['#id'])) + && (!isset($group_element['#markup']) || !strstr($group_element['#markup'], '#' . $group_element['#id'])) + ) { + $group_element['#prefix'] = '
' . (isset($group_element['#prefix']) ? $group_element['#prefix'] : ''); + $group_element['#suffix'] = (isset($group_element['#suffix']) ? $group_element['#suffix'] : '') . '
'; + } + } + conditional_fields_element_after_build($group_element, $form_state, TRUE); + if (isset($form['#conditional_fields'][$group_name], $form['#conditional_fields'][$group_name]['dependees'])) { + $new_dependents[$group_name] = &$group_element; + } + } + + // Call form_after_build + $form = conditional_fields_form_after_build($form, $form_state, TRUE); + + // Call validation for group dependents + foreach ($new_dependents as $dependent_name => &$dependent) { + conditional_fields_dependent_validate($dependent, $form_state, $form); + } + // Call form validation + conditional_fields_form_validate($form, $form_state); + + $element = $form; +} + +/** * Processes form elements with dependencies. * * Just adds a #conditional_fields property to the form with the needed @@ -217,7 +271,7 @@ function conditional_fields_element_info_alter(&$types) { * - The fields #parents property. * - Field dependencies data. */ -function conditional_fields_element_after_build($element, &$form_state) { +function conditional_fields_element_after_build($element, &$form_state, $reprocess = FALSE) { // Ensure that the element is a field. if (isset($element['#field_name'])) { $field = $element; @@ -237,6 +291,10 @@ function conditional_fields_element_after_build($element, &$form_state) { return $element; } + // Get fieldgroup name if field belongs to one + $group_name = isset($form['#group_children']) && isset($form['#group_children'][$field['#field_name']]) ? + $form['#group_children'][$field['#field_name']] : NULL; + // Some fields do not have entity type and bundle properties. In this case we // try to use the properties from the form. This is not an optimal solution, // since in case of fields in entities within entities they might not correspond, @@ -262,11 +320,24 @@ function conditional_fields_element_after_build($element, &$form_state) { // Attach dependent. if (isset($dependencies['dependents'][$field['#field_name']])) { foreach ($dependencies['dependents'][$field['#field_name']] as $id => $dependency) { - if (!isset($form['#conditional_fields'][$field['#field_name']]['dependees'][$id])) { + if ($reprocess || !isset($form['#conditional_fields'][$field['#field_name']]['dependees'][$id])) { conditional_fields_attach_dependency($form, array('#field_name' => $dependency['dependee']), $field, $dependency['options'], $id); } } } + // Also attach dependent if element is a (first) child in a dependent fieldgroup + // and the dependency state isn't 'visible' or 'hidden' + // (this is done on the fieldgroup element itself) + if ($group_name && isset($dependencies['dependents'][$group_name]) ) { + $group_dependent = $dependencies['dependents'][$group_name]; + if (!in_array($group_dependent[key($group_dependent)]['options']['state'], array('visible', 'hidden'))) { + foreach ($group_dependent as $id => $dependency) { + if ($reprocess || !isset($form['#conditional_fields'][$field['#field_name']]['dependees'][$id])) { + conditional_fields_attach_dependency($form, array('#field_name' => $dependency['dependee']), $field, $dependency['options'], $id); + } + } + } + } // Attach dependee. // TODO: collect information about every element of the dependee widget, not @@ -274,7 +345,7 @@ 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])) { + if ($reprocess || !isset($form['#conditional_fields'][$field['#field_name']]['dependents'][$id])) { conditional_fields_attach_dependency($form, $field, array('#field_name' => $dependency['dependent']), $dependency['options'], $id); } } @@ -400,6 +471,7 @@ function conditional_fields_attach_dependency(&$form, $dependee, $dependent, $op } if (isset($dependent_parents)) { $form['#conditional_fields'][$dependent['#field_name']]['field_parents'] = $dependent_parents; + $form['#conditional_fields'][$dependent['#field_name']]['array_parents'] = $dependent['#array_parents']; $form['#conditional_fields'][$dependent['#field_name']]['dependees'][$id] = array( 'dependee' => $dependee['#field_name'], 'options' => $options, @@ -424,6 +496,10 @@ function conditional_fields_form_after_build($form, &$form_state) { return $form; } + // Set $form_state in $form so hook_field_group_build_pre_render_alter has access to it + // when it is invoked after after_build (when fieldgroup elements are attached to form) + $form['#form_state'] =& $form_state; + $effects = array(); $state_handlers = conditional_fields_states_handlers(); @@ -445,9 +521,15 @@ function conditional_fields_form_after_build($form, &$form_state) { if (empty($form['#conditional_fields'][$dependee])) { continue; } + // Skip this dependency if it's a group element and state is not visible/hidden + // (dependencies for other states are attached to fieldgroup children elements) + if (in_array($dependent_form_field['#field_name'], array_keys($form['#fieldgroups'])) && !in_array($dependency['options']['state'], array('visible', 'hidden'))) { + continue; + } $dependee_info = $form['#conditional_fields'][$dependee]; - $dependee_form_field = drupal_array_get_nested_value($form, $dependee_info['parents']); + $dependee_location = $dependee_info['parents']; + $dependee_form_field = drupal_array_get_nested_value($form, $dependee_location); $options = $dependency['options']; // Load field edit behaviors. @@ -669,7 +751,12 @@ function conditional_fields_form_after_build($form, &$form_state) { * @see conditional_fields_form_validate() */ function conditional_fields_dependent_validate($element, &$form_state, $form) { - $dependent = $element[$element['#language']]; + if (isset($element['#language'], $element[$element['#language']])) { + $dependent = $element[$element['#language']]; + } + else { + $dependent = $element; + } // Check if this field's dependencies were triggered. if (conditional_fields_evaluate_dependencies($dependent, $form, $form_state)) { @@ -691,7 +778,7 @@ function conditional_fields_dependent_validate($element, &$form_state, $form) { // conditional_fields_form_validate(). $errors = form_get_errors(); - if ($errors) { + if ($errors && isset($dependent['#parents'])) { // group elements have no #parents key $error_key = implode('][', $dependent['#parents']); foreach ($errors as $name => $error) { // An error triggered by this field might have been set on a descendant @@ -720,7 +807,9 @@ function conditional_fields_dependent_validate($element, &$form_state, $form) { */ function conditional_fields_form_field_get_values($element, $form_state) { // Fall back to #parents to support custom dependencies. - $parents = !empty($element['#field_parents']) ? $element['#field_parents'] : $element['#parents']; + // $parents = !empty($element['#field_parents']) ? $element['#field_parents'] : $element['#parents']; + // Should this be the other way around? Isn't #parents the parent keys in $form_state['values']? + $parents = isset($element['#parents']) ? $element['#parents'] : $element['#field_parents']; return drupal_array_get_nested_value($form_state['values'], $parents); } @@ -1269,21 +1358,34 @@ function conditional_fields_load_dependencies($entity_type = NULL, $bundle = NUL $default_options = conditional_fields_dependency_default_options(); $select = db_select('conditional_fields', 'cf') - ->fields('cf', array('id', 'options')) - ->orderBy('cf.dependent'); + ->fields('cf', array('id', 'options')); $fci_depende = $select->join('field_config_instance', 'fci_dependee', 'cf.dependee = fci_dependee.id'); - $fci_dependent = $select->join('field_config_instance', 'fci_dependent', 'cf.dependent = fci_dependent.id'); $select->addField($fci_depende, 'field_name', 'dependee'); - $select->addField($fci_dependent, 'field_name', 'dependent'); $select->addField($fci_depende, 'entity_type'); $select->addField($fci_depende, 'bundle'); + // Clone query now to allow a union with fieldgroup results + $select_group = clone $select; + + // Join with field_config_instance + $fci_dependent = $select->join('field_config_instance', 'fci_dependent', 'cf.dependent = fci_dependent.id'); + $select->addField($fci_dependent, 'field_name', 'dependent'); + + // Join with field_group + $group_dependent = $select_group->join('field_group', 'fg_dependent', 'cf.dependent = fg_dependent.id'); + $select_group->addField($group_dependent, 'group_name', 'dependent'); + if ($entity_type) { $select->condition( db_and() ->condition('fci_dependee.entity_type', $entity_type) ->condition('fci_dependent.entity_type', $entity_type) ); + $select_group->condition( + db_and() + ->condition('fci_dependee.entity_type', $entity_type) + ->condition('fg_dependent.entity_type', $entity_type) + ); } if ($bundle) { @@ -1292,7 +1394,15 @@ function conditional_fields_load_dependencies($entity_type = NULL, $bundle = NUL ->condition('fci_dependee.bundle', $bundle) ->condition('fci_dependent.bundle', $bundle) ); + $select_group->condition( + db_and() + ->condition('fci_dependee.bundle', $bundle) + ->condition('fg_dependent.bundle', $bundle) + ); } + // Union of results + //$select->orderBy('cf.dependent'); + $select->union($select_group, 'UNION'); $result = $select->execute(); diff --git a/includes/conditional_fields.admin.inc b/includes/conditional_fields.admin.inc index bf790f0..308b475 100644 --- a/includes/conditional_fields.admin.inc +++ b/includes/conditional_fields.admin.inc @@ -106,6 +106,15 @@ function conditional_fields_dependencies_overview_page($bundle_name = NULL, $ent function conditional_fields_dependency_add_form($form, &$form_state, $entity_type, $bundle_name) { $form = array(); $instances = field_info_instances($entity_type, $bundle_name); + // Get field groups on entity + $groups = field_group_info_groups($entity_type, $bundle_name); + $groups = isset($groups['form']) ? $groups['form'] : array(); + foreach ($groups as $group_name => $group) { + $groups[$group_name] = (array)$group; + } + // New merged array of fields & groups for dependents + // Dependees should only be fields ($instances) + $instances_groups = $instances + $groups; if (count($instances) < 2) { $form['no_fields'] = array( @@ -163,7 +172,7 @@ function conditional_fields_dependency_add_form($form, &$form_state, $entity_typ // first row they will appear grouped. if ($first_row == TRUE) { $form['table']['dependencies'][$id]['dependent'] = array( - '#markup' => check_plain($instances[$dependent]['label']) . ' (' . $dependent . ')', + '#markup' => check_plain($instances_groups[$dependent]['label']) . ' (' . $dependent . ')', '#rowspan' => $dependee_count, ); @@ -191,7 +200,7 @@ function conditional_fields_dependency_add_form($form, &$form_state, $entity_typ $row['description']['#colspan'] = 2; } - $row['description']['#markup'] = conditional_fields_dependency_description($instances[$dependency['dependee']]['label'], $instances[$dependent]['label'], $dependency['options']); + $row['description']['#markup'] = conditional_fields_dependency_description($instances[$dependency['dependee']]['label'], $instances_groups[$dependent]['label'], $dependency['options']); $row['edit'] = array( '#type' => 'link', @@ -221,6 +230,14 @@ function conditional_fields_dependency_add_form($form, &$form_state, $entity_typ asort($fields); + // Build list of available groups. + $fieldgroups = array(); + foreach ($groups as $group_name => $group) { + $fieldgroups[$group['id']] = check_plain($group['label'] . ' (' . $group['group_name'] . ')'); + } + + asort($fieldgroups); + // Build list of states. $states = array_map('drupal_strtolower', conditional_fields_states()); @@ -236,7 +253,7 @@ function conditional_fields_dependency_add_form($form, &$form_state, $entity_typ '#title' => t('Dependent'), '#title_display' => 'invisible', '#description' => t('Dependent'), - '#options' => $fields, + '#options' => $fields + $fieldgroups, '#prefix' => '
' . t('Add new dependency') . '
', ), 'dependee' => array( diff --git a/includes/conditional_fields.features.inc b/includes/conditional_fields.features.inc index b998ce3..ec7f6fa 100644 --- a/includes/conditional_fields.features.inc +++ b/includes/conditional_fields.features.inc @@ -110,7 +110,21 @@ function conditional_fields_features_rebuild($module) { } $entity_instances = $instances[$field['entity']][$field['bundle']]; $dependee_id = $entity_instances[$field['dependee']]['id']; - $dependent_id = $entity_instances[$field['dependent']]['id']; + $dependent_id = 0; + if (array_key_exists($field['dependent'], $entity_instances)) { + $dependent_id = $entity_instances[$field['dependent']]['id']; + } + elseif (module_exists('field_group')) { + $entity_groups = field_group_info_groups($field['entity'], $field['bundle'], 'form'); + if (array_key_exists($field['dependent'], $entity_groups)) { + if (!$entity_groups[$field['dependent']]->id) { + field_group_group_save($entity_groups[$field['dependent']]); + $identifier = $entity_groups[$field['dependent']]->identifier; + $entity_groups[$field['dependent']] = field_group_load_field_group_by_identifier($identifier); + } + $dependent_id = $entity_groups[$field['dependent']]->id; + } + } conditional_fields_dependency_insert($dependee_id, $dependent_id, $field['options']); } }