You are here

protected function PremiumContent::addPremiumAccess in Node Option Premium 8

Adds a premium access filter to a search query, if applicable.

Parameters

\Drupal\search_api\Query\QueryInterface $query: The query to which a node access filter should be added, if applicable.

\Drupal\Core\Session\AccountInterface $account: The user for whom the search is executed.

Throws

\Drupal\search_api\SearchApiException Thrown if not all necessary fields are indexed on the index.

1 call to PremiumContent::addPremiumAccess()
PremiumContent::preprocessSearchQuery in src/Plugin/search_api/processor/PremiumContent.php
Preprocesses a search query.

File

src/Plugin/search_api/processor/PremiumContent.php, line 176

Class

PremiumContent
Adds premium information to the indexes.

Namespace

Drupal\nopremium\Plugin\search_api\processor

Code

protected function addPremiumAccess(QueryInterface $query, AccountInterface $account) {

  // Don't do anything if the user can access all premium content.
  if ($account
    ->hasPermission('view full premium content of any type')) {
    return;
  }

  // Gather the affected datasources, grouped by entity type, as well as the
  // unaffected ones.
  $affected_datasources = [];
  $unaffected_datasources = [];
  foreach ($this->index
    ->getDatasources() as $datasource_id => $datasource) {
    if ($datasource
      ->getEntityTypeId() === 'node') {
      $affected_datasources['node'][] = $datasource_id;
    }
    else {
      $unaffected_datasources[] = $datasource_id;
    }
  }

  // The filter structure we want looks like this:
  // @code
  //   [belongs to other datasource]
  //   OR
  //   (
  //     [is enabled (or was created by the user, if applicable)]
  //     AND
  //     [grants view access to one of the user's gid/realm combinations]
  //   )
  // @endcode
  // If there are no "other" datasources, we don't need the nested OR,
  // however, and can add the inner conditions directly to the query.
  if ($unaffected_datasources) {
    $outer_conditions = $query
      ->createConditionGroup('OR', [
      'content_access',
    ]);
    $query
      ->addConditionGroup($outer_conditions);
    foreach ($unaffected_datasources as $datasource_id) {
      $outer_conditions
        ->addCondition('search_api_datasource', $datasource_id);
    }
    $access_conditions = $query
      ->createConditionGroup('AND');
    $outer_conditions
      ->addConditionGroup($access_conditions);
  }
  else {
    $access_conditions = $query;
  }

  // If the user does not have the permission to see any content at all, deny
  // access to all items from affected datasources.
  if (!$affected_datasources) {

    // If there were "other" datasources, the existing filter will already
    // remove all results of node or comment datasources. Otherwise, we should
    // not return any results at all.
    if (!$unaffected_datasources) {
      $query
        ->abort($this
        ->t('You have no access to any results in this search.'));
    }
    return;
  }

  // Authors of premium nodes may always view their own nodes.
  $premium_conditions = $query
    ->createConditionGroup('OR');
  if ($account
    ->isAuthenticated()) {
    $author_conditions = $query
      ->createConditionGroup('OR');
    foreach ($affected_datasources as $entity_type => $datasources) {
      foreach ($datasources as $datasource_id) {
        if ($entity_type == 'node') {
          $author_field = $this
            ->findField($datasource_id, 'uid', 'integer');
          if ($author_field) {
            $author_conditions
              ->addCondition($author_field
              ->getFieldIdentifier(), $account
              ->id());
          }
        }
      }
    }
    $premium_conditions
      ->addConditionGroup($author_conditions);
  }
  foreach (NodeType::loadMultiple() as $type) {
    $type_id = $type
      ->id();
    if (!$account
      ->hasPermission("view full {$type_id} premium content")) {

      // User may only view non-premium nodes of this type.
      $node_type_conditions = $query
        ->createConditionGroup('AND');
      $node_type_conditions
        ->addCondition('type', $type_id);
      $node_type_conditions
        ->addCondition('premium', FALSE);
      $premium_conditions
        ->addConditionGroup($node_type_conditions);
    }
    else {
      $premium_conditions
        ->addCondition('type', $type_id);
    }
  }
  $access_conditions
    ->addConditionGroup($premium_conditions);
}