external_entity-1.0.x-dev/src/Plugin/ExternalEntity/RenderType/InternalEntityRenderType.php

src/Plugin/ExternalEntity/RenderType/InternalEntityRenderType.php
<?php

declare(strict_types=1);

namespace Drupal\external_entity\Plugin\ExternalEntity\RenderType;

use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\external_entity\AjaxFormTrait;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\external_entity\Service\EntityTypeInfo;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\external_entity\Contracts\ExternalEntityInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\external_entity\Contracts\ExternalEntityTypeInterface;
use Drupal\external_entity\Plugin\ExternalEntity\ExternalEntityRenderTypeBase;

/**
 * Define the internal entity render type.
 *
 * @ExternalEntityRenderType(
 *   id = "internal_entity",
 *   label = @Translation("Internal Entity")
 * )
 */
class InternalEntityRenderType extends ExternalEntityRenderTypeBase {

  use AjaxFormTrait;

  /**
   * @var \Drupal\external_entity\Service\EntityTypeInfo
   */
  protected $entityTypeInfo;

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

  /**
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $externalEntityCache;

  /**
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
   */
  protected $entityDisplayRepository;

  /**
   * Cached internal entities array.
   *
   * @var array
   */
  protected static $entities = [];

  /**
   * Internal entity render type constructor.
   *
   * @param array $configuration
   *   An array of plugin configurations.
   * @param string $plugin_id
   *   The plugin identifier.
   * @param mixed $plugin_definition
   *   The plugin definition.
   * @param \Drupal\external_entity\Service\EntityTypeInfo $entity_type_info
   *   The entity type manager service.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    EntityTypeInfo $entity_type_info,
    CacheBackendInterface $external_entity_cache,
    EntityTypeManagerInterface $entity_type_manager,
    EntityDisplayRepositoryInterface $entity_display_repository,
  ) {
    parent::__construct(
      $configuration,
      $plugin_id,
      $plugin_definition
    );
    $this->entityTypeInfo = $entity_type_info;
    $this->entityTypeManager = $entity_type_manager;
    $this->externalEntityCache = $external_entity_cache;
    $this->entityDisplayRepository = $entity_display_repository;
  }

  /**
   * {@inheritDoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition,
  ) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('external_entity.entity_type.info'),
      $container->get('cache.external_entity'),
      $container->get('entity_type.manager'),
      $container->get('entity_display.repository')
    );
  }

  /**
   * {@inheritDoc}
   */
  public function defaultConfiguration(): array {
    return [
      'bundle' => NULL,
      'display' => NULL,
      'entity_type' => NULL,
      'property_mapping' => [],
    ];
  }

  /**
   * {@inheritDoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $form_state,
  ): array {
    $form['#prefix'] = '<div id="internal-entity-render-type">';
    $form['#suffix'] = '<div/>';

    $entity_info = $this->entityTypeInfo;
    $entity_type_id = $this->getFormStateValue(
      'entity_type',
      $form_state,
      $this->getRenderEntityType()
    );
    $entity_type_option = $entity_info->getEntityTypeOptions();

    $form['entity_type'] = [
      '#type' => 'select',
      '#title' => $this->t('Entity Type'),
      '#required' => TRUE,
      '#empty_option' => $this->t('- Select -'),
      '#options' => $entity_type_option,
      '#default_value' => $entity_type_id,
      '#depth' => 1,
    ] + $this->baseAjaxFormElement();

    if (isset($entity_type_id, $entity_type_option[$entity_type_id])) {
      $bundle = $this->getFormStateValue(
        ['bundle'],
        $form_state,
        $this->getRenderEntityBundle()
      );
      $bundle_options = $entity_info->getEntityBundleOptions($entity_type_id);

      $form['bundle'] = [
        '#type' => 'select',
        '#title' => $this->t('Entity Bundle'),
        '#required' => TRUE,
        '#description' => $this->t('Select the entity bundle.'),
        '#empty_option' => $this->t('- Select -'),
        '#options' => $bundle_options,
        '#default_value' => $bundle,
      ] + $this->baseAjaxFormElement();

      if (isset($bundle, $bundle_options[$bundle]) && !empty($bundle)) {
        $form['property_mapping'] = [
          '#type' => 'table',
          '#title' => $this->t('Property Mapping'),
          '#header' => [
            $this->t('Resource Property'),
            $this->t('Entity Field'),
          ],
          '#tree' => TRUE,
          '#empty' => $this->t(
            'There are no external entity properties defined.'
          ),
        ];
        $field_options = $entity_info->getEntityFieldOptions(
          $entity_type_id,
          $bundle
        );
        $property_mapping = $this->getConfigurationValue('property_mapping', []);

        foreach ($this->getDisplayPropertyDefinitions() as $name => $definition) {
          $property_field = $property_mapping[$name]['field'] ?? NULL;
          $form['property_mapping'][$name]['name']['#markup'] = $name;
          $form['property_mapping'][$name]['field'] = [
            '#type' => 'select',
            '#options' => $field_options,
            '#empty_option' => $this->t('- None -'),
            '#default_value' => array_key_exists($property_field, $field_options)
              ? $property_field
              : NULL,
          ];
        }
      }
    }

    return $form;
  }

  /**
   * {@inheritDoc}
   */
  public function render(
    ExternalEntityInterface $external_entity,
    string $mode = 'default',
  ): array {
    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
    $entity = $this->createEntity($external_entity);
    return $this->renderEntityView($entity, $mode);
  }

  /**
   * {@inheritDoc}
   */
  public function createEntity(
    ExternalEntityInterface $external_entity,
  ): ?EntityInterface {
    $cid = "external_entity:render_entity:{$external_entity->id()}";
    $cache = $this->externalEntityCache->get($cid);

    if (
      is_object($cache)
      && isset($cache->data)
      && $cache->data instanceof EntityInterface
    ) {
      $entity = $cache->data;
    }
    else {
      $entity = $this->instantiateEntity();
      $entity->external_entity = $external_entity;
      $properties = $external_entity->getProperties();

      $this->attachDefaultEntityProperties($entity, $properties);
      $this->attachMappingEntityProperties($entity, $properties);

      $this->externalEntityCache->set(
        $cid,
        $entity,
        CacheBackendInterface::CACHE_PERMANENT,
        Cache::mergeTags($external_entity->getCacheTags(), $entity->getCacheTags())
      );
    }

    return $entity;
  }

  /**
   * {@inheritDoc}
   */
  public function getRenderModes(): array {
    return $this->entityDisplayRepository->getViewModeOptionsByBundle(
      $this->getRenderEntityType(),
      $this->getRenderEntityBundle()
    );
  }

  /**
   * {@inheritDoc}
   */
  public function getCacheTagsToInvalidate(): array {
    $tags = parent::getCacheTagsToInvalidate();
    $config = $this->getConfiguration();

    if (isset($config['entity_type'], $config['bundle'])) {
      $tags[] = "external_entity:{$this->pluginId}:{$config['entity_type']}:{$config['bundle']}";
    }

    return $tags;
  }

  /**
   * Define the base AJAX form element.
   *
   * @return array[]
   *   An array of default ajax elements.
   */
  protected function baseAjaxFormElement(): array {
    return [
      '#ajax' => [
        'event' => 'change',
        'method' => 'replaceWith',
        'wrapper' => 'internal-entity-render-type',
        'callback' => [$this, 'ajaxFormDepthCallback'],
      ],
    ];
  }

  /**
   * Instantiate the base internal base entity.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface|null
   *   The internal entity object.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function instantiateEntity(): ?ContentEntityInterface {
    if ($entity_type = $this->getRenderEntityType()) {
      $values = [];
      $definition = $this->entityTypeManager->getDefinition($entity_type);

      if ($bundle = $definition->getKey('bundle')) {
        $values += [
          $bundle => $this->getRenderEntityBundle(),
        ];
      }

      return $this->entityTypeManager->getStorage($entity_type)->create($values);
    }

    return NULL;
  }

  /**
   * Attach default entity properties.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The internal entity object.
   * @param array $properties
   *   An array of property definitions.
   */
  protected function attachDefaultEntityProperties(
    EntityInterface $entity,
    array $properties,
  ): void {
    $entity_type = $entity->getEntityType();

    foreach (['id', 'uuid'] as $key) {
      if (
        !isset($properties[$key])
        || !$entity_type->hasKey($key)
      ) {
        continue;
      }
      $name = $entity_type->getKey($key);
      $definition = $properties[$key];
      $entity->set($name, $definition['value'] ?? []);
    }
  }

  /**
   * Attach mapping entity properties.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The internal entity object.
   * @param array $properties
   *   An array of property definitions.
   */
  protected function attachMappingEntityProperties(
    EntityInterface $entity,
    array $properties,
  ): void {
    foreach ($this->getConfigurationValue('property_mapping') as $name => $info) {
      if (!isset($info['field'], $properties[$name]) || !$entity->hasField($info['field'])) {
        continue;
      }
      $definition = $properties[$name];

      if (!isset($definition['value'])) {
        continue;
      }
      $items = $entity->get($info['field']);
      $items->setValue($definition['value']);
    }
  }

  /**
   * Render an entity view.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   An entity instance to render.
   * @param string $mode
   *   The entity display mode.
   *
   * @return array
   *   A renderable array that's returned from the view builder.
   */
  protected function renderEntityView(
    EntityInterface $entity,
    string $mode = 'default',
  ): array {
    $builder = $this->entityTypeManager->getViewBuilder(
      $entity->getEntityTypeId()
    );

    return $builder->view($entity, $mode);
  }

  /**
   * Get the external entity display resource.
   *
   * @return string|null
   */
  protected function getResource(): ?string {
    return $this->externalEntityResourceDisplay->getResource();
  }

  /**
   * Get the external entity display variation.
   *
   * @return string|null
   */
  protected function getVariation(): ?string {
    return $this->externalEntityResourceDisplay->getVariation();
  }

  /**
   * Get the render plugin entity type ID.
   *
   * @return string
   *   The entity type ID.
   */
  protected function getRenderEntityType(): ?string {
    return $this->getConfigurationValue('entity_type');
  }

  /**
   * Get the render plugin entity bundle.
   *
   * @return string
   *   The entity bundle name.
   */
  protected function getRenderEntityBundle(): ?string {
    return $this->getConfigurationValue('bundle');
  }

  /**
   * Get a plugin configuration value.
   *
   * @param string $name
   *   The keyed name.
   *
   * @return mixed
   *   The plugin configuration value.
   */
  protected function getConfigurationValue(string $name) {
    return $this->getConfiguration()[$name];
  }

  /**
   * Get the display external entity type.
   *
   * @return \Drupal\external_entity\Contracts\ExternalEntityTypeInterface
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function getDisplayExternalEntityType(): ExternalEntityTypeInterface {
    return $this->externalEntityResourceDisplay->externalEntityType();
  }

  /**
   * Get display external entity type property definitions.
   *
   * @return array
   *   An array of property definitions.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\external_entity\Exception\InvalidResourceException
   * @throws \GuzzleHttp\Exception\GuzzleException
   */
  protected function getDisplayPropertyDefinitions(): array {
    $external_entity_type = $this->getDisplayExternalEntityType();
    return $external_entity_type->getResourceProperties(
      $this->getResource(),
      $this->getVariation()
    );
  }

}

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

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