quoteRepository = $quoteRepository; $this->converter = $converter; $this->addressRepository = $addressRepository; $this->totalsCollector = $totalsCollector; $this->addressFactory = $addressFactory ?: ObjectManager::getInstance() ->get(AddressInterfaceFactory::class); $this->quoteAddressResource = $quoteAddressResource ?: ObjectManager::getInstance() ->get(QuoteAddressResource::class); } /** * {@inheritDoc} */ public function get($cartId) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); /** @var \Magento\Quote\Model\Quote\Address $shippingAddress */ $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingMethod = $shippingAddress->getShippingMethod(); if (!$shippingMethod) { return null; } $shippingAddress->collectShippingRates(); /** @var \Magento\Quote\Model\Quote\Address\Rate $shippingRate */ $shippingRate = $shippingAddress->getShippingRateByCode($shippingMethod); if (!$shippingRate) { return null; } return $this->converter->modelToDataObject($shippingRate, $quote->getQuoteCurrencyCode()); } /** * {@inheritDoc} */ public function getList($cartId) { $output = []; /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); // no methods applicable for empty carts or carts with virtual products if ($quote->isVirtual() || 0 == $quote->getItemsCount()) { return []; } $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingAddress->collectShippingRates(); $shippingRates = $shippingAddress->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { $output[] = $this->converter->modelToDataObject($rate, $quote->getQuoteCurrencyCode()); } } return $output; } /** * {@inheritDoc} */ public function set($cartId, $carrierCode, $methodCode) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); try { $this->apply($cartId, $carrierCode, $methodCode); } catch (\Exception $e) { throw $e; } try { $this->quoteRepository->save($quote->collectTotals()); } catch (\Exception $e) { throw new CouldNotSaveException(__('The shipping method can\'t be set. %1', $e->getMessage())); } return true; } /** * @param int $cartId The shopping cart ID. * @param string $carrierCode The carrier code. * @param string $methodCode The shipping method code. * @return void * @throws InputException The shipping method is not valid for an empty cart. * @throws NoSuchEntityException CThe Cart includes virtual product(s) only, so a shipping address is not used. * @throws StateException The billing or shipping address is not set. * @throws \Exception */ public function apply($cartId, $carrierCode, $methodCode) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); if (0 == $quote->getItemsCount()) { throw new InputException( __('The shipping method can\'t be set for an empty cart. Add an item to cart and try again.') ); } if ($quote->isVirtual()) { throw new NoSuchEntityException( __('The Cart includes virtual product(s) only, so a shipping address is not used.') ); } $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { // Remove empty quote address $this->quoteAddressResource->delete($shippingAddress); throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingAddress->setShippingMethod($carrierCode . '_' . $methodCode); } /** * {@inheritDoc} */ public function estimateByAddress($cartId, \Magento\Quote\Api\Data\EstimateAddressInterface $address) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); // no methods applicable for empty carts or carts with virtual products if ($quote->isVirtual() || 0 == $quote->getItemsCount()) { return []; } return $this->getShippingMethods($quote, $address); } /** * @inheritdoc */ public function estimateByExtendedAddress($cartId, AddressInterface $address) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); // no methods applicable for empty carts or carts with virtual products if ($quote->isVirtual() || 0 == $quote->getItemsCount()) { return []; } return $this->getShippingMethods($quote, $address); } /** * {@inheritDoc} */ public function estimateByAddressId($cartId, $addressId) { /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); // no methods applicable for empty carts or carts with virtual products if ($quote->isVirtual() || 0 == $quote->getItemsCount()) { return []; } $address = $this->addressRepository->getById($addressId); return $this->getShippingMethods($quote, $address); } /** * Get estimated rates * * @param Quote $quote * @param int $country * @param string $postcode * @param int $regionId * @param string $region * @param \Magento\Framework\Api\ExtensibleDataInterface|null $address * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods. * @deprecated 100.1.6 */ protected function getEstimatedRates( \Magento\Quote\Model\Quote $quote, $country, $postcode, $regionId, $region, $address = null ) { if (!$address) { $address = $this->getAddressFactory()->create() ->setCountryId($country) ->setPostcode($postcode) ->setRegionId($regionId) ->setRegion($region); } return $this->getShippingMethods($quote, $address); } /** * Get list of available shipping methods * * @param \Magento\Quote\Model\Quote $quote * @param \Magento\Framework\Api\ExtensibleDataInterface $address * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] */ private function getShippingMethods(Quote $quote, $address) { $output = []; $shippingAddress = $quote->getShippingAddress(); $shippingAddress->addData($this->extractAddressData($address)); $shippingAddress->setCollectShippingRates(true); $this->totalsCollector->collectAddressTotals($quote, $shippingAddress); $shippingRates = $shippingAddress->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { $output[] = $this->converter->modelToDataObject($rate, $quote->getQuoteCurrencyCode()); } } return $output; } /** * Get transform address interface into Array * * @param \Magento\Framework\Api\ExtensibleDataInterface $address * @return array */ private function extractAddressData($address) { $className = \Magento\Customer\Api\Data\AddressInterface::class; if ($address instanceof \Magento\Quote\Api\Data\AddressInterface) { $className = \Magento\Quote\Api\Data\AddressInterface::class; } elseif ($address instanceof EstimateAddressInterface) { $className = EstimateAddressInterface::class; } return $this->getDataObjectProcessor()->buildOutputDataArray( $address, $className ); } /** * Gets the data object processor * * @return \Magento\Framework\Reflection\DataObjectProcessor * @deprecated 101.0.0 */ private function getDataObjectProcessor() { if ($this->dataProcessor === null) { $this->dataProcessor = ObjectManager::getInstance() ->get(DataObjectProcessor::class); } return $this->dataProcessor; } }