getSourcesAssignedToStockOrderedByPriority = $getSourcesAssignedToStockOrderedByPriority; $this->getDefaultSortedSourcesResult = $getDefaultSortedSourcesResult; $this->getDistanceFromSourceToAddress = $getDistanceFromSourceToAddress; } /** * @inheritdoc * @throws LocalizedException */ public function execute(InventoryRequestInterface $inventoryRequest): SourceSelectionResultInterface { $destinationAddress = $inventoryRequest->getExtensionAttributes()->getDestinationAddress(); if ($destinationAddress === null) { throw new LocalizedException(__('No destination address was provided in the request')); } $stockId = $inventoryRequest->getStockId(); $sortedSources = $this->getEnabledSourcesOrderedByDistanceByStockId( $stockId, $destinationAddress ); return $this->getDefaultSortedSourcesResult->execute($inventoryRequest, $sortedSources); } /** * Get enabled sources ordered by priority by $stockId * * @param int $stockId * @param AddressInterface $address * @return array * * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Exception\LocalizedException */ private function getEnabledSourcesOrderedByDistanceByStockId( int $stockId, AddressInterface $address ): array { // We keep priority order as computational base $sources = $this->getSourcesAssignedToStockOrderedByPriority->execute($stockId); $sources = array_filter($sources, function (SourceInterface $source) { return $source->isEnabled(); }); $distanceBySourceCode = $sortSources = $sourcesWithoutDistance = []; foreach ($sources as $source) { try { $distanceBySourceCode[$source->getSourceCode()] = $this->getDistanceFromSourceToAddress->execute( $source, $address ); $sortSources[] = $source; } catch (LocalizedException $e) { $sourcesWithoutDistance[] = $source; } } // Sort sources by distance uasort( $sortSources, function (SourceInterface $a, SourceInterface $b) use ($distanceBySourceCode) { $distanceFromA = $distanceBySourceCode[$a->getSourceCode()]; $distanceFromB = $distanceBySourceCode[$b->getSourceCode()]; return ($distanceFromA < $distanceFromB) ? -1 : 1; } ); return array_merge($sortSources, $sourcesWithoutDistance); } }