You are here

redhen_relation.module in RedHen CRM 7

Redhen CRM Relation Module.

File

modules/redhen_relation/redhen_relation.module
View source
<?php

/**
 * @file
 * Redhen CRM Relation Module.
 */
define('REDHEN_RELATION_STATUS_FIELD', 'redhen_relation_status');
define('REDHEN_RELATION_ROLES_FIELD', 'redhen_relation_roles');
define('REDHEN_RELATION_AFFILIATION', 'redhen_affiliation');
define('REDHEN_RELATION_CONNECTION', 'redhen_connection');

/**
 * Implements hook_menu().
 */
function redhen_relation_menu() {
  $items = array();

  // Contact connections.
  $items['redhen/contact/%redhen_contact/connections'] = array(
    'title' => 'Connections',
    'page callback' => 'redhen_relation_connections_page',
    'page arguments' => array(
      2,
      'redhen_contact',
    ),
    'access callback' => 'redhen_relation_access',
    'access arguments' => array(
      'view',
      2,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => -5,
  );
  $items['redhen/contact/%redhen_contact/connections/add'] = array(
    'title' => 'Add Connection',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'redhen_relation_connection_form',
      2,
    ),
    'file' => 'includes/redhen_relation.forms.inc',
    'access callback' => 'redhen_relation_access',
    'access arguments' => array(
      'edit',
      2,
    ),
    'type' => MENU_LOCAL_ACTION,
  );
  $items['redhen/contact/%redhen_contact/connections/%relation/edit'] = array(
    'title' => 'Edit Connection',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'redhen_relation_connection_form',
      2,
      4,
    ),
    'file' => 'includes/redhen_relation.forms.inc',
    'access callback' => 'redhen_relation_entity_access',
    'access arguments' => array(
      'update',
      4,
    ),
    'type' => MENU_LOCAL_ACTION,
  );

  // Org connections.
  $items['redhen/org/%redhen_org/connections'] = array(
    'title' => 'Connections',
    'page callback' => 'redhen_relation_connections_page',
    'page arguments' => array(
      2,
      'redhen_org',
    ),
    'access callback' => 'redhen_relation_access',
    'access arguments' => array(
      'view',
      2,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => -5,
  );
  $items['redhen/org/%redhen_org/connections/add'] = array(
    'title' => 'Add Connection',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'redhen_relation_connection_form',
      2,
    ),
    'file' => 'includes/redhen_relation.forms.inc',
    'access callback' => 'redhen_relation_access',
    'access arguments' => array(
      'edit',
      2,
    ),
    'type' => MENU_LOCAL_ACTION,
  );
  $items['redhen/relation/autocomplete/%'] = array(
    'title' => 'Autocomplete for RedHen Relations',
    'page callback' => 'redhen_relation_autocomplete',
    'page arguments' => array(
      3,
      4,
      5,
      6,
      7,
    ),
    // @todo Set permissions
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function redhen_relation_menu_alter(&$items) {

  // Relation_ui menu overrides.
  // Use our own page title callback for relation/X pages.
  $items['relation/%relation']['title callback'] = 'redhen_relation_page_title';
  $items['relation/%relation']['access callback'] = 'redhen_relation_entity_access';
  $items['relation/%relation']['access arguments'] = array(
    'view',
    1,
  );
  $items['relation/%relation/edit']['access callback'] = 'redhen_relation_entity_access';
  $items['relation/%relation/edit']['access arguments'] = array(
    'update',
    1,
  );
  $items['relation/%relation/delete']['access callback'] = 'redhen_relation_entity_access';
  $items['relation/%relation/delete']['access arguments'] = array(
    'delete',
    1,
  );
}

/**
 * Relation entity access call back. Replaces the default relation entity
 * access and menu access callbacks.
 *
 * @param string $op
 *   Operation. One of view, update, create or delete.
 * @param array $entity
 *   Relation entity.
 *
 * @return bool
 *   Access grant.
 */
function redhen_relation_entity_access($op, $entity) {
  global $user;

  // If admin, skip other checks.
  if (user_access('administer relations')) {
    return TRUE;
  }
  $permission = FALSE;
  switch ($op) {
    case 'view':
      $permission = 'access relations';
      $relation_permission = 'view_relation';
      break;
    case 'create':
      $permission = 'create relations';
      $relation_permission = 'edit_relation';
      break;
    case 'update':
      $relation_permission = 'edit_relation';
      $permission = 'edit relations';
      break;
    case 'delete':
      $relation_permission = 'delete_relation';
      $permission = 'delete relations';
      break;
  }

  // Get the default access permission based on the $op.
  $user_access = user_access($permission);

  // Check that this is a relation we care about.
  if (array_key_exists('relation_type', $entity) && $entity->relation_type == REDHEN_RELATION_AFFILIATION) {

    // Check for Org relation permissions.
    $permissions = redhen_relation_role_get_permissions($user);
    $relation = relation_get_endpoints($entity, 'redhen_org');
    $org = $relation ? current(current($relation)) : array();
    if ($relation && isset($permissions[$org->org_id][$relation_permission]) && $permissions[$org->org_id][$relation_permission] !== 0) {
      $user_access = TRUE;
    }
  }
  return $user_access;
}

/**
 * Custom title callback for relation pages.
 */
function redhen_relation_page_title($relation) {
  $endpoints = field_get_items('relation', $relation, 'endpoints');
  $redhen_entities = array(
    'redhen_contact',
    'redhen_org',
  );
  if (!in_array($endpoints[0]['entity_type'], $redhen_entities) || !in_array($endpoints[1]['entity_type'], $redhen_entities)) {
    return relation_ui_page_title($relation);
  }
  $relation_type = relation_type_load($relation->relation_type);
  foreach ($endpoints as $endpoint) {
    if ($endpoint['r_index'] == 0) {
      $label1 = entity_load_single($endpoint['entity_type'], $endpoint['entity_id'])
        ->label();
    }
    if ($endpoint['r_index'] == 1) {
      $label2 = entity_load_single($endpoint['entity_type'], $endpoint['entity_id'])
        ->label();
    }
  }
  return t('@type between @label1 and @label2', array(
    '@type' => relation_get_type_label($relation_type),
    '@label1' => $label1,
    '@label2' => $label2,
  ));
}

/**
 * Implements hook_permission().
 */
function redhen_relation_permission() {
  return array(
    'view redhen org connections' => array(
      'title' => t('Access RedHen Org Connections'),
      'description' => t('View the connections for an organization.'),
    ),
    'view redhen contact connections' => array(
      'title' => t('Access RedHen Contact Connections'),
      'description' => t('View the connections for a contact.'),
    ),
    'edit redhen org connections' => array(
      'title' => t('Manage RedHen Org Connections'),
      'description' => t('Add and edit connections for an organization.'),
    ),
    'edit redhen contact connections' => array(
      'title' => t('Manage RedHen Contact Connections'),
      'description' => t('Add and edit connections for a contact.'),
    ),
    'delete redhen org connections' => array(
      'title' => t('Delete RedHen Org Connections'),
      'description' => t('Delete connections for an organization.'),
    ),
    'delete redhen contact connections' => array(
      'title' => t('Delete RedHen Contact Connections'),
      'description' => t('Delete connections for a contact.'),
    ),
    'administer relation roles' => array(
      'title' => t('Administer redhen relation roles'),
      'description' => t('Administer redhen relation roles.'),
    ),
  );
}

/**
 * Access callback for viewing and managing relations on the RedHen connection
 * pages.
 *
 * @param string $op
 *   Operation.
 * @param $entity
 *   Entity.
 * @param $account
 *   User account to check permission for.
 * @param $entity_type
 *   The type of entity being checked.
 *
 * @return bool
 *   Access grant.
 */
function redhen_relation_access($op, $entity = NULL, $account = NULL, $entity_type = NULL) {
  global $user;
  $account = isset($account) ? $account : $user;
  $permissions = redhen_relation_role_get_permissions($account);
  $entity_type = $entity_type ? $entity_type : $entity
    ->entityType();
  $type = $entity_type == 'redhen_contact' ? 'contact' : 'org';
  if (entity_access($op, $entity_type, $entity) && user_access("{$op} redhen {$type} connections")) {
    return TRUE;
  }
  if (($op == 'edit' || $op == 'view') && $entity_type == 'redhen_org' && isset($permissions[$entity->org_id]) && $permissions[$entity->org_id]['add_connection'] !== 0) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Access callback for viewing and managing relations roles.
 *
 * @param sring $op
 *   Operation.
 * @param null $entity
 *   Entity.
 * @param null $account
 *   Account.
 * @param null $entity_type
 *   Entity type.
 *
 * @return bool
 *   Access grant.
 */
function redhen_relation_role_access($op, $entity = NULL, $account = NULL, $entity_type = NULL) {

  // TODO: Is this ever not true?
  if ($op == 'view') {
    return TRUE;
  }
  else {
    return user_access('administer relation roles', $account);
  }
}

/**
 * Return relation role permission for a given account and permission.
 *
 * @param object $account
 *   Account.
 *
 * @return array
 *   Permissions array.
 */
function redhen_relation_role_get_permissions($account) {
  $return =& drupal_static(__FUNCTION__);
  if (!isset($return[$account->uid])) {
    $return_permissions = array();
    $contact = redhen_contact_load_by_user($account);
    if ($contact) {
      $related = redhen_relation_relations($contact, REDHEN_RELATION_AFFILIATION, TRUE);
      $relations = relation_load_multiple(array_keys($related));
      foreach ($relations as $relation_id => $relation) {
        $relation_wrapper = entity_metadata_wrapper('relation', $relation);

        // Loop through all roles on this relation.
        $redhen_relation_roles = $relation_wrapper->redhen_relation_roles
          ->value();
        foreach ($redhen_relation_roles as $redhen_relation_role) {

          // Role needs to exist.
          if ($redhen_relation_role) {
            $redhen_relation_role_wrapper = entity_metadata_wrapper('redhen_relation_role', $redhen_relation_role);
            $org_id = $related[$relation_id][0]->org_id;
            $permissions = $redhen_relation_role_wrapper->permissions
              ->value();

            // Add all permissions from all roles on this relation.
            foreach ($permissions as $permission => $value) {

              // Add permissions if set.
              if ($value) {
                $return_permissions[$org_id][$permission] = $value;
              }
            }
          }
        }
      }
    }
    $return[$account->uid] = $return_permissions;
  }
  return $return[$account->uid];
}

/**
 * Page callback for listing connections.
 *
 * @param RedhenContact|RedhenOrg $entity
 *   Entity.
 *
 * @return array|null|string
 *   Connections list or message.
 */
function redhen_relation_connections_page($entity) {
  $related = redhen_relation_relations($entity);
  if (!empty($related)) {
    $header = array(
      'connection' => t('Connection'),
      'type' => t('Type'),
      'name' => t('Name'),
      'role' => t('Roles'),
      'status' => t('Status'),
      'created' => t('Created'),
      'author' => t('Author'),
    );
    if ($entity
      ->entityType() == 'redhen_org') {
      $header['primary'] = t('Primary contact');
    }
    $header['operations'] = array(
      'data' => t('Operations'),
    );
    $destination = drupal_get_destination();
    foreach ($related as $relation_id => $related_entities) {
      $relation = relation_load($relation_id);
      $relation_wrapper = entity_metadata_wrapper('relation', $relation);
      $relation_uri = entity_uri('relation', $relation);
      $reversed = FALSE;
      $endpoints = field_get_items('relation', $relation, 'endpoints');
      foreach ($endpoints as $endpoint) {
        if ($endpoint['entity_type'] == $entity
          ->entityType() && $endpoint['r_index']) {
          $reversed = TRUE;
          break;
        }
      }
      foreach ($related_entities as $related_entity) {
        $object_label = entity_label($related_entity
          ->entityType(), $related_entity);
        $object_uri = entity_uri($related_entity
          ->entityType(), $related_entity);
        $author = user_load($relation->uid);
        if (strpos($relation->relation_type, 'redhen_') === FALSE) {
          $active = t('NA', array(), array(
            'context' => 'redhen_relation',
          ));
        }
        else {
          $items = field_get_items('relation', $relation, REDHEN_RELATION_STATUS_FIELD);
          $active = $items[0]['value'] ? t('Active', array(), array(
            'context' => 'redhen_relation',
          )) : t('Inactive', array(), array(
            'context' => 'redhen_relation',
          ));
        }
        $related_entity_info = entity_get_info($related_entity
          ->entityType());

        // Get roles of the relation.
        $relation_role_names = array();
        if (isset($relation_wrapper->{REDHEN_RELATION_ROLES_FIELD})) {
          $relation_roles = $relation_wrapper->{REDHEN_RELATION_ROLES_FIELD}
            ->value();
          foreach ($relation_roles as $relation_role) {
            if (!empty($relation_role)) {
              $relation_role_names[] = $relation_role
                ->label();
            }
          }
          sort($relation_role_names);
        }
        $relation_role_names = implode(', ', $relation_role_names);
        $data = array(
          'connection' => array(
            'data' => array(
              '#markup' => relation_get_type_label($relation, $reversed),
            ),
          ),
          'type' => $related_entity_info['label'],
          'name' => array(
            'data' => array(
              '#type' => 'link',
              '#title' => $object_label,
              '#href' => $object_uri['path'],
            ),
          ),
          'role' => $relation_role_names,
          'active' => $active,
          'created' => date('m/d/Y', $relation->created),
          'author' => $author->name,
        );
        $row_classes = array();

        // Add primary contact handling for redhen_orgs and contacts.
        if ($entity
          ->entityType() == 'redhen_org' && $related_entity
          ->entityType() == 'redhen_contact') {
          if ($entity->primary_contact_id !== $related_entity->contact_id) {
            $entity_uri = entity_uri('redhen_org', $entity);
            $data['primary'] = array(
              'data' => array(
                '#type' => 'link',
                '#title' => t('set as primary'),
                '#href' => $entity_uri['path'] . '/primary/' . $related_entity->contact_id,
                '#options' => array(
                  'query' => array(
                    $destination,
                  ),
                ),
              ),
            );
          }
          else {
            $data['primary'] = t('Primary');
            $row_classes[] = 'primary_contact';
          }
        }
        elseif ($entity
          ->entityType() == 'redhen_org') {
          $data[] = t('NA', array(), array(
            'context' => 'redhen_relation',
          ));
        }

        // Build a list of all the accessible operations for the current relation.
        $ops = array();
        if (redhen_relation_entity_access('view', $relation)) {
          $ops['view'] = array(
            'title' => t('view'),
            'href' => $relation_uri['path'],
          );
        }
        if (redhen_relation_entity_access('update', $relation)) {
          $ops['edit'] = array(
            'title' => t('edit'),
            'href' => $relation_uri['path'] . '/edit',
            'query' => $destination,
          );
        }
        if (redhen_relation_entity_access('delete', $relation)) {
          $ops['delete'] = array(
            'title' => t('delete'),
            'href' => $relation_uri['path'] . '/delete',
            'query' => $destination,
          );
        }
        if (count($ops) > 1) {

          // Render an unordered list of operations links.
          $data['operations'] = array(
            'data' => array(
              '#theme' => 'links__node_operations',
              '#links' => $ops,
              '#attributes' => array(
                'class' => array(
                  'links',
                  'inline',
                ),
              ),
            ),
          );
        }
        elseif (!empty($ops)) {

          // Render the first and only operation as a link.
          $link = reset($ops);
          $data['operations'] = array(
            'data' => array(
              '#type' => 'link',
              '#title' => $link['title'],
              '#href' => $link['href'],
              '#options' => isset($link['query']) ? array(
                'query' => $link['query'],
              ) : array(),
            ),
          );
        }
        else {
          unset($header['operations']);
        }
        $rows[$relation_id] = array(
          'data' => $data,
          'class' => $row_classes,
        );
      }
    }
    return array(
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    );
  }
  else {
    return t('%name has no connections.', array(
      '%name' => $entity
        ->label(),
    ));
  }
}

/**
 * Return entities related to a given entity excluding self and duplicates.
 *
 * @param object $entity
 * @param string $relation_types
 *   Filter to given relation types if provided.
 * @param bool $active
 *   Optionally limit relations to those that are active.
 *
 * @return array
 *   Keyed by the relation id which contains an array of entities.
 *   Array (
 *     1 => array($entity1, $entity2),
 *     3 => array($entity3, $entity4)
 *   )
 */
function redhen_relation_relations($entity, $relation_types = array(), $active = FALSE) {

  // Backwards compatibility:
  if ($relation_types && !is_array($relation_types)) {
    $relation_types = array(
      $relation_types,
    );
  }
  $related_entities =& drupal_static(__FUNCTION__ . $entity
    ->entityType() . $entity
    ->internalIdentifier() . implode('-', $relation_types) . $active, array());
  if ($related_entities) {
    return $related_entities;
  }
  $query = relation_query($entity
    ->entityType(), $entity
    ->internalIdentifier());
  if ($relation_types) {
    $query
      ->propertyCondition('relation_type', $relation_types, 'IN');
  }

  // Optionally limit to only active relations.
  if ($active) {
    $query
      ->fieldCondition(REDHEN_RELATION_STATUS_FIELD, 'value', TRUE);
  }

  // This hideous hack is to avoid triggering the node access system which we
  // need to to in order to avoid infinite recursion in
  // redhen_org_group:node_grants().
  // time came from http://drupal.stackexchange.com/questions/3927/how-to-bypass-node-access-when-using-entityfieldquery
  // ticket pointing to issue http://drupal.org/node/1541236.
  $query
    ->addMetaData('account', user_load(1));
  $query
    ->addTag('redhen_relation');
  $results = $query
    ->execute();
  if ($results) {
    $relations = relation_load_multiple(array_keys($results));
    foreach ($relations as $relation) {
      $rid = entity_id('relation', $relation);
      $related_entities[$rid] = array();

      // To make sure duplicates of $entity get included in object list.
      $duplicate = FALSE;
      $endpoints = field_get_items('relation', $relation, 'endpoints');
      foreach ($endpoints as $endpoint) {

        // Add all entities that aren't this entity or duplicates, unless the
        // relation only has this entity as endpoint ($relation->arity = 1).
        if ($relation->arity > 1 && $endpoint['entity_type'] == $entity
          ->entityType() && $endpoint['entity_id'] == $entity
          ->internalIdentifier() && $duplicate == FALSE) {
          $duplicate = TRUE;
        }
        else {
          $object_entities = entity_load($endpoint['entity_type'], array(
            $endpoint['entity_id'],
          ));
          $related_entities[$rid][] = reset($object_entities);
        }
      }
    }
  }
  return $related_entities;
}

/**
 * Return a list of entities the given entity can be associated with.
 *
 * @param object $entity
 *   Entity.
 * @param string $entity_type_to_relate
 *   Entity type.
 * @param string $relation_type
 *   Relation type.
 * @param string $search
 *   Search string.
 * @param int $limit
 *   Limit.
 *
 * @return array
 *   Available entities.
 */
function redhen_relation_get_available_entities($entity, $entity_type_to_relate, $relation_type, $search = '', $limit = 0) {
  $entities = array();
  if (!in_array($entity_type_to_relate, array(
    'redhen_contact',
    'redhen_org',
  ))) {
    return $entities;
  }
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', $entity_type_to_relate)
    ->propertyCondition('redhen_state', REDHEN_STATE_ACTIVE);

  // Exclude existing relationships.
  $existing = redhen_relation_relations($entity, $relation_type);
  if (!empty($existing)) {
    $info = entity_get_info($entity_type_to_relate);
    $id_key = $info['entity keys']['id'];
    $to_exclude = array();
    foreach ($existing as $relation_id => $related_entities) {
      foreach ($related_entities as $related_entity) {
        $to_exclude[] = entity_id($related_entity
          ->entityType(), $related_entity);
      }
    }
    $query
      ->propertyCondition($id_key, $to_exclude, 'NOT IN');
  }

  // Keyword search.
  if ($search != '') {

    // If we're searching for redhen_contacts, set a query tag so we can alter
    // the fields that are searched in redhen_contact.
    if ($entity_type_to_relate == 'redhen_contact') {
      $query
        ->addTag('redhen_contact_label');
    }
    $query
      ->propertyCondition('label', $search, 'CONTAINS');
  }
  if ($limit > 0) {
    $query
      ->range(0, $limit);
  }
  if ($result = $query
    ->execute()) {
    $entities = entity_load($entity_type_to_relate, array_keys($result[$entity_type_to_relate]));
  }
  return $entities;
}

/**
 * Autocomplete callback for listing available entities for a relation type.
 */
function redhen_relation_autocomplete($relation_type = '', $entity_type_to_relate = '', $entity_type = '', $entity_id = '', $search = '') {
  $options = array();
  if (!empty($relation_type) && !empty($entity_type_to_relate) && !empty($entity_type) && !empty($entity_id)) {
    $entity = entity_load_single($entity_type, $entity_id);
    $available_entities = redhen_relation_get_available_entities($entity, $entity_type_to_relate, $relation_type, $search, 10);
    foreach ($available_entities as $available_entity) {
      $entity_id = $available_entity
        ->internalIdentifier();
      $entity_label = $available_entity
        ->label();
      $options[check_plain($entity_label) . ' (' . $entity_id . ')'] = check_plain($entity_label);
    }
  }
  drupal_json_output($options);
}

/**
 * Implements hook_entity_update().
 */
function redhen_relation_entity_update($entity, $entity_type) {

  //React to entity updates that require connection states to be changed
  if ($entity_type == 'redhen_contact' || $entity_type == 'redhen_org') {

    // If the entity is archived, we want to archive their relations.
    if ($entity->redhen_state != REDHEN_STATE_ACTIVE) {

      // Get all the relations associated with this entitity.
      $query = relation_query($entity_type, $entity
        ->internalIdentifier());

      // this hideous hack is to avoid triggering the node access system which we
      // need to to in order to avoid infinite recursion in
      // redhen_org_group:node_grants().
      // time came from http://drupal.stackexchange.com/questions/3927/how-to-bypass-node-access-when-using-entityfieldquery
      // ticket pointing to issue http://drupal.org/node/1541236.
      $query
        ->addMetaData('account', user_load(1));
      $query
        ->addTag('redhen_relation');
      $results = $query
        ->execute();
      if ($results) {
        $relations = relation_load_multiple(array_keys($results));
        foreach ($relations as $relation) {
          $relation->{REDHEN_RELATION_STATUS_FIELD}[LANGUAGE_NONE][0]['value'] = 0;
          relation_save($relation);
        }
      }
    }
  }
}

/**
 * Implements hook_entity_info().
 */
function redhen_relation_entity_info() {
  $entities = array(
    'redhen_relation_role' => array(
      'label' => t('RedHen Relation Role'),
      'plural label' => t('RedHen Relation Roles'),
      'controller class' => 'RedhenRelationRoleEntityController',
      'entity class' => 'RedhenRelationRole',
      'base table' => 'redhen_relation_role',
      'fieldable' => FALSE,
      'entity keys' => array(
        'id' => 'redhen_relation_role_id',
        'label' => 'label',
        'name' => 'name',
      ),
      'bundles' => array(
        'redhen_relation_role' => array(
          'label' => 'RedHen Relation Role',
        ),
      ),
      'admin ui' => array(
        'path' => 'admin/structure/redhen/relation_roles',
        'file' => 'redhen_relation_role.forms.inc',
        'file path' => drupal_get_path('module', 'redhen_relation') . '/includes',
        'controller class' => 'RedhenRelationRoleUIController',
      ),
      'token type' => 'redhen_relation_role',
      'module' => 'redhen_relation',
      'access callback' => 'redhen_relation_role_access',
      'exportable' => TRUE,
    ),
  );
  return $entities;
}

/**
 * Implements hook_entity_info_alter().
 */
function redhen_relation_entity_info_alter(&$entity_info) {

  // Add teaser view mode to relations.
  $entity_info['relation']['view modes']['teaser'] = array(
    'label' => t('Teaser'),
    'custom settings' => TRUE,
  );
  $entity_info['relation']['access callback'] = 'redhen_relation_entity_access';
}

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

/**
 * Return only relation types between RedHen entities.
 *
 * Wrapper around relation_get_available_types().
 *
 * @param RedhenContact|RedhenOrg $entity_type
 *   redhen_contact or redhen_org
 * @param string $bundle
 *   Bundle.
 *
 * @return array
 *   Available types.
 */
function redhen_relation_get_available_types($entity_type, $bundle) {
  $relation_types = relation_get_available_types($entity_type, $bundle, 'both');
  foreach ($relation_types as $key => $relation_type) {
    $redhen_types = array(
      'redhen_contact',
      'redhen_org',
    );
    foreach ($relation_type->source_bundles as $source_bundle) {
      list($source_entity_type) = explode(':', $source_bundle);
      if (!in_array($source_entity_type, $redhen_types)) {
        unset($relation_types[$key]);
        break;
      }
    }
    foreach ($relation_type->target_bundles as $target_bundle) {
      list($target_entity_type) = explode(':', $target_bundle);
      if (!in_array($target_entity_type, $redhen_types)) {
        unset($relation_types[$key]);
        break;
      }
    }
  }
  return $relation_types;
}

/**
 * Returns whether a relation roles name already exists.
 */
function redhen_relation_role_name_exists($name, $element, &$form_state) {
  $relation_role = entity_load('redhen_relation_role', array(
    $name,
  ));
  $relation_role = current($relation_role);
  if ($relation_role && $relation_role->redhen_relation_role_id != $form_state['redhen_relation_role']->redhen_relation_role_id) {
    return TRUE;
  }
}

/**
 * Returns permissions.
 *
 * @return array
 *   Permissions array.
 */
function redhen_relation_role_permissions() {
  $roles = module_invoke_all('redhen_relation_role_permissions');
  return $roles;
}

/**
 * Implements hook_redhen_relation_role_permissions().
 */
function redhen_relation_redhen_relation_role_permissions() {
  $roles = array(
    'add_connection' => array(
      'label' => 'Add Connection',
    ),
    'view_relation' => array(
      'label' => 'View Relation',
    ),
    'edit_relation' => array(
      'label' => 'Edit Relation',
    ),
    'delete_relation' => array(
      'label' => 'Delete Relation',
    ),
  );
  return $roles;
}

Functions

Namesort descending Description
redhen_relation_access Access callback for viewing and managing relations on the RedHen connection pages.
redhen_relation_autocomplete Autocomplete callback for listing available entities for a relation type.
redhen_relation_connections_page Page callback for listing connections.
redhen_relation_entity_access Relation entity access call back. Replaces the default relation entity access and menu access callbacks.
redhen_relation_entity_info Implements hook_entity_info().
redhen_relation_entity_info_alter Implements hook_entity_info_alter().
redhen_relation_entity_update Implements hook_entity_update().
redhen_relation_get_available_entities Return a list of entities the given entity can be associated with.
redhen_relation_get_available_types Return only relation types between RedHen entities.
redhen_relation_menu Implements hook_menu().
redhen_relation_menu_alter Implements hook_menu_alter().
redhen_relation_page_title Custom title callback for relation pages.
redhen_relation_permission Implements hook_permission().
redhen_relation_redhen_relation_role_permissions Implements hook_redhen_relation_role_permissions().
redhen_relation_relations Return entities related to a given entity excluding self and duplicates.
redhen_relation_role_access Access callback for viewing and managing relations roles.
redhen_relation_role_get_permissions Return relation role permission for a given account and permission.
redhen_relation_role_name_exists Returns whether a relation roles name already exists.
redhen_relation_role_permissions Returns permissions.
redhen_relation_views_api Implements hook_views_api().

Constants