Completed
Push — master ( b9260b...b1a7da )
by Joachim
06:19
created

ProductVariantCurrencyConverter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Setono\SyliusStockMovementPlugin\CurrencyConverter;
6
7
use Money\Currency;
8
use Money\Money;
9
use Safe\Exceptions\StringsException;
10
use Setono\SyliusStockMovementPlugin\Exception\CurrencyConversionException;
11
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
12
use Sylius\Component\Core\Model\ChannelInterface;
13
use Sylius\Component\Core\Model\ProductVariantInterface;
14
15
final class ProductVariantCurrencyConverter extends CurrencyConverter
16
{
17
    /** @var ChannelRepositoryInterface */
18
    private $channelRepository;
19
20
    public function __construct(ChannelRepositoryInterface $channelRepository)
21
    {
22
        $this->channelRepository = $channelRepository;
23
    }
24
25
    /**
26
     * @throws StringsException
27
     */
28
    public function convert(int $amount, string $sourceCurrency, string $targetCurrency, array $conversionContext = []): Money
29
    {
30
        if(!$this->supports($amount, $sourceCurrency, $targetCurrency, $conversionContext)) {
31
            throw new CurrencyConversionException($amount, $sourceCurrency, $targetCurrency, $conversionContext);
32
        }
33
34
        /** @var ProductVariantInterface $productVariant */
35
        $productVariant = $conversionContext['productVariant'];
36
37
        $productVariantSourceAmount = $productVariantTargetAmount = null;
38
39
        foreach ($productVariant->getChannelPricings() as $channelPricing) {
40
            /** @var ChannelInterface|null $channel */
41
            $channel = $this->channelRepository->findOneByCode($channelPricing->getChannelCode());
42
            if (null === $channel) {
43
                continue;
44
            }
45
46
            $baseCurrency = $channel->getBaseCurrency();
47
            if (null === $baseCurrency) {
48
                continue;
49
            }
50
51
            $baseCurrencyCode = $baseCurrency->getCode();
52
            if (null === $baseCurrencyCode) {
53
                continue;
54
            }
55
56
            if ($sourceCurrency === $baseCurrencyCode) {
57
                $productVariantSourceAmount = $channelPricing->getPrice();
58
            } elseif ($targetCurrency === $baseCurrencyCode) {
59
                $productVariantTargetAmount = $channelPricing->getPrice();
60
            }
61
        }
62
63
        if (null === $productVariantSourceAmount || null === $productVariantTargetAmount) {
0 ignored issues
show
introduced by
The condition null === $productVariantTargetAmount is always true.
Loading history...
64
            throw new CurrencyConversionException($amount, $sourceCurrency, $targetCurrency, $conversionContext);
65
        }
66
67
        $exchangeRate = $productVariantSourceAmount / $productVariantTargetAmount;
68
69
        $convertedAmount = round($amount / $exchangeRate);
70
71
        return new Money((int) $convertedAmount, new Currency($targetCurrency));
72
    }
73
74
    public function supports(int $amount, string $sourceCurrency, string $targetCurrency, array $conversionContext = []): bool
75
    {
76
        return isset($conversionContext['productVariant'])
77
            && $conversionContext['productVariant'] instanceof ProductVariantInterface;
78
    }
79
}
80