Completed
Branch BUG-10209-session-encoding (55265b)
by
unknown
63:54 queued 51:59
created

EE_Cart::__wakeup()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 2
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
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
	 * instance of the EE_Cart object
23
	 *
24
	 * @access    private
25
	 * @var EE_Cart $_instance
26
	 */
27
	private static $_instance;
28
29
	/**
30
	 * instance of the EE_Session object
31
	 *
32
	 * @access    protected
33
	 * @var EE_Session $_session
34
	 */
35
	protected $_session;
36
37
	/**
38
	 * The total Line item which comprises all the children line-item subtotals,
39
	 * which in turn each have their line items.
40
	 * Typically, the line item structure will look like:
41
	 * grand total
42
	 * -tickets-sub-total
43
	 * --ticket1
44
	 * --ticket2
45
	 * --...
46
	 * -taxes-sub-total
47
	 * --tax1
48
	 * --tax2
49
	 *
50
	 * @var EE_Line_Item
51
	 */
52
	private $_grand_total;
53
54
55
56
	/**
57
	 * @singleton method used to instantiate class object
58
	 * @access    public
59
	 * @param EE_Line_Item $grand_total
60
	 * @param EE_Session   $session
61
	 * @return \EE_Cart
62
	 * @throws \EE_Error
63
	 */
64
	public static function instance( EE_Line_Item $grand_total = null, EE_Session $session = null ) {
65
		if ( ! empty( $grand_total ) ) {
66
			self::$_instance = new self( $grand_total, $session );
67
		}
68
		// or maybe retrieve an existing one ?
69
		if ( ! self::$_instance instanceof EE_Cart ) {
70
			// try getting the cart out of the session
71
			$saved_cart = $session instanceof EE_Session ? $session->cart() : null;
72
			self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self( $grand_total, $session );
73
			unset( $saved_cart );
74
		}
75
		// verify that cart is ok and grand total line item exists
76
		if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item ) {
77
			self::$_instance = new self( $grand_total, $session );
78
		}
79
		self::$_instance->get_grand_total();
80
		// once everything is all said and done, save the cart to the EE_Session
81
		add_action( 'shutdown', array( self::$_instance, 'save_cart' ), 90 );
82
		return self::$_instance;
83
	}
84
85
86
87
	/**
88
	 * private constructor to prevent direct creation
89
	 *
90
	 * @Constructor
91
	 * @access private
92
	 * @param EE_Line_Item $grand_total
93
	 * @param EE_Session   $session
94
	 */
95
	private function __construct( EE_Line_Item $grand_total = null, EE_Session $session = null ) {
96
		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
97
		$this->set_session( $session );
98
		if ( $grand_total instanceof EE_Line_Item ) {
99
			$this->set_grand_total_line_item( $grand_total );
100
		}
101
	}
102
103
104
105
	/**
106
	 * Resets the cart completely (whereas empty_cart
107
	 *
108
	 * @param EE_Line_Item $grand_total
109
	 * @param EE_Session   $session
110
	 * @return EE_Cart
111
	 * @throws \EE_Error
112
	 */
113
	public static function reset( EE_Line_Item $grand_total = null, EE_Session $session = null ) {
114
		remove_action( 'shutdown', array( self::$_instance, 'save_cart' ), 90 );
115
		if ( $session instanceof EE_Session ) {
116
			$session->reset_cart();
117
		}
118
		self::$_instance = null;
119
		return self::instance( $grand_total, $session );
120
	}
121
122
123
124
	/**
125
	 * @return \EE_Session
126
	 */
127
	public function session() {
128
		if ( ! $this->_session instanceof EE_Session ) {
129
			$this->set_session();
130
		}
131
		return $this->_session;
132
	}
133
134
135
136
	/**
137
	 * @param EE_Session $session
138
	 */
139
	public function set_session( EE_Session $session = null ) {
140
		$this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core( 'Session' );
0 ignored issues
show
Documentation Bug introduced by
It seems like $session instanceof \EE_...)->load_core('Session') can also be of type boolean. However, the property $_session is declared as type object<EE_Session>. Maybe add an additional type check?

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 the id property of an instance of the Account 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.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
141
	}
142
143
144
145
	/**
146
	 * Sets the cart to match the line item. Especially handy for loading an old cart where you
147
	 *  know the grand total line item on it
148
	 *
149
	 * @param EE_Line_Item $line_item
150
	 */
151
	public function set_grand_total_line_item( EE_Line_Item $line_item ) {
152
		$this->_grand_total = $line_item;
153
	}
154
155
156
157
	/**
158
	 * get_cart_from_reg_url_link
159
	 *
160
	 * @access public
161
	 * @param EE_Transaction $transaction
162
	 * @param EE_Session     $session
163
	 * @return \EE_Cart
164
	 * @throws \EE_Error
165
	 */
166
	public static function get_cart_from_txn( EE_Transaction $transaction, EE_Session $session = null ) {
167
		$grand_total = $transaction->total_line_item();
168
		$grand_total->get_items();
169
		$grand_total->tax_descendants();
170
		return EE_Cart::instance( $grand_total, $session );
171
	}
172
173
174
175
	/**
176
	 * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
177
	 *
178
	 * @return EE_Line_Item
179
	 * @throws \EE_Error
180
	 */
181
	private function _create_grand_total() {
182
		$this->_grand_total = EEH_Line_Item::create_total_line_item();
183
		return $this->_grand_total;
184
	}
185
186
187
188
	/**
189
	 * Gets all the line items of object type Ticket
190
	 *
191
	 * @access public
192
	 * @return \EE_Line_Item[]
193
	 */
194
	public function get_tickets() {
195
		return EEH_Line_Item::get_ticket_line_items( $this->_grand_total );
196
	}
197
198
199
200
	/**
201
	 * returns the total quantity of tickets in the cart
202
	 *
203
	 * @access public
204
	 * @return int
205
	 * @throws \EE_Error
206
	 */
207
	public function all_ticket_quantity_count() {
208
		$tickets = $this->get_tickets();
209
		if ( empty( $tickets ) ) {
210
			return 0;
211
		}
212
		$count = 0;
213
		foreach ( $tickets as $ticket ) {
214
			$count += $ticket->get( 'LIN_quantity' );
215
		}
216
		return $count;
217
	}
218
219
220
221
	/**
222
	 * Gets all the tax line items
223
	 *
224
	 * @return \EE_Line_Item[]
225
	 * @throws \EE_Error
226
	 */
227
	public function get_taxes() {
228
		return EEH_Line_Item::get_taxes_subtotal( $this->_grand_total )->children();
229
	}
230
231
232
233
	/**
234
	 * Gets the total line item (which is a parent of all other line items) on this cart
235
	 *
236
	 * @return EE_Line_Item
237
	 * @throws \EE_Error
238
	 */
239
	public function get_grand_total() {
240
		return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total();
241
	}
242
243
244
245
	/**
246
	 * @process items for adding to cart
247
	 * @access  public
248
	 * @param EE_Ticket $ticket
249
	 * @param int       $qty
250
	 * @return TRUE on success, FALSE on fail
251
	 * @throws \EE_Error
252
	 */
253
	public function add_ticket_to_cart( EE_Ticket $ticket, $qty = 1 ) {
254
		EEH_Line_Item::add_ticket_purchase( $this->get_grand_total(), $ticket, $qty );
255
		return $this->save_cart() ? true : false;
256
	}
257
258
259
260
	/**
261
	 * get_cart_total_before_tax
262
	 *
263
	 * @access public
264
	 * @return float
265
	 * @throws \EE_Error
266
	 */
267
	public function get_cart_total_before_tax() {
268
		return $this->get_grand_total()->recalculate_pre_tax_total();
269
	}
270
271
272
273
	/**
274
	 * gets the total amount of tax paid for items in this cart
275
	 *
276
	 * @access public
277
	 * @return float
278
	 * @throws \EE_Error
279
	 */
280
	public function get_applied_taxes() {
281
		return EEH_Line_Item::ensure_taxes_applied( $this->_grand_total );
282
	}
283
284
285
286
	/**
287
	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
288
	 *
289
	 * @access public
290
	 * @return float
291
	 * @throws \EE_Error
292
	 */
293
	public function get_cart_grand_total() {
294
		EEH_Line_Item::ensure_taxes_applied( $this->_grand_total );
295
		return $this->get_grand_total()->total();
296
	}
297
298
299
300
	/**
301
	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
302
	 *
303
	 * @access public
304
	 * @return float
305
	 * @throws \EE_Error
306
	 */
307
	public function recalculate_all_cart_totals() {
308
		$pre_tax_total = $this->get_cart_total_before_tax();
309
		$taxes_total = EEH_Line_Item::ensure_taxes_applied( $this->_grand_total );
310
		$this->_grand_total->set_total( $pre_tax_total + $taxes_total );
311
		$this->_grand_total->save_this_and_descendants_to_txn();
312
		return $this->get_grand_total()->total();
313
	}
314
315
316
317
	/**
318
	 * deletes an item from the cart
319
	 *
320
	 * @access public
321
	 * @param array|bool|string $line_item_codes
322
	 * @return int on success, FALSE on fail
323
	 * @throws \EE_Error
324
	 */
325
	public function delete_items( $line_item_codes = false ) {
326
		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
327
		return EEH_Line_Item::delete_items( $this->get_grand_total(), $line_item_codes );
328
	}
329
330
331
332
	/**
333
	 * @remove ALL items from cart and zero ALL totals
334
	 * @access public
335
	 * @return bool
336
	 * @throws \EE_Error
337
	 */
338
	public function empty_cart() {
339
		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
340
		$this->_grand_total = $this->_create_grand_total();
341
		return $this->save_cart( true );
342
	}
343
344
345
346
	/**
347
	 * @remove ALL items from cart and delete total as well
348
	 * @access public
349
	 * @return bool
350
	 * @throws \EE_Error
351
	 */
352
	public function delete_cart() {
353
		$deleted = EEH_Line_Item::delete_all_child_items( $this->_grand_total );
354
		if ( $deleted ) {
355
			$deleted += $this->_grand_total->delete();
356
			$this->_grand_total = null;
357
		}
358
		return $deleted;
359
	}
360
361
362
363
	/**
364
	 * @save   cart to session
365
	 * @access public
366
	 * @param bool $apply_taxes
367
	 * @return TRUE on success, FALSE on fail
368
	 * @throws \EE_Error
369
	 */
370
	public function save_cart( $apply_taxes = true ) {
371
		if ( $apply_taxes && $this->_grand_total instanceof EE_Line_Item ) {
372
			EEH_Line_Item::ensure_taxes_applied( $this->_grand_total );
373
			//make sure we don't cache the transaction because it can get stale
374
			if ( $this->_grand_total->get_one_from_cache( 'Transaction' ) instanceof EE_Transaction
375
			     && $this->_grand_total->get_one_from_cache( 'Transaction' )->ID()
376
			) {
377
				$this->_grand_total->clear_cache( 'Transaction', null, true );
378
			}
379
		}
380
		if ( $this->session() instanceof EE_Session ) {
381
			return $this->session()->set_cart( $this );
382
		} else {
383
			return false;
384
		}
385
	}
386
387
388
389
	public function __wakeup() {
390
		if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0 ) {
391
			// $this->_grand_total is actually just an ID, so use it to get the object from the db
392
			$this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID( $this->_grand_total);
0 ignored issues
show
Documentation Bug introduced by
It seems like \EEM_Line_Item::instance...ID($this->_grand_total) can also be of type object<EE_Base_Class>. However, the property $_grand_total is declared as type object<EE_Line_Item>. Maybe add an additional type check?

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 the id property of an instance of the Account 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.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
393
		}
394
	}
395
396
397
398
	/**
399
	 * @return array
400
	 */
401
	public function __sleep() {
402
		if ( $this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID() ) {
403
			$this->_grand_total = $this->_grand_total->ID();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->_grand_total->ID() of type integer is incompatible with the declared type object<EE_Line_Item> of property $_grand_total.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
404
		}
405
		return array( '_grand_total' );
406
	}
407
408
409
}
410
/* End of file EE_Cart.core.php */
411
/* Location: /includes/core/EE_Cart.core.php */
412