commercetools-8.x-1.2-alpha1/modules/commercetools_content/src/Form/OrderSubmissionForm.php

modules/commercetools_content/src/Form/OrderSubmissionForm.php
<?php

namespace Drupal\commercetools_content\Form;

use Drupal\commercetools\CommercetoolsApiServiceInterface;
use Drupal\commercetools\CommercetoolsCarts;
use Drupal\commercetools\CommercetoolsCustomers;
use Drupal\commercetools\CommercetoolsLocalization;
use Drupal\commercetools\CommercetoolsService;
use Drupal\commercetools\Routing\UiModulesRouteProviderBase;
use Drupal\commercetools_content\Routing\RouteProvider;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides order submission form.
 */
class OrderSubmissionForm extends FormBase {

  /**
   * The Commercetools service.
   *
   * @var \Drupal\commercetools\CommercetoolsService
   */
  protected CommercetoolsService $ct;
  /**
   * The Commercetools API service.
   *
   * @var \Drupal\commercetools\CommercetoolsApiServiceInterface
   */
  protected CommercetoolsApiServiceInterface $ctApi;

  /**
   * The commercetools cart service.
   *
   * @var \Drupal\commercetools\CommercetoolsCarts
   */
  protected CommercetoolsCarts $ctCart;

  /**
   * The commercetools customers service.
   *
   * @var \Drupal\commercetools\CommercetoolsCustomers
   */
  protected CommercetoolsCustomers $ctCustomers;

  /**
   * The customers addresses.
   *
   * @var array
   */
  protected array $customerAddresses = [
    CommercetoolsCustomers::SHIPPING_ADDRESS_KEY => NULL,
    CommercetoolsCustomers::BILLING_ADDRESS_KEY  => NULL,
  ];

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $instance = parent::create($container);
    $instance->ctApi = $container->get('commercetools.api');
    $instance->ct = $container->get('commercetools');
    $instance->ctCart = $container->get('commercetools.carts');
    $instance->ctCustomers = $container->get('commercetools.customers');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'commercetools_content_order_submission';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $install_state = NULL) {
    $cart = $this->buildCartWithCustomerAddresses();

    $addressTypes = [
      CommercetoolsCustomers::SHIPPING_ADDRESS_KEY => $this->t('Shipping address'),
      CommercetoolsCustomers::BILLING_ADDRESS_KEY => $this->t('Billing address'),
    ];

    foreach ($addressTypes as $key => $label) {
      $addressValues = $cart[$key];
      $form[$key] = [
        '#type' => 'fieldset',
        '#tree' => TRUE,
        '#weight' => 1,
        '#attributes' => [
          'class' => ['shadow', 'p-3', 'bg-primary', 'bg-opacity-10'],
        ],
        'label' => [
          '#type' => 'html_tag',
          '#tag' => 'h2',
          '#value' => $label,
          '#weight' => -10,
          '#attributes' => [
            'class' => ['pb-3', 'mb-4', 'border-bottom'],
          ],
        ],
      ];

      $addressFields = [];
      if (!$this->currentUser()->isAuthenticated()) {
        $addressFields['new'] = $this->addressFields($addressValues);
      }
      else {
        $selectAddressSelector = ':input[name="' . $key . '[selected]"]';
        $stateNewAddress = [$selectAddressSelector => ['value' => 'new']];

        // Build fields for new addresses or address in cart that not saved.
        $addressFields['new'] = ['#type' => 'container'];
        $addressFields['new']['#states']['visible'][] = $stateNewAddress;
        $addressFields['new'] += $this->addressFields($addressValues && empty($addressValues['id']) ? $addressValues : []);
        array_walk($addressFields['new'], function (&$field) use ($stateNewAddress) {
          if (isset($field['#required'])) {
            $field['#required'] = FALSE;
            $field['#states']['required'][] = $stateNewAddress;
          }
        });

        // Build fields all addresses.
        if ($this->customerAddresses[$key]) {
          foreach ($this->customerAddresses[$key] as $addressKey => $address) {
            $existedAddressFields = $this->addressFields($address);
            array_walk($existedAddressFields, function (&$field) {
              $field['#disabled'] = TRUE;
              unset($field['#required']);
            });

            $addressFields[$addressKey] = ['#type' => 'container'];
            $addressFields[$addressKey]['#states']['visible'][] = [$selectAddressSelector => ['value' => $addressKey]];
            $addressFields[$addressKey] += $existedAddressFields;
          }
        }

        $addressFields['save'] = [
          '#type' => 'checkbox',
          '#title' => $this->t('Save this new address to reuse in the next orders'),
          '#attributes' => ['class' => ['saveAddress']],
          '#states' => [
            'visible' => $stateNewAddress,
          ],
        ];

        $addressFields['title'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Fill the title to name this address in the list of saved addresses'),
          '#states' => [
            'visible' => [
              ':input[name="' . $key . '[save]"]' => ['checked' => TRUE],
            ],
          ],
        ];
        $addressFields['set_default'] = [
          '#type' => 'checkbox',
          '#title' => $this->t('Use this address as default for the next orders'),
          '#states' => [
            'visible' => [
              ':input[name="' . $key . '[save]"]' => ['checked' => TRUE],
            ],
          ],
        ];

        if ($this->customerAddresses[$key]) {
          $addressFields['selected'] = [
            '#type' => 'select',
            '#title' => $this->t('Fill a new address or choose from saved'),
            '#options' => ['new' => $this->t('Add a new address')] + array_filter(array_column($this->customerAddresses[$key], 'title', 'id')),
            '#default_value' => $addressValues['id'] ?? 'new',
            '#weight' => -9,
          ];
        }
      }

      $form[$key] += $addressFields;
    }

    $form['same_address'] = [
      '#prefix' => '<div class="mt-4 mb-4 shadow p-3 bg-primary bg-opacity-10">',
      '#suffix' => '</div>',
      '#type' => 'checkbox',
      '#title' => $this->t('Billing address same as shipping address'),
      '#default_value' => empty($cart['billingAddress']),
      '#weight' => 2,
    ];

    $form['billingAddress']['#weight'] = 3;
    foreach ($form['billingAddress']['new'] as &$element) {
      if (isset($element['#required'])) {
        $element['#required'] = FALSE;
        $element['#states'] = [
          'required' => [
            ':input[name="same_address"]' => ['checked' => FALSE],
            ':input[name="billingAddress[selected]"]' => ['value' => 'new'],
          ],
        ];
      }
    }
    $form['billingAddress']['#states'] = [
      'invisible' => [
        ':input[name="same_address"]' => ['checked' => TRUE],
      ],
    ];

    $form['actions'] = [
      '#type' => 'actions',
      'submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Save & Continue'),
      ],
    ];

    $form_state->setValue('test', 'test1');

    return $form;
  }

  /**
   * Add fields with values to each address.
   */
  protected function addressFields(?array $addressValues): array {
    return [
      'firstName' => [
        '#type' => 'textfield',
        '#title' => $this->t('First name'),
        '#default_value' => $addressValues['firstName'] ?? NULL,
        '#required' => TRUE,
      ],
      'lastName' => [
        '#type' => 'textfield',
        '#title' => $this->t('Last name'),
        '#default_value' => $addressValues['lastName'] ?? NULL,
        '#required' => TRUE,
      ],
      'email' => [
        '#type' => 'email',
        '#title' => $this->t('Email'),
        '#default_value' => $addressValues['email'] ?? $this->currentUser()->getEmail() ?? NULL,
        '#disabled' => $this->currentUser()->isAuthenticated(),
        '#attributes' => ['class' => [$this->currentUser()->isAuthenticated() ? 'disabled' : '']],
        '#required' => TRUE,
      ],
      'country' => [
        '#type' => 'textfield',
        '#title' => $this->t('Country'),
        '#default_value' => $this->config(CommercetoolsLocalization::CONFIGURATION_NAME)
          ->get(CommercetoolsLocalization::CONFIG_COUNTRY),
        '#disabled' => TRUE,
        '#attributes' => ['class' => ['disabled']],
      ],
      'streetName' => [
        '#type' => 'textfield',
        '#title' => $this->t('Street Address'),
        '#default_value' => $addressValues['streetName'] ?? NULL,
        '#required' => TRUE,
      ],
      'streetNumber' => [
        '#type' => 'textfield',
        '#title' => $this->t('Street number'),
        '#default_value' => $addressValues['streetNumber'] ?? NULL,
      ],
      'state' => [
        '#type' => 'textfield',
        '#title' => $this->t('State'),
        '#default_value' => $addressValues['state'] ?? NULL,
        '#required' => TRUE,
      ],
      'city' => [
        '#type' => 'textfield',
        '#title' => $this->t('City'),
        '#default_value' => $addressValues['city'] ?? NULL,
        '#required' => TRUE,
      ],
      'postalCode' => [
        '#type' => 'textfield',
        '#title' => $this->t('ZIP code'),
        '#default_value' => $addressValues['postalCode'] ?? NULL,
        '#required' => TRUE,
      ],
      'phone' => [
        '#type' => 'textfield',
        '#title' => $this->t('Phone number'),
        '#default_value' => $addressValues['phone'] ?? NULL,
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $cart = $this->ctCart->getCurrentCart()->getData();
    $formValues = $form_state->getValues();
    $isAnonymous = !$this->currentUser()->isAuthenticated();

    $resolveAddress = function ($type) use ($formValues, $isAnonymous) {
      if ($isAnonymous) {
        return $formValues[$type]['new'];
      }
      $addressKey = $formValues[$type]['selected'] ?? 'new';
      $isNewAddress = $addressKey === 'new';
      $address = $isNewAddress
        ? $formValues[$type]['new']
        : $this->customerAddresses[$type][$addressKey];

      if ($isNewAddress && $formValues[$type]['save']) {
        $address['title'] = $formValues[$type]['title'];
        $address = $this->ctCustomers->addAddress($address, $type, $formValues[$type]['set_default']);
      }
      return $address;
    };

    $shippingAddress = $resolveAddress(CommercetoolsCustomers::SHIPPING_ADDRESS_KEY);

    $billingAddress = $formValues['same_address']
      ? $shippingAddress
      : $resolveAddress(CommercetoolsCustomers::BILLING_ADDRESS_KEY);

    try {
      $response = $this->ctCart->updateCart($cart['id'], $cart['version'], [
        [
          'setShippingAddress' => [
            'address' => $shippingAddress,
          ],
        ],
        [
          'setBillingAddress' => [
            'address' => $billingAddress,
          ],
        ],
      ]);

      $order = $this->ctCart->createOrderFromCart($response->getData())->getData();
      $this->ctCart->deleteCurrentCart();
      $form_state->setRedirect(RouteProvider::ROUTE_PREFIX . UiModulesRouteProviderBase::PAGE_USER_ORDER_ROUTE, [
        'user' => $this->currentUser()->id(),
        'orderId' => $order['id'],
      ]);
    }
    catch (\Exception $e) {
      $this->logger('commercetools_content')->error('OrderSubmissionForm: ' . $e->getMessage());
      $form_state->setRebuild();
    }
  }

  /**
   * Build the cart payload by merging in the authenticated user’s addresses.
   */
  protected function buildCartWithCustomerAddresses() {
    $billingSame = FALSE;
    $cart = $this->ctCart->getCurrentCart()->getData();
    if (!empty($cart['shippingAddress']['id']) && !empty($cart['billingAddress']['id']) &&
      $cart['shippingAddress']['id'] === $cart['billingAddress']['id']) {
      $cart['billingAddress'] = NULL;
      $billingSame = TRUE;
    }

    if (!$this->currentUser()->isAuthenticated()) {
      return $cart;
    }

    $addressData = $this->ctCustomers->getAddressDataByCustomer();

    $fillTitle = function (array $addr) {
      $addr['title'] ??= $addr['id'];
      return $addr;
    };

    foreach ([CommercetoolsCustomers::SHIPPING_ADDRESS_KEY, CommercetoolsCustomers::BILLING_ADDRESS_KEY] as $type) {
      $multiKey = CommercetoolsCustomers::ADDRESSES_MULTIPLE_KEYS[$type];

      $addresses = array_column($addressData[$multiKey], NULL, 'id');
      $this->customerAddresses[$type] = array_map($fillTitle, $addresses);

      if (empty($cart[$type]) && ($type !== CommercetoolsCustomers::BILLING_ADDRESS_KEY || !$billingSame)) {
        $cart[$type] = $addresses[$addressData['default' . ucfirst($type) . 'Id']] ?? NULL;
      }
    }

    return $cart;
  }

}

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

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