local_translation-8.x-1.x-dev/modules/local_translation_content/src/Plugin/LocalTranslationAccessRulesPluginManager.php

modules/local_translation_content/src/Plugin/LocalTranslationAccessRulesPluginManager.php
<?php

namespace Drupal\local_translation_content\Plugin;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Plugin\DefaultPluginManager;

/**
 * Class LocalTranslationAccessRulesPluginManager.
 *
 * @package Drupal\local_translation_content\Access
 */
class LocalTranslationAccessRulesPluginManager extends DefaultPluginManager {

  /**
   * Supported operations array.
   *
   * @var array
   */
  protected $supportedOperations;
  /**
   * Route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;
  /**
   * Current user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;
  /**
   * Flag about enabled permissions checking.
   *
   * @var bool
   */
  protected $isEnabled;
  /**
   * Entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;
  /**
   * Language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;
  /**
   * Config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;
  /**
   * Local Translation user skills service.
   *
   * @var \Drupal\local_translation\Services\LocalTranslationUserSkills
   */
  protected $userSkills;

  /**
   * {@inheritdoc}
   */
  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
    parent::__construct(
      'Plugin/LocalTranslationAccessRules',
      $namespaces,
      $module_handler,
      'Drupal\local_translation_content\Plugin\LocalTranslationAccessRulesInterface',
      'Drupal\local_translation_content\Annotation\LocalTranslationAccessRule'
    );
    $this->supportedOperations = ['update', 'delete', 'create'];
    $this->alterInfo('local_translation_content_access_rules_info');
    $this->setCacheBackend($cache_backend, 'local_translation_content_access_rules_info_plugins');

    list($this->userSkills,
      $this->languageManager,
      $this->entityTypeManager,
      $this->configFactory,
      $this->routeMatch,
      $this->currentUser) = array_reverse(func_get_args());
    $this->isEnabled = (bool) $this->configFactory
      ->get('local_translation.settings')
      ->get('enable_local_translation_content_permissions');
  }

  /**
   * Check user access for the specified operation and language.
   *
   * @param string $operation
   *   Operation name.
   * @param \Drupal\Core\Entity\ContentEntityInterface|null $entity
   *   Entity to be operated on.
   * @param string|null $langcode
   *   Language ID.
   *
   * @return \Drupal\Core\Access\AccessResult|\Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden|\Drupal\Core\Access\AccessResultNeutral
   *   Access result.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  public function checkAccess($operation, $entity = NULL, $langcode = NULL) {
    // Workaround for admins.
    if ($this->isAdmin()) {
      return AccessResult::allowed()
        ->cachePerPermissions();
    }

    // Skip any non-supported operations.
    if (!in_array($operation, $this->supportedOperations)) {
      return AccessResult::neutral()
        ->cachePerPermissions();
    }

    // If the permissions checking is disabled - re-use the core's flow.
    if (!$this->isEnabled) {
      // If the entity exists - inherit the core's way to check
      // the translation permissions.
      if ($entity instanceof ContentEntityInterface) {
        // Get entity base info.
        $entity_type_id = $entity->getEntityTypeId();
        $bundle = $entity->bundle();

        // Get entity's access callback.
        $definition      = $this->entityTypeManager->getDefinition($entity_type_id);
        $translation     = $definition->get('translation');
        $access_callback = $translation['content_translation']['access_callback'];
        $access          = call_user_func($access_callback, $entity);
        if ($access->isAllowed()) {
          return $access;
        }

        // Check "translate any entity" permission.
        if ($this->currentUser->hasPermission('translate any entity')) {
          return AccessResult::allowed()->cachePerPermissions();
        }

        // Check per entity permission.
        $permission = "translate {$entity_type_id}";
        if ($definition->getPermissionGranularity() == 'bundle') {
          $permission = "translate {$bundle} {$entity_type_id}";
        }
        $access = AccessResult::allowedIfHasPermission($this->currentUser, $permission);
        if ($access->isAllowed()) {
          return $access;
        }

        // Check for entity operation permission.
        return AccessResult::allowedIfHasPermission($this->currentUser, "$operation content translations");
      }
    }

    $definitions = $this->getDefinitions();
    // If there are no rules or no entity - skip checking.
    if (empty($definitions) || !$entity instanceof ContentEntityInterface) {
      // Workaround for "create" operation.
      if ($operation === 'create') {
        return $this->processCreateOperation();
      }
      return AccessResult::neutral()
        ->cachePerPermissions();
    }

    // Workaround for user edit form access.
    if ($entity->getEntityTypeId() === 'user' && !$this->currentUser->isAnonymous()) {
      if ($entity->id() === $this->currentUser->id() && $operation === 'update') {
        // Just return the same code as in User module.
        // @see \Drupal\user\UserAccessControlHandler::checkAccess().
        return AccessResult::allowed()->cachePerUser();
      }
    }

    // Additional workaround for the "create translation" operation.
    if ($operation === 'create' && $entity instanceof ContentEntityInterface) {
      return $this->processCreateTranslationOperation();
    }

    // Try to find at least one rule that allowing user to access.
    foreach ($definitions as $id => $definition) {
      /** @var \Drupal\local_translation_content\Plugin\LocalTranslationAccessRulesInterface $instance */
      $instance = $this->createInstance($id, $definition);
      if ($instance->isAllowed($operation, $entity, $langcode)) {
        return AccessResult::allowed()
          ->cachePerPermissions();
      }
    }

    return AccessResult::forbidden()
      ->cachePerPermissions();
  }

  /**
   * Process entity create translation operation access.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   Access result object.
   */
  protected function processCreateTranslationOperation() {
    // Fetch source language object from the route params.
    $source = $this->routeMatch->getParameter('source');
    // Prepare array with all "from" translation skills of the current user.
    $from = $this->userSkills->getSourceSkills();
    // Fallback for the non-specified source language.
    // In this case we gonna use the entity's default translation language.
    if (!$source instanceof LanguageInterface) {
      $entity = $this->routeMatch->getParameter('node');
      if ($entity instanceof ContentEntityInterface) {
        foreach ($from as $langcode) {
          if (!$entity->hasTranslation($langcode)) {
            continue;
          }
          $source = $this->languageManager->getLanguage($langcode);
          break;
        }
        if (!$source instanceof LanguageInterface) {
          $source = $entity->getUntranslated()->language();
        }
      }
    }

    // Allow access if the source translation language is exists
    // in the user's "from" translation skills array.
    return AccessResult::allowedIf(
      $source instanceof LanguageInterface
      && !empty($from)
      && in_array($source->getId(), $from)
    )->cachePerPermissions();
  }

  /**
   * Process entity create operation access.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   Access result object.
   */
  protected function processCreateOperation() {
    $langcode = $this->languageManager->getCurrentLanguage()->getId();
    foreach ($this->entityTypeManager->getDefinitions() as $entity_type) {
      if ($entity_type->getPermissionGranularity() === 'bundle') {
        $bundle_key = $entity_type->getBundleEntityType();
        if ($bundle = $this->routeMatch->getParameter($bundle_key)) {
          return AccessResult::allowedIfHasPermission(
            $this->currentUser,
            "local_translation_content create {$bundle->id()} content"
          )->andIf(
            AccessResult::allowedIf($this->userSkills->userHasSkill($langcode))
          )->cachePerPermissions();
        }
      }
    }
    return AccessResult::neutral()
      ->cachePerPermissions();
  }

  /**
   * Check whether the current user is admin or not.
   *
   * @return bool
   *   TRUE - if current user is admin, FALSE otherwise.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function isAdmin() {
    // Prevent any checking for anonymous users.
    if ($this->currentUser->isAnonymous()) {
      return FALSE;
    }
    // Load all admin roles.
    $admin_roles = $this->entityTypeManager
      ->getStorage('user_role')
      ->getQuery()
      ->condition('is_admin', TRUE, '=')
      ->execute();

    // Get roles of current users.
    $roles = $this->currentUser->getRoles(TRUE);

    return !empty(array_intersect($roles, $admin_roles));
  }

}

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

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