adva-8.x-1.0-rc9/src/Plugin/search_api/processor/AdvancedAccess.php

src/Plugin/search_api/processor/AdvancedAccess.php
<?php

namespace Drupal\adva\Plugin\search_api\processor;

use Drupal\adva\Plugin\adva\Manager\AccessConsumerManagerInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\LoggerTrait;
use Drupal\search_api\Plugin\search_api\datasource\ContentEntity;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Processor\ProcessorProperty;
use Drupal\search_api\Query\QueryInterface;
use Drupal\search_api\SearchApiException;
use Drupal\user\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Adds advanced access checks to entities.
 *
 * @SearchApiProcessor(
 *   id = "advanced_access",
 *   label = @Translation("Advanced access control"),
 *   description = @Translation("Adds advanced access checks to entities."),
 *   stages = {
 *     "add_properties" = 0,
 *     "pre_index_save" = -10,
 *     "preprocess_query" = -30,
 *   },
 * )
 */
class AdvancedAccess extends ProcessorPluginBase {

  use LoggerTrait;

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection|null
   */
  protected $database;

  /**
   * The current_user service used by this plugin.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface|null
   */
  protected $currentUser;

  /**
   * The consumer Manager used by this plugin.
   *
   * @var \Drupal\Core\Session\AccessConsumerManagerInterface|null
   */
  protected $consumerManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    /** @var static $processor */
    $processor = parent::create($container, $configuration, $plugin_id, $plugin_definition);

    $processor->setLogger($container->get('logger.channel.search_api'));
    $processor->setDatabase($container->get('database'));
    $processor->setCurrentUser($container->get('current_user'));
    $processor->setAccessConsumerManager($container->get('plugin.manager.adva.consumer'));

    return $processor;
  }

  /**
   * Retrieves the database connection.
   *
   * @return \Drupal\Core\Database\Connection
   *   The database connection.
   */
  public function getDatabase() {
    return $this->database ?: \Drupal::database();
  }

  /**
   * Sets the database connection.
   *
   * @param \Drupal\Core\Database\Connection $database
   *   The new database connection.
   *
   * @return $this
   */
  public function setDatabase(Connection $database) {
    $this->database = $database;
    return $this;
  }

  /**
   * Retrieves the current user.
   *
   * @return \Drupal\Core\Session\AccountProxyInterface
   *   The current user.
   */
  public function getCurrentUser() {
    return $this->currentUser ?: \Drupal::currentUser();
  }

  /**
   * Sets the current user.
   *
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current user.
   *
   * @return $this
   */
  public function setCurrentUser(AccountProxyInterface $current_user) {
    $this->currentUser = $current_user;
    return $this;
  }

  /**
   * Sets the access consumer manager service.
   *
   * @param \Drupal\Core\Session\AccessConsumerManagerInterface $manager
   *   The current service instance.
   */
  public function setAccessConsumerManager(AccessConsumerManagerInterface $manager) {
    $this->consumerManager = $manager;
  }

  /**
   * Retrieves the Access consumer manager service.
   *
   * @return \Drupal\Core\Session\AccessConsumerManagerInterface
   *   The current service instance.
   */
  public function getAccessConsumerManager() {
    return $this->consumerManager;
  }

  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
    $properties = [];

    if (!$datasource) {
      $definition = [
        'label' => $this->t('Entity access information'),
        'description' => $this->t('Data needed to apply entity access via Advanced Access.'),
        'type' => 'string',
        'processor_id' => $this->getPluginId(),
        'hidden' => TRUE,
        'is_list' => TRUE,
      ];
      $properties['search_api_adva_grants'] = new ProcessorProperty($definition);
    }

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function addFieldValues(ItemInterface $item) {

    $entity = $item->getOriginalObject()->getValue();

    if (!($entity instanceof EntityInterface)) {
      // We don't process items which are not entites.
      return;
    }

    $consumer = $this->getAccessConsumerManager()->getConsumerForEntityType($entity->getEntityType());
    if (!$consumer) {
      // There is no supported adva consumer. Nothing to do for this item.
      return;
    }

    $all_grants = $consumer->getAccessRecords($entity);
    $view_grants = [];
    foreach ($all_grants as $grant) {
      if ($grant["grant_view"] === 1) {
        $view_grants[] = $consumer->getPluginId() . ":" . $grant["realm"] . ":" . $grant["gid"];
      }
    }

    $fields = $item->getFields();
    $fields = $this->getFieldsHelper()
      ->filterForPropertyPath($fields, NULL, 'search_api_adva_grants');
    foreach ($fields as $field) {
      // Append the grant list to each grant field.
      foreach ($view_grants as $grant) {
        $field->addValue($grant);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function preIndexSave() {
    $field = $this->ensureField(NULL, 'search_api_adva_grants', 'string');
    $field->setHidden();
  }

  /**
   * Get a valid user instance for a given query.
   *
   * If the query specifies a user id use that id, other wise, use the currently
   * logged in user.
   *
   * @param \Drupal\search_api\Query\QueryInterface $query
   *   Search API Query instance.
   *
   * @return \Drupal\Core\Session\AccountInterface|null
   *   Valid account instance if one exists.
   */
  public function validateUser(QueryInterface $query) {
    if (!$query->getOption('search_api_bypass_access')) {
      $account = $query->getOption('search_api_access_account', $this->getCurrentUser());
      if (is_numeric($account)) {
        $account = User::load($account);
      }
      if ($account instanceof AccountInterface) {
        return $account;
      }
      else {
        $account = $query->getOption('search_api_access_account', $this->getCurrentUser());
        if ($account instanceof AccountInterface) {
          $account = $account->id();
        }
        if (!is_scalar($account)) {
          $account = var_export($account, TRUE);
        }
        $this->getLogger()->warning('An illegal user UID was given for node access: @uid.', ['@uid' => $account]);
        // We want to user the current user instance, to prevent invalid access.
        return $this->currentUser();
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function preprocessSearchQuery(QueryInterface $query) {
    $account = $this->validateUser($query);
    // If a invalid user is provided, no filtering will happen.
    if ($account) {
      try {
        $this->addAccessCondition($query, $account);
      }
      catch (SearchApiException $e) {
        $this->logException($e);
      }
    }
  }

  /**
   * Adds access filters to a search query, if applicable.
   *
   * @param \Drupal\search_api\Query\QueryInterface $query
   *   The query to which a node access filter should be added, if applicable.
   * @param \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.
   */
  protected function addAccessCondition(QueryInterface $query, AccountInterface $account) {
    $field = $this->findField(NULL, 'search_api_adva_grants', 'string');

    if (!$field) {
      return;
    }

    $access_conditions = $query->createConditionGroup('OR', ['advanced_access']);
    $access_conditions->addCondition($field->getFieldIdentifier(), NULL);
    $query->addConditionGroup($access_conditions);

    // Foreach datasource, get and set the relevant advanced_access grant.
    foreach ($query->getIndex()->getDatasources() as $datasource) {
      if ($datasource instanceof ContentEntity) {
        $entityTypeId = $datasource->getEntityTypeId();
        $consumer = $this->getAccessConsumerManager()->getConsumerForEntityTypeId($entityTypeId);
        if ($consumer) {
          $grants = $consumer->getAccessGrants('view', $account);
          foreach ($grants as $realm => $gids) {
            foreach ($gids as $gid) {
              $grant_value = $consumer->getPluginId() . ":" . $realm . ":" . $gid;
              $access_conditions->addCondition($field->getFieldIdentifier(), $grant_value);
            }
          }
        }
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc