You are here

og_ui.module in Organic groups 7.2

Same filename and directory in other branches
  1. 8 og_ui/og_ui.module
  2. 7 og_ui/og_ui.module

Organic groups UI.

File

og_ui/og_ui.module
View source
<?php

/**
 * @file
 * Organic groups UI.
 */

/**
 * Implements hook_menu().
 */
function og_ui_menu() {
  $items = array();
  $items['group/%/%/subscribe'] = array(
    'type' => MENU_CALLBACK,
    'file' => 'og_ui.pages.inc',
    'page callback' => 'og_ui_subscribe',
    'page arguments' => array(
      1,
      2,
    ),
    // Function will take care of permissions, as we want to show "you are
    // already a member of the group" to group members, however it is not
    // possible to give authenticated group members the "subscribe" permissions.
    'access callback' => 'user_is_logged_in',
    // We don't add the group name, as it might be private.
    'title' => 'Join group',
  );
  $items['group/%/%/unsubscribe'] = array(
    'type' => MENU_CALLBACK,
    'file' => 'og_ui.pages.inc',
    'page callback' => 'og_ui_unsubscribe',
    'page arguments' => array(
      1,
      2,
    ),
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'unsubscribe',
      1,
      2,
    ),
    'title' => 'Leave group',
  );
  $items['group/%/%/admin/people/add-user'] = array(
    'page callback' => 'drupal_get_form',
    'title' => 'Add members',
    'page arguments' => array(
      'og_ui_add_users',
      1,
      2,
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'og_ui.admin.inc',
    'weight' => 5,
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'add user',
      1,
      2,
    ),
  );

  // User listing pages.
  $items['group/%/%/admin/people'] = array(
    'title callback' => 'og_ui_menu_title_callback',
    'title arguments' => array(
      'People in group @group',
      1,
      2,
    ),
    'description' => 'Find and manage group members.',
    'page callback' => 'og_ui_admin_account',
    'page arguments' => array(
      1,
      2,
    ),
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'manage members',
      1,
      2,
    ),
    'weight' => -4,
    'file' => 'og_ui.admin.inc',
  );

  // User listing pages.
  $items['group/%/%/admin/people/edit-membership/%og_membership'] = array(
    'title callback' => 'og_ui_menu_title_callback',
    'title arguments' => array(
      'Edit membership in group @group',
      1,
      2,
    ),
    'type' => MENU_CALLBACK,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_edit_membership',
      1,
      2,
      6,
    ),
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'manage members',
      1,
      2,
    ),
    'file' => 'og_ui.admin.inc',
  );

  // Delete a single membership.
  $items['group/%/%/admin/people/delete-membership/%og_membership'] = array(
    'title' => 'Delete',
    'type' => MENU_CALLBACK,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_delete_membership',
      1,
      2,
      6,
    ),
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'manage members',
      1,
      2,
    ),
    'file' => 'og_ui.admin.inc',
  );

  // Permission administration pages.
  $items['group/%/%/admin/roles'] = array(
    'title callback' => 'og_ui_menu_title_callback',
    'title arguments' => array(
      'Roles for group @group',
      1,
      2,
    ),
    'description' => 'List, edit, or add user roles.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_admin_new_role',
      1,
      2,
    ),
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'manage roles',
      1,
      2,
    ),
    'file' => 'og_ui.admin.inc',
    'weight' => -9,
  );

  // Node specific role edit
  // group/[1: Group type]/[2: Group ID]/admin/role/[5: Role ID]/edit
  $items['group/%/%/admin/role/%/edit'] = array(
    'title' => 'Edit role',
    'description' => 'List, edit, or add user roles.',
    'page callback' => 'drupal_get_form',
    // Passing empty bundle name to og_ui_admin_roles. The bundle will be
    // loaded from the role.
    'page arguments' => array(
      'og_ui_admin_roles',
      1,
      2,
      '',
      5,
    ),
    'access callback' => 'og_ui_access_entity_role',
    // Require administer group permission to edit and delete roles.
    'access arguments' => array(
      'manage roles',
      1,
      2,
      5,
    ),
    'file' => 'og_ui.admin.inc',
    'weight' => -9,
  );
  $items['group/%/%/admin/permissions'] = array(
    'title callback' => 'og_ui_menu_title_callback',
    'title arguments' => array(
      'Permissions for group @group',
      1,
      2,
    ),
    'description' => 'Determine access to features by selecting permissions for roles.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_admin_permissions',
      1,
      2,
    ),
    'access callback' => 'og_ui_user_access_group',
    'access arguments' => array(
      'manage permissions',
      1,
      2,
    ),
    'file' => 'og_ui.admin.inc',
    'weight' => -8,
  );

  // Node specific permission edit
  // group/[1: Group type]/[2: Group ID]/admin/permission/[5: Role ID]/edit
  $items['group/%/%/admin/permission/%/edit'] = array(
    'title' => "Edit role's permissions",
    'description' => 'Determine access to features by selecting permissions for role.',
    'page callback' => 'drupal_get_form',
    // Passing empty bundle name to og_ui_admin_permissions. The bundle will be
    // loaded from the role.
    'page arguments' => array(
      'og_ui_admin_permissions',
      1,
      2,
      '',
      5,
    ),
    'access callback' => 'og_ui_access_entity_role',
    'access arguments' => array(
      'manage permissions',
      1,
      2,
      5,
    ),
    'file' => 'og_ui.admin.inc',
    'weight' => -9,
  );
  foreach (og_get_all_group_entity() as $entity_type => $value) {
    if ($entity_type == 'taxonomy_term') {
      $path = 'taxonomy/term/%/group';
      $argument = 2;
    }
    else {
      $path = "{$entity_type}/%/group";
      $argument = 1;
    }
    $items[$path] = array(
      'title' => 'Group',
      'page callback' => 'og_ui_group_admin_overview',
      'page arguments' => array(
        $entity_type,
        $argument,
      ),
      'access callback' => 'og_ui_get_group_admin',
      'access arguments' => array(
        $entity_type,
        $argument,
      ),
      'type' => MENU_LOCAL_TASK,
      'file' => 'og_ui.admin.inc',
      'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
    );
  }
  $items['admin/config/group'] = array(
    'title' => 'Organic groups',
    'description' => 'Administer the suite of Organic groups modules.',
    'position' => 'right',
    'weight' => -5,
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array(
      'administer group',
    ),
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'),
  );
  $items['admin/config/group/settings'] = array(
    'title' => 'OG settings',
    'description' => 'Administer OG settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_admin_settings',
    ),
    'access arguments' => array(
      'administer group',
    ),
    'file' => 'og_ui.admin.inc',
  );
  $items['admin/config/group/permissions'] = array(
    'page callback' => 'og_ui_group_types_overview',
    'page arguments' => array(
      'permissions',
    ),
    'title' => 'OG permissions overview',
    'access arguments' => array(
      'administer group',
    ),
    'description' => 'Overview of Organic groups permissions.',
    'file' => 'og_ui.admin.inc',
  );

  // Add menu item for each group type.
  // admin/config/group/roles/[Entity type]/[Group bundle]
  foreach (og_get_all_group_bundle() as $entity_type => $bundles) {
    $entity_info = entity_get_info($entity_type);
    foreach ($bundles as $bundle_name => $bundle_label) {
      $items["admin/config/group/permissions/{$entity_type}/{$bundle_name}"] = array(
        'page callback' => 'drupal_get_form',
        'page arguments' => array(
          'og_ui_admin_global_permissions',
          $entity_type,
          '0',
          $bundle_name,
        ),
        'title callback' => 'og_ui_menu_bundle_roles_title_callback',
        'title arguments' => array(
          'OG @type - @bundle permissions',
          $entity_type,
          $bundle_name,
        ),
        'access callback' => 'og_ui_access_group_permissions',
        'access arguments' => array(
          $entity_type,
          $bundle_name,
        ),
        'description' => 'Configure Organic groups group type permissions.',
        'file' => 'og_ui.admin.inc',
      );
    }
  }
  $items['admin/config/group/permission/%/edit'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_admin_permissions',
      '',
      '0',
      '',
      4,
    ),
    'title callback' => 'og_ui_menu_bundle_roles_title_callback',
    'title arguments' => array(
      'OG @type - @bundle - @role permissions',
      '',
      '',
      4,
    ),
    'access callback' => 'og_ui_access_bundle_role',
    'access arguments' => array(
      4,
    ),
    'description' => 'Configure Organic groups group type permissions.',
    'file' => 'og_ui.admin.inc',
  );
  $items['admin/config/group/roles'] = array(
    'page callback' => 'og_ui_group_types_overview',
    'page arguments' => array(
      'roles',
    ),
    'title' => 'OG roles overview',
    'access arguments' => array(
      'administer group',
    ),
    'description' => 'Overview of organic groups roles.',
    'file' => 'og_ui.admin.inc',
  );

  // Add menu item for each group type.
  // admin/config/group/roles/[Entity type]/[Group bundle]
  foreach (og_get_all_group_bundle() as $entity_type => $bundles) {
    $entity_info = entity_get_info($entity_type);
    foreach ($bundles as $bundle_name => $bundle_label) {
      $items["admin/config/group/roles/{$entity_type}/{$bundle_name}"] = array(
        'page callback' => 'drupal_get_form',
        'page arguments' => array(
          'og_ui_admin_new_role',
          $entity_type,
          '0',
          $bundle_name,
        ),
        'title callback' => 'og_ui_menu_bundle_roles_title_callback',
        'title arguments' => array(
          'OG @type - @bundle roles',
          $entity_type,
          $bundle_name,
        ),
        'access callback' => 'og_ui_access_bundle',
        'access arguments' => array(
          $entity_type,
          $bundle_name,
        ),
        'description' => 'Configure Organic groups group type roles.',
        'file' => 'og_ui.admin.inc',
      );
    }
  }
  $items['admin/config/group/role/%/edit'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_admin_roles',
      '',
      '0',
      '',
      4,
    ),
    'title callback' => 'og_ui_menu_bundle_roles_title_callback',
    'title arguments' => array(
      'OG @type - @bundle - @role',
      '',
      '',
      4,
    ),
    'access callback' => 'og_ui_access_bundle_role',
    'access arguments' => array(
      4,
    ),
    'description' => 'Configure Organic groups group type roles.',
    'file' => 'og_ui.admin.inc',
  );
  $items['admin/config/group/fields'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_field_settings',
    ),
    'title' => 'OG field settings',
    'access arguments' => array(
      'administer group',
    ),
    'description' => 'Configure Organic groups fields in bundles.',
    'file' => 'og_ui.admin.inc',
    'type' => MENU_NORMAL_ITEM,
  );
  $items['admin/config/group/fields/%/%/%field_ui_menu/delete'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_ui_field_delete_form',
      6,
    ),
    'load arguments' => array(
      4,
      5,
      5,
      '%map',
    ),
    'title' => 'Delete',
    'access arguments' => array(
      'administer group',
    ),
    'description' => 'Delete an OG field from a bundle.',
    'file' => 'og_ui.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implements hook_field_create_instance().
 *
 * Invalidate the menu when an instance is inserted, to add it to the roles /
 * premissions menus.
 *
 * @see og_ui_menu()
 */
function og_ui_field_create_instance($instance) {
  if ($instance['field_name'] != OG_GROUP_FIELD) {
    return;
  }
  variable_set('menu_rebuild_needed', TRUE);
}

/**
 * Implements hook_field_delete_instance().
 *
 * Invalidate the menu when an instance is deleted, to remove it from the roles
 * / premissions menus.
 *
 * @see og_ui_menu()
 */
function og_ui_field_delete_instance($instance) {
  if ($instance['field_name'] != OG_GROUP_FIELD) {
    return;
  }
  variable_set('menu_rebuild_needed', TRUE);
}

/**
 * Menu access; Check if entity is a group, and user has permission.
 */
function og_ui_user_access_group($perm, $group_type, $gid) {
  $group = entity_load_single($group_type, $gid);
  if (!$group || !og_is_group($group_type, $group)) {
    return FALSE;
  }

  // Extract the group's bundle.
  list(, , $bundle) = entity_extract_ids($group_type, $group);

  // Verify the bundle has roles
  if (!og_roles($group_type, $bundle, $gid)) {
    return FALSE;
  }
  return og_user_access($group_type, $gid, $perm);
}

/**
 * Menu access; Check access and validate values for group permissions page.
 *
 * @param $rid
 * @param $group_type
 * @param $gid
 * @param $bundle
 */
function og_ui_access_group_permissions($group_type, $bundle, $gid = 0, $rid = 0) {
  if (!user_access('administer group')) {
    return FALSE;
  }
  if ($group_type && !entity_get_info($group_type)) {
    return FALSE;
  }
  if ($gid && !entity_load_single($group_type, $gid)) {
    return FALSE;
  }
  if ($rid) {
    $og_roles = og_roles($group_type, $bundle, $gid);
    return !empty($og_roles[$rid]);
  }
  return TRUE;
}

/**
 * Menu access; Check permissions per-bundle editing.
 *
 * @param $group_type
 *   Group entity type. E.g. 'node'.
 * @param $bundle_name
 *   Bundle name.
 *
 * @return
 *   True if current user is allowed to edit given bundle. False otherwise.
 */
function og_ui_access_bundle($group_type, $bundle_name) {
  if (!user_access('administer group')) {
    return FALSE;
  }
  $role_names = og_roles($group_type, $bundle_name);
  if (!$role_names) {
    return FALSE;
  }
  return TRUE;
}

/**
 * Menu access; Check permissions for role editing.
 *
 * @param $perm
 *   Permission string. E.g. 'administer group'.
 * @param $rid
 *   Role ID.
 *
 * @return
 *   True if current user is allowed to edit given role. False otherwise.
 */
function og_ui_access_bundle_role($rid) {
  if (!user_access('administer group')) {
    return FALSE;
  }
  $role = og_role_load($rid);
  return (bool) $role;
}

/**
 * Menu access; Check permissions for role editing - For a specific entity.
 *
 * @param $perm
 *   Permission string. E.g. 'administer group'.
 * @param $group_type
 *   Group entity type. E.g. 'node'.
 * @param $gid
 *   Group ID.
 * @param $rid
 *   Role ID.
 *
 * @return
 *   True if current user is allowed to edit given role. False otherwise.
 */
function og_ui_access_entity_role($perm, $group_type, $gid, $rid) {
  if (!og_user_access($group_type, $gid, $perm)) {
    return FALSE;
  }
  $group = entity_load_single($group_type, $gid);
  if (!$group || !og_is_group($group_type, $group)) {
    return FALSE;
  }
  $role = og_role_load($rid);
  if (!$role || $role->group_type != $group_type) {

    // Role doesn't exist, or doesn't belong to the group.
    return FALSE;
  }
  if ($role->gid && $role->gid != $gid) {

    // Role isn't a global role (i.e. gid isn't 0), but it doesn't match the
    // given role.
    return FALSE;
  }
  return TRUE;
}

/**
 * Implements hook_views_api().
 */
function og_ui_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'og_ui') . '/includes/views',
  );
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function og_ui_ctools_plugin_directory($module, $plugin) {
  if ($module == 'ctools') {
    return 'plugins/' . $plugin;
  }
}

/**
 * Implements hook_admin_paths().
 */
function og_ui_admin_paths() {
  $paths = array(
    'node/*/group' => TRUE,
    'group/*/*/admin/*' => TRUE,
  );
  return $paths;
}

/**
 * Menu callback; Return the title of a menu item based on the group title.
 */
function og_ui_menu_title_callback($title, $entity_type, $etid) {
  $wrapper = entity_metadata_wrapper($entity_type, $etid);
  return str_replace('@group', $wrapper
    ->label(), $title);
}

/**
 * Title callback; Return the title for role or permission editing, based on
 * context.
 */
function og_ui_menu_bundle_roles_title_callback($title, $group_type, $bundle, $rid = 0) {
  if ($rid) {

    // Get group type and bundle from role.
    $role = og_role_load($rid);
    if (!$role->group_type) {
      $title = str_replace('@type', '', $title);
      $title = str_replace('@bundle', t('Global'), $title);
    }
    $bundle = $role->group_bundle;
    $group_type = $role->group_type;
    $title = str_replace('@role', check_plain($role->name), $title);
  }
  $entity_info = entity_get_info($group_type);
  if (!empty($entity_info['label'])) {
    $title = str_replace('@type', check_plain($entity_info['label']), $title);
    $title = str_replace('@bundle', check_plain($entity_info['bundles'][$bundle]['label']), $title);
  }
  return $title;
}

/**
 * Implement hook_theme().
 */
function og_ui_theme() {
  return array(
    'og_ui_admin_permissions' => array(
      'render element' => 'form',
      'file' => 'og_ui.admin.inc',
    ),
    'og_ui_admin_new_role' => array(
      'render element' => 'form',
      'file' => 'og_ui.admin.inc',
    ),
  );
}

/**
 * Implements hook_og_fields_info_alter().
 *
 * Change the default formatter of the group field.
 */
function og_ui_og_fields_info_alter(&$items) {
  $items[OG_GROUP_FIELD]['instance']['display']['default']['type'] = 'og_group_subscribe';
  $items[OG_AUDIENCE_FIELD]['instance']['display']['default']['type'] = 'og_list_default';
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Add option to hide the OG_GROUP_FIELD.
 *
 * @see og_field_access()
 */
function og_ui_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  if ($form['#field']['field_name'] != OG_GROUP_FIELD) {
    return;
  }
  $form['#instance']['widget']['settings'] += array(
    'og_hide' => TRUE,
  );
  $form['instance']['widget']['settings']['og_hide'] = array(
    '#type' => 'checkbox',
    '#title' => t('Hide'),
    '#description' => t('Hide group field, and apply default values.'),
    '#default_value' => $form['#instance']['widget']['settings']['og_hide'],
  );
}

/**
 * Implement hook_field_formatter_info().
 */
function og_ui_field_formatter_info() {
  return array(
    'og_group_subscribe' => array(
      'label' => t('OG subscribe link'),
      'field types' => array(
        'list_boolean',
      ),
      'settings' => array(
        'field_name' => FALSE,
      ),
    ),
    'og_list_default' => array(
      'label' => t('OG audience list'),
      'field types' => array(
        'entityreference',
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function og_ui_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  global $user;
  $settings = $display['settings'];
  switch ($display['type']) {
    case 'og_group_subscribe':
      $account = clone $user;
      if (!og_is_group($entity_type, $entity)) {
        return;
      }
      if (!empty($entity->uid) && $entity->uid == $account->uid) {

        // User is the group manager.
        $element[0] = array(
          '#type' => 'html_tag',
          '#tag' => 'span',
          '#attributes' => array(
            'title' => t('You are the group manager'),
            'class' => 'group manager',
          ),
          '#value' => t('You are the group manager'),
        );
        return $element;
      }
      list($id, , $bundle) = entity_extract_ids($entity_type, $entity);
      if (og_is_member($entity_type, $id, 'user', $account, array(
        OG_STATE_ACTIVE,
        OG_STATE_PENDING,
      ))) {
        if (og_user_access($entity_type, $id, 'unsubscribe', $account)) {
          $links['title'] = t('Unsubscribe from group');
          $links['href'] = "group/{$entity_type}/{$id}/unsubscribe";
          $links['class'] = 'group unsubscribe';
        }
      }
      else {
        if (og_is_member($entity_type, $id, 'user', $account, array(
          OG_STATE_BLOCKED,
        ))) {

          // If user is blocked, they should not be able to apply for
          // membership.
          return;
        }

        // Check if user can subscribe to the field.
        if (empty($settings['field_name']) && ($audience_field_name = og_get_best_group_audience_field('user', $account, $entity_type, $bundle))) {
          $settings['field_name'] = $audience_field_name;
        }
        if (!$settings['field_name']) {
          return;
        }
        $field_info = field_info_field($settings['field_name']);

        // Check if entity is referencable.
        if ($field_info['settings']['target_type'] != $entity_type) {

          // Group type doesn't match.
          return;
        }
        if (!empty($field_info['settings']['handler_settings']['target_bundles']) && !in_array($bundle, $field_info['settings']['handler_settings']['target_bundles'])) {

          // Bundles don't match.
          return;
        }
        if (!og_check_field_cardinality('user', $account, $settings['field_name'])) {
          $element[0] = array(
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#attributes' => array(
              'title' => format_plural($field_info['cardinality'], 'You are already registered to another group', 'You are already registered to @count groups'),
              'class' => 'group other',
            ),
            '#value' => format_plural($field_info['cardinality'], 'You are already registered to another group', 'You are already registered to @count groups'),
          );
          return $element;
        }
        $url = "group/{$entity_type}/{$id}/subscribe";
        if ($settings['field_name']) {
          $url .= '/' . $settings['field_name'];
        }
        if (og_user_access($entity_type, $id, 'subscribe without approval', $account)) {
          $links['title'] = t('Subscribe to group');
          $links['class'] = 'group subscribe';
          if ($account->uid) {
            $links['href'] = $url;
          }
          else {
            $links['href'] = 'user/login';
            $links['options'] = array(
              'query' => array(
                'destination' => $url,
              ),
            );
          }
        }
        elseif (og_user_access($entity_type, $id, 'subscribe')) {
          $links['title'] = t('Request group membership');
          $links['class'] = 'group subscribe request';
          if ($account->uid) {
            $links['href'] = $url;
          }
          else {
            $links['href'] = 'user/login';
            $links['options'] = array(
              'query' => array(
                'destination' => $url,
              ),
            );
          }
        }
        else {
          $element[0] = array(
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#attributes' => array(
              'title' => t('This is a closed group. Only a group administrator can add you.'),
              'class' => 'group closed',
            ),
            '#value' => t('This is a closed group. Only a group administrator can add you.'),
          );
          return $element;
        }
      }
      if (!empty($links['title'])) {
        $links += array(
          'options' => array(
            'attributes' => array(
              'title' => $links['title'],
              'class' => array(
                $links['class'],
              ),
            ),
          ),
        );
        $element[0] = array(
          '#type' => 'link',
          '#title' => $links['title'],
          '#href' => $links['href'],
          '#options' => $links['options'],
        );
        return $element;
      }

      // User didn't have permissions.
      break;
    case 'og_list_default':
      $accessible_ids = array();
      $private = FALSE;
      $wrapper = entity_metadata_wrapper($entity_type, $entity);
      $field_name = $field['field_name'];
      if (!$wrapper->{$field_name}
        ->value()) {
        return;
      }
      if ($field['cardinality'] == 1) {

        // Single-value field.
        if ($wrapper->{$field_name}
          ->entityAccess('view')) {
          $id = $wrapper->{$field_name}
            ->getIdentifier();
          $accessible_ids[$id] = TRUE;
        }
        else {
          $private = TRUE;
        }
      }
      else {

        // Multi-value field.
        foreach ($wrapper->{$field_name} as $wrapper_field) {
          $id = $wrapper_field
            ->value(array(
            'identifier' => TRUE,
          ));
          if ($wrapper_field
            ->entityAccess('view')) {
            $accessible_ids[$id] = TRUE;
          }
          else {
            $private = TRUE;
          }
        }
      }
      if ($entity_type == 'user') {

        // Show only the groups a user is active in.
        foreach ($wrapper->{$field_name . '__og_membership'}
          ->value() as $og_membership) {
          if ($og_membership->state != OG_STATE_ACTIVE) {
            unset($accessible_ids[$og_membership->gid]);
          }
        }
      }
      $group_type = $field['settings']['target_type'];
      $accessible_entity = entity_load($group_type, array_keys($accessible_ids));
      $element = array();
      foreach ($items as $delta => $item) {
        if (!empty($accessible_ids[$item['target_id']]) && !empty($accessible_entity[$item['target_id']])) {
          $wrapper = entity_metadata_wrapper($group_type, $item['target_id']);
          $element[$delta] = array(
            '#type' => 'link',
            '#title' => $wrapper
              ->label(),
            '#href' => $wrapper->url
              ->value(),
            // Add the group type and group ID, so it's easier for implementing
            // modules to extend the formatter.
            '#group_type' => $group_type,
            '#gid' => $wrapper
              ->getIdentifier(),
          );
        }
      }
      if ($private) {
        $element = array_values($element);
        $element[] = array(
          '#markup' => '- ' . t('Private group') . ' -',
        );
      }
      return $element;
  }
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function og_ui_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  if ($display['type'] == 'og_group_subscribe') {
    $element['field_name'] = array(
      '#title' => t('Field name'),
      '#description' => t('Select the field that should register the user subscription.'),
      '#type' => 'select',
      '#options' => array(
        0 => t('Automatic (best matching)'),
      ) + og_get_group_audience_fields('user', 'user'),
      '#default_value' => $settings['field_name'],
    );
  }
  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function og_ui_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  if ($display['type'] != 'og_group_subscribe') {
    return;
  }
  if ($settings['field_name']) {
    $fields = og_get_group_audience_fields();
    return t('Field %label', array(
      '%label' => $fields[$settings['field_name']],
    ));
  }
  else {
    return t('No field selected (best matching)');
  }
}

/**
 * Implements hook_field_access().
 */
function og_ui_field_access($op, $field, $entity_type, $entity, $account) {
  global $user;
  if (!og_is_group_audience_field($field['field_name'])) {
    return;
  }
  if (!$user->uid) {

    // User is anonymous, and user register might try to add the group-audience
    // field.
    return;
  }
  if ($op != 'edit') {
    return;
  }
  if ($entity_type != 'user') {
    return;
  }
  list($id, $vid, $bundle_name) = entity_extract_ids($entity_type, $entity);
  $instance = field_info_instance($entity_type, $field['field_name'], $bundle_name);
  if (!empty($instance['settings']['behaviors']['og_widget']['access_override'])) {
    return;
  }
  if (!user_access('administer group', $account)) {
    return FALSE;
  }
}

/**
 * Implements hook_og_user_access_alter().
 *
 * Add a permission to pending users to unsubscribe form group.
 */
function og_ui_og_user_access_alter(&$perms, $context) {
  if ($context['string'] != 'unsubscribe' || !empty($perm['unsubscribe'])) {
    return;
  }
  $group_type = $context['group_type'];
  $group = $context['group'];
  list($id) = entity_extract_ids($group_type, $group);
  $og_membership = og_get_membership($group_type, $id, 'user', $context['account']->uid);
  if (empty($og_membership) || $og_membership->state != OG_STATE_PENDING) {
    return;
  }

  // Allow user to unsubscribe.
  $perms['unsubscribe'] = TRUE;
}

/**
 * Implement hook_forms().
 */
function og_ui_forms() {
  $forms['og_ui_admin_new_role']['callback'] = 'og_ui_admin_roles';

  // Form to define the global permissions.
  $forms['og_ui_admin_global_permissions']['callback'] = 'og_ui_admin_permissions';
  return $forms;
}

/**
 * Implement hook_form_FORM_ID_alter().
 */
function og_ui_form_node_type_form_alter(&$form, &$form_state) {
  $node_type = $form['#node_type']->type;
  $form['og'] = array(
    '#type' => 'fieldset',
    '#title' => t('Organic groups'),
    '#collapsible' => TRUE,
    '#group' => 'additional_settings',
    '#description' => t('Specify how OG should treat content of this type. Content may behave as a group, as group content, or may not participate in OG at all.'),
  );

  // Group settings.
  $url = array(
    '!url' => l(t('Manage fields'), 'admin/structure/types/manage/' . str_replace('_', '-', $node_type) . '/fields'),
  );
  $is_group = og_is_group_type('node', $node_type);
  $description = t('Set the content type to be a group, that content will be associated with, and will have group members.');
  if ($is_group) {
    $description .= '<br/>' . t('To unset the group definition you should delete the "Group type" field via !url.', $url);
  }
  $form['og']['og_group_type'] = array(
    '#type' => 'checkbox',
    '#title' => t('Group'),
    '#default_value' => $is_group,
    '#description' => $description,
    '#disabled' => $is_group,
  );

  // Group content settings.
  $is_group_content = og_is_group_content_type('node', $node_type);
  $description = t('Set the content type to be a group content, that can be associated with groups.');
  if ($is_group_content) {
    $description .= '<br/>' . t('To unset the group content definition or change the settings you should delete the "Groups audience" field via !url.', $url);
  }
  $group_content_options = og_get_all_group_entity();
  if (!$group_content_options) {
    $description .= '<br/>' . t('There are no group bundles defined.');
  }
  $form['og']['og_group_content_type'] = array(
    '#type' => 'checkbox',
    '#title' => t('Group content'),
    '#default_value' => $is_group_content,
    '#description' => $description,
    '#disabled' => !$group_content_options || $is_group_content,
  );
  if ($group_content_options) {

    // Don't show the settings, as there might be multiple OG audience fields
    // in the same bundle.
    $form['og']['target_type'] = array(
      '#type' => 'select',
      '#title' => t('Target type'),
      '#options' => $group_content_options,
      '#default_value' => key($group_content_options),
      '#description' => t('The entity type that can be referenced thru this field.'),
      '#ajax' => array(
        'callback' => 'og_node_type_form_settings',
        'wrapper' => 'og-settings-wrapper',
      ),
      '#states' => array(
        'visible' => array(
          ':input[name="og_group_content_type"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $target_type = !empty($form_state['values']['target_type']) ? $form_state['values']['target_type'] : key($group_content_options);
    $entity_info = entity_get_info($target_type);
    $bundles = array();
    foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
      if (og_is_group_type($target_type, $bundle_name)) {
        $bundles[$bundle_name] = $bundle_info['label'];
      }
    }

    // Get the bundles that are acting as group.
    $form['og']['target_bundles'] = array(
      '#prefix' => '<div id="og-settings-wrapper">',
      '#suffix' => '</div>',
      '#type' => 'select',
      '#title' => t('Target bundles'),
      '#options' => $bundles,
      '#default_value' => array(),
      '#size' => 6,
      '#multiple' => TRUE,
      '#description' => t('The bundles of the entity type that can be referenced. Optional, leave empty for all bundles.'),
      '#states' => array(
        'visible' => array(
          ':input[name="og_group_content_type"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
  }
}

/**
 * AJAX callback to attach the message type fields to the form.
 *
 * Since the controlling logic for populating the form is in the form builder
 * function, all we do here is select the element and return it to be updated.
 */
function og_node_type_form_settings(array $form, array &$form_state) {
  return $form['og']['target_bundles'];
}

/**
 * Implements hook_node_type_insert().
 */
function og_ui_node_type_insert($info) {
  og_ui_node_type_save($info->type);
}

/**
 * Implements hook_node_type_update().
 */
function og_ui_node_type_update($info) {
  og_ui_node_type_save($info->type);
}

/**
 * Add group and group content fields to new content types.
 *
 * @param $bundle_name
 *   The content type name.
 */
function og_ui_node_type_save($bundle_name) {
  if (variable_get('og_group_type_' . $bundle_name, FALSE)) {
    og_create_field(OG_GROUP_FIELD, 'node', $bundle_name);
  }
  if (variable_get('og_group_content_type_' . $bundle_name, FALSE) && !og_is_group_content_type('node', $bundle_name)) {
    $og_field = og_fields_info(OG_AUDIENCE_FIELD);
    $og_field['field']['target_type'] = variable_get('target_type_' . $bundle_name);
    $og_field['field']['settings']['handler_settings']['target_bundles'] = variable_get('target_bundles_' . $bundle_name);
    og_create_field(OG_AUDIENCE_FIELD, 'node', $bundle_name, $og_field);
  }

  // Delete the variable, as we will rely on the presence of the field.
  $vars = array(
    'og_group_type',
    'og_group_content_type',
    'target_type',
    'target_bundles',
  );
  foreach ($vars as $var) {
    variable_del($var . '_' . $bundle_name);
  }
}

/**
 * Implement hook_og_permission().
 */
function og_ui_og_permission() {
  $items = array();
  $items['subscribe'] = array(
    'title' => t('Subscribe to group'),
    'description' => t('Allow non-members to request membership to a group (approval required).'),
    'roles' => array(
      OG_ANONYMOUS_ROLE,
    ),
    'default role' => array(
      OG_ANONYMOUS_ROLE,
    ),
  );
  $items['subscribe without approval'] = array(
    'title' => t('Subscribe to group (no approval required)'),
    'description' => t('Allow non-members to join a group without an approval from group administrators.'),
    'roles' => array(
      OG_ANONYMOUS_ROLE,
    ),
  );
  $items['unsubscribe'] = array(
    'title' => t('Unsubscribe from group'),
    'description' => t('Allow members to unsubscribe themselves from a group, removing their membership.'),
    'roles' => array(
      OG_AUTHENTICATED_ROLE,
    ),
    'default role' => array(
      OG_AUTHENTICATED_ROLE,
    ),
  );
  $items['approve and deny subscription'] = array(
    'title' => t('Approve and deny subscription'),
    'description' => t('Users may allow or deny another user\'s subscription request.'),
    'default role' => array(
      OG_ADMINISTRATOR_ROLE,
    ),
  );
  $items['add user'] = array(
    'title' => t('Add user'),
    'description' => t('Users may add other users to the group without approval.'),
    'default role' => array(
      OG_ADMINISTRATOR_ROLE,
    ),
  );
  $items['manage members'] = array(
    'title' => t('Manage members'),
    'description' => t('Users may remove group members and alter member status and roles.'),
    'default role' => array(
      OG_ADMINISTRATOR_ROLE,
    ),
    'restrict access' => TRUE,
  );
  $items['manage roles'] = array(
    'title' => t('Add roles'),
    'description' => t('Users may view group roles and add new roles if group default roles are overriden.'),
    'default role' => array(
      OG_ADMINISTRATOR_ROLE,
    ),
    'restrict access' => TRUE,
  );
  $items['manage permissions'] = array(
    'title' => t('Manage permissions'),
    'description' => t('Users may view the group permissions page and change permsissions if group default roles are overriden.'),
    'default role' => array(
      OG_ADMINISTRATOR_ROLE,
    ),
    'restrict access' => TRUE,
  );
  return $items;
}

/**
 * Get all the group admin menu items.
 */
function og_ui_get_group_admin($entity_type, $etid) {

  // We cache the values, as this function is also used as an access
  // callback, so we don't want to trigger it many times.
  $cache =& drupal_static(__FUNCTION__);
  if (isset($cache["{$entity_type}:{$etid}"])) {
    return $cache["{$entity_type}:{$etid}"];
  }

  // This function is also used as access callback for menu items, so we need to
  // make sure that the user supplied $etid is actually an integer.
  if (!ctype_digit($etid)) {
    return array();
  }

  // ensure we are invoking this on something worth doing it on
  $entity = entity_load_single($entity_type, $etid);
  if (!$entity) {

    // It is a non-existing group Id, giving up.
    return FALSE;
  }
  $entity_info = entity_get_info($entity_type);

  // if this isn't a group type, skip invoking admin modules
  if (empty($entity_info['entity keys']['bundle']) || !og_is_group_type($entity_type, $entity->{$entity_info['entity keys']['bundle']})) {
    $cache["{$entity_type}:{$etid}"] = FALSE;
    return FALSE;
  }
  $data = module_invoke_all('og_ui_get_group_admin', $entity_type, $etid);

  // Sort the results.
  uasort($data, 'drupal_sort_title');

  // Allow other modules to alter the menu items.
  $context = array(
    'entity_type' => $entity_type,
    'etid' => $etid,
  );
  drupal_alter('og_ui_get_group_admin', $data, $context);
  $cache["{$entity_type}:{$etid}"] = $data;
  return $data;
}

/**
 * Implements hook_og_ui_get_group_admin()
 */
function og_ui_og_ui_get_group_admin($group_type, $gid) {
  $items = array();
  $default_access = og_is_group_default_access($group_type, $gid);
  if (og_user_access($group_type, $gid, 'add user')) {
    $items['add_people'] = array(
      'title' => t('Add people'),
      'description' => t('Add group members.'),
      // The final URL will be "group/$group_type/$gid/admin/people/add-user".
      // @see og_ui_group_admin_overview().
      'href' => 'admin/people/add-user',
    );
  }
  if (og_user_access($group_type, $gid, 'manage members')) {
    $items['people'] = array(
      'title' => t('People'),
      'description' => t('Manage the group members.'),
      'href' => "admin/people",
    );
  }
  if (og_user_access($group_type, $gid, 'manage roles')) {
    $items['roles'] = array(
      'title' => !$default_access ? t('Roles') : t('Roles (read-only)'),
      'description' => !$default_access ? t('Manage the group roles.') : t('View the group roles.'),
      'href' => "admin/roles",
    );
  }
  if (og_user_access($group_type, $gid, 'manage permissions')) {
    $items['permissions'] = array(
      'title' => !$default_access ? t('Permissions') : t('Permissions (read-only)'),
      'description' => !$default_access ? t('Manage the group permissions.') : t('View the group permissions.'),
      'href' => "admin/permissions",
    );
  }
  return $items;
}

/**
 * Implements hook_migrate_api().
 */
function og_ui_migrate_api() {
  $migrations = array();
  if (db_table_exists('d6_og')) {
    $migrations['OgUiMigrateAddField'] = array(
      'class_name' => 'OgUiMigrateAddField',
    );
    $migrations['OgUiSetRoles'] = array(
      'class_name' => 'OgUiSetRoles',
    );
    foreach (node_type_get_names() as $bundle => $value) {
      $machine_name = 'OgUiPopulateField' . ucfirst($bundle);
      $migrations[$machine_name] = array(
        'class_name' => 'OgUiPopulateField',
        'bundle' => $bundle,
      );
    }
  }
  $api = array(
    'api' => 2,
    'migrations' => $migrations,
  );
  return $api;
}

Functions

Namesort descending Description
og_node_type_form_settings AJAX callback to attach the message type fields to the form.
og_ui_access_bundle Menu access; Check permissions per-bundle editing.
og_ui_access_bundle_role Menu access; Check permissions for role editing.
og_ui_access_entity_role Menu access; Check permissions for role editing - For a specific entity.
og_ui_access_group_permissions Menu access; Check access and validate values for group permissions page.
og_ui_admin_paths Implements hook_admin_paths().
og_ui_ctools_plugin_directory Implements hook_ctools_plugin_directory().
og_ui_field_access Implements hook_field_access().
og_ui_field_create_instance Implements hook_field_create_instance().
og_ui_field_delete_instance Implements hook_field_delete_instance().
og_ui_field_formatter_info Implement hook_field_formatter_info().
og_ui_field_formatter_settings_form Implements hook_field_formatter_settings_form().
og_ui_field_formatter_settings_summary Implements hook_field_formatter_settings_summary().
og_ui_field_formatter_view Implements hook_field_formatter_view().
og_ui_forms Implement hook_forms().
og_ui_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter().
og_ui_form_node_type_form_alter Implement hook_form_FORM_ID_alter().
og_ui_get_group_admin Get all the group admin menu items.
og_ui_menu Implements hook_menu().
og_ui_menu_bundle_roles_title_callback Title callback; Return the title for role or permission editing, based on context.
og_ui_menu_title_callback Menu callback; Return the title of a menu item based on the group title.
og_ui_migrate_api Implements hook_migrate_api().
og_ui_node_type_insert Implements hook_node_type_insert().
og_ui_node_type_save Add group and group content fields to new content types.
og_ui_node_type_update Implements hook_node_type_update().
og_ui_og_fields_info_alter Implements hook_og_fields_info_alter().
og_ui_og_permission Implement hook_og_permission().
og_ui_og_ui_get_group_admin Implements hook_og_ui_get_group_admin()
og_ui_og_user_access_alter Implements hook_og_user_access_alter().
og_ui_theme Implement hook_theme().
og_ui_user_access_group Menu access; Check if entity is a group, and user has permission.
og_ui_views_api Implements hook_views_api().