access_policy-1.0.x-dev/src/AccessPolicyEntityAccessControlHandler.php

src/AccessPolicyEntityAccessControlHandler.php
<?php

namespace Drupal\access_policy;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Access controller for content entities assigned an AccessPolicy.
 */
class AccessPolicyEntityAccessControlHandler implements ContainerInjectionInterface {

  /**
   * The access policy validator.
   *
   * @var \Drupal\access_policy\AccessPolicyValidator
   */
  protected $accessPolicyValidator;

  /**
   * The access policy selection service.
   *
   * @var \Drupal\access_policy\AccessPolicySelectionInterface
   */
  protected $accessPolicySelection;

  /**
   * Access policy information.
   *
   * @var \Drupal\access_policy\AccessPolicyInformation
   */
  protected $accessPolicyInformation;

  /**
   * The access rule manager.
   *
   * @var \Drupal\access_policy\AccessPolicyHandlerManager
   */
  protected $accessRuleManager;

  /**
   * The operation plugin manager.
   *
   * @var \Drupal\access_policy\AccessPolicyOperationPluginManager
   */
  protected $operationPluginManager;

  /**
   * Constructs a AccessPolicyEntityAccessControlHandler object.
   *
   * @param \Drupal\access_policy\AccessPolicyValidator $access_policy_validator
   *   The access policy validator.
   * @param \Drupal\access_policy\AccessPolicySelectionInterface $access_policy_selection
   *   The access policy selection handler.
   * @param \Drupal\access_policy\AccessPolicyInformation $policy_information
   *   The access policy information service.
   * @param \Drupal\access_policy\AccessPolicyHandlerManager $access_rule_manager
   *   The access rule manager.
   * @param \Drupal\access_policy\AccessPolicyOperationPluginManager $operation_plugin_manager
   *   The operation plugin manager.
   */
  public function __construct(AccessPolicyValidator $access_policy_validator, AccessPolicySelectionInterface $access_policy_selection, AccessPolicyInformation $policy_information, AccessPolicyHandlerManager $access_rule_manager, AccessPolicyOperationPluginManager $operation_plugin_manager) {
    $this->accessPolicyValidator = $access_policy_validator;
    $this->accessPolicySelection = $access_policy_selection;
    $this->accessPolicyInformation = $policy_information;
    $this->accessRuleManager = $access_rule_manager;
    $this->operationPluginManager = $operation_plugin_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('access_policy.validator'),
      $container->get('access_policy.selection'),
      $container->get('access_policy.information'),
      $container->get('plugin.manager.access_policy.access_rule'),
      $container->get('plugin.manager.access_policy_operation'),
    );
  }

  /**
   * Check access qualifications.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The content entity.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The current user.
   * @param string $operation
   *   The current operation.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function access(EntityInterface $entity, AccountInterface $account, string $operation) {

    if (!$this->accessPolicyInformation->hasEnabledForEntitiesOfEntityType($entity->getEntityType())) {
      return AccessResult::neutral();
    }

    $operation = $this->getCurrentOperation($entity, $operation);

    // If assigning an access policy confirm that the user has policies they
    // can assign first.
    if ($operation == 'manage_access') {
      $access = $this->accessPolicySelection->validateAssignAccessPolicy($entity, $account);
      if (!$access) {
        return $this->accessResult($entity, $operation, $access);
      }
    }

    $access = $this->accessPolicyValidator->validate($entity, $account, $operation);
    $violations = $this->accessPolicyValidator->getViolations($entity);

    return $this->accessResult($entity, $operation, $access, $violations);

  }

  /**
   * Final access result based on operation.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   * @param string $operation
   *   The operation.
   * @param bool $allowed
   *   TRUE if allowed; FALSE otherwise.
   * @param array $violations
   *   Array of violation messages.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   Access result.
   */
  private function accessResult(EntityInterface $entity, $operation, $allowed, array $violations = []) {
    $contexts = $this->getCacheContexts($entity);
    $this->addCacheableDependencies($entity);

    if (!$allowed) {
      $reason = $this->formatViolationReason($violations);
      return AccessResult::forbidden($reason)->addCacheableDependency($entity)->addCacheContexts($contexts);
    }

    // The view unpublished operation requires an allowed result otherwise it
    // will return forbidden. All other operations work with neutral.
    switch ($operation) {
      case 'manage_access':
        return AccessResult::allowed()->addCacheableDependency($entity)->addCacheContexts($contexts);

      default;
        return AccessResult::neutral()->addCacheableDependency($entity)->addCacheContexts($contexts);
    }
  }

  /**
   * Add any cacheable dependencies from the access policies.
   *
   * This ensures that the cache gets invalidated when the access policy is
   * updated.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   */
  protected function addCacheableDependencies(EntityInterface $entity) {
    $policies = $entity->get('access_policy')->referencedEntities();
    foreach ($policies as $policy) {
      $entity->addCacheableDependency($policy);
    }
  }

  /**
   * Get the cache context based on the entity's access policy.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   *
   * @return array
   *   The cache context.
   */
  protected function getCacheContexts(EntityInterface $entity) {
    return $this->accessPolicyValidator->getCacheContexts($entity);
  }

  /**
   * Format the violation reason string.
   *
   * @param array $violations
   *   Array of violations.
   *
   * @return string
   *   The violation reason.
   */
  private function formatViolationReason(array $violations) {
    $reason = [];
    foreach ($violations as $messages) {
      foreach ($messages as $message) {
        $reason[] = $message;
      }
    }
    return implode(', ', $reason);
  }

  /**
   * Get the current operation.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   * @param string $operation
   *   The operation.
   *
   * @return string
   *   The current operation.
   */
  private function getCurrentOperation(EntityInterface $entity, $operation) {
    $plugin = $this->operationPluginManager->getCurrentOperation($entity, $operation);
    if ($plugin) {
      return $plugin->getPluginId();
    }

    return $operation;
  }

}

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

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