AvailabilityChecker::getCart()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Setono\SyliusReserveStockPlugin\Checker;
6
7
use Setono\SyliusReserveStockPlugin\Repository\InCartQuantityForProductVariantOrderItemRepositoryAwareInterface;
8
use Sylius\Component\Core\Model\ProductVariantInterface;
9
use Sylius\Component\Inventory\Checker\AvailabilityCheckerInterface;
10
use Sylius\Component\Inventory\Model\StockableInterface;
11
use Sylius\Component\Order\Context\CartContextInterface;
12
use Sylius\Component\Order\Context\CartNotFoundException;
13
use Sylius\Component\Order\Model\OrderInterface;
14
15
final class AvailabilityChecker implements AvailabilityCheckerInterface
16
{
17
    /**
18
     * @var AvailabilityCheckerInterface
19
     */
20
    private $availabilityChecker;
21
22
    /**
23
     * @var InCartQuantityForProductVariantOrderItemRepositoryAwareInterface
24
     */
25
    private $repository;
26
27
    /**
28
     * @var int
29
     */
30
    private $cartTtl;
31
32
    /**
33
     * @var CartContextInterface
34
     */
35
    private $cartContext;
36
37
    public function __construct(
38
        AvailabilityCheckerInterface $availabilityChecker,
39
        InCartQuantityForProductVariantOrderItemRepositoryAwareInterface $repository,
40
        int $cartTtl,
41
        CartContextInterface $cartContext
42
    ) {
43
        $this->availabilityChecker = $availabilityChecker;
44
        $this->repository = $repository;
45
        $this->cartTtl = $cartTtl;
46
        $this->cartContext = $cartContext;
47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function isStockAvailable(StockableInterface $stockable): bool
53
    {
54
        /** @var ProductVariantInterface $stockable */
55
        if (!$stockable instanceof ProductVariantInterface) {
0 ignored issues
show
introduced by
$stockable is always a sub-type of Sylius\Component\Core\Mo...ProductVariantInterface.
Loading history...
56
            return $this->availabilityChecker->isStockAvailable($stockable);
57
        }
58
59
        return $this->isStockSufficient($stockable, 1);
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function isStockSufficient(StockableInterface $stockable, int $quantity): bool
66
    {
67
        /** @var ProductVariantInterface $stockable */
68
        if (!$stockable instanceof ProductVariantInterface) {
0 ignored issues
show
introduced by
$stockable is always a sub-type of Sylius\Component\Core\Mo...ProductVariantInterface.
Loading history...
69
            return $this->availabilityChecker->isStockSufficient($stockable, $quantity);
70
        }
71
72
        if (!$stockable->isTracked()) {
73
            return true;
74
        }
75
76
        $stockAvailable = $stockable->getOnHand() -
77
            $stockable->getOnHold() -
78
            $this->repository->inCartQuantityForProductVariantExcludingOrder($stockable, $this->cartTtl, $this->getCart());
79
80
        return $quantity <= $stockAvailable;
81
    }
82
83
    /**
84
     * Tries to fetch the current cart and return it in that case. If not, null will be returned.
85
     *
86
     * A try/catch block is used because the underlying cart context throws an exception in case there is
87
     * no cart found and a cart will not be generated. In all situations where no cart can be found, we should
88
     * be sure `null` is returned.
89
     */
90
    private function getCart(): ?OrderInterface
91
    {
92
        try {
93
            return $this->cartContext->getCart();
94
        } catch (CartNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
95
        }
96
97
        return null;
98
    }
99
}
100