Passed
Pull Request — master (#27)
by Jason
03:18 queued 54s
created

ProductInventoryManager::validate()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 3
nc 2
nop 1
1
<?php
2
3
namespace Dynamic\Foxy\Inventory\Extension;
4
5
use Dynamic\Foxy\Inventory\Model\CartReservation;
6
use Dynamic\Foxy\Orders\Model\OrderDetail;
7
use SilverStripe\Forms\CheckboxField;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\NumericField;
10
use SilverStripe\Forms\ReadonlyField;
11
use SilverStripe\ORM\ArrayList;
12
use SilverStripe\ORM\DataExtension;
13
use SilverStripe\ORM\DataList;
14
use SilverStripe\ORM\ValidationResult;
15
use UncleCheese\DisplayLogic\Forms\Wrapper;
16
17
class ProductInventoryManager extends DataExtension
18
{
19
    /**
20
     * @var array
21
     */
22
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
23
        'ControlInventory' => 'Boolean',
24
        'PurchaseLimit' => 'Int',
25
    ];
26
27
    /**
28
     * @param FieldList $fields
29
     */
30
    public function updateCMSFields(FieldList $fields)
31
    {
32
        $fields->removeByName([
33
            'ControlInventory',
34
            'PurchaseLimit',
35
            'EmbargoLimit',
36
            'NumberPurchased',
37
        ]);
38
39
        $fields->addFieldsToTab('Root.Inventory', [
40
            Wrapper::create(
41
                CheckboxField::create('ControlInventory', 'Control Inventory?')
42
                    ->setDescription('limit the number of this product available for purchase'),
43
                Wrapper::create(
44
                    NumericField::create('PurchaseLimit')
45
                        ->setTitle('Number Available')
46
                        ->setDescription('add to cart form will be disabled once number available equals purchased'),
47
                    ReadonlyField::create('NumberAvailable', 'Remaining Available', $this->getNumberAvailable())
48
                        ->setDescription('This takes into account products added to the cart. Products removed from the cart may persist in the "Cart Reservations" until the expiration time.')//,
49
                )->displayIf('ControlInventory')->isChecked()->end()
50
            )->displayIf('Available')->isChecked()->end(),
51
        ]);
52
    }
53
54
    /**
55
     * @param ValidationResult $validationResult
56
     * @throws \SilverStripe\ORM\ValidationException
57
     */
58
    public function validate(ValidationResult $validationResult)
59
    {
60
        parent::validate($validationResult);
61
62
        if ($this->owner->ControlInventory && $this->owner->PurchaseLimit == 0) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->owner->PurchaseLimit of type mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
63
            $validationResult->addFieldError('PurchaseLimit', 'You must specify a purchase limit more than 0');
64
        }
65
    }
66
67
    /**
68
     * @param $available
69
     */
70
    public function updateGetIsAvailable(&$available)
71
    {
72
        if ($this->owner->ControlInventory && !$this->owner->Variations()->count()) {
73
            $reserved = $this->getCartReservations()->count();
74
            $sold = $this->getNumberPurchased();
75
76
            if ((int)$reserved + (int)$sold >= (int)$this->owner->PurchaseLimit) {
77
                $available = true;
78
            } else {
79
                $available = false;
80
            }
81
        } elseif ($this->owner->Variations()->count()) {
82
            foreach ($this->owner->Variations() as $variation) {
83
                $available = false;
84
                if ($variation->getIsAvailable()) {
85
                    $available = true;
86
                }
87
            }
88
        }
89
    }
90
91
    /**
92
     * @return bool
93
     */
94
    public function getHasInventory()
95
    {
96
        return $this->owner->ControlInventory && $this->owner->PurchaseLimit != 0;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->owner->PurchaseLimit of type mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
97
    }
98
99
    /**
100
     * @return bool
101
     */
102
    public function getIsProductAvailable()
103
    {
104
        if ($this->owner->getHasInventory()) {
105
            return $this->getNumberAvailable() > 0;
106
        }
107
108
        return true;
109
    }
110
111
    /**
112
     * @return int|void
113
     */
114
    public function getNumberAvailable()
115
    {
116
        return (int)$this->owner->PurchaseLimit - (int)$this->getNumberPurchased() - (int)$this->getCartReservations()->count();
117
    }
118
119
    /**
120
     * @return int
121
     */
122
    public function getNumberPurchased()
123
    {
124
        $ct = 0;
125
        if ($this->getOrders()) {
126
            foreach ($this->getOrders() as $order) {
127
                $ct += $order->Quantity;
128
            }
129
        }
130
        return $ct;
131
    }
132
133
    /**
134
     * @return DataList|bool
135
     */
136
    public function getOrders()
137
    {
138
        if ($this->owner->ID) {
139
            $orderDetails = OrderDetail::get()->filter('ProductID', $this->owner->ID);
140
            $orders = ArrayList::create();
141
            foreach ($orderDetails as $orderDetail) {
142
                $hasVariation = false;
143
                foreach ($orderDetail->OrderVariations() as $variation) {
144
                    if ($variation->VariationID > 0) {
145
                        $hasVariation = true;
146
                    }
147
                }
148
                if (!$hasVariation) {
149
                    $orders->push($orderDetail);
150
                }
151
            }
152
153
            return $orders;
154
        }
155
156
        return false;
157
    }
158
159
    /**
160
     * @return DataList
161
     */
162
    public function getCartReservations()
163
    {
164
        return CartReservation::get()
165
            ->filter([
166
                'ProductID' => $this->owner->ID,
167
                'Expires:GreaterThan' => date('Y-m-d H:i:s', strtotime('now')),
168
            ]);
169
    }
170
}
171