You are here

domain_integration_search_api.module in Domain Integration (Drupal 7) 7

Domain Integration Search API.

File

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

/**
 * @file
 * Domain Integration Search API.
 */

/**
 * Implements hook_search_api_alter_callback_info().
 *
 * Adds 2 filter callbacks: one for nodes and one for users.
 */
function domain_integration_search_api_search_api_alter_callback_info() {
  $callbacks['search_api_alter_node_domain_access'] = array(
    'name' => t('Node Domain access'),
    'description' => t('Apply Node Domain Access to the index. <strong>Note:</strong> This implementation strictly follows Domain\'s grant method. This means that nodes will be visible to the searching user if the node is tagged on the current domain or has the Send-To-All property checked. Further filtering (like current-domain only) should be done with FacetAPI. The searching user must have \'View published content\' permission.'),
    'class' => 'SearchApiAlterNodeDomainAccess',
  );
  $callbacks['search_api_alter_user_domain_access'] = array(
    'name' => t('User Domain access'),
    'description' => t('Apply User Domain Access to the index. <strong>Note:</strong> This implementation loosely follows Domain\'s grant method. This means that users will be visible if they are assigned to the current domain or a domain where the searching user also is assigned to. Further filtering (like current-domain only) should be done with FacetAPI. The searching user must have \'View users profiles\' permission.'),
    'class' => 'SearchApiAlterUserDomainAccess',
  );
  return $callbacks;
}

/**
 * Implements hook_search_api_query_alter().
 *
 * Adds a filter for the current domain.
 */
function domain_integration_search_api_search_api_query_alter(SearchApiQueryInterface $query) {
  $index = $query
    ->getIndex();
  $type = $index
    ->getEntityType();

  // Only add Domain Access if enabled.
  if (!empty($index->options['data_alter_callbacks']["search_api_alter_{$type}_domain_access"]['status'])) {
    try {
      global $user;
      _search_api_query_add_domain_access($user, $query, $type);
    } catch (SearchApiException $e) {
      watchdog_exception('domain_integration_search_api', $e);
    }
  }
}

/**
 * Adds a node access filter to a search query, if applicable.
 *
 * @param object $account
 *   The user object, who searches.
 * @param SearchApiQueryInterface $query
 *   The query to which a node access filter should be added, if applicable.
 * @param string $type
 *   (optional) The type of search – either "node" or "user". Defaults to
 *   "node".
 *
 * @throws SearchApiException
 *   If not all necessary fields are indexed on the index.
 */
function _search_api_query_add_domain_access($account, SearchApiQueryInterface $query, $type = 'node') {

  // Check whether the necessary fields are indexed.
  _search_api_query_add_domain_access_test_required_fields($account, $query, $type);

  // Test if searching user has access to entity_type.
  if (!_search_api_query_add_domain_access_test_user_permission($account, $query, $type)) {
    $query
      ->condition('domain_domain_id', FALSE);
  }
  else {

    // Get domains the user is assigned to.
    $user_domains = domain_get_user_domains($account);

    // Always add the current_domain.
    $current_domain = domain_get_domain();
    $current_domain = array(
      $current_domain['domain_id'] => $current_domain['domain_id'],
    );

    // Normalize to only unique values.
    $user_domain_ids = array_unique($user_domains + $current_domain);

    // Create an OR filter:
    //   - Add user domains as options
    //   - Add SendToAll for nodes.
    $domain_filter = $query
      ->createFilter('OR');

    // Add user domain's (including current domain) as optional filters.
    foreach ($user_domain_ids as $domain_id) {
      $domain_filter
        ->condition('domain_domain_id', $domain_id);
    }

    // If it's a Node, add SendToAll as optional filter.
    if ($type == 'node') {
      $domain_filter
        ->condition('domain_domain_site', TRUE);
    }

    // Add domain filter to Query.
    $query
      ->filter($domain_filter);
  }
}

/**
 * Tests it required fields for applying Domain Access are indexed.
 *
 * @param $account
 *   User object (not used, but still here for consistency).
 *
 * @param SearchApiQueryInterface $query
 *   SearchAPI Query object.
 *
 * @param string $type
 *   Can be either 'node' or 'user'.
 *
 * @throws SearchApiException
 *   Throws an exception if required fields are not found.
 *   Throws an exception if unsupported $type is passed in.
 */
function _search_api_query_add_domain_access_test_required_fields($account, SearchApiQueryInterface $query, $type = 'node') {

  // Check whether a supported type is passed in.
  if ($type !== 'node' && $type !== 'user') {
    throw new SearchApiException(t('Unsupported entity type @type.', array(
      $type,
    )));
  }

  // Check whether the necessary fields are indexed.
  $fields = $query
    ->getIndex()->options['fields'];

  // Create an array with required fields (hardcoded).
  $required = array(
    'domain_domain_id',
  );
  if ($type == 'node') {
    $required[] = 'domain_domain_site';
  }

  // Check if required fields are indexed. Throw error if not.
  foreach ($required as $field) {
    if (empty($fields[$field])) {
      $vars['@field'] = $field;
      $vars['@index'] = $query
        ->getIndex()->name;
      drupal_set_message(t('Required field @field not indexed on index @index. Could not perform access checks.', $vars), 'error');
      throw new SearchApiException(t('Required field @field not indexed on index @index. Could not perform access checks.', $vars));
    }
  }
}

/**
 * Test if searching user has access to entity_type.
 *
 * @param $account
 *   User object (not used, but still here for consistency).
 *
 * @param SearchApiQueryInterface $query
 *   SearchAPI Query object.
 *
 * @param string $type
 *   Can be either 'node' or 'user'.
 *
 * @return bool
 *   FALSE if no permission.
 *   defaults to TRUE.
 */
function _search_api_query_add_domain_access_test_user_permission($account, SearchApiQueryInterface $query, $type = 'node') {

  // Check general access permission (not on a per item base, but on a bundle/
  // entity_type base.
  if ($type == 'user' && !user_access('access user profiles', $account)) {
    return FALSE;
  }
  if ($type == 'node' && !user_access('access content', $account)) {
    return FALSE;
  }

  // Defaults to TRUE.
  return TRUE;
}

Functions

Namesort descending Description
domain_integration_search_api_search_api_alter_callback_info Implements hook_search_api_alter_callback_info().
domain_integration_search_api_search_api_query_alter Implements hook_search_api_query_alter().
_search_api_query_add_domain_access Adds a node access filter to a search query, if applicable.
_search_api_query_add_domain_access_test_required_fields Tests it required fields for applying Domain Access are indexed.
_search_api_query_add_domain_access_test_user_permission Test if searching user has access to entity_type.