contacts_events-8.x-1.x-dev/src/Plugin/Field/FieldWidget/OrderItemAdditionalChargeWidget.php

src/Plugin/Field/FieldWidget/OrderItemAdditionalChargeWidget.php
<?php

namespace Drupal\contacts_events\Plugin\Field\FieldWidget;

use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowBase;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormBase;
use Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormComplex;

/**
 * Inline widget for additional charges.
 *
 * @FieldWidget(
 *   id = "inline_entity_form_order_item_additional_charges",
 *   label = @Translation("Booking Additional Charges"),
 *   field_types = {
 *     "entity_reference"
 *   },
 *   multiple_values = true
 * )
 */
class OrderItemAdditionalChargeWidget extends InlineEntityFormComplex {

  /**
   * {@inheritdoc}
   */
  protected function getTargetBundles() {
    // Don't allow creation of any other order item type other than ticket.
    return ['additional_charge'];
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return ['form_mode' => 'booking'] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $element = parent::settingsForm($form, $form_state);
    $element['allow_new']['#access'] = FALSE;
    $element['allow_existing']['#access'] = FALSE;
    $element['match_operator']['#access'] = FALSE;
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    return InlineEntityFormBase::settingsSummary();
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);

    // Disable the table drag as we don't want that.
    $element['entities']['#cache']['contexts'][] = 'user.permissions';
    $element['entities']['#disable_tabledrag'] = TRUE;

    // Override the field title as we are only dealing with additional charges.
    $element['#field_title'] = $this->t('Additional Charges');

    if ($items->offsetExists($delta)) {
      // If the item exists but doesn't have an entity then remove the item.
      if (!$items[$delta]->entity) {
        unset($items[$delta]);
        unset($element['entities'][$delta]);
      }
    }

    foreach (Element::children($element['entities']) as $delta) {
      if (!isset($items[$delta]->entity) || $items[$delta]->entity->bundle() != 'additional_charge') {
        unset($element['entities'][$delta]);
      }
    }

    // Loop over the tickets and add the operations as required.
    $entities = $form_state->get([
      'inline_entity_form',
      $this->getIefId(),
      'entities',
    ]);
    $workflow = NULL;
    $has_form = (bool) $form_state
      ->get(['inline_entity_form', $this->getIefId(), 'form']);
    foreach (Element::children($element['entities']) as $delta) {
      $entity_element = &$element['entities'][$delta];
      $entity_form = $entities[$delta]['form'] ?? FALSE;

      // If we are showing the row, update the AJAX settings to hide the form
      // actions.
      if (!$entity_form) {
        // Make each entity form action hide the submit buttons.
        foreach (Element::children($entity_element['actions']) as $key) {
          $type = $entity_element['actions'][$key]['#type'] ?? NULL;
          if ($type == 'submit' && isset($entity_element['actions'][$key]['#ajax'])) {
            // phpcs:ignore Drupal.Arrays.Array.LongLineDeclaration
            $entity_element['actions'][$key]['#ajax']['callback'] = [static::class, 'ajaxCallback'];
          }
        }
      }
      // Otherwise hide the add new action so we don't have multiple open.
      else {
        $has_form = TRUE;
      }
    }

    // If we have an expanded item, hide all other operations.
    if ($has_form) {
      // Use a process to disable the outer form actions.
      $element['#process'][] = [static::class, 'disableActions'];

      // Disable IEF actions such as 'Add'.
      $element['actions']['#disabled'] = TRUE;

      // Loop over the rows to disable row operations.
      foreach (Element::children($element['entities']) as $delta) {
        $element['entities'][$delta]['actions']['#disabled'] = TRUE;
      }
    }

    // Set the IEF actions to use the ajax callback.
    foreach (Element::children($element['actions']) as $key) {
      // phpcs:ignore Drupal.Arrays.Array.LongLineDeclaration
      $element['actions'][$key]['#ajax']['callback'] = [static::class, 'ajaxCallback'];
    }

    return $element;
  }

  /**
   * Process callback to disable the outer form actions.
   */
  public static function disableActions(array $element, FormStateInterface $form_state, &$complete_form) {
    foreach (Element::children($complete_form['actions']) as $key) {
      $complete_form['actions'][$key]['#attributes']['disabled'] = TRUE;
    }
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function buildEntityFormActions($element) {
    $element = parent::buildEntityFormActions($element);
    foreach (Element::children($element['actions']) as $key) {
      // phpcs:ignore Drupal.Arrays.Array.LongLineDeclaration
      $element['actions'][$key]['#ajax']['callback'] = [static::class, 'ajaxCallback'];
    }

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  protected function getEntityTypeLabels() {
    // The admin has specified the exact labels that should be used.
    if ($this->getSetting('override_labels')) {
      return [
        'singular' => $this->getSetting('label_singular'),
        'plural' => $this->getSetting('label_plural'),
      ];
    }
    else {
      return [
        'singular' => $this->t('additional charge'),
        'plural' => $this->t('additional charges'),
      ];
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function isApplicable(FieldDefinitionInterface $field_definition) {
    // Only allow for order items on the contacts booking bundle of orders.
    return $field_definition->getTargetEntityTypeId() == 'commerce_order'
      && $field_definition->getName() == 'order_items';
  }

  /**
   * {@inheritdoc}
   */
  public static function submitSaveEntity($entity_form, FormStateInterface $form_state) {
    /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
    $order_item = $entity_form['#entity'];

    parent::submitSaveEntity($entity_form, $form_state);

    $form_object = $form_state->getFormObject();
    // The form object may be a CheckoutFlowBase object which does not extend
    // FormBase so needs another method for accessing the order.
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $form_object instanceof CheckoutFlowBase ? $form_object->getOrder() : $form_object->getEntity();

    // We're explicitly updating the order items, so skip refreshing. Otherwise
    // we get a double save and the entity in the form is out of date.
    $order->setRefreshState(OrderInterface::REFRESH_SKIP);

    $order_item->save();
    // Ensure the item is added to the order and the total recalculated.
    $order->addItem($order_item)
      ->save();
  }

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

    $element = inline_entity_form_get_element($form, $form_state);
    $remove_button = $form_state->getTriggeringElement();
    $delta = $remove_button['#ief_row_delta'];

    /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
    $order_item = $element['entities'][$delta]['form']['#entity'];

    // Get the right order entity.
    $form_object = $form_state->getFormObject();
    // The form object may be a CheckoutFlowBase object which does not extend
    // FormBase so needs another method for accessing the order.
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $form_object instanceof CheckoutFlowBase ? $form_object->getOrder() : $form_object->getEntity();

    // Remove the order item from the order, save the order and delete the order
    // item. We do this immediately so you don't have to separate save the page.
    $order->removeItem($order_item);
    $order->save();
    $order_item->delete();

    // Show status message to user.
    \Drupal::messenger()->addStatus(new TranslatableMarkup('This additional charge has been removed.'));
  }

  /**
   * Ajax callback to show or hide outer form actions.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   *   An AJAX response containing both the default IEF update and the commands
   *   for showing or hiding the outer form actions.
   */
  public static function ajaxCallback(array $form, FormStateInterface $form_state) {
    // Wrap the inline entity form ajax callback so we can add commands.
    // To do that, build a response from the callback.
    // @see FormAjaxResponseBuilder::buildResponse
    $form = inline_entity_form_get_element($form, $form_state);
    $request = \Drupal::request();
    $route_match = \Drupal::routeMatch();
    $response = \Drupal::service('main_content_renderer.ajax')->renderResponse($form, $request, $route_match);

    // Replace the outer form actions.
    $complete_form = $form_state->getCompleteForm();
    $actions = [];
    foreach (Element::children($complete_form['actions']) as $key) {
      $actions[$key] = $complete_form['actions'][$key];
    }
    $response->addCommand(new HtmlCommand('#edit-actions', $actions));

    return $response;
  }

}

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

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