1
|
|
|
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
2
|
|
|
exit('No direct script access allowed'); |
3
|
|
|
} |
4
|
|
|
do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
5
|
|
|
|
6
|
|
|
|
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* EE_Cart class |
10
|
|
|
* Used to keep track of which tickets the user has specified they want to purchase. |
11
|
|
|
* This data is used for generating the Transaction and Registrations, and the |
12
|
|
|
* Line Items on cart are themselves saved for creating a persistent snapshot of |
13
|
|
|
* what was purchased and for how much. |
14
|
|
|
* |
15
|
|
|
* @version 2.0 |
16
|
|
|
* @subpackage includes/core/EE_Cart.core.php |
17
|
|
|
* @author Mike Nelson, Brent Christensen |
18
|
|
|
*/ |
19
|
|
|
class EE_Cart |
20
|
|
|
{ |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* instance of the EE_Cart object |
24
|
|
|
* |
25
|
|
|
* @access private |
26
|
|
|
* @var EE_Cart $_instance |
27
|
|
|
*/ |
28
|
|
|
private static $_instance; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* instance of the EE_Session object |
32
|
|
|
* |
33
|
|
|
* @access protected |
34
|
|
|
* @var EE_Session $_session |
35
|
|
|
*/ |
36
|
|
|
protected $_session; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* The total Line item which comprises all the children line-item subtotals, |
40
|
|
|
* which in turn each have their line items. |
41
|
|
|
* Typically, the line item structure will look like: |
42
|
|
|
* grand total |
43
|
|
|
* -tickets-sub-total |
44
|
|
|
* --ticket1 |
45
|
|
|
* --ticket2 |
46
|
|
|
* --... |
47
|
|
|
* -taxes-sub-total |
48
|
|
|
* --tax1 |
49
|
|
|
* --tax2 |
50
|
|
|
* |
51
|
|
|
* @var EE_Line_Item |
52
|
|
|
*/ |
53
|
|
|
private $_grand_total; |
54
|
|
|
|
55
|
|
|
|
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @singleton method used to instantiate class object |
59
|
|
|
* @access public |
60
|
|
|
* @param EE_Line_Item $grand_total |
61
|
|
|
* @param EE_Session $session |
62
|
|
|
* @return \EE_Cart |
63
|
|
|
* @throws \EE_Error |
64
|
|
|
*/ |
65
|
|
|
public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null) |
66
|
|
|
{ |
67
|
|
|
if ( ! empty($grand_total)) { |
68
|
|
|
self::$_instance = new self($grand_total, $session); |
69
|
|
|
} |
70
|
|
|
// or maybe retrieve an existing one ? |
71
|
|
|
if ( ! self::$_instance instanceof EE_Cart) { |
72
|
|
|
// try getting the cart out of the session |
73
|
|
|
$saved_cart = $session instanceof EE_Session ? $session->cart() : null; |
74
|
|
|
self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session); |
75
|
|
|
unset($saved_cart); |
76
|
|
|
} |
77
|
|
|
// verify that cart is ok and grand total line item exists |
78
|
|
|
if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) { |
79
|
|
|
self::$_instance = new self($grand_total, $session); |
80
|
|
|
} |
81
|
|
|
self::$_instance->get_grand_total(); |
82
|
|
|
// once everything is all said and done, save the cart to the EE_Session |
83
|
|
|
add_action('shutdown', array(self::$_instance, 'save_cart'), 90); |
84
|
|
|
return self::$_instance; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
|
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* private constructor to prevent direct creation |
91
|
|
|
* |
92
|
|
|
* @Constructor |
93
|
|
|
* @access private |
94
|
|
|
* @param EE_Line_Item $grand_total |
95
|
|
|
* @param EE_Session $session |
96
|
|
|
*/ |
97
|
|
|
private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null) |
98
|
|
|
{ |
99
|
|
|
do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
100
|
|
|
$this->set_session($session); |
101
|
|
|
if ($grand_total instanceof EE_Line_Item) { |
102
|
|
|
$this->set_grand_total_line_item($grand_total); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
|
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Resets the cart completely (whereas empty_cart |
110
|
|
|
* |
111
|
|
|
* @param EE_Line_Item $grand_total |
112
|
|
|
* @param EE_Session $session |
113
|
|
|
* @return EE_Cart |
114
|
|
|
* @throws \EE_Error |
115
|
|
|
*/ |
116
|
|
|
public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null) |
117
|
|
|
{ |
118
|
|
|
remove_action('shutdown', array(self::$_instance, 'save_cart'), 90); |
119
|
|
|
if ($session instanceof EE_Session) { |
120
|
|
|
$session->reset_cart(); |
121
|
|
|
} |
122
|
|
|
self::$_instance = null; |
123
|
|
|
return self::instance($grand_total, $session); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
|
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* @return \EE_Session |
130
|
|
|
*/ |
131
|
|
|
public function session() |
132
|
|
|
{ |
133
|
|
|
if ( ! $this->_session instanceof EE_Session) { |
134
|
|
|
$this->set_session(); |
135
|
|
|
} |
136
|
|
|
return $this->_session; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
|
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @param EE_Session $session |
143
|
|
|
*/ |
144
|
|
|
public function set_session(EE_Session $session = null) |
145
|
|
|
{ |
146
|
|
|
$this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session'); |
|
|
|
|
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
|
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Sets the cart to match the line item. Especially handy for loading an old cart where you |
153
|
|
|
* know the grand total line item on it |
154
|
|
|
* |
155
|
|
|
* @param EE_Line_Item $line_item |
156
|
|
|
*/ |
157
|
|
|
public function set_grand_total_line_item(EE_Line_Item $line_item) |
158
|
|
|
{ |
159
|
|
|
$this->_grand_total = $line_item; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
|
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* get_cart_from_reg_url_link |
166
|
|
|
* |
167
|
|
|
* @access public |
168
|
|
|
* @param EE_Transaction $transaction |
169
|
|
|
* @param EE_Session $session |
170
|
|
|
* @return \EE_Cart |
171
|
|
|
* @throws \EE_Error |
172
|
|
|
*/ |
173
|
|
|
public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null) |
174
|
|
|
{ |
175
|
|
|
$grand_total = $transaction->total_line_item(); |
176
|
|
|
$grand_total->get_items(); |
177
|
|
|
$grand_total->tax_descendants(); |
178
|
|
|
return EE_Cart::instance($grand_total, $session); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
|
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items |
185
|
|
|
* |
186
|
|
|
* @return EE_Line_Item |
187
|
|
|
* @throws \EE_Error |
188
|
|
|
*/ |
189
|
|
|
private function _create_grand_total() |
190
|
|
|
{ |
191
|
|
|
$this->_grand_total = EEH_Line_Item::create_total_line_item(); |
192
|
|
|
return $this->_grand_total; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
|
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Gets all the line items of object type Ticket |
199
|
|
|
* |
200
|
|
|
* @access public |
201
|
|
|
* @return \EE_Line_Item[] |
202
|
|
|
*/ |
203
|
|
|
public function get_tickets() |
204
|
|
|
{ |
205
|
|
|
return EEH_Line_Item::get_ticket_line_items($this->_grand_total); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
|
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* returns the total quantity of tickets in the cart |
212
|
|
|
* |
213
|
|
|
* @access public |
214
|
|
|
* @return int |
215
|
|
|
* @throws \EE_Error |
216
|
|
|
*/ |
217
|
|
|
public function all_ticket_quantity_count() |
218
|
|
|
{ |
219
|
|
|
$tickets = $this->get_tickets(); |
220
|
|
|
if (empty($tickets)) { |
221
|
|
|
return 0; |
222
|
|
|
} |
223
|
|
|
$count = 0; |
224
|
|
|
foreach ($tickets as $ticket) { |
225
|
|
|
$count += $ticket->get('LIN_quantity'); |
226
|
|
|
} |
227
|
|
|
return $count; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
|
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Gets all the tax line items |
234
|
|
|
* |
235
|
|
|
* @return \EE_Line_Item[] |
236
|
|
|
* @throws \EE_Error |
237
|
|
|
*/ |
238
|
|
|
public function get_taxes() |
239
|
|
|
{ |
240
|
|
|
return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children(); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
|
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Gets the total line item (which is a parent of all other line items) on this cart |
247
|
|
|
* |
248
|
|
|
* @return EE_Line_Item |
249
|
|
|
* @throws \EE_Error |
250
|
|
|
*/ |
251
|
|
|
public function get_grand_total() |
252
|
|
|
{ |
253
|
|
|
return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total(); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
|
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* @process items for adding to cart |
260
|
|
|
* @access public |
261
|
|
|
* @param EE_Ticket $ticket |
262
|
|
|
* @param int $qty |
263
|
|
|
* @return TRUE on success, FALSE on fail |
264
|
|
|
* @throws \EE_Error |
265
|
|
|
*/ |
266
|
|
|
public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1) |
267
|
|
|
{ |
268
|
|
|
EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty); |
269
|
|
|
return $this->save_cart() ? true : false; |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
|
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* get_cart_total_before_tax |
276
|
|
|
* |
277
|
|
|
* @access public |
278
|
|
|
* @return float |
279
|
|
|
* @throws \EE_Error |
280
|
|
|
*/ |
281
|
|
|
public function get_cart_total_before_tax() |
282
|
|
|
{ |
283
|
|
|
return $this->get_grand_total()->recalculate_pre_tax_total(); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
|
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* gets the total amount of tax paid for items in this cart |
290
|
|
|
* |
291
|
|
|
* @access public |
292
|
|
|
* @return float |
293
|
|
|
* @throws \EE_Error |
294
|
|
|
*/ |
295
|
|
|
public function get_applied_taxes() |
296
|
|
|
{ |
297
|
|
|
return EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
|
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Gets the total amount to be paid for the items in the cart, including taxes and other modifiers |
304
|
|
|
* |
305
|
|
|
* @access public |
306
|
|
|
* @return float |
307
|
|
|
* @throws \EE_Error |
308
|
|
|
*/ |
309
|
|
|
public function get_cart_grand_total() |
310
|
|
|
{ |
311
|
|
|
EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
312
|
|
|
return $this->get_grand_total()->total(); |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
|
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Gets the total amount to be paid for the items in the cart, including taxes and other modifiers |
319
|
|
|
* |
320
|
|
|
* @access public |
321
|
|
|
* @return float |
322
|
|
|
* @throws \EE_Error |
323
|
|
|
*/ |
324
|
|
|
public function recalculate_all_cart_totals() |
325
|
|
|
{ |
326
|
|
|
$pre_tax_total = $this->get_cart_total_before_tax(); |
327
|
|
|
$taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
328
|
|
|
$this->_grand_total->set_total($pre_tax_total + $taxes_total); |
329
|
|
|
$this->_grand_total->save_this_and_descendants_to_txn(); |
330
|
|
|
return $this->get_grand_total()->total(); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
|
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* deletes an item from the cart |
337
|
|
|
* |
338
|
|
|
* @access public |
339
|
|
|
* @param array|bool|string $line_item_codes |
340
|
|
|
* @return int on success, FALSE on fail |
341
|
|
|
* @throws \EE_Error |
342
|
|
|
*/ |
343
|
|
|
public function delete_items($line_item_codes = false) |
344
|
|
|
{ |
345
|
|
|
do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
346
|
|
|
return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
|
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* @remove ALL items from cart and zero ALL totals |
353
|
|
|
* @access public |
354
|
|
|
* @return bool |
355
|
|
|
* @throws \EE_Error |
356
|
|
|
*/ |
357
|
|
|
public function empty_cart() |
358
|
|
|
{ |
359
|
|
|
do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
360
|
|
|
$this->_grand_total = $this->_create_grand_total(); |
361
|
|
|
return $this->save_cart(true); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
|
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* @remove ALL items from cart and delete total as well |
368
|
|
|
* @access public |
369
|
|
|
* @return bool |
370
|
|
|
* @throws \EE_Error |
371
|
|
|
*/ |
372
|
|
|
public function delete_cart() |
373
|
|
|
{ |
374
|
|
|
$deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total); |
375
|
|
|
if ($deleted) { |
376
|
|
|
$deleted += $this->_grand_total->delete(); |
377
|
|
|
$this->_grand_total = null; |
378
|
|
|
} |
379
|
|
|
return $deleted; |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
|
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* @save cart to session |
386
|
|
|
* @access public |
387
|
|
|
* @param bool $apply_taxes |
388
|
|
|
* @return TRUE on success, FALSE on fail |
389
|
|
|
* @throws \EE_Error |
390
|
|
|
*/ |
391
|
|
|
public function save_cart($apply_taxes = true) |
392
|
|
|
{ |
393
|
|
|
if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) { |
394
|
|
|
EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
395
|
|
|
//make sure we don't cache the transaction because it can get stale |
396
|
|
|
if ($this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction |
397
|
|
|
&& $this->_grand_total->get_one_from_cache('Transaction')->ID() |
398
|
|
|
) { |
399
|
|
|
$this->_grand_total->clear_cache('Transaction', null, true); |
400
|
|
|
} |
401
|
|
|
} |
402
|
|
|
if ($this->session() instanceof EE_Session) { |
403
|
|
|
return $this->session()->set_cart($this); |
404
|
|
|
} else { |
405
|
|
|
return false; |
406
|
|
|
} |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
|
410
|
|
|
|
411
|
|
|
public function __wakeup() |
412
|
|
|
{ |
413
|
|
|
if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) { |
414
|
|
|
// $this->_grand_total is actually just an ID, so use it to get the object from the db |
415
|
|
|
$this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total); |
|
|
|
|
416
|
|
|
} |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
|
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* @return array |
423
|
|
|
*/ |
424
|
|
|
public function __sleep() |
425
|
|
|
{ |
426
|
|
|
if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) { |
427
|
|
|
$this->_grand_total = $this->_grand_total->ID(); |
|
|
|
|
428
|
|
|
} |
429
|
|
|
return array('_grand_total'); |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
|
433
|
|
|
} |
434
|
|
|
/* End of file EE_Cart.core.php */ |
435
|
|
|
/* Location: /includes/core/EE_Cart.core.php */ |
436
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.