You are here

field_group.module in Field Group 8

Same filename and directory in other branches
  1. 8.3 field_group.module
  2. 7.2 field_group.module
  3. 7 field_group.module

Allows administrators to attach custom fields to fieldable types.

File

field_group.module
View source
<?php

/**
 * @file
 * Allows administrators to attach custom fields to fieldable types.
 */
use Drupal\Core\Entity\ContentEntityFormInterface;
use Drupal\Core\Entity\Display\EntityDisplayInterface;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\ConfirmFormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
require_once __DIR__ . '/includes/helpers.inc';

/**
 * Implements hook_theme_registry_alter().
 */
function field_group_theme_registry_alter(&$theme_registry) {

  // Inject field_group_build_entity_groups in all entity theming functions.
  $entity_info = Drupal::entityTypeManager()
    ->getDefinitions();
  $entity_types = array();
  foreach ($entity_info as $entity_type_id => $entity_type) {
    if ($route_name = $entity_type
      ->get('field_ui_base_route')) {
      $entity_types[] = $entity_type_id;
    }
  }
  foreach ($theme_registry as $theme_hook => $info) {
    if (in_array($theme_hook, $entity_types) || !empty($info['base hook']) && in_array($info['base hook'], $entity_types)) {
      $theme_registry[$theme_hook]['preprocess functions'][] = 'field_group_build_entity_groups';
    }
  }

  // ECK does not use the eck as theme function.
  if (isset($theme_registry['eck_entity'])) {
    $theme_registry['eck_entity']['preprocess functions'][] = 'field_group_build_entity_groups';
  }
}

/**
 * Implements hook_theme().
 */
function field_group_theme() {
  return array(
    'horizontal_tabs' => array(
      'render element' => 'element',
      'template' => 'horizontal-tabs',
      'file' => 'templates/theme.inc',
    ),
    'field_group_accordion_item' => array(
      'render element' => 'element',
      'template' => 'field-group-accordion-item',
      'file' => 'templates/theme.inc',
    ),
    'field_group_accordion' => array(
      'render element' => 'element',
      'template' => 'field-group-accordion',
      'file' => 'templates/theme.inc',
    ),
    'field_group_html_element' => array(
      'render element' => 'element',
      'template' => 'field-group-html-element',
      'file' => 'templates/theme.inc',
    ),
  );
}

/**
 * Implements hook_theme_suggestions_alter().
 *
 * @param array $suggestions
 * @param array $variables
 * @param $hook
 */
function field_group_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  switch ($hook) {
    case 'horizontal_tabs':
    case 'field_group_accordion_item':
    case 'field_group_accordion':
    case 'field_group_html_element':
      $element = $variables['element'];
      $name = $element['#group_name'];
      $entity_type = $element['#entity_type'];
      $bundle = $element['#bundle'];
      $wrapper = '';
      if (isset($element['#wrapper_element'])) {
        $wrapper = $element['#wrapper_element'];
        $suggestions[] = $hook . '__' . $wrapper;
      }
      $suggestions[] = $hook . '__' . $entity_type;
      $suggestions[] = $hook . '__' . $bundle;
      $suggestions[] = $hook . '__' . $name;
      if ($wrapper) {
        $suggestions[] = $hook . '__' . $entity_type . '__' . $wrapper;
      }
      $suggestions[] = $hook . '__' . $entity_type . '__' . $bundle;
      $suggestions[] = $hook . '__' . $entity_type . '__' . $name;
      if ($wrapper) {
        $suggestions[] = $hook . '__' . $entity_type . '__' . $bundle . '__' . $wrapper;
      }
      $suggestions[] = $hook . '__' . $entity_type . '__' . $bundle . '__' . $name;
      break;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 * Using hook_form_field_ui_form_display_overview_form_alter.
 */
function field_group_form_entity_form_display_edit_form_alter(&$form, FormStateInterface $form_state) {
  $form_state
    ->loadInclude('field_group', 'inc', 'includes/field_ui');
  field_group_field_ui_display_form_alter($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter().
 * Using hook_form_field_ui_display_overview_form_alter.
 */
function field_group_form_entity_view_display_edit_form_alter(&$form, FormStateInterface $form_state) {
  $form_state
    ->loadInclude('field_group', 'inc', 'includes/field_ui');
  field_group_field_ui_display_form_alter($form, $form_state);
}

/**
 * Implements hook_field_info_max_weight().
 */
function field_group_field_info_max_weight($entity_type, $bundle, $context, $context_mode) {

  // Prevent recursion.
  // @see https://www.drupal.org/project/drupal/issues/2966137
  static $recursion_tracker = [];

  // Track the entity type.
  $key = $entity_type . ':' . $bundle . ':' . $context . ':' . $context_mode;

  // If entity type check was attempted but did not finish, do not continue.
  if (isset($recursion_tracker[$key])) {
    return NULL;
  }

  // Mark this as an attempt at entity type check.
  $recursion_tracker[$key] = TRUE;
  $groups = field_group_info_groups($entity_type, $bundle, $context, $context_mode);

  // Remove the indicator once the entity is successfully checked.
  unset($recursion_tracker[$key]);
  $weights = array();
  foreach ($groups as $group) {
    $weights[] = $group->weight;
  }
  return $weights ? max($weights) : NULL;
}

/**
 * Implements hook_form_alter().
 */
function field_group_form_alter(array &$form, FormStateInterface $form_state) {
  $form_object = $form_state
    ->getFormObject();
  if ($form_object instanceof ContentEntityFormInterface && !$form_object instanceof ConfirmFormInterface) {

    /**
     * @var EntityFormDisplayInterface $form_display
     */
    $storage = $form_state
      ->getStorage();
    if (!empty($storage['form_display'])) {
      $form_display = $storage['form_display'];
      $entity = $form_object
        ->getEntity();
      $context = array(
        'entity_type' => $entity
          ->getEntityTypeId(),
        'bundle' => $entity
          ->bundle(),
        'entity' => $entity,
        'context' => 'form',
        'display_context' => 'form',
        'mode' => $form_display
          ->getMode(),
      );
      field_group_attach_groups($form, $context);
      $form['#pre_render'][] = 'field_group_form_pre_render';
    }
  }
}

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 */
function field_group_inline_entity_form_entity_form_alter(&$entity_form, FormStateInterface $form_state) {

  // Attach the fieldgroups to current entity form.
  $context = [
    'entity_type' => $entity_form['#entity']
      ->getEntityTypeId(),
    'bundle' => $entity_form['#entity']
      ->bundle(),
    'entity' => $entity_form['#entity'],
    'display_context' => 'form',
    'mode' => isset($entity_form['#form_mode']) ? $entity_form['#form_mode'] : 'default',
  ];
  field_group_attach_groups($entity_form, $context);
  $entity_form['#pre_render'][] = 'field_group_form_pre_render';
}

/**
 * Implements hook_entity_view_alter().
 */
function field_group_entity_view_alter(&$build, EntityInterface $entity, EntityDisplayInterface $display) {
  $context = array(
    'entity_type' => $display
      ->getTargetEntityTypeId(),
    'bundle' => $entity
      ->bundle(),
    'entity' => $entity,
    'display_context' => 'view',
    'mode' => $display
      ->getMode(),
  );
  field_group_attach_groups($build, $context);

  // If no theme hook, we have no theme hook to preprocess.
  // Add a prerender.
  if (empty($build['#theme'])) {
    $ds_enabled = false;
    if (Drupal::moduleHandler()
      ->moduleExists('ds')) {

      // Check if DS is enabled for this display.
      if ($display
        ->getThirdPartySetting('ds', 'layout') && !Drupal\ds\Ds::isDisabled()) {
        $ds_enabled = true;
      }
    }

    // If DS is enabled, no pre render is needed (DS adds fieldgroup preprocessing).
    if (!$ds_enabled) {
      $build['#pre_render'][] = 'field_group_entity_view_pre_render';
    }
  }
}

/**
 * Pre render callback for rendering groups.
 * @see field_group_field_attach_form
 * @param $element Form that is being rendered.
 */
function field_group_form_pre_render($element) {
  if (empty($element['#field_group_form_pre_render'])) {
    $element['#field_group_form_pre_render'] = TRUE;
    field_group_build_entity_groups($element, 'form');
  }
  return $element;
}

/**
 * Pre render callback for rendering groups on entities without theme hook.
 * @param $element
 *   Entity being rendered.
 */
function field_group_entity_view_pre_render($element) {
  field_group_build_entity_groups($element, 'view');
  return $element;
}

/**
 * Implements hook_field_group_pre_render().
 *
 * @param Array $element
 *   Group beïng rendered.
 * @param Object $group
 *   The Field group info.
 * @param $rendering_object
 *   The entity / form beïng rendered
 */
function field_group_field_group_pre_render(&$element, &$group, &$rendering_object) {

  // Add all field_group format types to the js settings.
  $element['#attached']['drupalSettings']['field_group'] = array(
    $group->format_type => [
      'mode' => $group->mode,
      'context' => $group->context,
      'settings' => $group->format_settings,
    ],
  );
  $element['#weight'] = $group->weight;

  // Call the pre render function for the format type.
  $manager = Drupal::service('plugin.manager.field_group.formatters');
  $plugin = $manager
    ->getInstance(array(
    'format_type' => $group->format_type,
    'configuration' => array(
      'label' => $group->label,
      'settings' => $group->format_settings,
    ),
    'group' => $group,
  ));
  $plugin
    ->preRender($element, $rendering_object);
}

/**
 * Implements hook_field_group_build_pre_render_alter().
 * @param Array $elements by address.
 */
function field_group_field_group_build_pre_render_alter(&$element) {

  // Someone is doing a node view, in a node view. Reset content.
  if (isset($element['#node']->content) && count($element['#node']->content) > 0) {
    $element['#node']->content = array();
  }
  $display = isset($element['#view_mode']);
  $groups = array_keys($element['#fieldgroups']);

  // Dish the fieldgroups with no fields for non-forms.
  if ($display) {
    field_group_remove_empty_display_groups($element, $groups);
  }
  else {

    // Fix the problem on forms with additional settings.
    field_group_remove_empty_form_groups('form', $element, $groups, $element['#fieldgroups'], $element['#entity_type']);
  }
}

/**
 * Attach groups to the (form) build.
 *
 * @param Array $element
 *   The part of the form.
 *  @param Array $context
 *   The contextual information.
 */
function field_group_attach_groups(&$element, $context) {
  $entity_type = $context['entity_type'];
  $bundle = $context['bundle'];
  $mode = $context['mode'];
  $display_context = $context['display_context'];
  $element['#fieldgroups'] = field_group_info_groups($entity_type, $bundle, $display_context, $mode);

  // Create a lookup array.
  $group_children = array();
  foreach ($element['#fieldgroups'] as $group_name => $group) {
    foreach ($group->children as $child) {
      $group_children[$child] = $group_name;
    }
  }
  $element['#group_children'] = $group_children;
  $element['#entity_type'] = $entity_type;
}

/**
 * Preprocess/ Pre-render callback.
 *
 * @see field_group_form_pre_render()
 * @see field_group_theme_registry_alter
 * @see field_group_fields_nest()
 * @param $vars preprocess vars or form element
 * @param $context The display context (entity type, form or view)
 * @return $element Array with re-arranged fields in groups.
 */
function field_group_build_entity_groups(&$vars, $context = 'view') {
  if ($context == 'form') {
    $element =& $vars;
    $nest_vars = NULL;
  }
  else {
    if (isset($vars['elements'])) {
      $element =& $vars['elements'];
    }
    elseif (isset($vars['content'])) {
      $element =& $vars['content'];
    }
    else {
      if ($context === 'eck_entity') {
        $element =& $vars['entity'];
      }
      else {
        $element =& $vars;
      }
    }
    $nest_vars =& $vars;
  }

  // No groups on the entity.
  if (empty($element['#fieldgroups'])) {
    return $element;
  }

  // Nest the fields in the corresponding field groups.
  field_group_fields_nest($element, $nest_vars, $context);

  // Allow others to alter the pre_rendered build.
  Drupal::moduleHandler()
    ->alter('field_group_build_pre_render', $element);

  // Return the element on forms.
  if ($context == 'form') {
    return $element;
  }

  // No groups on the entity. Prerender removed empty field groups.
  if (empty($element['#fieldgroups'])) {
    return $element;
  }

  // Put groups inside content if we are rendering an entity_view.
  foreach ($element['#fieldgroups'] as $group) {
    if (!empty($element[$group->group_name])) {
      $key = field_group_get_content_element_key($context);
      if (isset($vars[$key])) {
        $vars[$key][$group->group_name] = $element[$group->group_name];
      }
    }
  }
}

/**
 * Recursive function to nest fields in the field groups.
 *
 * This function will take out all the elements in the form and
 * place them in the correct container element, a fieldgroup.
 * The current group element in the loop is passed recursively so we can
 * stash fields and groups in it while we go deeper in the array.
 * @param Array $element
 *   The current element to analyse for grouping.
 * @param Array $vars
 *   Rendering vars from the entity being viewed.
 * @param Array $context
 *   The display context (entity type, form or view).
 */
function field_group_fields_nest(&$element, &$vars = NULL, $context = NULL) {

  // Create all groups and keep a flat list of references to these groups.
  $group_references = array();
  foreach ($element['#fieldgroups'] as $group_name => $group) {

    // Construct own weight, as some fields (for example preprocess fields) don't have weight set.
    $element[$group_name] = array();
    $group_references[$group_name] =& $element[$group_name];
  }

  // Loop through all form children looking for those that are supposed to be
  // in groups, and insert placeholder element for the new group field in the
  // correct location within the form structure.
  $element_clone = array();
  foreach (Element::children($element) as $child_name) {
    $element_clone[$child_name] = $element[$child_name];

    // If this element is in a group, create the placeholder element.
    if (isset($element['#group_children'][$child_name])) {
      $element_clone[$element['#group_children'][$child_name]] = array();
    }
  }
  $element = array_merge($element_clone, $element);

  // Move all children to their parents. Use the flat list of references for
  // direct access as we don't know where in the root_element hierarchy the
  // parent currently is situated.
  foreach ($element['#group_children'] as $child_name => $parent_name) {

    // Entity being viewed
    if ($vars) {

      // If not a group, check the content variable for empty field.
      $key = field_group_get_content_element_key($context);
      if (!isset($element['#fieldgroups'][$child_name]) && isset($vars[$key][$child_name])) {
        $group_references[$parent_name][$child_name] = $vars[$key][$child_name];
        unset($vars[$key][$child_name]);
      }
      else {
        $group_references[$parent_name][$child_name] =& $element[$child_name];
        unset($element[$child_name]);
      }
    }
    else {

      // Block denied fields (#access) before they are put in groups.
      // Fields (not groups) that don't have children (like field_permissions) are removed
      // in field_group_field_group_build_pre_render_alter.
      if (isset($element[$child_name]) && (!isset($element[$child_name]['#access']) || $element[$child_name]['#access'])) {

        // If this is a group, we have to use a reference to keep the reference
        // list intact (but if it is a field we don't mind).
        $group_references[$parent_name][$child_name] =& $element[$child_name];
        $group_references[$parent_name]['#weight'] = $element['#fieldgroups'][$parent_name]->weight;
      }

      // The child has been copied to its parent: remove it from the root element.
      unset($element[$child_name]);
    }
  }

  // Bring extra element wrappers to achieve a grouping of fields.
  // This will mainly be prefix and suffix altering.
  foreach ($element['#fieldgroups'] as $group_name => $group) {
    field_group_pre_render($group_references[$group_name], $group, $element);
  }
}

/**
 * Function to pre render the field group element.
 *
 * @see field_group_fields_nest()
 *
 * @param $element
 *   Render array of group element that needs to be created.
 * @param $group
 *   Object with the group information.
 * @param $rendering_object
 *   The entity / form beïng rendered.
 */
function field_group_pre_render(&$element, $group, &$rendering_object) {

  // Only run the pre_render function if the group has elements.
  // $group->group_name
  if ($element == array()) {
    return;
  }

  // Let modules define their wrapping element.
  // Note that the group element has no properties, only elements.
  foreach (Drupal::moduleHandler()
    ->getImplementations('field_group_pre_render') as $module) {

    // The intention here is to have the opportunity to alter the
    // elements, as defined in hook_field_group_formatter_info.
    // Note, implement $element by reference!
    $function = $module . '_field_group_pre_render';
    $function($element, $group, $rendering_object);
  }

  // Allow others to alter the pre_render.
  Drupal::moduleHandler()
    ->alter('field_group_pre_render', $element, $group, $rendering_object);
}

/**
 * Provides the content element key for a display context.
 *
 * This allows entity modules to specify their content element for field group
 * support, or other modules to add entity module support.
 *
 * @param $context
 *   The display context (entity type, form or view).
 */
function field_group_get_content_element_key($context = 'default') {
  $keys =& drupal_static('field_group_content_elements');
  if (!isset($keys)) {
    $keys['default'] = 'content';

    // Allow other modules to alter the array.
    Drupal::moduleHandler()
      ->alter('field_group_content_element_keys', $keys);
  }

  // Check if we have a specific content element key for this entity type.
  $key = $keys['default'];
  if (isset($keys[$context])) {
    $key = $keys[$context];
  }
  return $key;
}

/**
 * Saves a group definition.
 *
 * This function is called by ctools export when calls are made through
 * ctools_export_crud_save(). It's also used as an api method to add groups to a
 * display.
 *
 * @param \stdClass $group
 *   A group definition.
 * @param \Drupal\Core\Entity\Display\EntityDisplayInterface $display
 *   The display to update if known.
 *
 * @return \Drupal\Core\Entity\Display\EntityDisplayInterface|NULL
 *   The updated entity display.
 */
function field_group_group_save($group, $display = NULL) {
  if ($display === NULL) {
    if ($group->context == 'form') {
      $display = EntityFormDisplay::load($group->entity_type . '.' . $group->bundle . '.' . $group->mode);
    }
    elseif ($group->context == 'view') {
      $display = EntityViewDisplay::load($group->entity_type . '.' . $group->bundle . '.' . $group->mode);
    }
  }

  // If no display was found. It doesn't exist yet, create it.
  if (!isset($display)) {
    if ($group->context == 'form') {
      $display = EntityFormDisplay::create(array(
        'targetEntityType' => $group->entity_type,
        'bundle' => $group->bundle,
        'mode' => $group->mode,
      ))
        ->setStatus(TRUE);
    }
    elseif ($group->context == 'view') {
      $display = EntityViewDisplay::create(array(
        'targetEntityType' => $group->entity_type,
        'bundle' => $group->bundle,
        'mode' => $group->mode,
      ))
        ->setStatus(TRUE);
    }
  }
  if (isset($display)) {
    $data = (array) $group;
    unset($data['group_name'], $data['entity_type'], $data['bundle'], $data['mode'], $data['form'], $data['context']);
    $display
      ->setThirdPartySetting('field_group', $group->group_name, $data);
    $display
      ->save();
  }
  return $display;
}

/**
 * Delete a field group.
 *
 * @param $group
 *   A group definition.
 */
function field_group_group_delete($group) {
  if ($group->context == 'form') {
    $display = EntityFormDisplay::load($group->entity_type . '.' . $group->bundle . '.' . $group->mode);
  }
  elseif ($group->context == 'view') {
    $display = EntityViewDisplay::load($group->entity_type . '.' . $group->bundle . '.' . $group->mode);
  }

  /**
   * @var $display \Drupal\Core\Entity\Display\EntityDisplayInterface
   */
  if (isset($display)) {
    $display
      ->unsetThirdPartySetting('field_group', $group->group_name);
    $display
      ->save();
  }
  Drupal::moduleHandler()
    ->invokeAll('field_group_delete_field_group', array(
    $group,
  ));
}

/**
 * Get all groups.
 *
 * @param $entity_type
 *   The name of the entity.
 * @param $bundle
 *   The name of the bundle.
 * @param $context
 *   The context of the view mode (form or view)
 * @param $mode
 *   The view mode.
 */
function field_group_info_groups($entity_type, $bundle, $context, $mode) {
  if ($context == 'form') {
    $display = EntityFormDisplay::load($entity_type . '.' . $bundle . '.' . $mode);
    if (!$display) {
      return array();
    }
    $data = $display
      ->getThirdPartySettings('field_group');
  }
  if ($context == 'view') {
    $display = EntityViewDisplay::load($entity_type . '.' . $bundle . '.' . $mode);
    if (!$display) {
      return array();
    }
    $data = $display
      ->getThirdPartySettings('field_group');
  }
  $groups = array();
  if (isset($data) && is_array($data)) {
    foreach ($data as $group_name => $definition) {
      $definition += array(
        'group_name' => $group_name,
        'entity_type' => $entity_type,
        'bundle' => $bundle,
        'context' => $context,
        'mode' => $mode,
      );
      $groups[$group_name] = (object) $definition;
    }
  }
  return $groups;
}

/**
 * Loads a group definition.
 *
 * @param $group_name
 *   The name of the group.
 * @param $entity_type
 *   The name of the entity.
 * @param $bundle
 *   The name of the bundle.
 * @param $context
 *   The context of the view mode (form or view)
 * @param $mode
 *   The view mode to load.
 */
function field_group_load_field_group($group_name, $entity_type, $bundle, $context, $mode) {
  $groups = field_group_info_groups($entity_type, $bundle, $context, $mode);
  if (isset($groups[$group_name])) {
    return $groups[$group_name];
  }
}

/**
 * Checks if a field_group exists in required context.
 *
 * @param String $group_name
 *   The name of the group.
 * @param String $entity_type
 *   The name of the entity.
 * @param String $bundle
 *   The bundle for the entity.
 * @param $context
 *   The context of the view mode (form or view)
 * @param String $mode
 *   The view mode context the group will be rendered.
 */
function field_group_exists($group_name, $entity_type, $bundle, $context, $mode) {
  return (bool) field_group_load_field_group($group_name, $entity_type, $bundle, $context, $mode);
}

/**
 * Remove empty groups on forms.
 *
 * @param String $parent_name
 *   The name of the element.
 * @param array $element
 *   The element to check the empty state.
 * @param array $groups
 *   Array of group objects.
 */
function field_group_remove_empty_form_groups($name, &$element, $groups, &$form_groups, $entity) {
  $exceptions = array(
    'user__account',
    'comment__author',
  );
  $children = Element::children($element);
  $hasChildren = FALSE;
  if (count($children)) {
    foreach ($children as $childname) {
      if (in_array($childname, $groups)) {
        field_group_remove_empty_form_groups($childname, $element[$childname], $groups, $form_groups, $entity);
      }
      $exception = $entity . '__' . $childname;
      $hasChildren = $hasChildren ? TRUE : isset($element[$childname]['#type']) || isset($element[$childname]['#markup']) || in_array($exception, $exceptions);
    }
  }
  if (!$hasChildren) {

    // Remove empty elements from the #fieldgroups.
    if (empty($element) && isset($form_groups[$name]) && !is_array($form_groups[$name])) {
      foreach ($form_groups as $group_name => $group) {
        if (isset($group->children)) {
          $group_children = array_flip($group->children);
          if (isset($group_children[$name])) {
            unset($form_groups[$group_name]->children[$group_children[$name]]);
          }
        }
      }
    }
    $element['#access'] = FALSE;
  }
}

/**
 * Remove empty groups on entity display.
 *
 * @param array $element
 *   The element to check the empty state.
 * @param array $groups
 *   Array of group objects.
 */
function field_group_remove_empty_display_groups(&$element, $groups) {
  $empty_child = TRUE;
  $empty_group = TRUE;

  // Loop through the visible children for current element.
  foreach (Element::getVisibleChildren($element) as $name) {

    // Descend if the child is a group.
    if (in_array($name, $groups)) {
      $empty_child = field_group_remove_empty_display_groups($element[$name], $groups);
      if (!$empty_child) {
        $empty_group = FALSE;
      }
    }
    elseif (!empty($element[$name])) {
      $clone_element = $element[$name];

      // Weight parameter can make empty element seen as not empty.
      unset($clone_element['#weight']);
      if (!Element::isEmpty($clone_element)) {
        $empty_group = FALSE;
      }
    }
  }

  // Reset an empty group.
  if ($empty_group) {
    $element = [];
  }
  return $empty_group;
}

Functions

Namesort descending Description
field_group_attach_groups Attach groups to the (form) build.
field_group_build_entity_groups Preprocess/ Pre-render callback.
field_group_entity_view_alter Implements hook_entity_view_alter().
field_group_entity_view_pre_render Pre render callback for rendering groups on entities without theme hook.
field_group_exists Checks if a field_group exists in required context.
field_group_fields_nest Recursive function to nest fields in the field groups.
field_group_field_group_build_pre_render_alter Implements hook_field_group_build_pre_render_alter().
field_group_field_group_pre_render Implements hook_field_group_pre_render().
field_group_field_info_max_weight Implements hook_field_info_max_weight().
field_group_form_alter Implements hook_form_alter().
field_group_form_entity_form_display_edit_form_alter Implements hook_form_FORM_ID_alter(). Using hook_form_field_ui_form_display_overview_form_alter.
field_group_form_entity_view_display_edit_form_alter Implements hook_form_FORM_ID_alter(). Using hook_form_field_ui_display_overview_form_alter.
field_group_form_pre_render Pre render callback for rendering groups.
field_group_get_content_element_key Provides the content element key for a display context.
field_group_group_delete Delete a field group.
field_group_group_save Saves a group definition.
field_group_info_groups Get all groups.
field_group_inline_entity_form_entity_form_alter Implements hook_inline_entity_form_entity_form_alter().
field_group_load_field_group Loads a group definition.
field_group_pre_render Function to pre render the field group element.
field_group_remove_empty_display_groups Remove empty groups on entity display.
field_group_remove_empty_form_groups Remove empty groups on forms.
field_group_theme Implements hook_theme().
field_group_theme_registry_alter Implements hook_theme_registry_alter().
field_group_theme_suggestions_alter Implements hook_theme_suggestions_alter().