adva-8.x-1.0-rc9/src/Plugin/adva/ReferenceAccessProvider.php

src/Plugin/adva/ReferenceAccessProvider.php
<?php

namespace Drupal\adva\Plugin\adva;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines api layer for field access in AccessProviders plugins.
 */
class ReferenceAccessProvider extends AccessProvider implements ReferenceAccessProviderInterface {

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

  /**
   * Create a new AccessProvider.
   *
   * @param array $configuration
   *   Plugin configuration.
   * @param string $plugin_id
   *   Unique plugin id.
   * @param array|mixed $plugin_definition
   *   Plugin instance definition.
   * @param Drupal\adva\Plugin\adva\AccessConsumerInterface $consumer
   *   Associated Access Consumer Instance.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The Entity Type manager to get entity storage.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, AccessConsumerInterface $consumer, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $consumer);

    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, AccessConsumerInterface $consumer) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $consumer,
      $container->get("entity_type.manager")
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getAccessRecords(EntityInterface $entity) {
    $field_values = $this->getReferencedItems($entity);
    $field_configs = $this->configuration['enabled_fields'];
    if (count($field_values)) {
      $grants = [];
      $grant_keys = [];
      foreach ($field_configs as $field_name => $field_config) {
        if (!isset($field_values[$field_name])) {
          continue;
        }
        // If we're here, there values fields on the entity used for access.
        $values = $field_values[$field_name];

        foreach ($values as $value) {

          $grant_view = !empty($field_config['grants']['view']) ? 1 : 0;
          $grant_update = !empty($field_config['grants']['update']) ? 1 : 0;
          $grant_delete = !empty($field_config['grants']['delete']) ? 1 : 0;

          $grant = [
            'realm' => $this->getPluginId() . '_' . $value,
            'gid' => 1,
            'grant_view' => $grant_view,
            'grant_update' => $grant_update,
            'grant_delete' => $grant_delete,
            'priority' => 0,
          ];

          // Filter out duplicate grants.
          $grant_key = implode(':', $grant);
          if (in_array($grant_key, $grant_keys)) {
            continue;
          }
          $grant_keys[] = $grant_key;

          /*
           * If the entity is a node, we will only grant for published content,
           * unless the field has been set to grant for unpublished content.
           */
          $is_node = $entity->getEntityType()->id() === "node";
          $grant_for_current_node = FALSE;
          if ($is_node && isset($field_config['unpublished'])) {
            $grant_unpublished = $field_config['unpublished'] ?: FALSE;
            $grant_for_current_node = ($grant_unpublished || $entity->isPublished());
          }
          if (!$is_node || $grant_for_current_node) {
            $grants[] = $grant;
          }
        }
        return $grants;
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getTargetType() {
    // Implementations should override this method.
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public static function getReferenceFields($entity_type_id, $target_type_id) {
    $type_fields = &drupal_static(__METHOD__);
    if (!isset($type_fields[$entity_type_id]) || !isset($type_fields[$entity_type_id][$target_type_id])) {
      $type_fields[$entity_type_id][$target_type_id] = [];
      $entityBundleManager = \Drupal::service('entity_type.bundle.info');

      $bundles = $entityBundleManager->getBundleInfo($entity_type_id);
      foreach (array_keys($bundles) as $bundle) {
        $bundle_fields = self::getBundleReferenceFields($entity_type_id, $bundle, $target_type_id);
        $type_fields[$entity_type_id][$target_type_id] = array_merge($type_fields[$entity_type_id][$target_type_id], $bundle_fields);
      }
    }
    return $type_fields[$entity_type_id][$target_type_id];
  }

  /**
   * {@inheritdoc}
   */
  public static function getBundleReferenceFields($entity_type_id, $bundle, $target_type_id) {
    $bundle_fields = &drupal_static(__METHOD__);
    if (!isset($bundle_fields[$entity_type_id])
      || !isset($bundle_fields[$entity_type_id][$bundle])
      || !isset($bundle_fields[$entity_type_id][$bundle][$target_type_id])) {
      // Create an empty array, to ensure there is a value to return.
      $bundle_fields[$entity_type_id][$bundle][$target_type_id] = [];

      $reference_field_types = [
        'entity_reference',
        'entity_reference_revisions',
        'field_collection',
      ];

      $entityFieldManager = \Drupal::service('entity_field.manager');
      $fields = $entityFieldManager->getFieldDefinitions($entity_type_id, $bundle);
      foreach ($fields as $field_name => $field) {
        $field_type = method_exists($field, 'getType') ? $field->getType() : NULL;
        $target_type = method_exists($field, 'getSetting') ? $field->getSetting('target_type') : NULL;
        if (in_array($field_type, $reference_field_types) && $target_type === $target_type_id) {
          $bundle_fields[$entity_type_id][$bundle][$target_type_id][$field_name] = $field;
        }
      }
    }
    return $bundle_fields[$entity_type_id][$bundle][$target_type_id];
  }

  /**
   * {@inheritdoc}
   */
  public function getEntityTypeManager() {
    return $this->entityTypeManager;
  }

  /**
   * {@inheritdoc}
   */
  public function getEnabledBundleFields($entity_type_id, $bundle = NULL) {
    if ($bundle === NULL) {
      $bundle = $entity_type_id;
    }

    $configuration = $this->getConfiguration();
    $field_config = isset($configuration['enabled_fields']) ? $configuration['enabled_fields'] : [];

    $enabled_field_names = array_keys($field_config);
    $bundle_fields = static::getBundleReferenceFields($entity_type_id, $bundle, static::getTargetType());
    $bundle_field_names = array_keys($bundle_fields);

    return array_intersect($bundle_field_names, $enabled_field_names);
  }

  /**
   * {@inheritdoc}
   */
  public function getReferencedItems(EntityInterface $entity) {
    static $item_ids = [];

    if (!$entity) {
      return [];
    }

    $id = $entity->id();
    $type = $entity->getEntityType();
    $type_id = $type->id();
    if (!isset($item_ids[$type_id]) || !isset($item_ids[$type_id][$id])) {
      // Ensure there will be a returnable value.
      $item_ids[$type_id][$id] = [];

      // Get list of fields.
      $bundle = $entity->bundle();
      $fields = $this->getEnabledBundleFields($type_id, $bundle);

      // Get values for each field.
      foreach ($fields as $field_name) {

        if (($field = $entity->get($field_name)) && ($items = $field->getValue())) {
          // Filter out empty values from items list.
          $items = array_filter($items);
          $type_key = ($field->getFieldDefinition()->getType() === 'field_collection') ? 'value' : 'target_id';
          $values = array_column($items, $type_key);
          // Filter out null values inserted by forms.
          $item_ids[$type_id][$id][$field_name] = array_filter($values);
        }
      }

      // Filter out any empty lists for a fields.
      $item_ids[$type_id][$id] = array_filter($item_ids[$type_id][$id]);
    }
    return isset($item_ids[$type_id][$id]) ? $item_ids[$type_id][$id] : [];
  }

  /**
   * {@inheritdoc}
   */
  public static function appliesToType(EntityTypeInterface $entityType) {
    if (!$entityType->entityClassImplements('\Drupal\Core\Entity\FieldableEntityInterface')) {
      return FALSE;
    }

    return (count(static::getReferenceFields($entityType->id(), static::getTargetType())) > 0);
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigForm(array $form, FormStateInterface $form_state) {
    $consumer = $this->getConsumer();
    $entity_type_id = $consumer->getEntityTypeId();
    $configuration = $this->getConfiguration();
    $field_config = isset($configuration['enabled_fields']) ? $configuration['enabled_fields'] : [];

    // Expected return value location in the parent tree.
    $base_parents = [
      'consumers',
      $consumer->getPluginId(),
      'config',
      'providers',
      $this->getPluginId(),
    ];

    // Enabled Field list.
    $form['enabled_fields'] = [
      '#type' => 'checkboxes',
      '#title' => $this->t('Enabled Fields'),
      '#description' => $this->t('Choose the fields to use when checking access.'),
      '#default_value' => array_keys($field_config) ?: [],
      '#parents' => array_merge($base_parents, ['enabled_fields']),
      '#options' => [],
    ];
    $form['field_options'] = [
      '#type' => 'item',
    ];

    // Foreach field, add it to the list above and build the grant selection.
    $available_fields = static::getReferenceFields($entity_type_id, static::getTargetType());
    foreach ($available_fields as $field_name => $field) {
      $form['enabled_fields']['#options'][$field_name] = $field->label();
      // Add a field set for the field if enabled.
      $form['field_options'][$field_name] = [
        '#type' => 'fieldset',
        '#title' => $field->label(),
        '#states' => [
          'visible' => [
            ':input[name="consumers[' . $entity_type_id . '][config][providers][' . $this->getPluginId() . '][enabled_fields][' . $field_name . ']"]' => [
              'checked' => TRUE,
            ],
          ],
        ],
      ];
      // Set the enabled grants.
      $form['field_options'][$field_name]['grants'] = [
        '#type' => 'checkboxes',
        '#title' => $this->t('Operation Grants'),
        '#parents' => array_merge(
          $base_parents,
          [
            'field_options',
            $field_name,
            'grants',
          ]
        ),
        '#options' => [
          'view' => 'View',
          'update' => 'Update',
          'delete' => 'Delete',
        ],
        '#default_value' => isset($field_config[$field_name]['grants']) ? $field_config[$field_name]['grants'] : [],
        '#attributes' => ['class' => ['container-inline']],
      ];
      // If for nodes, let the user authorize access to unpublished by field.
      if ($entity_type_id === 'node') {
        $form['field_options'][$field_name]['unpublished'] = [
          '#type' => 'checkbox',
          '#title' => $this->t('Grant access to unpublished content.'),
          '#description' => $this->t('This will permit the above operations on unpublished content.'),
          '#default_value' => isset($field_config[$field_name]['unpublished']) ? $field_config[$field_name]['unpublished'] : FALSE,
          '#parents' => array_merge(
            $base_parents,
            [
              'field_options',
              $field_name,
              'unpublished',
            ]
          ),
        ];
      }
    }
    if (count($form['enabled_fields']['#options']) === 0) {
      $form['enabled_fields']['#access'] = FALSE;
      $entityTypeManager = $this->getEntityTypeManager();
      $context = [
        '%target_type' => $entityTypeManager->getDefinition(static::getTargetType())->getLabel(),
        '%label' => $this->getLabel(),
        '%entity_type' => $entityTypeManager->getDefinition($entity_type_id)->getLabel(),
      ];
      $form['message'] = [
        '#type' => 'item',
        '#title' => $this->t('Enabled Fields: %target_type', $context),
        '#markup' => $this->t('There are no available %target_type reference fields. To use %label, please add a %target_type field to the %entity_type entity.', $context),
      ];
    }
    elseif (count($form['enabled_fields']['#default_value']) > 0) {
      $form['#open'] = TRUE;
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValues();
    $field_config = [];
    foreach ($values['enabled_fields'] as $field_name => $field_enabled) {
      if ($field_enabled && isset($values['field_options'][$field_name]['grants'])) {
        $field_config[$field_name]['grants'] = array_filter($values['field_options'][$field_name]['grants']);
        if (isset($values['field_options'][$field_name]['unpublished'])) {
          $field_config[$field_name]['unpublished'] = $values['field_options'][$field_name]['unpublished'];
        }
      }
    }
    $this->configuration['enabled_fields'] = $field_config;
  }

  /**
   * {@inheritdoc}
   */
  public function getAuthorizedEntityIds($operation, AccountInterface $account) {
    // Provide nothing by default.
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getAccessGrants($operation, AccountInterface $account) {
    $grants = [];

    // Get the entities the user is granted for, and then build grants.
    $entity_ids = $this->getAuthorizedEntityIds($operation, $account);
    foreach ($entity_ids as $entity_id) {
      $grants[$this->getPluginId() . '_' . $entity_id] = [1];
    }

    if (count($grants)) {
      return $grants;
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getHelperMessage(array $definition) {
    $entityType = \Drupal::service('entity_type.manager')->getDefinition(static::getTargetType());
    $context = [
      '%provider' => $definition['label'],
      '%target' => $entityType->getLabel(),
    ];
    $message = \Drupal::translation()->translate('<em>%provider</em> is supported on any field-able entity type.', $context);
    $message .= ' ' . \Drupal::translation()->translate('If you don\'t see the <em>%provider</em> listed for an expected entity, ensure that there is a <em>%target</em> field on the entity type.', $context);
    return $message;
  }

}

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

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