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

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

namespace Drupal\adva\Plugin\adva;

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

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines api layer for bundle based access in AccessProviders plugins.
 */
class EntityTypeAccessProvider extends AccessProvider implements EntityTypeAccessProviderInterface {

  /**
   * Indicates the subform is for a non bundled entity type.
   */
  const ENTITY_TYPE_OP = 'ENTITY_TYPE';

  /**
   * Indicates the subform is for a default.
   */
  const ENTITY_DEFAULT_OP = 'DEFAULT';

  /**
   * Indicates the subform is for a bundle.
   */
  const ENTITY_BUNDLE_OP = 'BUNDLE';

  /**
   * Access provider plugin manager.
   *
   * @var \Drupal\adva\Plugin\adva\Manager\AccessProviderManagerInterface
   */
  private $entityTypeManager;

  /**
   * Access provider plugin manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  private $entityBundleInfoManager;

  /**
   * Create a new EntityTypeAccessProvider.
   *
   * @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 Nanager to get entity storage.
   * @param Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info_manager
   *   The Entity Type Bundle Info Nanager to get entity storage.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, AccessConsumerInterface $consumer, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $bundle_info_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $consumer);

    $this->entityTypeManager = $entity_type_manager;
    $this->entityBundleInfoManager = $bundle_info_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'),
      $container->get('entity_type.bundle.info')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getAccessRecords(EntityInterface $entity) {
    static $record_cache = NULL;
    $entity_type = $entity->getEntityType();

    // If bundled entity.
    if ($entity_type->getBundleEntityType()) {
      $bundle_name = $entity->bundle();
      if (!isset($record_cache)) {
        $record_cache = [];
      }
      // If a bundle is enabled for specific overrides, use those settings.
      if (isset($this->configuration['bundles']['enabled']) && in_array($bundle_name, $this->configuration['bundles']['enabled'])) {
        if (!isset($record_cache['bundles'][$bundle_name])) {
          $record_cache['bundles'][$bundle_name] = $this->getEntityBundleAccessRecords($bundle_name);
        }
        $records = $record_cache['bundles'][$bundle_name];

        // For unpublished nodes, clear disabled op grants.
        if (isset($this->configuration['bundles']['override'][$bundle_name]['operations']) && $entity_type->id() === 'node' && !$entity->isPublished()) {
          $ops = ['view', 'update', 'delete'];
          $bundle_config = $this->configuration['bundles']['override'][$bundle_name]['operations'];
          foreach ($records as &$record) {
            foreach ($ops as $op) {
              if (!(isset($bundle_config[$op]['unpublished']) && $bundle_config[$op]['unpublished'])) {
                $record['grant_' . $op] = 0;
              }
            }
          }
        }
      }
      // For non enabled bundles, use the default config, if one is present.
      elseif (isset($this->configuration['default']['enabled']) && $this->configuration['default']['enabled']) {
        if (!isset($record_cache['default'])) {
          $record_cache['default'] = $this->getEntityDefaultAccessRecords();
        }
        $records = $record_cache['default'];

        // For unpublished nodes, clear disabled op grants.
        if (isset($this->configuration['default']['operations']) && $entity_type->id() === 'node' && !$entity->isPublished()) {
          $ops = ['view', 'update', 'delete'];
          $default_config = $this->configuration['default']['operations'];
          foreach ($records as &$record) {
            foreach ($ops as $op) {
              if (!(isset($default_config[$op]['unpublished']) && $default_config[$op]['unpublished'])) {
                $record['grant_' . $op] = 0;
              }
            }
          }
        }
      }
      // Otherwise, return no records.
      else {
        $records = [];
      }
    }
    // For non bundled entities.
    else {
      if (!isset($record_cache)) {
        $record_cache = $this->getEntityTypeAccessRecords();
      }
      $records = $record_cache;
    }

    if (!empty($records)) {
      foreach ($records as &$record) {
        if (!isset($record['langcode'])) {
          $record['langcode'] = $entity->language()->getId();
        }
      }
    }
    return $records;
  }

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

  /**
   * {@inheritdoc}
   */
  public function buildConfigForm(array $form, FormStateInterface $form_state) {
    $consumer = $this->getConsumer();
    $entity_type_id = $consumer->getEntityTypeId();
    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
    $bundles = $this->entityBundleInfoManager->getBundleInfo($entity_type_id);
    $operations = $this->getOperations();

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

    // For bundled entities, display default and per bundle configurations.
    if ($entity_type->getBundleEntityType()) {
      $default_description = $this->t("Default value will be used for any bundles which don't have specific configuration.");
      $default_description .= ' ' . $this->t('If no default configuration is provided, this provider will not grant access to entities with bundle specific configuration below.');
      $form['default'] = [
        '#type' => 'fieldset',
        '#title' => $this->t('Default Configuration'),
        '#parents' => array_merge($base_parents, ['default']),
        'enabled' => [
          '#type' => 'checkbox',
          '#title' => $this->t('Provide default configuration'),
          '#description' => $default_description,
          '#parents' => array_merge($base_parents, ['default', 'enabled']),
          '#default_value' => isset($this->configuration['default']['enabled']) ? $this->configuration['default']['enabled'] : FALSE,
        ],
        'operations' => [
          '#type' => 'item',
          '#states' => [
            'visible' => [
              ':input[name="consumers[' . $entity_type_id . '][config][providers][' . $this->getPluginId() . '][default][enabled]"]' => [
                'checked' => TRUE,
              ],
            ],
          ],
        ],
      ];
      $form['#open'] = isset($this->configuration['default']['enabled']) && $this->configuration['default']['enabled'];
      foreach ($operations as $op) {
        $form['default']['operations'][$op] = [
          '#type' => 'item',
          '#title' => $op,
          '#entity_op' => $op,
          '#entity_op_type' => static::ENTITY_DEFAULT_OP,
          '#parents' => array_merge(
            $base_parents,
            [
              'default',
              'operations',
              $op,
            ]
          ),
        ];
        $subform_state = SubformState::createForSubform($form['default']['operations'][$op], $form, $form_state);
        $form['default']['operations'][$op] = $this->buildOperationConfigForm($form['default']['operations'][$op], $subform_state);
      }

      if (count($bundles)) {
        $bundle_description = $this->t('Bundle specific configuration will override the default configuration set above.', $context);
        $bundle_description .= ' ' . $this->t('If bundle specific configuration is left blank for a bundle, no access records will be generated by %label.', $context);
        $bundle_description .= ' ' . $this->t('This can be used to prevent the above defaults from being used for entities of that bundle.', $context);
        $form['bundles'] = [
          '#type' => 'fieldset',
          '#title' => $this->t('Bundle Configuration'),
          'enabled' => [
            '#type' => 'checkboxes',
            '#title' => $this->t('Provide bundle specific configuration for'),
            '#description' => $bundle_description,
            '#options' => [],
            '#default_value' => isset($this->configuration['bundles']['enabled']) ? $this->configuration['bundles']['enabled'] : [],
            '#parents' => array_merge($base_parents, ['bundles', 'enabled']),
          ],
        ];
        $form['#open'] |= isset($this->configuration['bundles']['enabled']) && !empty($this->configuration['bundles']['enabled']);
        foreach ($bundles as $bundle_name => $bundle) {
          $bundle_context = $context + [
            '%bundle' => $bundle['label'],
          ];
          $form['bundles']['enabled']['#options'][$bundle_name] = $bundle['label'];
          $form['bundles']['override'][$bundle_name] = [
            '#type' => 'details',
            '#title' => $this->t('<em>%bundle</em> bundle configuration', $bundle_context),
            '#parents' => array_merge(
              $base_parents,
              [
                'bundles',
                'override',
                $bundle_name,
              ]
            ),
            '#open' => !in_array($bundle_name, $form['bundles']['enabled']['#default_value']),
            '#states' => [
              'visible' => [
                ':input[name="consumers[' . $entity_type_id . '][config][providers][' . $this->getPluginId() . '][bundles][enabled][' . $bundle_name . ']"]' => [
                  'checked' => TRUE,
                ],
              ],
            ],
            'operations' => [
              '#type' => 'item',
            ],
          ];

          foreach ($operations as $op) {
            $form['bundles']['override'][$bundle_name]['operations'][$op] = [
              '#type' => 'item',
              '#title' => $op,
              '#entity_op' => $op,
              '#entity_bundle' => $bundle_name,
              '#entity_op_type' => static::ENTITY_BUNDLE_OP,
              '#parents' => array_merge(
                $base_parents,
                [
                  'bundles',
                  'override',
                  $bundle_name,
                  'operations',
                  $op,
                ]
              ),
            ];
            $subform_state = SubformState::createForSubform($form['bundles']['override'][$bundle_name]['operations'][$op], $form, $form_state);
            $form['bundles']['override'][$bundle_name]['operations'][$op] = $this->buildOperationConfigForm($form['bundles']['override'][$bundle_name]['operations'][$op], $subform_state);
          }
        }
      }
    }
    // Otherwise, just display operations.
    else {
      $form['#open'] = TRUE;
      $form['operations'] = [
        '#type' => 'item',
      ];
      foreach ($operations as $op) {
        $form['operations'][$op] = [
          '#type' => 'item',
          '#title' => $op,
          '#entity_op' => $op,
          '#entity_op_type' => static::ENTITY_TYPE_OP,
          '#parents' => array_merge($base_parents, ['operations', $op]),
        ];
        $subform_state = SubformState::createForSubform($form['operations'][$op], $form, $form_state);
        $form['operations'][$op] = $this->buildOperationConfigForm($form['operations'][$op], $subform_state);
      }
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigForm(array &$form, FormStateInterface $form_state) {
    $consumer = $this->getConsumer();
    $entity_type_id = $consumer->getEntityTypeId();
    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
    $bundles = $this->entityBundleInfoManager->getBundleInfo($entity_type_id);
    $operations = $this->getOperations();

    $form_values = $form_state->getValues();

    // For bundled entities, unmap the nested values.
    if ($entity_type->getBundleEntityType()) {
      $this->configuration['default']['enabled'] = $form_values['default']['enabled'];
      if ($form_values['default']['enabled']) {
        foreach ($operations as $op) {
          $subform_state = SubformState::createForSubform($form['default']['operations'][$op], $form, $form_state);
          $this->validateOperationConfigForm($form['default']['operations'][$op], $subform_state);
        }
      }
      foreach ($bundles as $bundle_name => $bundle) {
        if (in_array($bundle_name, $form_values['bundles']['enabled'])) {
          foreach ($operations as $op) {
            $subform_state = SubformState::createForSubform($form['bundles']['override'][$bundle_name]['operations'][$op], $form, $form_state);
            $this->validateOperationConfigForm($form['bundles']['override'][$bundle_name]['operations'][$op], $subform_state);
          }
        }
      }
    }
    // For non bundled entities, just check for operation values.
    else {
      foreach ($operations as $op) {
        $subform_state = SubformState::createForSubform($form['operations'][$op], $form, $form_state);
        $this->validateOperationConfigForm($form['operations'][$op], $subform_state);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigForm(array &$form, FormStateInterface $form_state) {
    $consumer = $this->getConsumer();
    $entity_type_id = $consumer->getEntityTypeId();
    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
    $bundles = $this->entityBundleInfoManager->getBundleInfo($entity_type_id);
    $operations = $this->getOperations();

    $form_values = $form_state->getValues();

    // For bundled entities, unmap the nested values.
    if ($entity_type->getBundleEntityType()) {
      // If enabled, update values.
      if ($form_values['default']['enabled']) {
        $this->configuration['default']['enabled'] = $form_values['default']['enabled'];
        foreach ($operations as $op) {
          $subform_state = SubformState::createForSubform($form['default']['operations'][$op], $form, $form_state);
          $this->submitOperationConfigForm($form['default']['operations'][$op], $subform_state);
        }
      }
      if (isset($form_values['bundles']['enabled'])) {
        $this->configuration['bundles']['enabled'] = array_filter($form_values['bundles']['enabled']);
        foreach ($bundles as $bundle_name => $bundle) {
          // Only submit sub form for enabled bundles.
          if (in_array($bundle_name, $form_values['bundles']['enabled'])) {
            foreach ($operations as $op) {
              $subform_state = SubformState::createForSubform($form['bundles']['override'][$bundle_name]['operations'][$op], $form, $form_state);
              $this->submitOperationConfigForm($form['bundles']['override'][$bundle_name]['operations'][$op], $subform_state);
            }
          }
        }
      }
    }
    // For non bundled entities, just check for operation values.
    else {
      foreach ($operations as $op) {
        $subform_state = SubformState::createForSubform($form['operations'][$op], $form, $form_state);
        $this->submitOperationConfigForm($form['operations'][$op], $subform_state);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function buildOperationConfigForm(array $form, FormStateInterface $form_state) {
    $consumer = $this->getConsumer();
    $entity_type_id = $consumer->getEntityTypeId();
    if ($entity_type_id === 'node') {
      $op = $form['#entity_op'];
      $context = [
        '%op' => $op,
      ];

      $defaults = [];
      switch ($form['#entity_op_type']) {
        case EntityTypeAccessProvider::ENTITY_DEFAULT_OP:
          $config = isset($this->configuration['default']['operations']) ? $this->configuration['default']['operations'] : [];
          $defaults = isset($config[$op]) ? $config[$op] : [];
          break;

        case EntityTypeAccessProvider::ENTITY_BUNDLE_OP:
          if (isset($form['#entity_bundle'])) {
            $bundle = $form['#entity_bundle'];
            $config = isset($this->configuration['bundles']['override'][$bundle]['operations']) ? $this->configuration['bundles']['override'][$bundle]['operations'] : [];
            $defaults = isset($config[$op]) ? $config[$op] : [];
          }
          break;
      }

      $form_parents = $form['#parents'];
      $form['unpublished'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Grant <em>%op</em> on unpublished content.', $context),
        '#description' => $this->t('This will grant <em>%op</em> access on unpublished content based on the configuration above.', $context),
        '#default_value' => isset($defaults['unpublished']) && $defaults['unpublished'],
        '#parents' => array_merge($form_parents, ['unpublished']),
        '#weight' => 10,
      ];
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateOperationConfigForm(array $form, FormStateInterface $form_state) {
    // No default action.
  }

  /**
   * {@inheritdoc}
   */
  public function submitOperationConfigForm(array $form, FormStateInterface $form_state) {
    $new_config = array_filter($form_state->getValues());

    if (!isset($form['#entity_op']) || !isset($form['#entity_op_type'])) {
      return;
    }

    switch ($form['#entity_op_type']) {
      case EntityTypeAccessProvider::ENTITY_DEFAULT_OP:
        $this->configuration['default']['operations'][$form['#entity_op']]['unpublished'] = isset($new_config['unpublished']);
        break;

      case EntityTypeAccessProvider::ENTITY_BUNDLE_OP:
        if (isset($form['#entity_bundle'])) {
          $this->configuration['bundles']['override'][$form['#entity_bundle']]['operations'][$form['#entity_op']]['unpublished'] = isset($new_config['unpublished']);
        }
        break;
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getHelperMessage(array $definition) {
    $context = [
      '%provider' => $definition['label'],
    ];
    $message = \Drupal::translation()->translate('<em>%provider</em> is supported on any entity type.', $context);
    $message .= ' ' . \Drupal::translation()->translate('<em>%provider</em> allows mapping for basic access based on the entity type and bundle.', $context);
    $message .= ' ' . \Drupal::translation()->translate('For entity types with bundles, access can be configured per bundle.', $context);
    return $message;
  }

  /**
   * {@inheritdoc}
   */
  public function getAccessRecordsFromConfig(array $config) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getEntityTypeAccessRecords() {
    if (isset($this->configuration['operations'])) {
      return $this->getAccessRecordsFromConfig($this->configuration['operations']);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getEntityDefaultAccessRecords() {
    if (isset($this->configuration['default']['operations'])) {
      return $this->getAccessRecordsFromConfig($this->configuration['default']['operations']);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getEntityBundleAccessRecords($bundle_name) {
    if (isset($this->configuration['bundles']['override'][$bundle_name]['operations'])) {
      return $this->getAccessRecordsFromConfig($this->configuration['bundles']['override'][$bundle_name]['operations']);
    }
  }

}

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

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