acquia_commercemanager-8.x-1.122/modules/acm_checkout/src/Plugin/CheckoutPane/ShippingInformation.php

modules/acm_checkout/src/Plugin/CheckoutPane/ShippingInformation.php
<?php

namespace Drupal\acm_checkout\Plugin\CheckoutPane;

use Drupal\acm\ACMAddressFormatter;
use Drupal\acm\Element\AcmAddress;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides the contact information pane.
 *
 * @ACMCheckoutPane(
 *   id = "shipping_information",
 *   label = @Translation("Shipping information"),
 *   defaultStep = "shipping",
 *   wrapperElement = "fieldset",
 * )
 */
class ShippingInformation extends CheckoutPaneBase {

  use StoredAddressTrait;

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'weight' => 0,
    ] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function isVisible() {
    // @TODO: Uncomment once cart sets if items are shippable or not.
    // $cart = $this->getCart();
    // return $cart->getShippable();
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function buildPaneSummary() {
    $cart = $this->getCart();
    $shipping = $cart->getShipping();
    $address_formatter = new ACMAddressFormatter();
    /** @var \stdClass $shipping */
    $shipping = (object) ($shipping);
    return $address_formatter->render($shipping);
  }

  /**
   * {@inheritdoc}
   */
  public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $cart = $this->getCart();
    $address = $cart->getShipping();
    $address = (array) $address;
    $billing_address = $cart->getBilling();
    $billing_address = (array) $billing_address;

    $form_state->setTemporaryValue('address', $address);
    $form_state->setTemporaryValue('billing_address', $billing_address);

    $pane_form += $this->buildStoredAddressOptions($pane_form, $form_state, 'shipping', $address);

    $pane_form['address']['use_billing_address'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Use same address as billing'),
      '#default_value' => '',
      '#ajax' => [
        'callback' => [$this, 'updateAddressAjaxCallback'],
        'wrapper' => $pane_form['#wrapper_id'],
      ],
      '#weight' => -10,
    ];

    // Block proceeding checkout until shipping method is chosen.
    $complete_form['actions']['next']['#states'] = [
      'invisible' => [
        '#shipping_methods_wrapper' => ['value' => ''],
      ],
    ];

    $pane_form['shipping_methods'] = [
      '#type' => 'select',
      '#title' => t('Shipping Methods'),
      '#empty_option' => t('Available Shipping Methods'),
      '#default_value' => $cart->getShippingMethodAsString(),
      '#validated' => TRUE,
      '#attributes' => [
        'id' => ['shipping_methods_wrapper'],
      ],
    ];

    ShippingInformation::generateShippingEstimates(
      $address,
      $pane_form['shipping_methods']
    );

    $complete_form['actions']['get_shipping_methods'] = [
      '#type' => 'button',
      '#value' => $this->t('Estimate Shipping'),
      '#ajax' => [
        'callback' => [$this, 'updateAddressAjaxCallback'],
        'wrapper' => $pane_form['#wrapper_id'],
      ],
      '#weight' => -50,
    ];

    return $pane_form;
  }

  /**
   * Ajax handler for re-use address checkbox.
   */
  public static function updateAddressAjaxCallback($form, FormStateInterface $form_state) {
    $values = $form_state->getValue($form['#parents']);
    $values = $values['shipping_information'];
    $use_billing_address = $values['address']['use_billing_address'];
    $address = $form_state->getTemporaryValue('address');
    $shipping_methods =& $form['shipping_information']['shipping_methods'];
    if (!empty($use_billing_address)) {
      $address = $form_state->getTemporaryValue('billing_address');
    }
    else {
      // Check if a stored address was selected.
      if (isset($values['shipping_address_options']) && $values['shipping_address_options'] != 'new_address') {
        $address = self::findAddress($values['shipping_address_options']);
      }
      else {
        $address = [
          'region' => $values['address']['address_fields']['region'],
          'country_id' => $values['address']['address_fields']['country_id'],
          'street' => $values['address']['address_fields']['street'],
          'street2' => $values['address']['address_fields']['street2'],
          'postcode' => $values['address']['address_fields']['postcode'],
          'city' => $values['address']['address_fields']['city'],
          'firstname' => $values['address']['address_fields']['firstname'],
          'lastname' => $values['address']['address_fields']['lastname'],
          'telephone' => isset($values['address']['address_fields']['telephone']) ? $values['address']['address_fields']['telephone'] : '',
          'title' => isset($values['address']['address_fields']['title']) ? $values['address']['address_fields']['title'] : '',
        ];
      }
    }

    ShippingInformation::generateShippingEstimates(
      $address,
      $shipping_methods
    );

    if (isset($form['shipping_information']['address'])) {
      $address_fields =& $form['shipping_information']['address'];
      if (isset($address_fields['address_fields']['title'])) {
        $address_fields['address_fields']['title']['#value'] = isset($address['title']) ? $address['title'] : '';
      }
      if (isset($address_fields['address_fields']['telephone'])) {
        $address_fields['address_fields']['telephone']['#value'] = isset($address['telephone']) ? $address['telephone'] : '';
      }
      $address_fields['address_fields']['firstname']['#value'] = isset($address['firstname']) ? $address['firstname'] : '';
      $address_fields['address_fields']['lastname']['#value'] = isset($address['lastname']) ? $address['lastname'] : '';
      $address_fields['address_fields']['street']['#value'] = isset($address['street']) ? $address['street'] : '';
      $address_fields['address_fields']['street2']['#value'] = isset($address['street2']) ? $address['street2'] : '';
      $address_fields['address_fields']['dynamic_parts']['city']['#value'] = isset($address['city']) ? $address['city'] : '';
      $address_fields['address_fields']['dynamic_parts']['postcode']['#value'] = isset($address['postcode']) ? $address['postcode'] : '';
      $address_fields['address_fields']['dynamic_parts']['country_id']['#value'] = isset($address['country_id']) ? $address['country_id'] : '';

      $country = $address_fields['address_fields']['dynamic_parts']['country_id']['#value'];

      $dynamic_parts = AcmAddress::calculateDynamicParts($country);
      // Set the region value accordingly.
      $possiblyMatchingRegion = "";
      if ($address['region'] && $dynamic_parts['region']['#access']) {
        $subdivisionRepository = \Drupal::service('address.subdivision_repository');
        $regions = $subdivisionRepository->getList([$country]);
        $possiblyMatchingRegion = AcmAddress::fixRegionMess($address['region'], $regions);
      }
      // Noting that ['region']['#value'] will now be set to ""
      // if  $dynamic_parts['region']['#access'] is falsey
      // (which is what we want: clear any pre-existing region value).
      $address_fields['address_fields']['dynamic_parts']['region']['#value'] = $possiblyMatchingRegion;

      $address_fields['address_fields']['dynamic_parts'] = array_replace_recursive($address_fields['address_fields']['dynamic_parts'], $dynamic_parts);
    }

    return $form['shipping_information'];
  }

  /**
   * Generates shipping estimate based on address and chosen shipping method.
   *
   * @param array|object $address
   *   The object of address.
   * @param array $select
   *   Array with selected shipping method.
   */
  public static function generateShippingEstimates($address, array &$select) {

    // Default suffix (unset or updated later).
    $select['#suffix'] = t("No shipping methods available. Please complete this shipping address form and press the 'Estimate Shipping' button.");

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

    $hasCountrySet = FALSE;
    if (is_array($address)) {
      if (strlen((string) ($address['country_id'])) > 0) {
        $hasCountrySet = TRUE;
      }
    }
    elseif (is_object($address)) {
      $countryThing = "";
      if (isset($address->countryCode)) {
        $countryThing = $address->countryCode;
      }
      elseif (isset($address->country_id)) {
        $countryThing = $address->country_id;
      }
      if (strlen((string) ($countryThing)) > 0) {
        $hasCountrySet = TRUE;
      }
    }
    if (!$hasCountrySet) {
      return;
    }

    $cart = \Drupal::service('acm_cart.cart_storage');
    $user = \Drupal::service('acm.commerce_user_manager')->getAccount();

    unset($address['address_id']);

    try {
      // Some ecommerce backends like hybris require a shipping address to be
      // set before an estimate can be calculated, but we only want to update
      // the address if it's different than what's already set on the cart.
      $current_shipping = (array) $cart->getShipping();
      if (!self::isMateriallyTheSameAddress($current_shipping, (array) $address)) {
        $cart->setShipping($address);
        $cart->updateCart();
      }

      $customer_id = NULL;
      if ($user->isAuthenticated()) {
        $customer_id = $user->id();
      }

      $shipping_methods = \Drupal::service('acm.api')
        ->getShippingEstimates($cart->id(), $address, $customer_id);
    }
    catch (\Exception $error) {
      \Drupal::logger('acm_checkout')->error(t('Unable to fetch shipping methods: @reason', [
        '@reason' => $error->getMessage(),
      ]));
    }

    if (empty($shipping_methods)) {
      $select['#suffix'] = t('No shipping methods found, please check your address and try again.');
      return;
    }
    else {
      unset($select['#suffix']);
    }

    foreach ($shipping_methods as $method) {
      // Key needs to hold both carrier and method.
      $key = implode(
        ',',
        [
          $method['carrier_code'],
          $method['method_code'],
        ]
      );

      $name = t(
        '@carrier — @method (@price)',
        [
          '@carrier' => $method['carrier_title'],
          '@method' => $method['method_title'],
          '@price' => $method['amount'] ? $method['amount'] : t('Free'),
        ]
      );

      $select['#options'][$key] = $name;
    }

    // TODO If address has shipping method, if it matches an option,
    // set that as the selected default option.
    // TODO Use radio buttons instead of dropdown.
  }

  /**
   * Function isMateriallyTheSameAddress().
   *
   * Checks values in the new address against the corresponding
   * values in the incumbent address. If they are equal, we say that
   * the two addresses are materially the same.
   *
   * @param array $incumbentAddress
   *   The incumbent address.
   * @param array $newAddress
   *   The new address.
   *
   * @return bool
   *   True if a human would say the two address are the same.
   */
  public static function isMateriallyTheSameAddress(array $incumbentAddress, array $newAddress) {
    $isMateriallyTheSameAddress = TRUE;
    foreach ($newAddress as $key => $value) {
      if (array_key_exists($key, $incumbentAddress)) {
        if ($incumbentAddress[$key] != $newAddress[$key]) {
          $isMateriallyTheSameAddress = FALSE;
        }
      }
      else {
        $isMateriallyTheSameAddress = FALSE;
      }
    }
    return $isMateriallyTheSameAddress;
  }

  /**
   * {@inheritdoc}
   */
  public function validatePaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
  }

  /**
   * {@inheritdoc}
   */
  public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
    $values = $form_state->getValue($pane_form['#parents']);

    $shipping_method = NULL;

    if (isset($values['shipping_methods'])) {
      $shipping_method = $values['shipping_methods'];
      unset($values['shipping_methods']);
    }

    if (isset($values['shipping_address_options']) && $values['shipping_address_options'] != 'new_address') {
      $address = self::findAddress($values['shipping_address_options']);
    }
    else {
      $address_values = $values['address'];
      $address = [];

      array_walk_recursive($address_values, function ($value, $key) use (&$address) {
        $address[$key] = $value;
      });
    }

    $cart = $this->getCart();
    $cart->setShipping($address);

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

    list($carrier, $method) = explode(',', $shipping_method);

    $cart->setShippingMethod($carrier, $method);
    $cart->updateCart();
  }

}

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

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