entity_change_notifier-8.x-1.0/src/Form/PublisherForm.php

src/Form/PublisherForm.php
<?php

namespace Drupal\entity_change_notifier\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\entity_change_notifier\Entity\PublisherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class PublisherForm.
 */
class PublisherForm extends EntityForm {

  /**
   * The entity type bundle info.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * The entity type bundle info.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected $entityTypeBundleInfo;

  /**
   * Constructs a PublisherForm object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info.
   */
  public function __construct(EntityTypeManager $entity_type_manager,
                              EntityTypeBundleInfoInterface $entity_type_bundle_info) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityTypeBundleInfo = $entity_type_bundle_info;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('entity_type.bundle.info')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);

    /** @var \Drupal\entity_change_notifier\Entity\PublisherInterface $publisher */
    $publisher = $this->entity;

    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Label'),
      '#maxlength' => 255,
      '#default_value' => $publisher->label(),
      '#description' => $this->t("Label for the Publisher."),
      '#required' => TRUE,
    ];

    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $publisher->id(),
      '#machine_name' => [
        'exists' => '\Drupal\entity_change_notifier\Entity\Publisher::load',
      ],
      '#disabled' => !$publisher->isNew(),
    ];

    $this->destinationElement($form, $publisher);

    $this->publishTypesElement($form, $publisher);

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $form_state->cleanValues();

    /** @var \Drupal\entity_change_notifier\Entity\PublisherInterface $publisher */
    $publisher = $this->entity;

    // First, merge the values from the additional entity types with the entity
    // types that have bundles. This gives us entity and bundle types sorted by
    // their group, but additional entities still have string values while
    // bundles have array values.
    $publishTypes = [];
    foreach (['content', 'configuration', 'other'] as $type) {
      $publishTypes[$type] = [];
      $values = $form_state->getValue($type);
      foreach (['publish_types', 'no_bundles'] as $key) {
        if (isset($values[$key])) {
          $publishTypes[$type] = array_merge((array) $publishTypes[$type], $values[$key]);
        }
      }
    }

    // Now, we need to make the additional entities values be arrays too.
    foreach ($publishTypes as $type => &$publishType) {
      foreach ($publishType as &$entityType) {
        // The entity type contains bundles.
        if (is_array($entityType)) {
          // Filter out unselected bundles. Then, remove the keys from any
          // remaining bundles since we store them as a sequence.
          $entityType = array_values(array_filter($entityType));
        }
        else {
          // Only convert it if $entityType is 1 (meaning checked).
          if ($entityType) {
            // If it's selected, we need to make it an array for it's internal
            // bundle type (which will equal the entity type.
            $publishType[$entityType] = [$entityType];
          }
        }
      }

      // Remove any unselected publish types. This handles both additional
      // entities set to 0 and empty arrays from entities with bundles.
      $publishTypes[$type] = array_filter($publishTypes[$type]);
    }

    // Finally, remove our grouping and implode them into one configuration
    // array, since the grouping is only for the UI and not functionality.
    $publishTypes = array_merge([], (array) $publishTypes['content'], (array) $publishTypes['configuration'], (array) $publishTypes['other']);
    $publisher->setPublishTypes($publishTypes);
    $status = $publisher->save();

    switch ($status) {
      case SAVED_NEW:
        drupal_set_message($this->t('Created the %label Publisher.', [
          '%label' => $publisher->label(),
        ]));
        break;

      default:
        drupal_set_message($this->t('Saved the %label Publisher.', [
          '%label' => $publisher->label(),
        ]));
    }
    $form_state->setRedirectUrl($publisher->toUrl('collection'));
  }

  /**
   * Builds a list containing all bundles for a given entity type.
   */
  private function buildEntityList($entity_type_id) {
    $entityList = [];
    $bundleInfo = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
    foreach ($bundleInfo as $bundle_name => $bundle) {
      $entityList[$bundle_name] = $bundle['label'];
    }
    return $entityList;

  }

  /**
   * Create the "destination" dropdown.
   *
   * @param array $form
   *   The form being built.
   * @param \Drupal\entity_change_notifier\Entity\PublisherInterface $publisher
   *   The publisher being added or edited.
   */
  private function destinationElement(array &$form, PublisherInterface $publisher) {
    $destinationEntities = $this->entityTypeManager->getStorage('ecn_destination')
      ->loadMultiple();

    if (empty($destinationEntities)) {
      \drupal_set_message($this->t('No destinations exist to publish entities to. <a href="@add-destination">Add a destination</a> before adding a publisher.', [
        '@add-destination' => Url::fromRoute('entity.ecn_destination.add_form')->toString(),
      ]), 'warning');
    }

    $options = [];
    foreach ($destinationEntities as $destination) {
      $options[$destination->id()] = $destination->label();
    }

    // Use the set destination or the first if we are adding a new Publisher.
    if (!empty($publisher->getDestination())) {
      $destination_id = $publisher->getDestination();
    }
    else {
      $keys = array_keys($options);
      $destination_id = reset($keys);
    }

    $form['destination'] = [
      '#type' => 'select',
      '#title' => $this->t('Destination'),
      '#description' => $this->t('The destination to send notifications to.'),
      '#default_value' => $destination_id,
      '#options' => $options,
      '#required' => TRUE,
    ];
  }

  /**
   * Add the publish types fields to the form.
   *
   * Entities typically are classified as either Content Entities or
   * Configuration Entities. However, nothing prevents an entity from being it's
   * own type. To make the form easier to use, we split the list of all entities
   * and bundles into three sections:
   *
   *   - Content entities
   *   - Configuration entities
   *   - Other
   *
   * Other will usually be empty and not shown at all.
   *
   * Within each group, we have to handle two cases:
   *
   *   - Entities with bundles (nodes, taxonomies, etc).
   *   - Entities with no bundles (though they have a bundle ID equalling their
   *     entity ID).
   *
   * Since showing bundles for bundle-less entities would be very noisy on the
   * form, we group them together. With each section, we end up with:
   *
   *   - A list of checkboxes of entities with bundles, sorted alphabetically
   *     by the entity label.
   *   - A single checkboxes element for all bundle-less entities.
   *
   * @param array $form
   *   The form being built.
   * @param \Drupal\entity_change_notifier\Entity\PublisherInterface $publisher
   *   The publisher being edited.
   */
  private function publishTypesElement(array &$form, PublisherInterface $publisher) {
    $definitions = $this->getSortedEntityDefinitions();

    // Initialize each details element so that form values are put into arrays.
    $form['content'] = [
      '#type' => 'details',
      '#title' => $this->t('Content entity types'),
      '#open' => TRUE,
      '#tree' => TRUE,
    ];
    $form['configuration'] = [
      '#type' => 'details',
      '#title' => $this->t('Configuration entity types'),
      '#tree' => TRUE,
    ];
    $form['other'] = [
      '#type' => 'details',
      '#title' => $this->t('Other entity types'),
      '#tree' => TRUE,
    ];

    // Loop through the three groups of entity types.
    foreach ($definitions as $type => &$group) {
      // Sort each entity type by label.
      uasort($group, function (EntityTypeInterface $a, EntityTypeInterface $b) {
        return (string) $a->getLabel() > (string) $b->getLabel();
      });

      // Store all entity types that don't have bundles.
      $additionalEntityTypes = [];
      /** @var \Drupal\Core\Entity\EntityTypeInterface $definition */
      foreach ($group as $definition) {
        // If the entity definition has bundles, then we put all of it's bundles
        // into one checkbox list.
        if ($definition->getBundleEntityType()) {
          // Fetch the array of publish types that may already be set for this
          // entity type when editing a publisher.
          $default_value = [];
          if (isset($publisher->getPublishTypes()[$definition->id()])) {
            $default_value = $publisher->getPublishTypes()[$definition->id()];
          }
          $form[$type]['publish_types'][$definition->id()] = [
            '#type' => 'checkboxes',
            '#title' => $this->t('@entity types', ['@entity' => $definition->getLabel()]),
            '#default_value' => $default_value,
            '#options' => $this->buildEntityList($definition->id()),
          ];
        }
        else {
          $additionalEntityTypes[$definition->id()] = $definition->getLabel();
        }
      }

      // If we have any bundle-less entities, put them at the end.
      if (!empty($additionalEntityTypes)) {
        $default_value = array_keys(array_intersect_key($additionalEntityTypes, $publisher->getPublishTypes()));
        $form[$type]['no_bundles'] = [
          '#type' => 'checkboxes',
          '#title' => $this->t('Additional entity types'),
          '#options' => $additionalEntityTypes,
          '#default_value' => $default_value,
        ];
      }
    }

    // Sites will always have content and config entities, but "other" is just
    // our fallback. Most sites won't have entities that are outside of those
    // two groups.
    if (empty(Element::children($form['other']))) {
      unset($form['other']);
    }
  }

  /**
   * Return all entity definitions sorted by their group.
   *
   *  First, sort all entity definitions into 'content', 'configuration', and
   *  'other'. The group is a free-form string and can be overridden in an
   *  entity annotation, so we don't know all of the options. For example,
   *  \Drupal\Core\Entity\Annotation\ConfigEntityType::$group doesn't use a
   *  a class constant.
   *
   * @return array
   *   An array of entity definitions sorted into:
   *     - 'content'
   *     - 'configuration'
   *     - 'other'
   */
  private function getSortedEntityDefinitions() {
    $definitions = [];
    $definitions['content'] = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $v) {
      return $v->getGroup() == 'content';
    });
    $definitions['configuration'] = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $v) {
      return $v->getGroup() == 'configuration';
    });
    $definitions['other'] = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $v) {
      return $v->getGroup() != 'content' && $v->getGroup() != 'configuration';
    });
    return $definitions;
  }

}

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

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