| Current Path : /var/www/clients/client3/web2/web/vendor/magento/module-quote/Model/ |
| Current File : /var/www/clients/client3/web2/web/vendor/magento/module-quote/Model/ShippingMethodManagement.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\Quote\Model;
use Magento\Customer\Api\AddressRepositoryInterface;
use Magento\Customer\Api\Data\AddressInterfaceFactory;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Framework\Api\ExtensibleDataInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\StateException;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Api\Data\AddressInterface;
use Magento\Quote\Api\Data\EstimateAddressInterface;
use Magento\Quote\Api\Data\ShippingMethodInterface;
use Magento\Quote\Api\ShipmentEstimationInterface;
use Magento\Quote\Model\Cart\ShippingMethodConverter;
use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote\Address\Rate;
use Magento\Quote\Model\Quote\TotalsCollector;
use Magento\Quote\Model\ResourceModel\Quote\Address as QuoteAddressResource;
use Magento\Customer\Model\Data\Address as CustomerAddress;
/**
* Shipping method read service
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
*/
class ShippingMethodManagement implements
\Magento\Quote\Api\ShippingMethodManagementInterface,
\Magento\Quote\Model\ShippingMethodManagementInterface,
ShipmentEstimationInterface
{
/**
* Quote repository model
*
* @var CartRepositoryInterface
*/
protected $quoteRepository;
/**
* Shipping method converter
*
* @var ShippingMethodConverter
*/
protected $converter;
/**
* Customer Address repository
*
* @var AddressRepositoryInterface
*/
protected $addressRepository;
/**
* @var Quote\TotalsCollector
*/
protected $totalsCollector;
/**
* @var DataObjectProcessor $dataProcessor
*/
private $dataProcessor;
/**
* @var AddressInterfaceFactory $addressFactory
*/
private $addressFactory;
/**
* @var QuoteAddressResource
*/
private $quoteAddressResource;
/**
* @var CustomerSession
*/
private $customerSession;
/**
* Constructor
*
* @param CartRepositoryInterface $quoteRepository
* @param Cart\ShippingMethodConverter $converter
* @param AddressRepositoryInterface $addressRepository
* @param Quote\TotalsCollector $totalsCollector
* @param AddressInterfaceFactory|null $addressFactory
* @param QuoteAddressResource|null $quoteAddressResource
* @param CustomerSession|null $customerSession
*/
public function __construct(
CartRepositoryInterface $quoteRepository,
Cart\ShippingMethodConverter $converter,
AddressRepositoryInterface $addressRepository,
TotalsCollector $totalsCollector,
AddressInterfaceFactory $addressFactory = null,
QuoteAddressResource $quoteAddressResource = null,
CustomerSession $customerSession = null
) {
$this->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);
$this->customerSession = $customerSession ?? ObjectManager::getInstance()->get(CustomerSession::class);
}
/**
* @inheritDoc
*/
public function get($cartId)
{
/** @var Quote $quote */
$quote = $this->quoteRepository->getActive($cartId);
/** @var 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 Rate $shippingRate */
$shippingRate = $shippingAddress->getShippingRateByCode($shippingMethod);
if (!$shippingRate) {
return null;
}
return $this->converter->modelToDataObject($shippingRate, $quote->getQuoteCurrencyCode());
}
/**
* @inheritDoc
*/
public function getList($cartId)
{
$output = [];
/** @var 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 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;
}
/**
* Apply carrier code.
*
* @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 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, EstimateAddressInterface $address)
{
/** @var 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 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
* @throws InputException
* @throws NoSuchEntityException
*/
public function estimateByAddressId($cartId, $addressId)
{
/** @var 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->getAddress($addressId, $quote);
return $this->getShippingMethods($quote, $address);
}
/**
* Get estimated rates
*
* @param Quote $quote
* @param int $country
* @param string $postcode
* @param int $regionId
* @param string $region
* @param ExtensibleDataInterface|null $address
* @return ShippingMethodInterface[] An array of shipping methods.
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @deprecated 100.1.6
*/
protected function getEstimatedRates(
Quote $quote,
$country,
$postcode,
$regionId,
$region,
$address = null
) {
if (!$address) {
$address = $this->addressFactory->create()
->setCountryId($country)
->setPostcode($postcode)
->setRegionId($regionId);
}
return $this->getShippingMethods($quote, $address);
}
/**
* Get list of available shipping methods
*
* @param Quote $quote
* @param ExtensibleDataInterface $address
* @return ShippingMethodInterface[]
*/
private function getShippingMethods(Quote $quote, $address)
{
$output = [];
$shippingAddress = $quote->getShippingAddress();
$shippingAddress->addData($this->extractAddressData($address));
$shippingAddress->setCollectShippingRates(true);
$this->totalsCollector->collectAddressTotals($quote, $shippingAddress);
$quoteCustomerGroupId = $quote->getCustomerGroupId();
$customerGroupId = $this->customerSession->getCustomerGroupId();
$isCustomerGroupChanged = $quoteCustomerGroupId !== $customerGroupId;
if ($isCustomerGroupChanged) {
$quote->setCustomerGroupId($customerGroupId);
}
$shippingRates = $shippingAddress->getGroupedAllShippingRates();
foreach ($shippingRates as $carrierRates) {
foreach ($carrierRates as $rate) {
$output[] = $this->converter->modelToDataObject($rate, $quote->getQuoteCurrencyCode());
}
}
if ($isCustomerGroupChanged) {
$quote->setCustomerGroupId($quoteCustomerGroupId);
}
return $output;
}
/**
* Get transform address interface into Array
*
* @param ExtensibleDataInterface $address
* @return array
*/
private function extractAddressData($address)
{
$className = \Magento\Customer\Api\Data\AddressInterface::class;
if ($address instanceof AddressInterface) {
$className = AddressInterface::class;
} elseif ($address instanceof EstimateAddressInterface) {
$className = EstimateAddressInterface::class;
}
$addressData = $this->getDataObjectProcessor()->buildOutputDataArray(
$address,
$className
);
unset($addressData[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]);
return $addressData;
}
/**
* Gets the data object processor
*
* @return DataObjectProcessor
* @deprecated 101.0.0
*/
private function getDataObjectProcessor()
{
if ($this->dataProcessor === null) {
$this->dataProcessor = ObjectManager::getInstance()
->get(DataObjectProcessor::class);
}
return $this->dataProcessor;
}
/**
* Gets the address if exists for customer
*
* @param int $addressId
* @param Quote $quote
* @return CustomerAddress
* @throws InputException The shipping address is incorrect.
*/
private function getAddress(int $addressId, Quote $quote): CustomerAddress
{
$addresses = $quote->getCustomer()->getAddresses();
foreach ($addresses as $address) {
if ($addressId === (int)$address->getId()) {
return $address;
}
}
throw new InputException(__('The shipping address is missing. Set the address and try again.'));
}
}