association-1.0.0-alpha2/src/Plugin/Association/Behavior/EntityListBehavior.php

src/Plugin/Association/Behavior/EntityListBehavior.php
<?php

namespace Drupal\association\Plugin\Association\Behavior;

use Drupal\association\Attribute\AssociationBehavior;
use Drupal\association\Entity\AssociationTypeInterface;
use Drupal\association\Plugin\AssociationPluginFormInterface;
use Drupal\association\Plugin\BehaviorBase;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\toolshed\Strategy\Exception\StrategyException;

/**
 * Behavior for managing associations that have a entity list.
 *
 * Manages entities linked to association and dictates the controls, which
 * entities/bundles are allowed. The behavior also is responsible for building
 * the admin UI for the association management.
 */
#[AssociationBehavior(
  id: 'entity_list',
  label: new TranslatableMarkup('Entity list'),
  manager_builder: '\Drupal\association\Behavior\Manager\EntityListBuilder',
)]
class EntityListBehavior extends BehaviorBase implements AssociationPluginFormInterface {

  /**
   * List of labels for behavior tags, keyed by the tag identifier.
   *
   * @var \Drupal\Component\Render\MarkupInterface[]|string[]
   */
  protected $tagLabels = [];

  /**
   * Get the key to use for an entity tag of specified entity type and bundle.
   *
   * @param string $entity_type_id
   *   The entity type ID.
   * @param string $bundle_id
   *   The entity bundle ID.
   *
   * @return string
   *   The machine name / tag key to use for an entity type and bundle.
   */
  protected function getTagKey(string $entity_type_id, string $bundle_id): string {
    return $entity_type_id . ':' . $bundle_id;
  }

  /**
   * Formats the association entity tag label.
   *
   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|string $entity_type_label
   *   The entity type label.
   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|string $bundle_label
   *   The entity bundle label.
   *
   * @return \Drupal\Component\Render\MarkupInterface
   *   A formatted label to use for the entity tag for that entity type and
   *   bundle.
   */
  protected function formatTagLabel($entity_type_label, $bundle_label): MarkupInterface {
    return new FormattableMarkup('@entity_type_label: @bundle_label', [
      '@entity_type_label' => $entity_type_label,
      '@bundle_label' => $bundle_label,
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'entity_types' => [],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getEntityTypes(): array {
    $entityTypes = $this->getConfiguration()['entity_types'] ?? [];
    $adapterTypes = $this->adapterManager->getEntityTypes();

    return array_intersect_key($adapterTypes, $entityTypes);
  }

  /**
   * {@inheritdoc}
   */
  public function isValidEntity($tag, $entity_type, $bundle): bool {
    // Tag is no longer relevant for entity list behaviors.
    $allowedTypes = $this->getConfiguration()['entity_types'] ?? [];
    return !empty($allowedTypes[$entity_type][$bundle]);
  }

  /**
   * {@inheritdoc}
   */
  public function getTags(): array {
    $types = $this->getConfiguration()['entity_types'] ?? [];

    $tags = [];
    foreach ($types as $entityTypeId => $bundles) {
      if ($adapter = $this->adapterManager->getAdapterByEntityType($entityTypeId)) {
        $avail = $adapter->getBundles();

        foreach ($bundles as $bundle) {
          if (!empty($bundles[$bundle])) {
            $key = $this->getTagKey($entityTypeId, $bundle);
            $tags[$key] = $this->formatTagLabel($adapter->getLabel(), $avail[$bundle]);
          }
        }
      }
    }

    return $tags;
  }

  /**
   * {@inheritdoc}
   */
  public function getTagLabel($tag, $entity_type_id, $bundle) {
    $key = $this->getTagKey($entity_type_id, $bundle);

    if (!isset($this->tagLabels[$key])) {
      $this->tagLabels[$key] = FALSE;

      if ($adapter = $this->adapterManager->getAdapterByEntityType($entity_type_id)) {
        $bundles = $adapter->getBundles();

        if (!empty($bundles[$bundle])) {
          $this->tagLabels[$key] = $this->formatTagLabel($adapter->getLabel(), $bundles[$bundle]);
        }
      }
    }

    return $this->tagLabels[$key] ?: '';
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigUpdate(AssociationTypeInterface $assocation_type, array $changes): array {
    $errors = [];
    $current = $this->getConfiguration()['entity_types'] ?? [];
    $entityTypes = $changes['entity_types'];

    if ($diff = array_diff($current, $entityTypes)) {
      $errors[] = $this->t('Cannot remove entity types from entity list behavior when there is data: @list', [
        '@list' => implode(', ', $diff),
      ]);
    }
    else {
      foreach ($current as $type => $bundles) {
        if ($bundleDiff = array_diff($bundles, $entityTypes[$type])) {
          $errors[] = $this->t('Cannot remove @type bundles (@list) when Entity Association has content.', [
            '@type' => $type,
            '@list' => implode(', ', $bundleDiff),
          ]);
        }
      }
    }

    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state, AssociationTypeInterface $association_type = NULL): array {
    $entityTypes = $this->getConfiguration()['entity_types'] ?? [];
    $form_state->set('association_type', $association_type->id());

    foreach ($this->adapterManager->getEntityTypes() as $type) {
      try {
        $adapter = $this->adapterManager->getAdapterByEntityType($type);

        $form['entity_types'][$type] = [
          '#type' => 'checkboxes',
          '#title' => $this->t('Allowed @label types', [
            '@label' => $adapter->getLabel(),
          ]),
          '#options' => $adapter->getBundles(),
          '#default_value' => $entityTypes[$type] ?? [],
        ];
      }
      catch (StrategyException $e) {
        // Unable to create the association entity adapter for the entity type.
        // Skip as this probably means a providing module is missing.
      }
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    $current = $this->getConfiguration()['entity_types'] ?? [];
    $entityTypes = $form_state->getValue('entity_types');

    if ($typeId = $form_state->get('association_type')) {
      /** @var \Drupal\association\Entity\AssociationTypeInterface */
      $type = $this->entityTypeManager->getStorage('association_type')->load($typeId);
      if (!($type && $type->hasData())) {
        return;
      }
    }

    foreach ($current as $type => $bundles) {
      $updated = array_filter($entityTypes[$type]);

      // Check for missing entity bundles.
      if (empty($updated)) {
        $form_state->setError($form['entity_types'][$type], $this->t('Cannot remove @type bundles (@list) when entity association has content.', [
          '@type' => $type,
          '@list' => implode(', ', $bundles),
        ]));
      }
      elseif ($bundleDiff = array_diff($bundles, $updated)) {
        $form_state->setError($form['entity_types'][$type], $this->t('Cannot remove @type bundles (@list) when entity association has data.', [
          '@type' => $type,
          '@list' => implode(', ', $bundleDiff),
        ]));
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $entityTypes = $form_state->getValue('entity_types') ?? [];

    foreach ($entityTypes as &$bundles) {
      $bundles = array_filter($bundles);
    }

    $config = ['entity_types' => array_filter($entityTypes)];
    $this->setConfiguration($config);
  }

}

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

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