# This patch file was generated by NetBeans IDE
# It uses platform neutral UTF-8 encoding and \n newlines.
--- a/conditional_fields.module
+++ b/conditional_fields.module
@@ -211,6 +211,64 @@
}
/**
+ * 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)
+
+ // If this isn't for a form (i.e., being called because the entity is being viewed), just return.
+ if ( !isset($element['#form_state']) || empty($element['#form_state']) ) {
+ return;
+ }
+ // $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
@@ -218,7 +276,7 @@
* - 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) {
// Some fields are wrapped in containers before processing. Wrapped data must
// take precedence over the container, because Entity Translation and
// possibly other modules add #field_name to the container as well.
@@ -239,6 +297,10 @@
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,
@@ -264,19 +326,32 @@
// 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
// just the first encountered. This bottom-up approach would allow us to
// 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);
}
}
@@ -402,6 +477,7 @@
}
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,
@@ -426,6 +502,10 @@
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();
@@ -436,6 +516,12 @@
if (empty($dependent_info['dependees'])) {
continue;
}
+ if ( isset($dependent_info['options']['group']) && $dependent_info['options']['group'] ) {
+ $is_group = TRUE;
+ }
+ else {
+ $is_group = FALSE;
+ }
$dependent_location = array_merge($dependent_info['field_parents'], array($dependent));
$dependent_form_field = drupal_array_get_nested_value($form, $dependent_location);
@@ -448,8 +534,14 @@
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, 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.
@@ -672,7 +764,12 @@
* @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)) {
@@ -693,7 +790,7 @@
// 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
@@ -722,7 +819,9 @@
*/
function conditional_fields_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);
}
@@ -846,11 +945,10 @@
$evaluated_dependents = array();
foreach ($dependencies['dependents'] as $dependent => $dependency) {
- if (empty($build[$dependent]['#access'])) {
- continue;
- }
-
foreach ($dependency as $dependency_options) {
+ if (empty($build[$dependent]['#access']) && $dependency_options['type'] != 'group') {
+ continue 2;
+ }
$dependee = $dependency_options['dependee'];
$options = $dependency_options['options'];
@@ -923,7 +1021,12 @@
case CONDITIONAL_FIELDS_FIELD_VIEW_EVALUATE:
// Hide the dependent if it is not triggered.
if (!$is_triggered) {
- $build[$dependent]['#access'] = FALSE;
+ if ( $dependency_options['type'] == 'group' ) {
+ conditional_fields_hide_group($build, $dependent);
+ }
+ else {
+ $build[$dependent]['#access'] = FALSE;
+ }
}
break;
@@ -934,7 +1037,12 @@
case CONDITIONAL_FIELDS_FIELD_VIEW_HIDE_UNTRIGGERED_ORPHAN:
// Hide the dependent if the dependee is not viewable and the dependency is not triggered.
if ($is_orphan && !$is_triggered) {
- $build[$dependent]['#access'] = FALSE;
+ if ( $dependency_options['type'] == 'group' ) {
+ conditional_fields_hide_group($build, $dependent);
+ }
+ else {
+ $build[$dependent]['#access'] = FALSE;
+ }
}
break;
@@ -976,6 +1084,49 @@
}
/**
+ * Helper function to hide a group.
+ * @param array $build The build array.
+ * @param string $dependent The group name to be hidden;
+ */
+function conditional_fields_hide_group(&$build, $dependent) {
+ $all_children = _conditional_fields_get_all_progeny($build['#group_children'], $build['#groups'], $dependent);
+ foreach ( $all_children as $child => $parent ) {
+ if ( in_array($child, $build['#groups']) ) {
+ unset($build['#groups'][$child]);
+ }
+ else {
+ $build[$child]['#access'] = FALSE;
+ }
+ unset($build['#group_children'][$child]);
+ if ( isset($build['#groups'][$parent]) ) {
+ unset($build['#groups'][$parent]);
+ }
+ }
+ unset($build['#groups'][$dependent]);
+ unset($build['#fieldgroups'][$dependent]);
+}
+
+/**
+ * Helper function to recursively find all progeny of a group to deal with nested groups.
+ * @param array $elements Array of all fields and groups that are in a group.
+ * @param array $groups Array of all groups.
+ * @param string $parent The parent group for which its children are being sought.
+ * @return array Children as keys, and the parent group as the values.
+ */
+function _conditional_fields_get_all_progeny($elements, $groups, $parent) {
+ $children = array();
+ foreach ( $elements as $child => $group ) {
+ if ( in_array($child, $groups) ) {
+ $children += _conditional_fields_get_all_progeny($elements, $groups, $child);
+ }
+ if ( $group == $parent ) {
+ $children[$child] = $group;
+ }
+ }
+ return $children;
+}
+
+/**
* Evaluates an array with 'AND', 'OR' and 'XOR' groupings,
* each containing a list of boolean values.
*/
@@ -1274,7 +1425,7 @@
*
* The result can be filtered by providing an entity type and a bundle name.
*/
-function conditional_fields_load_dependencies($entity_type = NULL, $bundle = NULL) {
+function conditional_fields_load_dependencies($entity_type = NULL, $bundle = NULL, $group_view_mode = 'form') {
// Use the advanced drupal_static() pattern.
static $dependencies;
if (!isset($dependencies)) {
@@ -1291,49 +1442,62 @@
}
$default_options = conditional_fields_dependency_default_options();
+ // Get dependent fields and groupd separately, as which will be 'joined' depends
+ // on the options['group'] value.
+ $dependent_fields_select = db_select('field_config_instance', 'fci')
+ ->fields('fci', array('id', 'field_name'));
+ $dependent_groups_select = db_select('field_group', 'fg')
+ ->fields('fg', array('id', 'group_name'))
+ ->condition('mode', $group_view_mode);
+
$select = db_select('conditional_fields', 'cf')
- ->fields('cf', array('id', 'options'))
- ->orderBy('cf.dependent');
+ ->fields('cf', array('id', 'dependent', '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');
if ($entity_type) {
- $select->condition(
- db_and()
- ->condition('fci_dependee.entity_type', $entity_type)
- ->condition('fci_dependent.entity_type', $entity_type)
- );
+ $dependent_fields_select->condition('fci.entity_type', $entity_type);
+ $dependent_groups_select->condition('fg.entity_type', $entity_type);
+ $select->condition('fci_dependee.entity_type', $entity_type);
}
if ($bundle) {
- $select->condition(
- db_and()
- ->condition('fci_dependee.bundle', $bundle)
- ->condition('fci_dependent.bundle', $bundle)
- );
+ $dependent_fields_select->condition('fci.bundle', $bundle);
+ $dependent_groups_select->condition('fg.bundle', $bundle);
+ $select->condition('fci_dependee.bundle', $bundle);
}
$result = $select->execute();
+ $dependent_fields = $dependent_fields_select->execute()->fetchAllAssoc('id');
+ $dependent_groups = $dependent_groups_select->execute()->fetchAllAssoc('id');
foreach ($result as $dependency) {
$result_entity_type = $entity_type ? $entity_type : $dependency->entity_type;
$result_bundle = $bundle ? $bundle : $dependency->bundle;
$options = unserialize($dependency->options);
+ if ( isset($options['group']) && $options['group'] ) {
+ $dependency->dependent = $dependent_groups[$dependency->dependent]->group_name;
+ $dependency->type = 'group';
+ }
+ else {
+ $dependency->dependent =$dependent_fields[$dependency->dependent]->field_name;
+ $dependency->type = 'field';
+ }
$options += $default_options;
$dependencies[$result_entity_type][$result_bundle]['dependents'][$dependency->dependent][$dependency->id] = array(
'dependee' => $dependency->dependee,
'options' => $options,
+ 'type' => $dependency->type,
);
$dependencies[$result_entity_type][$result_bundle]['dependees'][$dependency->dependee][$dependency->id] = array(
'dependent' => $dependency->dependent,
'options' => $options,
+ 'type' => $dependency->type,
);
}
}
--- a/includes/conditional_fields.admin.inc
+++ b/includes/conditional_fields.admin.inc
@@ -106,6 +106,15 @@
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 @@
// 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 @@
$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,15 @@
asort($fields);
+ // Build list of available groups. Preface each id with a 'g' to avoid collission
+ // with field ids, and to identify it as a group.
+ $fieldgroups = array();
+ foreach ($groups as $group_name => $group) {
+ $fieldgroups['g' . $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 +254,7 @@
'#title' => t('Dependent'),
'#title_display' => 'invisible',
'#description' => t('Dependent'),
- '#options' => $fields,
+ '#options' => $fields + $fieldgroups,
'#prefix' => '' . t('Add new dependency') . '
',
),
'dependee' => array(
@@ -302,6 +320,12 @@
'state' => $form_state['values']['state'],
'condition' => $form_state['values']['condition']
);
+ // Determine if the dependent is a group, and adjust the ID and save the group
+ // indicator in options.
+ if ( substr($form_state['values']['dependent'], 0, 1) == 'g' ) {
+ $options['group'] = TRUE;
+ $form_state['values']['dependent'] = substr($form_state['values']['dependent'], 1);
+ }
if (!$id = conditional_fields_dependency_insert($form_state['values']['dependee'], $form_state['values']['dependent'], $options)) {
drupal_set_message(t('There was an error while trying to create the dependency.'), 'error');
@@ -800,6 +824,11 @@
}
}
+ // Save the group indicator in options.
+ if ( isset($form['#dependency']['options']['group']) && $form['#dependency']['options']['group'] ) {
+ $dependency['options']['group'] = $form['#dependency']['options']['group'];
+ }
+
conditional_fields_dependency_update($dependency);
drupal_set_message(t('Saved dependency configuration.'));
}
--- a/includes/conditional_fields.features.inc
+++ b/includes/conditional_fields.features.inc
@@ -111,7 +111,21 @@
}
$entity_instances = $instances[$field['entity']][$field['bundle']];
$dependee_id = $entity_instances[$field['dependee']]['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']);
}
}