subentity-1.x-dev/src/ReferencedEntityAccessControlHandler.php

src/ReferencedEntityAccessControlHandler.php
<?php

namespace Drupal\subentity;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityAccessControlHandler;
use Drupal\Core\Entity\EntityHandlerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Access control handler for the referenced entity.
 *
 * Finding parent entity permissions to assign them to this entity.
 */
class ReferencedEntityAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {

  /**
   * Entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs an access control handler instance for referenced entity.
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
   *   The entity type.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(EntityTypeInterface $entity_type, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($entity_type);

    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
    // @phpstan-ignore new.static
    return new static($entity_type, $container->get('entity_type.manager'));
  }

  /**
   * {@inheritdoc}
   */
  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
    $storage_by_entity_type = $this->getStorageByEntityType();
    $target_id = $entity->id();

    // Finds the parent which references this entity.
    foreach ($storage_by_entity_type as $entity_type => $storages) {
      $entity_storage = $this->entityTypeManager->getStorage($entity_type);
      $query = $entity_storage->getQuery('OR')->accessCheck();

      /** @var \Drupal\field\FieldStorageConfigInterface $storage */
      foreach ($storages as $storage) {
        $query->condition($storage->get('field_name') . '.target_id', $target_id);
      }

      $result = $query->execute();

      // If the parent is found, check its access control.
      if ($result) {
        $entities = $entity_storage->loadMultiple($result);

        /** @var \Drupal\Core\Entity\ContentEntityInterface $entity_parent */
        foreach ($entities as $entity_parent) {
          if ($entity_parent->access($operation)) {
            return AccessResult::allowed();
          }
        }
      }
    }

    // Unknown operation, no opinion.
    return AccessResult::neutral();
  }

  /**
   * {@inheritdoc}
   */
  protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
    $storage_by_entity_type = $this->getStorageByEntityType();

    foreach ($storage_by_entity_type as $entity_type => $storages) {
      $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type);

      /** @var \Drupal\field\FieldStorageConfigInterface $storage */
      foreach ($storages as $storage) {
        foreach ($storage->getBundles() as $bundle) {
          if ($access_control_handler->createAccess($bundle, $account)) {
            return AccessResult::allowed();
          }
        }
      }
    }

    return AccessResult::forbidden();
  }

  /**
   * Return storages of referenced fields targeting the current entity type.
   *
   * @return array<string, \Drupal\field\FieldStorageConfigInterface[]>
   *   Associative array.
   */
  protected function getStorageByEntityType() {
    /** @var \Drupal\subentity\Entity\EntityParentHandler $handler */
    $handler = $this->entityTypeManager->getHandler($this->entityTypeId, 'parent');
    return $handler->getStorageByEntityType();
  }

}

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

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