1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Treestoneit\ShoppingCart\Models; |
4
|
|
|
|
5
|
|
|
use Illuminate\Database\Eloquent\Model; |
6
|
|
|
use Illuminate\Support\Arr; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* App\Cart\Models\CartItem. |
10
|
|
|
* |
11
|
|
|
* @property int $id |
12
|
|
|
* @property int $cart_id |
13
|
|
|
* @property int $buyable_id |
14
|
|
|
* @property string $buyable_type |
15
|
|
|
* @property int $quantity |
16
|
|
|
* @property array $options |
17
|
|
|
* @property \Illuminate\Support\Carbon|null $created_at |
18
|
|
|
* @property \Illuminate\Support\Carbon|null $updated_at |
19
|
|
|
* @property-read \Treestoneit\ShoppingCart\Buyable $buyable |
20
|
|
|
* @property-read mixed $description |
21
|
|
|
* @property-read float|int $extra_fees |
22
|
|
|
* @property-read float|null $price |
23
|
|
|
* @property-read float $subtotal |
24
|
|
|
* @property-read float $total |
25
|
|
|
* @property-read string $identifier |
26
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem newModelQuery() |
27
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem newQuery() |
28
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem query() |
29
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereBuyableId($value) |
30
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereBuyableType($value) |
31
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereCartId($value) |
32
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereCreatedAt($value) |
33
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereId($value) |
34
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereQuantity($value) |
35
|
|
|
* @method static \Illuminate\Database\Eloquent\Builder|\Treestoneit\ShoppingCart\Models\CartItem whereUpdatedAt($value) |
36
|
|
|
* @mixin \Eloquent |
37
|
|
|
*/ |
38
|
|
|
class CartItem extends Model |
39
|
|
|
{ |
40
|
|
|
/** |
41
|
|
|
* The attributes that aren't mass assignable. |
42
|
|
|
* |
43
|
|
|
* @var array |
44
|
|
|
*/ |
45
|
|
|
protected $guarded = ['id']; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* The attributes that should be cast to native types. |
49
|
|
|
* |
50
|
|
|
* @var array |
51
|
|
|
*/ |
52
|
|
|
protected $casts = ['options' => 'array']; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* The unique, option specific identifier for this cart item. |
56
|
|
|
* |
57
|
|
|
* @var string |
58
|
|
|
*/ |
59
|
|
|
protected $identifier; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* The buyable instance. |
63
|
|
|
* |
64
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\MorphTo |
65
|
|
|
*/ |
66
|
|
|
public function buyable() |
67
|
|
|
{ |
68
|
|
|
return $this->morphTo('buyable'); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Create a new collection instance. |
73
|
|
|
* |
74
|
|
|
* @param array $models |
75
|
|
|
* @return \Treestoneit\ShoppingCart\Models\CartItemCollection |
76
|
|
|
*/ |
77
|
|
|
public function newCollection(array $models = []) |
78
|
|
|
{ |
79
|
|
|
return new CartItemCollection($models); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Get the name of the item. |
84
|
|
|
*/ |
85
|
|
|
public function getDescriptionAttribute() |
86
|
|
|
{ |
87
|
|
|
return $this->buyable->getBuyableDescription(); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Get the base price of the item. |
92
|
|
|
* |
93
|
|
|
* @return float|null |
94
|
|
|
*/ |
95
|
|
|
public function getPriceAttribute() |
96
|
|
|
{ |
97
|
|
|
return $this->buyable->getBuyablePrice($this->options); |
|
|
|
|
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Get the price * quantity. |
102
|
|
|
* |
103
|
|
|
* @return float |
104
|
|
|
*/ |
105
|
|
|
public function getSubtotalAttribute() |
106
|
|
|
{ |
107
|
|
|
return round( |
108
|
|
|
$this->buyable->getBuyablePrice($this->options) * $this->attributes['quantity'], |
|
|
|
|
109
|
|
|
2 |
110
|
|
|
); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Get the extra fees for this product. |
115
|
|
|
* |
116
|
|
|
* @return float|int |
117
|
|
|
*/ |
118
|
|
|
public function getExtraFeesAttribute() |
119
|
|
|
{ |
120
|
|
|
return $this->buyable->getExtraFees(); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Get the total for this item. |
125
|
|
|
* |
126
|
|
|
* @return float |
127
|
|
|
*/ |
128
|
|
|
public function getTotalAttribute() |
129
|
|
|
{ |
130
|
|
|
return round( |
131
|
|
|
$this->getSubtotalAttribute() + $this->getExtraFeesAttribute(), |
132
|
|
|
2 |
133
|
|
|
); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Get the unique identifier for this cart item. |
138
|
|
|
* |
139
|
|
|
* @return string |
140
|
|
|
*/ |
141
|
|
|
public function getIdentifierAttribute(): string |
142
|
|
|
{ |
143
|
|
|
if (is_null($this->identifier)) { |
144
|
|
|
$this->identifier = $this->makeIdentifier(); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
return $this->identifier; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Add options to this cart item. |
152
|
|
|
* |
153
|
|
|
* @param array $options |
154
|
|
|
*/ |
155
|
|
|
public function setOptionsAttribute(array $options) |
156
|
|
|
{ |
157
|
|
|
$this->attributes['options'] = json_encode(array_merge( |
158
|
|
|
$this->options ?? [], |
159
|
|
|
$this->validateOptions($options) |
160
|
|
|
)); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Make sure that only the enumerated option values for this buyable are present in the options array. |
165
|
|
|
* |
166
|
|
|
* @param array $options |
167
|
|
|
* @return array |
168
|
|
|
*/ |
169
|
|
|
protected function validateOptions(array $options): array |
170
|
|
|
{ |
171
|
|
|
$defaults = $this->buyable->getOptions(); |
172
|
|
|
|
173
|
|
|
return array_filter($options, function ($value, $key) use ($defaults) { |
174
|
|
|
if (! array_key_exists($key, $defaults)) { |
175
|
|
|
return false; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
return $defaults[$key] == '*' || in_array($value, $defaults[$key]); |
179
|
|
|
}, ARRAY_FILTER_USE_BOTH); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Create a unique identifier for this cart item. |
184
|
|
|
* |
185
|
|
|
* @return string |
186
|
|
|
*/ |
187
|
|
|
protected function makeIdentifier(): string |
188
|
|
|
{ |
189
|
|
|
return md5($this->buyable_id.$this->buyable_type.serialize(Arr::sort($this->options))); |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.