Completed
Branch FET-8385-datetime-ticket-selec... (304b56)
by
unknown
51:42 queued 39:36
created

EE_Cart::__wakeup()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 2
nop 0
dl 0
loc 7
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
    /**
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');
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...
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);
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...
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();
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...
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