123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Quote\Model\Quote\Address\Total;
- use Magento\Framework\Pricing\PriceCurrencyInterface;
- use Magento\Quote\Api\Data\AddressInterface;
- use Magento\Quote\Model\Quote\Address\FreeShippingInterface;
- /**
- * Collect totals for shipping.
- */
- class Shipping extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
- {
- /**
- * @var PriceCurrencyInterface
- */
- protected $priceCurrency;
- /**
- * @var FreeShippingInterface
- */
- protected $freeShipping;
- /**
- * @param PriceCurrencyInterface $priceCurrency
- * @param FreeShippingInterface $freeShipping
- */
- public function __construct(
- PriceCurrencyInterface $priceCurrency,
- FreeShippingInterface $freeShipping
- ) {
- $this->priceCurrency = $priceCurrency;
- $this->freeShipping = $freeShipping;
- $this->setCode('shipping');
- }
- /**
- * Collect totals information about shipping
- *
- * @param \Magento\Quote\Model\Quote $quote
- * @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
- * @param \Magento\Quote\Model\Quote\Address\Total $total
- * @return $this
- * @SuppressWarnings(PHPMD.NPathComplexity)
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function collect(
- \Magento\Quote\Model\Quote $quote,
- \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
- \Magento\Quote\Model\Quote\Address\Total $total
- ) {
- parent::collect($quote, $shippingAssignment, $total);
- $address = $shippingAssignment->getShipping()->getAddress();
- $method = $shippingAssignment->getShipping()->getMethod();
- $total->setTotalAmount($this->getCode(), 0);
- $total->setBaseTotalAmount($this->getCode(), 0);
- if (!count($shippingAssignment->getItems())) {
- return $this;
- }
- $data = $this->getAssignmentWeightData($address, $shippingAssignment->getItems());
- $address->setItemQty($data['addressQty']);
- $address->setWeight($data['addressWeight']);
- $address->setFreeMethodWeight($data['freeMethodWeight']);
- $addressFreeShipping = (bool)$address->getFreeShipping();
- $isFreeShipping = $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems());
- $address->setFreeShipping($isFreeShipping);
- if (!$addressFreeShipping && $isFreeShipping) {
- $data = $this->getAssignmentWeightData($address, $shippingAssignment->getItems());
- $address->setItemQty($data['addressQty']);
- $address->setWeight($data['addressWeight']);
- $address->setFreeMethodWeight($data['freeMethodWeight']);
- }
- $address->collectShippingRates();
- if ($method) {
- foreach ($address->getAllShippingRates() as $rate) {
- if ($rate->getCode() == $method) {
- $store = $quote->getStore();
- $amountPrice = $this->priceCurrency->convert(
- $rate->getPrice(),
- $store
- );
- $total->setTotalAmount($this->getCode(), $amountPrice);
- $total->setBaseTotalAmount($this->getCode(), $rate->getPrice());
- $shippingDescription = $rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle();
- $address->setShippingDescription(trim($shippingDescription, ' -'));
- $total->setBaseShippingAmount($rate->getPrice());
- $total->setShippingAmount($amountPrice);
- $total->setShippingDescription($address->getShippingDescription());
- break;
- }
- }
- }
- return $this;
- }
- /**
- * Add shipping totals information to address object
- *
- * @param \Magento\Quote\Model\Quote $quote
- * @param \Magento\Quote\Model\Quote\Address\Total $total
- * @return array
- * @SuppressWarnings(PHPMD.UnusedFormalParameter)
- */
- public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total)
- {
- $amount = $total->getShippingAmount();
- $shippingDescription = $total->getShippingDescription();
- $title = ($shippingDescription)
- ? __('Shipping & Handling (%1)', $shippingDescription)
- : __('Shipping & Handling');
- return [
- 'code' => $this->getCode(),
- 'title' => $title,
- 'value' => $amount
- ];
- }
- /**
- * Get Shipping label
- *
- * @return \Magento\Framework\Phrase
- */
- public function getLabel()
- {
- return __('Shipping');
- }
- /**
- * Gets shipping assignments data like items weight, address weight, items quantity.
- *
- * @param AddressInterface $address
- * @param array $items
- * @return array
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- */
- private function getAssignmentWeightData(AddressInterface $address, array $items): array
- {
- $address->setWeight(0);
- $address->setFreeMethodWeight(0);
- $addressWeight = $address->getWeight();
- $freeMethodWeight = $address->getFreeMethodWeight();
- $addressFreeShipping = (bool)$address->getFreeShipping();
- $addressQty = 0;
- foreach ($items as $item) {
- /**
- * Skip if this item is virtual
- */
- if ($item->getProduct()->isVirtual()) {
- continue;
- }
- /**
- * Children weight we calculate for parent
- */
- if ($item->getParentItem()) {
- continue;
- }
- $itemQty = (float)$item->getQty();
- $itemWeight = (float)$item->getWeight();
- if ($item->getHasChildren() && $item->isShipSeparately()) {
- foreach ($item->getChildren() as $child) {
- if ($child->getProduct()->isVirtual()) {
- continue;
- }
- $addressQty += $child->getTotalQty();
- if (!$item->getProduct()->getWeightType()) {
- $itemWeight = (float)$child->getWeight();
- $itemQty = (float)$child->getTotalQty();
- $addressWeight += ($itemWeight * $itemQty);
- $rowWeight = $this->getItemRowWeight(
- $addressFreeShipping,
- $itemWeight,
- $itemQty,
- $child->getFreeShipping()
- );
- $freeMethodWeight += $rowWeight;
- $item->setRowWeight($rowWeight);
- }
- }
- if ($item->getProduct()->getWeightType()) {
- $addressWeight += ($itemWeight * $itemQty);
- $rowWeight = $this->getItemRowWeight(
- $addressFreeShipping,
- $itemWeight,
- $itemQty,
- $item->getFreeShipping()
- );
- $freeMethodWeight += $rowWeight;
- $item->setRowWeight($rowWeight);
- }
- } else {
- if (!$item->getProduct()->isVirtual()) {
- $addressQty += $itemQty;
- }
- $addressWeight += ($itemWeight * $itemQty);
- $rowWeight = $this->getItemRowWeight(
- $addressFreeShipping,
- $itemWeight,
- $itemQty,
- $item->getFreeShipping()
- );
- $freeMethodWeight += $rowWeight;
- $item->setRowWeight($rowWeight);
- }
- }
- return [
- 'addressQty' => $addressQty,
- 'addressWeight' => $addressWeight,
- 'freeMethodWeight' => $freeMethodWeight
- ];
- }
- /**
- * Calculates item row weight.
- *
- * @param bool $addressFreeShipping
- * @param float $itemWeight
- * @param float $itemQty
- * @param bool $freeShipping
- * @return float
- */
- private function getItemRowWeight(
- bool $addressFreeShipping,
- float $itemWeight,
- float $itemQty,
- $freeShipping
- ): float {
- $rowWeight = $itemWeight * $itemQty;
- if ($addressFreeShipping || $freeShipping === true) {
- $rowWeight = 0;
- } elseif (is_numeric($freeShipping)) {
- $freeQty = $freeShipping;
- if ($itemQty > $freeQty) {
- $rowWeight = $itemWeight * ($itemQty - $freeQty);
- } else {
- $rowWeight = 0;
- }
- }
- return (float)$rowWeight;
- }
- }
|