![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-shipping/Model/Carrier/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Shipping\Model\Carrier; use Magento\Quote\Model\Quote\Address\RateResult\Error; use Magento\Shipping\Model\Shipment\Request; /** * Class AbstractCarrier * * phpcs:disable Magento2.Classes.AbstractApi * @api * @since 100.0.2 */ abstract class AbstractCarrier extends \Magento\Framework\DataObject implements AbstractCarrierInterface { public const DEBUG_KEYS_MASK = '****'; /** * @var string */ protected $_code; /** * @var array|null */ protected $_rates; /** * @var int */ protected $_numBoxes = 1; /** * @var string */ protected $_freeMethod = 'free_method'; /** * @var bool */ protected $_isFixed = false; /** * @var string[] */ protected $_customizableContainerTypes = []; public const USA_COUNTRY_ID = 'US'; public const CANADA_COUNTRY_ID = 'CA'; public const MEXICO_COUNTRY_ID = 'MX'; public const HANDLING_TYPE_PERCENT = 'P'; public const HANDLING_TYPE_FIXED = 'F'; public const HANDLING_ACTION_PERPACKAGE = 'P'; public const HANDLING_ACTION_PERORDER = 'O'; /** * @var array */ protected $_debugReplacePrivateDataKeys = []; /** * Core store config * * @var \Magento\Framework\App\Config\ScopeConfigInterface */ protected $_scopeConfig; /** * @var \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory */ protected $_rateErrorFactory; /** * @var \Psr\Log\LoggerInterface */ protected $_logger; /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory * @param \Psr\Log\LoggerInterface $logger * @param array $data */ public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory, \Psr\Log\LoggerInterface $logger, array $data = [] ) { parent::__construct($data); $this->_scopeConfig = $scopeConfig; $this->_rateErrorFactory = $rateErrorFactory; $this->_logger = $logger; } /** * Retrieve information from carrier configuration * * @param string $field * @return false|string */ public function getConfigData($field) { if (empty($this->_code)) { return false; } $path = 'carriers/' . $this->_code . '/' . $field; return $this->_scopeConfig->getValue( $path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $this->getStore() ); } /** * Retrieve config flag for store by field * * @param string $field * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ public function getConfigFlag($field) { if (empty($this->_code)) { return false; } $path = 'carriers/' . $this->_code . '/' . $field; return $this->_scopeConfig->isSetFlag( $path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $this->getStore() ); } /** * Do request to shipment. * * Implementation must be in overridden method * * @param Request $request * @return \Magento\Framework\DataObject * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function requestToShipment($request) { return new \Magento\Framework\DataObject(); } /** * Do return of shipment. * * Implementation must be in overridden method * * @param Request $request * @return \Magento\Framework\DataObject * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function returnOfShipment($request) { return new \Magento\Framework\DataObject(); } /** * Return container types of carrier * * @param \Magento\Framework\DataObject|null $params * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function getContainerTypes(\Magento\Framework\DataObject $params = null) { return []; } /** * Get allowed containers of carrier * * @param \Magento\Framework\DataObject|null $params * @return array|bool * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _getAllowedContainers(\Magento\Framework\DataObject $params = null) { $containersAll = $this->getContainerTypesAll(); if (empty($containersAll)) { return []; } if (empty($params)) { return $containersAll; } $containersFilter = $this->getContainerTypesFilter(); $containersFiltered = []; $method = $params->getMethod(); $countryShipper = $params->getCountryShipper(); $countryRecipient = $params->getCountryRecipient(); if (empty($containersFilter)) { return $containersAll; } if (!$params || !$method || !$countryShipper || !$countryRecipient) { return $containersAll; } if ($countryShipper == self::USA_COUNTRY_ID && $countryRecipient == self::USA_COUNTRY_ID) { $direction = 'within_us'; } else { if ($countryShipper == self::USA_COUNTRY_ID && $countryRecipient != self::USA_COUNTRY_ID) { $direction = 'from_us'; } else { return $containersAll; } } foreach ($containersFilter as $dataItem) { $containers = $dataItem['containers']; $filters = $dataItem['filters']; if (!empty($filters[$direction]['method']) && in_array($method, $filters[$direction]['method'])) { foreach ($containers as $container) { if (!empty($containersAll[$container])) { $containersFiltered[$container] = $containersAll[$container]; } } } } return !empty($containersFiltered) ? $containersFiltered : $containersAll; } /** * Get Container Types, that could be customized * * @return string[] */ public function getCustomizableContainerTypes() { return $this->_customizableContainerTypes; } /** * Return delivery confirmation types of carrier * * @param \Magento\Framework\DataObject|null $params * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function getDeliveryConfirmationTypes(\Magento\Framework\DataObject $params = null) { return []; } /** * Validate request for available ship countries. * * @param \Magento\Framework\DataObject $request * @return $this|bool|false|\Magento\Framework\Model\AbstractModel * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function checkAvailableShipCountries(\Magento\Framework\DataObject $request) { $speCountriesAllow = $this->getConfigData('sallowspecific'); /* * for specific countries, the flag will be 1 */ if ($speCountriesAllow && $speCountriesAllow == 1) { $showMethod = $this->getConfigData('showmethod'); $availableCountries = []; if ($this->getConfigData('specificcountry')) { $availableCountries = explode(',', $this->getConfigData('specificcountry')); } if ($availableCountries && in_array($request->getDestCountryId(), $availableCountries)) { return $this; } elseif ($showMethod && (!$availableCountries || $availableCountries && !in_array( $request->getDestCountryId(), $availableCountries )) ) { /** @var Error $error */ $error = $this->_rateErrorFactory->create(); $error->setCarrier($this->_code); $error->setCarrierTitle($this->getConfigData('title')); $errorMsg = $this->getConfigData('specificerrmsg'); $error->setErrorMessage( $errorMsg ? $errorMsg : __( 'Sorry, but we can\'t deliver to the destination country with this shipping module.' ) ); return $error; } else { /* * The admin set not to show the shipping module if the delivery country * is not within specific countries */ return false; } } return $this; } /** * Processing additional validation to check is carrier applicable. * * @param \Magento\Framework\DataObject $request * @return $this|bool|\Magento\Framework\DataObject * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @since 100.2.6 */ public function processAdditionalValidation(\Magento\Framework\DataObject $request) { return $this; } /** * Processing additional validation to check is carrier applicable. * * @param \Magento\Framework\DataObject $request * @return $this|bool|\Magento\Framework\DataObject * @deprecated 100.2.6 * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function proccessAdditionalValidation(\Magento\Framework\DataObject $request) { return $this->processAdditionalValidation($request); } /** * Determine whether current carrier enabled for activity * * @return bool */ public function isActive() { $active = $this->getConfigData('active'); return $active == 1 || $active == 'true'; } /** * Whether this carrier has fixed rates calculation * * @return bool */ public function isFixed() { return $this->_isFixed; } /** * Check if carrier has shipping tracking option available * * @return bool */ public function isTrackingAvailable() { return false; } /** * Check if carrier has shipping label option available * * @return bool */ public function isShippingLabelsAvailable() { return false; } /** * Retrieve sort order of current carrier * * @return string|null */ public function getSortOrder() { return $this->getConfigData('sort_order'); } /** * Check if the request has free shipping weight * * @param \Magento\Quote\Model\Quote\Address\RateRequest $request * @return bool */ private function hasFreeMethodWeight($request): bool { return ( $request->getFreeShipping() || ( $request->hasFreeMethodWeight() && ((float) $request->getFreeMethodWeight()) !== ((float) $request->getPackageWeight()) ) ); } /** * Allows free shipping when all product items have free shipping. * * @param \Magento\Quote\Model\Quote\Address\RateRequest $request * @return void * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _updateFreeMethodQuote($request) { if (!$this->hasFreeMethodWeight($request)) { return; } $freeMethod = $this->getConfigData($this->_freeMethod); if (!$freeMethod) { return; } $freeRateId = false; // phpstan:ignore if (is_object($this->_result)) { foreach ($this->_result->getAllRates() as $i => $item) { if ($item->getMethod() == $freeMethod) { $freeRateId = $i; break; } } } if ($freeRateId === false) { return; } $price = null; if ($request->getFreeMethodWeight() > 0) { // phpstan:ignore $this->_setFreeMethodRequest($freeMethod); // phpstan:ignore $result = $this->_getQuotes(); if ($result && ($rates = $result->getAllRates()) && count($rates) > 0) { if (count($rates) == 1 && $rates[0] instanceof \Magento\Quote\Model\Quote\Address\RateResult\Method) { $price = $rates[0]->getPrice(); } if (count($rates) > 1) { foreach ($rates as $rate) { if ($rate instanceof \Magento\Quote\Model\Quote\Address\RateResult\Method && $rate->getMethod() == $freeMethod ) { $price = $rate->getPrice(); } } } } } else { /** * if we can apply free shipping for all order we should force price * to $0.00 for shipping with out sending second request to carrier */ $price = 0; } /** * if we did not get our free shipping method in response we must use its old price */ if ($price !== null) { $this->_result->getRateById($freeRateId)->setPrice($price); } } /** * Get the handling fee for the shipping + cost * * @param float $cost * @return float final price for shipping method */ public function getFinalPriceWithHandlingFee($cost) { $handlingFee = (float)$this->getConfigData('handling_fee'); $handlingType = $this->getConfigData('handling_type'); if (!$handlingType) { $handlingType = self::HANDLING_TYPE_FIXED; } $handlingAction = $this->getConfigData('handling_action'); if (!$handlingAction) { $handlingAction = self::HANDLING_ACTION_PERORDER; } return $handlingAction == self::HANDLING_ACTION_PERPACKAGE ? $this->_getPerpackagePrice( $cost, $handlingType, $handlingFee ) : $this->_getPerorderPrice( $cost, $handlingType, $handlingFee ); } /** * Get final price for shipping method with handling fee per package * * @param float $cost * @param string $handlingType * @param float $handlingFee * @return float */ protected function _getPerpackagePrice($cost, $handlingType, $handlingFee) { if ($handlingType == self::HANDLING_TYPE_PERCENT) { return ($cost + $cost * $handlingFee / 100) * $this->_numBoxes; } return ($cost + $handlingFee) * $this->_numBoxes; } /** * Get final price for shipping method with handling fee per order * * @param float $cost * @param string $handlingType * @param float $handlingFee * @return float */ protected function _getPerorderPrice($cost, $handlingType, $handlingFee) { if ($handlingType == self::HANDLING_TYPE_PERCENT) { return $cost * $this->_numBoxes + $cost * $this->_numBoxes * $handlingFee / 100; } return $cost * $this->_numBoxes + $handlingFee; } /** * Gets the average weight of each box available for shipping * * @param float $weight in some measure * @return float */ public function getTotalNumOfBoxes($weight) { /* reset num box first before retrieve again */ $this->_numBoxes = 1; $maxPackageWeight = $this->getConfigData('max_package_weight'); if ($weight > $maxPackageWeight && $maxPackageWeight != 0) { $this->_numBoxes = ceil($weight / $maxPackageWeight); $weight = (float)$weight / $this->_numBoxes; } return $weight; } /** * Is state province required * * @return bool */ public function isStateProvinceRequired() { return false; } /** * Check if city option required * * @return bool */ public function isCityRequired() { return false; } /** * Determine whether zip-code is required for the country of destination * * @param string|null $countryId * @return bool * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function isZipCodeRequired($countryId = null) { return false; } /** * Log debug data to file * * @param mixed $debugData * @return void */ protected function _debug($debugData) { if ($this->getDebugFlag()) { $this->_logger->debug(var_export($debugData, true)); } } /** * Define if debugging is enabled * * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ public function getDebugFlag() { return $this->getConfigData('debug'); } /** * Used to call debug method from not Payment Method context * * @param mixed $debugData * @return void */ public function debugData($debugData) { $this->_debug($debugData); } /** * Getter for carrier code * * @return string */ public function getCarrierCode() { return $this->_code; } /** * Return content types of package * * @param \Magento\Framework\DataObject $params * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function getContentTypes(\Magento\Framework\DataObject $params) { return []; } /** * Recursive replace sensitive fields of XML document. * * For example if xml document has the following structure: * ```xml * <Request> * <LicenseNumber>E437FJFD</LicenseNumber> * <UserId>testUser1</UserId> * <Password>userPassword</Password> * </Request> * ``` * and sensitive fields are specified as `['UserId', 'Password']`, then sensitive fields * will be replaced by the mask(by default it is '****') * * @param string $data * @return string * @since 100.1.0 */ protected function filterDebugData($data) { try { $xml = new \SimpleXMLElement($data); $this->filterXmlData($xml); $data = $xml->asXML(); } catch (\Exception $e) { $this->_logger->critical($e); } return $data; } /** * Recursive replace sensitive xml nodes values by specified mask. * * @param \SimpleXMLElement $xml * @return void */ private function filterXmlData(\SimpleXMLElement $xml) { /** @var \SimpleXMLElement $child */ foreach ($xml->children() as $child) { if ($child->count()) { $this->filterXmlData($child); } elseif (in_array((string) $child->getName(), $this->_debugReplacePrivateDataKeys)) { $child[0] = self::DEBUG_KEYS_MASK; } } } }