getStoreId(); $available = $this->hasPhysicalItems($quote) && $this->scopeConfig->isSetFlag( self::XML_PATH_FLATRATE_ACTIVE, ScopeInterface::SCOPE_STORE, $storeId ); $freeShipping = $available && $this->isFreeShipping($quote); $baseAmount = $available && !$freeShipping ? (float)$this->scopeConfig->getValue( self::XML_PATH_FLATRATE_PRICE, ScopeInterface::SCOPE_STORE, $storeId ) : 0.0; $amount = $available ? (float)$this->priceCurrency->convertAndRound($baseAmount, $quote->getStore()) : 0.0; return [ 'available' => $available, 'free_shipping' => $freeShipping, 'quantity' => $this->getPhysicalQuantity($quote), 'base_amount' => $baseAmount, 'amount' => $amount, 'description' => $available ? $this->getDescription($storeId, $freeShipping) : '', ]; } public function isFreeShipping(Quote $quote): bool { if (!$this->hasPhysicalItems($quote) || !$quote->getStoreId()) { return false; } $address = clone $quote->getShippingAddress(); $address->setTotalQty($this->getPhysicalQuantity($quote)) ->setSubtotal((float)$quote->getSubtotal()) ->setBaseSubtotal((float)$quote->getBaseSubtotal()); $collection = $this->ruleCollectionFactory->create(); $collection->setValidationFilter( (int)$quote->getStore()->getWebsiteId(), (int)$quote->getCustomerGroupId(), (string)$quote->getCouponCode(), null, $address ); foreach ($collection as $rule) { if ((int)$rule->getSimpleFreeShipping() > 0 && $rule->getConditions()->validate($address) ) { return true; } } return false; } /** * @param AbstractItem[] $items */ public function isFreeShippingForItems(array $items): bool { foreach ($items as $item) { $quote = $item->getQuote(); if ($quote instanceof Quote) { return $this->isFreeShipping($quote); } $addressQuote = $item->getAddress()?->getQuote(); if ($addressQuote instanceof Quote) { return $this->isFreeShipping($addressQuote); } } return false; } private function hasPhysicalItems(Quote $quote): bool { return $this->getPhysicalQuantity($quote) > 0; } private function getPhysicalQuantity(Quote $quote): float { $quantity = 0.0; foreach ($quote->getAllVisibleItems() as $item) { if ($item->getProduct()->isVirtual()) { continue; } $quantity += (float)$item->getQty(); } return $quantity; } private function getDescription(int $storeId, bool $freeShipping): string { if ($freeShipping) { return (string)__('Free Shipping'); } $title = (string)$this->scopeConfig->getValue( self::XML_PATH_FLATRATE_TITLE, ScopeInterface::SCOPE_STORE, $storeId ); $name = (string)$this->scopeConfig->getValue( self::XML_PATH_FLATRATE_NAME, ScopeInterface::SCOPE_STORE, $storeId ); return trim($title . ($title !== '' && $name !== '' ? ' - ' : '') . $name); } }