collection-8.x-1.x-dev/src/CollectionContentEntityFormAlter.php

src/CollectionContentEntityFormAlter.php
<?php

namespace Drupal\collection;

use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Session\AccountProxy;
use Drupal\collection\CollectionContentManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\ContentEntityDeleteForm;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * A service to alter a content entity form.
 */
class CollectionContentEntityFormAlter {

  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  private $entityTypeManager;

  /**
   * The current user account.
   *
   * @var \Drupal\Core\Session\AccountProxy
   */
  private $account;

  /**
   * The collection content manager service.
   *
   * @var \Drupal\collection\CollectionContentManager
   */
  protected $collectionContentManager;

  /**
   * CollectionContentEntityFormAlter constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Session\AccountProxy $current_user
   *   The current user.
   * @param \Drupal\collection\CollectionContentManager $collection_content_manager
   *   The collection content manager.
   */
  public function __construct(EntityTypeManager $entity_type_manager, AccountProxy $current_user, CollectionContentManager $collection_content_manager) {
    $this->entityTypeManager = $entity_type_manager;
    $this->account = $current_user;
    $this->collectionContentManager = $collection_content_manager;
  }

  /**
   * Returns extra/pseudo fields for any content entity that can be collected.
   *
   * @see collection_entity_extra_field_info().
   *
   * @return array
   *   A nested array of 'pseudo-field' elements. See
   *   EntityFieldManagerInterface::getExtraFields().
   */
  public function getExtraFieldInfo() {
    static $extra;

    if (isset($extra)) {
      return $extra;
    }

    $extra = [];
    $collection_item_type_storage = $this->entityTypeManager->getStorage('collection_item_type');

    /** @var \Drupal\collection\Entity\CollectionItemType $collection_item_type */
    foreach ($collection_item_type_storage->loadMultiple() as $collection_item_type) {
      foreach ($collection_item_type->getAllowedBundles() as $allowed_bundle) {
        list($entity_type_id, $bundle) = explode('.', $allowed_bundle);

        $extra[$entity_type_id][$bundle]['form']['ief_collection_items'] = [
          'label' => t('Collections'),
          'weight' => 50,
          'visible' => TRUE,
        ];
      }
    }

    return $extra;
  }

  /**
   * Alter a content entity add/edit form.
   *
   * @see collection_form_alter().
   *
   * @param array $form
   *   A Form API form.
   * @param FormStateInterface $form_state
   *   The form state.
   * @param string $form_id
   *   The form ID.
   */
  public function alterForm(array &$form, FormStateInterface $form_state, $form_id) {
    $form_object = $form_state->getFormObject();

    if (!$form_object instanceof ContentEntityForm || $form_object instanceof ContentEntityDeleteForm) {
      return;
    }

    if ($form_state->get('form_display')->getComponent('ief_collection_items')) {
      $entity = $form_object->getEntity();

      if ($entity->isNew()) {
        $this->addNewCollectionItem($form, $form_state, $entity);
      }
      else {
        $this->addExistingCollectionItems($form, $form_state, $entity);
      }
    }
  }

  /**
   * Add a new collection items inline form.
   *
   * Embed a collection item add form in any content entity (e.g. node) forms
   * if there is a `collection` query parameter.
   *
   * @param array $form
   *   A content entity add/edit form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity for this ContentEntityForm.
   */
  public function addNewCollectionItem(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    $collection_storage = $this->entityTypeManager->getStorage('collection');
    $collection_item_storage = $this->entityTypeManager->getStorage('collection_item');

    // Check to see if there is a query param requesting the addition to an
    // existing collection.
    if (($collection_id_from_param = \Drupal::request()->query->get('collection')) && ($collection_from_param = $collection_storage->load($collection_id_from_param))) {

      // Ensure that the current user can add items to this collection.
      if (!$collection_from_param->access('update')) {
        return;
      }

      $allowed_types = $collection_from_param->type->entity->getAllowedCollectionItemTypes($entity->getEntityTypeId(), $entity->bundle());

      if (empty($allowed_types)) {
        return;
      }

      $collection_item_new = $collection_item_storage->create([
        'type' => reset($allowed_types),
        'collection' => $collection_from_param,
        'canonical' => TRUE,
      ]);

      $form['ief_collection_items'] = [
        '#type' => 'details',
        '#title' => $this->t('Collections'),
        '#open' => TRUE,
      ];

      if (!isset($form['actions']['submit']['#submit'])) {
        $form['ief_collection_items']['collection_new'] = [
          '#markup' => $this->t('Missing submit handler.'),
        ];
        return;
      }

      $form['ief_collection_items']['collection_new'] = [
        '#type' => 'fieldset',
        '#title' => $collection_from_param->label(),
        '#open' => TRUE,
        '#attributes' => ['class' => ['collection-item', 'collection-item--' . $collection_item_new->bundle()]],
      ];

      $form['ief_collection_items']['collection_new']['item'] = [
        '#type' => 'inline_entity_form',
        '#entity_type' => 'collection_item',
        '#bundle' => $collection_item_new->bundle(),
        '#default_value' => $collection_item_new,
        '#form_mode' => 'mini',
        '#save_entity' => FALSE,
        '#op' => 'add',
        '#ief_id' => 'collection_item_subform-new',
        // Do not validate this collection_item for new content entities,
        // because validators like UniqueItemValidator and
        // SingleCanonicalItemValidator are only relevant for existing content
        // entities. In this case, there is no $collection_item->item entity
        // until the content entity form is submitted and `handleNewCollection`
        // is called. The missing `item` entity causes some validators to fail.
        '#element_validate' => [],
      ];

      // This will allow the methods in EntityInlineForm to be called (e.g.
      // buildEntity).
      if (!$form_state->get(['inline_entity_form'])) {
        $form_state->set(['inline_entity_form'], []);
      }

      // This additional submit handler is called to save the collection_item
      // _after_ the host content entity. This is so we have access to the new
      // content entity id.
      $form['actions']['submit']['#submit'][] = [static::class, 'handleNewCollection'];
    }
  }

  /**
   * Add collection items for this entity to the form.
   *
   * Embed collection item edit forms in any content entity (e.g. node) forms
   * if that entity is in one or more collections.
   *
   * @param array $form
   *   A content entity add/edit form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity for this ContentEntityForm.
   */
  public function addExistingCollectionItems(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    $collection_item_storage = $this->entityTypeManager->getStorage('collection_item');

    // Load all collection items that reference this entity.
    $collection_items = $this->collectionContentManager->getCollectionItemsForEntity($entity, 'update');

    if (($collection_item_count = count($collection_items)) === 0) {
      return;
    }

    $form['ief_collection_items'] = [
      '#type' => 'details',
      '#title' => $this->t('Collections'),
      '#open' => TRUE,
    ];

    foreach ($collection_items as $collection_item) {
      $collection = $collection_item->collection->entity;

      $form['ief_collection_items']['collection_' . $collection->id()] = [
        '#type' => 'details',
        '#title' => $collection->label() . ($collection_item->isCanonical() ? ' *' : ''),
        '#open' => $collection_item_count === 1,
        '#attributes' => ['class' => ['collection-item', 'collection-item--' . $collection_item->bundle()]],
      ];

      $form['ief_collection_items']['collection_' . $collection->id()]['item_' . $collection_item->id()] = [
        '#type' => 'inline_entity_form',
        '#entity_type' => 'collection_item',
        '#bundle' => $collection_item->bundle(),
        '#default_value' => $collection_item,
        '#form_mode' => 'mini',
        '#save_entity' => TRUE,
        '#op' => 'edit',
        '#ief_id' => 'collection_item_subform-' . $collection_item->id(),
      ];
    }

    $form['ief_collection_items']['note'] = [
      '#markup' => $this->t('* Canonical collection'),
      '#theme_wrappers' => [
        'container' => [
          '#attributes' => ['class' => ['collection-items-inline-note']],
        ],
      ],
    ];

    // Set the bare minimum 'inline_entity_form' value to the form state. This is
    // required to add the proper submit handlers to the node add/edit form. See
    // inline_entity_form_form_alter() in inline_entity_form.module
    if (!$form_state->get(['inline_entity_form'])) {
      $form_state->set(['inline_entity_form'], []);
    }

  }

  /**
   * Submit callback for a content entity with an inline collection item form.
   *
   * The collection item is saved here, rather than via `inline_entity_form`
   * `#save_entity`, because we're doing the opposite of what IEF usually does.
   *
   * Normally, IEF forms create a new entity that will be added to a reference
   * field on the content entity.
   *
   * Instead, we need the content entity saved first, so that the
   * collection_item can refer to it.
   *
   * @see self::addNewCollectionItem().
   */
  public static function handleNewCollection($form, FormStateInterface $form_state) {
    $collection_item = $form['ief_collection_items']['collection_new']['item']['#entity'] ?? FALSE;
    $collection_item->item = $form_state->getformObject()->getEntity();
    $collection_item->save();
  }

}

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

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