Completed
Branch FET/10339/exit-modal-for-ee-de... (81712e)
by
unknown
29:29 queued 13:19
created
core/helpers/EEH_Line_Item.helper.php 2 patches
Indentation   +1698 added lines, -1698 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (!defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 /**
@@ -23,1703 +23,1703 @@  discard block
 block discarded – undo
23 23
 class EEH_Line_Item
24 24
 {
25 25
 
26
-    //other functions: cancel ticket purchase
27
-    //delete ticket purchase
28
-    //add promotion
29
-
30
-
31
-    /**
32
-     * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
33
-     * Does NOT automatically re-calculate the line item totals or update the related transaction.
34
-     * You should call recalculate_total_including_taxes() on the grant total line item after this
35
-     * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
36
-     * to keep the registration final prices in-sync with the transaction's total.
37
-     *
38
-     * @param EE_Line_Item $parent_line_item
39
-     * @param string $name
40
-     * @param float $unit_price
41
-     * @param string $description
42
-     * @param int $quantity
43
-     * @param boolean $taxable
44
-     * @param boolean $code if set to a value, ensures there is only one line item with that code
45
-     * @return boolean success
46
-     * @throws \EE_Error
47
-     */
48
-    public static function add_unrelated_item(EE_Line_Item $parent_line_item, $name, $unit_price, $description = '', $quantity = 1, $taxable = FALSE, $code = NULL)
49
-    {
50
-        $items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
51
-        $line_item = EE_Line_Item::new_instance(array(
52
-            'LIN_name' => $name,
53
-            'LIN_desc' => $description,
54
-            'LIN_unit_price' => $unit_price,
55
-            'LIN_quantity' => $quantity,
56
-            'LIN_percent' => null,
57
-            'LIN_is_taxable' => $taxable,
58
-            'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
59
-            'LIN_total' => (float)$unit_price * (int)$quantity,
60
-            'LIN_type' => EEM_Line_Item::type_line_item,
61
-            'LIN_code' => $code,
62
-        ));
63
-        $line_item = apply_filters(
64
-            'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
65
-            $line_item,
66
-            $parent_line_item
67
-        );
68
-        return self::add_item($parent_line_item, $line_item);
69
-    }
70
-
71
-
72
-    /**
73
-     * Adds a simple item ( unrelated to any other model object) to the total line item,
74
-     * in the correct spot in the line item tree. Automatically
75
-     * re-calculates the line item totals and updates the related transaction. But
76
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
77
-     * should probably change because of this).
78
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
79
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
80
-     *
81
-     * @param EE_Line_Item $parent_line_item
82
-     * @param string $name
83
-     * @param float $percentage_amount
84
-     * @param string $description
85
-     * @param boolean $taxable
86
-     * @return boolean success
87
-     * @throws \EE_Error
88
-     */
89
-    public static function add_percentage_based_item(EE_Line_Item $parent_line_item, $name, $percentage_amount, $description = '', $taxable = FALSE)
90
-    {
91
-        $line_item = EE_Line_Item::new_instance(array(
92
-            'LIN_name' => $name,
93
-            'LIN_desc' => $description,
94
-            'LIN_unit_price' => 0,
95
-            'LIN_percent' => $percentage_amount,
96
-            'LIN_quantity' => 1,
97
-            'LIN_is_taxable' => $taxable,
98
-            'LIN_total' => (float)($percentage_amount * ($parent_line_item->total() / 100)),
99
-            'LIN_type' => EEM_Line_Item::type_line_item,
100
-            'LIN_parent' => $parent_line_item->ID()
101
-        ));
102
-        $line_item = apply_filters(
103
-            'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
104
-            $line_item
105
-        );
106
-        return $parent_line_item->add_child_line_item($line_item, false);
107
-    }
108
-
109
-
110
-    /**
111
-     * Returns the new line item created by adding a purchase of the ticket
112
-     * ensures that ticket line item is saved, and that cart total has been recalculated.
113
-     * If this ticket has already been purchased, just increments its count.
114
-     * Automatically re-calculates the line item totals and updates the related transaction. But
115
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
116
-     * should probably change because of this).
117
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
118
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
119
-     *
120
-     * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
121
-     * @param EE_Ticket $ticket
122
-     * @param int $qty
123
-     * @return \EE_Line_Item
124
-     * @throws \EE_Error
125
-     */
126
-    public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
127
-    {
128
-        if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) {
129
-            throw new EE_Error(sprintf(__('A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', 'event_espresso'), $ticket->ID(), $total_line_item->ID()));
130
-        }
131
-        // either increment the qty for an existing ticket
132
-        $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
133
-        // or add a new one
134
-        if (!$line_item instanceof EE_Line_Item) {
135
-            $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
136
-        }
137
-        $total_line_item->recalculate_total_including_taxes();
138
-        return $line_item;
139
-    }
140
-
141
-
142
-    /**
143
-     * Returns the new line item created by adding a purchase of the ticket
144
-     * @param \EE_Line_Item $total_line_item
145
-     * @param EE_Ticket $ticket
146
-     * @param int $qty
147
-     * @return \EE_Line_Item
148
-     * @throws \EE_Error
149
-     */
150
-    public static function increment_ticket_qty_if_already_in_cart(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
151
-    {
152
-        $line_item = null;
153
-        if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
154
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
155
-            foreach ((array)$ticket_line_items as $ticket_line_item) {
156
-                if (
157
-                    $ticket_line_item instanceof EE_Line_Item
158
-                    && (int)$ticket_line_item->OBJ_ID() === (int)$ticket->ID()
159
-                ) {
160
-                    $line_item = $ticket_line_item;
161
-                    break;
162
-                }
163
-            }
164
-        }
165
-        if ($line_item instanceof EE_Line_Item) {
166
-            EEH_Line_Item::increment_quantity($line_item, $qty);
167
-            return $line_item;
168
-        }
169
-        return null;
170
-    }
171
-
172
-
173
-    /**
174
-     * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
175
-     * Does NOT save or recalculate other line items totals
176
-     *
177
-     * @param EE_Line_Item $line_item
178
-     * @param int $qty
179
-     * @return void
180
-     * @throws \EE_Error
181
-     */
182
-    public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
183
-    {
184
-        if (!$line_item->is_percent()) {
185
-            $qty += $line_item->quantity();
186
-            $line_item->set_quantity($qty);
187
-            $line_item->set_total($line_item->unit_price() * $qty);
188
-            $line_item->save();
189
-        }
190
-        foreach ($line_item->children() as $child) {
191
-            if ($child->is_sub_line_item()) {
192
-                EEH_Line_Item::update_quantity($child, $qty);
193
-            }
194
-        }
195
-    }
196
-
197
-
198
-    /**
199
-     * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
200
-     * Does NOT save or recalculate other line items totals
201
-     *
202
-     * @param EE_Line_Item $line_item
203
-     * @param int $qty
204
-     * @return void
205
-     * @throws \EE_Error
206
-     */
207
-    public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
208
-    {
209
-        if (!$line_item->is_percent()) {
210
-            $qty = $line_item->quantity() - $qty;
211
-            $qty = max($qty, 0);
212
-            $line_item->set_quantity($qty);
213
-            $line_item->set_total($line_item->unit_price() * $qty);
214
-            $line_item->save();
215
-        }
216
-        foreach ($line_item->children() as $child) {
217
-            if ($child->is_sub_line_item()) {
218
-                EEH_Line_Item::update_quantity($child, $qty);
219
-            }
220
-        }
221
-    }
222
-
223
-
224
-    /**
225
-     * Updates the line item and its children's quantities to the specified number.
226
-     * Does NOT save them or recalculate totals.
227
-     *
228
-     * @param EE_Line_Item $line_item
229
-     * @param int $new_quantity
230
-     * @throws \EE_Error
231
-     */
232
-    public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
233
-    {
234
-        if (!$line_item->is_percent()) {
235
-            $line_item->set_quantity($new_quantity);
236
-            $line_item->set_total($line_item->unit_price() * $new_quantity);
237
-            $line_item->save();
238
-        }
239
-        foreach ($line_item->children() as $child) {
240
-            if ($child->is_sub_line_item()) {
241
-                EEH_Line_Item::update_quantity($child, $new_quantity);
242
-            }
243
-        }
244
-    }
245
-
246
-
247
-    /**
248
-     * Returns the new line item created by adding a purchase of the ticket
249
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
250
-     * @param EE_Ticket $ticket
251
-     * @param int $qty
252
-     * @return \EE_Line_Item
253
-     * @throws \EE_Error
254
-     */
255
-    public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
256
-    {
257
-        $datetimes = $ticket->datetimes();
258
-        $first_datetime = reset($datetimes);
259
-        if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
260
-            $first_datetime_name = $first_datetime->event()->name();
261
-        } else {
262
-            $first_datetime_name = __('Event', 'event_espresso');
263
-        }
264
-        $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
265
-        // get event subtotal line
266
-        $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
267
-        // add $ticket to cart
268
-        $line_item = EE_Line_Item::new_instance(array(
269
-            'LIN_name' => $ticket->name(),
270
-            'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
271
-            'LIN_unit_price' => $ticket->price(),
272
-            'LIN_quantity' => $qty,
273
-            'LIN_is_taxable' => $ticket->taxable(),
274
-            'LIN_order' => count($events_sub_total->children()),
275
-            'LIN_total' => $ticket->price() * $qty,
276
-            'LIN_type' => EEM_Line_Item::type_line_item,
277
-            'OBJ_ID' => $ticket->ID(),
278
-            'OBJ_type' => 'Ticket'
279
-        ));
280
-        $line_item = apply_filters(
281
-            'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
282
-            $line_item
283
-        );
284
-        $events_sub_total->add_child_line_item($line_item);
285
-        //now add the sub-line items
286
-        $running_total_for_ticket = 0;
287
-        foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
288
-            $sign = $price->is_discount() ? -1 : 1;
289
-            $price_total = $price->is_percent()
290
-                ? $running_total_for_ticket * $price->amount() / 100
291
-                : $price->amount() * $qty;
292
-            $sub_line_item = EE_Line_Item::new_instance(array(
293
-                'LIN_name' => $price->name(),
294
-                'LIN_desc' => $price->desc(),
295
-                'LIN_quantity' => $price->is_percent() ? null : $qty,
296
-                'LIN_is_taxable' => false,
297
-                'LIN_order' => $price->order(),
298
-                'LIN_total' => $sign * $price_total,
299
-                'LIN_type' => EEM_Line_Item::type_sub_line_item,
300
-                'OBJ_ID' => $price->ID(),
301
-                'OBJ_type' => 'Price'
302
-            ));
303
-            $sub_line_item = apply_filters(
304
-                'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
305
-                $sub_line_item
306
-            );
307
-            if ($price->is_percent()) {
308
-                $sub_line_item->set_percent($sign * $price->amount());
309
-            } else {
310
-                $sub_line_item->set_unit_price($sign * $price->amount());
311
-            }
312
-            $running_total_for_ticket += $price_total;
313
-            $line_item->add_child_line_item($sub_line_item);
314
-        }
315
-        return $line_item;
316
-    }
317
-
318
-
319
-    /**
320
-     * Adds the specified item under the pre-tax-sub-total line item. Automatically
321
-     * re-calculates the line item totals and updates the related transaction. But
322
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
323
-     * should probably change because of this).
324
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
325
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
326
-     *
327
-     * @param EE_Line_Item $total_line_item
328
-     * @param EE_Line_Item $item to be added
329
-     * @return boolean
330
-     * @throws \EE_Error
331
-     */
332
-    public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
333
-    {
334
-        $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
335
-        if ($pre_tax_subtotal instanceof EE_Line_Item) {
336
-            $success = $pre_tax_subtotal->add_child_line_item($item);
337
-        } else {
338
-            return FALSE;
339
-        }
340
-        $total_line_item->recalculate_total_including_taxes();
341
-        return $success;
342
-    }
343
-
344
-
345
-    /**
346
-     * cancels an existing ticket line item,
347
-     * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
348
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
349
-     *
350
-     * @param EE_Line_Item $ticket_line_item
351
-     * @param int $qty
352
-     * @return bool success
353
-     * @throws \EE_Error
354
-     */
355
-    public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
356
-    {
357
-        // validate incoming line_item
358
-        if ($ticket_line_item->OBJ_type() !== 'Ticket') {
359
-            throw new EE_Error(
360
-                sprintf(
361
-                    __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
362
-                    $ticket_line_item->type()
363
-                )
364
-            );
365
-        }
366
-        if ($ticket_line_item->quantity() < $qty) {
367
-            throw new EE_Error(
368
-                sprintf(
369
-                    __('Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', 'event_espresso'),
370
-                    $qty,
371
-                    $ticket_line_item->quantity()
372
-                )
373
-            );
374
-        }
375
-        // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
376
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
377
-        foreach ($ticket_line_item->children() as $child_line_item) {
378
-            if (
379
-                $child_line_item->is_sub_line_item()
380
-                && !$child_line_item->is_percent()
381
-                && !$child_line_item->is_cancellation()
382
-            ) {
383
-                $child_line_item->set_quantity($child_line_item->quantity() - $qty);
384
-            }
385
-        }
386
-        // get cancellation sub line item
387
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
388
-            $ticket_line_item,
389
-            EEM_Line_Item::type_cancellation
390
-        );
391
-        $cancellation_line_item = reset($cancellation_line_item);
392
-        // verify that this ticket was indeed previously cancelled
393
-        if ($cancellation_line_item instanceof EE_Line_Item) {
394
-            // increment cancelled quantity
395
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
396
-        } else {
397
-            // create cancellation sub line item
398
-            $cancellation_line_item = EE_Line_Item::new_instance(array(
399
-                'LIN_name' => __('Cancellation', 'event_espresso'),
400
-                'LIN_desc' => sprintf(
401
-                    _x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'),
402
-                    $ticket_line_item->name(),
403
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
404
-                ),
405
-                'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
406
-                'LIN_quantity' => $qty,
407
-                'LIN_is_taxable' => $ticket_line_item->is_taxable(),
408
-                'LIN_order' => count($ticket_line_item->children()),
409
-                'LIN_total' => 0, // $ticket_line_item->unit_price()
410
-                'LIN_type' => EEM_Line_Item::type_cancellation,
411
-            ));
412
-            $ticket_line_item->add_child_line_item($cancellation_line_item);
413
-        }
414
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
415
-            // decrement parent line item quantity
416
-            $event_line_item = $ticket_line_item->parent();
417
-            if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
418
-                $event_line_item->set_quantity($event_line_item->quantity() - $qty);
419
-                $event_line_item->save();
420
-            }
421
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
422
-            return true;
423
-        }
424
-        return false;
425
-    }
426
-
427
-
428
-    /**
429
-     * reinstates (un-cancels?) a previously canceled ticket line item,
430
-     * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
431
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
432
-     *
433
-     * @param EE_Line_Item $ticket_line_item
434
-     * @param int $qty
435
-     * @return bool success
436
-     * @throws \EE_Error
437
-     */
438
-    public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
439
-    {
440
-        // validate incoming line_item
441
-        if ($ticket_line_item->OBJ_type() !== 'Ticket') {
442
-            throw new EE_Error(
443
-                sprintf(
444
-                    __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
445
-                    $ticket_line_item->type()
446
-                )
447
-            );
448
-        }
449
-        // get cancellation sub line item
450
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
451
-            $ticket_line_item,
452
-            EEM_Line_Item::type_cancellation
453
-        );
454
-        $cancellation_line_item = reset($cancellation_line_item);
455
-        // verify that this ticket was indeed previously cancelled
456
-        if (!$cancellation_line_item instanceof EE_Line_Item) {
457
-            return false;
458
-        }
459
-        if ($cancellation_line_item->quantity() > $qty) {
460
-            // decrement cancelled quantity
461
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
462
-        } else if ($cancellation_line_item->quantity() == $qty) {
463
-            // decrement cancelled quantity in case anyone still has the object kicking around
464
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
465
-            // delete because quantity will end up as 0
466
-            $cancellation_line_item->delete();
467
-            // and attempt to destroy the object,
468
-            // even though PHP won't actually destroy it until it needs the memory
469
-            unset($cancellation_line_item);
470
-        } else {
471
-            // what ?!?! negative quantity ?!?!
472
-            throw new EE_Error(
473
-                sprintf(
474
-                    __('Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
475
-                        'event_espresso'),
476
-                    $qty,
477
-                    $cancellation_line_item->quantity()
478
-                )
479
-            );
480
-        }
481
-        // increment ticket quantity
482
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
483
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
484
-            // increment parent line item quantity
485
-            $event_line_item = $ticket_line_item->parent();
486
-            if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
487
-                $event_line_item->set_quantity($event_line_item->quantity() + $qty);
488
-            }
489
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
490
-            return true;
491
-        }
492
-        return false;
493
-    }
494
-
495
-
496
-    /**
497
-     * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
498
-     * then EE_Line_Item::recalculate_total_including_taxes() on the result
499
-     *
500
-     * @param EE_Line_Item $line_item
501
-     * @return \EE_Line_Item
502
-     */
503
-    public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
504
-    {
505
-        $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
506
-        return $grand_total_line_item->recalculate_total_including_taxes();
507
-    }
508
-
509
-
510
-    /**
511
-     * Gets the line item which contains the subtotal of all the items
512
-     *
513
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
514
-     * @return \EE_Line_Item
515
-     * @throws \EE_Error
516
-     */
517
-    public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
518
-    {
519
-        $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
520
-        return $pre_tax_subtotal instanceof EE_Line_Item
521
-            ? $pre_tax_subtotal
522
-            : self::create_pre_tax_subtotal($total_line_item);
523
-    }
524
-
525
-
526
-    /**
527
-     * Gets the line item for the taxes subtotal
528
-     *
529
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
530
-     * @return \EE_Line_Item
531
-     * @throws \EE_Error
532
-     */
533
-    public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
534
-    {
535
-        $taxes = $total_line_item->get_child_line_item('taxes');
536
-        return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
537
-    }
538
-
539
-
540
-    /**
541
-     * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
542
-     *
543
-     * @param EE_Line_Item $line_item
544
-     * @param EE_Transaction $transaction
545
-     * @return void
546
-     * @throws \EE_Error
547
-     */
548
-    public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = NULL)
549
-    {
550
-        if ($transaction) {
551
-            /** @type EEM_Transaction $EEM_Transaction */
552
-            $EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
553
-            $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
554
-            $line_item->set_TXN_ID($TXN_ID);
555
-        }
556
-    }
557
-
558
-
559
-    /**
560
-     * Creates a new default total line item for the transaction,
561
-     * and its tickets subtotal and taxes subtotal line items (and adds the
562
-     * existing taxes as children of the taxes subtotal line item)
563
-     *
564
-     * @param EE_Transaction $transaction
565
-     * @return \EE_Line_Item of type total
566
-     * @throws \EE_Error
567
-     */
568
-    public static function create_total_line_item($transaction = NULL)
569
-    {
570
-        $total_line_item = EE_Line_Item::new_instance(array(
571
-            'LIN_code' => 'total',
572
-            'LIN_name' => __('Grand Total', 'event_espresso'),
573
-            'LIN_type' => EEM_Line_Item::type_total,
574
-            'OBJ_type' => 'Transaction'
575
-        ));
576
-        $total_line_item = apply_filters(
577
-            'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
578
-            $total_line_item
579
-        );
580
-        self::set_TXN_ID($total_line_item, $transaction);
581
-        self::create_pre_tax_subtotal($total_line_item, $transaction);
582
-        self::create_taxes_subtotal($total_line_item, $transaction);
583
-        return $total_line_item;
584
-    }
585
-
586
-
587
-    /**
588
-     * Creates a default items subtotal line item
589
-     *
590
-     * @param EE_Line_Item $total_line_item
591
-     * @param EE_Transaction $transaction
592
-     * @return EE_Line_Item
593
-     * @throws \EE_Error
594
-     */
595
-    protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
596
-    {
597
-        $pre_tax_line_item = EE_Line_Item::new_instance(array(
598
-            'LIN_code' => 'pre-tax-subtotal',
599
-            'LIN_name' => __('Pre-Tax Subtotal', 'event_espresso'),
600
-            'LIN_type' => EEM_Line_Item::type_sub_total
601
-        ));
602
-        $pre_tax_line_item = apply_filters(
603
-            'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
604
-            $pre_tax_line_item
605
-        );
606
-        self::set_TXN_ID($pre_tax_line_item, $transaction);
607
-        $total_line_item->add_child_line_item($pre_tax_line_item);
608
-        self::create_event_subtotal($pre_tax_line_item, $transaction);
609
-        return $pre_tax_line_item;
610
-    }
611
-
612
-
613
-    /**
614
-     * Creates a line item for the taxes subtotal and finds all the tax prices
615
-     * and applies taxes to it
616
-     *
617
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
618
-     * @param EE_Transaction $transaction
619
-     * @return EE_Line_Item
620
-     * @throws \EE_Error
621
-     */
622
-    protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
623
-    {
624
-        $tax_line_item = EE_Line_Item::new_instance(array(
625
-            'LIN_code' => 'taxes',
626
-            'LIN_name' => __('Taxes', 'event_espresso'),
627
-            'LIN_type' => EEM_Line_Item::type_tax_sub_total,
628
-            'LIN_order' => 1000,//this should always come last
629
-        ));
630
-        $tax_line_item = apply_filters(
631
-            'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
632
-            $tax_line_item
633
-        );
634
-        self::set_TXN_ID($tax_line_item, $transaction);
635
-        $total_line_item->add_child_line_item($tax_line_item);
636
-        //and lastly, add the actual taxes
637
-        self::apply_taxes($total_line_item);
638
-        return $tax_line_item;
639
-    }
640
-
641
-
642
-    /**
643
-     * Creates a default items subtotal line item
644
-     *
645
-     * @param EE_Line_Item $pre_tax_line_item
646
-     * @param EE_Transaction $transaction
647
-     * @param EE_Event $event
648
-     * @return EE_Line_Item
649
-     * @throws \EE_Error
650
-     */
651
-    public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = NULL, $event = NULL)
652
-    {
653
-        $event_line_item = EE_Line_Item::new_instance(array(
654
-            'LIN_code' => self::get_event_code($event),
655
-            'LIN_name' => self::get_event_name($event),
656
-            'LIN_desc' => self::get_event_desc($event),
657
-            'LIN_type' => EEM_Line_Item::type_sub_total,
658
-            'OBJ_type' => 'Event',
659
-            'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0
660
-        ));
661
-        $event_line_item = apply_filters(
662
-            'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
663
-            $event_line_item
664
-        );
665
-        self::set_TXN_ID($event_line_item, $transaction);
666
-        $pre_tax_line_item->add_child_line_item($event_line_item);
667
-        return $event_line_item;
668
-    }
669
-
670
-
671
-    /**
672
-     * Gets what the event ticket's code SHOULD be
673
-     *
674
-     * @param EE_Event $event
675
-     * @return string
676
-     * @throws \EE_Error
677
-     */
678
-    public static function get_event_code($event)
679
-    {
680
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
681
-    }
682
-
683
-    /**
684
-     * Gets the event name
685
-     * @param EE_Event $event
686
-     * @return string
687
-     */
688
-    public static function get_event_name($event)
689
-    {
690
-        return $event instanceof EE_Event ? $event->name() : __('Event', 'event_espresso');
691
-    }
692
-
693
-    /**
694
-     * Gets the event excerpt
695
-     * @param EE_Event $event
696
-     * @return string
697
-     */
698
-    public static function get_event_desc($event)
699
-    {
700
-        return $event instanceof EE_Event ? $event->short_description() : '';
701
-    }
702
-
703
-    /**
704
-     * Given the grand total line item and a ticket, finds the event sub-total
705
-     * line item the ticket's purchase should be added onto
706
-     *
707
-     * @access public
708
-     * @param EE_Line_Item $grand_total the grand total line item
709
-     * @param EE_Ticket $ticket
710
-     * @throws \EE_Error
711
-     * @return EE_Line_Item
712
-     */
713
-    public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
714
-    {
715
-        $first_datetime = $ticket->first_datetime();
716
-        if (!$first_datetime instanceof EE_Datetime) {
717
-            throw new EE_Error(
718
-                sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID())
719
-            );
720
-        }
721
-        $event = $first_datetime->event();
722
-        if (!$event instanceof EE_Event) {
723
-            throw new EE_Error(
724
-                sprintf(
725
-                    __('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'),
726
-                    $ticket->ID()
727
-                )
728
-            );
729
-        }
730
-        $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
731
-        if (!$events_sub_total instanceof EE_Line_Item) {
732
-            throw new EE_Error(
733
-                sprintf(
734
-                    __('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'),
735
-                    $ticket->ID(),
736
-                    $grand_total->ID()
737
-                )
738
-            );
739
-        }
740
-        return $events_sub_total;
741
-    }
742
-
743
-
744
-    /**
745
-     * Gets the event line item
746
-     *
747
-     * @param EE_Line_Item $grand_total
748
-     * @param EE_Event $event
749
-     * @return EE_Line_Item for the event subtotal which is a child of $grand_total
750
-     * @throws \EE_Error
751
-     */
752
-    public static function get_event_line_item(EE_Line_Item $grand_total, $event)
753
-    {
754
-        /** @type EE_Event $event */
755
-        $event = EEM_Event::instance()->ensure_is_obj($event, true);
756
-        $event_line_item = NULL;
757
-        $found = false;
758
-        foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
759
-            // default event subtotal, we should only ever find this the first time this method is called
760
-            if (!$event_line_item->OBJ_ID()) {
761
-                // let's use this! but first... set the event details
762
-                EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
763
-                $found = true;
764
-                break;
765
-            } else if ($event_line_item->OBJ_ID() === $event->ID()) {
766
-                // found existing line item for this event in the cart, so break out of loop and use this one
767
-                $found = true;
768
-                break;
769
-            }
770
-        }
771
-        if (!$found) {
772
-            //there is no event sub-total yet, so add it
773
-            $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
774
-            // create a new "event" subtotal below that
775
-            $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
776
-            // and set the event details
777
-            EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
778
-        }
779
-        return $event_line_item;
780
-    }
781
-
782
-
783
-    /**
784
-     * Creates a default items subtotal line item
785
-     *
786
-     * @param EE_Line_Item $event_line_item
787
-     * @param EE_Event $event
788
-     * @param EE_Transaction $transaction
789
-     * @return EE_Line_Item
790
-     * @throws \EE_Error
791
-     */
792
-    public static function set_event_subtotal_details(
793
-        EE_Line_Item $event_line_item,
794
-        EE_Event $event,
795
-        $transaction = null
796
-    )
797
-    {
798
-        if ($event instanceof EE_Event) {
799
-            $event_line_item->set_code(self::get_event_code($event));
800
-            $event_line_item->set_name(self::get_event_name($event));
801
-            $event_line_item->set_desc(self::get_event_desc($event));
802
-            $event_line_item->set_OBJ_ID($event->ID());
803
-        }
804
-        self::set_TXN_ID($event_line_item, $transaction);
805
-    }
806
-
807
-
808
-    /**
809
-     * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
810
-     * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
811
-     * any old taxes are removed
812
-     *
813
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
814
-     * @throws \EE_Error
815
-     */
816
-    public static function apply_taxes(EE_Line_Item $total_line_item)
817
-    {
818
-        /** @type EEM_Price $EEM_Price */
819
-        $EEM_Price = EE_Registry::instance()->load_model('Price');
820
-        // get array of taxes via Price Model
821
-        $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
822
-        ksort($ordered_taxes);
823
-        $taxes_line_item = self::get_taxes_subtotal($total_line_item);
824
-        //just to be safe, remove its old tax line items
825
-        $taxes_line_item->delete_children_line_items();
826
-        //loop thru taxes
827
-        foreach ($ordered_taxes as $order => $taxes) {
828
-            foreach ($taxes as $tax) {
829
-                if ($tax instanceof EE_Price) {
830
-                    $tax_line_item = EE_Line_Item::new_instance(
831
-                        array(
832
-                            'LIN_name' => $tax->name(),
833
-                            'LIN_desc' => $tax->desc(),
834
-                            'LIN_percent' => $tax->amount(),
835
-                            'LIN_is_taxable' => false,
836
-                            'LIN_order' => $order,
837
-                            'LIN_total' => 0,
838
-                            'LIN_type' => EEM_Line_Item::type_tax,
839
-                            'OBJ_type' => 'Price',
840
-                            'OBJ_ID' => $tax->ID()
841
-                        )
842
-                    );
843
-                    $tax_line_item = apply_filters(
844
-                        'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
845
-                        $tax_line_item
846
-                    );
847
-                    $taxes_line_item->add_child_line_item($tax_line_item);
848
-                }
849
-            }
850
-        }
851
-        $total_line_item->recalculate_total_including_taxes();
852
-    }
853
-
854
-
855
-    /**
856
-     * Ensures that taxes have been applied to the order, if not applies them.
857
-     * Returns the total amount of tax
858
-     *
859
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
860
-     * @return float
861
-     * @throws \EE_Error
862
-     */
863
-    public static function ensure_taxes_applied($total_line_item)
864
-    {
865
-        $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
866
-        if (!$taxes_subtotal->children()) {
867
-            self::apply_taxes($total_line_item);
868
-        }
869
-        return $taxes_subtotal->total();
870
-    }
871
-
872
-
873
-    /**
874
-     * Deletes ALL children of the passed line item
875
-     *
876
-     * @param EE_Line_Item $parent_line_item
877
-     * @return bool
878
-     * @throws \EE_Error
879
-     */
880
-    public static function delete_all_child_items(EE_Line_Item $parent_line_item)
881
-    {
882
-        $deleted = 0;
883
-        foreach ($parent_line_item->children() as $child_line_item) {
884
-            if ($child_line_item instanceof EE_Line_Item) {
885
-                $deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
886
-                if ($child_line_item->ID()) {
887
-                    $child_line_item->delete();
888
-                    unset($child_line_item);
889
-                } else {
890
-                    $parent_line_item->delete_child_line_item($child_line_item->code());
891
-                }
892
-                $deleted++;
893
-            }
894
-        }
895
-        return $deleted;
896
-    }
897
-
898
-
899
-    /**
900
-     * Deletes the line items as indicated by the line item code(s) provided,
901
-     * regardless of where they're found in the line item tree. Automatically
902
-     * re-calculates the line item totals and updates the related transaction. But
903
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
904
-     * should probably change because of this).
905
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
906
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
907
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
908
-     * @param array|bool|string $line_item_codes
909
-     * @return int number of items successfully removed
910
-     */
911
-    public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = FALSE)
912
-    {
913
-
914
-        if ($total_line_item->type() !== EEM_Line_Item::type_total) {
915
-            EE_Error::doing_it_wrong(
916
-                'EEH_Line_Item::delete_items',
917
-                __(
918
-                    'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
919
-                    'event_espresso'
920
-                ),
921
-                '4.6.18'
922
-            );
923
-        }
924
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
925
-
926
-        // check if only a single line_item_id was passed
927
-        if (!empty($line_item_codes) && !is_array($line_item_codes)) {
928
-            // place single line_item_id in an array to appear as multiple line_item_ids
929
-            $line_item_codes = array($line_item_codes);
930
-        }
931
-        $removals = 0;
932
-        // cycle thru line_item_ids
933
-        foreach ($line_item_codes as $line_item_id) {
934
-            $removals += $total_line_item->delete_child_line_item($line_item_id);
935
-        }
936
-
937
-        if ($removals > 0) {
938
-            $total_line_item->recalculate_taxes_and_tax_total();
939
-            return $removals;
940
-        } else {
941
-            return FALSE;
942
-        }
943
-    }
944
-
945
-
946
-    /**
947
-     * Overwrites the previous tax by clearing out the old taxes, and creates a new
948
-     * tax and updates the total line item accordingly
949
-     *
950
-     * @param EE_Line_Item $total_line_item
951
-     * @param float $amount
952
-     * @param string $name
953
-     * @param string $description
954
-     * @param string $code
955
-     * @param boolean $add_to_existing_line_item
956
-     *                          if true, and a duplicate line item with the same code is found,
957
-     *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
958
-     * @return EE_Line_Item the new tax line item created
959
-     * @throws \EE_Error
960
-     */
961
-    public static function set_total_tax_to(
962
-        EE_Line_Item $total_line_item,
963
-        $amount,
964
-        $name = null,
965
-        $description = null,
966
-        $code = null,
967
-        $add_to_existing_line_item = false
968
-    )
969
-    {
970
-        $tax_subtotal = self::get_taxes_subtotal($total_line_item);
971
-        $taxable_total = $total_line_item->taxable_total();
972
-
973
-        if ($add_to_existing_line_item) {
974
-            $new_tax = $tax_subtotal->get_child_line_item($code);
975
-            EEM_Line_Item::instance()->delete(
976
-                array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
977
-            );
978
-        } else {
979
-            $new_tax = null;
980
-            $tax_subtotal->delete_children_line_items();
981
-        }
982
-        if ($new_tax) {
983
-            $new_tax->set_total($new_tax->total() + $amount);
984
-            $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
985
-        } else {
986
-            //no existing tax item. Create it
987
-            $new_tax = EE_Line_Item::new_instance(array(
988
-                'TXN_ID' => $total_line_item->TXN_ID(),
989
-                'LIN_name' => $name ? $name : __('Tax', 'event_espresso'),
990
-                'LIN_desc' => $description ? $description : '',
991
-                'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
992
-                'LIN_total' => $amount,
993
-                'LIN_parent' => $tax_subtotal->ID(),
994
-                'LIN_type' => EEM_Line_Item::type_tax,
995
-                'LIN_code' => $code
996
-            ));
997
-        }
998
-
999
-        $new_tax = apply_filters(
1000
-            'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1001
-            $new_tax,
1002
-            $total_line_item
1003
-        );
1004
-        $new_tax->save();
1005
-        $tax_subtotal->set_total($new_tax->total());
1006
-        $tax_subtotal->save();
1007
-        $total_line_item->recalculate_total_including_taxes();
1008
-        return $new_tax;
1009
-    }
1010
-
1011
-
1012
-    /**
1013
-     * Makes all the line items which are children of $line_item taxable (or not).
1014
-     * Does NOT save the line items
1015
-     * @param EE_Line_Item $line_item
1016
-     * @param string $code_substring_for_whitelist if this string is part of the line item's code
1017
-     *  it will be whitelisted (ie, except from becoming taxable)
1018
-     * @param boolean $taxable
1019
-     */
1020
-    public static function set_line_items_taxable(
1021
-        EE_Line_Item $line_item,
1022
-        $taxable = true,
1023
-        $code_substring_for_whitelist = null
1024
-    )
1025
-    {
1026
-        $whitelisted = false;
1027
-        if ($code_substring_for_whitelist !== null) {
1028
-            $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false;
1029
-        }
1030
-        if (!$whitelisted && $line_item->is_line_item()) {
1031
-            $line_item->set_is_taxable($taxable);
1032
-        }
1033
-        foreach ($line_item->children() as $child_line_item) {
1034
-            EEH_Line_Item::set_line_items_taxable($child_line_item, $taxable, $code_substring_for_whitelist);
1035
-        }
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * Gets all descendants that are event subtotals
1041
-     *
1042
-     * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1043
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1044
-     * @return EE_Line_Item[]
1045
-     */
1046
-    public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1047
-    {
1048
-        return self::get_subtotals_of_object_type($parent_line_item, 'Event');
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * Gets all descendants subtotals that match the supplied object type
1054
-     *
1055
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1056
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1057
-     * @param string $obj_type
1058
-     * @return EE_Line_Item[]
1059
-     */
1060
-    public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1061
-    {
1062
-        return self::_get_descendants_by_type_and_object_type(
1063
-            $parent_line_item,
1064
-            EEM_Line_Item::type_sub_total,
1065
-            $obj_type
1066
-        );
1067
-    }
1068
-
1069
-
1070
-    /**
1071
-     * Gets all descendants that are tickets
1072
-     *
1073
-     * @uses  EEH_Line_Item::get_line_items_of_object_type()
1074
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1075
-     * @return EE_Line_Item[]
1076
-     */
1077
-    public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1078
-    {
1079
-        return self::get_line_items_of_object_type($parent_line_item, 'Ticket');
1080
-    }
1081
-
1082
-
1083
-    /**
1084
-     * Gets all descendants subtotals that match the supplied object type
1085
-     *
1086
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1087
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1088
-     * @param string $obj_type
1089
-     * @return EE_Line_Item[]
1090
-     */
1091
-    public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1092
-    {
1093
-        return self::_get_descendants_by_type_and_object_type($parent_line_item, EEM_Line_Item::type_line_item, $obj_type);
1094
-    }
1095
-
1096
-
1097
-    /**
1098
-     * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1099
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1100
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1101
-     * @return EE_Line_Item[]
1102
-     */
1103
-    public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1104
-    {
1105
-        return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_tax);
1106
-    }
1107
-
1108
-
1109
-    /**
1110
-     * Gets all the real items purchased which are children of this item
1111
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1112
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1113
-     * @return EE_Line_Item[]
1114
-     */
1115
-    public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1116
-    {
1117
-        return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_line_item);
1118
-    }
1119
-
1120
-
1121
-    /**
1122
-     * Gets all descendants of supplied line item that match the supplied line item type
1123
-     *
1124
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1125
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1126
-     * @param string $line_item_type one of the EEM_Line_Item constants
1127
-     * @return EE_Line_Item[]
1128
-     */
1129
-    public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1130
-    {
1131
-        return self::_get_descendants_by_type_and_object_type($parent_line_item, $line_item_type, NULL);
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1137
-     *
1138
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1139
-     * @param string $line_item_type one of the EEM_Line_Item constants
1140
-     * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when searching
1141
-     * @return EE_Line_Item[]
1142
-     */
1143
-    protected static function _get_descendants_by_type_and_object_type(
1144
-        EE_Line_Item $parent_line_item,
1145
-        $line_item_type,
1146
-        $obj_type = null
1147
-    )
1148
-    {
1149
-        $objects = array();
1150
-        foreach ($parent_line_item->children() as $child_line_item) {
1151
-            if ($child_line_item instanceof EE_Line_Item) {
1152
-                if (
1153
-                    $child_line_item->type() === $line_item_type
1154
-                    && (
1155
-                        $child_line_item->OBJ_type() === $obj_type || $obj_type === null
1156
-                    )
1157
-                ) {
1158
-                    $objects[] = $child_line_item;
1159
-                } else {
1160
-                    //go-through-all-its children looking for more matches
1161
-                    $objects = array_merge(
1162
-                        $objects,
1163
-                        self::_get_descendants_by_type_and_object_type(
1164
-                            $child_line_item,
1165
-                            $line_item_type,
1166
-                            $obj_type
1167
-                        )
1168
-                    );
1169
-                }
1170
-            }
1171
-        }
1172
-        return $objects;
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * Gets all descendants subtotals that match the supplied object type
1178
-     *
1179
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1180
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1181
-     * @param string $OBJ_type object type (like Event)
1182
-     * @param array $OBJ_IDs array of OBJ_IDs
1183
-     * @return EE_Line_Item[]
1184
-     */
1185
-    public static function get_line_items_by_object_type_and_IDs(
1186
-        EE_Line_Item $parent_line_item,
1187
-        $OBJ_type = '',
1188
-        $OBJ_IDs = array()
1189
-    )
1190
-    {
1191
-        return self::_get_descendants_by_object_type_and_object_ID($parent_line_item, $OBJ_type, $OBJ_IDs);
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1197
-     *
1198
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1199
-     * @param string $OBJ_type object type (like Event)
1200
-     * @param array $OBJ_IDs array of OBJ_IDs
1201
-     * @return EE_Line_Item[]
1202
-     */
1203
-    protected static function _get_descendants_by_object_type_and_object_ID(
1204
-        EE_Line_Item $parent_line_item,
1205
-        $OBJ_type,
1206
-        $OBJ_IDs
1207
-    )
1208
-    {
1209
-        $objects = array();
1210
-        foreach ($parent_line_item->children() as $child_line_item) {
1211
-            if ($child_line_item instanceof EE_Line_Item) {
1212
-                if (
1213
-                    $child_line_item->OBJ_type() === $OBJ_type
1214
-                    && is_array($OBJ_IDs)
1215
-                    && in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1216
-                ) {
1217
-                    $objects[] = $child_line_item;
1218
-                } else {
1219
-                    //go-through-all-its children looking for more matches
1220
-                    $objects = array_merge(
1221
-                        $objects,
1222
-                        self::_get_descendants_by_object_type_and_object_ID(
1223
-                            $child_line_item,
1224
-                            $OBJ_type,
1225
-                            $OBJ_IDs
1226
-                        )
1227
-                    );
1228
-                }
1229
-            }
1230
-        }
1231
-        return $objects;
1232
-    }
1233
-
1234
-
1235
-    /**
1236
-     * Uses a breadth-first-search in order to find the nearest descendant of
1237
-     * the specified type and returns it, else NULL
1238
-     *
1239
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1240
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1241
-     * @param string $type like one of the EEM_Line_Item::type_*
1242
-     * @return EE_Line_Item
1243
-     */
1244
-    public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1245
-    {
1246
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1247
-    }
1248
-
1249
-
1250
-    /**
1251
-     * Uses a breadth-first-search in order to find the nearest descendant
1252
-     * having the specified LIN_code and returns it, else NULL
1253
-     *
1254
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1255
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1256
-     * @param string $code any value used for LIN_code
1257
-     * @return EE_Line_Item
1258
-     */
1259
-    public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1260
-    {
1261
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1262
-    }
1263
-
1264
-
1265
-    /**
1266
-     * Uses a breadth-first-search in order to find the nearest descendant
1267
-     * having the specified LIN_code and returns it, else NULL
1268
-     *
1269
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1270
-     * @param string $search_field name of EE_Line_Item property
1271
-     * @param string $value any value stored in $search_field
1272
-     * @return EE_Line_Item
1273
-     */
1274
-    protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1275
-    {
1276
-        foreach ($parent_line_item->children() as $child) {
1277
-            if ($child->get($search_field) == $value) {
1278
-                return $child;
1279
-            }
1280
-        }
1281
-        foreach ($parent_line_item->children() as $child) {
1282
-            $descendant_found = self::_get_nearest_descendant($child, $search_field, $value);
1283
-            if ($descendant_found) {
1284
-                return $descendant_found;
1285
-            }
1286
-        }
1287
-        return NULL;
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1293
-     * else recursively walks up the line item tree until a parent of type total is found,
1294
-     *
1295
-     * @param EE_Line_Item $line_item
1296
-     * @return \EE_Line_Item
1297
-     * @throws \EE_Error
1298
-     */
1299
-    public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1300
-    {
1301
-        if ($line_item->TXN_ID()) {
1302
-            $total_line_item = $line_item->transaction()->total_line_item(false);
1303
-            if ($total_line_item instanceof EE_Line_Item) {
1304
-                return $total_line_item;
1305
-            }
1306
-        } else {
1307
-            $line_item_parent = $line_item->parent();
1308
-            if ($line_item_parent instanceof EE_Line_Item) {
1309
-                if ($line_item_parent->is_total()) {
1310
-                    return $line_item_parent;
1311
-                }
1312
-                return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1313
-            }
1314
-        }
1315
-        throw new EE_Error(
1316
-            sprintf(
1317
-                __('A valid grand total for line item %1$d was not found.', 'event_espresso'),
1318
-                $line_item->ID()
1319
-            )
1320
-        );
1321
-    }
1322
-
1323
-
1324
-    /**
1325
-     * Prints out a representation of the line item tree
1326
-     *
1327
-     * @param EE_Line_Item $line_item
1328
-     * @param int $indentation
1329
-     * @return void
1330
-     * @throws \EE_Error
1331
-     */
1332
-    public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1333
-    {
1334
-        echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1335
-        if (!$indentation) {
1336
-            echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1337
-        }
1338
-        for ($i = 0; $i < $indentation; $i++) {
1339
-            echo ". ";
1340
-        }
1341
-        $breakdown = '';
1342
-        if ($line_item->is_line_item()) {
1343
-            if ($line_item->is_percent()) {
1344
-                $breakdown = "{$line_item->percent()}%";
1345
-            } else {
1346
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1347
-            }
1348
-        }
1349
-        echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}";
1350
-        if ($breakdown) {
1351
-            echo " ( {$breakdown} )";
1352
-        }
1353
-        if ($line_item->is_taxable()) {
1354
-            echo "  * taxable";
1355
-        }
1356
-        if ($line_item->children()) {
1357
-            foreach ($line_item->children() as $child) {
1358
-                self::visualize($child, $indentation + 1);
1359
-            }
1360
-        }
1361
-    }
1362
-
1363
-
1364
-    /**
1365
-     * Calculates the registration's final price, taking into account that they
1366
-     * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1367
-     * and receive a portion of any transaction-wide discounts.
1368
-     * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1369
-     * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1370
-     * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1371
-     * and brent's final price should be $5.50.
1372
-     *
1373
-     * In order to do this, we basically need to traverse the line item tree calculating
1374
-     * the running totals (just as if we were recalculating the total), but when we identify
1375
-     * regular line items, we need to keep track of their share of the grand total.
1376
-     * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1377
-     * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1378
-     * when there are non-taxable items; otherwise they would be the same)
1379
-     *
1380
-     * @param EE_Line_Item $line_item
1381
-     * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that
1382
-     *                                                                            can be included in price calculations at this moment
1383
-     * @return array        keys are line items for tickets IDs and values are their share of the running total,
1384
-     *                                          plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg
1385
-     *                                          array(
1386
-     *                                          12 => 4.3
1387
-     *                                          23 => 8.0
1388
-     *                                          'total' => 16.6,
1389
-     *                                          'taxable' => array(
1390
-     *                                          12 => 10,
1391
-     *                                          23 => 4
1392
-     *                                          ).
1393
-     *                                          So to find which registrations have which final price, we need to find which line item
1394
-     *                                          is theirs, which can be done with
1395
-     *                                          `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );`
1396
-     */
1397
-    public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array())
1398
-    {
1399
-        //init running grand total if not already
1400
-        if (!isset($running_totals['total'])) {
1401
-            $running_totals['total'] = 0;
1402
-        }
1403
-        if (!isset($running_totals['taxable'])) {
1404
-            $running_totals['taxable'] = array('total' => 0);
1405
-        }
1406
-        foreach ($line_item->children() as $child_line_item) {
1407
-            switch ($child_line_item->type()) {
1408
-
1409
-                case EEM_Line_Item::type_sub_total :
1410
-                    $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities);
1411
-                    //combine arrays but preserve numeric keys
1412
-                    $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1413
-                    $running_totals['total'] += $running_totals_from_subtotal['total'];
1414
-                    $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1415
-                    break;
1416
-
1417
-                case EEM_Line_Item::type_tax_sub_total :
1418
-
1419
-                    //find how much the taxes percentage is
1420
-                    if ($child_line_item->percent() !== 0) {
1421
-                        $tax_percent_decimal = $child_line_item->percent() / 100;
1422
-                    } else {
1423
-                        $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1424
-                    }
1425
-                    //and apply to all the taxable totals, and add to the pretax totals
1426
-                    foreach ($running_totals as $line_item_id => $this_running_total) {
1427
-                        //"total" and "taxable" array key is an exception
1428
-                        if ($line_item_id === 'taxable') {
1429
-                            continue;
1430
-                        }
1431
-                        $taxable_total = $running_totals['taxable'][$line_item_id];
1432
-                        $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal);
1433
-                    }
1434
-                    break;
1435
-
1436
-                case EEM_Line_Item::type_line_item :
1437
-
1438
-                    // ticket line items or ????
1439
-                    if ($child_line_item->OBJ_type() === 'Ticket') {
1440
-                        // kk it's a ticket
1441
-                        if (isset($running_totals[$child_line_item->ID()])) {
1442
-                            //huh? that shouldn't happen.
1443
-                            $running_totals['total'] += $child_line_item->total();
1444
-                        } else {
1445
-                            //its not in our running totals yet. great.
1446
-                            if ($child_line_item->is_taxable()) {
1447
-                                $taxable_amount = $child_line_item->unit_price();
1448
-                            } else {
1449
-                                $taxable_amount = 0;
1450
-                            }
1451
-                            // are we only calculating totals for some tickets?
1452
-                            if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) {
1453
-                                $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()];
1454
-                                $running_totals[$child_line_item->ID()] = $quantity
1455
-                                    ? $child_line_item->unit_price()
1456
-                                    : 0;
1457
-                                $running_totals['taxable'][$child_line_item->ID()] = $quantity
1458
-                                    ? $taxable_amount
1459
-                                    : 0;
1460
-                            } else {
1461
-                                $quantity = $child_line_item->quantity();
1462
-                                $running_totals[$child_line_item->ID()] = $child_line_item->unit_price();
1463
-                                $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount;
1464
-                            }
1465
-                            $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1466
-                            $running_totals['total'] += $child_line_item->unit_price() * $quantity;
1467
-                        }
1468
-                    } else {
1469
-                        // it's some other type of item added to the cart
1470
-                        // it should affect the running totals
1471
-                        // basically we want to convert it into a PERCENT modifier. Because
1472
-                        // more clearly affect all registration's final price equally
1473
-                        $line_items_percent_of_running_total = $running_totals['total'] > 0
1474
-                            ? ($child_line_item->total() / $running_totals['total']) + 1
1475
-                            : 1;
1476
-                        foreach ($running_totals as $line_item_id => $this_running_total) {
1477
-                            //the "taxable" array key is an exception
1478
-                            if ($line_item_id === 'taxable') {
1479
-                                continue;
1480
-                            }
1481
-                            // update the running totals
1482
-                            // yes this actually even works for the running grand total!
1483
-                            $running_totals[$line_item_id] =
1484
-                                $line_items_percent_of_running_total * $this_running_total;
1485
-
1486
-                            if ($child_line_item->is_taxable()) {
1487
-                                $running_totals['taxable'][$line_item_id] =
1488
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id];
1489
-                            }
1490
-                        }
1491
-                    }
1492
-                    break;
1493
-            }
1494
-        }
1495
-        return $running_totals;
1496
-    }
1497
-
1498
-
1499
-    /**
1500
-     * @param \EE_Line_Item $total_line_item
1501
-     * @param \EE_Line_Item $ticket_line_item
1502
-     * @return float | null
1503
-     * @throws \OutOfRangeException
1504
-     */
1505
-    public static function calculate_final_price_for_ticket_line_item(\EE_Line_Item $total_line_item, \EE_Line_Item $ticket_line_item)
1506
-    {
1507
-        static $final_prices_per_ticket_line_item = array();
1508
-        if (empty($final_prices_per_ticket_line_item)) {
1509
-            $final_prices_per_ticket_line_item = \EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1510
-                $total_line_item
1511
-            );
1512
-        }
1513
-        //ok now find this new registration's final price
1514
-        if (isset($final_prices_per_ticket_line_item[$ticket_line_item->ID()])) {
1515
-            return $final_prices_per_ticket_line_item[$ticket_line_item->ID()];
1516
-        }
1517
-        $message = sprintf(
1518
-            __(
1519
-                'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1520
-                'event_espresso'
1521
-            ),
1522
-            $ticket_line_item->ID()
1523
-        );
1524
-        if (WP_DEBUG) {
1525
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1526
-            throw new \OutOfRangeException($message);
1527
-        } else {
1528
-            EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1529
-        }
1530
-        return null;
1531
-    }
1532
-
1533
-
1534
-    /**
1535
-     * Creates a duplicate of the line item tree, except only includes billable items
1536
-     * and the portion of line items attributed to billable things
1537
-     *
1538
-     * @param EE_Line_Item $line_item
1539
-     * @param EE_Registration[] $registrations
1540
-     * @return \EE_Line_Item
1541
-     * @throws \EE_Error
1542
-     */
1543
-    public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1544
-    {
1545
-        $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1546
-        foreach ($line_item->children() as $child_li) {
1547
-            $copy_li->add_child_line_item(EEH_Line_Item::billable_line_item_tree($child_li, $registrations));
1548
-        }
1549
-        //if this is the grand total line item, make sure the totals all add up
1550
-        //(we could have duplicated this logic AS we copied the line items, but
1551
-        //it seems DRYer this way)
1552
-        if ($copy_li->type() === EEM_Line_Item::type_total) {
1553
-            $copy_li->recalculate_total_including_taxes();
1554
-        }
1555
-        return $copy_li;
1556
-    }
1557
-
1558
-
1559
-    /**
1560
-     * Creates a new, unsaved line item from $line_item that factors in the
1561
-     * number of billable registrations on $registrations.
1562
-     *
1563
-     * @param EE_Line_Item $line_item
1564
-     * @return EE_Line_Item
1565
-     * @throws \EE_Error
1566
-     * @param EE_Registration[] $registrations
1567
-     */
1568
-    public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1569
-    {
1570
-        $new_li_fields = $line_item->model_field_array();
1571
-        if ($line_item->type() === EEM_Line_Item::type_line_item &&
1572
-            $line_item->OBJ_type() === 'Ticket'
1573
-        ) {
1574
-            $count = 0;
1575
-            foreach ($registrations as $registration) {
1576
-                if ($line_item->OBJ_ID() === $registration->ticket_ID() &&
1577
-                    in_array($registration->status_ID(), EEM_Registration::reg_statuses_that_allow_payment())
1578
-                ) {
1579
-                    $count++;
1580
-                }
1581
-            }
1582
-            $new_li_fields['LIN_quantity'] = $count;
1583
-        }
1584
-        //don't set the total. We'll leave that up to the code that calculates it
1585
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1586
-        return EE_Line_Item::new_instance($new_li_fields);
1587
-    }
1588
-
1589
-
1590
-    /**
1591
-     * Returns a modified line item tree where all the subtotals which have a total of 0
1592
-     * are removed, and line items with a quantity of 0
1593
-     *
1594
-     * @param EE_Line_Item $line_item |null
1595
-     * @return \EE_Line_Item|null
1596
-     * @throws \EE_Error
1597
-     */
1598
-    public static function non_empty_line_items(EE_Line_Item $line_item)
1599
-    {
1600
-        $copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1601
-        if ($copied_li === null) {
1602
-            return null;
1603
-        }
1604
-        //if this is an event subtotal, we want to only include it if it
1605
-        //has a non-zero total and at least one ticket line item child
1606
-        $ticket_children = 0;
1607
-        foreach ($line_item->children() as $child_li) {
1608
-            $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1609
-            if ($child_li_copy !== null) {
1610
-                $copied_li->add_child_line_item($child_li_copy);
1611
-                if ($child_li_copy->type() === EEM_Line_Item::type_line_item &&
1612
-                    $child_li_copy->OBJ_type() === 'Ticket'
1613
-                ) {
1614
-                    $ticket_children++;
1615
-                }
1616
-            }
1617
-        }
1618
-        //if this is an event subtotal with NO ticket children
1619
-        //we basically want to ignore it
1620
-        if (
1621
-            $ticket_children === 0
1622
-            && $line_item->type() === EEM_Line_Item::type_sub_total
1623
-            && $line_item->OBJ_type() === 'Event'
1624
-            && $line_item->total() === 0
1625
-        ) {
1626
-            return null;
1627
-        }
1628
-        return $copied_li;
1629
-    }
1630
-
1631
-
1632
-    /**
1633
-     * Creates a new, unsaved line item, but if it's a ticket line item
1634
-     * with a total of 0, or a subtotal of 0, returns null instead
1635
-     *
1636
-     * @param EE_Line_Item $line_item
1637
-     * @return EE_Line_Item
1638
-     * @throws \EE_Error
1639
-     */
1640
-    public static function non_empty_line_item(EE_Line_Item $line_item)
1641
-    {
1642
-        if ($line_item->type() === EEM_Line_Item::type_line_item &&
1643
-            $line_item->OBJ_type() === 'Ticket' &&
1644
-            $line_item->quantity() === 0
1645
-        ) {
1646
-            return null;
1647
-        }
1648
-        $new_li_fields = $line_item->model_field_array();
1649
-        //don't set the total. We'll leave that up to the code that calculates it
1650
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1651
-        return EE_Line_Item::new_instance($new_li_fields);
1652
-    }
1653
-
1654
-
1655
-
1656
-    /**************************************** @DEPRECATED METHODS *************************************** */
1657
-    /**
1658
-     * @deprecated
1659
-     * @param EE_Line_Item $total_line_item
1660
-     * @return \EE_Line_Item
1661
-     * @throws \EE_Error
1662
-     */
1663
-    public static function get_items_subtotal(EE_Line_Item $total_line_item)
1664
-    {
1665
-        EE_Error::doing_it_wrong('EEH_Line_Item::get_items_subtotal()', __('Method replaced with EEH_Line_Item::get_pre_tax_subtotal()', 'event_espresso'), '4.6.0');
1666
-        return self::get_pre_tax_subtotal($total_line_item);
1667
-    }
1668
-
1669
-
1670
-    /**
1671
-     * @deprecated
1672
-     * @param EE_Transaction $transaction
1673
-     * @return \EE_Line_Item
1674
-     * @throws \EE_Error
1675
-     */
1676
-    public static function create_default_total_line_item($transaction = NULL)
1677
-    {
1678
-        EE_Error::doing_it_wrong('EEH_Line_Item::create_default_total_line_item()', __('Method replaced with EEH_Line_Item::create_total_line_item()', 'event_espresso'), '4.6.0');
1679
-        return self::create_total_line_item($transaction);
1680
-    }
1681
-
1682
-
1683
-    /**
1684
-     * @deprecated
1685
-     * @param EE_Line_Item $total_line_item
1686
-     * @param EE_Transaction $transaction
1687
-     * @return \EE_Line_Item
1688
-     * @throws \EE_Error
1689
-     */
1690
-    public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
1691
-    {
1692
-        EE_Error::doing_it_wrong('EEH_Line_Item::create_default_tickets_subtotal()', __('Method replaced with EEH_Line_Item::create_pre_tax_subtotal()', 'event_espresso'), '4.6.0');
1693
-        return self::create_pre_tax_subtotal($total_line_item, $transaction);
1694
-    }
1695
-
1696
-
1697
-    /**
1698
-     * @deprecated
1699
-     * @param EE_Line_Item $total_line_item
1700
-     * @param EE_Transaction $transaction
1701
-     * @return \EE_Line_Item
1702
-     * @throws \EE_Error
1703
-     */
1704
-    public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
1705
-    {
1706
-        EE_Error::doing_it_wrong('EEH_Line_Item::create_default_taxes_subtotal()', __('Method replaced with EEH_Line_Item::create_taxes_subtotal()', 'event_espresso'), '4.6.0');
1707
-        return self::create_taxes_subtotal($total_line_item, $transaction);
1708
-    }
1709
-
1710
-
1711
-    /**
1712
-     * @deprecated
1713
-     * @param EE_Line_Item $total_line_item
1714
-     * @param EE_Transaction $transaction
1715
-     * @return \EE_Line_Item
1716
-     * @throws \EE_Error
1717
-     */
1718
-    public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
1719
-    {
1720
-        EE_Error::doing_it_wrong('EEH_Line_Item::create_default_event_subtotal()', __('Method replaced with EEH_Line_Item::create_event_subtotal()', 'event_espresso'), '4.6.0');
1721
-        return self::create_event_subtotal($total_line_item, $transaction);
1722
-    }
26
+	//other functions: cancel ticket purchase
27
+	//delete ticket purchase
28
+	//add promotion
29
+
30
+
31
+	/**
32
+	 * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
33
+	 * Does NOT automatically re-calculate the line item totals or update the related transaction.
34
+	 * You should call recalculate_total_including_taxes() on the grant total line item after this
35
+	 * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
36
+	 * to keep the registration final prices in-sync with the transaction's total.
37
+	 *
38
+	 * @param EE_Line_Item $parent_line_item
39
+	 * @param string $name
40
+	 * @param float $unit_price
41
+	 * @param string $description
42
+	 * @param int $quantity
43
+	 * @param boolean $taxable
44
+	 * @param boolean $code if set to a value, ensures there is only one line item with that code
45
+	 * @return boolean success
46
+	 * @throws \EE_Error
47
+	 */
48
+	public static function add_unrelated_item(EE_Line_Item $parent_line_item, $name, $unit_price, $description = '', $quantity = 1, $taxable = FALSE, $code = NULL)
49
+	{
50
+		$items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
51
+		$line_item = EE_Line_Item::new_instance(array(
52
+			'LIN_name' => $name,
53
+			'LIN_desc' => $description,
54
+			'LIN_unit_price' => $unit_price,
55
+			'LIN_quantity' => $quantity,
56
+			'LIN_percent' => null,
57
+			'LIN_is_taxable' => $taxable,
58
+			'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
59
+			'LIN_total' => (float)$unit_price * (int)$quantity,
60
+			'LIN_type' => EEM_Line_Item::type_line_item,
61
+			'LIN_code' => $code,
62
+		));
63
+		$line_item = apply_filters(
64
+			'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
65
+			$line_item,
66
+			$parent_line_item
67
+		);
68
+		return self::add_item($parent_line_item, $line_item);
69
+	}
70
+
71
+
72
+	/**
73
+	 * Adds a simple item ( unrelated to any other model object) to the total line item,
74
+	 * in the correct spot in the line item tree. Automatically
75
+	 * re-calculates the line item totals and updates the related transaction. But
76
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
77
+	 * should probably change because of this).
78
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
79
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
80
+	 *
81
+	 * @param EE_Line_Item $parent_line_item
82
+	 * @param string $name
83
+	 * @param float $percentage_amount
84
+	 * @param string $description
85
+	 * @param boolean $taxable
86
+	 * @return boolean success
87
+	 * @throws \EE_Error
88
+	 */
89
+	public static function add_percentage_based_item(EE_Line_Item $parent_line_item, $name, $percentage_amount, $description = '', $taxable = FALSE)
90
+	{
91
+		$line_item = EE_Line_Item::new_instance(array(
92
+			'LIN_name' => $name,
93
+			'LIN_desc' => $description,
94
+			'LIN_unit_price' => 0,
95
+			'LIN_percent' => $percentage_amount,
96
+			'LIN_quantity' => 1,
97
+			'LIN_is_taxable' => $taxable,
98
+			'LIN_total' => (float)($percentage_amount * ($parent_line_item->total() / 100)),
99
+			'LIN_type' => EEM_Line_Item::type_line_item,
100
+			'LIN_parent' => $parent_line_item->ID()
101
+		));
102
+		$line_item = apply_filters(
103
+			'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
104
+			$line_item
105
+		);
106
+		return $parent_line_item->add_child_line_item($line_item, false);
107
+	}
108
+
109
+
110
+	/**
111
+	 * Returns the new line item created by adding a purchase of the ticket
112
+	 * ensures that ticket line item is saved, and that cart total has been recalculated.
113
+	 * If this ticket has already been purchased, just increments its count.
114
+	 * Automatically re-calculates the line item totals and updates the related transaction. But
115
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
116
+	 * should probably change because of this).
117
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
118
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
119
+	 *
120
+	 * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
121
+	 * @param EE_Ticket $ticket
122
+	 * @param int $qty
123
+	 * @return \EE_Line_Item
124
+	 * @throws \EE_Error
125
+	 */
126
+	public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
127
+	{
128
+		if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) {
129
+			throw new EE_Error(sprintf(__('A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', 'event_espresso'), $ticket->ID(), $total_line_item->ID()));
130
+		}
131
+		// either increment the qty for an existing ticket
132
+		$line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
133
+		// or add a new one
134
+		if (!$line_item instanceof EE_Line_Item) {
135
+			$line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
136
+		}
137
+		$total_line_item->recalculate_total_including_taxes();
138
+		return $line_item;
139
+	}
140
+
141
+
142
+	/**
143
+	 * Returns the new line item created by adding a purchase of the ticket
144
+	 * @param \EE_Line_Item $total_line_item
145
+	 * @param EE_Ticket $ticket
146
+	 * @param int $qty
147
+	 * @return \EE_Line_Item
148
+	 * @throws \EE_Error
149
+	 */
150
+	public static function increment_ticket_qty_if_already_in_cart(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
151
+	{
152
+		$line_item = null;
153
+		if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
154
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
155
+			foreach ((array)$ticket_line_items as $ticket_line_item) {
156
+				if (
157
+					$ticket_line_item instanceof EE_Line_Item
158
+					&& (int)$ticket_line_item->OBJ_ID() === (int)$ticket->ID()
159
+				) {
160
+					$line_item = $ticket_line_item;
161
+					break;
162
+				}
163
+			}
164
+		}
165
+		if ($line_item instanceof EE_Line_Item) {
166
+			EEH_Line_Item::increment_quantity($line_item, $qty);
167
+			return $line_item;
168
+		}
169
+		return null;
170
+	}
171
+
172
+
173
+	/**
174
+	 * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
175
+	 * Does NOT save or recalculate other line items totals
176
+	 *
177
+	 * @param EE_Line_Item $line_item
178
+	 * @param int $qty
179
+	 * @return void
180
+	 * @throws \EE_Error
181
+	 */
182
+	public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
183
+	{
184
+		if (!$line_item->is_percent()) {
185
+			$qty += $line_item->quantity();
186
+			$line_item->set_quantity($qty);
187
+			$line_item->set_total($line_item->unit_price() * $qty);
188
+			$line_item->save();
189
+		}
190
+		foreach ($line_item->children() as $child) {
191
+			if ($child->is_sub_line_item()) {
192
+				EEH_Line_Item::update_quantity($child, $qty);
193
+			}
194
+		}
195
+	}
196
+
197
+
198
+	/**
199
+	 * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
200
+	 * Does NOT save or recalculate other line items totals
201
+	 *
202
+	 * @param EE_Line_Item $line_item
203
+	 * @param int $qty
204
+	 * @return void
205
+	 * @throws \EE_Error
206
+	 */
207
+	public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
208
+	{
209
+		if (!$line_item->is_percent()) {
210
+			$qty = $line_item->quantity() - $qty;
211
+			$qty = max($qty, 0);
212
+			$line_item->set_quantity($qty);
213
+			$line_item->set_total($line_item->unit_price() * $qty);
214
+			$line_item->save();
215
+		}
216
+		foreach ($line_item->children() as $child) {
217
+			if ($child->is_sub_line_item()) {
218
+				EEH_Line_Item::update_quantity($child, $qty);
219
+			}
220
+		}
221
+	}
222
+
223
+
224
+	/**
225
+	 * Updates the line item and its children's quantities to the specified number.
226
+	 * Does NOT save them or recalculate totals.
227
+	 *
228
+	 * @param EE_Line_Item $line_item
229
+	 * @param int $new_quantity
230
+	 * @throws \EE_Error
231
+	 */
232
+	public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
233
+	{
234
+		if (!$line_item->is_percent()) {
235
+			$line_item->set_quantity($new_quantity);
236
+			$line_item->set_total($line_item->unit_price() * $new_quantity);
237
+			$line_item->save();
238
+		}
239
+		foreach ($line_item->children() as $child) {
240
+			if ($child->is_sub_line_item()) {
241
+				EEH_Line_Item::update_quantity($child, $new_quantity);
242
+			}
243
+		}
244
+	}
245
+
246
+
247
+	/**
248
+	 * Returns the new line item created by adding a purchase of the ticket
249
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
250
+	 * @param EE_Ticket $ticket
251
+	 * @param int $qty
252
+	 * @return \EE_Line_Item
253
+	 * @throws \EE_Error
254
+	 */
255
+	public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
256
+	{
257
+		$datetimes = $ticket->datetimes();
258
+		$first_datetime = reset($datetimes);
259
+		if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
260
+			$first_datetime_name = $first_datetime->event()->name();
261
+		} else {
262
+			$first_datetime_name = __('Event', 'event_espresso');
263
+		}
264
+		$event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
265
+		// get event subtotal line
266
+		$events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
267
+		// add $ticket to cart
268
+		$line_item = EE_Line_Item::new_instance(array(
269
+			'LIN_name' => $ticket->name(),
270
+			'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
271
+			'LIN_unit_price' => $ticket->price(),
272
+			'LIN_quantity' => $qty,
273
+			'LIN_is_taxable' => $ticket->taxable(),
274
+			'LIN_order' => count($events_sub_total->children()),
275
+			'LIN_total' => $ticket->price() * $qty,
276
+			'LIN_type' => EEM_Line_Item::type_line_item,
277
+			'OBJ_ID' => $ticket->ID(),
278
+			'OBJ_type' => 'Ticket'
279
+		));
280
+		$line_item = apply_filters(
281
+			'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
282
+			$line_item
283
+		);
284
+		$events_sub_total->add_child_line_item($line_item);
285
+		//now add the sub-line items
286
+		$running_total_for_ticket = 0;
287
+		foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
288
+			$sign = $price->is_discount() ? -1 : 1;
289
+			$price_total = $price->is_percent()
290
+				? $running_total_for_ticket * $price->amount() / 100
291
+				: $price->amount() * $qty;
292
+			$sub_line_item = EE_Line_Item::new_instance(array(
293
+				'LIN_name' => $price->name(),
294
+				'LIN_desc' => $price->desc(),
295
+				'LIN_quantity' => $price->is_percent() ? null : $qty,
296
+				'LIN_is_taxable' => false,
297
+				'LIN_order' => $price->order(),
298
+				'LIN_total' => $sign * $price_total,
299
+				'LIN_type' => EEM_Line_Item::type_sub_line_item,
300
+				'OBJ_ID' => $price->ID(),
301
+				'OBJ_type' => 'Price'
302
+			));
303
+			$sub_line_item = apply_filters(
304
+				'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
305
+				$sub_line_item
306
+			);
307
+			if ($price->is_percent()) {
308
+				$sub_line_item->set_percent($sign * $price->amount());
309
+			} else {
310
+				$sub_line_item->set_unit_price($sign * $price->amount());
311
+			}
312
+			$running_total_for_ticket += $price_total;
313
+			$line_item->add_child_line_item($sub_line_item);
314
+		}
315
+		return $line_item;
316
+	}
317
+
318
+
319
+	/**
320
+	 * Adds the specified item under the pre-tax-sub-total line item. Automatically
321
+	 * re-calculates the line item totals and updates the related transaction. But
322
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
323
+	 * should probably change because of this).
324
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
325
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
326
+	 *
327
+	 * @param EE_Line_Item $total_line_item
328
+	 * @param EE_Line_Item $item to be added
329
+	 * @return boolean
330
+	 * @throws \EE_Error
331
+	 */
332
+	public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
333
+	{
334
+		$pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
335
+		if ($pre_tax_subtotal instanceof EE_Line_Item) {
336
+			$success = $pre_tax_subtotal->add_child_line_item($item);
337
+		} else {
338
+			return FALSE;
339
+		}
340
+		$total_line_item->recalculate_total_including_taxes();
341
+		return $success;
342
+	}
343
+
344
+
345
+	/**
346
+	 * cancels an existing ticket line item,
347
+	 * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
348
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
349
+	 *
350
+	 * @param EE_Line_Item $ticket_line_item
351
+	 * @param int $qty
352
+	 * @return bool success
353
+	 * @throws \EE_Error
354
+	 */
355
+	public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
356
+	{
357
+		// validate incoming line_item
358
+		if ($ticket_line_item->OBJ_type() !== 'Ticket') {
359
+			throw new EE_Error(
360
+				sprintf(
361
+					__('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
362
+					$ticket_line_item->type()
363
+				)
364
+			);
365
+		}
366
+		if ($ticket_line_item->quantity() < $qty) {
367
+			throw new EE_Error(
368
+				sprintf(
369
+					__('Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', 'event_espresso'),
370
+					$qty,
371
+					$ticket_line_item->quantity()
372
+				)
373
+			);
374
+		}
375
+		// decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
376
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
377
+		foreach ($ticket_line_item->children() as $child_line_item) {
378
+			if (
379
+				$child_line_item->is_sub_line_item()
380
+				&& !$child_line_item->is_percent()
381
+				&& !$child_line_item->is_cancellation()
382
+			) {
383
+				$child_line_item->set_quantity($child_line_item->quantity() - $qty);
384
+			}
385
+		}
386
+		// get cancellation sub line item
387
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
388
+			$ticket_line_item,
389
+			EEM_Line_Item::type_cancellation
390
+		);
391
+		$cancellation_line_item = reset($cancellation_line_item);
392
+		// verify that this ticket was indeed previously cancelled
393
+		if ($cancellation_line_item instanceof EE_Line_Item) {
394
+			// increment cancelled quantity
395
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
396
+		} else {
397
+			// create cancellation sub line item
398
+			$cancellation_line_item = EE_Line_Item::new_instance(array(
399
+				'LIN_name' => __('Cancellation', 'event_espresso'),
400
+				'LIN_desc' => sprintf(
401
+					_x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'),
402
+					$ticket_line_item->name(),
403
+					current_time(get_option('date_format') . ' ' . get_option('time_format'))
404
+				),
405
+				'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
406
+				'LIN_quantity' => $qty,
407
+				'LIN_is_taxable' => $ticket_line_item->is_taxable(),
408
+				'LIN_order' => count($ticket_line_item->children()),
409
+				'LIN_total' => 0, // $ticket_line_item->unit_price()
410
+				'LIN_type' => EEM_Line_Item::type_cancellation,
411
+			));
412
+			$ticket_line_item->add_child_line_item($cancellation_line_item);
413
+		}
414
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
415
+			// decrement parent line item quantity
416
+			$event_line_item = $ticket_line_item->parent();
417
+			if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
418
+				$event_line_item->set_quantity($event_line_item->quantity() - $qty);
419
+				$event_line_item->save();
420
+			}
421
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
422
+			return true;
423
+		}
424
+		return false;
425
+	}
426
+
427
+
428
+	/**
429
+	 * reinstates (un-cancels?) a previously canceled ticket line item,
430
+	 * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
431
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
432
+	 *
433
+	 * @param EE_Line_Item $ticket_line_item
434
+	 * @param int $qty
435
+	 * @return bool success
436
+	 * @throws \EE_Error
437
+	 */
438
+	public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
439
+	{
440
+		// validate incoming line_item
441
+		if ($ticket_line_item->OBJ_type() !== 'Ticket') {
442
+			throw new EE_Error(
443
+				sprintf(
444
+					__('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
445
+					$ticket_line_item->type()
446
+				)
447
+			);
448
+		}
449
+		// get cancellation sub line item
450
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
451
+			$ticket_line_item,
452
+			EEM_Line_Item::type_cancellation
453
+		);
454
+		$cancellation_line_item = reset($cancellation_line_item);
455
+		// verify that this ticket was indeed previously cancelled
456
+		if (!$cancellation_line_item instanceof EE_Line_Item) {
457
+			return false;
458
+		}
459
+		if ($cancellation_line_item->quantity() > $qty) {
460
+			// decrement cancelled quantity
461
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
462
+		} else if ($cancellation_line_item->quantity() == $qty) {
463
+			// decrement cancelled quantity in case anyone still has the object kicking around
464
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
465
+			// delete because quantity will end up as 0
466
+			$cancellation_line_item->delete();
467
+			// and attempt to destroy the object,
468
+			// even though PHP won't actually destroy it until it needs the memory
469
+			unset($cancellation_line_item);
470
+		} else {
471
+			// what ?!?! negative quantity ?!?!
472
+			throw new EE_Error(
473
+				sprintf(
474
+					__('Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
475
+						'event_espresso'),
476
+					$qty,
477
+					$cancellation_line_item->quantity()
478
+				)
479
+			);
480
+		}
481
+		// increment ticket quantity
482
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
483
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
484
+			// increment parent line item quantity
485
+			$event_line_item = $ticket_line_item->parent();
486
+			if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
487
+				$event_line_item->set_quantity($event_line_item->quantity() + $qty);
488
+			}
489
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
490
+			return true;
491
+		}
492
+		return false;
493
+	}
494
+
495
+
496
+	/**
497
+	 * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
498
+	 * then EE_Line_Item::recalculate_total_including_taxes() on the result
499
+	 *
500
+	 * @param EE_Line_Item $line_item
501
+	 * @return \EE_Line_Item
502
+	 */
503
+	public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
504
+	{
505
+		$grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
506
+		return $grand_total_line_item->recalculate_total_including_taxes();
507
+	}
508
+
509
+
510
+	/**
511
+	 * Gets the line item which contains the subtotal of all the items
512
+	 *
513
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
514
+	 * @return \EE_Line_Item
515
+	 * @throws \EE_Error
516
+	 */
517
+	public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
518
+	{
519
+		$pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
520
+		return $pre_tax_subtotal instanceof EE_Line_Item
521
+			? $pre_tax_subtotal
522
+			: self::create_pre_tax_subtotal($total_line_item);
523
+	}
524
+
525
+
526
+	/**
527
+	 * Gets the line item for the taxes subtotal
528
+	 *
529
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
530
+	 * @return \EE_Line_Item
531
+	 * @throws \EE_Error
532
+	 */
533
+	public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
534
+	{
535
+		$taxes = $total_line_item->get_child_line_item('taxes');
536
+		return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
537
+	}
538
+
539
+
540
+	/**
541
+	 * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
542
+	 *
543
+	 * @param EE_Line_Item $line_item
544
+	 * @param EE_Transaction $transaction
545
+	 * @return void
546
+	 * @throws \EE_Error
547
+	 */
548
+	public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = NULL)
549
+	{
550
+		if ($transaction) {
551
+			/** @type EEM_Transaction $EEM_Transaction */
552
+			$EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
553
+			$TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
554
+			$line_item->set_TXN_ID($TXN_ID);
555
+		}
556
+	}
557
+
558
+
559
+	/**
560
+	 * Creates a new default total line item for the transaction,
561
+	 * and its tickets subtotal and taxes subtotal line items (and adds the
562
+	 * existing taxes as children of the taxes subtotal line item)
563
+	 *
564
+	 * @param EE_Transaction $transaction
565
+	 * @return \EE_Line_Item of type total
566
+	 * @throws \EE_Error
567
+	 */
568
+	public static function create_total_line_item($transaction = NULL)
569
+	{
570
+		$total_line_item = EE_Line_Item::new_instance(array(
571
+			'LIN_code' => 'total',
572
+			'LIN_name' => __('Grand Total', 'event_espresso'),
573
+			'LIN_type' => EEM_Line_Item::type_total,
574
+			'OBJ_type' => 'Transaction'
575
+		));
576
+		$total_line_item = apply_filters(
577
+			'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
578
+			$total_line_item
579
+		);
580
+		self::set_TXN_ID($total_line_item, $transaction);
581
+		self::create_pre_tax_subtotal($total_line_item, $transaction);
582
+		self::create_taxes_subtotal($total_line_item, $transaction);
583
+		return $total_line_item;
584
+	}
585
+
586
+
587
+	/**
588
+	 * Creates a default items subtotal line item
589
+	 *
590
+	 * @param EE_Line_Item $total_line_item
591
+	 * @param EE_Transaction $transaction
592
+	 * @return EE_Line_Item
593
+	 * @throws \EE_Error
594
+	 */
595
+	protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
596
+	{
597
+		$pre_tax_line_item = EE_Line_Item::new_instance(array(
598
+			'LIN_code' => 'pre-tax-subtotal',
599
+			'LIN_name' => __('Pre-Tax Subtotal', 'event_espresso'),
600
+			'LIN_type' => EEM_Line_Item::type_sub_total
601
+		));
602
+		$pre_tax_line_item = apply_filters(
603
+			'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
604
+			$pre_tax_line_item
605
+		);
606
+		self::set_TXN_ID($pre_tax_line_item, $transaction);
607
+		$total_line_item->add_child_line_item($pre_tax_line_item);
608
+		self::create_event_subtotal($pre_tax_line_item, $transaction);
609
+		return $pre_tax_line_item;
610
+	}
611
+
612
+
613
+	/**
614
+	 * Creates a line item for the taxes subtotal and finds all the tax prices
615
+	 * and applies taxes to it
616
+	 *
617
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
618
+	 * @param EE_Transaction $transaction
619
+	 * @return EE_Line_Item
620
+	 * @throws \EE_Error
621
+	 */
622
+	protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
623
+	{
624
+		$tax_line_item = EE_Line_Item::new_instance(array(
625
+			'LIN_code' => 'taxes',
626
+			'LIN_name' => __('Taxes', 'event_espresso'),
627
+			'LIN_type' => EEM_Line_Item::type_tax_sub_total,
628
+			'LIN_order' => 1000,//this should always come last
629
+		));
630
+		$tax_line_item = apply_filters(
631
+			'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
632
+			$tax_line_item
633
+		);
634
+		self::set_TXN_ID($tax_line_item, $transaction);
635
+		$total_line_item->add_child_line_item($tax_line_item);
636
+		//and lastly, add the actual taxes
637
+		self::apply_taxes($total_line_item);
638
+		return $tax_line_item;
639
+	}
640
+
641
+
642
+	/**
643
+	 * Creates a default items subtotal line item
644
+	 *
645
+	 * @param EE_Line_Item $pre_tax_line_item
646
+	 * @param EE_Transaction $transaction
647
+	 * @param EE_Event $event
648
+	 * @return EE_Line_Item
649
+	 * @throws \EE_Error
650
+	 */
651
+	public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = NULL, $event = NULL)
652
+	{
653
+		$event_line_item = EE_Line_Item::new_instance(array(
654
+			'LIN_code' => self::get_event_code($event),
655
+			'LIN_name' => self::get_event_name($event),
656
+			'LIN_desc' => self::get_event_desc($event),
657
+			'LIN_type' => EEM_Line_Item::type_sub_total,
658
+			'OBJ_type' => 'Event',
659
+			'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0
660
+		));
661
+		$event_line_item = apply_filters(
662
+			'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
663
+			$event_line_item
664
+		);
665
+		self::set_TXN_ID($event_line_item, $transaction);
666
+		$pre_tax_line_item->add_child_line_item($event_line_item);
667
+		return $event_line_item;
668
+	}
669
+
670
+
671
+	/**
672
+	 * Gets what the event ticket's code SHOULD be
673
+	 *
674
+	 * @param EE_Event $event
675
+	 * @return string
676
+	 * @throws \EE_Error
677
+	 */
678
+	public static function get_event_code($event)
679
+	{
680
+		return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
681
+	}
682
+
683
+	/**
684
+	 * Gets the event name
685
+	 * @param EE_Event $event
686
+	 * @return string
687
+	 */
688
+	public static function get_event_name($event)
689
+	{
690
+		return $event instanceof EE_Event ? $event->name() : __('Event', 'event_espresso');
691
+	}
692
+
693
+	/**
694
+	 * Gets the event excerpt
695
+	 * @param EE_Event $event
696
+	 * @return string
697
+	 */
698
+	public static function get_event_desc($event)
699
+	{
700
+		return $event instanceof EE_Event ? $event->short_description() : '';
701
+	}
702
+
703
+	/**
704
+	 * Given the grand total line item and a ticket, finds the event sub-total
705
+	 * line item the ticket's purchase should be added onto
706
+	 *
707
+	 * @access public
708
+	 * @param EE_Line_Item $grand_total the grand total line item
709
+	 * @param EE_Ticket $ticket
710
+	 * @throws \EE_Error
711
+	 * @return EE_Line_Item
712
+	 */
713
+	public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
714
+	{
715
+		$first_datetime = $ticket->first_datetime();
716
+		if (!$first_datetime instanceof EE_Datetime) {
717
+			throw new EE_Error(
718
+				sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID())
719
+			);
720
+		}
721
+		$event = $first_datetime->event();
722
+		if (!$event instanceof EE_Event) {
723
+			throw new EE_Error(
724
+				sprintf(
725
+					__('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'),
726
+					$ticket->ID()
727
+				)
728
+			);
729
+		}
730
+		$events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
731
+		if (!$events_sub_total instanceof EE_Line_Item) {
732
+			throw new EE_Error(
733
+				sprintf(
734
+					__('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'),
735
+					$ticket->ID(),
736
+					$grand_total->ID()
737
+				)
738
+			);
739
+		}
740
+		return $events_sub_total;
741
+	}
742
+
743
+
744
+	/**
745
+	 * Gets the event line item
746
+	 *
747
+	 * @param EE_Line_Item $grand_total
748
+	 * @param EE_Event $event
749
+	 * @return EE_Line_Item for the event subtotal which is a child of $grand_total
750
+	 * @throws \EE_Error
751
+	 */
752
+	public static function get_event_line_item(EE_Line_Item $grand_total, $event)
753
+	{
754
+		/** @type EE_Event $event */
755
+		$event = EEM_Event::instance()->ensure_is_obj($event, true);
756
+		$event_line_item = NULL;
757
+		$found = false;
758
+		foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
759
+			// default event subtotal, we should only ever find this the first time this method is called
760
+			if (!$event_line_item->OBJ_ID()) {
761
+				// let's use this! but first... set the event details
762
+				EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
763
+				$found = true;
764
+				break;
765
+			} else if ($event_line_item->OBJ_ID() === $event->ID()) {
766
+				// found existing line item for this event in the cart, so break out of loop and use this one
767
+				$found = true;
768
+				break;
769
+			}
770
+		}
771
+		if (!$found) {
772
+			//there is no event sub-total yet, so add it
773
+			$pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
774
+			// create a new "event" subtotal below that
775
+			$event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
776
+			// and set the event details
777
+			EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
778
+		}
779
+		return $event_line_item;
780
+	}
781
+
782
+
783
+	/**
784
+	 * Creates a default items subtotal line item
785
+	 *
786
+	 * @param EE_Line_Item $event_line_item
787
+	 * @param EE_Event $event
788
+	 * @param EE_Transaction $transaction
789
+	 * @return EE_Line_Item
790
+	 * @throws \EE_Error
791
+	 */
792
+	public static function set_event_subtotal_details(
793
+		EE_Line_Item $event_line_item,
794
+		EE_Event $event,
795
+		$transaction = null
796
+	)
797
+	{
798
+		if ($event instanceof EE_Event) {
799
+			$event_line_item->set_code(self::get_event_code($event));
800
+			$event_line_item->set_name(self::get_event_name($event));
801
+			$event_line_item->set_desc(self::get_event_desc($event));
802
+			$event_line_item->set_OBJ_ID($event->ID());
803
+		}
804
+		self::set_TXN_ID($event_line_item, $transaction);
805
+	}
806
+
807
+
808
+	/**
809
+	 * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
810
+	 * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
811
+	 * any old taxes are removed
812
+	 *
813
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
814
+	 * @throws \EE_Error
815
+	 */
816
+	public static function apply_taxes(EE_Line_Item $total_line_item)
817
+	{
818
+		/** @type EEM_Price $EEM_Price */
819
+		$EEM_Price = EE_Registry::instance()->load_model('Price');
820
+		// get array of taxes via Price Model
821
+		$ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
822
+		ksort($ordered_taxes);
823
+		$taxes_line_item = self::get_taxes_subtotal($total_line_item);
824
+		//just to be safe, remove its old tax line items
825
+		$taxes_line_item->delete_children_line_items();
826
+		//loop thru taxes
827
+		foreach ($ordered_taxes as $order => $taxes) {
828
+			foreach ($taxes as $tax) {
829
+				if ($tax instanceof EE_Price) {
830
+					$tax_line_item = EE_Line_Item::new_instance(
831
+						array(
832
+							'LIN_name' => $tax->name(),
833
+							'LIN_desc' => $tax->desc(),
834
+							'LIN_percent' => $tax->amount(),
835
+							'LIN_is_taxable' => false,
836
+							'LIN_order' => $order,
837
+							'LIN_total' => 0,
838
+							'LIN_type' => EEM_Line_Item::type_tax,
839
+							'OBJ_type' => 'Price',
840
+							'OBJ_ID' => $tax->ID()
841
+						)
842
+					);
843
+					$tax_line_item = apply_filters(
844
+						'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
845
+						$tax_line_item
846
+					);
847
+					$taxes_line_item->add_child_line_item($tax_line_item);
848
+				}
849
+			}
850
+		}
851
+		$total_line_item->recalculate_total_including_taxes();
852
+	}
853
+
854
+
855
+	/**
856
+	 * Ensures that taxes have been applied to the order, if not applies them.
857
+	 * Returns the total amount of tax
858
+	 *
859
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
860
+	 * @return float
861
+	 * @throws \EE_Error
862
+	 */
863
+	public static function ensure_taxes_applied($total_line_item)
864
+	{
865
+		$taxes_subtotal = self::get_taxes_subtotal($total_line_item);
866
+		if (!$taxes_subtotal->children()) {
867
+			self::apply_taxes($total_line_item);
868
+		}
869
+		return $taxes_subtotal->total();
870
+	}
871
+
872
+
873
+	/**
874
+	 * Deletes ALL children of the passed line item
875
+	 *
876
+	 * @param EE_Line_Item $parent_line_item
877
+	 * @return bool
878
+	 * @throws \EE_Error
879
+	 */
880
+	public static function delete_all_child_items(EE_Line_Item $parent_line_item)
881
+	{
882
+		$deleted = 0;
883
+		foreach ($parent_line_item->children() as $child_line_item) {
884
+			if ($child_line_item instanceof EE_Line_Item) {
885
+				$deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
886
+				if ($child_line_item->ID()) {
887
+					$child_line_item->delete();
888
+					unset($child_line_item);
889
+				} else {
890
+					$parent_line_item->delete_child_line_item($child_line_item->code());
891
+				}
892
+				$deleted++;
893
+			}
894
+		}
895
+		return $deleted;
896
+	}
897
+
898
+
899
+	/**
900
+	 * Deletes the line items as indicated by the line item code(s) provided,
901
+	 * regardless of where they're found in the line item tree. Automatically
902
+	 * re-calculates the line item totals and updates the related transaction. But
903
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
904
+	 * should probably change because of this).
905
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
906
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
907
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
908
+	 * @param array|bool|string $line_item_codes
909
+	 * @return int number of items successfully removed
910
+	 */
911
+	public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = FALSE)
912
+	{
913
+
914
+		if ($total_line_item->type() !== EEM_Line_Item::type_total) {
915
+			EE_Error::doing_it_wrong(
916
+				'EEH_Line_Item::delete_items',
917
+				__(
918
+					'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
919
+					'event_espresso'
920
+				),
921
+				'4.6.18'
922
+			);
923
+		}
924
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
925
+
926
+		// check if only a single line_item_id was passed
927
+		if (!empty($line_item_codes) && !is_array($line_item_codes)) {
928
+			// place single line_item_id in an array to appear as multiple line_item_ids
929
+			$line_item_codes = array($line_item_codes);
930
+		}
931
+		$removals = 0;
932
+		// cycle thru line_item_ids
933
+		foreach ($line_item_codes as $line_item_id) {
934
+			$removals += $total_line_item->delete_child_line_item($line_item_id);
935
+		}
936
+
937
+		if ($removals > 0) {
938
+			$total_line_item->recalculate_taxes_and_tax_total();
939
+			return $removals;
940
+		} else {
941
+			return FALSE;
942
+		}
943
+	}
944
+
945
+
946
+	/**
947
+	 * Overwrites the previous tax by clearing out the old taxes, and creates a new
948
+	 * tax and updates the total line item accordingly
949
+	 *
950
+	 * @param EE_Line_Item $total_line_item
951
+	 * @param float $amount
952
+	 * @param string $name
953
+	 * @param string $description
954
+	 * @param string $code
955
+	 * @param boolean $add_to_existing_line_item
956
+	 *                          if true, and a duplicate line item with the same code is found,
957
+	 *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
958
+	 * @return EE_Line_Item the new tax line item created
959
+	 * @throws \EE_Error
960
+	 */
961
+	public static function set_total_tax_to(
962
+		EE_Line_Item $total_line_item,
963
+		$amount,
964
+		$name = null,
965
+		$description = null,
966
+		$code = null,
967
+		$add_to_existing_line_item = false
968
+	)
969
+	{
970
+		$tax_subtotal = self::get_taxes_subtotal($total_line_item);
971
+		$taxable_total = $total_line_item->taxable_total();
972
+
973
+		if ($add_to_existing_line_item) {
974
+			$new_tax = $tax_subtotal->get_child_line_item($code);
975
+			EEM_Line_Item::instance()->delete(
976
+				array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
977
+			);
978
+		} else {
979
+			$new_tax = null;
980
+			$tax_subtotal->delete_children_line_items();
981
+		}
982
+		if ($new_tax) {
983
+			$new_tax->set_total($new_tax->total() + $amount);
984
+			$new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
985
+		} else {
986
+			//no existing tax item. Create it
987
+			$new_tax = EE_Line_Item::new_instance(array(
988
+				'TXN_ID' => $total_line_item->TXN_ID(),
989
+				'LIN_name' => $name ? $name : __('Tax', 'event_espresso'),
990
+				'LIN_desc' => $description ? $description : '',
991
+				'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
992
+				'LIN_total' => $amount,
993
+				'LIN_parent' => $tax_subtotal->ID(),
994
+				'LIN_type' => EEM_Line_Item::type_tax,
995
+				'LIN_code' => $code
996
+			));
997
+		}
998
+
999
+		$new_tax = apply_filters(
1000
+			'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1001
+			$new_tax,
1002
+			$total_line_item
1003
+		);
1004
+		$new_tax->save();
1005
+		$tax_subtotal->set_total($new_tax->total());
1006
+		$tax_subtotal->save();
1007
+		$total_line_item->recalculate_total_including_taxes();
1008
+		return $new_tax;
1009
+	}
1010
+
1011
+
1012
+	/**
1013
+	 * Makes all the line items which are children of $line_item taxable (or not).
1014
+	 * Does NOT save the line items
1015
+	 * @param EE_Line_Item $line_item
1016
+	 * @param string $code_substring_for_whitelist if this string is part of the line item's code
1017
+	 *  it will be whitelisted (ie, except from becoming taxable)
1018
+	 * @param boolean $taxable
1019
+	 */
1020
+	public static function set_line_items_taxable(
1021
+		EE_Line_Item $line_item,
1022
+		$taxable = true,
1023
+		$code_substring_for_whitelist = null
1024
+	)
1025
+	{
1026
+		$whitelisted = false;
1027
+		if ($code_substring_for_whitelist !== null) {
1028
+			$whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false;
1029
+		}
1030
+		if (!$whitelisted && $line_item->is_line_item()) {
1031
+			$line_item->set_is_taxable($taxable);
1032
+		}
1033
+		foreach ($line_item->children() as $child_line_item) {
1034
+			EEH_Line_Item::set_line_items_taxable($child_line_item, $taxable, $code_substring_for_whitelist);
1035
+		}
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * Gets all descendants that are event subtotals
1041
+	 *
1042
+	 * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1043
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1044
+	 * @return EE_Line_Item[]
1045
+	 */
1046
+	public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1047
+	{
1048
+		return self::get_subtotals_of_object_type($parent_line_item, 'Event');
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * Gets all descendants subtotals that match the supplied object type
1054
+	 *
1055
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1056
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1057
+	 * @param string $obj_type
1058
+	 * @return EE_Line_Item[]
1059
+	 */
1060
+	public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1061
+	{
1062
+		return self::_get_descendants_by_type_and_object_type(
1063
+			$parent_line_item,
1064
+			EEM_Line_Item::type_sub_total,
1065
+			$obj_type
1066
+		);
1067
+	}
1068
+
1069
+
1070
+	/**
1071
+	 * Gets all descendants that are tickets
1072
+	 *
1073
+	 * @uses  EEH_Line_Item::get_line_items_of_object_type()
1074
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1075
+	 * @return EE_Line_Item[]
1076
+	 */
1077
+	public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1078
+	{
1079
+		return self::get_line_items_of_object_type($parent_line_item, 'Ticket');
1080
+	}
1081
+
1082
+
1083
+	/**
1084
+	 * Gets all descendants subtotals that match the supplied object type
1085
+	 *
1086
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1087
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1088
+	 * @param string $obj_type
1089
+	 * @return EE_Line_Item[]
1090
+	 */
1091
+	public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1092
+	{
1093
+		return self::_get_descendants_by_type_and_object_type($parent_line_item, EEM_Line_Item::type_line_item, $obj_type);
1094
+	}
1095
+
1096
+
1097
+	/**
1098
+	 * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1099
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1100
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1101
+	 * @return EE_Line_Item[]
1102
+	 */
1103
+	public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1104
+	{
1105
+		return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_tax);
1106
+	}
1107
+
1108
+
1109
+	/**
1110
+	 * Gets all the real items purchased which are children of this item
1111
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1112
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1113
+	 * @return EE_Line_Item[]
1114
+	 */
1115
+	public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1116
+	{
1117
+		return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_line_item);
1118
+	}
1119
+
1120
+
1121
+	/**
1122
+	 * Gets all descendants of supplied line item that match the supplied line item type
1123
+	 *
1124
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1125
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1126
+	 * @param string $line_item_type one of the EEM_Line_Item constants
1127
+	 * @return EE_Line_Item[]
1128
+	 */
1129
+	public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1130
+	{
1131
+		return self::_get_descendants_by_type_and_object_type($parent_line_item, $line_item_type, NULL);
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1137
+	 *
1138
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1139
+	 * @param string $line_item_type one of the EEM_Line_Item constants
1140
+	 * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when searching
1141
+	 * @return EE_Line_Item[]
1142
+	 */
1143
+	protected static function _get_descendants_by_type_and_object_type(
1144
+		EE_Line_Item $parent_line_item,
1145
+		$line_item_type,
1146
+		$obj_type = null
1147
+	)
1148
+	{
1149
+		$objects = array();
1150
+		foreach ($parent_line_item->children() as $child_line_item) {
1151
+			if ($child_line_item instanceof EE_Line_Item) {
1152
+				if (
1153
+					$child_line_item->type() === $line_item_type
1154
+					&& (
1155
+						$child_line_item->OBJ_type() === $obj_type || $obj_type === null
1156
+					)
1157
+				) {
1158
+					$objects[] = $child_line_item;
1159
+				} else {
1160
+					//go-through-all-its children looking for more matches
1161
+					$objects = array_merge(
1162
+						$objects,
1163
+						self::_get_descendants_by_type_and_object_type(
1164
+							$child_line_item,
1165
+							$line_item_type,
1166
+							$obj_type
1167
+						)
1168
+					);
1169
+				}
1170
+			}
1171
+		}
1172
+		return $objects;
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * Gets all descendants subtotals that match the supplied object type
1178
+	 *
1179
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1180
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1181
+	 * @param string $OBJ_type object type (like Event)
1182
+	 * @param array $OBJ_IDs array of OBJ_IDs
1183
+	 * @return EE_Line_Item[]
1184
+	 */
1185
+	public static function get_line_items_by_object_type_and_IDs(
1186
+		EE_Line_Item $parent_line_item,
1187
+		$OBJ_type = '',
1188
+		$OBJ_IDs = array()
1189
+	)
1190
+	{
1191
+		return self::_get_descendants_by_object_type_and_object_ID($parent_line_item, $OBJ_type, $OBJ_IDs);
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1197
+	 *
1198
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1199
+	 * @param string $OBJ_type object type (like Event)
1200
+	 * @param array $OBJ_IDs array of OBJ_IDs
1201
+	 * @return EE_Line_Item[]
1202
+	 */
1203
+	protected static function _get_descendants_by_object_type_and_object_ID(
1204
+		EE_Line_Item $parent_line_item,
1205
+		$OBJ_type,
1206
+		$OBJ_IDs
1207
+	)
1208
+	{
1209
+		$objects = array();
1210
+		foreach ($parent_line_item->children() as $child_line_item) {
1211
+			if ($child_line_item instanceof EE_Line_Item) {
1212
+				if (
1213
+					$child_line_item->OBJ_type() === $OBJ_type
1214
+					&& is_array($OBJ_IDs)
1215
+					&& in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1216
+				) {
1217
+					$objects[] = $child_line_item;
1218
+				} else {
1219
+					//go-through-all-its children looking for more matches
1220
+					$objects = array_merge(
1221
+						$objects,
1222
+						self::_get_descendants_by_object_type_and_object_ID(
1223
+							$child_line_item,
1224
+							$OBJ_type,
1225
+							$OBJ_IDs
1226
+						)
1227
+					);
1228
+				}
1229
+			}
1230
+		}
1231
+		return $objects;
1232
+	}
1233
+
1234
+
1235
+	/**
1236
+	 * Uses a breadth-first-search in order to find the nearest descendant of
1237
+	 * the specified type and returns it, else NULL
1238
+	 *
1239
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1240
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1241
+	 * @param string $type like one of the EEM_Line_Item::type_*
1242
+	 * @return EE_Line_Item
1243
+	 */
1244
+	public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1245
+	{
1246
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1247
+	}
1248
+
1249
+
1250
+	/**
1251
+	 * Uses a breadth-first-search in order to find the nearest descendant
1252
+	 * having the specified LIN_code and returns it, else NULL
1253
+	 *
1254
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1255
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1256
+	 * @param string $code any value used for LIN_code
1257
+	 * @return EE_Line_Item
1258
+	 */
1259
+	public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1260
+	{
1261
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1262
+	}
1263
+
1264
+
1265
+	/**
1266
+	 * Uses a breadth-first-search in order to find the nearest descendant
1267
+	 * having the specified LIN_code and returns it, else NULL
1268
+	 *
1269
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1270
+	 * @param string $search_field name of EE_Line_Item property
1271
+	 * @param string $value any value stored in $search_field
1272
+	 * @return EE_Line_Item
1273
+	 */
1274
+	protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1275
+	{
1276
+		foreach ($parent_line_item->children() as $child) {
1277
+			if ($child->get($search_field) == $value) {
1278
+				return $child;
1279
+			}
1280
+		}
1281
+		foreach ($parent_line_item->children() as $child) {
1282
+			$descendant_found = self::_get_nearest_descendant($child, $search_field, $value);
1283
+			if ($descendant_found) {
1284
+				return $descendant_found;
1285
+			}
1286
+		}
1287
+		return NULL;
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1293
+	 * else recursively walks up the line item tree until a parent of type total is found,
1294
+	 *
1295
+	 * @param EE_Line_Item $line_item
1296
+	 * @return \EE_Line_Item
1297
+	 * @throws \EE_Error
1298
+	 */
1299
+	public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1300
+	{
1301
+		if ($line_item->TXN_ID()) {
1302
+			$total_line_item = $line_item->transaction()->total_line_item(false);
1303
+			if ($total_line_item instanceof EE_Line_Item) {
1304
+				return $total_line_item;
1305
+			}
1306
+		} else {
1307
+			$line_item_parent = $line_item->parent();
1308
+			if ($line_item_parent instanceof EE_Line_Item) {
1309
+				if ($line_item_parent->is_total()) {
1310
+					return $line_item_parent;
1311
+				}
1312
+				return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1313
+			}
1314
+		}
1315
+		throw new EE_Error(
1316
+			sprintf(
1317
+				__('A valid grand total for line item %1$d was not found.', 'event_espresso'),
1318
+				$line_item->ID()
1319
+			)
1320
+		);
1321
+	}
1322
+
1323
+
1324
+	/**
1325
+	 * Prints out a representation of the line item tree
1326
+	 *
1327
+	 * @param EE_Line_Item $line_item
1328
+	 * @param int $indentation
1329
+	 * @return void
1330
+	 * @throws \EE_Error
1331
+	 */
1332
+	public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1333
+	{
1334
+		echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1335
+		if (!$indentation) {
1336
+			echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1337
+		}
1338
+		for ($i = 0; $i < $indentation; $i++) {
1339
+			echo ". ";
1340
+		}
1341
+		$breakdown = '';
1342
+		if ($line_item->is_line_item()) {
1343
+			if ($line_item->is_percent()) {
1344
+				$breakdown = "{$line_item->percent()}%";
1345
+			} else {
1346
+				$breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1347
+			}
1348
+		}
1349
+		echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}";
1350
+		if ($breakdown) {
1351
+			echo " ( {$breakdown} )";
1352
+		}
1353
+		if ($line_item->is_taxable()) {
1354
+			echo "  * taxable";
1355
+		}
1356
+		if ($line_item->children()) {
1357
+			foreach ($line_item->children() as $child) {
1358
+				self::visualize($child, $indentation + 1);
1359
+			}
1360
+		}
1361
+	}
1362
+
1363
+
1364
+	/**
1365
+	 * Calculates the registration's final price, taking into account that they
1366
+	 * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1367
+	 * and receive a portion of any transaction-wide discounts.
1368
+	 * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1369
+	 * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1370
+	 * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1371
+	 * and brent's final price should be $5.50.
1372
+	 *
1373
+	 * In order to do this, we basically need to traverse the line item tree calculating
1374
+	 * the running totals (just as if we were recalculating the total), but when we identify
1375
+	 * regular line items, we need to keep track of their share of the grand total.
1376
+	 * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1377
+	 * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1378
+	 * when there are non-taxable items; otherwise they would be the same)
1379
+	 *
1380
+	 * @param EE_Line_Item $line_item
1381
+	 * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that
1382
+	 *                                                                            can be included in price calculations at this moment
1383
+	 * @return array        keys are line items for tickets IDs and values are their share of the running total,
1384
+	 *                                          plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg
1385
+	 *                                          array(
1386
+	 *                                          12 => 4.3
1387
+	 *                                          23 => 8.0
1388
+	 *                                          'total' => 16.6,
1389
+	 *                                          'taxable' => array(
1390
+	 *                                          12 => 10,
1391
+	 *                                          23 => 4
1392
+	 *                                          ).
1393
+	 *                                          So to find which registrations have which final price, we need to find which line item
1394
+	 *                                          is theirs, which can be done with
1395
+	 *                                          `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );`
1396
+	 */
1397
+	public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array())
1398
+	{
1399
+		//init running grand total if not already
1400
+		if (!isset($running_totals['total'])) {
1401
+			$running_totals['total'] = 0;
1402
+		}
1403
+		if (!isset($running_totals['taxable'])) {
1404
+			$running_totals['taxable'] = array('total' => 0);
1405
+		}
1406
+		foreach ($line_item->children() as $child_line_item) {
1407
+			switch ($child_line_item->type()) {
1408
+
1409
+				case EEM_Line_Item::type_sub_total :
1410
+					$running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities);
1411
+					//combine arrays but preserve numeric keys
1412
+					$running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1413
+					$running_totals['total'] += $running_totals_from_subtotal['total'];
1414
+					$running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1415
+					break;
1416
+
1417
+				case EEM_Line_Item::type_tax_sub_total :
1418
+
1419
+					//find how much the taxes percentage is
1420
+					if ($child_line_item->percent() !== 0) {
1421
+						$tax_percent_decimal = $child_line_item->percent() / 100;
1422
+					} else {
1423
+						$tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1424
+					}
1425
+					//and apply to all the taxable totals, and add to the pretax totals
1426
+					foreach ($running_totals as $line_item_id => $this_running_total) {
1427
+						//"total" and "taxable" array key is an exception
1428
+						if ($line_item_id === 'taxable') {
1429
+							continue;
1430
+						}
1431
+						$taxable_total = $running_totals['taxable'][$line_item_id];
1432
+						$running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal);
1433
+					}
1434
+					break;
1435
+
1436
+				case EEM_Line_Item::type_line_item :
1437
+
1438
+					// ticket line items or ????
1439
+					if ($child_line_item->OBJ_type() === 'Ticket') {
1440
+						// kk it's a ticket
1441
+						if (isset($running_totals[$child_line_item->ID()])) {
1442
+							//huh? that shouldn't happen.
1443
+							$running_totals['total'] += $child_line_item->total();
1444
+						} else {
1445
+							//its not in our running totals yet. great.
1446
+							if ($child_line_item->is_taxable()) {
1447
+								$taxable_amount = $child_line_item->unit_price();
1448
+							} else {
1449
+								$taxable_amount = 0;
1450
+							}
1451
+							// are we only calculating totals for some tickets?
1452
+							if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) {
1453
+								$quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()];
1454
+								$running_totals[$child_line_item->ID()] = $quantity
1455
+									? $child_line_item->unit_price()
1456
+									: 0;
1457
+								$running_totals['taxable'][$child_line_item->ID()] = $quantity
1458
+									? $taxable_amount
1459
+									: 0;
1460
+							} else {
1461
+								$quantity = $child_line_item->quantity();
1462
+								$running_totals[$child_line_item->ID()] = $child_line_item->unit_price();
1463
+								$running_totals['taxable'][$child_line_item->ID()] = $taxable_amount;
1464
+							}
1465
+							$running_totals['taxable']['total'] += $taxable_amount * $quantity;
1466
+							$running_totals['total'] += $child_line_item->unit_price() * $quantity;
1467
+						}
1468
+					} else {
1469
+						// it's some other type of item added to the cart
1470
+						// it should affect the running totals
1471
+						// basically we want to convert it into a PERCENT modifier. Because
1472
+						// more clearly affect all registration's final price equally
1473
+						$line_items_percent_of_running_total = $running_totals['total'] > 0
1474
+							? ($child_line_item->total() / $running_totals['total']) + 1
1475
+							: 1;
1476
+						foreach ($running_totals as $line_item_id => $this_running_total) {
1477
+							//the "taxable" array key is an exception
1478
+							if ($line_item_id === 'taxable') {
1479
+								continue;
1480
+							}
1481
+							// update the running totals
1482
+							// yes this actually even works for the running grand total!
1483
+							$running_totals[$line_item_id] =
1484
+								$line_items_percent_of_running_total * $this_running_total;
1485
+
1486
+							if ($child_line_item->is_taxable()) {
1487
+								$running_totals['taxable'][$line_item_id] =
1488
+									$line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id];
1489
+							}
1490
+						}
1491
+					}
1492
+					break;
1493
+			}
1494
+		}
1495
+		return $running_totals;
1496
+	}
1497
+
1498
+
1499
+	/**
1500
+	 * @param \EE_Line_Item $total_line_item
1501
+	 * @param \EE_Line_Item $ticket_line_item
1502
+	 * @return float | null
1503
+	 * @throws \OutOfRangeException
1504
+	 */
1505
+	public static function calculate_final_price_for_ticket_line_item(\EE_Line_Item $total_line_item, \EE_Line_Item $ticket_line_item)
1506
+	{
1507
+		static $final_prices_per_ticket_line_item = array();
1508
+		if (empty($final_prices_per_ticket_line_item)) {
1509
+			$final_prices_per_ticket_line_item = \EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1510
+				$total_line_item
1511
+			);
1512
+		}
1513
+		//ok now find this new registration's final price
1514
+		if (isset($final_prices_per_ticket_line_item[$ticket_line_item->ID()])) {
1515
+			return $final_prices_per_ticket_line_item[$ticket_line_item->ID()];
1516
+		}
1517
+		$message = sprintf(
1518
+			__(
1519
+				'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1520
+				'event_espresso'
1521
+			),
1522
+			$ticket_line_item->ID()
1523
+		);
1524
+		if (WP_DEBUG) {
1525
+			$message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1526
+			throw new \OutOfRangeException($message);
1527
+		} else {
1528
+			EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1529
+		}
1530
+		return null;
1531
+	}
1532
+
1533
+
1534
+	/**
1535
+	 * Creates a duplicate of the line item tree, except only includes billable items
1536
+	 * and the portion of line items attributed to billable things
1537
+	 *
1538
+	 * @param EE_Line_Item $line_item
1539
+	 * @param EE_Registration[] $registrations
1540
+	 * @return \EE_Line_Item
1541
+	 * @throws \EE_Error
1542
+	 */
1543
+	public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1544
+	{
1545
+		$copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1546
+		foreach ($line_item->children() as $child_li) {
1547
+			$copy_li->add_child_line_item(EEH_Line_Item::billable_line_item_tree($child_li, $registrations));
1548
+		}
1549
+		//if this is the grand total line item, make sure the totals all add up
1550
+		//(we could have duplicated this logic AS we copied the line items, but
1551
+		//it seems DRYer this way)
1552
+		if ($copy_li->type() === EEM_Line_Item::type_total) {
1553
+			$copy_li->recalculate_total_including_taxes();
1554
+		}
1555
+		return $copy_li;
1556
+	}
1557
+
1558
+
1559
+	/**
1560
+	 * Creates a new, unsaved line item from $line_item that factors in the
1561
+	 * number of billable registrations on $registrations.
1562
+	 *
1563
+	 * @param EE_Line_Item $line_item
1564
+	 * @return EE_Line_Item
1565
+	 * @throws \EE_Error
1566
+	 * @param EE_Registration[] $registrations
1567
+	 */
1568
+	public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1569
+	{
1570
+		$new_li_fields = $line_item->model_field_array();
1571
+		if ($line_item->type() === EEM_Line_Item::type_line_item &&
1572
+			$line_item->OBJ_type() === 'Ticket'
1573
+		) {
1574
+			$count = 0;
1575
+			foreach ($registrations as $registration) {
1576
+				if ($line_item->OBJ_ID() === $registration->ticket_ID() &&
1577
+					in_array($registration->status_ID(), EEM_Registration::reg_statuses_that_allow_payment())
1578
+				) {
1579
+					$count++;
1580
+				}
1581
+			}
1582
+			$new_li_fields['LIN_quantity'] = $count;
1583
+		}
1584
+		//don't set the total. We'll leave that up to the code that calculates it
1585
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1586
+		return EE_Line_Item::new_instance($new_li_fields);
1587
+	}
1588
+
1589
+
1590
+	/**
1591
+	 * Returns a modified line item tree where all the subtotals which have a total of 0
1592
+	 * are removed, and line items with a quantity of 0
1593
+	 *
1594
+	 * @param EE_Line_Item $line_item |null
1595
+	 * @return \EE_Line_Item|null
1596
+	 * @throws \EE_Error
1597
+	 */
1598
+	public static function non_empty_line_items(EE_Line_Item $line_item)
1599
+	{
1600
+		$copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1601
+		if ($copied_li === null) {
1602
+			return null;
1603
+		}
1604
+		//if this is an event subtotal, we want to only include it if it
1605
+		//has a non-zero total and at least one ticket line item child
1606
+		$ticket_children = 0;
1607
+		foreach ($line_item->children() as $child_li) {
1608
+			$child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1609
+			if ($child_li_copy !== null) {
1610
+				$copied_li->add_child_line_item($child_li_copy);
1611
+				if ($child_li_copy->type() === EEM_Line_Item::type_line_item &&
1612
+					$child_li_copy->OBJ_type() === 'Ticket'
1613
+				) {
1614
+					$ticket_children++;
1615
+				}
1616
+			}
1617
+		}
1618
+		//if this is an event subtotal with NO ticket children
1619
+		//we basically want to ignore it
1620
+		if (
1621
+			$ticket_children === 0
1622
+			&& $line_item->type() === EEM_Line_Item::type_sub_total
1623
+			&& $line_item->OBJ_type() === 'Event'
1624
+			&& $line_item->total() === 0
1625
+		) {
1626
+			return null;
1627
+		}
1628
+		return $copied_li;
1629
+	}
1630
+
1631
+
1632
+	/**
1633
+	 * Creates a new, unsaved line item, but if it's a ticket line item
1634
+	 * with a total of 0, or a subtotal of 0, returns null instead
1635
+	 *
1636
+	 * @param EE_Line_Item $line_item
1637
+	 * @return EE_Line_Item
1638
+	 * @throws \EE_Error
1639
+	 */
1640
+	public static function non_empty_line_item(EE_Line_Item $line_item)
1641
+	{
1642
+		if ($line_item->type() === EEM_Line_Item::type_line_item &&
1643
+			$line_item->OBJ_type() === 'Ticket' &&
1644
+			$line_item->quantity() === 0
1645
+		) {
1646
+			return null;
1647
+		}
1648
+		$new_li_fields = $line_item->model_field_array();
1649
+		//don't set the total. We'll leave that up to the code that calculates it
1650
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1651
+		return EE_Line_Item::new_instance($new_li_fields);
1652
+	}
1653
+
1654
+
1655
+
1656
+	/**************************************** @DEPRECATED METHODS *************************************** */
1657
+	/**
1658
+	 * @deprecated
1659
+	 * @param EE_Line_Item $total_line_item
1660
+	 * @return \EE_Line_Item
1661
+	 * @throws \EE_Error
1662
+	 */
1663
+	public static function get_items_subtotal(EE_Line_Item $total_line_item)
1664
+	{
1665
+		EE_Error::doing_it_wrong('EEH_Line_Item::get_items_subtotal()', __('Method replaced with EEH_Line_Item::get_pre_tax_subtotal()', 'event_espresso'), '4.6.0');
1666
+		return self::get_pre_tax_subtotal($total_line_item);
1667
+	}
1668
+
1669
+
1670
+	/**
1671
+	 * @deprecated
1672
+	 * @param EE_Transaction $transaction
1673
+	 * @return \EE_Line_Item
1674
+	 * @throws \EE_Error
1675
+	 */
1676
+	public static function create_default_total_line_item($transaction = NULL)
1677
+	{
1678
+		EE_Error::doing_it_wrong('EEH_Line_Item::create_default_total_line_item()', __('Method replaced with EEH_Line_Item::create_total_line_item()', 'event_espresso'), '4.6.0');
1679
+		return self::create_total_line_item($transaction);
1680
+	}
1681
+
1682
+
1683
+	/**
1684
+	 * @deprecated
1685
+	 * @param EE_Line_Item $total_line_item
1686
+	 * @param EE_Transaction $transaction
1687
+	 * @return \EE_Line_Item
1688
+	 * @throws \EE_Error
1689
+	 */
1690
+	public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
1691
+	{
1692
+		EE_Error::doing_it_wrong('EEH_Line_Item::create_default_tickets_subtotal()', __('Method replaced with EEH_Line_Item::create_pre_tax_subtotal()', 'event_espresso'), '4.6.0');
1693
+		return self::create_pre_tax_subtotal($total_line_item, $transaction);
1694
+	}
1695
+
1696
+
1697
+	/**
1698
+	 * @deprecated
1699
+	 * @param EE_Line_Item $total_line_item
1700
+	 * @param EE_Transaction $transaction
1701
+	 * @return \EE_Line_Item
1702
+	 * @throws \EE_Error
1703
+	 */
1704
+	public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
1705
+	{
1706
+		EE_Error::doing_it_wrong('EEH_Line_Item::create_default_taxes_subtotal()', __('Method replaced with EEH_Line_Item::create_taxes_subtotal()', 'event_espresso'), '4.6.0');
1707
+		return self::create_taxes_subtotal($total_line_item, $transaction);
1708
+	}
1709
+
1710
+
1711
+	/**
1712
+	 * @deprecated
1713
+	 * @param EE_Line_Item $total_line_item
1714
+	 * @param EE_Transaction $transaction
1715
+	 * @return \EE_Line_Item
1716
+	 * @throws \EE_Error
1717
+	 */
1718
+	public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = NULL)
1719
+	{
1720
+		EE_Error::doing_it_wrong('EEH_Line_Item::create_default_event_subtotal()', __('Method replaced with EEH_Line_Item::create_event_subtotal()', 'event_espresso'), '4.6.0');
1721
+		return self::create_event_subtotal($total_line_item, $transaction);
1722
+	}
1723 1723
 
1724 1724
 
1725 1725
 }
Please login to merge, or discard this patch.
Spacing   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (!defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
             'LIN_percent' => null,
57 57
             'LIN_is_taxable' => $taxable,
58 58
             'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
59
-            'LIN_total' => (float)$unit_price * (int)$quantity,
59
+            'LIN_total' => (float) $unit_price * (int) $quantity,
60 60
             'LIN_type' => EEM_Line_Item::type_line_item,
61 61
             'LIN_code' => $code,
62 62
         ));
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
             'LIN_percent' => $percentage_amount,
96 96
             'LIN_quantity' => 1,
97 97
             'LIN_is_taxable' => $taxable,
98
-            'LIN_total' => (float)($percentage_amount * ($parent_line_item->total() / 100)),
98
+            'LIN_total' => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
99 99
             'LIN_type' => EEM_Line_Item::type_line_item,
100 100
             'LIN_parent' => $parent_line_item->ID()
101 101
         ));
@@ -125,13 +125,13 @@  discard block
 block discarded – undo
125 125
      */
126 126
     public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
127 127
     {
128
-        if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) {
128
+        if ( ! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
129 129
             throw new EE_Error(sprintf(__('A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', 'event_espresso'), $ticket->ID(), $total_line_item->ID()));
130 130
         }
131 131
         // either increment the qty for an existing ticket
132 132
         $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
133 133
         // or add a new one
134
-        if (!$line_item instanceof EE_Line_Item) {
134
+        if ( ! $line_item instanceof EE_Line_Item) {
135 135
             $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
136 136
         }
137 137
         $total_line_item->recalculate_total_including_taxes();
@@ -152,10 +152,10 @@  discard block
 block discarded – undo
152 152
         $line_item = null;
153 153
         if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
154 154
             $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
155
-            foreach ((array)$ticket_line_items as $ticket_line_item) {
155
+            foreach ((array) $ticket_line_items as $ticket_line_item) {
156 156
                 if (
157 157
                     $ticket_line_item instanceof EE_Line_Item
158
-                    && (int)$ticket_line_item->OBJ_ID() === (int)$ticket->ID()
158
+                    && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
159 159
                 ) {
160 160
                     $line_item = $ticket_line_item;
161 161
                     break;
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
      */
182 182
     public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
183 183
     {
184
-        if (!$line_item->is_percent()) {
184
+        if ( ! $line_item->is_percent()) {
185 185
             $qty += $line_item->quantity();
186 186
             $line_item->set_quantity($qty);
187 187
             $line_item->set_total($line_item->unit_price() * $qty);
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
      */
207 207
     public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
208 208
     {
209
-        if (!$line_item->is_percent()) {
209
+        if ( ! $line_item->is_percent()) {
210 210
             $qty = $line_item->quantity() - $qty;
211 211
             $qty = max($qty, 0);
212 212
             $line_item->set_quantity($qty);
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
      */
232 232
     public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
233 233
     {
234
-        if (!$line_item->is_percent()) {
234
+        if ( ! $line_item->is_percent()) {
235 235
             $line_item->set_quantity($new_quantity);
236 236
             $line_item->set_total($line_item->unit_price() * $new_quantity);
237 237
             $line_item->save();
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
         // add $ticket to cart
268 268
         $line_item = EE_Line_Item::new_instance(array(
269 269
             'LIN_name' => $ticket->name(),
270
-            'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
270
+            'LIN_desc' => $ticket->description() !== '' ? $ticket->description().' '.$event : $event,
271 271
             'LIN_unit_price' => $ticket->price(),
272 272
             'LIN_quantity' => $qty,
273 273
             'LIN_is_taxable' => $ticket->taxable(),
@@ -377,8 +377,8 @@  discard block
 block discarded – undo
377 377
         foreach ($ticket_line_item->children() as $child_line_item) {
378 378
             if (
379 379
                 $child_line_item->is_sub_line_item()
380
-                && !$child_line_item->is_percent()
381
-                && !$child_line_item->is_cancellation()
380
+                && ! $child_line_item->is_percent()
381
+                && ! $child_line_item->is_cancellation()
382 382
             ) {
383 383
                 $child_line_item->set_quantity($child_line_item->quantity() - $qty);
384 384
             }
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
                 'LIN_desc' => sprintf(
401 401
                     _x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'),
402 402
                     $ticket_line_item->name(),
403
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
403
+                    current_time(get_option('date_format').' '.get_option('time_format'))
404 404
                 ),
405 405
                 'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
406 406
                 'LIN_quantity' => $qty,
@@ -453,7 +453,7 @@  discard block
 block discarded – undo
453 453
         );
454 454
         $cancellation_line_item = reset($cancellation_line_item);
455 455
         // verify that this ticket was indeed previously cancelled
456
-        if (!$cancellation_line_item instanceof EE_Line_Item) {
456
+        if ( ! $cancellation_line_item instanceof EE_Line_Item) {
457 457
             return false;
458 458
         }
459 459
         if ($cancellation_line_item->quantity() > $qty) {
@@ -625,7 +625,7 @@  discard block
 block discarded – undo
625 625
             'LIN_code' => 'taxes',
626 626
             'LIN_name' => __('Taxes', 'event_espresso'),
627 627
             'LIN_type' => EEM_Line_Item::type_tax_sub_total,
628
-            'LIN_order' => 1000,//this should always come last
628
+            'LIN_order' => 1000, //this should always come last
629 629
         ));
630 630
         $tax_line_item = apply_filters(
631 631
             'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
      */
678 678
     public static function get_event_code($event)
679 679
     {
680
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
680
+        return 'event-'.($event instanceof EE_Event ? $event->ID() : '0');
681 681
     }
682 682
 
683 683
     /**
@@ -713,13 +713,13 @@  discard block
 block discarded – undo
713 713
     public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
714 714
     {
715 715
         $first_datetime = $ticket->first_datetime();
716
-        if (!$first_datetime instanceof EE_Datetime) {
716
+        if ( ! $first_datetime instanceof EE_Datetime) {
717 717
             throw new EE_Error(
718 718
                 sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID())
719 719
             );
720 720
         }
721 721
         $event = $first_datetime->event();
722
-        if (!$event instanceof EE_Event) {
722
+        if ( ! $event instanceof EE_Event) {
723 723
             throw new EE_Error(
724 724
                 sprintf(
725 725
                     __('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'),
@@ -728,7 +728,7 @@  discard block
 block discarded – undo
728 728
             );
729 729
         }
730 730
         $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
731
-        if (!$events_sub_total instanceof EE_Line_Item) {
731
+        if ( ! $events_sub_total instanceof EE_Line_Item) {
732 732
             throw new EE_Error(
733 733
                 sprintf(
734 734
                     __('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'),
@@ -757,7 +757,7 @@  discard block
 block discarded – undo
757 757
         $found = false;
758 758
         foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
759 759
             // default event subtotal, we should only ever find this the first time this method is called
760
-            if (!$event_line_item->OBJ_ID()) {
760
+            if ( ! $event_line_item->OBJ_ID()) {
761 761
                 // let's use this! but first... set the event details
762 762
                 EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
763 763
                 $found = true;
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
                 break;
769 769
             }
770 770
         }
771
-        if (!$found) {
771
+        if ( ! $found) {
772 772
             //there is no event sub-total yet, so add it
773 773
             $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
774 774
             // create a new "event" subtotal below that
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
     public static function ensure_taxes_applied($total_line_item)
864 864
     {
865 865
         $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
866
-        if (!$taxes_subtotal->children()) {
866
+        if ( ! $taxes_subtotal->children()) {
867 867
             self::apply_taxes($total_line_item);
868 868
         }
869 869
         return $taxes_subtotal->total();
@@ -924,7 +924,7 @@  discard block
 block discarded – undo
924 924
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
925 925
 
926 926
         // check if only a single line_item_id was passed
927
-        if (!empty($line_item_codes) && !is_array($line_item_codes)) {
927
+        if ( ! empty($line_item_codes) && ! is_array($line_item_codes)) {
928 928
             // place single line_item_id in an array to appear as multiple line_item_ids
929 929
             $line_item_codes = array($line_item_codes);
930 930
         }
@@ -1027,7 +1027,7 @@  discard block
 block discarded – undo
1027 1027
         if ($code_substring_for_whitelist !== null) {
1028 1028
             $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false;
1029 1029
         }
1030
-        if (!$whitelisted && $line_item->is_line_item()) {
1030
+        if ( ! $whitelisted && $line_item->is_line_item()) {
1031 1031
             $line_item->set_is_taxable($taxable);
1032 1032
         }
1033 1033
         foreach ($line_item->children() as $child_line_item) {
@@ -1332,7 +1332,7 @@  discard block
 block discarded – undo
1332 1332
     public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1333 1333
     {
1334 1334
         echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1335
-        if (!$indentation) {
1335
+        if ( ! $indentation) {
1336 1336
             echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1337 1337
         }
1338 1338
         for ($i = 0; $i < $indentation; $i++) {
@@ -1343,10 +1343,10 @@  discard block
 block discarded – undo
1343 1343
             if ($line_item->is_percent()) {
1344 1344
                 $breakdown = "{$line_item->percent()}%";
1345 1345
             } else {
1346
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1346
+                $breakdown = '$'."{$line_item->unit_price()} x {$line_item->quantity()}";
1347 1347
             }
1348 1348
         }
1349
-        echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}";
1349
+        echo $line_item->name()." [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ".'$'."{$line_item->total()}";
1350 1350
         if ($breakdown) {
1351 1351
             echo " ( {$breakdown} )";
1352 1352
         }
@@ -1397,10 +1397,10 @@  discard block
 block discarded – undo
1397 1397
     public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array())
1398 1398
     {
1399 1399
         //init running grand total if not already
1400
-        if (!isset($running_totals['total'])) {
1400
+        if ( ! isset($running_totals['total'])) {
1401 1401
             $running_totals['total'] = 0;
1402 1402
         }
1403
-        if (!isset($running_totals['taxable'])) {
1403
+        if ( ! isset($running_totals['taxable'])) {
1404 1404
             $running_totals['taxable'] = array('total' => 0);
1405 1405
         }
1406 1406
         foreach ($line_item->children() as $child_line_item) {
@@ -1522,7 +1522,7 @@  discard block
 block discarded – undo
1522 1522
             $ticket_line_item->ID()
1523 1523
         );
1524 1524
         if (WP_DEBUG) {
1525
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1525
+            $message .= '<br>'.print_r($final_prices_per_ticket_line_item, true);
1526 1526
             throw new \OutOfRangeException($message);
1527 1527
         } else {
1528 1528
             EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
Please login to merge, or discard this patch.
core/db_classes/EE_Line_Item.class.php 2 patches
Indentation   +1426 added lines, -1426 removed lines patch added patch discarded remove patch
@@ -17,1432 +17,1432 @@
 block discarded – undo
17 17
 class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item
18 18
 {
19 19
 
20
-    /**
21
-     * for children line items (currently not a normal relation)
22
-     *
23
-     * @type EE_Line_Item[]
24
-     */
25
-    protected $_children = array();
26
-
27
-    /**
28
-     * for the parent line item
29
-     *
30
-     * @var EE_Line_Item
31
-     */
32
-    protected $_parent;
33
-
34
-
35
-    /**
36
-     *
37
-     * @param array $props_n_values incoming values
38
-     * @param string $timezone incoming timezone (if not set the timezone set for the website will be
39
-     *                                        used.)
40
-     * @param array $date_formats incoming date_formats in an array where the first value is the
41
-     *                                        date_format and the second value is the time format
42
-     * @return EE_Line_Item
43
-     * @throws EE_Error
44
-     */
45
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
46
-    {
47
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
48
-        return $has_object
49
-            ? $has_object
50
-            : new self($props_n_values, false, $timezone);
51
-    }
52
-
53
-
54
-    /**
55
-     * @param array $props_n_values incoming values from the database
56
-     * @param string $timezone incoming timezone as set by the model.  If not set the timezone for
57
-     *                                the website will be used.
58
-     * @return EE_Line_Item
59
-     * @throws EE_Error
60
-     */
61
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
62
-    {
63
-        return new self($props_n_values, true, $timezone);
64
-    }
65
-
66
-
67
-    /**
68
-     * Adds some defaults if they're not specified
69
-     *
70
-     * @param array $fieldValues
71
-     * @param bool $bydb
72
-     * @param string $timezone
73
-     * @throws EE_Error
74
-     */
75
-    protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
76
-    {
77
-        parent::__construct($fieldValues, $bydb, $timezone);
78
-        if (!$this->get('LIN_code')) {
79
-            $this->set_code($this->generate_code());
80
-        }
81
-    }
82
-
83
-
84
-    /**
85
-     * Gets ID
86
-     *
87
-     * @return int
88
-     * @throws EE_Error
89
-     */
90
-    public function ID()
91
-    {
92
-        return $this->get('LIN_ID');
93
-    }
94
-
95
-
96
-    /**
97
-     * Gets TXN_ID
98
-     *
99
-     * @return int
100
-     * @throws EE_Error
101
-     */
102
-    public function TXN_ID()
103
-    {
104
-        return $this->get('TXN_ID');
105
-    }
106
-
107
-
108
-    /**
109
-     * Sets TXN_ID
110
-     *
111
-     * @param int $TXN_ID
112
-     * @throws EE_Error
113
-     */
114
-    public function set_TXN_ID($TXN_ID)
115
-    {
116
-        $this->set('TXN_ID', $TXN_ID);
117
-    }
118
-
119
-
120
-    /**
121
-     * Gets name
122
-     *
123
-     * @return string
124
-     * @throws EE_Error
125
-     */
126
-    public function name()
127
-    {
128
-        $name = $this->get('LIN_name');
129
-        if (!$name) {
130
-            $name = ucwords(str_replace('-', ' ', $this->type()));
131
-        }
132
-        return $name;
133
-    }
134
-
135
-
136
-    /**
137
-     * Sets name
138
-     *
139
-     * @param string $name
140
-     * @throws EE_Error
141
-     */
142
-    public function set_name($name)
143
-    {
144
-        $this->set('LIN_name', $name);
145
-    }
146
-
147
-
148
-    /**
149
-     * Gets desc
150
-     *
151
-     * @return string
152
-     * @throws EE_Error
153
-     */
154
-    public function desc()
155
-    {
156
-        return $this->get('LIN_desc');
157
-    }
158
-
159
-
160
-    /**
161
-     * Sets desc
162
-     *
163
-     * @param string $desc
164
-     * @throws EE_Error
165
-     */
166
-    public function set_desc($desc)
167
-    {
168
-        $this->set('LIN_desc', $desc);
169
-    }
170
-
171
-
172
-    /**
173
-     * Gets quantity
174
-     *
175
-     * @return int
176
-     * @throws EE_Error
177
-     */
178
-    public function quantity()
179
-    {
180
-        return $this->get('LIN_quantity');
181
-    }
182
-
183
-
184
-    /**
185
-     * Sets quantity
186
-     *
187
-     * @param int $quantity
188
-     * @throws EE_Error
189
-     */
190
-    public function set_quantity($quantity)
191
-    {
192
-        $this->set('LIN_quantity', max($quantity, 0));
193
-    }
194
-
195
-
196
-    /**
197
-     * Gets item_id
198
-     *
199
-     * @return string
200
-     * @throws EE_Error
201
-     */
202
-    public function OBJ_ID()
203
-    {
204
-        return $this->get('OBJ_ID');
205
-    }
206
-
207
-
208
-    /**
209
-     * Sets item_id
210
-     *
211
-     * @param string $item_id
212
-     * @throws EE_Error
213
-     */
214
-    public function set_OBJ_ID($item_id)
215
-    {
216
-        $this->set('OBJ_ID', $item_id);
217
-    }
218
-
219
-
220
-    /**
221
-     * Gets item_type
222
-     *
223
-     * @return string
224
-     * @throws EE_Error
225
-     */
226
-    public function OBJ_type()
227
-    {
228
-        return $this->get('OBJ_type');
229
-    }
230
-
231
-
232
-    /**
233
-     * Gets item_type
234
-     *
235
-     * @return string
236
-     * @throws EE_Error
237
-     */
238
-    public function OBJ_type_i18n()
239
-    {
240
-        $obj_type = $this->OBJ_type();
241
-        switch ($obj_type) {
242
-            case 'Event':
243
-                $obj_type = __('Event', 'event_espresso');
244
-                break;
245
-            case 'Price':
246
-                $obj_type = __('Price', 'event_espresso');
247
-                break;
248
-            case 'Promotion':
249
-                $obj_type = __('Promotion', 'event_espresso');
250
-                break;
251
-            case 'Ticket':
252
-                $obj_type = __('Ticket', 'event_espresso');
253
-                break;
254
-            case 'Transaction':
255
-                $obj_type = __('Transaction', 'event_espresso');
256
-                break;
257
-        }
258
-        return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this);
259
-    }
260
-
261
-
262
-    /**
263
-     * Sets item_type
264
-     *
265
-     * @param string $OBJ_type
266
-     * @throws EE_Error
267
-     */
268
-    public function set_OBJ_type($OBJ_type)
269
-    {
270
-        $this->set('OBJ_type', $OBJ_type);
271
-    }
272
-
273
-
274
-    /**
275
-     * Gets unit_price
276
-     *
277
-     * @return float
278
-     * @throws EE_Error
279
-     */
280
-    public function unit_price()
281
-    {
282
-        return $this->get('LIN_unit_price');
283
-    }
284
-
285
-
286
-    /**
287
-     * Sets unit_price
288
-     *
289
-     * @param float $unit_price
290
-     * @throws EE_Error
291
-     */
292
-    public function set_unit_price($unit_price)
293
-    {
294
-        $this->set('LIN_unit_price', $unit_price);
295
-    }
296
-
297
-
298
-    /**
299
-     * Checks if this item is a percentage modifier or not
300
-     *
301
-     * @return boolean
302
-     * @throws EE_Error
303
-     */
304
-    public function is_percent()
305
-    {
306
-        if ($this->is_tax_sub_total()) {
307
-            //tax subtotals HAVE a percent on them, that percentage only applies
308
-            //to taxable items, so its' an exception. Treat it like a flat line item
309
-            return false;
310
-        }
311
-        $unit_price = abs($this->get('LIN_unit_price'));
312
-        $percent = abs($this->get('LIN_percent'));
313
-        if ($unit_price < .001 && $percent) {
314
-            return true;
315
-        }
316
-        if ($unit_price >= .001 && !$percent) {
317
-            return false;
318
-        }
319
-        if ($unit_price >= .001 && $percent) {
320
-            throw new EE_Error(
321
-                sprintf(
322
-                    esc_html__('A Line Item can not have a unit price of (%s) AND a percent (%s)!', 'event_espresso'),
323
-                    $unit_price, $percent
324
-                )
325
-            );
326
-        }
327
-        // if they're both 0, assume its not a percent item
328
-        return false;
329
-    }
330
-
331
-
332
-    /**
333
-     * Gets percent (between 100-.001)
334
-     *
335
-     * @return float
336
-     * @throws EE_Error
337
-     */
338
-    public function percent()
339
-    {
340
-        return $this->get('LIN_percent');
341
-    }
342
-
343
-
344
-    /**
345
-     * Sets percent (between 100-0.01)
346
-     *
347
-     * @param float $percent
348
-     * @throws EE_Error
349
-     */
350
-    public function set_percent($percent)
351
-    {
352
-        $this->set('LIN_percent', $percent);
353
-    }
354
-
355
-
356
-    /**
357
-     * Gets total
358
-     *
359
-     * @return float
360
-     * @throws EE_Error
361
-     */
362
-    public function total()
363
-    {
364
-        return $this->get('LIN_total');
365
-    }
366
-
367
-
368
-    /**
369
-     * Sets total
370
-     *
371
-     * @param float $total
372
-     * @throws EE_Error
373
-     */
374
-    public function set_total($total)
375
-    {
376
-        $this->set('LIN_total', $total);
377
-    }
378
-
379
-
380
-    /**
381
-     * Gets order
382
-     *
383
-     * @return int
384
-     * @throws EE_Error
385
-     */
386
-    public function order()
387
-    {
388
-        return $this->get('LIN_order');
389
-    }
390
-
391
-
392
-    /**
393
-     * Sets order
394
-     *
395
-     * @param int $order
396
-     * @throws EE_Error
397
-     */
398
-    public function set_order($order)
399
-    {
400
-        $this->set('LIN_order', $order);
401
-    }
402
-
403
-
404
-    /**
405
-     * Gets parent
406
-     *
407
-     * @return int
408
-     * @throws EE_Error
409
-     */
410
-    public function parent_ID()
411
-    {
412
-        return $this->get('LIN_parent');
413
-    }
414
-
415
-
416
-    /**
417
-     * Sets parent
418
-     *
419
-     * @param int $parent
420
-     * @throws EE_Error
421
-     */
422
-    public function set_parent_ID($parent)
423
-    {
424
-        $this->set('LIN_parent', $parent);
425
-    }
426
-
427
-
428
-    /**
429
-     * Gets type
430
-     *
431
-     * @return string
432
-     * @throws EE_Error
433
-     */
434
-    public function type()
435
-    {
436
-        return $this->get('LIN_type');
437
-    }
438
-
439
-
440
-    /**
441
-     * Sets type
442
-     *
443
-     * @param string $type
444
-     * @throws EE_Error
445
-     */
446
-    public function set_type($type)
447
-    {
448
-        $this->set('LIN_type', $type);
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\
454
-     * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB
455
-     * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()`
456
-     * or indirectly by `EE_Line_item::add_child_line_item()`)
457
-     *
458
-     * @return EE_Base_Class|EE_Line_Item
459
-     * @throws EE_Error
460
-     */
461
-    public function parent()
462
-    {
463
-        return $this->ID()
464
-            ? $this->get_model()->get_one_by_ID($this->parent_ID())
465
-            : $this->_parent;
466
-    }
467
-
468
-
469
-    /**
470
-     * Gets ALL the children of this line item (ie, all the parts that contribute towards this total).
471
-     *
472
-     * @return EE_Base_Class[]|EE_Line_Item[]
473
-     * @throws EE_Error
474
-     */
475
-    public function children()
476
-    {
477
-        if ($this->ID()) {
478
-            return $this->get_model()->get_all(
479
-                array(
480
-                    array('LIN_parent' => $this->ID()),
481
-                    'order_by' => array('LIN_order' => 'ASC'),
482
-                )
483
-            );
484
-        }
485
-        if (!is_array($this->_children)) {
486
-            $this->_children = array();
487
-        }
488
-        return $this->_children;
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets code
494
-     *
495
-     * @return string
496
-     * @throws EE_Error
497
-     */
498
-    public function code()
499
-    {
500
-        return $this->get('LIN_code');
501
-    }
502
-
503
-
504
-    /**
505
-     * Sets code
506
-     *
507
-     * @param string $code
508
-     * @throws EE_Error
509
-     */
510
-    public function set_code($code)
511
-    {
512
-        $this->set('LIN_code', $code);
513
-    }
514
-
515
-
516
-    /**
517
-     * Gets is_taxable
518
-     *
519
-     * @return boolean
520
-     * @throws EE_Error
521
-     */
522
-    public function is_taxable()
523
-    {
524
-        return $this->get('LIN_is_taxable');
525
-    }
526
-
527
-
528
-    /**
529
-     * Sets is_taxable
530
-     *
531
-     * @param boolean $is_taxable
532
-     * @throws EE_Error
533
-     */
534
-    public function set_is_taxable($is_taxable)
535
-    {
536
-        $this->set('LIN_is_taxable', $is_taxable);
537
-    }
538
-
539
-
540
-    /**
541
-     * Gets the object that this model-joins-to.
542
-     * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on
543
-     * EEM_Promotion_Object
544
-     *
545
-     *        Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object
546
-     *
547
-     * @return EE_Base_Class | NULL
548
-     * @throws EE_Error
549
-     */
550
-    public function get_object()
551
-    {
552
-        $model_name_of_related_obj = $this->OBJ_type();
553
-        return $this->get_model()->has_relation($model_name_of_related_obj)
554
-            ? $this->get_first_related($model_name_of_related_obj)
555
-            : null;
556
-    }
557
-
558
-
559
-    /**
560
-     * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket.
561
-     * (IE, if this line item is for a price or something else, will return NULL)
562
-     *
563
-     * @param array $query_params
564
-     * @return EE_Base_Class|EE_Ticket
565
-     * @throws EE_Error
566
-     */
567
-    public function ticket($query_params = array())
568
-    {
569
-        //we're going to assume that when this method is called we always want to receive the attached ticket EVEN if that ticket is archived.  This can be overridden via the incoming $query_params argument
570
-        $remove_defaults = array('default_where_conditions' => 'none');
571
-        $query_params = array_merge($remove_defaults, $query_params);
572
-        return $this->get_first_related('Ticket', $query_params);
573
-    }
574
-
575
-
576
-    /**
577
-     * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket
578
-     *
579
-     * @return EE_Datetime | NULL
580
-     * @throws EE_Error
581
-     */
582
-    public function get_ticket_datetime()
583
-    {
584
-        if ($this->OBJ_type() === 'Ticket') {
585
-            $ticket = $this->ticket();
586
-            if ($ticket instanceof EE_Ticket) {
587
-                $datetime = $ticket->first_datetime();
588
-                if ($datetime instanceof EE_Datetime) {
589
-                    return $datetime;
590
-                }
591
-            }
592
-        }
593
-        return null;
594
-    }
595
-
596
-
597
-    /**
598
-     * Gets the event's name that's related to the ticket, if this is for
599
-     * a ticket
600
-     *
601
-     * @return string
602
-     * @throws EE_Error
603
-     */
604
-    public function ticket_event_name()
605
-    {
606
-        $event_name = esc_html__('Unknown', 'event_espresso');
607
-        $event = $this->ticket_event();
608
-        if ($event instanceof EE_Event) {
609
-            $event_name = $event->name();
610
-        }
611
-        return $event_name;
612
-    }
613
-
614
-
615
-    /**
616
-     * Gets the event that's related to the ticket, if this line item represents a ticket.
617
-     *
618
-     * @return EE_Event|null
619
-     * @throws EE_Error
620
-     */
621
-    public function ticket_event()
622
-    {
623
-        $event = null;
624
-        $ticket = $this->ticket();
625
-        if ($ticket instanceof EE_Ticket) {
626
-            $datetime = $ticket->first_datetime();
627
-            if ($datetime instanceof EE_Datetime) {
628
-                $event = $datetime->event();
629
-            }
630
-        }
631
-        return $event;
632
-    }
633
-
634
-
635
-    /**
636
-     * Gets the first datetime for this lien item, assuming it's for a ticket
637
-     *
638
-     * @param string $date_format
639
-     * @param string $time_format
640
-     * @return string
641
-     * @throws EE_Error
642
-     */
643
-    public function ticket_datetime_start($date_format = '', $time_format = '')
644
-    {
645
-        $first_datetime_string = esc_html__('Unknown', 'event_espresso');
646
-        $datetime = $this->get_ticket_datetime();
647
-        if ($datetime) {
648
-            $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format);
649
-        }
650
-        return $first_datetime_string;
651
-    }
652
-
653
-
654
-    /**
655
-     * Adds the line item as a child to this line item. If there is another child line
656
-     * item with the same LIN_code, it is overwritten by this new one
657
-     *
658
-     * @param EEI_Line_Item $line_item
659
-     * @param bool $set_order
660
-     * @return bool success
661
-     * @throws EE_Error
662
-     */
663
-    public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true)
664
-    {
665
-        // should we calculate the LIN_order for this line item ?
666
-        if ($set_order || $line_item->order() === null) {
667
-            $line_item->set_order(count($this->children()));
668
-        }
669
-        if ($this->ID()) {
670
-            //check for any duplicate line items (with the same code), if so, this replaces it
671
-            $line_item_with_same_code = $this->get_child_line_item($line_item->code());
672
-            if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) {
673
-                $this->delete_child_line_item($line_item_with_same_code->code());
674
-            }
675
-            $line_item->set_parent_ID($this->ID());
676
-            if ($this->TXN_ID()) {
677
-                $line_item->set_TXN_ID($this->TXN_ID());
678
-            }
679
-            return $line_item->save();
680
-        }
681
-        $this->_children[$line_item->code()] = $line_item;
682
-        if ($line_item->parent() !== $this) {
683
-            $line_item->set_parent($this);
684
-        }
685
-        return true;
686
-    }
687
-
688
-
689
-    /**
690
-     * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation.
691
-     * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save()
692
-     * However, if this line item is NOT saved to the DB, this just caches the parent on
693
-     * the EE_Line_Item::_parent property.
694
-     *
695
-     * @param EE_Line_Item $line_item
696
-     * @throws EE_Error
697
-     */
698
-    public function set_parent($line_item)
699
-    {
700
-        if ($this->ID()) {
701
-            if (!$line_item->ID()) {
702
-                $line_item->save();
703
-            }
704
-            $this->set_parent_ID($line_item->ID());
705
-            $this->save();
706
-        } else {
707
-            $this->_parent = $line_item;
708
-            $this->set_parent_ID($line_item->ID());
709
-        }
710
-    }
711
-
712
-
713
-    /**
714
-     * Gets the child line item as specified by its code. Because this returns an object (by reference)
715
-     * you can modify this child line item and the parent (this object) can know about them
716
-     * because it also has a reference to that line item
717
-     *
718
-     * @param string $code
719
-     * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
720
-     * @throws EE_Error
721
-     */
722
-    public function get_child_line_item($code)
723
-    {
724
-        if ($this->ID()) {
725
-            return $this->get_model()->get_one(
726
-                array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
727
-            );
728
-        }
729
-        return isset($this->_children[$code])
730
-            ? $this->_children[$code]
731
-            : null;
732
-    }
733
-
734
-
735
-    /**
736
-     * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD
737
-     * cached on it)
738
-     *
739
-     * @return int
740
-     * @throws EE_Error
741
-     */
742
-    public function delete_children_line_items()
743
-    {
744
-        if ($this->ID()) {
745
-            return $this->get_model()->delete(array(array('LIN_parent' => $this->ID())));
746
-        }
747
-        $count = count($this->_children);
748
-        $this->_children = array();
749
-        return $count;
750
-    }
751
-
752
-
753
-    /**
754
-     * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line
755
-     * HAS NOT been saved to the DB, removes the child line item with index $code.
756
-     * Also searches through the child's children for a matching line item. However, once a line item has been found
757
-     * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be
758
-     * deleted)
759
-     *
760
-     * @param string $code
761
-     * @param bool $stop_search_once_found
762
-     * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to
763
-     *             the DB yet)
764
-     * @throws EE_Error
765
-     */
766
-    public function delete_child_line_item($code, $stop_search_once_found = true)
767
-    {
768
-        if ($this->ID()) {
769
-            $items_deleted = 0;
770
-            if ($this->code() === $code) {
771
-                $items_deleted += EEH_Line_Item::delete_all_child_items($this);
772
-                $items_deleted += (int)$this->delete();
773
-                if ($stop_search_once_found) {
774
-                    return $items_deleted;
775
-                }
776
-            }
777
-            foreach ($this->children() as $child_line_item) {
778
-                $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found);
779
-            }
780
-            return $items_deleted;
781
-        }
782
-        if (isset($this->_children[$code])) {
783
-            unset($this->_children[$code]);
784
-            return 1;
785
-        }
786
-        return 0;
787
-    }
788
-
789
-
790
-    /**
791
-     * If this line item is in the database, is of the type subtotal, and
792
-     * has no children, why do we have it? It should be deleted so this function
793
-     * does that
794
-     *
795
-     * @return boolean
796
-     * @throws EE_Error
797
-     */
798
-    public function delete_if_childless_subtotal()
799
-    {
800
-        if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && !$this->children()) {
801
-            return $this->delete();
802
-        }
803
-        return false;
804
-    }
805
-
806
-
807
-    /**
808
-     * Creates a code and returns a string. doesn't assign the code to this model object
809
-     *
810
-     * @return string
811
-     * @throws EE_Error
812
-     */
813
-    public function generate_code()
814
-    {
815
-        // each line item in the cart requires a unique identifier
816
-        return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
817
-    }
818
-
819
-
820
-    /**
821
-     * @return bool
822
-     * @throws EE_Error
823
-     */
824
-    public function is_tax()
825
-    {
826
-        return $this->type() === EEM_Line_Item::type_tax;
827
-    }
828
-
829
-
830
-    /**
831
-     * @return bool
832
-     * @throws EE_Error
833
-     */
834
-    public function is_tax_sub_total()
835
-    {
836
-        return $this->type() === EEM_Line_Item::type_tax_sub_total;
837
-    }
838
-
839
-
840
-    /**
841
-     * @return bool
842
-     * @throws EE_Error
843
-     */
844
-    public function is_line_item()
845
-    {
846
-        return $this->type() === EEM_Line_Item::type_line_item;
847
-    }
848
-
849
-
850
-    /**
851
-     * @return bool
852
-     * @throws EE_Error
853
-     */
854
-    public function is_sub_line_item()
855
-    {
856
-        return $this->type() === EEM_Line_Item::type_sub_line_item;
857
-    }
858
-
859
-
860
-    /**
861
-     * @return bool
862
-     * @throws EE_Error
863
-     */
864
-    public function is_sub_total()
865
-    {
866
-        return $this->type() === EEM_Line_Item::type_sub_total;
867
-    }
868
-
869
-
870
-    /**
871
-     * Whether or not this line item is a cancellation line item
872
-     *
873
-     * @return boolean
874
-     * @throws EE_Error
875
-     */
876
-    public function is_cancellation()
877
-    {
878
-        return EEM_Line_Item::type_cancellation === $this->type();
879
-    }
880
-
881
-
882
-    /**
883
-     * @return bool
884
-     * @throws EE_Error
885
-     */
886
-    public function is_total()
887
-    {
888
-        return $this->type() === EEM_Line_Item::type_total;
889
-    }
890
-
891
-
892
-    /**
893
-     * @return bool
894
-     * @throws EE_Error
895
-     */
896
-    public function is_cancelled()
897
-    {
898
-        return $this->type() === EEM_Line_Item::type_cancellation;
899
-    }
900
-
901
-
902
-    /**
903
-     * @return string like '2, 004.00', formatted according to the localized currency
904
-     * @throws EE_Error
905
-     */
906
-    public function unit_price_no_code()
907
-    {
908
-        return $this->get_pretty('LIN_unit_price', 'no_currency_code');
909
-    }
910
-
911
-
912
-    /**
913
-     * @return string like '2, 004.00', formatted according to the localized currency
914
-     * @throws EE_Error
915
-     */
916
-    public function total_no_code()
917
-    {
918
-        return $this->get_pretty('LIN_total', 'no_currency_code');
919
-    }
920
-
921
-
922
-    /**
923
-     * Gets the final total on this item, taking taxes into account.
924
-     * Has the side-effect of setting the sub-total as it was just calculated.
925
-     * If this is used on a grand-total line item, also updates the transaction's
926
-     * TXN_total (provided this line item is allowed to persist, otherwise we don't
927
-     * want to change a persistable transaction with info from a non-persistent line item)
928
-     *
929
-     * @return float
930
-     * @throws EE_Error
931
-     * @throws InvalidArgumentException
932
-     * @throws InvalidInterfaceException
933
-     * @throws InvalidDataTypeException
934
-     */
935
-    public function recalculate_total_including_taxes()
936
-    {
937
-        $pre_tax_total = $this->recalculate_pre_tax_total();
938
-        $tax_total = $this->recalculate_taxes_and_tax_total();
939
-        $total = $pre_tax_total + $tax_total;
940
-        // no negative totals plz
941
-        $total = max($total, 0);
942
-        $this->set_total($total);
943
-        //only update the related transaction's total
944
-        //if we intend to save this line item and its a grand total
945
-        if (
946
-            $this->allow_persist() && $this->type() === EEM_Line_Item::type_total
947
-            && $this->transaction()
948
-            instanceof
949
-            EE_Transaction
950
-        ) {
951
-            $this->transaction()->set_total($total);
952
-            if ($this->transaction()->ID()) {
953
-                $this->transaction()->save();
954
-            }
955
-        }
956
-        $this->maybe_save();
957
-        return $total;
958
-    }
959
-
960
-
961
-    /**
962
-     * Recursively goes through all the children and recalculates sub-totals EXCEPT for
963
-     * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its
964
-     * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
965
-     * when this is called on the grand total
966
-     *
967
-     * @return float
968
-     * @throws InvalidArgumentException
969
-     * @throws InvalidInterfaceException
970
-     * @throws InvalidDataTypeException
971
-     * @throws EE_Error
972
-     */
973
-    public function recalculate_pre_tax_total()
974
-    {
975
-        $total = 0;
976
-        $my_children = $this->children();
977
-        $has_children = !empty($my_children);
978
-        if ($has_children && $this->is_line_item()) {
979
-            $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
980
-        } elseif (!$has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
981
-            $total = $this->unit_price() * $this->quantity();
982
-        } elseif ($this->is_sub_total() || $this->is_total()) {
983
-            $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
984
-        } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) {
985
-            // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total
986
-            return 0;
987
-        }
988
-        // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
989
-        if (
990
-            !$this->is_line_item() && !$this->is_sub_line_item() && !$this->is_cancellation()
991
-        ) {
992
-            if ($this->OBJ_type() !== 'Event') {
993
-                $this->set_quantity(1);
994
-            }
995
-            if (!$this->is_percent()) {
996
-                $this->set_unit_price($total);
997
-            }
998
-        }
999
-        //we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1000
-        //so it ought to be
1001
-        if (!$this->is_total()) {
1002
-            $this->set_total($total);
1003
-            //if not a percent line item, make sure we keep the unit price in sync
1004
-            if (
1005
-                $has_children
1006
-                && $this->is_line_item()
1007
-                && !$this->is_percent()
1008
-            ) {
1009
-                if ($this->quantity() === 0) {
1010
-                    $new_unit_price = 0;
1011
-                } else {
1012
-                    $new_unit_price = $this->total() / $this->quantity();
1013
-                }
1014
-                $this->set_unit_price($new_unit_price);
1015
-            }
1016
-            $this->maybe_save();
1017
-        }
1018
-        return $total;
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * Calculates the pretax total when this line item is a subtotal or total line item.
1024
-     * Basically does a sum-then-round approach (ie, any percent line item that are children
1025
-     * will calculate their total based on the un-rounded total we're working with so far, and
1026
-     * THEN round the result; instead of rounding as we go like with sub-line-items)
1027
-     *
1028
-     * @param float $calculated_total_so_far
1029
-     * @param EE_Line_Item[] $my_children
1030
-     * @return float
1031
-     * @throws InvalidArgumentException
1032
-     * @throws InvalidInterfaceException
1033
-     * @throws InvalidDataTypeException
1034
-     * @throws EE_Error
1035
-     */
1036
-    protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null)
1037
-    {
1038
-        if ($my_children === null) {
1039
-            $my_children = $this->children();
1040
-        }
1041
-        $subtotal_quantity = 0;
1042
-        //get the total of all its children
1043
-        foreach ($my_children as $child_line_item) {
1044
-            if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) {
1045
-                // percentage line items are based on total so far
1046
-                if ($child_line_item->is_percent()) {
1047
-                    //round as we go so that the line items add up ok
1048
-                    $percent_total = round(
1049
-                        $calculated_total_so_far * $child_line_item->percent() / 100,
1050
-                        EE_Registry::instance()->CFG->currency->dec_plc
1051
-                    );
1052
-                    $child_line_item->set_total($percent_total);
1053
-                    //so far all percent line items should have a quantity of 1
1054
-                    //(ie, no double percent discounts. Although that might be requested someday)
1055
-                    $child_line_item->set_quantity(1);
1056
-                    $child_line_item->maybe_save();
1057
-                    $calculated_total_so_far += $percent_total;
1058
-                } else {
1059
-                    //verify flat sub-line-item quantities match their parent
1060
-                    if ($child_line_item->is_sub_line_item()) {
1061
-                        $child_line_item->set_quantity($this->quantity());
1062
-                    }
1063
-                    $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1064
-                    $subtotal_quantity += $child_line_item->quantity();
1065
-                }
1066
-            }
1067
-        }
1068
-        if ($this->is_sub_total()) {
1069
-            // no negative totals plz
1070
-            $calculated_total_so_far = max($calculated_total_so_far, 0);
1071
-            $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0;
1072
-            $this->set_quantity($subtotal_quantity);
1073
-            $this->maybe_save();
1074
-        }
1075
-        return $calculated_total_so_far;
1076
-    }
1077
-
1078
-
1079
-    /**
1080
-     * Calculates the pretax total for a normal line item, in a round-then-sum approach
1081
-     * (where each sub-line-item is applied to the base price for the line item
1082
-     * and the result is immediately rounded, rather than summing all the sub-line-items
1083
-     * then rounding, like we do when recalculating pretax totals on totals and subtotals).
1084
-     *
1085
-     * @param float $calculated_total_so_far
1086
-     * @param EE_Line_Item[] $my_children
1087
-     * @return float
1088
-     * @throws InvalidArgumentException
1089
-     * @throws InvalidInterfaceException
1090
-     * @throws InvalidDataTypeException
1091
-     * @throws EE_Error
1092
-     */
1093
-    protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null)
1094
-    {
1095
-        if ($my_children === null) {
1096
-            $my_children = $this->children();
1097
-        }
1098
-        //we need to keep track of the running total for a single item,
1099
-        //because we need to round as we go
1100
-        $unit_price_for_total = 0;
1101
-        $quantity_for_total = 1;
1102
-        //get the total of all its children
1103
-        foreach ($my_children as $child_line_item) {
1104
-            if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) {
1105
-                if ($child_line_item->is_percent()) {
1106
-                    //it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1107
-                    //not total multiplied by percent, because that ignores rounding along-the-way
1108
-                    $percent_unit_price = round(
1109
-                        $unit_price_for_total * $child_line_item->percent() / 100,
1110
-                        EE_Registry::instance()->CFG->currency->dec_plc
1111
-                    );
1112
-                    $percent_total = $percent_unit_price * $quantity_for_total;
1113
-                    $child_line_item->set_total($percent_total);
1114
-                    //so far all percent line items should have a quantity of 1
1115
-                    //(ie, no double percent discounts. Although that might be requested someday)
1116
-                    $child_line_item->set_quantity(1);
1117
-                    $child_line_item->maybe_save();
1118
-                    $calculated_total_so_far += $percent_total;
1119
-                    $unit_price_for_total += $percent_unit_price;
1120
-                } else {
1121
-                    //verify flat sub-line-item quantities match their parent
1122
-                    if ($child_line_item->is_sub_line_item()) {
1123
-                        $child_line_item->set_quantity($this->quantity());
1124
-                    }
1125
-                    $quantity_for_total = $child_line_item->quantity();
1126
-                    $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1127
-                    $unit_price_for_total += $child_line_item->unit_price();
1128
-                }
1129
-            }
1130
-        }
1131
-        return $calculated_total_so_far;
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
1137
-     * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
1138
-     * and tax sub-total if already in the DB
1139
-     *
1140
-     * @return float
1141
-     * @throws EE_Error
1142
-     */
1143
-    public function recalculate_taxes_and_tax_total()
1144
-    {
1145
-        //get all taxes
1146
-        $taxes = $this->tax_descendants();
1147
-        //calculate the pretax total
1148
-        $taxable_total = $this->taxable_total();
1149
-        $tax_total = 0;
1150
-        foreach ($taxes as $tax) {
1151
-            $total_on_this_tax = $taxable_total * $tax->percent() / 100;
1152
-            //remember the total on this line item
1153
-            $tax->set_total($total_on_this_tax);
1154
-            $tax->maybe_save();
1155
-            $tax_total += $tax->total();
1156
-        }
1157
-        $this->_recalculate_tax_sub_total();
1158
-        return $tax_total;
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
1164
-     *
1165
-     * @return void
1166
-     * @throws EE_Error
1167
-     */
1168
-    private function _recalculate_tax_sub_total()
1169
-    {
1170
-        if ($this->is_tax_sub_total()) {
1171
-            $total = 0;
1172
-            $total_percent = 0;
1173
-            //simply loop through all its children (which should be taxes) and sum their total
1174
-            foreach ($this->children() as $child_tax) {
1175
-                if ($child_tax instanceof EE_Line_Item) {
1176
-                    $total += $child_tax->total();
1177
-                    $total_percent += $child_tax->percent();
1178
-                }
1179
-            }
1180
-            $this->set_total($total);
1181
-            $this->set_percent($total_percent);
1182
-            $this->maybe_save();
1183
-        } elseif ($this->is_total()) {
1184
-            foreach ($this->children() as $maybe_tax_subtotal) {
1185
-                if ($maybe_tax_subtotal instanceof EE_Line_Item) {
1186
-                    $maybe_tax_subtotal->_recalculate_tax_sub_total();
1187
-                }
1188
-            }
1189
-        }
1190
-    }
1191
-
1192
-
1193
-    /**
1194
-     * Gets the total tax on this line item. Assumes taxes have already been calculated using
1195
-     * recalculate_taxes_and_total
1196
-     *
1197
-     * @return float
1198
-     * @throws EE_Error
1199
-     */
1200
-    public function get_total_tax()
1201
-    {
1202
-        $this->_recalculate_tax_sub_total();
1203
-        $total = 0;
1204
-        foreach ($this->tax_descendants() as $tax_line_item) {
1205
-            if ($tax_line_item instanceof EE_Line_Item) {
1206
-                $total += $tax_line_item->total();
1207
-            }
1208
-        }
1209
-        return $total;
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * Gets the total for all the items purchased only
1215
-     *
1216
-     * @return float
1217
-     * @throws EE_Error
1218
-     */
1219
-    public function get_items_total()
1220
-    {
1221
-        //by default, let's make sure we're consistent with the existing line item
1222
-        if ($this->is_total()) {
1223
-            $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this);
1224
-            if ($pretax_subtotal_li instanceof EE_Line_Item) {
1225
-                return $pretax_subtotal_li->total();
1226
-            }
1227
-        }
1228
-        $total = 0;
1229
-        foreach ($this->get_items() as $item) {
1230
-            if ($item instanceof EE_Line_Item) {
1231
-                $total += $item->total();
1232
-            }
1233
-        }
1234
-        return $total;
1235
-    }
1236
-
1237
-
1238
-    /**
1239
-     * Gets all the descendants (ie, children or children of children etc) that
1240
-     * are of the type 'tax'
1241
-     *
1242
-     * @return EE_Line_Item[]
1243
-     */
1244
-    public function tax_descendants()
1245
-    {
1246
-        return EEH_Line_Item::get_tax_descendants($this);
1247
-    }
1248
-
1249
-
1250
-    /**
1251
-     * Gets all the real items purchased which are children of this item
1252
-     *
1253
-     * @return EE_Line_Item[]
1254
-     */
1255
-    public function get_items()
1256
-    {
1257
-        return EEH_Line_Item::get_line_item_descendants($this);
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * Returns the amount taxable among this line item's children (or if it has no children,
1263
-     * how much of it is taxable). Does not recalculate totals or subtotals.
1264
-     * If the taxable total is negative, (eg, if none of the tickets were taxable,
1265
-     * but there is a "Taxable" discount), returns 0.
1266
-     *
1267
-     * @return float
1268
-     * @throws EE_Error
1269
-     */
1270
-    public function taxable_total()
1271
-    {
1272
-        $total = 0;
1273
-        if ($this->children()) {
1274
-            foreach ($this->children() as $child_line_item) {
1275
-                if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) {
1276
-                    //if it's a percent item, only take into account the percent
1277
-                    //that's taxable too (the taxable total so far)
1278
-                    if ($child_line_item->is_percent()) {
1279
-                        $total += ($total * $child_line_item->percent() / 100);
1280
-                    } else {
1281
-                        $total += $child_line_item->total();
1282
-                    }
1283
-                } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) {
1284
-                    $total += $child_line_item->taxable_total();
1285
-                }
1286
-            }
1287
-        }
1288
-        return max($total, 0);
1289
-    }
1290
-
1291
-
1292
-    /**
1293
-     * Gets the transaction for this line item
1294
-     *
1295
-     * @return EE_Base_Class|EE_Transaction
1296
-     * @throws EE_Error
1297
-     */
1298
-    public function transaction()
1299
-    {
1300
-        return $this->get_first_related('Transaction');
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * Saves this line item to the DB, and recursively saves its descendants.
1306
-     * Because there currently is no proper parent-child relation on the model,
1307
-     * save_this_and_cached() will NOT save the descendants.
1308
-     * Also sets the transaction on this line item and all its descendants before saving
1309
-     *
1310
-     * @param int $txn_id if none is provided, assumes $this->TXN_ID()
1311
-     * @return int count of items saved
1312
-     * @throws EE_Error
1313
-     */
1314
-    public function save_this_and_descendants_to_txn($txn_id = null)
1315
-    {
1316
-        $count = 0;
1317
-        if (!$txn_id) {
1318
-            $txn_id = $this->TXN_ID();
1319
-        }
1320
-        $this->set_TXN_ID($txn_id);
1321
-        $children = $this->children();
1322
-        $count += $this->save()
1323
-            ? 1
1324
-            : 0;
1325
-        foreach ($children as $child_line_item) {
1326
-            if ($child_line_item instanceof EE_Line_Item) {
1327
-                $child_line_item->set_parent_ID($this->ID());
1328
-                $count += $child_line_item->save_this_and_descendants_to_txn($txn_id);
1329
-            }
1330
-        }
1331
-        return $count;
1332
-    }
1333
-
1334
-
1335
-    /**
1336
-     * Saves this line item to the DB, and recursively saves its descendants.
1337
-     *
1338
-     * @return int count of items saved
1339
-     * @throws EE_Error
1340
-     */
1341
-    public function save_this_and_descendants()
1342
-    {
1343
-        $count = 0;
1344
-        $children = $this->children();
1345
-        $count += $this->save()
1346
-            ? 1
1347
-            : 0;
1348
-        foreach ($children as $child_line_item) {
1349
-            if ($child_line_item instanceof EE_Line_Item) {
1350
-                $child_line_item->set_parent_ID($this->ID());
1351
-                $count += $child_line_item->save_this_and_descendants();
1352
-            }
1353
-        }
1354
-        return $count;
1355
-    }
1356
-
1357
-
1358
-    /**
1359
-     * returns the cancellation line item if this item was cancelled
1360
-     *
1361
-     * @return EE_Line_Item[]
1362
-     * @throws InvalidArgumentException
1363
-     * @throws InvalidInterfaceException
1364
-     * @throws InvalidDataTypeException
1365
-     * @throws ReflectionException
1366
-     * @throws EE_Error
1367
-     */
1368
-    public function get_cancellations()
1369
-    {
1370
-        EE_Registry::instance()->load_helper('Line_Item');
1371
-        return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation);
1372
-    }
1373
-
1374
-
1375
-    /**
1376
-     * If this item has an ID, then this saves it again to update the db
1377
-     *
1378
-     * @return int count of items saved
1379
-     * @throws EE_Error
1380
-     */
1381
-    public function maybe_save()
1382
-    {
1383
-        if ($this->ID()) {
1384
-            return $this->save();
1385
-        }
1386
-        return false;
1387
-    }
1388
-
1389
-
1390
-    /**
1391
-     * clears the cached children and parent from the line item
1392
-     *
1393
-     * @return void
1394
-     */
1395
-    public function clear_related_line_item_cache()
1396
-    {
1397
-        $this->_children = array();
1398
-        $this->_parent = null;
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * @param bool $raw
1404
-     * @return int
1405
-     * @throws EE_Error
1406
-     */
1407
-    public function timestamp($raw = false)
1408
-    {
1409
-        return $raw
1410
-            ? $this->get_raw('LIN_timestamp')
1411
-            : $this->get('LIN_timestamp');
1412
-    }
1413
-
1414
-
1415
-
1416
-
1417
-    /************************* DEPRECATED *************************/
1418
-    /**
1419
-     * @deprecated 4.6.0
1420
-     * @param string $type one of the constants on EEM_Line_Item
1421
-     * @return EE_Line_Item[]
1422
-     */
1423
-    protected function _get_descendants_of_type($type)
1424
-    {
1425
-        EE_Error::doing_it_wrong(
1426
-            'EE_Line_Item::_get_descendants_of_type()',
1427
-            __('Method replaced with EEH_Line_Item::get_descendants_of_type()', 'event_espresso'), '4.6.0'
1428
-        );
1429
-        return EEH_Line_Item::get_descendants_of_type($this, $type);
1430
-    }
1431
-
1432
-
1433
-    /**
1434
-     * @deprecated 4.6.0
1435
-     * @param string $type like one of the EEM_Line_Item::type_*
1436
-     * @return EE_Line_Item
1437
-     */
1438
-    public function get_nearest_descendant_of_type($type)
1439
-    {
1440
-        EE_Error::doing_it_wrong(
1441
-            'EE_Line_Item::get_nearest_descendant_of_type()',
1442
-            __('Method replaced with EEH_Line_Item::get_nearest_descendant_of_type()', 'event_espresso'), '4.6.0'
1443
-        );
1444
-        return EEH_Line_Item::get_nearest_descendant_of_type($this, $type);
1445
-    }
20
+	/**
21
+	 * for children line items (currently not a normal relation)
22
+	 *
23
+	 * @type EE_Line_Item[]
24
+	 */
25
+	protected $_children = array();
26
+
27
+	/**
28
+	 * for the parent line item
29
+	 *
30
+	 * @var EE_Line_Item
31
+	 */
32
+	protected $_parent;
33
+
34
+
35
+	/**
36
+	 *
37
+	 * @param array $props_n_values incoming values
38
+	 * @param string $timezone incoming timezone (if not set the timezone set for the website will be
39
+	 *                                        used.)
40
+	 * @param array $date_formats incoming date_formats in an array where the first value is the
41
+	 *                                        date_format and the second value is the time format
42
+	 * @return EE_Line_Item
43
+	 * @throws EE_Error
44
+	 */
45
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
46
+	{
47
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
48
+		return $has_object
49
+			? $has_object
50
+			: new self($props_n_values, false, $timezone);
51
+	}
52
+
53
+
54
+	/**
55
+	 * @param array $props_n_values incoming values from the database
56
+	 * @param string $timezone incoming timezone as set by the model.  If not set the timezone for
57
+	 *                                the website will be used.
58
+	 * @return EE_Line_Item
59
+	 * @throws EE_Error
60
+	 */
61
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
62
+	{
63
+		return new self($props_n_values, true, $timezone);
64
+	}
65
+
66
+
67
+	/**
68
+	 * Adds some defaults if they're not specified
69
+	 *
70
+	 * @param array $fieldValues
71
+	 * @param bool $bydb
72
+	 * @param string $timezone
73
+	 * @throws EE_Error
74
+	 */
75
+	protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
76
+	{
77
+		parent::__construct($fieldValues, $bydb, $timezone);
78
+		if (!$this->get('LIN_code')) {
79
+			$this->set_code($this->generate_code());
80
+		}
81
+	}
82
+
83
+
84
+	/**
85
+	 * Gets ID
86
+	 *
87
+	 * @return int
88
+	 * @throws EE_Error
89
+	 */
90
+	public function ID()
91
+	{
92
+		return $this->get('LIN_ID');
93
+	}
94
+
95
+
96
+	/**
97
+	 * Gets TXN_ID
98
+	 *
99
+	 * @return int
100
+	 * @throws EE_Error
101
+	 */
102
+	public function TXN_ID()
103
+	{
104
+		return $this->get('TXN_ID');
105
+	}
106
+
107
+
108
+	/**
109
+	 * Sets TXN_ID
110
+	 *
111
+	 * @param int $TXN_ID
112
+	 * @throws EE_Error
113
+	 */
114
+	public function set_TXN_ID($TXN_ID)
115
+	{
116
+		$this->set('TXN_ID', $TXN_ID);
117
+	}
118
+
119
+
120
+	/**
121
+	 * Gets name
122
+	 *
123
+	 * @return string
124
+	 * @throws EE_Error
125
+	 */
126
+	public function name()
127
+	{
128
+		$name = $this->get('LIN_name');
129
+		if (!$name) {
130
+			$name = ucwords(str_replace('-', ' ', $this->type()));
131
+		}
132
+		return $name;
133
+	}
134
+
135
+
136
+	/**
137
+	 * Sets name
138
+	 *
139
+	 * @param string $name
140
+	 * @throws EE_Error
141
+	 */
142
+	public function set_name($name)
143
+	{
144
+		$this->set('LIN_name', $name);
145
+	}
146
+
147
+
148
+	/**
149
+	 * Gets desc
150
+	 *
151
+	 * @return string
152
+	 * @throws EE_Error
153
+	 */
154
+	public function desc()
155
+	{
156
+		return $this->get('LIN_desc');
157
+	}
158
+
159
+
160
+	/**
161
+	 * Sets desc
162
+	 *
163
+	 * @param string $desc
164
+	 * @throws EE_Error
165
+	 */
166
+	public function set_desc($desc)
167
+	{
168
+		$this->set('LIN_desc', $desc);
169
+	}
170
+
171
+
172
+	/**
173
+	 * Gets quantity
174
+	 *
175
+	 * @return int
176
+	 * @throws EE_Error
177
+	 */
178
+	public function quantity()
179
+	{
180
+		return $this->get('LIN_quantity');
181
+	}
182
+
183
+
184
+	/**
185
+	 * Sets quantity
186
+	 *
187
+	 * @param int $quantity
188
+	 * @throws EE_Error
189
+	 */
190
+	public function set_quantity($quantity)
191
+	{
192
+		$this->set('LIN_quantity', max($quantity, 0));
193
+	}
194
+
195
+
196
+	/**
197
+	 * Gets item_id
198
+	 *
199
+	 * @return string
200
+	 * @throws EE_Error
201
+	 */
202
+	public function OBJ_ID()
203
+	{
204
+		return $this->get('OBJ_ID');
205
+	}
206
+
207
+
208
+	/**
209
+	 * Sets item_id
210
+	 *
211
+	 * @param string $item_id
212
+	 * @throws EE_Error
213
+	 */
214
+	public function set_OBJ_ID($item_id)
215
+	{
216
+		$this->set('OBJ_ID', $item_id);
217
+	}
218
+
219
+
220
+	/**
221
+	 * Gets item_type
222
+	 *
223
+	 * @return string
224
+	 * @throws EE_Error
225
+	 */
226
+	public function OBJ_type()
227
+	{
228
+		return $this->get('OBJ_type');
229
+	}
230
+
231
+
232
+	/**
233
+	 * Gets item_type
234
+	 *
235
+	 * @return string
236
+	 * @throws EE_Error
237
+	 */
238
+	public function OBJ_type_i18n()
239
+	{
240
+		$obj_type = $this->OBJ_type();
241
+		switch ($obj_type) {
242
+			case 'Event':
243
+				$obj_type = __('Event', 'event_espresso');
244
+				break;
245
+			case 'Price':
246
+				$obj_type = __('Price', 'event_espresso');
247
+				break;
248
+			case 'Promotion':
249
+				$obj_type = __('Promotion', 'event_espresso');
250
+				break;
251
+			case 'Ticket':
252
+				$obj_type = __('Ticket', 'event_espresso');
253
+				break;
254
+			case 'Transaction':
255
+				$obj_type = __('Transaction', 'event_espresso');
256
+				break;
257
+		}
258
+		return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this);
259
+	}
260
+
261
+
262
+	/**
263
+	 * Sets item_type
264
+	 *
265
+	 * @param string $OBJ_type
266
+	 * @throws EE_Error
267
+	 */
268
+	public function set_OBJ_type($OBJ_type)
269
+	{
270
+		$this->set('OBJ_type', $OBJ_type);
271
+	}
272
+
273
+
274
+	/**
275
+	 * Gets unit_price
276
+	 *
277
+	 * @return float
278
+	 * @throws EE_Error
279
+	 */
280
+	public function unit_price()
281
+	{
282
+		return $this->get('LIN_unit_price');
283
+	}
284
+
285
+
286
+	/**
287
+	 * Sets unit_price
288
+	 *
289
+	 * @param float $unit_price
290
+	 * @throws EE_Error
291
+	 */
292
+	public function set_unit_price($unit_price)
293
+	{
294
+		$this->set('LIN_unit_price', $unit_price);
295
+	}
296
+
297
+
298
+	/**
299
+	 * Checks if this item is a percentage modifier or not
300
+	 *
301
+	 * @return boolean
302
+	 * @throws EE_Error
303
+	 */
304
+	public function is_percent()
305
+	{
306
+		if ($this->is_tax_sub_total()) {
307
+			//tax subtotals HAVE a percent on them, that percentage only applies
308
+			//to taxable items, so its' an exception. Treat it like a flat line item
309
+			return false;
310
+		}
311
+		$unit_price = abs($this->get('LIN_unit_price'));
312
+		$percent = abs($this->get('LIN_percent'));
313
+		if ($unit_price < .001 && $percent) {
314
+			return true;
315
+		}
316
+		if ($unit_price >= .001 && !$percent) {
317
+			return false;
318
+		}
319
+		if ($unit_price >= .001 && $percent) {
320
+			throw new EE_Error(
321
+				sprintf(
322
+					esc_html__('A Line Item can not have a unit price of (%s) AND a percent (%s)!', 'event_espresso'),
323
+					$unit_price, $percent
324
+				)
325
+			);
326
+		}
327
+		// if they're both 0, assume its not a percent item
328
+		return false;
329
+	}
330
+
331
+
332
+	/**
333
+	 * Gets percent (between 100-.001)
334
+	 *
335
+	 * @return float
336
+	 * @throws EE_Error
337
+	 */
338
+	public function percent()
339
+	{
340
+		return $this->get('LIN_percent');
341
+	}
342
+
343
+
344
+	/**
345
+	 * Sets percent (between 100-0.01)
346
+	 *
347
+	 * @param float $percent
348
+	 * @throws EE_Error
349
+	 */
350
+	public function set_percent($percent)
351
+	{
352
+		$this->set('LIN_percent', $percent);
353
+	}
354
+
355
+
356
+	/**
357
+	 * Gets total
358
+	 *
359
+	 * @return float
360
+	 * @throws EE_Error
361
+	 */
362
+	public function total()
363
+	{
364
+		return $this->get('LIN_total');
365
+	}
366
+
367
+
368
+	/**
369
+	 * Sets total
370
+	 *
371
+	 * @param float $total
372
+	 * @throws EE_Error
373
+	 */
374
+	public function set_total($total)
375
+	{
376
+		$this->set('LIN_total', $total);
377
+	}
378
+
379
+
380
+	/**
381
+	 * Gets order
382
+	 *
383
+	 * @return int
384
+	 * @throws EE_Error
385
+	 */
386
+	public function order()
387
+	{
388
+		return $this->get('LIN_order');
389
+	}
390
+
391
+
392
+	/**
393
+	 * Sets order
394
+	 *
395
+	 * @param int $order
396
+	 * @throws EE_Error
397
+	 */
398
+	public function set_order($order)
399
+	{
400
+		$this->set('LIN_order', $order);
401
+	}
402
+
403
+
404
+	/**
405
+	 * Gets parent
406
+	 *
407
+	 * @return int
408
+	 * @throws EE_Error
409
+	 */
410
+	public function parent_ID()
411
+	{
412
+		return $this->get('LIN_parent');
413
+	}
414
+
415
+
416
+	/**
417
+	 * Sets parent
418
+	 *
419
+	 * @param int $parent
420
+	 * @throws EE_Error
421
+	 */
422
+	public function set_parent_ID($parent)
423
+	{
424
+		$this->set('LIN_parent', $parent);
425
+	}
426
+
427
+
428
+	/**
429
+	 * Gets type
430
+	 *
431
+	 * @return string
432
+	 * @throws EE_Error
433
+	 */
434
+	public function type()
435
+	{
436
+		return $this->get('LIN_type');
437
+	}
438
+
439
+
440
+	/**
441
+	 * Sets type
442
+	 *
443
+	 * @param string $type
444
+	 * @throws EE_Error
445
+	 */
446
+	public function set_type($type)
447
+	{
448
+		$this->set('LIN_type', $type);
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\
454
+	 * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB
455
+	 * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()`
456
+	 * or indirectly by `EE_Line_item::add_child_line_item()`)
457
+	 *
458
+	 * @return EE_Base_Class|EE_Line_Item
459
+	 * @throws EE_Error
460
+	 */
461
+	public function parent()
462
+	{
463
+		return $this->ID()
464
+			? $this->get_model()->get_one_by_ID($this->parent_ID())
465
+			: $this->_parent;
466
+	}
467
+
468
+
469
+	/**
470
+	 * Gets ALL the children of this line item (ie, all the parts that contribute towards this total).
471
+	 *
472
+	 * @return EE_Base_Class[]|EE_Line_Item[]
473
+	 * @throws EE_Error
474
+	 */
475
+	public function children()
476
+	{
477
+		if ($this->ID()) {
478
+			return $this->get_model()->get_all(
479
+				array(
480
+					array('LIN_parent' => $this->ID()),
481
+					'order_by' => array('LIN_order' => 'ASC'),
482
+				)
483
+			);
484
+		}
485
+		if (!is_array($this->_children)) {
486
+			$this->_children = array();
487
+		}
488
+		return $this->_children;
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets code
494
+	 *
495
+	 * @return string
496
+	 * @throws EE_Error
497
+	 */
498
+	public function code()
499
+	{
500
+		return $this->get('LIN_code');
501
+	}
502
+
503
+
504
+	/**
505
+	 * Sets code
506
+	 *
507
+	 * @param string $code
508
+	 * @throws EE_Error
509
+	 */
510
+	public function set_code($code)
511
+	{
512
+		$this->set('LIN_code', $code);
513
+	}
514
+
515
+
516
+	/**
517
+	 * Gets is_taxable
518
+	 *
519
+	 * @return boolean
520
+	 * @throws EE_Error
521
+	 */
522
+	public function is_taxable()
523
+	{
524
+		return $this->get('LIN_is_taxable');
525
+	}
526
+
527
+
528
+	/**
529
+	 * Sets is_taxable
530
+	 *
531
+	 * @param boolean $is_taxable
532
+	 * @throws EE_Error
533
+	 */
534
+	public function set_is_taxable($is_taxable)
535
+	{
536
+		$this->set('LIN_is_taxable', $is_taxable);
537
+	}
538
+
539
+
540
+	/**
541
+	 * Gets the object that this model-joins-to.
542
+	 * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on
543
+	 * EEM_Promotion_Object
544
+	 *
545
+	 *        Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object
546
+	 *
547
+	 * @return EE_Base_Class | NULL
548
+	 * @throws EE_Error
549
+	 */
550
+	public function get_object()
551
+	{
552
+		$model_name_of_related_obj = $this->OBJ_type();
553
+		return $this->get_model()->has_relation($model_name_of_related_obj)
554
+			? $this->get_first_related($model_name_of_related_obj)
555
+			: null;
556
+	}
557
+
558
+
559
+	/**
560
+	 * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket.
561
+	 * (IE, if this line item is for a price or something else, will return NULL)
562
+	 *
563
+	 * @param array $query_params
564
+	 * @return EE_Base_Class|EE_Ticket
565
+	 * @throws EE_Error
566
+	 */
567
+	public function ticket($query_params = array())
568
+	{
569
+		//we're going to assume that when this method is called we always want to receive the attached ticket EVEN if that ticket is archived.  This can be overridden via the incoming $query_params argument
570
+		$remove_defaults = array('default_where_conditions' => 'none');
571
+		$query_params = array_merge($remove_defaults, $query_params);
572
+		return $this->get_first_related('Ticket', $query_params);
573
+	}
574
+
575
+
576
+	/**
577
+	 * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket
578
+	 *
579
+	 * @return EE_Datetime | NULL
580
+	 * @throws EE_Error
581
+	 */
582
+	public function get_ticket_datetime()
583
+	{
584
+		if ($this->OBJ_type() === 'Ticket') {
585
+			$ticket = $this->ticket();
586
+			if ($ticket instanceof EE_Ticket) {
587
+				$datetime = $ticket->first_datetime();
588
+				if ($datetime instanceof EE_Datetime) {
589
+					return $datetime;
590
+				}
591
+			}
592
+		}
593
+		return null;
594
+	}
595
+
596
+
597
+	/**
598
+	 * Gets the event's name that's related to the ticket, if this is for
599
+	 * a ticket
600
+	 *
601
+	 * @return string
602
+	 * @throws EE_Error
603
+	 */
604
+	public function ticket_event_name()
605
+	{
606
+		$event_name = esc_html__('Unknown', 'event_espresso');
607
+		$event = $this->ticket_event();
608
+		if ($event instanceof EE_Event) {
609
+			$event_name = $event->name();
610
+		}
611
+		return $event_name;
612
+	}
613
+
614
+
615
+	/**
616
+	 * Gets the event that's related to the ticket, if this line item represents a ticket.
617
+	 *
618
+	 * @return EE_Event|null
619
+	 * @throws EE_Error
620
+	 */
621
+	public function ticket_event()
622
+	{
623
+		$event = null;
624
+		$ticket = $this->ticket();
625
+		if ($ticket instanceof EE_Ticket) {
626
+			$datetime = $ticket->first_datetime();
627
+			if ($datetime instanceof EE_Datetime) {
628
+				$event = $datetime->event();
629
+			}
630
+		}
631
+		return $event;
632
+	}
633
+
634
+
635
+	/**
636
+	 * Gets the first datetime for this lien item, assuming it's for a ticket
637
+	 *
638
+	 * @param string $date_format
639
+	 * @param string $time_format
640
+	 * @return string
641
+	 * @throws EE_Error
642
+	 */
643
+	public function ticket_datetime_start($date_format = '', $time_format = '')
644
+	{
645
+		$first_datetime_string = esc_html__('Unknown', 'event_espresso');
646
+		$datetime = $this->get_ticket_datetime();
647
+		if ($datetime) {
648
+			$first_datetime_string = $datetime->start_date_and_time($date_format, $time_format);
649
+		}
650
+		return $first_datetime_string;
651
+	}
652
+
653
+
654
+	/**
655
+	 * Adds the line item as a child to this line item. If there is another child line
656
+	 * item with the same LIN_code, it is overwritten by this new one
657
+	 *
658
+	 * @param EEI_Line_Item $line_item
659
+	 * @param bool $set_order
660
+	 * @return bool success
661
+	 * @throws EE_Error
662
+	 */
663
+	public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true)
664
+	{
665
+		// should we calculate the LIN_order for this line item ?
666
+		if ($set_order || $line_item->order() === null) {
667
+			$line_item->set_order(count($this->children()));
668
+		}
669
+		if ($this->ID()) {
670
+			//check for any duplicate line items (with the same code), if so, this replaces it
671
+			$line_item_with_same_code = $this->get_child_line_item($line_item->code());
672
+			if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) {
673
+				$this->delete_child_line_item($line_item_with_same_code->code());
674
+			}
675
+			$line_item->set_parent_ID($this->ID());
676
+			if ($this->TXN_ID()) {
677
+				$line_item->set_TXN_ID($this->TXN_ID());
678
+			}
679
+			return $line_item->save();
680
+		}
681
+		$this->_children[$line_item->code()] = $line_item;
682
+		if ($line_item->parent() !== $this) {
683
+			$line_item->set_parent($this);
684
+		}
685
+		return true;
686
+	}
687
+
688
+
689
+	/**
690
+	 * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation.
691
+	 * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save()
692
+	 * However, if this line item is NOT saved to the DB, this just caches the parent on
693
+	 * the EE_Line_Item::_parent property.
694
+	 *
695
+	 * @param EE_Line_Item $line_item
696
+	 * @throws EE_Error
697
+	 */
698
+	public function set_parent($line_item)
699
+	{
700
+		if ($this->ID()) {
701
+			if (!$line_item->ID()) {
702
+				$line_item->save();
703
+			}
704
+			$this->set_parent_ID($line_item->ID());
705
+			$this->save();
706
+		} else {
707
+			$this->_parent = $line_item;
708
+			$this->set_parent_ID($line_item->ID());
709
+		}
710
+	}
711
+
712
+
713
+	/**
714
+	 * Gets the child line item as specified by its code. Because this returns an object (by reference)
715
+	 * you can modify this child line item and the parent (this object) can know about them
716
+	 * because it also has a reference to that line item
717
+	 *
718
+	 * @param string $code
719
+	 * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
720
+	 * @throws EE_Error
721
+	 */
722
+	public function get_child_line_item($code)
723
+	{
724
+		if ($this->ID()) {
725
+			return $this->get_model()->get_one(
726
+				array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
727
+			);
728
+		}
729
+		return isset($this->_children[$code])
730
+			? $this->_children[$code]
731
+			: null;
732
+	}
733
+
734
+
735
+	/**
736
+	 * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD
737
+	 * cached on it)
738
+	 *
739
+	 * @return int
740
+	 * @throws EE_Error
741
+	 */
742
+	public function delete_children_line_items()
743
+	{
744
+		if ($this->ID()) {
745
+			return $this->get_model()->delete(array(array('LIN_parent' => $this->ID())));
746
+		}
747
+		$count = count($this->_children);
748
+		$this->_children = array();
749
+		return $count;
750
+	}
751
+
752
+
753
+	/**
754
+	 * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line
755
+	 * HAS NOT been saved to the DB, removes the child line item with index $code.
756
+	 * Also searches through the child's children for a matching line item. However, once a line item has been found
757
+	 * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be
758
+	 * deleted)
759
+	 *
760
+	 * @param string $code
761
+	 * @param bool $stop_search_once_found
762
+	 * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to
763
+	 *             the DB yet)
764
+	 * @throws EE_Error
765
+	 */
766
+	public function delete_child_line_item($code, $stop_search_once_found = true)
767
+	{
768
+		if ($this->ID()) {
769
+			$items_deleted = 0;
770
+			if ($this->code() === $code) {
771
+				$items_deleted += EEH_Line_Item::delete_all_child_items($this);
772
+				$items_deleted += (int)$this->delete();
773
+				if ($stop_search_once_found) {
774
+					return $items_deleted;
775
+				}
776
+			}
777
+			foreach ($this->children() as $child_line_item) {
778
+				$items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found);
779
+			}
780
+			return $items_deleted;
781
+		}
782
+		if (isset($this->_children[$code])) {
783
+			unset($this->_children[$code]);
784
+			return 1;
785
+		}
786
+		return 0;
787
+	}
788
+
789
+
790
+	/**
791
+	 * If this line item is in the database, is of the type subtotal, and
792
+	 * has no children, why do we have it? It should be deleted so this function
793
+	 * does that
794
+	 *
795
+	 * @return boolean
796
+	 * @throws EE_Error
797
+	 */
798
+	public function delete_if_childless_subtotal()
799
+	{
800
+		if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && !$this->children()) {
801
+			return $this->delete();
802
+		}
803
+		return false;
804
+	}
805
+
806
+
807
+	/**
808
+	 * Creates a code and returns a string. doesn't assign the code to this model object
809
+	 *
810
+	 * @return string
811
+	 * @throws EE_Error
812
+	 */
813
+	public function generate_code()
814
+	{
815
+		// each line item in the cart requires a unique identifier
816
+		return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
817
+	}
818
+
819
+
820
+	/**
821
+	 * @return bool
822
+	 * @throws EE_Error
823
+	 */
824
+	public function is_tax()
825
+	{
826
+		return $this->type() === EEM_Line_Item::type_tax;
827
+	}
828
+
829
+
830
+	/**
831
+	 * @return bool
832
+	 * @throws EE_Error
833
+	 */
834
+	public function is_tax_sub_total()
835
+	{
836
+		return $this->type() === EEM_Line_Item::type_tax_sub_total;
837
+	}
838
+
839
+
840
+	/**
841
+	 * @return bool
842
+	 * @throws EE_Error
843
+	 */
844
+	public function is_line_item()
845
+	{
846
+		return $this->type() === EEM_Line_Item::type_line_item;
847
+	}
848
+
849
+
850
+	/**
851
+	 * @return bool
852
+	 * @throws EE_Error
853
+	 */
854
+	public function is_sub_line_item()
855
+	{
856
+		return $this->type() === EEM_Line_Item::type_sub_line_item;
857
+	}
858
+
859
+
860
+	/**
861
+	 * @return bool
862
+	 * @throws EE_Error
863
+	 */
864
+	public function is_sub_total()
865
+	{
866
+		return $this->type() === EEM_Line_Item::type_sub_total;
867
+	}
868
+
869
+
870
+	/**
871
+	 * Whether or not this line item is a cancellation line item
872
+	 *
873
+	 * @return boolean
874
+	 * @throws EE_Error
875
+	 */
876
+	public function is_cancellation()
877
+	{
878
+		return EEM_Line_Item::type_cancellation === $this->type();
879
+	}
880
+
881
+
882
+	/**
883
+	 * @return bool
884
+	 * @throws EE_Error
885
+	 */
886
+	public function is_total()
887
+	{
888
+		return $this->type() === EEM_Line_Item::type_total;
889
+	}
890
+
891
+
892
+	/**
893
+	 * @return bool
894
+	 * @throws EE_Error
895
+	 */
896
+	public function is_cancelled()
897
+	{
898
+		return $this->type() === EEM_Line_Item::type_cancellation;
899
+	}
900
+
901
+
902
+	/**
903
+	 * @return string like '2, 004.00', formatted according to the localized currency
904
+	 * @throws EE_Error
905
+	 */
906
+	public function unit_price_no_code()
907
+	{
908
+		return $this->get_pretty('LIN_unit_price', 'no_currency_code');
909
+	}
910
+
911
+
912
+	/**
913
+	 * @return string like '2, 004.00', formatted according to the localized currency
914
+	 * @throws EE_Error
915
+	 */
916
+	public function total_no_code()
917
+	{
918
+		return $this->get_pretty('LIN_total', 'no_currency_code');
919
+	}
920
+
921
+
922
+	/**
923
+	 * Gets the final total on this item, taking taxes into account.
924
+	 * Has the side-effect of setting the sub-total as it was just calculated.
925
+	 * If this is used on a grand-total line item, also updates the transaction's
926
+	 * TXN_total (provided this line item is allowed to persist, otherwise we don't
927
+	 * want to change a persistable transaction with info from a non-persistent line item)
928
+	 *
929
+	 * @return float
930
+	 * @throws EE_Error
931
+	 * @throws InvalidArgumentException
932
+	 * @throws InvalidInterfaceException
933
+	 * @throws InvalidDataTypeException
934
+	 */
935
+	public function recalculate_total_including_taxes()
936
+	{
937
+		$pre_tax_total = $this->recalculate_pre_tax_total();
938
+		$tax_total = $this->recalculate_taxes_and_tax_total();
939
+		$total = $pre_tax_total + $tax_total;
940
+		// no negative totals plz
941
+		$total = max($total, 0);
942
+		$this->set_total($total);
943
+		//only update the related transaction's total
944
+		//if we intend to save this line item and its a grand total
945
+		if (
946
+			$this->allow_persist() && $this->type() === EEM_Line_Item::type_total
947
+			&& $this->transaction()
948
+			instanceof
949
+			EE_Transaction
950
+		) {
951
+			$this->transaction()->set_total($total);
952
+			if ($this->transaction()->ID()) {
953
+				$this->transaction()->save();
954
+			}
955
+		}
956
+		$this->maybe_save();
957
+		return $total;
958
+	}
959
+
960
+
961
+	/**
962
+	 * Recursively goes through all the children and recalculates sub-totals EXCEPT for
963
+	 * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its
964
+	 * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
965
+	 * when this is called on the grand total
966
+	 *
967
+	 * @return float
968
+	 * @throws InvalidArgumentException
969
+	 * @throws InvalidInterfaceException
970
+	 * @throws InvalidDataTypeException
971
+	 * @throws EE_Error
972
+	 */
973
+	public function recalculate_pre_tax_total()
974
+	{
975
+		$total = 0;
976
+		$my_children = $this->children();
977
+		$has_children = !empty($my_children);
978
+		if ($has_children && $this->is_line_item()) {
979
+			$total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
980
+		} elseif (!$has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
981
+			$total = $this->unit_price() * $this->quantity();
982
+		} elseif ($this->is_sub_total() || $this->is_total()) {
983
+			$total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
984
+		} elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) {
985
+			// completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total
986
+			return 0;
987
+		}
988
+		// ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
989
+		if (
990
+			!$this->is_line_item() && !$this->is_sub_line_item() && !$this->is_cancellation()
991
+		) {
992
+			if ($this->OBJ_type() !== 'Event') {
993
+				$this->set_quantity(1);
994
+			}
995
+			if (!$this->is_percent()) {
996
+				$this->set_unit_price($total);
997
+			}
998
+		}
999
+		//we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1000
+		//so it ought to be
1001
+		if (!$this->is_total()) {
1002
+			$this->set_total($total);
1003
+			//if not a percent line item, make sure we keep the unit price in sync
1004
+			if (
1005
+				$has_children
1006
+				&& $this->is_line_item()
1007
+				&& !$this->is_percent()
1008
+			) {
1009
+				if ($this->quantity() === 0) {
1010
+					$new_unit_price = 0;
1011
+				} else {
1012
+					$new_unit_price = $this->total() / $this->quantity();
1013
+				}
1014
+				$this->set_unit_price($new_unit_price);
1015
+			}
1016
+			$this->maybe_save();
1017
+		}
1018
+		return $total;
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * Calculates the pretax total when this line item is a subtotal or total line item.
1024
+	 * Basically does a sum-then-round approach (ie, any percent line item that are children
1025
+	 * will calculate their total based on the un-rounded total we're working with so far, and
1026
+	 * THEN round the result; instead of rounding as we go like with sub-line-items)
1027
+	 *
1028
+	 * @param float $calculated_total_so_far
1029
+	 * @param EE_Line_Item[] $my_children
1030
+	 * @return float
1031
+	 * @throws InvalidArgumentException
1032
+	 * @throws InvalidInterfaceException
1033
+	 * @throws InvalidDataTypeException
1034
+	 * @throws EE_Error
1035
+	 */
1036
+	protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null)
1037
+	{
1038
+		if ($my_children === null) {
1039
+			$my_children = $this->children();
1040
+		}
1041
+		$subtotal_quantity = 0;
1042
+		//get the total of all its children
1043
+		foreach ($my_children as $child_line_item) {
1044
+			if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) {
1045
+				// percentage line items are based on total so far
1046
+				if ($child_line_item->is_percent()) {
1047
+					//round as we go so that the line items add up ok
1048
+					$percent_total = round(
1049
+						$calculated_total_so_far * $child_line_item->percent() / 100,
1050
+						EE_Registry::instance()->CFG->currency->dec_plc
1051
+					);
1052
+					$child_line_item->set_total($percent_total);
1053
+					//so far all percent line items should have a quantity of 1
1054
+					//(ie, no double percent discounts. Although that might be requested someday)
1055
+					$child_line_item->set_quantity(1);
1056
+					$child_line_item->maybe_save();
1057
+					$calculated_total_so_far += $percent_total;
1058
+				} else {
1059
+					//verify flat sub-line-item quantities match their parent
1060
+					if ($child_line_item->is_sub_line_item()) {
1061
+						$child_line_item->set_quantity($this->quantity());
1062
+					}
1063
+					$calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1064
+					$subtotal_quantity += $child_line_item->quantity();
1065
+				}
1066
+			}
1067
+		}
1068
+		if ($this->is_sub_total()) {
1069
+			// no negative totals plz
1070
+			$calculated_total_so_far = max($calculated_total_so_far, 0);
1071
+			$subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0;
1072
+			$this->set_quantity($subtotal_quantity);
1073
+			$this->maybe_save();
1074
+		}
1075
+		return $calculated_total_so_far;
1076
+	}
1077
+
1078
+
1079
+	/**
1080
+	 * Calculates the pretax total for a normal line item, in a round-then-sum approach
1081
+	 * (where each sub-line-item is applied to the base price for the line item
1082
+	 * and the result is immediately rounded, rather than summing all the sub-line-items
1083
+	 * then rounding, like we do when recalculating pretax totals on totals and subtotals).
1084
+	 *
1085
+	 * @param float $calculated_total_so_far
1086
+	 * @param EE_Line_Item[] $my_children
1087
+	 * @return float
1088
+	 * @throws InvalidArgumentException
1089
+	 * @throws InvalidInterfaceException
1090
+	 * @throws InvalidDataTypeException
1091
+	 * @throws EE_Error
1092
+	 */
1093
+	protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null)
1094
+	{
1095
+		if ($my_children === null) {
1096
+			$my_children = $this->children();
1097
+		}
1098
+		//we need to keep track of the running total for a single item,
1099
+		//because we need to round as we go
1100
+		$unit_price_for_total = 0;
1101
+		$quantity_for_total = 1;
1102
+		//get the total of all its children
1103
+		foreach ($my_children as $child_line_item) {
1104
+			if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) {
1105
+				if ($child_line_item->is_percent()) {
1106
+					//it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1107
+					//not total multiplied by percent, because that ignores rounding along-the-way
1108
+					$percent_unit_price = round(
1109
+						$unit_price_for_total * $child_line_item->percent() / 100,
1110
+						EE_Registry::instance()->CFG->currency->dec_plc
1111
+					);
1112
+					$percent_total = $percent_unit_price * $quantity_for_total;
1113
+					$child_line_item->set_total($percent_total);
1114
+					//so far all percent line items should have a quantity of 1
1115
+					//(ie, no double percent discounts. Although that might be requested someday)
1116
+					$child_line_item->set_quantity(1);
1117
+					$child_line_item->maybe_save();
1118
+					$calculated_total_so_far += $percent_total;
1119
+					$unit_price_for_total += $percent_unit_price;
1120
+				} else {
1121
+					//verify flat sub-line-item quantities match their parent
1122
+					if ($child_line_item->is_sub_line_item()) {
1123
+						$child_line_item->set_quantity($this->quantity());
1124
+					}
1125
+					$quantity_for_total = $child_line_item->quantity();
1126
+					$calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1127
+					$unit_price_for_total += $child_line_item->unit_price();
1128
+				}
1129
+			}
1130
+		}
1131
+		return $calculated_total_so_far;
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
1137
+	 * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
1138
+	 * and tax sub-total if already in the DB
1139
+	 *
1140
+	 * @return float
1141
+	 * @throws EE_Error
1142
+	 */
1143
+	public function recalculate_taxes_and_tax_total()
1144
+	{
1145
+		//get all taxes
1146
+		$taxes = $this->tax_descendants();
1147
+		//calculate the pretax total
1148
+		$taxable_total = $this->taxable_total();
1149
+		$tax_total = 0;
1150
+		foreach ($taxes as $tax) {
1151
+			$total_on_this_tax = $taxable_total * $tax->percent() / 100;
1152
+			//remember the total on this line item
1153
+			$tax->set_total($total_on_this_tax);
1154
+			$tax->maybe_save();
1155
+			$tax_total += $tax->total();
1156
+		}
1157
+		$this->_recalculate_tax_sub_total();
1158
+		return $tax_total;
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
1164
+	 *
1165
+	 * @return void
1166
+	 * @throws EE_Error
1167
+	 */
1168
+	private function _recalculate_tax_sub_total()
1169
+	{
1170
+		if ($this->is_tax_sub_total()) {
1171
+			$total = 0;
1172
+			$total_percent = 0;
1173
+			//simply loop through all its children (which should be taxes) and sum their total
1174
+			foreach ($this->children() as $child_tax) {
1175
+				if ($child_tax instanceof EE_Line_Item) {
1176
+					$total += $child_tax->total();
1177
+					$total_percent += $child_tax->percent();
1178
+				}
1179
+			}
1180
+			$this->set_total($total);
1181
+			$this->set_percent($total_percent);
1182
+			$this->maybe_save();
1183
+		} elseif ($this->is_total()) {
1184
+			foreach ($this->children() as $maybe_tax_subtotal) {
1185
+				if ($maybe_tax_subtotal instanceof EE_Line_Item) {
1186
+					$maybe_tax_subtotal->_recalculate_tax_sub_total();
1187
+				}
1188
+			}
1189
+		}
1190
+	}
1191
+
1192
+
1193
+	/**
1194
+	 * Gets the total tax on this line item. Assumes taxes have already been calculated using
1195
+	 * recalculate_taxes_and_total
1196
+	 *
1197
+	 * @return float
1198
+	 * @throws EE_Error
1199
+	 */
1200
+	public function get_total_tax()
1201
+	{
1202
+		$this->_recalculate_tax_sub_total();
1203
+		$total = 0;
1204
+		foreach ($this->tax_descendants() as $tax_line_item) {
1205
+			if ($tax_line_item instanceof EE_Line_Item) {
1206
+				$total += $tax_line_item->total();
1207
+			}
1208
+		}
1209
+		return $total;
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * Gets the total for all the items purchased only
1215
+	 *
1216
+	 * @return float
1217
+	 * @throws EE_Error
1218
+	 */
1219
+	public function get_items_total()
1220
+	{
1221
+		//by default, let's make sure we're consistent with the existing line item
1222
+		if ($this->is_total()) {
1223
+			$pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this);
1224
+			if ($pretax_subtotal_li instanceof EE_Line_Item) {
1225
+				return $pretax_subtotal_li->total();
1226
+			}
1227
+		}
1228
+		$total = 0;
1229
+		foreach ($this->get_items() as $item) {
1230
+			if ($item instanceof EE_Line_Item) {
1231
+				$total += $item->total();
1232
+			}
1233
+		}
1234
+		return $total;
1235
+	}
1236
+
1237
+
1238
+	/**
1239
+	 * Gets all the descendants (ie, children or children of children etc) that
1240
+	 * are of the type 'tax'
1241
+	 *
1242
+	 * @return EE_Line_Item[]
1243
+	 */
1244
+	public function tax_descendants()
1245
+	{
1246
+		return EEH_Line_Item::get_tax_descendants($this);
1247
+	}
1248
+
1249
+
1250
+	/**
1251
+	 * Gets all the real items purchased which are children of this item
1252
+	 *
1253
+	 * @return EE_Line_Item[]
1254
+	 */
1255
+	public function get_items()
1256
+	{
1257
+		return EEH_Line_Item::get_line_item_descendants($this);
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * Returns the amount taxable among this line item's children (or if it has no children,
1263
+	 * how much of it is taxable). Does not recalculate totals or subtotals.
1264
+	 * If the taxable total is negative, (eg, if none of the tickets were taxable,
1265
+	 * but there is a "Taxable" discount), returns 0.
1266
+	 *
1267
+	 * @return float
1268
+	 * @throws EE_Error
1269
+	 */
1270
+	public function taxable_total()
1271
+	{
1272
+		$total = 0;
1273
+		if ($this->children()) {
1274
+			foreach ($this->children() as $child_line_item) {
1275
+				if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) {
1276
+					//if it's a percent item, only take into account the percent
1277
+					//that's taxable too (the taxable total so far)
1278
+					if ($child_line_item->is_percent()) {
1279
+						$total += ($total * $child_line_item->percent() / 100);
1280
+					} else {
1281
+						$total += $child_line_item->total();
1282
+					}
1283
+				} elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) {
1284
+					$total += $child_line_item->taxable_total();
1285
+				}
1286
+			}
1287
+		}
1288
+		return max($total, 0);
1289
+	}
1290
+
1291
+
1292
+	/**
1293
+	 * Gets the transaction for this line item
1294
+	 *
1295
+	 * @return EE_Base_Class|EE_Transaction
1296
+	 * @throws EE_Error
1297
+	 */
1298
+	public function transaction()
1299
+	{
1300
+		return $this->get_first_related('Transaction');
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * Saves this line item to the DB, and recursively saves its descendants.
1306
+	 * Because there currently is no proper parent-child relation on the model,
1307
+	 * save_this_and_cached() will NOT save the descendants.
1308
+	 * Also sets the transaction on this line item and all its descendants before saving
1309
+	 *
1310
+	 * @param int $txn_id if none is provided, assumes $this->TXN_ID()
1311
+	 * @return int count of items saved
1312
+	 * @throws EE_Error
1313
+	 */
1314
+	public function save_this_and_descendants_to_txn($txn_id = null)
1315
+	{
1316
+		$count = 0;
1317
+		if (!$txn_id) {
1318
+			$txn_id = $this->TXN_ID();
1319
+		}
1320
+		$this->set_TXN_ID($txn_id);
1321
+		$children = $this->children();
1322
+		$count += $this->save()
1323
+			? 1
1324
+			: 0;
1325
+		foreach ($children as $child_line_item) {
1326
+			if ($child_line_item instanceof EE_Line_Item) {
1327
+				$child_line_item->set_parent_ID($this->ID());
1328
+				$count += $child_line_item->save_this_and_descendants_to_txn($txn_id);
1329
+			}
1330
+		}
1331
+		return $count;
1332
+	}
1333
+
1334
+
1335
+	/**
1336
+	 * Saves this line item to the DB, and recursively saves its descendants.
1337
+	 *
1338
+	 * @return int count of items saved
1339
+	 * @throws EE_Error
1340
+	 */
1341
+	public function save_this_and_descendants()
1342
+	{
1343
+		$count = 0;
1344
+		$children = $this->children();
1345
+		$count += $this->save()
1346
+			? 1
1347
+			: 0;
1348
+		foreach ($children as $child_line_item) {
1349
+			if ($child_line_item instanceof EE_Line_Item) {
1350
+				$child_line_item->set_parent_ID($this->ID());
1351
+				$count += $child_line_item->save_this_and_descendants();
1352
+			}
1353
+		}
1354
+		return $count;
1355
+	}
1356
+
1357
+
1358
+	/**
1359
+	 * returns the cancellation line item if this item was cancelled
1360
+	 *
1361
+	 * @return EE_Line_Item[]
1362
+	 * @throws InvalidArgumentException
1363
+	 * @throws InvalidInterfaceException
1364
+	 * @throws InvalidDataTypeException
1365
+	 * @throws ReflectionException
1366
+	 * @throws EE_Error
1367
+	 */
1368
+	public function get_cancellations()
1369
+	{
1370
+		EE_Registry::instance()->load_helper('Line_Item');
1371
+		return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation);
1372
+	}
1373
+
1374
+
1375
+	/**
1376
+	 * If this item has an ID, then this saves it again to update the db
1377
+	 *
1378
+	 * @return int count of items saved
1379
+	 * @throws EE_Error
1380
+	 */
1381
+	public function maybe_save()
1382
+	{
1383
+		if ($this->ID()) {
1384
+			return $this->save();
1385
+		}
1386
+		return false;
1387
+	}
1388
+
1389
+
1390
+	/**
1391
+	 * clears the cached children and parent from the line item
1392
+	 *
1393
+	 * @return void
1394
+	 */
1395
+	public function clear_related_line_item_cache()
1396
+	{
1397
+		$this->_children = array();
1398
+		$this->_parent = null;
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * @param bool $raw
1404
+	 * @return int
1405
+	 * @throws EE_Error
1406
+	 */
1407
+	public function timestamp($raw = false)
1408
+	{
1409
+		return $raw
1410
+			? $this->get_raw('LIN_timestamp')
1411
+			: $this->get('LIN_timestamp');
1412
+	}
1413
+
1414
+
1415
+
1416
+
1417
+	/************************* DEPRECATED *************************/
1418
+	/**
1419
+	 * @deprecated 4.6.0
1420
+	 * @param string $type one of the constants on EEM_Line_Item
1421
+	 * @return EE_Line_Item[]
1422
+	 */
1423
+	protected function _get_descendants_of_type($type)
1424
+	{
1425
+		EE_Error::doing_it_wrong(
1426
+			'EE_Line_Item::_get_descendants_of_type()',
1427
+			__('Method replaced with EEH_Line_Item::get_descendants_of_type()', 'event_espresso'), '4.6.0'
1428
+		);
1429
+		return EEH_Line_Item::get_descendants_of_type($this, $type);
1430
+	}
1431
+
1432
+
1433
+	/**
1434
+	 * @deprecated 4.6.0
1435
+	 * @param string $type like one of the EEM_Line_Item::type_*
1436
+	 * @return EE_Line_Item
1437
+	 */
1438
+	public function get_nearest_descendant_of_type($type)
1439
+	{
1440
+		EE_Error::doing_it_wrong(
1441
+			'EE_Line_Item::get_nearest_descendant_of_type()',
1442
+			__('Method replaced with EEH_Line_Item::get_nearest_descendant_of_type()', 'event_espresso'), '4.6.0'
1443
+		);
1444
+		return EEH_Line_Item::get_nearest_descendant_of_type($this, $type);
1445
+	}
1446 1446
 
1447 1447
 
1448 1448
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
     protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
76 76
     {
77 77
         parent::__construct($fieldValues, $bydb, $timezone);
78
-        if (!$this->get('LIN_code')) {
78
+        if ( ! $this->get('LIN_code')) {
79 79
             $this->set_code($this->generate_code());
80 80
         }
81 81
     }
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
     public function name()
127 127
     {
128 128
         $name = $this->get('LIN_name');
129
-        if (!$name) {
129
+        if ( ! $name) {
130 130
             $name = ucwords(str_replace('-', ' ', $this->type()));
131 131
         }
132 132
         return $name;
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
         if ($unit_price < .001 && $percent) {
314 314
             return true;
315 315
         }
316
-        if ($unit_price >= .001 && !$percent) {
316
+        if ($unit_price >= .001 && ! $percent) {
317 317
             return false;
318 318
         }
319 319
         if ($unit_price >= .001 && $percent) {
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
                 )
483 483
             );
484 484
         }
485
-        if (!is_array($this->_children)) {
485
+        if ( ! is_array($this->_children)) {
486 486
             $this->_children = array();
487 487
         }
488 488
         return $this->_children;
@@ -698,7 +698,7 @@  discard block
 block discarded – undo
698 698
     public function set_parent($line_item)
699 699
     {
700 700
         if ($this->ID()) {
701
-            if (!$line_item->ID()) {
701
+            if ( ! $line_item->ID()) {
702 702
                 $line_item->save();
703 703
             }
704 704
             $this->set_parent_ID($line_item->ID());
@@ -769,7 +769,7 @@  discard block
 block discarded – undo
769 769
             $items_deleted = 0;
770 770
             if ($this->code() === $code) {
771 771
                 $items_deleted += EEH_Line_Item::delete_all_child_items($this);
772
-                $items_deleted += (int)$this->delete();
772
+                $items_deleted += (int) $this->delete();
773 773
                 if ($stop_search_once_found) {
774 774
                     return $items_deleted;
775 775
                 }
@@ -797,7 +797,7 @@  discard block
 block discarded – undo
797 797
      */
798 798
     public function delete_if_childless_subtotal()
799 799
     {
800
-        if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && !$this->children()) {
800
+        if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) {
801 801
             return $this->delete();
802 802
         }
803 803
         return false;
@@ -813,7 +813,7 @@  discard block
 block discarded – undo
813 813
     public function generate_code()
814 814
     {
815 815
         // each line item in the cart requires a unique identifier
816
-        return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
816
+        return md5($this->get('OBJ_type').$this->get('OBJ_ID').microtime());
817 817
     }
818 818
 
819 819
 
@@ -974,10 +974,10 @@  discard block
 block discarded – undo
974 974
     {
975 975
         $total = 0;
976 976
         $my_children = $this->children();
977
-        $has_children = !empty($my_children);
977
+        $has_children = ! empty($my_children);
978 978
         if ($has_children && $this->is_line_item()) {
979 979
             $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
980
-        } elseif (!$has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
980
+        } elseif ( ! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
981 981
             $total = $this->unit_price() * $this->quantity();
982 982
         } elseif ($this->is_sub_total() || $this->is_total()) {
983 983
             $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
@@ -987,24 +987,24 @@  discard block
 block discarded – undo
987 987
         }
988 988
         // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
989 989
         if (
990
-            !$this->is_line_item() && !$this->is_sub_line_item() && !$this->is_cancellation()
990
+            ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation()
991 991
         ) {
992 992
             if ($this->OBJ_type() !== 'Event') {
993 993
                 $this->set_quantity(1);
994 994
             }
995
-            if (!$this->is_percent()) {
995
+            if ( ! $this->is_percent()) {
996 996
                 $this->set_unit_price($total);
997 997
             }
998 998
         }
999 999
         //we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1000 1000
         //so it ought to be
1001
-        if (!$this->is_total()) {
1001
+        if ( ! $this->is_total()) {
1002 1002
             $this->set_total($total);
1003 1003
             //if not a percent line item, make sure we keep the unit price in sync
1004 1004
             if (
1005 1005
                 $has_children
1006 1006
                 && $this->is_line_item()
1007
-                && !$this->is_percent()
1007
+                && ! $this->is_percent()
1008 1008
             ) {
1009 1009
                 if ($this->quantity() === 0) {
1010 1010
                     $new_unit_price = 0;
@@ -1041,7 +1041,7 @@  discard block
 block discarded – undo
1041 1041
         $subtotal_quantity = 0;
1042 1042
         //get the total of all its children
1043 1043
         foreach ($my_children as $child_line_item) {
1044
-            if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) {
1044
+            if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1045 1045
                 // percentage line items are based on total so far
1046 1046
                 if ($child_line_item->is_percent()) {
1047 1047
                     //round as we go so that the line items add up ok
@@ -1101,7 +1101,7 @@  discard block
 block discarded – undo
1101 1101
         $quantity_for_total = 1;
1102 1102
         //get the total of all its children
1103 1103
         foreach ($my_children as $child_line_item) {
1104
-            if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) {
1104
+            if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1105 1105
                 if ($child_line_item->is_percent()) {
1106 1106
                     //it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1107 1107
                     //not total multiplied by percent, because that ignores rounding along-the-way
@@ -1314,7 +1314,7 @@  discard block
 block discarded – undo
1314 1314
     public function save_this_and_descendants_to_txn($txn_id = null)
1315 1315
     {
1316 1316
         $count = 0;
1317
-        if (!$txn_id) {
1317
+        if ( ! $txn_id) {
1318 1318
             $txn_id = $this->TXN_ID();
1319 1319
         }
1320 1320
         $this->set_TXN_ID($txn_id);
Please login to merge, or discard this patch.
core/EE_Data_Migration_Manager.core.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -3,7 +3,6 @@
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\InvalidDataTypeException;
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5 5
 use EventEspresso\core\interfaces\ResettableInterface;
6
-
7 6
 use EventEspresso\core\services\database\TableManager;
8 7
 use EventEspresso\core\services\database\TableAnalysis;
9 8
 
Please login to merge, or discard this patch.
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -136,9 +136,9 @@  discard block
 block discarded – undo
136 136
 	protected $script_migration_versions;
137 137
 
138 138
 	/**
139
-     * 	@var EE_Data_Migration_Manager $_instance
139
+	 * 	@var EE_Data_Migration_Manager $_instance
140 140
 	 * 	@access 	private
141
-     */
141
+	 */
142 142
 	private static $_instance = NULL;
143 143
 
144 144
 
@@ -322,9 +322,9 @@  discard block
 block discarded – undo
322 322
 	 */
323 323
 	public function get_data_migration_script_folders(){
324 324
 		return  apply_filters(
325
-		    'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
326
-            array('Core' => EE_CORE.'data_migration_scripts')
327
-        );
325
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
326
+			array('Core' => EE_CORE.'data_migration_scripts')
327
+		);
328 328
 	}
329 329
 
330 330
 	/**
@@ -337,15 +337,15 @@  discard block
 block discarded – undo
337 337
 	 * @throws EE_Error
338 338
 	 */
339 339
 	public function script_migrates_to_version($migration_script_name, $eeAddonClass = ''){
340
-	    if(isset($this->script_migration_versions[ $migration_script_name ])){
341
-	        return $this->script_migration_versions[ $migration_script_name ];
342
-        }
340
+		if(isset($this->script_migration_versions[ $migration_script_name ])){
341
+			return $this->script_migration_versions[ $migration_script_name ];
342
+		}
343 343
 		$dms_info = $this->parse_dms_classname($migration_script_name);
344
-        $this->script_migration_versions[ $migration_script_name ] = array(
344
+		$this->script_migration_versions[ $migration_script_name ] = array(
345 345
 			'slug'=> $eeAddonClass !== '' ? $eeAddonClass : $dms_info[ 'slug' ],
346 346
 			'version'=> $dms_info[ 'major_version' ] . "." . $dms_info[ 'minor_version' ] . "." . $dms_info[ 'micro_version' ]
347
-        );
348
-        return $this->script_migration_versions[ $migration_script_name ];
347
+		);
348
+		return $this->script_migration_versions[ $migration_script_name ];
349 349
 	}
350 350
 
351 351
 	/**
@@ -736,60 +736,60 @@  discard block
 block discarded – undo
736 736
 	}
737 737
 
738 738
 
739
-    /**
740
-     * Gets all the data migration scripts available in the core folder and folders
741
-     * in addons. Has the side effect of adding them for autoloading
742
-     *
743
-     * @return array keys are expected classnames, values are their filepaths
744
-     * @throws InvalidInterfaceException
745
-     * @throws InvalidDataTypeException
746
-     * @throws EE_Error
747
-     * @throws InvalidArgumentException
748
-     */
749
-    public function get_all_data_migration_scripts_available()
750
-    {
751
-        if (! $this->_data_migration_class_to_filepath_map) {
752
-            $this->_data_migration_class_to_filepath_map = array();
753
-            foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
754
-                // strip any placeholders added to classname to make it a unique array key
755
-                $eeAddonClass = trim($eeAddonClass, '*');
756
-                $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
757
-                    ? $eeAddonClass
758
-                    : '';
759
-                $folder_path  = EEH_File::end_with_directory_separator($folder_path);
760
-                $files        = glob($folder_path . '*.dms.php');
761
-                if (empty($files)) {
762
-                    continue;
763
-                }
764
-                foreach ($files as $file) {
765
-                    $pos_of_last_slash = strrpos($file, DS);
766
-                    $classname         = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
767
-                    $migrates_to       = $this->script_migrates_to_version($classname, $eeAddonClass);
768
-                    $slug              = $migrates_to['slug'];
769
-                    //check that the slug as contained in the DMS is associated with
770
-                    //the slug of an addon or core
771
-                    if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
772
-                        EE_Error::doing_it_wrong(
773
-                            __FUNCTION__,
774
-                            sprintf(
775
-                                esc_html__(
776
-                                    'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
777
-                                    'event_espresso'
778
-                                ),
779
-                                $classname,
780
-                                $slug,
781
-                                implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
782
-                            ),
783
-                            '4.3.0.alpha.019'
784
-                        );
785
-                    }
786
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
787
-                }
788
-            }
789
-            EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
790
-        }
791
-        return $this->_data_migration_class_to_filepath_map;
792
-    }
739
+	/**
740
+	 * Gets all the data migration scripts available in the core folder and folders
741
+	 * in addons. Has the side effect of adding them for autoloading
742
+	 *
743
+	 * @return array keys are expected classnames, values are their filepaths
744
+	 * @throws InvalidInterfaceException
745
+	 * @throws InvalidDataTypeException
746
+	 * @throws EE_Error
747
+	 * @throws InvalidArgumentException
748
+	 */
749
+	public function get_all_data_migration_scripts_available()
750
+	{
751
+		if (! $this->_data_migration_class_to_filepath_map) {
752
+			$this->_data_migration_class_to_filepath_map = array();
753
+			foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
754
+				// strip any placeholders added to classname to make it a unique array key
755
+				$eeAddonClass = trim($eeAddonClass, '*');
756
+				$eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass)
757
+					? $eeAddonClass
758
+					: '';
759
+				$folder_path  = EEH_File::end_with_directory_separator($folder_path);
760
+				$files        = glob($folder_path . '*.dms.php');
761
+				if (empty($files)) {
762
+					continue;
763
+				}
764
+				foreach ($files as $file) {
765
+					$pos_of_last_slash = strrpos($file, DS);
766
+					$classname         = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1));
767
+					$migrates_to       = $this->script_migrates_to_version($classname, $eeAddonClass);
768
+					$slug              = $migrates_to['slug'];
769
+					//check that the slug as contained in the DMS is associated with
770
+					//the slug of an addon or core
771
+					if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) {
772
+						EE_Error::doing_it_wrong(
773
+							__FUNCTION__,
774
+							sprintf(
775
+								esc_html__(
776
+									'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ',
777
+									'event_espresso'
778
+								),
779
+								$classname,
780
+								$slug,
781
+								implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name()))
782
+							),
783
+							'4.3.0.alpha.019'
784
+						);
785
+					}
786
+					$this->_data_migration_class_to_filepath_map[ $classname ] = $file;
787
+				}
788
+			}
789
+			EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
790
+		}
791
+		return $this->_data_migration_class_to_filepath_map;
792
+	}
793 793
 
794 794
 
795 795
 
@@ -961,12 +961,12 @@  discard block
 block discarded – undo
961 961
 	}
962 962
 
963 963
 /**
964
-	 * Resets the borked data migration scripts so they're no longer borked
965
-	 * so we can again attempt to migrate
966
-	 *
967
-	 * @return bool
968
-	 * @throws EE_Error
969
-	 */
964
+ * Resets the borked data migration scripts so they're no longer borked
965
+ * so we can again attempt to migrate
966
+ *
967
+ * @return bool
968
+ * @throws EE_Error
969
+ */
970 970
 	public function reattempt(){
971 971
 		//find if the last-ran script was borked
972 972
 		//set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
Please login to merge, or discard this patch.
Spacing   +198 added lines, -198 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
 	 * of this EE installation. Keys should be the name of the version the script upgraded to
86 86
 	 * @var EE_Data_Migration_Script_Base[]
87 87
 	 */
88
-	private $_data_migrations_ran =null;
88
+	private $_data_migrations_ran = null;
89 89
 	/**
90 90
 	 * The last ran script. It's nice to store this somewhere accessible, as its easiest
91 91
 	 * to know which was the last run by which is the newest wp option; but in most of the code
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
 	 */
151 151
 	public static function instance() {
152 152
 		// check if class object is instantiated
153
-		if ( ! self::$_instance instanceof EE_Data_Migration_Manager ) {
153
+		if ( ! self::$_instance instanceof EE_Data_Migration_Manager) {
154 154
 			self::$_instance = new self();
155 155
 		}
156 156
 		return self::$_instance;
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
 	 * all new usages of the singleton should be made with Classname::instance()) and returns it
161 161
 	 * @return EE_Data_Migration_Manager
162 162
 	 */
163
-	public static function reset(){
163
+	public static function reset() {
164 164
 		self::$_instance = NULL;
165 165
 		return self::instance();
166 166
 	}
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 	/**
171 171
 	 * constructor
172 172
 	 */
173
-	private function __construct(){
173
+	private function __construct() {
174 174
 		$this->stati_that_indicate_to_continue_migrations = array(
175 175
 			self::status_continue,
176 176
 			self::status_completed
@@ -189,13 +189,13 @@  discard block
 block discarded – undo
189 189
 		);
190 190
 		//make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class
191 191
 		//to be defined, because right now it doesn't get autoloaded on its own
192
-		EE_Registry::instance()->load_core( 'Data_Migration_Class_Base', array(), TRUE );
193
-		EE_Registry::instance()->load_core( 'Data_Migration_Script_Base', array(), TRUE );
194
-		EE_Registry::instance()->load_core( 'DMS_Unknown_1_0_0', array(), TRUE );
195
-		EE_Registry::instance()->load_core( 'Data_Migration_Script_Stage', array(), TRUE );
196
-		EE_Registry::instance()->load_core( 'Data_Migration_Script_Stage_Table', array(), TRUE );
197
-		$this->_table_manager = EE_Registry::instance()->create( 'TableManager', array(), true );
198
-		$this->_table_analysis = EE_Registry::instance()->create( 'TableAnalysis', array(), true );
192
+		EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), TRUE);
193
+		EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), TRUE);
194
+		EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), TRUE);
195
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), TRUE);
196
+		EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), TRUE);
197
+		$this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true);
198
+		$this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
199 199
 	}
200 200
 
201 201
 
@@ -208,21 +208,21 @@  discard block
 block discarded – undo
208 208
 	 * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set)
209 209
 	 * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of that plugin (eg '4.1.0')
210 210
 	 */
211
-	private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name){
211
+	private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name) {
212 212
 		$plugin_slug_and_version_string = str_replace(EE_Data_Migration_Manager::data_migration_script_option_prefix, "", $option_name);
213 213
 		//check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style)
214
-		$parts = explode(".",$plugin_slug_and_version_string);
214
+		$parts = explode(".", $plugin_slug_and_version_string);
215 215
 
216
-		if(count($parts) == 4){
216
+		if (count($parts) == 4) {
217 217
 			//it's 4.2-style.eg Core.4.1.0
218
-			$plugin_slug = $parts[0];//eg Core
218
+			$plugin_slug = $parts[0]; //eg Core
219 219
 			$version_string = $parts[1].".".$parts[2].".".$parts[3]; //eg 4.1.0
220
-		}else{
220
+		} else {
221 221
 			//it's 4.1-style: eg 4.1.0
222 222
 			$plugin_slug = 'Core';
223
-			$version_string = $plugin_slug_and_version_string;//eg 4.1.0
223
+			$version_string = $plugin_slug_and_version_string; //eg 4.1.0
224 224
 		}
225
-		return array($plugin_slug,$version_string);
225
+		return array($plugin_slug, $version_string);
226 226
 	}
227 227
 
228 228
 	/**
@@ -233,21 +233,21 @@  discard block
 block discarded – undo
233 233
 	 * @return EE_Data_Migration_Script_Base
234 234
 	 * @throws EE_Error
235 235
 	 */
236
-	private function _get_dms_class_from_wp_option($dms_option_name,$dms_option_value){
236
+	private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value) {
237 237
 		$data_migration_data = maybe_unserialize($dms_option_value);
238
-		if(isset($data_migration_data['class']) && class_exists($data_migration_data['class'])){
238
+		if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) {
239 239
 			$class = new $data_migration_data['class'];
240
-			if($class instanceof EE_Data_Migration_Script_Base){
240
+			if ($class instanceof EE_Data_Migration_Script_Base) {
241 241
 				$class->instantiate_from_array_of_properties($data_migration_data);
242 242
 				return $class;
243
-			}else{
243
+			} else {
244 244
 				//huh, so its an object but not a data migration script?? that shouldn't happen
245 245
 				//just leave it as an array (which will probably just get ignored)
246
-				throw new EE_Error(sprintf(__("Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists", 'event_espresso'),$data_migration_data['class']));
246
+				throw new EE_Error(sprintf(__("Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists", 'event_espresso'), $data_migration_data['class']));
247 247
 			}
248
-		}else{
248
+		} else {
249 249
 			//so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists
250
-			throw new EE_Error(sprintf(__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'),$dms_option_name));
250
+			throw new EE_Error(sprintf(__("The wp option  with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name));
251 251
 		}
252 252
 	}
253 253
 	/**
@@ -255,34 +255,34 @@  discard block
 block discarded – undo
255 255
 	 * the last ran which hasn't finished yet
256 256
 	 * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy arrays in there - which should probably be ignored)
257 257
 	 */
258
-	public function get_data_migrations_ran(){
259
-		if( ! $this->_data_migrations_ran ){
258
+	public function get_data_migrations_ran() {
259
+		if ( ! $this->_data_migrations_ran) {
260 260
 			//setup autoloaders for each of the scripts in there
261 261
 			$this->get_all_data_migration_scripts_available();
262
-			$data_migrations_options = $this->get_all_migration_script_options();//get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
262
+			$data_migrations_options = $this->get_all_migration_script_options(); //get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array()));
263 263
 
264 264
 			$data_migrations_ran = array();
265 265
 			//convert into data migration script classes where possible
266
-			foreach($data_migrations_options as $data_migration_option){
267
-				list($plugin_slug,$version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name($data_migration_option['option_name']);
266
+			foreach ($data_migrations_options as $data_migration_option) {
267
+				list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name($data_migration_option['option_name']);
268 268
 
269
-				try{
270
-					$class = $this->_get_dms_class_from_wp_option($data_migration_option['option_name'],$data_migration_option['option_value']);
269
+				try {
270
+					$class = $this->_get_dms_class_from_wp_option($data_migration_option['option_name'], $data_migration_option['option_value']);
271 271
 					$data_migrations_ran[$plugin_slug][$version_string] = $class;
272 272
 					//ok so far THIS is the 'last-ran-script'... unless we find another on next iteration
273 273
 					$this->_last_ran_script = $class;
274
-					if( ! $class->is_completed()){
274
+					if ( ! $class->is_completed()) {
275 275
 						//sometimes we also like to know which was the last incomplete script (or if there are any at all)
276 276
 						$this->_last_ran_incomplete_script = $class;
277 277
 					}
278
-				}catch(EE_Error $e){
278
+				} catch (EE_Error $e) {
279 279
 					//ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs
280 280
 					$data_migrations_ran[$plugin_slug][$version_string] = maybe_unserialize($data_migration_option['option_value']);
281 281
 				}
282 282
 			}
283 283
 			//so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays
284 284
 			$this->_data_migrations_ran = $data_migrations_ran;
285
-			 if ( ! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran) ){
285
+			 if ( ! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) {
286 286
 				$this->_data_migrations_ran = array();
287 287
 			}
288 288
 		}
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
 	 * @param        $new_table
300 300
 	 * @return mixed string or int
301 301
 	 */
302
-	public function get_mapping_new_pk( $script_name, $old_table, $old_pk, $new_table){
302
+	public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table) {
303 303
 		$script = EE_Registry::instance()->load_dms($script_name);
304 304
 		$mapping = $script->get_mapping_new_pk($old_table, $old_pk, $new_table);
305 305
 		return $mapping;
@@ -310,9 +310,9 @@  discard block
 block discarded – undo
310 310
 	 * option returned in this array is the most-recently ran DMS option
311 311
 	 * @return array
312 312
 	 */
313
-	 public function get_all_migration_script_options(){
313
+	 public function get_all_migration_script_options() {
314 314
 		global $wpdb;
315
-		return $wpdb->get_results("SELECT * FROM {$wpdb->options} WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id ASC",ARRAY_A);
315
+		return $wpdb->get_results("SELECT * FROM {$wpdb->options} WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id ASC", ARRAY_A);
316 316
 	}
317 317
 
318 318
 	/**
@@ -320,7 +320,7 @@  discard block
 block discarded – undo
320 320
 	 * @return array where each value is the full folder path of a folder containing data migration scripts, WITH slashes at the end of the
321 321
 	 * folder name.
322 322
 	 */
323
-	public function get_data_migration_script_folders(){
323
+	public function get_data_migration_script_folders() {
324 324
 		return  apply_filters(
325 325
 		    'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
326 326
             array('Core' => EE_CORE.'data_migration_scripts')
@@ -336,16 +336,16 @@  discard block
 block discarded – undo
336 336
 	 * }
337 337
 	 * @throws EE_Error
338 338
 	 */
339
-	public function script_migrates_to_version($migration_script_name, $eeAddonClass = ''){
340
-	    if(isset($this->script_migration_versions[ $migration_script_name ])){
341
-	        return $this->script_migration_versions[ $migration_script_name ];
339
+	public function script_migrates_to_version($migration_script_name, $eeAddonClass = '') {
340
+	    if (isset($this->script_migration_versions[$migration_script_name])) {
341
+	        return $this->script_migration_versions[$migration_script_name];
342 342
         }
343 343
 		$dms_info = $this->parse_dms_classname($migration_script_name);
344
-        $this->script_migration_versions[ $migration_script_name ] = array(
345
-			'slug'=> $eeAddonClass !== '' ? $eeAddonClass : $dms_info[ 'slug' ],
346
-			'version'=> $dms_info[ 'major_version' ] . "." . $dms_info[ 'minor_version' ] . "." . $dms_info[ 'micro_version' ]
344
+        $this->script_migration_versions[$migration_script_name] = array(
345
+			'slug'=> $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'],
346
+			'version'=> $dms_info['major_version'].".".$dms_info['minor_version'].".".$dms_info['micro_version']
347 347
         );
348
-        return $this->script_migration_versions[ $migration_script_name ];
348
+        return $this->script_migration_versions[$migration_script_name];
349 349
 	}
350 350
 
351 351
 	/**
@@ -354,13 +354,13 @@  discard block
 block discarded – undo
354 354
 	 * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints)
355 355
 	 * @throws EE_Error
356 356
 	 */
357
-	public function parse_dms_classname($classname){
357
+	public function parse_dms_classname($classname) {
358 358
 		$matches = array();
359
-		preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~',$classname,$matches);
360
-		if( ! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))){
361
-				throw new EE_Error(sprintf(__("%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ", "event_espresso"),$classname));
359
+		preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches);
360
+		if ( ! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) {
361
+				throw new EE_Error(sprintf(__("%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ", "event_espresso"), $classname));
362 362
 		}
363
-		return array('slug'=>$matches[1],'major_version'=>intval($matches[2]),'minor_version'=>intval($matches[3]),'micro_version'=>intval($matches[4]));
363
+		return array('slug'=>$matches[1], 'major_version'=>intval($matches[2]), 'minor_version'=>intval($matches[3]), 'micro_version'=>intval($matches[4]));
364 364
 	}
365 365
 	/**
366 366
 	 * Ensures that the option indicating the current DB version is set. This should only be
@@ -369,33 +369,33 @@  discard block
 block discarded – undo
369 369
 	 * to 4.1.x.
370 370
 	 * @return string of current db state
371 371
 	 */
372
-	public function ensure_current_database_state_is_set(){
373
-		$espresso_db_core_updates = get_option( 'espresso_db_update', array() );
372
+	public function ensure_current_database_state_is_set() {
373
+		$espresso_db_core_updates = get_option('espresso_db_update', array());
374 374
 		$db_state = get_option(EE_Data_Migration_Manager::current_database_state);
375
-		if( ! $db_state ){
375
+		if ( ! $db_state) {
376 376
 			//mark the DB as being in the state as the last version in there.
377 377
 			//this is done to trigger maintenance mode and do data migration scripts
378 378
 			//if the admin installed this version of EE over 3.1.x or 4.0.x
379 379
 			//otherwise, the normal maintenance mode code is fine
380 380
 			$previous_versions_installed = array_keys($espresso_db_core_updates);
381 381
 			$previous_version_installed = end($previous_versions_installed);
382
-			if(version_compare('4.1.0', $previous_version_installed)){
382
+			if (version_compare('4.1.0', $previous_version_installed)) {
383 383
 				//last installed version was less than 4.1
384 384
 				//so we want the data migrations to happen. SO, we're going to say the DB is at that state
385 385
 //				echo "4.1.0 is greater than $previous_version_installed! update the option";
386 386
 				$db_state = array('Core'=>$previous_version_installed);
387
-			}else{
387
+			} else {
388 388
 //					echo "4.1.0 is SMALLER than $previous_version_installed";
389 389
 					$db_state = array('Core'=>EVENT_ESPRESSO_VERSION);
390 390
 			}
391
-			update_option(EE_Data_Migration_Manager::current_database_state,$db_state);
391
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
392 392
 		}
393 393
 		//in 4.1, $db_state would have only been a simple string like '4.1.0',
394 394
 		//but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's
395 395
 		//db, and possibly other keys for other addons like 'Calendar','Permissions',etc
396
-		if( ! is_array($db_state)){
396
+		if ( ! is_array($db_state)) {
397 397
 			$db_state = array('Core'=>$db_state);
398
-			update_option(EE_Data_Migration_Manager::current_database_state,$db_state);
398
+			update_option(EE_Data_Migration_Manager::current_database_state, $db_state);
399 399
 		}
400 400
 		return $db_state;
401 401
 	}
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
 	 * or they don't apply), returns an empty array
407 407
 	 * @return EE_Data_Migration_Script_Base[]
408 408
 	 */
409
-	public function check_for_applicable_data_migration_scripts(){
409
+	public function check_for_applicable_data_migration_scripts() {
410 410
 		//get the option describing what options have already run
411 411
 		$scripts_ran = $this->get_data_migrations_ran();
412 412
 		//$scripts_ran = array('4.1.0.core'=>array('monkey'=>null));
@@ -419,62 +419,62 @@  discard block
 block discarded – undo
419 419
 		$iteration = 0;
420 420
 		$next_database_state_to_consider = $current_database_state;
421 421
 		$theoretical_database_state = NULL;
422
-		do{
422
+		do {
423 423
 			//the next state after the currently-considered one will start off looking the same as the current, but we may make additions...
424 424
 			$theoretical_database_state = $next_database_state_to_consider;
425 425
 			//the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?)
426
-			foreach($script_class_and_filepaths_available as $classname => $filepath){
426
+			foreach ($script_class_and_filepaths_available as $classname => $filepath) {
427 427
 
428 428
 				$migrates_to_version = $this->script_migrates_to_version($classname);
429
-				$script_converts_plugin_slug = $migrates_to_version[ 'slug' ];
430
-				$script_converts_to_version = $migrates_to_version[ 'version' ];
429
+				$script_converts_plugin_slug = $migrates_to_version['slug'];
430
+				$script_converts_to_version = $migrates_to_version['version'];
431 431
 				//check if this version script is DONE or not; or if it's never been ran
432
-				if(		! $scripts_ran ||
432
+				if ( ! $scripts_ran ||
433 433
 						! isset($scripts_ran[$script_converts_plugin_slug]) ||
434
-						! isset($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version])){
434
+						! isset($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version])) {
435 435
 					//we haven't ran this conversion script before
436 436
 					//now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available
437
-					$script = new $classname( $this->_get_table_manager(), $this->_get_table_analysis() );
437
+					$script = new $classname($this->_get_table_manager(), $this->_get_table_analysis());
438 438
 					/* @var $script EE_Data_Migration_Script_Base */
439 439
 					$can_migrate = $script->can_migrate_from_version($theoretical_database_state);
440
-					if($can_migrate){
440
+					if ($can_migrate) {
441 441
 						$script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
442 442
 						$migrates_to_version = $script->migrates_to_version();
443
-						$next_database_state_to_consider[ $migrates_to_version[ 'slug' ] ] = $migrates_to_version[ 'version' ];
443
+						$next_database_state_to_consider[$migrates_to_version['slug']] = $migrates_to_version['version'];
444 444
 						unset($script_class_and_filepaths_available[$classname]);
445 445
 					}
446
-				} elseif($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version] instanceof EE_Data_Migration_Script_Base){
446
+				} elseif ($scripts_ran[$script_converts_plugin_slug][$script_converts_to_version] instanceof EE_Data_Migration_Script_Base) {
447 447
 					//this script has been ran, or at least started
448 448
 					$script = $scripts_ran[$script_converts_plugin_slug][$script_converts_to_version];
449
-					if( $script->get_status() != self::status_completed){
449
+					if ($script->get_status() != self::status_completed) {
450 450
 						//this script is already underway... keep going with it
451 451
 						$script_classes_that_should_run_per_iteration[$iteration][$script->priority()][] = $script;
452 452
 						$migrates_to_version = $script->migrates_to_version();
453
-						$next_database_state_to_consider[ $migrates_to_version[ 'slug' ] ] = $migrates_to_version[ 'version' ];
453
+						$next_database_state_to_consider[$migrates_to_version['slug']] = $migrates_to_version['version'];
454 454
 						unset($script_class_and_filepaths_available[$classname]);
455
-					}else{
455
+					} else {
456 456
 						//it must have a status that indicates it has finished, so we don't want to try and run it again
457 457
 					}
458
-				}else{
458
+				} else {
459 459
 					//it exists but it's not  a proper data migration script
460 460
 					//maybe the script got renamed? or was simply removed from EE?
461 461
 					//either way, its certainly not runnable!
462 462
 				}
463 463
 			}
464 464
 			$iteration++;
465
-		}while( $next_database_state_to_consider != $theoretical_database_state && $iteration<6);
465
+		}while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6);
466 466
 		//ok we have all the scripts that should run, now let's make them into flat array
467 467
 		$scripts_that_should_run = array();
468
-		foreach($script_classes_that_should_run_per_iteration as $scripts_at_priority){
468
+		foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) {
469 469
 			ksort($scripts_at_priority);
470
-			foreach($scripts_at_priority as $scripts){
471
-				foreach($scripts as $script){
470
+			foreach ($scripts_at_priority as $scripts) {
471
+				foreach ($scripts as $script) {
472 472
 					$scripts_that_should_run[get_class($script)] = $script;
473 473
 				}
474 474
 			}
475 475
 		}
476 476
 
477
-		do_action( 'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run', $scripts_that_should_run );
477
+		do_action('AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run', $scripts_that_should_run);
478 478
 		return $scripts_that_should_run;
479 479
 	}
480 480
 
@@ -488,14 +488,14 @@  discard block
 block discarded – undo
488 488
 	 * @param bool $include_completed_scripts
489 489
 	 * @return EE_Data_Migration_Script_Base
490 490
 	 */
491
-	public function get_last_ran_script($include_completed_scripts = false){
491
+	public function get_last_ran_script($include_completed_scripts = false) {
492 492
 		//make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script
493
-		if( ! $this->_data_migrations_ran){
493
+		if ( ! $this->_data_migrations_ran) {
494 494
 			$this->get_data_migrations_ran();
495 495
 		}
496
-		if($include_completed_scripts){
496
+		if ($include_completed_scripts) {
497 497
 			return $this->_last_ran_script;
498
-		}else{
498
+		} else {
499 499
 			return $this->_last_ran_incomplete_script;
500 500
 		}
501 501
 	}
@@ -518,19 +518,19 @@  discard block
 block discarded – undo
518 518
 	 * 		@type string $message string describing what was done during this step
519 519
 	 * }
520 520
 	 */
521
-	public function migration_step( $step_size = 0 ){
521
+	public function migration_step($step_size = 0) {
522 522
 
523 523
 		//bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535
524
-		if ( class_exists( 'EE_CPT_Strategy' ) ) {
525
-			remove_action( 'pre_get_posts', array( EE_CPT_Strategy::instance(), 'pre_get_posts' ), 5 );
524
+		if (class_exists('EE_CPT_Strategy')) {
525
+			remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5);
526 526
 		}
527 527
 
528
-		try{
528
+		try {
529 529
 			$currently_executing_script = $this->get_last_ran_script();
530
-			if( ! $currently_executing_script){
530
+			if ( ! $currently_executing_script) {
531 531
 				//Find the next script that needs to execute
532 532
 				$scripts = $this->check_for_applicable_data_migration_scripts();
533
-				if( ! $scripts ){
533
+				if ( ! $scripts) {
534 534
 					//huh, no more scripts to run... apparently we're done!
535 535
 					//but dont forget to make sure initial data is there
536 536
 					//we should be good to allow them to exit maintenance mode now
@@ -551,18 +551,18 @@  discard block
 block discarded – undo
551 551
 				//and add to the array/wp option showing the scripts ran
552 552
 //				$this->_data_migrations_ran[$this->script_migrates_to_version(get_class($currently_executing_script))] = $currently_executing_script;
553 553
 				$migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script));
554
-				$plugin_slug = $migrates_to[ 'slug' ];
555
-				$version = $migrates_to[ 'version' ];
554
+				$plugin_slug = $migrates_to['slug'];
555
+				$version = $migrates_to['version'];
556 556
 				$this->_data_migrations_ran[$plugin_slug][$version] = $currently_executing_script;
557 557
 			}
558 558
 			$current_script_name = get_class($currently_executing_script);
559
-		}catch(Exception $e){
559
+		} catch (Exception $e) {
560 560
 			//an exception occurred while trying to get migration scripts
561 561
 
562
-			$message =  sprintf( __("Error Message: %sStack Trace:%s", "event_espresso"), $e->getMessage() . '<br>', $e->getTraceAsString() );
562
+			$message = sprintf(__("Error Message: %sStack Trace:%s", "event_espresso"), $e->getMessage().'<br>', $e->getTraceAsString());
563 563
 			//record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations
564 564
 			//but that's ok-- it's just an FYI to support that we couldn't even run any data migrations
565
-			$this->add_error_to_migrations_ran(sprintf(__("Could not run data migrations because: %s", "event_espresso"),$message));
565
+			$this->add_error_to_migrations_ran(sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message));
566 566
 			return array(
567 567
 				'records_to_migrate'=>1,
568 568
 				'records_migrated'=>0,
@@ -572,16 +572,16 @@  discard block
 block discarded – undo
572 572
 			);
573 573
 		}
574 574
 		//ok so we definitely have a data migration script
575
-		try{
575
+		try {
576 576
 			//how big of a bite do we want to take? Allow users to easily override via their wp-config
577
-			if( ! absint( $step_size ) > 0 ){
578
-				$step_size = defined( 'EE_MIGRATION_STEP_SIZE' ) && absint( EE_MIGRATION_STEP_SIZE ) ? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size;
577
+			if ( ! absint($step_size) > 0) {
578
+				$step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE) ? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size;
579 579
 			}
580 580
 			//do what we came to do!
581 581
 			$currently_executing_script->migration_step($step_size);
582 582
 			//can we wrap it up and verify default data?
583 583
 			$init_dbs = false;
584
-			switch($currently_executing_script->get_status()){
584
+			switch ($currently_executing_script->get_status()) {
585 585
 				case EE_Data_Migration_Manager::status_continue:
586 586
 					$response_array = array(
587 587
 						'records_to_migrate'=>$currently_executing_script->count_records_to_migrate(),
@@ -593,16 +593,16 @@  discard block
 block discarded – undo
593 593
 				case EE_Data_Migration_Manager::status_completed:
594 594
 					//ok so THAT script has completed
595 595
 					$this->update_current_database_state_to($this->script_migrates_to_version($current_script_name));
596
-					$response_array =  array(
596
+					$response_array = array(
597 597
 							'records_to_migrate'=>$currently_executing_script->count_records_to_migrate(),
598 598
 							'records_migrated'=>$currently_executing_script->count_records_migrated(),
599 599
 							'status'=> EE_Data_Migration_Manager::status_completed,
600 600
 							'message'=>$currently_executing_script->get_feedback_message(),
601
-							'script'=> sprintf(__("%s Completed",'event_espresso'),$currently_executing_script->pretty_name())
601
+							'script'=> sprintf(__("%s Completed", 'event_espresso'), $currently_executing_script->pretty_name())
602 602
 						);
603 603
 					//check if there are any more after this one.
604 604
 					$scripts_remaining = $this->check_for_applicable_data_migration_scripts();
605
-					if( ! $scripts_remaining ){
605
+					if ( ! $scripts_remaining) {
606 606
 						//we should be good to allow them to exit maintenance mode now
607 607
 						EE_Maintenance_Mode::instance()->set_maintenance_level(intval(EE_Maintenance_Mode::level_0_not_in_maintenance));
608 608
 						////huh, no more scripts to run... apparently we're done!
@@ -616,39 +616,39 @@  discard block
 block discarded – undo
616 616
 						'records_to_migrate'=>$currently_executing_script->count_records_to_migrate(),
617 617
 						'records_migrated'=>$currently_executing_script->count_records_migrated(),
618 618
 						'status'=> $currently_executing_script->get_status(),
619
-						'message'=>  sprintf(__("Minor errors occurred during %s: %s", "event_espresso"), $currently_executing_script->pretty_name(), implode(", ",$currently_executing_script->get_errors())),
619
+						'message'=>  sprintf(__("Minor errors occurred during %s: %s", "event_espresso"), $currently_executing_script->pretty_name(), implode(", ", $currently_executing_script->get_errors())),
620 620
 						'script'=>$currently_executing_script->pretty_name()
621 621
 					);
622 622
 					break;
623 623
 			}
624
-		}catch(Exception $e){
624
+		} catch (Exception $e) {
625 625
 			//ok so some exception was thrown which killed the data migration script
626 626
 			//double-check we have a real script
627
-			if($currently_executing_script instanceof EE_Data_Migration_Script_Base){
627
+			if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) {
628 628
 				$script_name = $currently_executing_script->pretty_name();
629 629
 				$currently_executing_script->set_broken();
630 630
 				$currently_executing_script->add_error($e->getMessage());
631
-			}else{
631
+			} else {
632 632
 				$script_name = __("Error getting Migration Script", "event_espresso");
633 633
 			}
634 634
 			$response_array = array(
635 635
 				'records_to_migrate'=>1,
636 636
 				'records_migrated'=>0,
637 637
 				'status'=>self::status_fatal_error,
638
-				'message'=>  sprintf(__("A fatal error occurred during the migration: %s", "event_espresso"),$e->getMessage()),
638
+				'message'=>  sprintf(__("A fatal error occurred during the migration: %s", "event_espresso"), $e->getMessage()),
639 639
 				'script'=>$script_name
640 640
 			);
641 641
 		}
642 642
 		$successful_save = $this->_save_migrations_ran();
643
-		if($successful_save !== TRUE){
643
+		if ($successful_save !== TRUE) {
644 644
 			//ok so the current wp option didn't save. that's tricky, because we'd like to update it
645 645
 			//and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION!
646 646
 			//however, if we throw an exception, and return that, then the next request
647 647
 			//won't have as much info in it, and it may be able to save
648
-			throw new EE_Error(sprintf(__("The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.", "event_espresso"),$successful_save));
648
+			throw new EE_Error(sprintf(__("The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.", "event_espresso"), $successful_save));
649 649
 		}
650 650
 		//if we're all done, initialize EE plugins' default data etc.
651
-		if( $init_dbs ) {
651
+		if ($init_dbs) {
652 652
 			$this->initialize_db_for_enqueued_ee_plugins();
653 653
 		}
654 654
 		return $response_array;
@@ -666,23 +666,23 @@  discard block
 block discarded – undo
666 666
 	 * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into errors, notifications, and successes
667 667
 	 * 'script'=>a pretty name of the script currently running
668 668
 	 */
669
-	public function response_to_migration_ajax_request(){
669
+	public function response_to_migration_ajax_request() {
670 670
 //		//start output buffer just to make sure we don't mess up the json
671 671
 		ob_start();
672
-		try{
672
+		try {
673 673
 			$response = $this->migration_step();
674
-		}catch(Exception $e){
674
+		} catch (Exception $e) {
675 675
 			$response = array(
676 676
 				'records_to_migrate'=>0,
677 677
 				'records_migrated'=>0,
678 678
 				'status'=> EE_Data_Migration_Manager::status_fatal_error,
679
-				'message'=> sprintf(__("Unknown fatal error occurred: %s", "event_espresso"),$e->getMessage()),
679
+				'message'=> sprintf(__("Unknown fatal error occurred: %s", "event_espresso"), $e->getMessage()),
680 680
 				'script'=>'Unknown');
681 681
 			$this->add_error_to_migrations_ran($e->getMessage()."; Stack trace:".$e->getTraceAsString());
682 682
 		}
683 683
 		$warnings_etc = @ob_get_contents();
684 684
 		ob_end_clean();
685
-		$response['message'] .=$warnings_etc;
685
+		$response['message'] .= $warnings_etc;
686 686
 		return $response;
687 687
 	}
688 688
 
@@ -695,14 +695,14 @@  discard block
 block discarded – undo
695 695
 	 * }
696 696
 	 * @return void
697 697
 	 */
698
-	public function update_current_database_state_to($slug_and_version = null){
699
-		if( ! $slug_and_version ){
698
+	public function update_current_database_state_to($slug_and_version = null) {
699
+		if ( ! $slug_and_version) {
700 700
 			//no version was provided, assume it should be at the current code version
701 701
 			$slug_and_version = array('slug' => 'Core', 'version' => espresso_version());
702 702
 		}
703 703
 		$current_database_state = get_option(self::current_database_state);
704
-		$current_database_state[ $slug_and_version[ 'slug' ] ]=$slug_and_version[ 'version' ];
705
-		update_option(self::current_database_state,$current_database_state);
704
+		$current_database_state[$slug_and_version['slug']] = $slug_and_version['version'];
705
+		update_option(self::current_database_state, $current_database_state);
706 706
 	}
707 707
 
708 708
 	/**
@@ -713,20 +713,20 @@  discard block
 block discarded – undo
713 713
 	 * }
714 714
 	 * @return boolean
715 715
 	 */
716
-	public function database_needs_updating_to( $slug_and_version ) {
716
+	public function database_needs_updating_to($slug_and_version) {
717 717
 
718
-		$slug = $slug_and_version[ 'slug' ];
719
-		$version = $slug_and_version[ 'version' ];
718
+		$slug = $slug_and_version['slug'];
719
+		$version = $slug_and_version['version'];
720 720
 		$current_database_state = get_option(self::current_database_state);
721
-		if( ! isset( $current_database_state[ $slug ] ) ) {
721
+		if ( ! isset($current_database_state[$slug])) {
722 722
 			return true;
723
-		}else{
723
+		} else {
724 724
 			//just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes
725
-			$version_parts_current_db_state = array_slice( explode('.', $current_database_state[ $slug ] ), 0, 3);
726
-			$version_parts_of_provided_db_state = array_slice( explode( '.', $version ), 0, 3 );
725
+			$version_parts_current_db_state = array_slice(explode('.', $current_database_state[$slug]), 0, 3);
726
+			$version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3);
727 727
 			$needs_updating = false;
728
-			foreach($version_parts_current_db_state as $offset => $version_part_in_current_db_state ) {
729
-				if( $version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ] ) {
728
+			foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) {
729
+				if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[$offset]) {
730 730
 					$needs_updating = true;
731 731
 					break;
732 732
 				}
@@ -748,7 +748,7 @@  discard block
 block discarded – undo
748 748
      */
749 749
     public function get_all_data_migration_scripts_available()
750 750
     {
751
-        if (! $this->_data_migration_class_to_filepath_map) {
751
+        if ( ! $this->_data_migration_class_to_filepath_map) {
752 752
             $this->_data_migration_class_to_filepath_map = array();
753 753
             foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) {
754 754
                 // strip any placeholders added to classname to make it a unique array key
@@ -757,7 +757,7 @@  discard block
 block discarded – undo
757 757
                     ? $eeAddonClass
758 758
                     : '';
759 759
                 $folder_path  = EEH_File::end_with_directory_separator($folder_path);
760
-                $files        = glob($folder_path . '*.dms.php');
760
+                $files        = glob($folder_path.'*.dms.php');
761 761
                 if (empty($files)) {
762 762
                     continue;
763 763
                 }
@@ -783,7 +783,7 @@  discard block
 block discarded – undo
783 783
                             '4.3.0.alpha.019'
784 784
                         );
785 785
                     }
786
-                    $this->_data_migration_class_to_filepath_map[ $classname ] = $file;
786
+                    $this->_data_migration_class_to_filepath_map[$classname] = $file;
787 787
                 }
788 788
             }
789 789
             EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map);
@@ -798,7 +798,7 @@  discard block
 block discarded – undo
798 798
 	 * from each addon, and check if they need updating,
799 799
 	 * @return boolean
800 800
 	 */
801
-	public function addons_need_updating(){
801
+	public function addons_need_updating() {
802 802
 		return false;
803 803
 	}
804 804
 	/**
@@ -807,25 +807,25 @@  discard block
 block discarded – undo
807 807
 	 * @param string $error_message
808 808
 	 * @throws EE_Error
809 809
 	 */
810
-	public function add_error_to_migrations_ran($error_message){
810
+	public function add_error_to_migrations_ran($error_message) {
811 811
 		//get last-ran migration script
812 812
 		global $wpdb;
813
-		$last_migration_script_option = $wpdb->get_row("SELECT * FROM $wpdb->options WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id DESC LIMIT 1",ARRAY_A);
813
+		$last_migration_script_option = $wpdb->get_row("SELECT * FROM $wpdb->options WHERE option_name like '".EE_Data_Migration_Manager::data_migration_script_option_prefix."%' ORDER BY option_id DESC LIMIT 1", ARRAY_A);
814 814
 
815 815
 		$last_ran_migration_script_properties = isset($last_migration_script_option['option_value']) ? maybe_unserialize($last_migration_script_option['option_value']) : null;
816 816
 		//now, tread lightly because we're here because a FATAL non-catchable error
817 817
 		//was thrown last time when we were trying to run a data migration script
818 818
 		//so the fatal error could have happened while getting the migration script
819 819
 		//or doing running it...
820
-		$versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(EE_Data_Migration_Manager::data_migration_script_option_prefix,"",$last_migration_script_option['option_name']) : null;
820
+		$versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace(EE_Data_Migration_Manager::data_migration_script_option_prefix, "", $last_migration_script_option['option_name']) : null;
821 821
 
822 822
 		//check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet
823 823
 		//because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done)
824
-		if(isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed){
824
+		if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) {
825 825
 			//ok then just add this error to its list of errors
826 826
 			$last_ran_migration_script_properties['_errors'][] = $error_message;
827 827
 			$last_ran_migration_script_properties['_status'] = self::status_fatal_error;
828
-		}else{
828
+		} else {
829 829
 			//so we don't even know which script was last running
830 830
 			//use the data migration error stub, which is designed specifically for this type of thing
831 831
 			$general_migration_error = new EE_DMS_Unknown_1_0_0();
@@ -835,39 +835,39 @@  discard block
 block discarded – undo
835 835
 			$versions_migrated_to = 'Unknown.1.0.0';
836 836
 			//now just to make sure appears as last (in case the were previously a fatal error like this)
837 837
 			//delete the old one
838
-			delete_option( self::data_migration_script_option_prefix . $versions_migrated_to );
838
+			delete_option(self::data_migration_script_option_prefix.$versions_migrated_to);
839 839
 		}
840
-		update_option(self::data_migration_script_option_prefix.$versions_migrated_to,$last_ran_migration_script_properties);
840
+		update_option(self::data_migration_script_option_prefix.$versions_migrated_to, $last_ran_migration_script_properties);
841 841
 
842 842
 	}
843 843
 	/**
844 844
 	 * saves what data migrations have ran to the database
845 845
 	 * @return mixed TRUE if successfully saved migrations ran, string if an error occurred
846 846
 	 */
847
-	protected function _save_migrations_ran(){
848
-		if($this->_data_migrations_ran == null){
847
+	protected function _save_migrations_ran() {
848
+		if ($this->_data_migrations_ran == null) {
849 849
 			$this->get_data_migrations_ran();
850 850
 		}
851 851
 		//now, we don't want to save actual classes to the DB because that's messy
852 852
 		$successful_updates = true;
853
-		foreach($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin){
854
-			foreach($migrations_ran_for_plugin as $version_string => $array_or_migration_obj){
853
+		foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) {
854
+			foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) {
855 855
 	//			echo "saving migration script to $version_string<br>";
856 856
 				$plugin_slug_for_use_in_option_name = $plugin_slug.".";
857 857
 				$option_name = self::data_migration_script_option_prefix.$plugin_slug_for_use_in_option_name.$version_string;
858 858
 				$old_option_value = get_option($option_name);
859
-				if($array_or_migration_obj instanceof EE_Data_Migration_Script_Base){
859
+				if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) {
860 860
 					$script_array_for_saving = $array_or_migration_obj->properties_as_array();
861
-					if( $old_option_value != $script_array_for_saving){
862
-						$successful_updates = update_option($option_name,$script_array_for_saving);
861
+					if ($old_option_value != $script_array_for_saving) {
862
+						$successful_updates = update_option($option_name, $script_array_for_saving);
863 863
 					}
864
-				}else{//we don't know what this array-thing is. So just save it as-is
864
+				} else {//we don't know what this array-thing is. So just save it as-is
865 865
 	//				$array_of_migrations[$version_string] = $array_or_migration_obj;
866
-					if($old_option_value != $array_or_migration_obj){
867
-						$successful_updates = update_option($option_name,$array_or_migration_obj);
866
+					if ($old_option_value != $array_or_migration_obj) {
867
+						$successful_updates = update_option($option_name, $array_or_migration_obj);
868 868
 					}
869 869
 				}
870
-				if( ! $successful_updates ){
870
+				if ( ! $successful_updates) {
871 871
 					global $wpdb;
872 872
 					return $wpdb->last_error;
873 873
 				}
@@ -891,17 +891,17 @@  discard block
 block discarded – undo
891 891
 	 * @return EE_Data_Migration_Script_Base
892 892
 	 * @throws EE_Error
893 893
 	 */
894
-	function _instantiate_script_from_properties_array($properties_array){
895
-		if( ! isset($properties_array['class'])){
896
-			throw new EE_Error(sprintf(__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"),implode(",",$properties_array)));
894
+	function _instantiate_script_from_properties_array($properties_array) {
895
+		if ( ! isset($properties_array['class'])) {
896
+			throw new EE_Error(sprintf(__("Properties array  has no 'class' properties. Here's what it has: %s", "event_espresso"), implode(",", $properties_array)));
897 897
 		}
898 898
 		$class_name = $properties_array['class'];
899
-		if( ! class_exists($class_name)){
900
-			throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"),$class_name));
899
+		if ( ! class_exists($class_name)) {
900
+			throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name));
901 901
 		}
902 902
 		$class = new $class_name;
903
-		if( ! $class instanceof EE_Data_Migration_Script_Base){
904
-			throw new EE_Error(sprintf(__("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"),$class_name,get_class($class)));
903
+		if ( ! $class instanceof EE_Data_Migration_Script_Base) {
904
+			throw new EE_Error(sprintf(__("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"), $class_name, get_class($class)));
905 905
 		}
906 906
 		$class->instantiate_from_array_of_properties($properties_array);
907 907
 		return $class;
@@ -913,25 +913,25 @@  discard block
 block discarded – undo
913 913
 	 * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core'
914 914
 	 * @return string
915 915
 	 */
916
-	public function get_most_up_to_date_dms($plugin_slug = 'Core'){
916
+	public function get_most_up_to_date_dms($plugin_slug = 'Core') {
917 917
 		$class_to_filepath_map = $this->get_all_data_migration_scripts_available();
918 918
 		$most_up_to_date_dms_classname = NULL;
919
-		foreach($class_to_filepath_map as $classname => $filepath){
920
-			if($most_up_to_date_dms_classname === NULL){
919
+		foreach ($class_to_filepath_map as $classname => $filepath) {
920
+			if ($most_up_to_date_dms_classname === NULL) {
921 921
 				$migrates_to = $this->script_migrates_to_version($classname);
922
-				$this_plugin_slug = $migrates_to[ 'slug' ];
922
+				$this_plugin_slug = $migrates_to['slug'];
923 923
 //				$version_string = $migrates_to[ 'version' ];
924 924
 //				$details = $this->parse_dms_classname($classname);
925
-				if($this_plugin_slug == $plugin_slug){
925
+				if ($this_plugin_slug == $plugin_slug) {
926 926
 					//if it's for core, it wins
927 927
 					$most_up_to_date_dms_classname = $classname;
928 928
 				}
929 929
 				//if it wasn't for core, we must keep searching for one that is!
930 930
 				continue;
931
-			}else{
932
-				$champion_migrates_to= $this->script_migrates_to_version($most_up_to_date_dms_classname);
931
+			} else {
932
+				$champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname);
933 933
 				$contender_migrates_to = $this->script_migrates_to_version($classname);
934
-				if($contender_migrates_to[ 'slug' ] == $plugin_slug && version_compare($champion_migrates_to[ 'version' ], $contender_migrates_to[ 'version' ], '<')){
934
+				if ($contender_migrates_to['slug'] == $plugin_slug && version_compare($champion_migrates_to['version'], $contender_migrates_to['version'], '<')) {
935 935
 					//so the contenders version is higher and its for Core
936 936
 					$most_up_to_date_dms_classname = $classname;
937 937
 				}
@@ -951,11 +951,11 @@  discard block
 block discarded – undo
951 951
 	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
952 952
 	 * @return EE_Data_Migration_Script_Base
953 953
 	 */
954
-	public function get_migration_ran( $version, $plugin_slug = 'Core' ) {
954
+	public function get_migration_ran($version, $plugin_slug = 'Core') {
955 955
 		$migrations_ran = $this->get_data_migrations_ran();
956
-		if( isset( $migrations_ran[ $plugin_slug ] ) && isset( $migrations_ran[ $plugin_slug ][ $version ] ) ){
957
-			return $migrations_ran[ $plugin_slug ][ $version ];
958
-		}else{
956
+		if (isset($migrations_ran[$plugin_slug]) && isset($migrations_ran[$plugin_slug][$version])) {
957
+			return $migrations_ran[$plugin_slug][$version];
958
+		} else {
959 959
 			return NULL;
960 960
 		}
961 961
 	}
@@ -967,20 +967,20 @@  discard block
 block discarded – undo
967 967
 	 * @return bool
968 968
 	 * @throws EE_Error
969 969
 	 */
970
-	public function reattempt(){
970
+	public function reattempt() {
971 971
 		//find if the last-ran script was borked
972 972
 		//set it as being non-borked (we shouldn't ever get DMSs that we don't recognize)
973 973
 		//add an 'error' saying that we attempted to reset
974 974
 		//does it have a stage that was borked too? if so make it no longer borked
975 975
 		//add an 'error' saying we attempted to reset
976 976
 		$last_ran_script = $this->get_last_ran_script();
977
-		if( $last_ran_script instanceof EE_DMS_Unknown_1_0_0 ){
977
+		if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) {
978 978
 			//if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it)
979 979
 			$last_ran_script->set_completed();
980
-		}elseif( $last_ran_script instanceof EE_Data_Migration_Script_Base ) {
980
+		}elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) {
981 981
 			$last_ran_script->reattempt();
982
-		}else{
983
-			throw new EE_Error( sprintf( __( 'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s', 'event_espresso' ), print_r( $last_ran_script, true ) ) );
982
+		} else {
983
+			throw new EE_Error(sprintf(__('Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s', 'event_espresso'), print_r($last_ran_script, true)));
984 984
 		}
985 985
 		return $this->_save_migrations_ran();
986 986
 	}
@@ -990,19 +990,19 @@  discard block
 block discarded – undo
990 990
 	 * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc
991 991
 	 * @return boolean
992 992
 	 */
993
-	public function migration_has_ran( $version, $plugin_slug = 'Core' ) {
994
-		return $this->get_migration_ran( $version, $plugin_slug ) !== NULL;
993
+	public function migration_has_ran($version, $plugin_slug = 'Core') {
994
+		return $this->get_migration_ran($version, $plugin_slug) !== NULL;
995 995
 	}
996 996
 	/**
997 997
 	 * Enqueues this ee plugin to have its data initialized
998 998
 	 * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value
999 999
 	 */
1000
-	public function enqueue_db_initialization_for( $plugin_slug ) {
1000
+	public function enqueue_db_initialization_for($plugin_slug) {
1001 1001
 		$queue = $this->get_db_initialization_queue();
1002
-		if( ! in_array( $plugin_slug, $queue ) ) {
1002
+		if ( ! in_array($plugin_slug, $queue)) {
1003 1003
 			$queue[] = $plugin_slug;
1004 1004
 		}
1005
-		update_option( self::db_init_queue_option_name, $queue );
1005
+		update_option(self::db_init_queue_option_name, $queue);
1006 1006
 	}
1007 1007
 	/**
1008 1008
 	 * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon
@@ -1012,26 +1012,26 @@  discard block
 block discarded – undo
1012 1012
 	public function initialize_db_for_enqueued_ee_plugins() {
1013 1013
 //		EEH_Debug_Tools::instance()->start_timer( 'initialize_db_for_enqueued_ee_plugins' );
1014 1014
 		$queue = $this->get_db_initialization_queue();
1015
-		foreach( $queue as $plugin_slug ) {
1016
-			$most_up_to_date_dms = $this->get_most_up_to_date_dms( $plugin_slug );
1017
-			if( ! $most_up_to_date_dms ) {
1015
+		foreach ($queue as $plugin_slug) {
1016
+			$most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug);
1017
+			if ( ! $most_up_to_date_dms) {
1018 1018
 				//if there is NO DMS for this plugin, obviously there's no schema to verify anyways
1019 1019
 				$verify_db = false;
1020
-			}else{
1021
-				$most_up_to_date_dms_migrates_to = $this->script_migrates_to_version( $most_up_to_date_dms );
1022
-				$verify_db = $this->database_needs_updating_to( $most_up_to_date_dms_migrates_to );
1020
+			} else {
1021
+				$most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms);
1022
+				$verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to);
1023 1023
 			}
1024
-			if( $plugin_slug == 'Core' ){
1024
+			if ($plugin_slug == 'Core') {
1025 1025
 				EE_System::instance()->initialize_db_if_no_migrations_required(
1026 1026
 						false,
1027 1027
 						$verify_db
1028 1028
 					);
1029
-			}else{
1029
+			} else {
1030 1030
 				//just loop through the addons to make sure their database is setup
1031
-				foreach( EE_Registry::instance()->addons as $addon ) {
1032
-					if( $addon->name() == $plugin_slug ) {
1031
+				foreach (EE_Registry::instance()->addons as $addon) {
1032
+					if ($addon->name() == $plugin_slug) {
1033 1033
 
1034
-						$addon->initialize_db_if_no_migrations_required( $verify_db );
1034
+						$addon->initialize_db_if_no_migrations_required($verify_db);
1035 1035
 						break;
1036 1036
 					}
1037 1037
 				}
@@ -1041,7 +1041,7 @@  discard block
 block discarded – undo
1041 1041
 //		EEH_Debug_Tools::instance()->show_times();
1042 1042
 		//because we just initialized the DBs for the enqueued ee plugins
1043 1043
 		//we don't need to keep remembering which ones needed to be initialized
1044
-		delete_option( self::db_init_queue_option_name );
1044
+		delete_option(self::db_init_queue_option_name);
1045 1045
 	}
1046 1046
 
1047 1047
 	/**
@@ -1050,8 +1050,8 @@  discard block
 block discarded – undo
1050 1050
 	 * 'Core', or the return value of EE_Addon::name() for an addon
1051 1051
 	 * @return array
1052 1052
 	 */
1053
-	public function get_db_initialization_queue(){
1054
-		return get_option ( self::db_init_queue_option_name, array() );
1053
+	public function get_db_initialization_queue() {
1054
+		return get_option(self::db_init_queue_option_name, array());
1055 1055
 	}
1056 1056
 
1057 1057
 	/**
@@ -1061,13 +1061,13 @@  discard block
 block discarded – undo
1061 1061
 	 * @throws EE_Error
1062 1062
 	 */
1063 1063
 	protected function _get_table_analysis() {
1064
-		if( $this->_table_analysis instanceof TableAnalysis ) {
1064
+		if ($this->_table_analysis instanceof TableAnalysis) {
1065 1065
 			return $this->_table_analysis;
1066 1066
 		} else {
1067 1067
 			throw new EE_Error(
1068 1068
 				sprintf(
1069
-					__( 'Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1070
-					get_class( $this )
1069
+					__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
1070
+					get_class($this)
1071 1071
 				)
1072 1072
 			);
1073 1073
 		}
@@ -1080,13 +1080,13 @@  discard block
 block discarded – undo
1080 1080
 	 * @throws EE_Error
1081 1081
 	 */
1082 1082
 	protected function _get_table_manager() {
1083
-		if( $this->_table_manager instanceof TableManager ) {
1083
+		if ($this->_table_manager instanceof TableManager) {
1084 1084
 			return $this->_table_manager;
1085 1085
 		} else {
1086 1086
 			throw new EE_Error(
1087 1087
 				sprintf(
1088
-					__( 'Table manager class on class %1$s is not set properly.', 'event_espresso'),
1089
-					get_class( $this )
1088
+					__('Table manager class on class %1$s is not set properly.', 'event_espresso'),
1089
+					get_class($this)
1090 1090
 				)
1091 1091
 			);
1092 1092
 		}
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_Addon.lib.php 2 patches
Indentation   +1092 added lines, -1092 removed lines patch added patch discarded remove patch
@@ -25,1152 +25,1152 @@
 block discarded – undo
25 25
 class EE_Register_Addon implements EEI_Plugin_API
26 26
 {
27 27
 
28
-    /**
29
-     * possibly truncated version of the EE core version string
30
-     *
31
-     * @var string
32
-     */
33
-    protected static $_core_version = '';
28
+	/**
29
+	 * possibly truncated version of the EE core version string
30
+	 *
31
+	 * @var string
32
+	 */
33
+	protected static $_core_version = '';
34 34
 
35
-    /**
36
-     * Holds values for registered addons
37
-     *
38
-     * @var array
39
-     */
40
-    protected static $_settings = array();
35
+	/**
36
+	 * Holds values for registered addons
37
+	 *
38
+	 * @var array
39
+	 */
40
+	protected static $_settings = array();
41 41
 
42
-    /**
43
-     * @var  array $_incompatible_addons keys are addon SLUGS
44
-     * (first argument passed to EE_Register_Addon::register()), keys are
45
-     * their MINIMUM VERSION (with all 5 parts. Eg 1.2.3.rc.004).
46
-     * Generally this should be used sparingly, as we don't want to muddle up
47
-     * EE core with knowledge of ALL the addons out there.
48
-     * If you want NO versions of an addon to run with a certain version of core,
49
-     * it's usually best to define the addon's "min_core_version" as part of its call
50
-     * to EE_Register_Addon::register(), rather than using this array with a super high value for its
51
-     * minimum plugin version.
52
-     * @access    protected
53
-     */
54
-    protected static $_incompatible_addons = array(
55
-        'Multi_Event_Registration' => '2.0.11.rc.002',
56
-        'Promotions'               => '1.0.0.rc.084',
57
-    );
42
+	/**
43
+	 * @var  array $_incompatible_addons keys are addon SLUGS
44
+	 * (first argument passed to EE_Register_Addon::register()), keys are
45
+	 * their MINIMUM VERSION (with all 5 parts. Eg 1.2.3.rc.004).
46
+	 * Generally this should be used sparingly, as we don't want to muddle up
47
+	 * EE core with knowledge of ALL the addons out there.
48
+	 * If you want NO versions of an addon to run with a certain version of core,
49
+	 * it's usually best to define the addon's "min_core_version" as part of its call
50
+	 * to EE_Register_Addon::register(), rather than using this array with a super high value for its
51
+	 * minimum plugin version.
52
+	 * @access    protected
53
+	 */
54
+	protected static $_incompatible_addons = array(
55
+		'Multi_Event_Registration' => '2.0.11.rc.002',
56
+		'Promotions'               => '1.0.0.rc.084',
57
+	);
58 58
 
59 59
 
60
-    /**
61
-     * We should always be comparing core to a version like '4.3.0.rc.000',
62
-     * not just '4.3.0'.
63
-     * So if the addon developer doesn't provide that full version string,
64
-     * fill in the blanks for them
65
-     *
66
-     * @param string $min_core_version
67
-     * @return string always like '4.3.0.rc.000'
68
-     */
69
-    protected static function _effective_version($min_core_version)
70
-    {
71
-        // versions: 4 . 3 . 1 . p . 123
72
-        // offsets:    0 . 1 . 2 . 3 . 4
73
-        $version_parts = explode('.', $min_core_version);
74
-        //check they specified the micro version (after 2nd period)
75
-        if (! isset($version_parts[2])) {
76
-            $version_parts[2] = '0';
77
-        }
78
-        //if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
79
-        //soon we can assume that's 'rc', but this current version is 'alpha'
80
-        if (! isset($version_parts[3])) {
81
-            $version_parts[3] = 'dev';
82
-        }
83
-        if (! isset($version_parts[4])) {
84
-            $version_parts[4] = '000';
85
-        }
86
-        return implode('.', $version_parts);
87
-    }
60
+	/**
61
+	 * We should always be comparing core to a version like '4.3.0.rc.000',
62
+	 * not just '4.3.0'.
63
+	 * So if the addon developer doesn't provide that full version string,
64
+	 * fill in the blanks for them
65
+	 *
66
+	 * @param string $min_core_version
67
+	 * @return string always like '4.3.0.rc.000'
68
+	 */
69
+	protected static function _effective_version($min_core_version)
70
+	{
71
+		// versions: 4 . 3 . 1 . p . 123
72
+		// offsets:    0 . 1 . 2 . 3 . 4
73
+		$version_parts = explode('.', $min_core_version);
74
+		//check they specified the micro version (after 2nd period)
75
+		if (! isset($version_parts[2])) {
76
+			$version_parts[2] = '0';
77
+		}
78
+		//if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
79
+		//soon we can assume that's 'rc', but this current version is 'alpha'
80
+		if (! isset($version_parts[3])) {
81
+			$version_parts[3] = 'dev';
82
+		}
83
+		if (! isset($version_parts[4])) {
84
+			$version_parts[4] = '000';
85
+		}
86
+		return implode('.', $version_parts);
87
+	}
88 88
 
89 89
 
90
-    /**
91
-     * Returns whether or not the min core version requirement of the addon is met
92
-     *
93
-     * @param string $min_core_version    the minimum core version required by the addon
94
-     * @param string $actual_core_version the actual core version, optional
95
-     * @return boolean
96
-     */
97
-    public static function _meets_min_core_version_requirement(
98
-        $min_core_version,
99
-        $actual_core_version = EVENT_ESPRESSO_VERSION
100
-    ) {
101
-        return version_compare(
102
-            self::_effective_version($actual_core_version),
103
-            self::_effective_version($min_core_version),
104
-            '>='
105
-        );
106
-    }
90
+	/**
91
+	 * Returns whether or not the min core version requirement of the addon is met
92
+	 *
93
+	 * @param string $min_core_version    the minimum core version required by the addon
94
+	 * @param string $actual_core_version the actual core version, optional
95
+	 * @return boolean
96
+	 */
97
+	public static function _meets_min_core_version_requirement(
98
+		$min_core_version,
99
+		$actual_core_version = EVENT_ESPRESSO_VERSION
100
+	) {
101
+		return version_compare(
102
+			self::_effective_version($actual_core_version),
103
+			self::_effective_version($min_core_version),
104
+			'>='
105
+		);
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * Method for registering new EE_Addons.
111
-     * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE
112
-     * AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. However, it
113
-     * may also be called after the 'activate_plugin' action (when an addon is activated), because an activating addon
114
-     * won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. If its called after
115
-     * 'activate_plugin', it registers the addon still, but its components are not registered
116
-     * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do
117
-     * anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns
118
-     * (so that we can detect that the addon has activated on the subsequent request)
119
-     *
120
-     * @since    4.3.0
121
-     * @param string                  $addon_name                       [Required] the EE_Addon's name.
122
-     * @param  array                  $setup_args                       {
123
-     *                                                                  An array of arguments provided for registering
124
-     *                                                                  the message type.
125
-     * @type  string                  $class_name                       the addon's main file name.
126
-     *                                                                  If left blank, generated from the addon name,
127
-     *                                                                  changes something like "calendar" to
128
-     *                                                                  "EE_Calendar"
129
-     * @type string                   $min_core_version                 the minimum version of EE Core that the
130
-     *                                                                  addon will work with. eg "4.8.1.rc.084"
131
-     * @type string                   $version                          the "software" version for the addon. eg
132
-     *                                                                  "1.0.0.p" for a first stable release, or
133
-     *                                                                  "1.0.0.rc.043" for a version in progress
134
-     * @type string                   $main_file_path                   the full server path to the main file
135
-     *                                                                  loaded directly by WP
136
-     * @type string                   $domain_fqcn                      Fully Qualified Class Name
137
-     *                                                                  for the addon's Domain class
138
-     *                                                                  (see EventEspresso\core\domain\Domain)
139
-     * @type string                   $admin_path                       full server path to the folder where the
140
-     *                                                                  addon\'s admin files reside
141
-     * @type string                   $admin_callback                   a method to be called when the EE Admin is
142
-     *                                                                  first invoked, can be used for hooking into
143
-     *                                                                  any admin page
144
-     * @type string                   $config_section                   the section name for this addon's
145
-     *                                                                  configuration settings section
146
-     *                                                                  (defaults to "addons")
147
-     * @type string                   $config_class                     the class name for this addon's
148
-     *                                                                  configuration settings object
149
-     * @type string                   $config_name                      the class name for this addon's
150
-     *                                                                  configuration settings object
151
-     * @type string $autoloader_paths                                   [Required] an array of class names and the full
152
-     *                                                                  server paths to those files.
153
-     * @type string                   $autoloader_folders               an array of  "full server paths" for any
154
-     *                                                                  folders containing classes that might be
155
-     *                                                                  invoked by the addon
156
-     * @type string                   $dms_paths                        [Required] an array of full server paths to
157
-     *                                                                  folders that contain data migration scripts.
158
-     *                                                                  The key should be the EE_Addon class name that
159
-     *                                                                  this set of data migration scripts belongs to.
160
-     *                                                                  If the EE_Addon class is namespaced, then this
161
-     *                                                                  needs to be the Fully Qualified Class Name
162
-     * @type string                   $module_paths                     an array of full server paths to any
163
-     *                                                                  EED_Modules used by the addon
164
-     * @type string                   $shortcode_paths                  an array of full server paths to folders
165
-     *                                                                  that contain EES_Shortcodes
166
-     * @type string                   $widget_paths                     an array of full server paths to folders
167
-     *                                                                  that contain WP_Widgets
168
-     * @type string                   $pue_options
169
-     * @type array                    $capabilities                     an array indexed by role name
170
-     *                                                                  (i.e administrator,author ) and the values
171
-     *                                                                  are an array of caps to add to the role.
172
-     *                                                                  'administrator' => array(
173
-     *                                                                  'read_addon',
174
-     *                                                                  'edit_addon',
175
-     *                                                                  etc.
176
-     *                                                                  ).
177
-     * @type EE_Meta_Capability_Map[] $capability_maps                  an array of EE_Meta_Capability_Map object
178
-     *                                                                  for any addons that need to register any
179
-     *                                                                  special meta mapped capabilities.  Should
180
-     *                                                                  be indexed where the key is the
181
-     *                                                                  EE_Meta_Capability_Map class name and the
182
-     *                                                                  values are the arguments sent to the class.
183
-     * @type array                    $model_paths                      array of folders containing DB models
184
-     * @see      EE_Register_Model
185
-     * @type array                    $class_paths                      array of folders containing DB classes
186
-     * @see      EE_Register_Model
187
-     * @type array                    $model_extension_paths            array of folders containing DB model
188
-     *                                                                  extensions
189
-     * @see      EE_Register_Model_Extension
190
-     * @type array                    $class_extension_paths            array of folders containing DB class
191
-     *                                                                  extensions
192
-     * @see      EE_Register_Model_Extension
193
-     * @type array message_types {
194
-     *                                                                  An array of message types with the key as
195
-     *                                                                  the message type name and the values as
196
-     *                                                                  below:
197
-     * @type string $mtfilename                                         [Required] The filename of the message type
198
-     *                                                                  being registered. This will be the main
199
-     *                                                                  EE_{Message Type Name}_message_type class.
200
-     *                                                                  for example:
201
-     *                                                                  EE_Declined_Registration_message_type.class.php
202
-     * @type array                    $autoloadpaths                    [Required] An array of paths to add to the
203
-     *                                                                  messages autoloader for the new message type.
204
-     * @type array                    $messengers_to_activate_with      An array of messengers that this message
205
-     *                                                                  type should activate with. Each value in
206
-     *                                                                  the
207
-     *                                                                  array
208
-     *                                                                  should match the name property of a
209
-     *                                                                  EE_messenger. Optional.
210
-     * @type array                    $messengers_to_validate_with      An array of messengers that this message
211
-     *                                                                  type should validate with. Each value in
212
-     *                                                                  the
213
-     *                                                                  array
214
-     *                                                                  should match the name property of an
215
-     *                                                                  EE_messenger.
216
-     *                                                                  Optional.
217
-     *                                                                  }
218
-     * @type array                    $custom_post_types
219
-     * @type array                    $custom_taxonomies
220
-     * @type array                    $payment_method_paths             each element is the folder containing the
221
-     *                                                                  EE_PMT_Base child class
222
-     *                                                                  (eg,
223
-     *                                                                  '/wp-content/plugins/my_plugin/Payomatic/'
224
-     *                                                                  which contains the files
225
-     *                                                                  EE_PMT_Payomatic.pm.php)
226
-     * @type array                    $default_terms
227
-     * @type array                    $namespace                        {
228
-     *                                                                  An array with two items for registering the
229
-     *                                                                  addon's namespace. (If, for some reason, you
230
-     *                                                                  require additional namespaces,
231
-     *                                                                  use
232
-     *                                                                  EventEspresso\core\Psr4Autoloader::addNamespace()
233
-     *                                                                  directly)
234
-     * @see      EventEspresso\core\Psr4Autoloader::addNamespace()
235
-     * @type string                   $FQNS                             the namespace prefix
236
-     * @type string                   $DIR                              a base directory for class files in the
237
-     *                                                                  namespace.
238
-     *                                                                  }
239
-     *                                                                  }
240
-     * @return void
241
-     * @throws DomainException
242
-     * @throws EE_Error
243
-     * @throws InvalidArgumentException
244
-     * @throws ReflectionException
245
-     * @throws InvalidDataTypeException
246
-     * @throws InvalidInterfaceException
247
-     */
248
-    public static function register($addon_name = '', $setup_args = array())
249
-    {
250
-        // required fields MUST be present, so let's make sure they are.
251
-        EE_Register_Addon::_verify_parameters($addon_name, $setup_args);
252
-        // get class name for addon
253
-        $class_name = EE_Register_Addon::_parse_class_name($addon_name, $setup_args);
254
-        //setup $_settings array from incoming values.
255
-        $addon_settings = EE_Register_Addon::_get_addon_settings($class_name, $setup_args);
256
-        // setup PUE
257
-        EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
258
-        // does this addon work with this version of core or WordPress ?
259
-        if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
260
-            return;
261
-        }
262
-        // register namespaces
263
-        EE_Register_Addon::_setup_namespaces($addon_settings);
264
-        // check if this is an activation request
265
-        if (EE_Register_Addon::_addon_activation($addon_name, $addon_settings)) {
266
-            // dont bother setting up the rest of the addon atm
267
-            return;
268
-        }
269
-        // we need cars
270
-        EE_Register_Addon::_setup_autoloaders($addon_name);
271
-        // register new models and extensions
272
-        EE_Register_Addon::_register_models_and_extensions($addon_name);
273
-        // setup DMS
274
-        EE_Register_Addon::_register_data_migration_scripts($addon_name);
275
-        // if config_class is present let's register config.
276
-        EE_Register_Addon::_register_config($addon_name);
277
-        // register admin pages
278
-        EE_Register_Addon::_register_admin_pages($addon_name);
279
-        // add to list of modules to be registered
280
-        EE_Register_Addon::_register_modules($addon_name);
281
-        // add to list of shortcodes to be registered
282
-        EE_Register_Addon::_register_shortcodes($addon_name);
283
-        // add to list of widgets to be registered
284
-        EE_Register_Addon::_register_widgets($addon_name);
285
-        // register capability related stuff.
286
-        EE_Register_Addon::_register_capabilities($addon_name);
287
-        // any message type to register?
288
-        EE_Register_Addon::_register_message_types($addon_name);
289
-        // any custom post type/ custom capabilities or default terms to register
290
-        EE_Register_Addon::_register_custom_post_types($addon_name);
291
-        // and any payment methods
292
-        EE_Register_Addon::_register_payment_methods($addon_name);
293
-        // load and instantiate main addon class
294
-        $addon = EE_Register_Addon::_load_and_init_addon_class($addon_name);
295
-        //delay calling after_registration hook on each addon until after all add-ons have been registered.
296
-        add_action('AHEE__EE_System__load_espresso_addons__complete', array($addon, 'after_registration'), 999);
297
-    }
109
+	/**
110
+	 * Method for registering new EE_Addons.
111
+	 * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE
112
+	 * AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. However, it
113
+	 * may also be called after the 'activate_plugin' action (when an addon is activated), because an activating addon
114
+	 * won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. If its called after
115
+	 * 'activate_plugin', it registers the addon still, but its components are not registered
116
+	 * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do
117
+	 * anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns
118
+	 * (so that we can detect that the addon has activated on the subsequent request)
119
+	 *
120
+	 * @since    4.3.0
121
+	 * @param string                  $addon_name                       [Required] the EE_Addon's name.
122
+	 * @param  array                  $setup_args                       {
123
+	 *                                                                  An array of arguments provided for registering
124
+	 *                                                                  the message type.
125
+	 * @type  string                  $class_name                       the addon's main file name.
126
+	 *                                                                  If left blank, generated from the addon name,
127
+	 *                                                                  changes something like "calendar" to
128
+	 *                                                                  "EE_Calendar"
129
+	 * @type string                   $min_core_version                 the minimum version of EE Core that the
130
+	 *                                                                  addon will work with. eg "4.8.1.rc.084"
131
+	 * @type string                   $version                          the "software" version for the addon. eg
132
+	 *                                                                  "1.0.0.p" for a first stable release, or
133
+	 *                                                                  "1.0.0.rc.043" for a version in progress
134
+	 * @type string                   $main_file_path                   the full server path to the main file
135
+	 *                                                                  loaded directly by WP
136
+	 * @type string                   $domain_fqcn                      Fully Qualified Class Name
137
+	 *                                                                  for the addon's Domain class
138
+	 *                                                                  (see EventEspresso\core\domain\Domain)
139
+	 * @type string                   $admin_path                       full server path to the folder where the
140
+	 *                                                                  addon\'s admin files reside
141
+	 * @type string                   $admin_callback                   a method to be called when the EE Admin is
142
+	 *                                                                  first invoked, can be used for hooking into
143
+	 *                                                                  any admin page
144
+	 * @type string                   $config_section                   the section name for this addon's
145
+	 *                                                                  configuration settings section
146
+	 *                                                                  (defaults to "addons")
147
+	 * @type string                   $config_class                     the class name for this addon's
148
+	 *                                                                  configuration settings object
149
+	 * @type string                   $config_name                      the class name for this addon's
150
+	 *                                                                  configuration settings object
151
+	 * @type string $autoloader_paths                                   [Required] an array of class names and the full
152
+	 *                                                                  server paths to those files.
153
+	 * @type string                   $autoloader_folders               an array of  "full server paths" for any
154
+	 *                                                                  folders containing classes that might be
155
+	 *                                                                  invoked by the addon
156
+	 * @type string                   $dms_paths                        [Required] an array of full server paths to
157
+	 *                                                                  folders that contain data migration scripts.
158
+	 *                                                                  The key should be the EE_Addon class name that
159
+	 *                                                                  this set of data migration scripts belongs to.
160
+	 *                                                                  If the EE_Addon class is namespaced, then this
161
+	 *                                                                  needs to be the Fully Qualified Class Name
162
+	 * @type string                   $module_paths                     an array of full server paths to any
163
+	 *                                                                  EED_Modules used by the addon
164
+	 * @type string                   $shortcode_paths                  an array of full server paths to folders
165
+	 *                                                                  that contain EES_Shortcodes
166
+	 * @type string                   $widget_paths                     an array of full server paths to folders
167
+	 *                                                                  that contain WP_Widgets
168
+	 * @type string                   $pue_options
169
+	 * @type array                    $capabilities                     an array indexed by role name
170
+	 *                                                                  (i.e administrator,author ) and the values
171
+	 *                                                                  are an array of caps to add to the role.
172
+	 *                                                                  'administrator' => array(
173
+	 *                                                                  'read_addon',
174
+	 *                                                                  'edit_addon',
175
+	 *                                                                  etc.
176
+	 *                                                                  ).
177
+	 * @type EE_Meta_Capability_Map[] $capability_maps                  an array of EE_Meta_Capability_Map object
178
+	 *                                                                  for any addons that need to register any
179
+	 *                                                                  special meta mapped capabilities.  Should
180
+	 *                                                                  be indexed where the key is the
181
+	 *                                                                  EE_Meta_Capability_Map class name and the
182
+	 *                                                                  values are the arguments sent to the class.
183
+	 * @type array                    $model_paths                      array of folders containing DB models
184
+	 * @see      EE_Register_Model
185
+	 * @type array                    $class_paths                      array of folders containing DB classes
186
+	 * @see      EE_Register_Model
187
+	 * @type array                    $model_extension_paths            array of folders containing DB model
188
+	 *                                                                  extensions
189
+	 * @see      EE_Register_Model_Extension
190
+	 * @type array                    $class_extension_paths            array of folders containing DB class
191
+	 *                                                                  extensions
192
+	 * @see      EE_Register_Model_Extension
193
+	 * @type array message_types {
194
+	 *                                                                  An array of message types with the key as
195
+	 *                                                                  the message type name and the values as
196
+	 *                                                                  below:
197
+	 * @type string $mtfilename                                         [Required] The filename of the message type
198
+	 *                                                                  being registered. This will be the main
199
+	 *                                                                  EE_{Message Type Name}_message_type class.
200
+	 *                                                                  for example:
201
+	 *                                                                  EE_Declined_Registration_message_type.class.php
202
+	 * @type array                    $autoloadpaths                    [Required] An array of paths to add to the
203
+	 *                                                                  messages autoloader for the new message type.
204
+	 * @type array                    $messengers_to_activate_with      An array of messengers that this message
205
+	 *                                                                  type should activate with. Each value in
206
+	 *                                                                  the
207
+	 *                                                                  array
208
+	 *                                                                  should match the name property of a
209
+	 *                                                                  EE_messenger. Optional.
210
+	 * @type array                    $messengers_to_validate_with      An array of messengers that this message
211
+	 *                                                                  type should validate with. Each value in
212
+	 *                                                                  the
213
+	 *                                                                  array
214
+	 *                                                                  should match the name property of an
215
+	 *                                                                  EE_messenger.
216
+	 *                                                                  Optional.
217
+	 *                                                                  }
218
+	 * @type array                    $custom_post_types
219
+	 * @type array                    $custom_taxonomies
220
+	 * @type array                    $payment_method_paths             each element is the folder containing the
221
+	 *                                                                  EE_PMT_Base child class
222
+	 *                                                                  (eg,
223
+	 *                                                                  '/wp-content/plugins/my_plugin/Payomatic/'
224
+	 *                                                                  which contains the files
225
+	 *                                                                  EE_PMT_Payomatic.pm.php)
226
+	 * @type array                    $default_terms
227
+	 * @type array                    $namespace                        {
228
+	 *                                                                  An array with two items for registering the
229
+	 *                                                                  addon's namespace. (If, for some reason, you
230
+	 *                                                                  require additional namespaces,
231
+	 *                                                                  use
232
+	 *                                                                  EventEspresso\core\Psr4Autoloader::addNamespace()
233
+	 *                                                                  directly)
234
+	 * @see      EventEspresso\core\Psr4Autoloader::addNamespace()
235
+	 * @type string                   $FQNS                             the namespace prefix
236
+	 * @type string                   $DIR                              a base directory for class files in the
237
+	 *                                                                  namespace.
238
+	 *                                                                  }
239
+	 *                                                                  }
240
+	 * @return void
241
+	 * @throws DomainException
242
+	 * @throws EE_Error
243
+	 * @throws InvalidArgumentException
244
+	 * @throws ReflectionException
245
+	 * @throws InvalidDataTypeException
246
+	 * @throws InvalidInterfaceException
247
+	 */
248
+	public static function register($addon_name = '', $setup_args = array())
249
+	{
250
+		// required fields MUST be present, so let's make sure they are.
251
+		EE_Register_Addon::_verify_parameters($addon_name, $setup_args);
252
+		// get class name for addon
253
+		$class_name = EE_Register_Addon::_parse_class_name($addon_name, $setup_args);
254
+		//setup $_settings array from incoming values.
255
+		$addon_settings = EE_Register_Addon::_get_addon_settings($class_name, $setup_args);
256
+		// setup PUE
257
+		EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
258
+		// does this addon work with this version of core or WordPress ?
259
+		if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
260
+			return;
261
+		}
262
+		// register namespaces
263
+		EE_Register_Addon::_setup_namespaces($addon_settings);
264
+		// check if this is an activation request
265
+		if (EE_Register_Addon::_addon_activation($addon_name, $addon_settings)) {
266
+			// dont bother setting up the rest of the addon atm
267
+			return;
268
+		}
269
+		// we need cars
270
+		EE_Register_Addon::_setup_autoloaders($addon_name);
271
+		// register new models and extensions
272
+		EE_Register_Addon::_register_models_and_extensions($addon_name);
273
+		// setup DMS
274
+		EE_Register_Addon::_register_data_migration_scripts($addon_name);
275
+		// if config_class is present let's register config.
276
+		EE_Register_Addon::_register_config($addon_name);
277
+		// register admin pages
278
+		EE_Register_Addon::_register_admin_pages($addon_name);
279
+		// add to list of modules to be registered
280
+		EE_Register_Addon::_register_modules($addon_name);
281
+		// add to list of shortcodes to be registered
282
+		EE_Register_Addon::_register_shortcodes($addon_name);
283
+		// add to list of widgets to be registered
284
+		EE_Register_Addon::_register_widgets($addon_name);
285
+		// register capability related stuff.
286
+		EE_Register_Addon::_register_capabilities($addon_name);
287
+		// any message type to register?
288
+		EE_Register_Addon::_register_message_types($addon_name);
289
+		// any custom post type/ custom capabilities or default terms to register
290
+		EE_Register_Addon::_register_custom_post_types($addon_name);
291
+		// and any payment methods
292
+		EE_Register_Addon::_register_payment_methods($addon_name);
293
+		// load and instantiate main addon class
294
+		$addon = EE_Register_Addon::_load_and_init_addon_class($addon_name);
295
+		//delay calling after_registration hook on each addon until after all add-ons have been registered.
296
+		add_action('AHEE__EE_System__load_espresso_addons__complete', array($addon, 'after_registration'), 999);
297
+	}
298 298
 
299 299
 
300
-    /**
301
-     * @param string $addon_name
302
-     * @param array  $setup_args
303
-     * @return void
304
-     * @throws EE_Error
305
-     */
306
-    private static function _verify_parameters($addon_name, array $setup_args)
307
-    {
308
-        // required fields MUST be present, so let's make sure they are.
309
-        if (empty($addon_name) || ! is_array($setup_args)) {
310
-            throw new EE_Error(
311
-                __(
312
-                    'In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.',
313
-                    'event_espresso'
314
-                )
315
-            );
316
-        }
317
-        if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
318
-            throw new EE_Error(
319
-                sprintf(
320
-                    __(
321
-                        'When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s',
322
-                        'event_espresso'
323
-                    ),
324
-                    implode(',', array_keys($setup_args))
325
-                )
326
-            );
327
-        }
328
-        // check that addon has not already been registered with that name
329
-        if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
330
-            throw new EE_Error(
331
-                sprintf(
332
-                    __(
333
-                        'An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.',
334
-                        'event_espresso'
335
-                    ),
336
-                    $addon_name
337
-                )
338
-            );
339
-        }
340
-    }
300
+	/**
301
+	 * @param string $addon_name
302
+	 * @param array  $setup_args
303
+	 * @return void
304
+	 * @throws EE_Error
305
+	 */
306
+	private static function _verify_parameters($addon_name, array $setup_args)
307
+	{
308
+		// required fields MUST be present, so let's make sure they are.
309
+		if (empty($addon_name) || ! is_array($setup_args)) {
310
+			throw new EE_Error(
311
+				__(
312
+					'In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.',
313
+					'event_espresso'
314
+				)
315
+			);
316
+		}
317
+		if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
318
+			throw new EE_Error(
319
+				sprintf(
320
+					__(
321
+						'When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s',
322
+						'event_espresso'
323
+					),
324
+					implode(',', array_keys($setup_args))
325
+				)
326
+			);
327
+		}
328
+		// check that addon has not already been registered with that name
329
+		if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
330
+			throw new EE_Error(
331
+				sprintf(
332
+					__(
333
+						'An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.',
334
+						'event_espresso'
335
+					),
336
+					$addon_name
337
+				)
338
+			);
339
+		}
340
+	}
341 341
 
342 342
 
343
-    /**
344
-     * @param string $addon_name
345
-     * @param array  $setup_args
346
-     * @return string
347
-     */
348
-    private static function _parse_class_name($addon_name, array $setup_args)
349
-    {
350
-        if (empty($setup_args['class_name'])) {
351
-            // generate one by first separating name with spaces
352
-            $class_name = str_replace(array('-', '_'), ' ', trim($addon_name));
353
-            //capitalize, then replace spaces with underscores
354
-            $class_name = str_replace(' ', '_', ucwords($class_name));
355
-        } else {
356
-            $class_name = $setup_args['class_name'];
357
-        }
358
-        // check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
359
-        return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
360
-            ? $class_name
361
-            : 'EE_' . $class_name;
362
-    }
343
+	/**
344
+	 * @param string $addon_name
345
+	 * @param array  $setup_args
346
+	 * @return string
347
+	 */
348
+	private static function _parse_class_name($addon_name, array $setup_args)
349
+	{
350
+		if (empty($setup_args['class_name'])) {
351
+			// generate one by first separating name with spaces
352
+			$class_name = str_replace(array('-', '_'), ' ', trim($addon_name));
353
+			//capitalize, then replace spaces with underscores
354
+			$class_name = str_replace(' ', '_', ucwords($class_name));
355
+		} else {
356
+			$class_name = $setup_args['class_name'];
357
+		}
358
+		// check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
359
+		return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
360
+			? $class_name
361
+			: 'EE_' . $class_name;
362
+	}
363 363
 
364 364
 
365
-    /**
366
-     * @param string $class_name
367
-     * @param array  $setup_args
368
-     * @return array
369
-     */
370
-    private static function _get_addon_settings($class_name, array $setup_args)
371
-    {
372
-        //setup $_settings array from incoming values.
373
-        $addon_settings = array(
374
-            // generated from the addon name, changes something like "calendar" to "EE_Calendar"
375
-            'class_name'            => $class_name,
376
-            // the addon slug for use in URLs, etc
377
-            'plugin_slug'           => isset($setup_args['plugin_slug'])
378
-                ? (string) $setup_args['plugin_slug']
379
-                : '',
380
-            // page slug to be used when generating the "Settings" link on the WP plugin page
381
-            'plugin_action_slug'    => isset($setup_args['plugin_action_slug'])
382
-                ? (string) $setup_args['plugin_action_slug']
383
-                : '',
384
-            // the "software" version for the addon
385
-            'version'               => isset($setup_args['version'])
386
-                ? (string) $setup_args['version']
387
-                : '',
388
-            // the minimum version of EE Core that the addon will work with
389
-            'min_core_version'      => isset($setup_args['min_core_version'])
390
-                ? (string) $setup_args['min_core_version']
391
-                : '',
392
-            // the minimum version of WordPress that the addon will work with
393
-            'min_wp_version'        => isset($setup_args['min_wp_version'])
394
-                ? (string) $setup_args['min_wp_version']
395
-                : EE_MIN_WP_VER_REQUIRED,
396
-            // full server path to main file (file loaded directly by WP)
397
-            'main_file_path'        => isset($setup_args['main_file_path'])
398
-                ? (string) $setup_args['main_file_path']
399
-                : '',
400
-            // Fully Qualified Class Name for the addon's Domain class
401
-            'domain_fqcn'           => isset($setup_args['domain_fqcn'])
402
-                ? (string) $setup_args['domain_fqcn']
403
-                : '',
404
-            // path to folder containing files for integrating with the EE core admin and/or setting up EE admin pages
405
-            'admin_path'            => isset($setup_args['admin_path'])
406
-                ? (string) $setup_args['admin_path'] : '',
407
-            // a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page
408
-            'admin_callback'        => isset($setup_args['admin_callback'])
409
-                ? (string) $setup_args['admin_callback']
410
-                : '',
411
-            // the section name for this addon's configuration settings section (defaults to "addons")
412
-            'config_section'        => isset($setup_args['config_section'])
413
-                ? (string) $setup_args['config_section']
414
-                : 'addons',
415
-            // the class name for this addon's configuration settings object
416
-            'config_class'          => isset($setup_args['config_class'])
417
-                ? (string) $setup_args['config_class'] : '',
418
-            //the name given to the config for this addons' configuration settings object (optional)
419
-            'config_name'           => isset($setup_args['config_name'])
420
-                ? (string) $setup_args['config_name'] : '',
421
-            // an array of "class names" => "full server paths" for any classes that might be invoked by the addon
422
-            'autoloader_paths'      => isset($setup_args['autoloader_paths'])
423
-                ? (array) $setup_args['autoloader_paths']
424
-                : array(),
425
-            // an array of  "full server paths" for any folders containing classes that might be invoked by the addon
426
-            'autoloader_folders'    => isset($setup_args['autoloader_folders'])
427
-                ? (array) $setup_args['autoloader_folders']
428
-                : array(),
429
-            // array of full server paths to any EE_DMS data migration scripts used by the addon.
430
-            // The key should be the EE_Addon class name that this set of data migration scripts belongs to.
431
-            // If the EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
432
-            'dms_paths'             => isset($setup_args['dms_paths'])
433
-                ? (array) $setup_args['dms_paths']
434
-                : array(),
435
-            // array of full server paths to any EED_Modules used by the addon
436
-            'module_paths'          => isset($setup_args['module_paths'])
437
-                ? (array) $setup_args['module_paths']
438
-                : array(),
439
-            // array of full server paths to any EES_Shortcodes used by the addon
440
-            'shortcode_paths'       => isset($setup_args['shortcode_paths'])
441
-                ? (array) $setup_args['shortcode_paths']
442
-                : array(),
443
-            'shortcode_fqcns'       => isset($setup_args['shortcode_fqcns'])
444
-                ? (array) $setup_args['shortcode_fqcns']
445
-                : array(),
446
-            // array of full server paths to any WP_Widgets used by the addon
447
-            'widget_paths'          => isset($setup_args['widget_paths'])
448
-                ? (array) $setup_args['widget_paths']
449
-                : array(),
450
-            // array of PUE options used by the addon
451
-            'pue_options'           => isset($setup_args['pue_options'])
452
-                ? (array) $setup_args['pue_options']
453
-                : array(),
454
-            'message_types'         => isset($setup_args['message_types'])
455
-                ? (array) $setup_args['message_types']
456
-                : array(),
457
-            'capabilities'          => isset($setup_args['capabilities'])
458
-                ? (array) $setup_args['capabilities']
459
-                : array(),
460
-            'capability_maps'       => isset($setup_args['capability_maps'])
461
-                ? (array) $setup_args['capability_maps']
462
-                : array(),
463
-            'model_paths'           => isset($setup_args['model_paths'])
464
-                ? (array) $setup_args['model_paths']
465
-                : array(),
466
-            'class_paths'           => isset($setup_args['class_paths'])
467
-                ? (array) $setup_args['class_paths']
468
-                : array(),
469
-            'model_extension_paths' => isset($setup_args['model_extension_paths'])
470
-                ? (array) $setup_args['model_extension_paths']
471
-                : array(),
472
-            'class_extension_paths' => isset($setup_args['class_extension_paths'])
473
-                ? (array) $setup_args['class_extension_paths']
474
-                : array(),
475
-            'custom_post_types'     => isset($setup_args['custom_post_types'])
476
-                ? (array) $setup_args['custom_post_types']
477
-                : array(),
478
-            'custom_taxonomies'     => isset($setup_args['custom_taxonomies'])
479
-                ? (array) $setup_args['custom_taxonomies']
480
-                : array(),
481
-            'payment_method_paths'  => isset($setup_args['payment_method_paths'])
482
-                ? (array) $setup_args['payment_method_paths']
483
-                : array(),
484
-            'default_terms'         => isset($setup_args['default_terms'])
485
-                ? (array) $setup_args['default_terms']
486
-                : array(),
487
-            // if not empty, inserts a new table row after this plugin's row on the WP Plugins page
488
-            // that can be used for adding upgrading/marketing info
489
-            'plugins_page_row'      => isset($setup_args['plugins_page_row'])
490
-                ? $setup_args['plugins_page_row']
491
-                : '',
492
-            'namespace'             => isset(
493
-                $setup_args['namespace']['FQNS'],
494
-                $setup_args['namespace']['DIR']
495
-            )
496
-                ? (array) $setup_args['namespace']
497
-                : array(),
498
-        );
499
-        // if plugin_action_slug is NOT set, but an admin page path IS set,
500
-        // then let's just use the plugin_slug since that will be used for linking to the admin page
501
-        $addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug'])
502
-                                                && ! empty($addon_settings['admin_path'])
503
-            ? $addon_settings['plugin_slug']
504
-            : $addon_settings['plugin_action_slug'];
505
-        // full server path to main file (file loaded directly by WP)
506
-        $addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']);
507
-        return $addon_settings;
508
-    }
365
+	/**
366
+	 * @param string $class_name
367
+	 * @param array  $setup_args
368
+	 * @return array
369
+	 */
370
+	private static function _get_addon_settings($class_name, array $setup_args)
371
+	{
372
+		//setup $_settings array from incoming values.
373
+		$addon_settings = array(
374
+			// generated from the addon name, changes something like "calendar" to "EE_Calendar"
375
+			'class_name'            => $class_name,
376
+			// the addon slug for use in URLs, etc
377
+			'plugin_slug'           => isset($setup_args['plugin_slug'])
378
+				? (string) $setup_args['plugin_slug']
379
+				: '',
380
+			// page slug to be used when generating the "Settings" link on the WP plugin page
381
+			'plugin_action_slug'    => isset($setup_args['plugin_action_slug'])
382
+				? (string) $setup_args['plugin_action_slug']
383
+				: '',
384
+			// the "software" version for the addon
385
+			'version'               => isset($setup_args['version'])
386
+				? (string) $setup_args['version']
387
+				: '',
388
+			// the minimum version of EE Core that the addon will work with
389
+			'min_core_version'      => isset($setup_args['min_core_version'])
390
+				? (string) $setup_args['min_core_version']
391
+				: '',
392
+			// the minimum version of WordPress that the addon will work with
393
+			'min_wp_version'        => isset($setup_args['min_wp_version'])
394
+				? (string) $setup_args['min_wp_version']
395
+				: EE_MIN_WP_VER_REQUIRED,
396
+			// full server path to main file (file loaded directly by WP)
397
+			'main_file_path'        => isset($setup_args['main_file_path'])
398
+				? (string) $setup_args['main_file_path']
399
+				: '',
400
+			// Fully Qualified Class Name for the addon's Domain class
401
+			'domain_fqcn'           => isset($setup_args['domain_fqcn'])
402
+				? (string) $setup_args['domain_fqcn']
403
+				: '',
404
+			// path to folder containing files for integrating with the EE core admin and/or setting up EE admin pages
405
+			'admin_path'            => isset($setup_args['admin_path'])
406
+				? (string) $setup_args['admin_path'] : '',
407
+			// a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page
408
+			'admin_callback'        => isset($setup_args['admin_callback'])
409
+				? (string) $setup_args['admin_callback']
410
+				: '',
411
+			// the section name for this addon's configuration settings section (defaults to "addons")
412
+			'config_section'        => isset($setup_args['config_section'])
413
+				? (string) $setup_args['config_section']
414
+				: 'addons',
415
+			// the class name for this addon's configuration settings object
416
+			'config_class'          => isset($setup_args['config_class'])
417
+				? (string) $setup_args['config_class'] : '',
418
+			//the name given to the config for this addons' configuration settings object (optional)
419
+			'config_name'           => isset($setup_args['config_name'])
420
+				? (string) $setup_args['config_name'] : '',
421
+			// an array of "class names" => "full server paths" for any classes that might be invoked by the addon
422
+			'autoloader_paths'      => isset($setup_args['autoloader_paths'])
423
+				? (array) $setup_args['autoloader_paths']
424
+				: array(),
425
+			// an array of  "full server paths" for any folders containing classes that might be invoked by the addon
426
+			'autoloader_folders'    => isset($setup_args['autoloader_folders'])
427
+				? (array) $setup_args['autoloader_folders']
428
+				: array(),
429
+			// array of full server paths to any EE_DMS data migration scripts used by the addon.
430
+			// The key should be the EE_Addon class name that this set of data migration scripts belongs to.
431
+			// If the EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
432
+			'dms_paths'             => isset($setup_args['dms_paths'])
433
+				? (array) $setup_args['dms_paths']
434
+				: array(),
435
+			// array of full server paths to any EED_Modules used by the addon
436
+			'module_paths'          => isset($setup_args['module_paths'])
437
+				? (array) $setup_args['module_paths']
438
+				: array(),
439
+			// array of full server paths to any EES_Shortcodes used by the addon
440
+			'shortcode_paths'       => isset($setup_args['shortcode_paths'])
441
+				? (array) $setup_args['shortcode_paths']
442
+				: array(),
443
+			'shortcode_fqcns'       => isset($setup_args['shortcode_fqcns'])
444
+				? (array) $setup_args['shortcode_fqcns']
445
+				: array(),
446
+			// array of full server paths to any WP_Widgets used by the addon
447
+			'widget_paths'          => isset($setup_args['widget_paths'])
448
+				? (array) $setup_args['widget_paths']
449
+				: array(),
450
+			// array of PUE options used by the addon
451
+			'pue_options'           => isset($setup_args['pue_options'])
452
+				? (array) $setup_args['pue_options']
453
+				: array(),
454
+			'message_types'         => isset($setup_args['message_types'])
455
+				? (array) $setup_args['message_types']
456
+				: array(),
457
+			'capabilities'          => isset($setup_args['capabilities'])
458
+				? (array) $setup_args['capabilities']
459
+				: array(),
460
+			'capability_maps'       => isset($setup_args['capability_maps'])
461
+				? (array) $setup_args['capability_maps']
462
+				: array(),
463
+			'model_paths'           => isset($setup_args['model_paths'])
464
+				? (array) $setup_args['model_paths']
465
+				: array(),
466
+			'class_paths'           => isset($setup_args['class_paths'])
467
+				? (array) $setup_args['class_paths']
468
+				: array(),
469
+			'model_extension_paths' => isset($setup_args['model_extension_paths'])
470
+				? (array) $setup_args['model_extension_paths']
471
+				: array(),
472
+			'class_extension_paths' => isset($setup_args['class_extension_paths'])
473
+				? (array) $setup_args['class_extension_paths']
474
+				: array(),
475
+			'custom_post_types'     => isset($setup_args['custom_post_types'])
476
+				? (array) $setup_args['custom_post_types']
477
+				: array(),
478
+			'custom_taxonomies'     => isset($setup_args['custom_taxonomies'])
479
+				? (array) $setup_args['custom_taxonomies']
480
+				: array(),
481
+			'payment_method_paths'  => isset($setup_args['payment_method_paths'])
482
+				? (array) $setup_args['payment_method_paths']
483
+				: array(),
484
+			'default_terms'         => isset($setup_args['default_terms'])
485
+				? (array) $setup_args['default_terms']
486
+				: array(),
487
+			// if not empty, inserts a new table row after this plugin's row on the WP Plugins page
488
+			// that can be used for adding upgrading/marketing info
489
+			'plugins_page_row'      => isset($setup_args['plugins_page_row'])
490
+				? $setup_args['plugins_page_row']
491
+				: '',
492
+			'namespace'             => isset(
493
+				$setup_args['namespace']['FQNS'],
494
+				$setup_args['namespace']['DIR']
495
+			)
496
+				? (array) $setup_args['namespace']
497
+				: array(),
498
+		);
499
+		// if plugin_action_slug is NOT set, but an admin page path IS set,
500
+		// then let's just use the plugin_slug since that will be used for linking to the admin page
501
+		$addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug'])
502
+												&& ! empty($addon_settings['admin_path'])
503
+			? $addon_settings['plugin_slug']
504
+			: $addon_settings['plugin_action_slug'];
505
+		// full server path to main file (file loaded directly by WP)
506
+		$addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']);
507
+		return $addon_settings;
508
+	}
509 509
 
510 510
 
511
-    /**
512
-     * @param string $addon_name
513
-     * @param array  $addon_settings
514
-     * @return boolean
515
-     */
516
-    private static function _addon_is_compatible($addon_name, array $addon_settings)
517
-    {
518
-        global $wp_version;
519
-        $incompatibility_message = '';
520
-        //check whether this addon version is compatible with EE core
521
-        if (
522
-            isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
523
-            && ! self::_meets_min_core_version_requirement(
524
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
525
-                $addon_settings['version']
526
-            )
527
-        ) {
528
-            $incompatibility_message = sprintf(
529
-                __(
530
-                    '%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon is not compatible with this version of Event Espresso.%2$sPlease upgrade your "%1$s" addon to version %3$s or newer to resolve this issue.'
531
-                ),
532
-                $addon_name,
533
-                '<br />',
534
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
535
-                '<span style="font-weight: bold; color: #D54E21;">',
536
-                '</span><br />'
537
-            );
538
-        } elseif (
539
-        ! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
540
-        ) {
541
-            $incompatibility_message = sprintf(
542
-                __(
543
-                    '%5$sIMPORTANT!%6$sThe Event Espresso "%1$s" addon requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-activate "%1$s".',
544
-                    'event_espresso'
545
-                ),
546
-                $addon_name,
547
-                self::_effective_version($addon_settings['min_core_version']),
548
-                self::_effective_version(espresso_version()),
549
-                '<br />',
550
-                '<span style="font-weight: bold; color: #D54E21;">',
551
-                '</span><br />'
552
-            );
553
-        } elseif (version_compare($wp_version, $addon_settings['min_wp_version'], '<')) {
554
-            $incompatibility_message = sprintf(
555
-                __(
556
-                    '%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon requires WordPress version "%2$s" or greater.%3$sPlease update your version of WordPress to use the "%1$s" addon and to keep your site secure.',
557
-                    'event_espresso'
558
-                ),
559
-                $addon_name,
560
-                $addon_settings['min_wp_version'],
561
-                '<br />',
562
-                '<span style="font-weight: bold; color: #D54E21;">',
563
-                '</span><br />'
564
-            );
565
-        }
566
-        if (! empty($incompatibility_message)) {
567
-            // remove 'activate' from the REQUEST
568
-            // so WP doesn't erroneously tell the user the plugin activated fine when it didn't
569
-            unset($_GET['activate'], $_REQUEST['activate']);
570
-            if (current_user_can('activate_plugins')) {
571
-                // show an error message indicating the plugin didn't activate properly
572
-                EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
573
-            }
574
-            // BAIL FROM THE ADDON REGISTRATION PROCESS
575
-            return false;
576
-        }
577
-        // addon IS compatible
578
-        return true;
579
-    }
511
+	/**
512
+	 * @param string $addon_name
513
+	 * @param array  $addon_settings
514
+	 * @return boolean
515
+	 */
516
+	private static function _addon_is_compatible($addon_name, array $addon_settings)
517
+	{
518
+		global $wp_version;
519
+		$incompatibility_message = '';
520
+		//check whether this addon version is compatible with EE core
521
+		if (
522
+			isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
523
+			&& ! self::_meets_min_core_version_requirement(
524
+				EE_Register_Addon::$_incompatible_addons[ $addon_name ],
525
+				$addon_settings['version']
526
+			)
527
+		) {
528
+			$incompatibility_message = sprintf(
529
+				__(
530
+					'%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon is not compatible with this version of Event Espresso.%2$sPlease upgrade your "%1$s" addon to version %3$s or newer to resolve this issue.'
531
+				),
532
+				$addon_name,
533
+				'<br />',
534
+				EE_Register_Addon::$_incompatible_addons[ $addon_name ],
535
+				'<span style="font-weight: bold; color: #D54E21;">',
536
+				'</span><br />'
537
+			);
538
+		} elseif (
539
+		! self::_meets_min_core_version_requirement($addon_settings['min_core_version'], espresso_version())
540
+		) {
541
+			$incompatibility_message = sprintf(
542
+				__(
543
+					'%5$sIMPORTANT!%6$sThe Event Espresso "%1$s" addon requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-activate "%1$s".',
544
+					'event_espresso'
545
+				),
546
+				$addon_name,
547
+				self::_effective_version($addon_settings['min_core_version']),
548
+				self::_effective_version(espresso_version()),
549
+				'<br />',
550
+				'<span style="font-weight: bold; color: #D54E21;">',
551
+				'</span><br />'
552
+			);
553
+		} elseif (version_compare($wp_version, $addon_settings['min_wp_version'], '<')) {
554
+			$incompatibility_message = sprintf(
555
+				__(
556
+					'%4$sIMPORTANT!%5$sThe Event Espresso "%1$s" addon requires WordPress version "%2$s" or greater.%3$sPlease update your version of WordPress to use the "%1$s" addon and to keep your site secure.',
557
+					'event_espresso'
558
+				),
559
+				$addon_name,
560
+				$addon_settings['min_wp_version'],
561
+				'<br />',
562
+				'<span style="font-weight: bold; color: #D54E21;">',
563
+				'</span><br />'
564
+			);
565
+		}
566
+		if (! empty($incompatibility_message)) {
567
+			// remove 'activate' from the REQUEST
568
+			// so WP doesn't erroneously tell the user the plugin activated fine when it didn't
569
+			unset($_GET['activate'], $_REQUEST['activate']);
570
+			if (current_user_can('activate_plugins')) {
571
+				// show an error message indicating the plugin didn't activate properly
572
+				EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__);
573
+			}
574
+			// BAIL FROM THE ADDON REGISTRATION PROCESS
575
+			return false;
576
+		}
577
+		// addon IS compatible
578
+		return true;
579
+	}
580 580
 
581 581
 
582
-    /**
583
-     * if plugin update engine is being used for auto-updates,
584
-     * then let's set that up now before going any further so that ALL addons can be updated
585
-     * (not needed if PUE is not being used)
586
-     *
587
-     * @param string $addon_name
588
-     * @param string $class_name
589
-     * @param array  $setup_args
590
-     * @return void
591
-     */
592
-    private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
593
-    {
594
-        if (! empty($setup_args['pue_options'])) {
595
-            self::$_settings[ $addon_name ]['pue_options'] = array(
596
-                'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
597
-                    ? (string) $setup_args['pue_options']['pue_plugin_slug']
598
-                    : 'espresso_' . strtolower($class_name),
599
-                'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
600
-                    ? (string) $setup_args['pue_options']['plugin_basename']
601
-                    : plugin_basename($setup_args['main_file_path']),
602
-                'checkPeriod'     => isset($setup_args['pue_options']['checkPeriod'])
603
-                    ? (string) $setup_args['pue_options']['checkPeriod']
604
-                    : '24',
605
-                'use_wp_update'   => isset($setup_args['pue_options']['use_wp_update'])
606
-                    ? (string) $setup_args['pue_options']['use_wp_update']
607
-                    : false,
608
-            );
609
-            add_action(
610
-                'AHEE__EE_System__brew_espresso__after_pue_init',
611
-                array('EE_Register_Addon', 'load_pue_update')
612
-            );
613
-        }
614
-    }
582
+	/**
583
+	 * if plugin update engine is being used for auto-updates,
584
+	 * then let's set that up now before going any further so that ALL addons can be updated
585
+	 * (not needed if PUE is not being used)
586
+	 *
587
+	 * @param string $addon_name
588
+	 * @param string $class_name
589
+	 * @param array  $setup_args
590
+	 * @return void
591
+	 */
592
+	private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
593
+	{
594
+		if (! empty($setup_args['pue_options'])) {
595
+			self::$_settings[ $addon_name ]['pue_options'] = array(
596
+				'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
597
+					? (string) $setup_args['pue_options']['pue_plugin_slug']
598
+					: 'espresso_' . strtolower($class_name),
599
+				'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
600
+					? (string) $setup_args['pue_options']['plugin_basename']
601
+					: plugin_basename($setup_args['main_file_path']),
602
+				'checkPeriod'     => isset($setup_args['pue_options']['checkPeriod'])
603
+					? (string) $setup_args['pue_options']['checkPeriod']
604
+					: '24',
605
+				'use_wp_update'   => isset($setup_args['pue_options']['use_wp_update'])
606
+					? (string) $setup_args['pue_options']['use_wp_update']
607
+					: false,
608
+			);
609
+			add_action(
610
+				'AHEE__EE_System__brew_espresso__after_pue_init',
611
+				array('EE_Register_Addon', 'load_pue_update')
612
+			);
613
+		}
614
+	}
615 615
 
616 616
 
617
-    /**
618
-     * register namespaces right away before any other files or classes get loaded, but AFTER the version checks
619
-     *
620
-     * @param array $addon_settings
621
-     * @return void
622
-     */
623
-    private static function _setup_namespaces(array $addon_settings)
624
-    {
625
-        //
626
-        if (
627
-        isset(
628
-            $addon_settings['namespace']['FQNS'],
629
-            $addon_settings['namespace']['DIR']
630
-        )
631
-        ) {
632
-            EE_Psr4AutoloaderInit::psr4_loader()->addNamespace(
633
-                $addon_settings['namespace']['FQNS'],
634
-                $addon_settings['namespace']['DIR']
635
-            );
636
-        }
637
-    }
617
+	/**
618
+	 * register namespaces right away before any other files or classes get loaded, but AFTER the version checks
619
+	 *
620
+	 * @param array $addon_settings
621
+	 * @return void
622
+	 */
623
+	private static function _setup_namespaces(array $addon_settings)
624
+	{
625
+		//
626
+		if (
627
+		isset(
628
+			$addon_settings['namespace']['FQNS'],
629
+			$addon_settings['namespace']['DIR']
630
+		)
631
+		) {
632
+			EE_Psr4AutoloaderInit::psr4_loader()->addNamespace(
633
+				$addon_settings['namespace']['FQNS'],
634
+				$addon_settings['namespace']['DIR']
635
+			);
636
+		}
637
+	}
638 638
 
639 639
 
640
-    /**
641
-     * @param string $addon_name
642
-     * @param array  $addon_settings
643
-     * @return bool
644
-     * @throws EE_Error
645
-     * @throws InvalidArgumentException
646
-     * @throws ReflectionException
647
-     * @throws InvalidDataTypeException
648
-     * @throws InvalidInterfaceException
649
-     */
650
-    private static function _addon_activation($addon_name, array $addon_settings)
651
-    {
652
-        // this is an activation request
653
-        if (did_action('activate_plugin')) {
654
-            //to find if THIS is the addon that was activated, just check if we have already registered it or not
655
-            //(as the newly-activated addon wasn't around the first time addons were registered).
656
-            //Note: the presence of pue_options in the addon registration options will initialize the $_settings
657
-            //property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
658
-            if (! isset(self::$_settings[ $addon_name ])
659
-                || (isset(self::$_settings[ $addon_name ])
660
-                    && ! isset(self::$_settings[ $addon_name ]['class_name'])
661
-                )
662
-            ) {
663
-                self::$_settings[ $addon_name ] = $addon_settings;
664
-                $addon                          = self::_load_and_init_addon_class($addon_name);
665
-                $addon->set_activation_indicator_option();
666
-                // dont bother setting up the rest of the addon.
667
-                // we know it was just activated and the request will end soon
668
-            }
669
-            return true;
670
-        }
671
-        // make sure this was called in the right place!
672
-        if (
673
-            ! did_action('AHEE__EE_System__load_espresso_addons')
674
-            || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
675
-        ) {
676
-            EE_Error::doing_it_wrong(
677
-                __METHOD__,
678
-                sprintf(
679
-                    __(
680
-                        'An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.',
681
-                        'event_espresso'
682
-                    ),
683
-                    $addon_name
684
-                ),
685
-                '4.3.0'
686
-            );
687
-        }
688
-        // make sure addon settings are set correctly without overwriting anything existing
689
-        if (isset(self::$_settings[ $addon_name ])) {
690
-            self::$_settings[ $addon_name ] += $addon_settings;
691
-        } else {
692
-            self::$_settings[ $addon_name ] = $addon_settings;
693
-        }
694
-        return false;
695
-    }
640
+	/**
641
+	 * @param string $addon_name
642
+	 * @param array  $addon_settings
643
+	 * @return bool
644
+	 * @throws EE_Error
645
+	 * @throws InvalidArgumentException
646
+	 * @throws ReflectionException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws InvalidInterfaceException
649
+	 */
650
+	private static function _addon_activation($addon_name, array $addon_settings)
651
+	{
652
+		// this is an activation request
653
+		if (did_action('activate_plugin')) {
654
+			//to find if THIS is the addon that was activated, just check if we have already registered it or not
655
+			//(as the newly-activated addon wasn't around the first time addons were registered).
656
+			//Note: the presence of pue_options in the addon registration options will initialize the $_settings
657
+			//property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
658
+			if (! isset(self::$_settings[ $addon_name ])
659
+				|| (isset(self::$_settings[ $addon_name ])
660
+					&& ! isset(self::$_settings[ $addon_name ]['class_name'])
661
+				)
662
+			) {
663
+				self::$_settings[ $addon_name ] = $addon_settings;
664
+				$addon                          = self::_load_and_init_addon_class($addon_name);
665
+				$addon->set_activation_indicator_option();
666
+				// dont bother setting up the rest of the addon.
667
+				// we know it was just activated and the request will end soon
668
+			}
669
+			return true;
670
+		}
671
+		// make sure this was called in the right place!
672
+		if (
673
+			! did_action('AHEE__EE_System__load_espresso_addons')
674
+			|| did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
675
+		) {
676
+			EE_Error::doing_it_wrong(
677
+				__METHOD__,
678
+				sprintf(
679
+					__(
680
+						'An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.',
681
+						'event_espresso'
682
+					),
683
+					$addon_name
684
+				),
685
+				'4.3.0'
686
+			);
687
+		}
688
+		// make sure addon settings are set correctly without overwriting anything existing
689
+		if (isset(self::$_settings[ $addon_name ])) {
690
+			self::$_settings[ $addon_name ] += $addon_settings;
691
+		} else {
692
+			self::$_settings[ $addon_name ] = $addon_settings;
693
+		}
694
+		return false;
695
+	}
696 696
 
697 697
 
698
-    /**
699
-     * @param string $addon_name
700
-     * @return void
701
-     * @throws EE_Error
702
-     */
703
-    private static function _setup_autoloaders($addon_name)
704
-    {
705
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
706
-            // setup autoloader for single file
707
-            EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
708
-        }
709
-        // setup autoloaders for folders
710
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
711
-            foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
712
-                EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
713
-            }
714
-        }
715
-    }
698
+	/**
699
+	 * @param string $addon_name
700
+	 * @return void
701
+	 * @throws EE_Error
702
+	 */
703
+	private static function _setup_autoloaders($addon_name)
704
+	{
705
+		if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
706
+			// setup autoloader for single file
707
+			EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
708
+		}
709
+		// setup autoloaders for folders
710
+		if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
711
+			foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
712
+				EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
713
+			}
714
+		}
715
+	}
716 716
 
717 717
 
718
-    /**
719
-     * register new models and extensions
720
-     *
721
-     * @param string $addon_name
722
-     * @return void
723
-     * @throws EE_Error
724
-     */
725
-    private static function _register_models_and_extensions($addon_name)
726
-    {
727
-        // register new models
728
-        if (
729
-            ! empty(self::$_settings[ $addon_name ]['model_paths'])
730
-            || ! empty(self::$_settings[ $addon_name ]['class_paths'])
731
-        ) {
732
-            EE_Register_Model::register(
733
-                $addon_name,
734
-                array(
735
-                    'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
736
-                    'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
737
-                )
738
-            );
739
-        }
740
-        // register model extensions
741
-        if (
742
-            ! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
743
-            || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
744
-        ) {
745
-            EE_Register_Model_Extensions::register(
746
-                $addon_name,
747
-                array(
748
-                    'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
749
-                    'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
750
-                )
751
-            );
752
-        }
753
-    }
718
+	/**
719
+	 * register new models and extensions
720
+	 *
721
+	 * @param string $addon_name
722
+	 * @return void
723
+	 * @throws EE_Error
724
+	 */
725
+	private static function _register_models_and_extensions($addon_name)
726
+	{
727
+		// register new models
728
+		if (
729
+			! empty(self::$_settings[ $addon_name ]['model_paths'])
730
+			|| ! empty(self::$_settings[ $addon_name ]['class_paths'])
731
+		) {
732
+			EE_Register_Model::register(
733
+				$addon_name,
734
+				array(
735
+					'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
736
+					'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
737
+				)
738
+			);
739
+		}
740
+		// register model extensions
741
+		if (
742
+			! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
743
+			|| ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
744
+		) {
745
+			EE_Register_Model_Extensions::register(
746
+				$addon_name,
747
+				array(
748
+					'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
749
+					'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
750
+				)
751
+			);
752
+		}
753
+	}
754 754
 
755 755
 
756
-    /**
757
-     * @param string $addon_name
758
-     * @return void
759
-     * @throws EE_Error
760
-     */
761
-    private static function _register_data_migration_scripts($addon_name)
762
-    {
763
-        // setup DMS
764
-        if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
765
-            EE_Register_Data_Migration_Scripts::register(
766
-                $addon_name,
767
-                array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
768
-            );
769
-        }
770
-    }
756
+	/**
757
+	 * @param string $addon_name
758
+	 * @return void
759
+	 * @throws EE_Error
760
+	 */
761
+	private static function _register_data_migration_scripts($addon_name)
762
+	{
763
+		// setup DMS
764
+		if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
765
+			EE_Register_Data_Migration_Scripts::register(
766
+				$addon_name,
767
+				array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
768
+			);
769
+		}
770
+	}
771 771
 
772 772
 
773
-    /**
774
-     * @param string $addon_name
775
-     * @return void
776
-     * @throws EE_Error
777
-     */
778
-    private static function _register_config($addon_name)
779
-    {
780
-        // if config_class is present let's register config.
781
-        if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
782
-            EE_Register_Config::register(
783
-                self::$_settings[ $addon_name ]['config_class'],
784
-                array(
785
-                    'config_section' => self::$_settings[ $addon_name ]['config_section'],
786
-                    'config_name'    => self::$_settings[ $addon_name ]['config_name'],
787
-                )
788
-            );
789
-        }
790
-    }
773
+	/**
774
+	 * @param string $addon_name
775
+	 * @return void
776
+	 * @throws EE_Error
777
+	 */
778
+	private static function _register_config($addon_name)
779
+	{
780
+		// if config_class is present let's register config.
781
+		if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
782
+			EE_Register_Config::register(
783
+				self::$_settings[ $addon_name ]['config_class'],
784
+				array(
785
+					'config_section' => self::$_settings[ $addon_name ]['config_section'],
786
+					'config_name'    => self::$_settings[ $addon_name ]['config_name'],
787
+				)
788
+			);
789
+		}
790
+	}
791 791
 
792 792
 
793
-    /**
794
-     * @param string $addon_name
795
-     * @return void
796
-     * @throws EE_Error
797
-     */
798
-    private static function _register_admin_pages($addon_name)
799
-    {
800
-        if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
801
-            EE_Register_Admin_Page::register(
802
-                $addon_name,
803
-                array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
804
-            );
805
-        }
806
-    }
793
+	/**
794
+	 * @param string $addon_name
795
+	 * @return void
796
+	 * @throws EE_Error
797
+	 */
798
+	private static function _register_admin_pages($addon_name)
799
+	{
800
+		if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
801
+			EE_Register_Admin_Page::register(
802
+				$addon_name,
803
+				array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
804
+			);
805
+		}
806
+	}
807 807
 
808 808
 
809
-    /**
810
-     * @param string $addon_name
811
-     * @return void
812
-     * @throws EE_Error
813
-     */
814
-    private static function _register_modules($addon_name)
815
-    {
816
-        if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
817
-            EE_Register_Module::register(
818
-                $addon_name,
819
-                array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
820
-            );
821
-        }
822
-    }
809
+	/**
810
+	 * @param string $addon_name
811
+	 * @return void
812
+	 * @throws EE_Error
813
+	 */
814
+	private static function _register_modules($addon_name)
815
+	{
816
+		if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
817
+			EE_Register_Module::register(
818
+				$addon_name,
819
+				array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
820
+			);
821
+		}
822
+	}
823 823
 
824 824
 
825
-    /**
826
-     * @param string $addon_name
827
-     * @return void
828
-     * @throws EE_Error
829
-     */
830
-    private static function _register_shortcodes($addon_name)
831
-    {
832
-        if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
833
-            || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
834
-        ) {
835
-            EE_Register_Shortcode::register(
836
-                $addon_name,
837
-                array(
838
-                    'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
839
-                        ? self::$_settings[ $addon_name ]['shortcode_paths']
840
-                        : array(),
841
-                    'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
842
-                        ? self::$_settings[ $addon_name ]['shortcode_fqcns']
843
-                        : array(),
844
-                )
845
-            );
846
-        }
847
-    }
825
+	/**
826
+	 * @param string $addon_name
827
+	 * @return void
828
+	 * @throws EE_Error
829
+	 */
830
+	private static function _register_shortcodes($addon_name)
831
+	{
832
+		if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
833
+			|| ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
834
+		) {
835
+			EE_Register_Shortcode::register(
836
+				$addon_name,
837
+				array(
838
+					'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
839
+						? self::$_settings[ $addon_name ]['shortcode_paths']
840
+						: array(),
841
+					'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
842
+						? self::$_settings[ $addon_name ]['shortcode_fqcns']
843
+						: array(),
844
+				)
845
+			);
846
+		}
847
+	}
848 848
 
849 849
 
850
-    /**
851
-     * @param string $addon_name
852
-     * @return void
853
-     * @throws EE_Error
854
-     */
855
-    private static function _register_widgets($addon_name)
856
-    {
857
-        if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
858
-            EE_Register_Widget::register(
859
-                $addon_name,
860
-                array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
861
-            );
862
-        }
863
-    }
850
+	/**
851
+	 * @param string $addon_name
852
+	 * @return void
853
+	 * @throws EE_Error
854
+	 */
855
+	private static function _register_widgets($addon_name)
856
+	{
857
+		if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
858
+			EE_Register_Widget::register(
859
+				$addon_name,
860
+				array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
861
+			);
862
+		}
863
+	}
864 864
 
865 865
 
866
-    /**
867
-     * @param string $addon_name
868
-     * @return void
869
-     * @throws EE_Error
870
-     */
871
-    private static function _register_capabilities($addon_name)
872
-    {
873
-        if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
874
-            EE_Register_Capabilities::register(
875
-                $addon_name,
876
-                array(
877
-                    'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
878
-                    'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
879
-                )
880
-            );
881
-        }
882
-    }
866
+	/**
867
+	 * @param string $addon_name
868
+	 * @return void
869
+	 * @throws EE_Error
870
+	 */
871
+	private static function _register_capabilities($addon_name)
872
+	{
873
+		if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
874
+			EE_Register_Capabilities::register(
875
+				$addon_name,
876
+				array(
877
+					'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
878
+					'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
879
+				)
880
+			);
881
+		}
882
+	}
883 883
 
884 884
 
885
-    /**
886
-     * @param string $addon_name
887
-     * @return void
888
-     * @throws EE_Error
889
-     */
890
-    private static function _register_message_types($addon_name)
891
-    {
892
-        if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
893
-            add_action(
894
-                'EE_Brewing_Regular___messages_caf',
895
-                array('EE_Register_Addon', 'register_message_types')
896
-            );
897
-        }
898
-    }
885
+	/**
886
+	 * @param string $addon_name
887
+	 * @return void
888
+	 * @throws EE_Error
889
+	 */
890
+	private static function _register_message_types($addon_name)
891
+	{
892
+		if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
893
+			add_action(
894
+				'EE_Brewing_Regular___messages_caf',
895
+				array('EE_Register_Addon', 'register_message_types')
896
+			);
897
+		}
898
+	}
899 899
 
900 900
 
901
-    /**
902
-     * @param string $addon_name
903
-     * @return void
904
-     * @throws EE_Error
905
-     */
906
-    private static function _register_custom_post_types($addon_name)
907
-    {
908
-        if (
909
-            ! empty(self::$_settings[ $addon_name ]['custom_post_types'])
910
-            || ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
911
-        ) {
912
-            EE_Register_CPT::register(
913
-                $addon_name,
914
-                array(
915
-                    'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
916
-                    'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
917
-                    'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
918
-                )
919
-            );
920
-        }
921
-    }
901
+	/**
902
+	 * @param string $addon_name
903
+	 * @return void
904
+	 * @throws EE_Error
905
+	 */
906
+	private static function _register_custom_post_types($addon_name)
907
+	{
908
+		if (
909
+			! empty(self::$_settings[ $addon_name ]['custom_post_types'])
910
+			|| ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
911
+		) {
912
+			EE_Register_CPT::register(
913
+				$addon_name,
914
+				array(
915
+					'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
916
+					'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
917
+					'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
918
+				)
919
+			);
920
+		}
921
+	}
922 922
 
923 923
 
924
-    /**
925
-     * @param string $addon_name
926
-     * @return void
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidInterfaceException
929
-     * @throws InvalidDataTypeException
930
-     * @throws DomainException
931
-     * @throws EE_Error
932
-     */
933
-    private static function _register_payment_methods($addon_name)
934
-    {
935
-        if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
936
-            EE_Register_Payment_Method::register(
937
-                $addon_name,
938
-                array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
939
-            );
940
-        }
941
-    }
924
+	/**
925
+	 * @param string $addon_name
926
+	 * @return void
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidInterfaceException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws DomainException
931
+	 * @throws EE_Error
932
+	 */
933
+	private static function _register_payment_methods($addon_name)
934
+	{
935
+		if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
936
+			EE_Register_Payment_Method::register(
937
+				$addon_name,
938
+				array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
939
+			);
940
+		}
941
+	}
942 942
 
943 943
 
944
-    /**
945
-     * Loads and instantiates the EE_Addon class and adds it onto the registry
946
-     *
947
-     * @param string $addon_name
948
-     * @return EE_Addon
949
-     * @throws InvalidArgumentException
950
-     * @throws InvalidInterfaceException
951
-     * @throws InvalidDataTypeException
952
-     * @throws ReflectionException
953
-     * @throws EE_Error
954
-     */
955
-    private static function _load_and_init_addon_class($addon_name)
956
-    {
957
-        $loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader();
958
-        $addon  = $loader->getShared(
959
-            self::$_settings[ $addon_name ]['class_name'],
960
-            array('EE_Registry::create(addon)' => true)
961
-        );
962
-        // setter inject dep map if required
963
-        if ($addon instanceof RequiresDependencyMapInterface && $addon->dependencyMap() === null) {
964
-            $addon->setDependencyMap($loader->getShared('EE_Dependency_Map'));
965
-        }
966
-        // setter inject domain if required
967
-        if (
968
-            $addon instanceof RequiresDomainInterface
969
-            && self::$_settings[ $addon_name ]['domain_fqcn'] !== ''
970
-            && $addon->domain() === null
971
-        ) {
972
-            $addon->setDomain(
973
-                $loader->getShared(
974
-                    self::$_settings[ $addon_name ]['domain_fqcn'],
975
-                    array(
976
-                        self::$_settings[ $addon_name ]['main_file_path'],
977
-                        self::$_settings[ $addon_name ]['version'],
978
-                    )
979
-                )
980
-            );
981
-        }
982
-        $addon->set_name($addon_name);
983
-        $addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
984
-        $addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
985
-        $addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
986
-        $addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
987
-        $addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
988
-        $addon->set_version(self::$_settings[ $addon_name ]['version']);
989
-        $addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
990
-        $addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
991
-        $addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
992
-        $addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
993
-        //unfortunately this can't be hooked in upon construction, because we don't have
994
-        //the plugin mainfile's path upon construction.
995
-        register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
996
-        // call any additional admin_callback functions during load_admin_controller hook
997
-        if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
998
-            add_action(
999
-                'AHEE__EE_System__load_controllers__load_admin_controllers',
1000
-                array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1001
-            );
1002
-        }
1003
-        return $addon;
1004
-    }
944
+	/**
945
+	 * Loads and instantiates the EE_Addon class and adds it onto the registry
946
+	 *
947
+	 * @param string $addon_name
948
+	 * @return EE_Addon
949
+	 * @throws InvalidArgumentException
950
+	 * @throws InvalidInterfaceException
951
+	 * @throws InvalidDataTypeException
952
+	 * @throws ReflectionException
953
+	 * @throws EE_Error
954
+	 */
955
+	private static function _load_and_init_addon_class($addon_name)
956
+	{
957
+		$loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader();
958
+		$addon  = $loader->getShared(
959
+			self::$_settings[ $addon_name ]['class_name'],
960
+			array('EE_Registry::create(addon)' => true)
961
+		);
962
+		// setter inject dep map if required
963
+		if ($addon instanceof RequiresDependencyMapInterface && $addon->dependencyMap() === null) {
964
+			$addon->setDependencyMap($loader->getShared('EE_Dependency_Map'));
965
+		}
966
+		// setter inject domain if required
967
+		if (
968
+			$addon instanceof RequiresDomainInterface
969
+			&& self::$_settings[ $addon_name ]['domain_fqcn'] !== ''
970
+			&& $addon->domain() === null
971
+		) {
972
+			$addon->setDomain(
973
+				$loader->getShared(
974
+					self::$_settings[ $addon_name ]['domain_fqcn'],
975
+					array(
976
+						self::$_settings[ $addon_name ]['main_file_path'],
977
+						self::$_settings[ $addon_name ]['version'],
978
+					)
979
+				)
980
+			);
981
+		}
982
+		$addon->set_name($addon_name);
983
+		$addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
984
+		$addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
985
+		$addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
986
+		$addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
987
+		$addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
988
+		$addon->set_version(self::$_settings[ $addon_name ]['version']);
989
+		$addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
990
+		$addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
991
+		$addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
992
+		$addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
993
+		//unfortunately this can't be hooked in upon construction, because we don't have
994
+		//the plugin mainfile's path upon construction.
995
+		register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
996
+		// call any additional admin_callback functions during load_admin_controller hook
997
+		if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
998
+			add_action(
999
+				'AHEE__EE_System__load_controllers__load_admin_controllers',
1000
+				array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1001
+			);
1002
+		}
1003
+		return $addon;
1004
+	}
1005 1005
 
1006 1006
 
1007
-    /**
1008
-     *    load_pue_update - Update notifications
1009
-     *
1010
-     * @return void
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidDataTypeException
1013
-     * @throws InvalidInterfaceException
1014
-     */
1015
-    public static function load_pue_update()
1016
-    {
1017
-        // load PUE client
1018
-        require_once EE_THIRD_PARTY . 'pue' . DS . 'pue-client.php';
1019
-        // cycle thru settings
1020
-        foreach (self::$_settings as $settings) {
1021
-            if (! empty($settings['pue_options'])) {
1022
-                // initiate the class and start the plugin update engine!
1023
-                new PluginUpdateEngineChecker(
1024
-                // host file URL
1025
-                    'https://eventespresso.com',
1026
-                    // plugin slug(s)
1027
-                    array(
1028
-                        'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1029
-                        'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1030
-                    ),
1031
-                    // options
1032
-                    array(
1033
-                        'apikey'            => EE_Registry::instance()->NET_CFG->core->site_license_key,
1034
-                        'lang_domain'       => 'event_espresso',
1035
-                        'checkPeriod'       => $settings['pue_options']['checkPeriod'],
1036
-                        'option_key'        => 'site_license_key',
1037
-                        'options_page_slug' => 'event_espresso',
1038
-                        'plugin_basename'   => $settings['pue_options']['plugin_basename'],
1039
-                        // if use_wp_update is TRUE it means you want FREE versions of the plugin to be updated from WP
1040
-                        'use_wp_update'     => $settings['pue_options']['use_wp_update'],
1041
-                    )
1042
-                );
1043
-            }
1044
-        }
1045
-    }
1007
+	/**
1008
+	 *    load_pue_update - Update notifications
1009
+	 *
1010
+	 * @return void
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidDataTypeException
1013
+	 * @throws InvalidInterfaceException
1014
+	 */
1015
+	public static function load_pue_update()
1016
+	{
1017
+		// load PUE client
1018
+		require_once EE_THIRD_PARTY . 'pue' . DS . 'pue-client.php';
1019
+		// cycle thru settings
1020
+		foreach (self::$_settings as $settings) {
1021
+			if (! empty($settings['pue_options'])) {
1022
+				// initiate the class and start the plugin update engine!
1023
+				new PluginUpdateEngineChecker(
1024
+				// host file URL
1025
+					'https://eventespresso.com',
1026
+					// plugin slug(s)
1027
+					array(
1028
+						'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1029
+						'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1030
+					),
1031
+					// options
1032
+					array(
1033
+						'apikey'            => EE_Registry::instance()->NET_CFG->core->site_license_key,
1034
+						'lang_domain'       => 'event_espresso',
1035
+						'checkPeriod'       => $settings['pue_options']['checkPeriod'],
1036
+						'option_key'        => 'site_license_key',
1037
+						'options_page_slug' => 'event_espresso',
1038
+						'plugin_basename'   => $settings['pue_options']['plugin_basename'],
1039
+						// if use_wp_update is TRUE it means you want FREE versions of the plugin to be updated from WP
1040
+						'use_wp_update'     => $settings['pue_options']['use_wp_update'],
1041
+					)
1042
+				);
1043
+			}
1044
+		}
1045
+	}
1046 1046
 
1047 1047
 
1048
-    /**
1049
-     * Callback for EE_Brewing_Regular__messages_caf hook used to register message types.
1050
-     *
1051
-     * @since 4.4.0
1052
-     * @return void
1053
-     * @throws EE_Error
1054
-     */
1055
-    public static function register_message_types()
1056
-    {
1057
-        foreach (self::$_settings as $addon_name => $settings) {
1058
-            if (! empty($settings['message_types'])) {
1059
-                foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1060
-                    EE_Register_Message_Type::register($message_type, $message_type_settings);
1061
-                }
1062
-            }
1063
-        }
1064
-    }
1048
+	/**
1049
+	 * Callback for EE_Brewing_Regular__messages_caf hook used to register message types.
1050
+	 *
1051
+	 * @since 4.4.0
1052
+	 * @return void
1053
+	 * @throws EE_Error
1054
+	 */
1055
+	public static function register_message_types()
1056
+	{
1057
+		foreach (self::$_settings as $addon_name => $settings) {
1058
+			if (! empty($settings['message_types'])) {
1059
+				foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1060
+					EE_Register_Message_Type::register($message_type, $message_type_settings);
1061
+				}
1062
+			}
1063
+		}
1064
+	}
1065 1065
 
1066 1066
 
1067
-    /**
1068
-     * This deregisters an addon that was previously registered with a specific addon_name.
1069
-     *
1070
-     * @since    4.3.0
1071
-     * @param string $addon_name the name for the addon that was previously registered
1072
-     * @throws DomainException
1073
-     * @throws EE_Error
1074
-     * @throws InvalidArgumentException
1075
-     * @throws InvalidDataTypeException
1076
-     * @throws InvalidInterfaceException
1077
-     */
1078
-    public static function deregister($addon_name = null)
1079
-    {
1080
-        if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1081
-            try {
1082
-                do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1083
-                $class_name = self::$_settings[ $addon_name ]['class_name'];
1084
-                if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1085
-                    // setup DMS
1086
-                    EE_Register_Data_Migration_Scripts::deregister($addon_name);
1087
-                }
1088
-                if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1089
-                    // register admin page
1090
-                    EE_Register_Admin_Page::deregister($addon_name);
1091
-                }
1092
-                if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1093
-                    // add to list of modules to be registered
1094
-                    EE_Register_Module::deregister($addon_name);
1095
-                }
1096
-                if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1097
-                    || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1098
-                ) {
1099
-                    // add to list of shortcodes to be registered
1100
-                    EE_Register_Shortcode::deregister($addon_name);
1101
-                }
1102
-                if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1103
-                    // if config_class present let's register config.
1104
-                    EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1105
-                }
1106
-                if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1107
-                    // add to list of widgets to be registered
1108
-                    EE_Register_Widget::deregister($addon_name);
1109
-                }
1110
-                if (! empty(self::$_settings[ $addon_name ]['model_paths'])
1111
-                    || ! empty(self::$_settings[ $addon_name ]['class_paths'])
1112
-                ) {
1113
-                    // add to list of shortcodes to be registered
1114
-                    EE_Register_Model::deregister($addon_name);
1115
-                }
1116
-                if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1117
-                    || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1118
-                ) {
1119
-                    // add to list of shortcodes to be registered
1120
-                    EE_Register_Model_Extensions::deregister($addon_name);
1121
-                }
1122
-                if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1123
-                    foreach (
1124
-                        (array) self::$_settings[ $addon_name ]['message_types'] as $message_type =>
1125
-                        $message_type_settings
1126
-                    ) {
1127
-                        EE_Register_Message_Type::deregister($message_type);
1128
-                    }
1129
-                }
1130
-                //deregister capabilities for addon
1131
-                if (
1132
-                    ! empty(self::$_settings[ $addon_name ]['capabilities'])
1133
-                    || ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1134
-                ) {
1135
-                    EE_Register_Capabilities::deregister($addon_name);
1136
-                }
1137
-                //deregister custom_post_types for addon
1138
-                if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1139
-                    EE_Register_CPT::deregister($addon_name);
1140
-                }
1141
-                if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1142
-                    EE_Register_Payment_Method::deregister($addon_name);
1143
-                }
1144
-                $addon = EE_Registry::instance()->getAddon($class_name);
1145
-                if ($addon instanceof EE_Addon) {
1146
-                    remove_action(
1147
-                        'deactivate_' . $addon->get_main_plugin_file_basename(),
1148
-                        array($addon, 'deactivation')
1149
-                    );
1150
-                    remove_action(
1151
-                        'AHEE__EE_System__perform_activations_upgrades_and_migrations',
1152
-                        array($addon, 'initialize_db_if_no_migrations_required')
1153
-                    );
1154
-                    //remove `after_registration` call
1155
-                    remove_action(
1156
-                        'AHEE__EE_System__load_espresso_addons__complete',
1157
-                        array($addon, 'after_registration'),
1158
-                        999
1159
-                    );
1160
-                }
1161
-                EE_Registry::instance()->removeAddon($class_name);
1162
-            } catch (OutOfBoundsException $addon_not_yet_registered_exception) {
1163
-                // the add-on was not yet registered in the registry,
1164
-                // so RegistryContainer::__get() throws this exception.
1165
-                // also no need to worry about this or log it,
1166
-                // it's ok to deregister an add-on before its registered in the registry
1167
-            } catch (Exception $e) {
1168
-                new ExceptionLogger($e);
1169
-            }
1170
-            unset(self::$_settings[ $addon_name ]);
1171
-            do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1172
-        }
1173
-    }
1067
+	/**
1068
+	 * This deregisters an addon that was previously registered with a specific addon_name.
1069
+	 *
1070
+	 * @since    4.3.0
1071
+	 * @param string $addon_name the name for the addon that was previously registered
1072
+	 * @throws DomainException
1073
+	 * @throws EE_Error
1074
+	 * @throws InvalidArgumentException
1075
+	 * @throws InvalidDataTypeException
1076
+	 * @throws InvalidInterfaceException
1077
+	 */
1078
+	public static function deregister($addon_name = null)
1079
+	{
1080
+		if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1081
+			try {
1082
+				do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1083
+				$class_name = self::$_settings[ $addon_name ]['class_name'];
1084
+				if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1085
+					// setup DMS
1086
+					EE_Register_Data_Migration_Scripts::deregister($addon_name);
1087
+				}
1088
+				if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1089
+					// register admin page
1090
+					EE_Register_Admin_Page::deregister($addon_name);
1091
+				}
1092
+				if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1093
+					// add to list of modules to be registered
1094
+					EE_Register_Module::deregister($addon_name);
1095
+				}
1096
+				if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1097
+					|| ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1098
+				) {
1099
+					// add to list of shortcodes to be registered
1100
+					EE_Register_Shortcode::deregister($addon_name);
1101
+				}
1102
+				if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1103
+					// if config_class present let's register config.
1104
+					EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1105
+				}
1106
+				if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1107
+					// add to list of widgets to be registered
1108
+					EE_Register_Widget::deregister($addon_name);
1109
+				}
1110
+				if (! empty(self::$_settings[ $addon_name ]['model_paths'])
1111
+					|| ! empty(self::$_settings[ $addon_name ]['class_paths'])
1112
+				) {
1113
+					// add to list of shortcodes to be registered
1114
+					EE_Register_Model::deregister($addon_name);
1115
+				}
1116
+				if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1117
+					|| ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1118
+				) {
1119
+					// add to list of shortcodes to be registered
1120
+					EE_Register_Model_Extensions::deregister($addon_name);
1121
+				}
1122
+				if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1123
+					foreach (
1124
+						(array) self::$_settings[ $addon_name ]['message_types'] as $message_type =>
1125
+						$message_type_settings
1126
+					) {
1127
+						EE_Register_Message_Type::deregister($message_type);
1128
+					}
1129
+				}
1130
+				//deregister capabilities for addon
1131
+				if (
1132
+					! empty(self::$_settings[ $addon_name ]['capabilities'])
1133
+					|| ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1134
+				) {
1135
+					EE_Register_Capabilities::deregister($addon_name);
1136
+				}
1137
+				//deregister custom_post_types for addon
1138
+				if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1139
+					EE_Register_CPT::deregister($addon_name);
1140
+				}
1141
+				if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1142
+					EE_Register_Payment_Method::deregister($addon_name);
1143
+				}
1144
+				$addon = EE_Registry::instance()->getAddon($class_name);
1145
+				if ($addon instanceof EE_Addon) {
1146
+					remove_action(
1147
+						'deactivate_' . $addon->get_main_plugin_file_basename(),
1148
+						array($addon, 'deactivation')
1149
+					);
1150
+					remove_action(
1151
+						'AHEE__EE_System__perform_activations_upgrades_and_migrations',
1152
+						array($addon, 'initialize_db_if_no_migrations_required')
1153
+					);
1154
+					//remove `after_registration` call
1155
+					remove_action(
1156
+						'AHEE__EE_System__load_espresso_addons__complete',
1157
+						array($addon, 'after_registration'),
1158
+						999
1159
+					);
1160
+				}
1161
+				EE_Registry::instance()->removeAddon($class_name);
1162
+			} catch (OutOfBoundsException $addon_not_yet_registered_exception) {
1163
+				// the add-on was not yet registered in the registry,
1164
+				// so RegistryContainer::__get() throws this exception.
1165
+				// also no need to worry about this or log it,
1166
+				// it's ok to deregister an add-on before its registered in the registry
1167
+			} catch (Exception $e) {
1168
+				new ExceptionLogger($e);
1169
+			}
1170
+			unset(self::$_settings[ $addon_name ]);
1171
+			do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1172
+		}
1173
+	}
1174 1174
 }
1175 1175
 // End of file EE_Register_Addon.lib.php
1176 1176
 // Location: /core/libraries/plugin_api/EE_Register_Addon.lib.php
Please login to merge, or discard this patch.
Spacing   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -72,15 +72,15 @@  discard block
 block discarded – undo
72 72
         // offsets:    0 . 1 . 2 . 3 . 4
73 73
         $version_parts = explode('.', $min_core_version);
74 74
         //check they specified the micro version (after 2nd period)
75
-        if (! isset($version_parts[2])) {
75
+        if ( ! isset($version_parts[2])) {
76 76
             $version_parts[2] = '0';
77 77
         }
78 78
         //if they didn't specify the 'p', or 'rc' part. Just assume the lowest possible
79 79
         //soon we can assume that's 'rc', but this current version is 'alpha'
80
-        if (! isset($version_parts[3])) {
80
+        if ( ! isset($version_parts[3])) {
81 81
             $version_parts[3] = 'dev';
82 82
         }
83
-        if (! isset($version_parts[4])) {
83
+        if ( ! isset($version_parts[4])) {
84 84
             $version_parts[4] = '000';
85 85
         }
86 86
         return implode('.', $version_parts);
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
         // setup PUE
257 257
         EE_Register_Addon::_parse_pue_options($addon_name, $class_name, $setup_args);
258 258
         // does this addon work with this version of core or WordPress ?
259
-        if (! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
259
+        if ( ! EE_Register_Addon::_addon_is_compatible($addon_name, $addon_settings)) {
260 260
             return;
261 261
         }
262 262
         // register namespaces
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
                 )
315 315
             );
316 316
         }
317
-        if (! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
317
+        if ( ! isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) {
318 318
             throw new EE_Error(
319 319
                 sprintf(
320 320
                     __(
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
             );
327 327
         }
328 328
         // check that addon has not already been registered with that name
329
-        if (isset(self::$_settings[ $addon_name ]) && ! did_action('activate_plugin')) {
329
+        if (isset(self::$_settings[$addon_name]) && ! did_action('activate_plugin')) {
330 330
             throw new EE_Error(
331 331
                 sprintf(
332 332
                     __(
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
         // check if classname is fully  qualified or is a legacy classname already prefixed with 'EE_'
359 359
         return strpos($class_name, '\\') || strpos($class_name, 'EE_') === 0
360 360
             ? $class_name
361
-            : 'EE_' . $class_name;
361
+            : 'EE_'.$class_name;
362 362
     }
363 363
 
364 364
 
@@ -519,9 +519,9 @@  discard block
 block discarded – undo
519 519
         $incompatibility_message = '';
520 520
         //check whether this addon version is compatible with EE core
521 521
         if (
522
-            isset(EE_Register_Addon::$_incompatible_addons[ $addon_name ])
522
+            isset(EE_Register_Addon::$_incompatible_addons[$addon_name])
523 523
             && ! self::_meets_min_core_version_requirement(
524
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
524
+                EE_Register_Addon::$_incompatible_addons[$addon_name],
525 525
                 $addon_settings['version']
526 526
             )
527 527
         ) {
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
                 ),
532 532
                 $addon_name,
533 533
                 '<br />',
534
-                EE_Register_Addon::$_incompatible_addons[ $addon_name ],
534
+                EE_Register_Addon::$_incompatible_addons[$addon_name],
535 535
                 '<span style="font-weight: bold; color: #D54E21;">',
536 536
                 '</span><br />'
537 537
             );
@@ -563,7 +563,7 @@  discard block
 block discarded – undo
563 563
                 '</span><br />'
564 564
             );
565 565
         }
566
-        if (! empty($incompatibility_message)) {
566
+        if ( ! empty($incompatibility_message)) {
567 567
             // remove 'activate' from the REQUEST
568 568
             // so WP doesn't erroneously tell the user the plugin activated fine when it didn't
569 569
             unset($_GET['activate'], $_REQUEST['activate']);
@@ -591,11 +591,11 @@  discard block
 block discarded – undo
591 591
      */
592 592
     private static function _parse_pue_options($addon_name, $class_name, array $setup_args)
593 593
     {
594
-        if (! empty($setup_args['pue_options'])) {
595
-            self::$_settings[ $addon_name ]['pue_options'] = array(
594
+        if ( ! empty($setup_args['pue_options'])) {
595
+            self::$_settings[$addon_name]['pue_options'] = array(
596 596
                 'pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug'])
597 597
                     ? (string) $setup_args['pue_options']['pue_plugin_slug']
598
-                    : 'espresso_' . strtolower($class_name),
598
+                    : 'espresso_'.strtolower($class_name),
599 599
                 'plugin_basename' => isset($setup_args['pue_options']['plugin_basename'])
600 600
                     ? (string) $setup_args['pue_options']['plugin_basename']
601 601
                     : plugin_basename($setup_args['main_file_path']),
@@ -655,12 +655,12 @@  discard block
 block discarded – undo
655 655
             //(as the newly-activated addon wasn't around the first time addons were registered).
656 656
             //Note: the presence of pue_options in the addon registration options will initialize the $_settings
657 657
             //property for the add-on, but the add-on is only partially initialized.  Hence, the additional check.
658
-            if (! isset(self::$_settings[ $addon_name ])
659
-                || (isset(self::$_settings[ $addon_name ])
660
-                    && ! isset(self::$_settings[ $addon_name ]['class_name'])
658
+            if ( ! isset(self::$_settings[$addon_name])
659
+                || (isset(self::$_settings[$addon_name])
660
+                    && ! isset(self::$_settings[$addon_name]['class_name'])
661 661
                 )
662 662
             ) {
663
-                self::$_settings[ $addon_name ] = $addon_settings;
663
+                self::$_settings[$addon_name] = $addon_settings;
664 664
                 $addon                          = self::_load_and_init_addon_class($addon_name);
665 665
                 $addon->set_activation_indicator_option();
666 666
                 // dont bother setting up the rest of the addon.
@@ -686,10 +686,10 @@  discard block
 block discarded – undo
686 686
             );
687 687
         }
688 688
         // make sure addon settings are set correctly without overwriting anything existing
689
-        if (isset(self::$_settings[ $addon_name ])) {
690
-            self::$_settings[ $addon_name ] += $addon_settings;
689
+        if (isset(self::$_settings[$addon_name])) {
690
+            self::$_settings[$addon_name] += $addon_settings;
691 691
         } else {
692
-            self::$_settings[ $addon_name ] = $addon_settings;
692
+            self::$_settings[$addon_name] = $addon_settings;
693 693
         }
694 694
         return false;
695 695
     }
@@ -702,13 +702,13 @@  discard block
 block discarded – undo
702 702
      */
703 703
     private static function _setup_autoloaders($addon_name)
704 704
     {
705
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_paths'])) {
705
+        if ( ! empty(self::$_settings[$addon_name]['autoloader_paths'])) {
706 706
             // setup autoloader for single file
707
-            EEH_Autoloader::instance()->register_autoloader(self::$_settings[ $addon_name ]['autoloader_paths']);
707
+            EEH_Autoloader::instance()->register_autoloader(self::$_settings[$addon_name]['autoloader_paths']);
708 708
         }
709 709
         // setup autoloaders for folders
710
-        if (! empty(self::$_settings[ $addon_name ]['autoloader_folders'])) {
711
-            foreach ((array) self::$_settings[ $addon_name ]['autoloader_folders'] as $autoloader_folder) {
710
+        if ( ! empty(self::$_settings[$addon_name]['autoloader_folders'])) {
711
+            foreach ((array) self::$_settings[$addon_name]['autoloader_folders'] as $autoloader_folder) {
712 712
                 EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder);
713 713
             }
714 714
         }
@@ -726,27 +726,27 @@  discard block
 block discarded – undo
726 726
     {
727 727
         // register new models
728 728
         if (
729
-            ! empty(self::$_settings[ $addon_name ]['model_paths'])
730
-            || ! empty(self::$_settings[ $addon_name ]['class_paths'])
729
+            ! empty(self::$_settings[$addon_name]['model_paths'])
730
+            || ! empty(self::$_settings[$addon_name]['class_paths'])
731 731
         ) {
732 732
             EE_Register_Model::register(
733 733
                 $addon_name,
734 734
                 array(
735
-                    'model_paths' => self::$_settings[ $addon_name ]['model_paths'],
736
-                    'class_paths' => self::$_settings[ $addon_name ]['class_paths'],
735
+                    'model_paths' => self::$_settings[$addon_name]['model_paths'],
736
+                    'class_paths' => self::$_settings[$addon_name]['class_paths'],
737 737
                 )
738 738
             );
739 739
         }
740 740
         // register model extensions
741 741
         if (
742
-            ! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
743
-            || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
742
+            ! empty(self::$_settings[$addon_name]['model_extension_paths'])
743
+            || ! empty(self::$_settings[$addon_name]['class_extension_paths'])
744 744
         ) {
745 745
             EE_Register_Model_Extensions::register(
746 746
                 $addon_name,
747 747
                 array(
748
-                    'model_extension_paths' => self::$_settings[ $addon_name ]['model_extension_paths'],
749
-                    'class_extension_paths' => self::$_settings[ $addon_name ]['class_extension_paths'],
748
+                    'model_extension_paths' => self::$_settings[$addon_name]['model_extension_paths'],
749
+                    'class_extension_paths' => self::$_settings[$addon_name]['class_extension_paths'],
750 750
                 )
751 751
             );
752 752
         }
@@ -761,10 +761,10 @@  discard block
 block discarded – undo
761 761
     private static function _register_data_migration_scripts($addon_name)
762 762
     {
763 763
         // setup DMS
764
-        if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
764
+        if ( ! empty(self::$_settings[$addon_name]['dms_paths'])) {
765 765
             EE_Register_Data_Migration_Scripts::register(
766 766
                 $addon_name,
767
-                array('dms_paths' => self::$_settings[ $addon_name ]['dms_paths'])
767
+                array('dms_paths' => self::$_settings[$addon_name]['dms_paths'])
768 768
             );
769 769
         }
770 770
     }
@@ -778,12 +778,12 @@  discard block
 block discarded – undo
778 778
     private static function _register_config($addon_name)
779 779
     {
780 780
         // if config_class is present let's register config.
781
-        if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
781
+        if ( ! empty(self::$_settings[$addon_name]['config_class'])) {
782 782
             EE_Register_Config::register(
783
-                self::$_settings[ $addon_name ]['config_class'],
783
+                self::$_settings[$addon_name]['config_class'],
784 784
                 array(
785
-                    'config_section' => self::$_settings[ $addon_name ]['config_section'],
786
-                    'config_name'    => self::$_settings[ $addon_name ]['config_name'],
785
+                    'config_section' => self::$_settings[$addon_name]['config_section'],
786
+                    'config_name'    => self::$_settings[$addon_name]['config_name'],
787 787
                 )
788 788
             );
789 789
         }
@@ -797,10 +797,10 @@  discard block
 block discarded – undo
797 797
      */
798 798
     private static function _register_admin_pages($addon_name)
799 799
     {
800
-        if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
800
+        if ( ! empty(self::$_settings[$addon_name]['admin_path'])) {
801 801
             EE_Register_Admin_Page::register(
802 802
                 $addon_name,
803
-                array('page_path' => self::$_settings[ $addon_name ]['admin_path'])
803
+                array('page_path' => self::$_settings[$addon_name]['admin_path'])
804 804
             );
805 805
         }
806 806
     }
@@ -813,10 +813,10 @@  discard block
 block discarded – undo
813 813
      */
814 814
     private static function _register_modules($addon_name)
815 815
     {
816
-        if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
816
+        if ( ! empty(self::$_settings[$addon_name]['module_paths'])) {
817 817
             EE_Register_Module::register(
818 818
                 $addon_name,
819
-                array('module_paths' => self::$_settings[ $addon_name ]['module_paths'])
819
+                array('module_paths' => self::$_settings[$addon_name]['module_paths'])
820 820
             );
821 821
         }
822 822
     }
@@ -829,17 +829,17 @@  discard block
 block discarded – undo
829 829
      */
830 830
     private static function _register_shortcodes($addon_name)
831 831
     {
832
-        if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
833
-            || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
832
+        if ( ! empty(self::$_settings[$addon_name]['shortcode_paths'])
833
+            || ! empty(self::$_settings[$addon_name]['shortcode_fqcns'])
834 834
         ) {
835 835
             EE_Register_Shortcode::register(
836 836
                 $addon_name,
837 837
                 array(
838
-                    'shortcode_paths' => isset(self::$_settings[ $addon_name ]['shortcode_paths'])
839
-                        ? self::$_settings[ $addon_name ]['shortcode_paths']
838
+                    'shortcode_paths' => isset(self::$_settings[$addon_name]['shortcode_paths'])
839
+                        ? self::$_settings[$addon_name]['shortcode_paths']
840 840
                         : array(),
841
-                    'shortcode_fqcns' => isset(self::$_settings[ $addon_name ]['shortcode_fqcns'])
842
-                        ? self::$_settings[ $addon_name ]['shortcode_fqcns']
841
+                    'shortcode_fqcns' => isset(self::$_settings[$addon_name]['shortcode_fqcns'])
842
+                        ? self::$_settings[$addon_name]['shortcode_fqcns']
843 843
                         : array(),
844 844
                 )
845 845
             );
@@ -854,10 +854,10 @@  discard block
 block discarded – undo
854 854
      */
855 855
     private static function _register_widgets($addon_name)
856 856
     {
857
-        if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
857
+        if ( ! empty(self::$_settings[$addon_name]['widget_paths'])) {
858 858
             EE_Register_Widget::register(
859 859
                 $addon_name,
860
-                array('widget_paths' => self::$_settings[ $addon_name ]['widget_paths'])
860
+                array('widget_paths' => self::$_settings[$addon_name]['widget_paths'])
861 861
             );
862 862
         }
863 863
     }
@@ -870,12 +870,12 @@  discard block
 block discarded – undo
870 870
      */
871 871
     private static function _register_capabilities($addon_name)
872 872
     {
873
-        if (! empty(self::$_settings[ $addon_name ]['capabilities'])) {
873
+        if ( ! empty(self::$_settings[$addon_name]['capabilities'])) {
874 874
             EE_Register_Capabilities::register(
875 875
                 $addon_name,
876 876
                 array(
877
-                    'capabilities'    => self::$_settings[ $addon_name ]['capabilities'],
878
-                    'capability_maps' => self::$_settings[ $addon_name ]['capability_maps'],
877
+                    'capabilities'    => self::$_settings[$addon_name]['capabilities'],
878
+                    'capability_maps' => self::$_settings[$addon_name]['capability_maps'],
879 879
                 )
880 880
             );
881 881
         }
@@ -889,7 +889,7 @@  discard block
 block discarded – undo
889 889
      */
890 890
     private static function _register_message_types($addon_name)
891 891
     {
892
-        if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
892
+        if ( ! empty(self::$_settings[$addon_name]['message_types'])) {
893 893
             add_action(
894 894
                 'EE_Brewing_Regular___messages_caf',
895 895
                 array('EE_Register_Addon', 'register_message_types')
@@ -906,15 +906,15 @@  discard block
 block discarded – undo
906 906
     private static function _register_custom_post_types($addon_name)
907 907
     {
908 908
         if (
909
-            ! empty(self::$_settings[ $addon_name ]['custom_post_types'])
910
-            || ! empty(self::$_settings[ $addon_name ]['custom_taxonomies'])
909
+            ! empty(self::$_settings[$addon_name]['custom_post_types'])
910
+            || ! empty(self::$_settings[$addon_name]['custom_taxonomies'])
911 911
         ) {
912 912
             EE_Register_CPT::register(
913 913
                 $addon_name,
914 914
                 array(
915
-                    'cpts'          => self::$_settings[ $addon_name ]['custom_post_types'],
916
-                    'cts'           => self::$_settings[ $addon_name ]['custom_taxonomies'],
917
-                    'default_terms' => self::$_settings[ $addon_name ]['default_terms'],
915
+                    'cpts'          => self::$_settings[$addon_name]['custom_post_types'],
916
+                    'cts'           => self::$_settings[$addon_name]['custom_taxonomies'],
917
+                    'default_terms' => self::$_settings[$addon_name]['default_terms'],
918 918
                 )
919 919
             );
920 920
         }
@@ -932,10 +932,10 @@  discard block
 block discarded – undo
932 932
      */
933 933
     private static function _register_payment_methods($addon_name)
934 934
     {
935
-        if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
935
+        if ( ! empty(self::$_settings[$addon_name]['payment_method_paths'])) {
936 936
             EE_Register_Payment_Method::register(
937 937
                 $addon_name,
938
-                array('payment_method_paths' => self::$_settings[ $addon_name ]['payment_method_paths'])
938
+                array('payment_method_paths' => self::$_settings[$addon_name]['payment_method_paths'])
939 939
             );
940 940
         }
941 941
     }
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
     {
957 957
         $loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader();
958 958
         $addon  = $loader->getShared(
959
-            self::$_settings[ $addon_name ]['class_name'],
959
+            self::$_settings[$addon_name]['class_name'],
960 960
             array('EE_Registry::create(addon)' => true)
961 961
         );
962 962
         // setter inject dep map if required
@@ -966,38 +966,38 @@  discard block
 block discarded – undo
966 966
         // setter inject domain if required
967 967
         if (
968 968
             $addon instanceof RequiresDomainInterface
969
-            && self::$_settings[ $addon_name ]['domain_fqcn'] !== ''
969
+            && self::$_settings[$addon_name]['domain_fqcn'] !== ''
970 970
             && $addon->domain() === null
971 971
         ) {
972 972
             $addon->setDomain(
973 973
                 $loader->getShared(
974
-                    self::$_settings[ $addon_name ]['domain_fqcn'],
974
+                    self::$_settings[$addon_name]['domain_fqcn'],
975 975
                     array(
976
-                        self::$_settings[ $addon_name ]['main_file_path'],
977
-                        self::$_settings[ $addon_name ]['version'],
976
+                        self::$_settings[$addon_name]['main_file_path'],
977
+                        self::$_settings[$addon_name]['version'],
978 978
                     )
979 979
                 )
980 980
             );
981 981
         }
982 982
         $addon->set_name($addon_name);
983
-        $addon->set_plugin_slug(self::$_settings[ $addon_name ]['plugin_slug']);
984
-        $addon->set_plugin_basename(self::$_settings[ $addon_name ]['plugin_basename']);
985
-        $addon->set_main_plugin_file(self::$_settings[ $addon_name ]['main_file_path']);
986
-        $addon->set_plugin_action_slug(self::$_settings[ $addon_name ]['plugin_action_slug']);
987
-        $addon->set_plugins_page_row(self::$_settings[ $addon_name ]['plugins_page_row']);
988
-        $addon->set_version(self::$_settings[ $addon_name ]['version']);
989
-        $addon->set_min_core_version(self::_effective_version(self::$_settings[ $addon_name ]['min_core_version']));
990
-        $addon->set_config_section(self::$_settings[ $addon_name ]['config_section']);
991
-        $addon->set_config_class(self::$_settings[ $addon_name ]['config_class']);
992
-        $addon->set_config_name(self::$_settings[ $addon_name ]['config_name']);
983
+        $addon->set_plugin_slug(self::$_settings[$addon_name]['plugin_slug']);
984
+        $addon->set_plugin_basename(self::$_settings[$addon_name]['plugin_basename']);
985
+        $addon->set_main_plugin_file(self::$_settings[$addon_name]['main_file_path']);
986
+        $addon->set_plugin_action_slug(self::$_settings[$addon_name]['plugin_action_slug']);
987
+        $addon->set_plugins_page_row(self::$_settings[$addon_name]['plugins_page_row']);
988
+        $addon->set_version(self::$_settings[$addon_name]['version']);
989
+        $addon->set_min_core_version(self::_effective_version(self::$_settings[$addon_name]['min_core_version']));
990
+        $addon->set_config_section(self::$_settings[$addon_name]['config_section']);
991
+        $addon->set_config_class(self::$_settings[$addon_name]['config_class']);
992
+        $addon->set_config_name(self::$_settings[$addon_name]['config_name']);
993 993
         //unfortunately this can't be hooked in upon construction, because we don't have
994 994
         //the plugin mainfile's path upon construction.
995 995
         register_deactivation_hook($addon->get_main_plugin_file(), array($addon, 'deactivation'));
996 996
         // call any additional admin_callback functions during load_admin_controller hook
997
-        if (! empty(self::$_settings[ $addon_name ]['admin_callback'])) {
997
+        if ( ! empty(self::$_settings[$addon_name]['admin_callback'])) {
998 998
             add_action(
999 999
                 'AHEE__EE_System__load_controllers__load_admin_controllers',
1000
-                array($addon, self::$_settings[ $addon_name ]['admin_callback'])
1000
+                array($addon, self::$_settings[$addon_name]['admin_callback'])
1001 1001
             );
1002 1002
         }
1003 1003
         return $addon;
@@ -1015,10 +1015,10 @@  discard block
 block discarded – undo
1015 1015
     public static function load_pue_update()
1016 1016
     {
1017 1017
         // load PUE client
1018
-        require_once EE_THIRD_PARTY . 'pue' . DS . 'pue-client.php';
1018
+        require_once EE_THIRD_PARTY.'pue'.DS.'pue-client.php';
1019 1019
         // cycle thru settings
1020 1020
         foreach (self::$_settings as $settings) {
1021
-            if (! empty($settings['pue_options'])) {
1021
+            if ( ! empty($settings['pue_options'])) {
1022 1022
                 // initiate the class and start the plugin update engine!
1023 1023
                 new PluginUpdateEngineChecker(
1024 1024
                 // host file URL
@@ -1026,7 +1026,7 @@  discard block
 block discarded – undo
1026 1026
                     // plugin slug(s)
1027 1027
                     array(
1028 1028
                         'premium'    => array('p' => $settings['pue_options']['pue_plugin_slug']),
1029
-                        'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'] . '-pr'),
1029
+                        'prerelease' => array('beta' => $settings['pue_options']['pue_plugin_slug'].'-pr'),
1030 1030
                     ),
1031 1031
                     // options
1032 1032
                     array(
@@ -1055,7 +1055,7 @@  discard block
 block discarded – undo
1055 1055
     public static function register_message_types()
1056 1056
     {
1057 1057
         foreach (self::$_settings as $addon_name => $settings) {
1058
-            if (! empty($settings['message_types'])) {
1058
+            if ( ! empty($settings['message_types'])) {
1059 1059
                 foreach ((array) $settings['message_types'] as $message_type => $message_type_settings) {
1060 1060
                     EE_Register_Message_Type::register($message_type, $message_type_settings);
1061 1061
                 }
@@ -1077,51 +1077,51 @@  discard block
 block discarded – undo
1077 1077
      */
1078 1078
     public static function deregister($addon_name = null)
1079 1079
     {
1080
-        if (isset(self::$_settings[ $addon_name ]['class_name'])) {
1080
+        if (isset(self::$_settings[$addon_name]['class_name'])) {
1081 1081
             try {
1082 1082
                 do_action('AHEE__EE_Register_Addon__deregister__before', $addon_name);
1083
-                $class_name = self::$_settings[ $addon_name ]['class_name'];
1084
-                if (! empty(self::$_settings[ $addon_name ]['dms_paths'])) {
1083
+                $class_name = self::$_settings[$addon_name]['class_name'];
1084
+                if ( ! empty(self::$_settings[$addon_name]['dms_paths'])) {
1085 1085
                     // setup DMS
1086 1086
                     EE_Register_Data_Migration_Scripts::deregister($addon_name);
1087 1087
                 }
1088
-                if (! empty(self::$_settings[ $addon_name ]['admin_path'])) {
1088
+                if ( ! empty(self::$_settings[$addon_name]['admin_path'])) {
1089 1089
                     // register admin page
1090 1090
                     EE_Register_Admin_Page::deregister($addon_name);
1091 1091
                 }
1092
-                if (! empty(self::$_settings[ $addon_name ]['module_paths'])) {
1092
+                if ( ! empty(self::$_settings[$addon_name]['module_paths'])) {
1093 1093
                     // add to list of modules to be registered
1094 1094
                     EE_Register_Module::deregister($addon_name);
1095 1095
                 }
1096
-                if (! empty(self::$_settings[ $addon_name ]['shortcode_paths'])
1097
-                    || ! empty(self::$_settings[ $addon_name ]['shortcode_fqcns'])
1096
+                if ( ! empty(self::$_settings[$addon_name]['shortcode_paths'])
1097
+                    || ! empty(self::$_settings[$addon_name]['shortcode_fqcns'])
1098 1098
                 ) {
1099 1099
                     // add to list of shortcodes to be registered
1100 1100
                     EE_Register_Shortcode::deregister($addon_name);
1101 1101
                 }
1102
-                if (! empty(self::$_settings[ $addon_name ]['config_class'])) {
1102
+                if ( ! empty(self::$_settings[$addon_name]['config_class'])) {
1103 1103
                     // if config_class present let's register config.
1104
-                    EE_Register_Config::deregister(self::$_settings[ $addon_name ]['config_class']);
1104
+                    EE_Register_Config::deregister(self::$_settings[$addon_name]['config_class']);
1105 1105
                 }
1106
-                if (! empty(self::$_settings[ $addon_name ]['widget_paths'])) {
1106
+                if ( ! empty(self::$_settings[$addon_name]['widget_paths'])) {
1107 1107
                     // add to list of widgets to be registered
1108 1108
                     EE_Register_Widget::deregister($addon_name);
1109 1109
                 }
1110
-                if (! empty(self::$_settings[ $addon_name ]['model_paths'])
1111
-                    || ! empty(self::$_settings[ $addon_name ]['class_paths'])
1110
+                if ( ! empty(self::$_settings[$addon_name]['model_paths'])
1111
+                    || ! empty(self::$_settings[$addon_name]['class_paths'])
1112 1112
                 ) {
1113 1113
                     // add to list of shortcodes to be registered
1114 1114
                     EE_Register_Model::deregister($addon_name);
1115 1115
                 }
1116
-                if (! empty(self::$_settings[ $addon_name ]['model_extension_paths'])
1117
-                    || ! empty(self::$_settings[ $addon_name ]['class_extension_paths'])
1116
+                if ( ! empty(self::$_settings[$addon_name]['model_extension_paths'])
1117
+                    || ! empty(self::$_settings[$addon_name]['class_extension_paths'])
1118 1118
                 ) {
1119 1119
                     // add to list of shortcodes to be registered
1120 1120
                     EE_Register_Model_Extensions::deregister($addon_name);
1121 1121
                 }
1122
-                if (! empty(self::$_settings[ $addon_name ]['message_types'])) {
1122
+                if ( ! empty(self::$_settings[$addon_name]['message_types'])) {
1123 1123
                     foreach (
1124
-                        (array) self::$_settings[ $addon_name ]['message_types'] as $message_type =>
1124
+                        (array) self::$_settings[$addon_name]['message_types'] as $message_type =>
1125 1125
                         $message_type_settings
1126 1126
                     ) {
1127 1127
                         EE_Register_Message_Type::deregister($message_type);
@@ -1129,22 +1129,22 @@  discard block
 block discarded – undo
1129 1129
                 }
1130 1130
                 //deregister capabilities for addon
1131 1131
                 if (
1132
-                    ! empty(self::$_settings[ $addon_name ]['capabilities'])
1133
-                    || ! empty(self::$_settings[ $addon_name ]['capability_maps'])
1132
+                    ! empty(self::$_settings[$addon_name]['capabilities'])
1133
+                    || ! empty(self::$_settings[$addon_name]['capability_maps'])
1134 1134
                 ) {
1135 1135
                     EE_Register_Capabilities::deregister($addon_name);
1136 1136
                 }
1137 1137
                 //deregister custom_post_types for addon
1138
-                if (! empty(self::$_settings[ $addon_name ]['custom_post_types'])) {
1138
+                if ( ! empty(self::$_settings[$addon_name]['custom_post_types'])) {
1139 1139
                     EE_Register_CPT::deregister($addon_name);
1140 1140
                 }
1141
-                if (! empty(self::$_settings[ $addon_name ]['payment_method_paths'])) {
1141
+                if ( ! empty(self::$_settings[$addon_name]['payment_method_paths'])) {
1142 1142
                     EE_Register_Payment_Method::deregister($addon_name);
1143 1143
                 }
1144 1144
                 $addon = EE_Registry::instance()->getAddon($class_name);
1145 1145
                 if ($addon instanceof EE_Addon) {
1146 1146
                     remove_action(
1147
-                        'deactivate_' . $addon->get_main_plugin_file_basename(),
1147
+                        'deactivate_'.$addon->get_main_plugin_file_basename(),
1148 1148
                         array($addon, 'deactivation')
1149 1149
                     );
1150 1150
                     remove_action(
@@ -1167,7 +1167,7 @@  discard block
 block discarded – undo
1167 1167
             } catch (Exception $e) {
1168 1168
                 new ExceptionLogger($e);
1169 1169
             }
1170
-            unset(self::$_settings[ $addon_name ]);
1170
+            unset(self::$_settings[$addon_name]);
1171 1171
             do_action('AHEE__EE_Register_Addon__deregister__after', $addon_name);
1172 1172
         }
1173 1173
     }
Please login to merge, or discard this patch.
core/libraries/plugin_api/EE_Register_Data_Migration_Scripts.lib.php 2 patches
Indentation   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -18,99 +18,99 @@
 block discarded – undo
18 18
 class EE_Register_Data_Migration_Scripts implements EEI_Plugin_API
19 19
 {
20 20
 
21
-    /**
22
-     * Holds values for registered DMSs
23
-     *
24
-     * @var array[][]
25
-     */
26
-    protected static $_settings = array();
21
+	/**
22
+	 * Holds values for registered DMSs
23
+	 *
24
+	 * @var array[][]
25
+	 */
26
+	protected static $_settings = array();
27 27
 
28 28
 
29
-    /**
30
-     * Method for registering new Data Migration Scripts
31
-     *
32
-     * @since 4.3.0
33
-     * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
34
-     *                           If EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
35
-     * @param array $setup_args {
36
-     *      @type string  $dms_paths an array of full server paths to folders that contain data migration scripts
37
-     *  }
38
-     * @throws EE_Error
39
-     * @return void
40
-     */
41
-    public static function register($addon_name = '', $setup_args = array())
42
-    {
43
-        //required fields MUST be present, so let's make sure they are.
44
-        if (empty($addon_name) || ! is_array($setup_args) || empty($setup_args['dms_paths'])) {
45
-            throw new EE_Error(
46
-                esc_html__(
47
-                    'In order to register Data Migration Scripts with EE_Register_Data_Migration_Scripts::register(), you must include the EE_Addon class name (used as a unique identifier for this set of data migration scripts), and an array containing the following keys: "dms_paths" (an array of full server paths to folders that contain data migration scripts)',
48
-                    'event_espresso'
49
-                )
50
-            );
51
-        }
52
-        //make sure we don't register twice
53
-        if (isset(self::$_settings[ $addon_name ])) {
54
-            return;
55
-        }
56
-        //make sure this was called in the right place!
57
-        if (! did_action('AHEE__EE_System__load_espresso_addons')
58
-            || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
59
-        ) {
60
-            EE_Error::doing_it_wrong(
61
-                __METHOD__,
62
-                esc_html__(
63
-                    'An attempt to register Data Migration Scripts has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register Data Migration Scripts.',
64
-                    'event_espresso'
65
-                ),
66
-                '4.3.0'
67
-            );
68
-        }
69
-        //setup $_settings array from incoming values.
70
-        self::$_settings[ $addon_name ] = array(
71
-            'dms_paths' => (array) $setup_args['dms_paths']
72
-        );
73
-        // setup DMS
74
-        add_filter(
75
-            'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
76
-            array('EE_Register_Data_Migration_Scripts', 'add_data_migration_script_folders')
77
-        );
78
-    }
29
+	/**
30
+	 * Method for registering new Data Migration Scripts
31
+	 *
32
+	 * @since 4.3.0
33
+	 * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
34
+	 *                           If EE_Addon class is namespaced, then this needs to be the Fully Qualified Class Name
35
+	 * @param array $setup_args {
36
+	 *      @type string  $dms_paths an array of full server paths to folders that contain data migration scripts
37
+	 *  }
38
+	 * @throws EE_Error
39
+	 * @return void
40
+	 */
41
+	public static function register($addon_name = '', $setup_args = array())
42
+	{
43
+		//required fields MUST be present, so let's make sure they are.
44
+		if (empty($addon_name) || ! is_array($setup_args) || empty($setup_args['dms_paths'])) {
45
+			throw new EE_Error(
46
+				esc_html__(
47
+					'In order to register Data Migration Scripts with EE_Register_Data_Migration_Scripts::register(), you must include the EE_Addon class name (used as a unique identifier for this set of data migration scripts), and an array containing the following keys: "dms_paths" (an array of full server paths to folders that contain data migration scripts)',
48
+					'event_espresso'
49
+				)
50
+			);
51
+		}
52
+		//make sure we don't register twice
53
+		if (isset(self::$_settings[ $addon_name ])) {
54
+			return;
55
+		}
56
+		//make sure this was called in the right place!
57
+		if (! did_action('AHEE__EE_System__load_espresso_addons')
58
+			|| did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
59
+		) {
60
+			EE_Error::doing_it_wrong(
61
+				__METHOD__,
62
+				esc_html__(
63
+					'An attempt to register Data Migration Scripts has failed because it was not registered at the correct time.  Please use the "AHEE__EE_System__load_espresso_addons" hook to register Data Migration Scripts.',
64
+					'event_espresso'
65
+				),
66
+				'4.3.0'
67
+			);
68
+		}
69
+		//setup $_settings array from incoming values.
70
+		self::$_settings[ $addon_name ] = array(
71
+			'dms_paths' => (array) $setup_args['dms_paths']
72
+		);
73
+		// setup DMS
74
+		add_filter(
75
+			'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',
76
+			array('EE_Register_Data_Migration_Scripts', 'add_data_migration_script_folders')
77
+		);
78
+	}
79 79
 
80 80
 
81
-    /**
82
-     * @param array $dms_paths
83
-     * @return array
84
-     */
85
-    public static function add_data_migration_script_folders($dms_paths = array())
86
-    {
87
-        foreach (self::$_settings as $addon_name => $settings) {
88
-            $wildcards = 0;
89
-            foreach ($settings['dms_paths'] as $dms_path) {
90
-                // since we are using the addon name for the array key
91
-                // we need to ensure that the key is unique,
92
-                // so if for some reason an addon has multiple dms paths,
93
-                // we append one or more * to the classname
94
-                // which will get stripped out later on
95
-                $dms_paths[ $addon_name . str_repeat('*', $wildcards) ] = $dms_path;
96
-                $wildcards++;
97
-            }
98
-        }
99
-        return $dms_paths;
100
-    }
81
+	/**
82
+	 * @param array $dms_paths
83
+	 * @return array
84
+	 */
85
+	public static function add_data_migration_script_folders($dms_paths = array())
86
+	{
87
+		foreach (self::$_settings as $addon_name => $settings) {
88
+			$wildcards = 0;
89
+			foreach ($settings['dms_paths'] as $dms_path) {
90
+				// since we are using the addon name for the array key
91
+				// we need to ensure that the key is unique,
92
+				// so if for some reason an addon has multiple dms paths,
93
+				// we append one or more * to the classname
94
+				// which will get stripped out later on
95
+				$dms_paths[ $addon_name . str_repeat('*', $wildcards) ] = $dms_path;
96
+				$wildcards++;
97
+			}
98
+		}
99
+		return $dms_paths;
100
+	}
101 101
 
102 102
 
103
-    /**
104
-     * This deregisters a set of Data Migration Scripts that were previously registered with a specific dms_id
105
-     *
106
-     * @since 4.3.0
107
-     * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
108
-     * @return void
109
-     */
110
-    public static function deregister($addon_name = '')
111
-    {
112
-        unset(self::$_settings[ $addon_name ]);
113
-    }
103
+	/**
104
+	 * This deregisters a set of Data Migration Scripts that were previously registered with a specific dms_id
105
+	 *
106
+	 * @since 4.3.0
107
+	 * @param string $addon_name EE_Addon class name that this set of data migration scripts belongs to
108
+	 * @return void
109
+	 */
110
+	public static function deregister($addon_name = '')
111
+	{
112
+		unset(self::$_settings[ $addon_name ]);
113
+	}
114 114
 }
115 115
 // End of file EE_Register_Data_Migration_Scripts.lib.php
116 116
 // Location: /core/libraries/plugin_api/EE_Register_Data_Migration_Scripts.lib.php
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -50,11 +50,11 @@  discard block
 block discarded – undo
50 50
             );
51 51
         }
52 52
         //make sure we don't register twice
53
-        if (isset(self::$_settings[ $addon_name ])) {
53
+        if (isset(self::$_settings[$addon_name])) {
54 54
             return;
55 55
         }
56 56
         //make sure this was called in the right place!
57
-        if (! did_action('AHEE__EE_System__load_espresso_addons')
57
+        if ( ! did_action('AHEE__EE_System__load_espresso_addons')
58 58
             || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')
59 59
         ) {
60 60
             EE_Error::doing_it_wrong(
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
             );
68 68
         }
69 69
         //setup $_settings array from incoming values.
70
-        self::$_settings[ $addon_name ] = array(
70
+        self::$_settings[$addon_name] = array(
71 71
             'dms_paths' => (array) $setup_args['dms_paths']
72 72
         );
73 73
         // setup DMS
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
                 // so if for some reason an addon has multiple dms paths,
93 93
                 // we append one or more * to the classname
94 94
                 // which will get stripped out later on
95
-                $dms_paths[ $addon_name . str_repeat('*', $wildcards) ] = $dms_path;
95
+                $dms_paths[$addon_name.str_repeat('*', $wildcards)] = $dms_path;
96 96
                 $wildcards++;
97 97
             }
98 98
         }
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
      */
110 110
     public static function deregister($addon_name = '')
111 111
     {
112
-        unset(self::$_settings[ $addon_name ]);
112
+        unset(self::$_settings[$addon_name]);
113 113
     }
114 114
 }
115 115
 // End of file EE_Register_Data_Migration_Scripts.lib.php
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1587 added lines, -1587 removed lines patch added patch discarded remove patch
@@ -23,1593 +23,1593 @@
 block discarded – undo
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registry $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var EE_Dependency_Map $_dependency_map
33
-     */
34
-    protected $_dependency_map;
35
-
36
-    /**
37
-     * @var array $_class_abbreviations
38
-     */
39
-    protected $_class_abbreviations = array();
40
-
41
-    /**
42
-     * @var CommandBusInterface $BUS
43
-     */
44
-    public $BUS;
45
-
46
-    /**
47
-     * @var EE_Cart $CART
48
-     */
49
-    public $CART;
50
-
51
-    /**
52
-     * @var EE_Config $CFG
53
-     */
54
-    public $CFG;
55
-
56
-    /**
57
-     * @var EE_Network_Config $NET_CFG
58
-     */
59
-    public $NET_CFG;
60
-
61
-    /**
62
-     * StdClass object for storing library classes in
63
-     *
64
-     * @var StdClass $LIB
65
-     */
66
-    public $LIB;
67
-
68
-    /**
69
-     * @var EE_Request_Handler $REQ
70
-     */
71
-    public $REQ;
72
-
73
-    /**
74
-     * @var EE_Session $SSN
75
-     */
76
-    public $SSN;
77
-
78
-    /**
79
-     * @since 4.5.0
80
-     * @var EE_Capabilities $CAP
81
-     */
82
-    public $CAP;
83
-
84
-    /**
85
-     * @since 4.9.0
86
-     * @var EE_Message_Resource_Manager $MRM
87
-     */
88
-    public $MRM;
89
-
90
-
91
-    /**
92
-     * @var Registry $AssetsRegistry
93
-     */
94
-    public $AssetsRegistry;
95
-
96
-    /**
97
-     * StdClass object for holding addons which have registered themselves to work with EE core
98
-     *
99
-     * @var EE_Addon[] $addons
100
-     */
101
-    public $addons;
102
-
103
-    /**
104
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
105
-     *
106
-     * @var EEM_Base[] $models
107
-     */
108
-    public $models = array();
109
-
110
-    /**
111
-     * @var EED_Module[] $modules
112
-     */
113
-    public $modules;
114
-
115
-    /**
116
-     * @var EES_Shortcode[] $shortcodes
117
-     */
118
-    public $shortcodes;
119
-
120
-    /**
121
-     * @var WP_Widget[] $widgets
122
-     */
123
-    public $widgets;
124
-
125
-    /**
126
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
127
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
128
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
129
-     * classnames (eg "EEM_Event")
130
-     *
131
-     * @var array $non_abstract_db_models
132
-     */
133
-    public $non_abstract_db_models = array();
134
-
135
-
136
-    /**
137
-     * internationalization for JS strings
138
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
139
-     *    in js file:  var translatedString = eei18n.string_key;
140
-     *
141
-     * @var array $i18n_js_strings
142
-     */
143
-    public static $i18n_js_strings = array();
144
-
145
-
146
-    /**
147
-     * $main_file - path to espresso.php
148
-     *
149
-     * @var array $main_file
150
-     */
151
-    public $main_file;
152
-
153
-    /**
154
-     * array of ReflectionClass objects where the key is the class name
155
-     *
156
-     * @var ReflectionClass[] $_reflectors
157
-     */
158
-    public $_reflectors;
159
-
160
-    /**
161
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
162
-     *
163
-     * @var boolean $_cache_on
164
-     */
165
-    protected $_cache_on = true;
166
-
167
-
168
-
169
-    /**
170
-     * @singleton method used to instantiate class object
171
-     * @param  EE_Dependency_Map $dependency_map
172
-     * @return EE_Registry instance
173
-     * @throws InvalidArgumentException
174
-     * @throws InvalidInterfaceException
175
-     * @throws InvalidDataTypeException
176
-     */
177
-    public static function instance(EE_Dependency_Map $dependency_map = null)
178
-    {
179
-        // check if class object is instantiated
180
-        if (! self::$_instance instanceof EE_Registry) {
181
-            self::$_instance = new self($dependency_map);
182
-        }
183
-        return self::$_instance;
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * protected constructor to prevent direct creation
190
-     *
191
-     * @Constructor
192
-     * @param  EE_Dependency_Map $dependency_map
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     * @throws InvalidArgumentException
196
-     */
197
-    protected function __construct(EE_Dependency_Map $dependency_map)
198
-    {
199
-        $this->_dependency_map = $dependency_map;
200
-        // $registry_container = new RegistryContainer();
201
-        $this->LIB = new RegistryContainer();
202
-        $this->addons = new RegistryContainer();
203
-        $this->modules = new RegistryContainer();
204
-        $this->shortcodes = new RegistryContainer();
205
-        $this->widgets = new RegistryContainer();
206
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
207
-    }
208
-
209
-
210
-
211
-    /**
212
-     * initialize
213
-     *
214
-     * @throws EE_Error
215
-     * @throws ReflectionException
216
-     */
217
-    public function initialize()
218
-    {
219
-        $this->_class_abbreviations = apply_filters(
220
-            'FHEE__EE_Registry____construct___class_abbreviations',
221
-            array(
222
-                'EE_Config'                                       => 'CFG',
223
-                'EE_Session'                                      => 'SSN',
224
-                'EE_Capabilities'                                 => 'CAP',
225
-                'EE_Cart'                                         => 'CART',
226
-                'EE_Network_Config'                               => 'NET_CFG',
227
-                'EE_Request_Handler'                              => 'REQ',
228
-                'EE_Message_Resource_Manager'                     => 'MRM',
229
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
230
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
231
-            )
232
-        );
233
-        $this->load_core('Base', array(), true);
234
-        // add our request and response objects to the cache
235
-        $request_loader = $this->_dependency_map->class_loader(
236
-            'EventEspresso\core\services\request\Request'
237
-        );
238
-        $this->_set_cached_class(
239
-            $request_loader(),
240
-            'EventEspresso\core\services\request\Request'
241
-        );
242
-        $response_loader = $this->_dependency_map->class_loader(
243
-            'EventEspresso\core\services\request\Response'
244
-        );
245
-        $this->_set_cached_class(
246
-            $response_loader(),
247
-            'EventEspresso\core\services\request\Response'
248
-        );
249
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     * @return void
256
-     */
257
-    public function init()
258
-    {
259
-        // Get current page protocol
260
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
261
-        // Output admin-ajax.php URL with same protocol as current page
262
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
263
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
264
-    }
265
-
266
-
267
-
268
-    /**
269
-     * localize_i18n_js_strings
270
-     *
271
-     * @return string
272
-     */
273
-    public static function localize_i18n_js_strings()
274
-    {
275
-        $i18n_js_strings = (array)self::$i18n_js_strings;
276
-        foreach ($i18n_js_strings as $key => $value) {
277
-            if (is_scalar($value)) {
278
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
279
-            }
280
-        }
281
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @param mixed string | EED_Module $module
288
-     * @throws EE_Error
289
-     * @throws ReflectionException
290
-     */
291
-    public function add_module($module)
292
-    {
293
-        if ($module instanceof EED_Module) {
294
-            $module_class = get_class($module);
295
-            $this->modules->{$module_class} = $module;
296
-        } else {
297
-            if ( ! class_exists('EE_Module_Request_Router', false)) {
298
-                $this->load_core('Module_Request_Router');
299
-            }
300
-            EE_Module_Request_Router::module_factory($module);
301
-        }
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @param string $module_name
308
-     * @return mixed EED_Module | NULL
309
-     */
310
-    public function get_module($module_name = '')
311
-    {
312
-        return isset($this->modules->{$module_name})
313
-            ? $this->modules->{$module_name}
314
-            : null;
315
-    }
316
-
317
-
318
-
319
-    /**
320
-     * loads core classes - must be singletons
321
-     *
322
-     * @param string $class_name - simple class name ie: session
323
-     * @param mixed  $arguments
324
-     * @param bool   $load_only
325
-     * @return mixed
326
-     * @throws EE_Error
327
-     * @throws ReflectionException
328
-     */
329
-    public function load_core($class_name, $arguments = array(), $load_only = false)
330
-    {
331
-        $core_paths = apply_filters(
332
-            'FHEE__EE_Registry__load_core__core_paths',
333
-            array(
334
-                EE_CORE,
335
-                EE_ADMIN,
336
-                EE_CPTS,
337
-                EE_CORE . 'data_migration_scripts' . DS,
338
-                EE_CORE . 'capabilities' . DS,
339
-                EE_CORE . 'request_stack' . DS,
340
-                EE_CORE . 'middleware' . DS,
341
-            )
342
-        );
343
-        // retrieve instantiated class
344
-        return $this->_load(
345
-            $core_paths,
346
-            'EE_',
347
-            $class_name,
348
-            'core',
349
-            $arguments,
350
-            false,
351
-            true,
352
-            $load_only
353
-        );
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * loads service classes
360
-     *
361
-     * @param string $class_name - simple class name ie: session
362
-     * @param mixed  $arguments
363
-     * @param bool   $load_only
364
-     * @return mixed
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    public function load_service($class_name, $arguments = array(), $load_only = false)
369
-    {
370
-        $service_paths = apply_filters(
371
-            'FHEE__EE_Registry__load_service__service_paths',
372
-            array(
373
-                EE_CORE . 'services' . DS,
374
-            )
375
-        );
376
-        // retrieve instantiated class
377
-        return $this->_load(
378
-            $service_paths,
379
-            'EE_',
380
-            $class_name,
381
-            'class',
382
-            $arguments,
383
-            false,
384
-            true,
385
-            $load_only
386
-        );
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * loads data_migration_scripts
393
-     *
394
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
395
-     * @param mixed  $arguments
396
-     * @return EE_Data_Migration_Script_Base|mixed
397
-     * @throws EE_Error
398
-     * @throws ReflectionException
399
-     */
400
-    public function load_dms($class_name, $arguments = array())
401
-    {
402
-        // retrieve instantiated class
403
-        return $this->_load(
404
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
405
-            'EE_DMS_',
406
-            $class_name,
407
-            'dms',
408
-            $arguments,
409
-            false,
410
-            false
411
-        );
412
-    }
413
-
414
-
415
-
416
-    /**
417
-     * loads object creating classes - must be singletons
418
-     *
419
-     * @param string $class_name - simple class name ie: attendee
420
-     * @param mixed  $arguments  - an array of arguments to pass to the class
421
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
422
-     *                           instantiate
423
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
424
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
425
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
426
-     *                           (default)
427
-     * @return EE_Base_Class | bool
428
-     * @throws EE_Error
429
-     * @throws ReflectionException
430
-     */
431
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
432
-    {
433
-        $paths = apply_filters(
434
-            'FHEE__EE_Registry__load_class__paths', array(
435
-            EE_CORE,
436
-            EE_CLASSES,
437
-            EE_BUSINESS,
438
-        )
439
-        );
440
-        // retrieve instantiated class
441
-        return $this->_load(
442
-            $paths,
443
-            'EE_',
444
-            $class_name,
445
-            'class',
446
-            $arguments,
447
-            $from_db,
448
-            $cache,
449
-            $load_only
450
-        );
451
-    }
452
-
453
-
454
-
455
-    /**
456
-     * loads helper classes - must be singletons
457
-     *
458
-     * @param string $class_name - simple class name ie: price
459
-     * @param mixed  $arguments
460
-     * @param bool   $load_only
461
-     * @return EEH_Base | bool
462
-     * @throws EE_Error
463
-     * @throws ReflectionException
464
-     */
465
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
466
-    {
467
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
468
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
469
-        // retrieve instantiated class
470
-        return $this->_load(
471
-            $helper_paths,
472
-            'EEH_',
473
-            $class_name,
474
-            'helper',
475
-            $arguments,
476
-            false,
477
-            true,
478
-            $load_only
479
-        );
480
-    }
481
-
482
-
483
-
484
-    /**
485
-     * loads core classes - must be singletons
486
-     *
487
-     * @param string $class_name - simple class name ie: session
488
-     * @param mixed  $arguments
489
-     * @param bool   $load_only
490
-     * @param bool   $cache      whether to cache the object or not.
491
-     * @return mixed
492
-     * @throws EE_Error
493
-     * @throws ReflectionException
494
-     */
495
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
496
-    {
497
-        $paths = array(
498
-            EE_LIBRARIES,
499
-            EE_LIBRARIES . 'messages' . DS,
500
-            EE_LIBRARIES . 'shortcodes' . DS,
501
-            EE_LIBRARIES . 'qtips' . DS,
502
-            EE_LIBRARIES . 'payment_methods' . DS,
503
-        );
504
-        // retrieve instantiated class
505
-        return $this->_load(
506
-            $paths,
507
-            'EE_',
508
-            $class_name,
509
-            'lib',
510
-            $arguments,
511
-            false,
512
-            $cache,
513
-            $load_only
514
-        );
515
-    }
516
-
517
-
518
-
519
-    /**
520
-     * loads model classes - must be singletons
521
-     *
522
-     * @param string $class_name - simple class name ie: price
523
-     * @param mixed  $arguments
524
-     * @param bool   $load_only
525
-     * @return EEM_Base | bool
526
-     * @throws EE_Error
527
-     * @throws ReflectionException
528
-     */
529
-    public function load_model($class_name, $arguments = array(), $load_only = false)
530
-    {
531
-        $paths = apply_filters(
532
-            'FHEE__EE_Registry__load_model__paths', array(
533
-            EE_MODELS,
534
-            EE_CORE,
535
-        )
536
-        );
537
-        // retrieve instantiated class
538
-        return $this->_load(
539
-            $paths,
540
-            'EEM_',
541
-            $class_name,
542
-            'model',
543
-            $arguments,
544
-            false,
545
-            true,
546
-            $load_only
547
-        );
548
-    }
549
-
550
-
551
-
552
-    /**
553
-     * loads model classes - must be singletons
554
-     *
555
-     * @param string $class_name - simple class name ie: price
556
-     * @param mixed  $arguments
557
-     * @param bool   $load_only
558
-     * @return mixed | bool
559
-     * @throws EE_Error
560
-     * @throws ReflectionException
561
-     */
562
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
563
-    {
564
-        $paths = array(
565
-            EE_MODELS . 'fields' . DS,
566
-            EE_MODELS . 'helpers' . DS,
567
-            EE_MODELS . 'relations' . DS,
568
-            EE_MODELS . 'strategies' . DS,
569
-        );
570
-        // retrieve instantiated class
571
-        return $this->_load(
572
-            $paths,
573
-            'EE_',
574
-            $class_name,
575
-            '',
576
-            $arguments,
577
-            false,
578
-            true,
579
-            $load_only
580
-        );
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     * Determines if $model_name is the name of an actual EE model.
587
-     *
588
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
589
-     * @return boolean
590
-     */
591
-    public function is_model_name($model_name)
592
-    {
593
-        return isset($this->models[$model_name]);
594
-    }
595
-
596
-
597
-
598
-    /**
599
-     * generic class loader
600
-     *
601
-     * @param string $path_to_file - directory path to file location, not including filename
602
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
603
-     * @param string $type         - file type - core? class? helper? model?
604
-     * @param mixed  $arguments
605
-     * @param bool   $load_only
606
-     * @return mixed
607
-     * @throws EE_Error
608
-     * @throws ReflectionException
609
-     */
610
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
611
-    {
612
-        // retrieve instantiated class
613
-        return $this->_load(
614
-            $path_to_file,
615
-            '',
616
-            $file_name,
617
-            $type,
618
-            $arguments,
619
-            false,
620
-            true,
621
-            $load_only
622
-        );
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @param string $path_to_file - directory path to file location, not including filename
629
-     * @param string $class_name   - full class name  ie:  My_Class
630
-     * @param string $type         - file type - core? class? helper? model?
631
-     * @param mixed  $arguments
632
-     * @param bool   $load_only
633
-     * @return bool|EE_Addon|object
634
-     * @throws EE_Error
635
-     * @throws ReflectionException
636
-     */
637
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
638
-    {
639
-        // retrieve instantiated class
640
-        return $this->_load(
641
-            $path_to_file,
642
-            'addon',
643
-            $class_name,
644
-            $type,
645
-            $arguments,
646
-            false,
647
-            true,
648
-            $load_only
649
-        );
650
-    }
651
-
652
-
653
-
654
-    /**
655
-     * instantiates, caches, and automatically resolves dependencies
656
-     * for classes that use a Fully Qualified Class Name.
657
-     * if the class is not capable of being loaded using PSR-4 autoloading,
658
-     * then you need to use one of the existing load_*() methods
659
-     * which can resolve the classname and filepath from the passed arguments
660
-     *
661
-     * @param bool|string $class_name   Fully Qualified Class Name
662
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
663
-     * @param bool        $cache        whether to cache the instantiated object for reuse
664
-     * @param bool        $from_db      some classes are instantiated from the db
665
-     *                                  and thus call a different method to instantiate
666
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
667
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
668
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
669
-     *                                  object = class loaded and instantiated successfully.
670
-     *                                  bool = fail or success when $load_only is true
671
-     * @throws EE_Error
672
-     * @throws ReflectionException
673
-     */
674
-    public function create(
675
-        $class_name = false,
676
-        $arguments = array(),
677
-        $cache = false,
678
-        $from_db = false,
679
-        $load_only = false,
680
-        $addon = false
681
-    ) {
682
-        $class_name = ltrim($class_name, '\\');
683
-        $class_name = $this->_dependency_map->get_alias($class_name);
684
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
685
-        // if a non-FQCN was passed, then verifyClassExists() might return an object
686
-        // or it could return null if the class just could not be found anywhere
687
-        if ($class_exists instanceof $class_name || $class_exists === null){
688
-            // either way, return the results
689
-            return $class_exists;
690
-        }
691
-        $class_name = $class_exists;
692
-        // if we're only loading the class and it already exists, then let's just return true immediately
693
-        if ($load_only) {
694
-            return true;
695
-        }
696
-        $addon = $addon
697
-            ? 'addon'
698
-            : '';
699
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
700
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
701
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
702
-        if ($this->_cache_on && $cache && ! $load_only) {
703
-            // return object if it's already cached
704
-            $cached_class = $this->_get_cached_class($class_name, $addon);
705
-            if ($cached_class !== null) {
706
-                return $cached_class;
707
-            }
708
-        }
709
-        // obtain the loader method from the dependency map
710
-        $loader = $this->_dependency_map->class_loader($class_name);
711
-        // instantiate the requested object
712
-        if ($loader instanceof Closure) {
713
-            $class_obj = $loader($arguments);
714
-        } else if ($loader && method_exists($this, $loader)) {
715
-            $class_obj = $this->{$loader}($class_name, $arguments);
716
-        } else {
717
-            $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
718
-        }
719
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
720
-            // save it for later... kinda like gum  { : $
721
-            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
722
-        }
723
-        $this->_cache_on = true;
724
-        return $class_obj;
725
-    }
726
-
727
-
728
-
729
-    /**
730
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
731
-     *
732
-     * @param string $class_name
733
-     * @param array  $arguments
734
-     * @param int    $attempt
735
-     * @return mixed
736
-     */
737
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1) {
738
-        if (is_object($class_name) || class_exists($class_name)) {
739
-            return $class_name;
740
-        }
741
-        switch ($attempt) {
742
-            case 1:
743
-                // if it's a FQCN then maybe the class is registered with a preceding \
744
-                $class_name = strpos($class_name, '\\') !== false
745
-                    ? '\\' . ltrim($class_name, '\\')
746
-                    : $class_name;
747
-                break;
748
-            case 2:
749
-                //
750
-                $loader = $this->_dependency_map->class_loader($class_name);
751
-                if ($loader && method_exists($this, $loader)) {
752
-                    return $this->{$loader}($class_name, $arguments);
753
-                }
754
-                break;
755
-            case 3:
756
-            default;
757
-                return null;
758
-        }
759
-        $attempt++;
760
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
761
-    }
762
-
763
-
764
-
765
-    /**
766
-     * instantiates, caches, and injects dependencies for classes
767
-     *
768
-     * @param array       $file_paths   an array of paths to folders to look in
769
-     * @param string      $class_prefix EE  or EEM or... ???
770
-     * @param bool|string $class_name   $class name
771
-     * @param string      $type         file type - core? class? helper? model?
772
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
773
-     * @param bool        $from_db      some classes are instantiated from the db
774
-     *                                  and thus call a different method to instantiate
775
-     * @param bool        $cache        whether to cache the instantiated object for reuse
776
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
777
-     * @return bool|null|object null = failure to load or instantiate class object.
778
-     *                                  object = class loaded and instantiated successfully.
779
-     *                                  bool = fail or success when $load_only is true
780
-     * @throws EE_Error
781
-     * @throws ReflectionException
782
-     */
783
-    protected function _load(
784
-        $file_paths = array(),
785
-        $class_prefix = 'EE_',
786
-        $class_name = false,
787
-        $type = 'class',
788
-        $arguments = array(),
789
-        $from_db = false,
790
-        $cache = true,
791
-        $load_only = false
792
-    ) {
793
-        $class_name = ltrim($class_name, '\\');
794
-        // strip php file extension
795
-        $class_name = str_replace('.php', '', trim($class_name));
796
-        // does the class have a prefix ?
797
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
798
-            // make sure $class_prefix is uppercase
799
-            $class_prefix = strtoupper(trim($class_prefix));
800
-            // add class prefix ONCE!!!
801
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
802
-        }
803
-        $class_name = $this->_dependency_map->get_alias($class_name);
804
-        $class_exists = class_exists($class_name, false);
805
-        // if we're only loading the class and it already exists, then let's just return true immediately
806
-        if ($load_only && $class_exists) {
807
-            return true;
808
-        }
809
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
810
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
811
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
812
-        if ($this->_cache_on && $cache && ! $load_only) {
813
-            // return object if it's already cached
814
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
815
-            if ($cached_class !== null) {
816
-                return $cached_class;
817
-            }
818
-        }
819
-        // if the class doesn't already exist.. then we need to try and find the file and load it
820
-        if (! $class_exists) {
821
-            // get full path to file
822
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
823
-            // load the file
824
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
825
-            // if loading failed, or we are only loading a file but NOT instantiating an object
826
-            if (! $loaded || $load_only) {
827
-                // return boolean if only loading, or null if an object was expected
828
-                return $load_only
829
-                    ? $loaded
830
-                    : null;
831
-            }
832
-        }
833
-        // instantiate the requested object
834
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
835
-        if ($this->_cache_on && $cache) {
836
-            // save it for later... kinda like gum  { : $
837
-            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
838
-        }
839
-        $this->_cache_on = true;
840
-        return $class_obj;
841
-    }
842
-
843
-
844
-
845
-    /**
846
-     * @param string $class_name
847
-     * @param string $default have to specify something, but not anything that will conflict
848
-     * @return mixed|string
849
-     */
850
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
851
-    {
852
-        return isset($this->_class_abbreviations[$class_name])
853
-            ? $this->_class_abbreviations[$class_name]
854
-            : $default;
855
-    }
856
-
857
-    /**
858
-     * attempts to find a cached version of the requested class
859
-     * by looking in the following places:
860
-     *        $this->{$class_abbreviation}            ie:    $this->CART
861
-     *        $this->{$class_name}                        ie:    $this->Some_Class
862
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
863
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
864
-     *
865
-     * @param string $class_name
866
-     * @param string $class_prefix
867
-     * @return mixed
868
-     * @throws OutOfBoundsException
869
-     */
870
-    protected function _get_cached_class($class_name, $class_prefix = '')
871
-    {
872
-        if ($class_name === 'EE_Registry') {
873
-            return $this;
874
-        }
875
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
876
-        $class_name = str_replace('\\', '_', $class_name);
877
-        // check if class has already been loaded, and return it if it has been
878
-        if (isset($this->{$class_abbreviation})) {
879
-            return $this->{$class_abbreviation};
880
-        }
881
-        if (isset ($this->{$class_name})) {
882
-            return $this->{$class_name};
883
-        }
884
-        if (isset ($this->LIB->{$class_name})) {
885
-            return $this->LIB->{$class_name};
886
-        }
887
-        if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
888
-            return $this->addons->{$class_name};
889
-        }
890
-        return null;
891
-    }
892
-
893
-
894
-
895
-    /**
896
-     * removes a cached version of the requested class
897
-     *
898
-     * @param string  $class_name
899
-     * @param boolean $addon
900
-     * @return boolean
901
-     * @throws OutOfBoundsException
902
-     */
903
-    public function clear_cached_class($class_name, $addon = false)
904
-    {
905
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
906
-        $class_name = str_replace('\\', '_', $class_name);
907
-        // check if class has already been loaded, and return it if it has been
908
-        if (isset($this->{$class_abbreviation})) {
909
-            $this->{$class_abbreviation} = null;
910
-            return true;
911
-        }
912
-        if (isset($this->{$class_name})) {
913
-            $this->{$class_name} = null;
914
-            return true;
915
-        }
916
-        if (isset($this->LIB->{$class_name})) {
917
-            unset($this->LIB->{$class_name});
918
-            return true;
919
-        }
920
-        if ($addon && isset($this->addons->{$class_name})) {
921
-            unset($this->addons->{$class_name});
922
-            return true;
923
-        }
924
-        return false;
925
-    }
926
-
927
-
928
-
929
-    /**
930
-     * attempts to find a full valid filepath for the requested class.
931
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
932
-     * then returns that path if the target file has been found and is readable
933
-     *
934
-     * @param string $class_name
935
-     * @param string $type
936
-     * @param array  $file_paths
937
-     * @return string | bool
938
-     */
939
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
940
-    {
941
-        // make sure $file_paths is an array
942
-        $file_paths = is_array($file_paths)
943
-            ? $file_paths
944
-            : array($file_paths);
945
-        // cycle thru paths
946
-        foreach ($file_paths as $key => $file_path) {
947
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
948
-            $file_path = $file_path
949
-                ? str_replace(array('/', '\\'), DS, $file_path)
950
-                : EE_CLASSES;
951
-            // prep file type
952
-            $type = ! empty($type)
953
-                ? trim($type, '.') . '.'
954
-                : '';
955
-            // build full file path
956
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
957
-            //does the file exist and can be read ?
958
-            if (is_readable($file_paths[$key])) {
959
-                return $file_paths[$key];
960
-            }
961
-        }
962
-        return false;
963
-    }
964
-
965
-
966
-
967
-    /**
968
-     * basically just performs a require_once()
969
-     * but with some error handling
970
-     *
971
-     * @param  string $path
972
-     * @param  string $class_name
973
-     * @param  string $type
974
-     * @param  array  $file_paths
975
-     * @return bool
976
-     * @throws EE_Error
977
-     * @throws ReflectionException
978
-     */
979
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
980
-    {
981
-        $this->resolve_legacy_class_parent($class_name);
982
-        // don't give up! you gotta...
983
-        try {
984
-            //does the file exist and can it be read ?
985
-            if (! $path) {
986
-                // just in case the file has already been autoloaded,
987
-                // but discrepancies in the naming schema are preventing it from
988
-                // being loaded via one of the EE_Registry::load_*() methods,
989
-                // then let's try one last hail mary before throwing an exception
990
-                // and call class_exists() again, but with autoloading turned ON
991
-                if(class_exists($class_name)) {
992
-                    return true;
993
-                }
994
-                // so sorry, can't find the file
995
-                throw new EE_Error (
996
-                    sprintf(
997
-                        esc_html__(
998
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
999
-                            'event_espresso'
1000
-                        ),
1001
-                        trim($type, '.'),
1002
-                        $class_name,
1003
-                        '<br />' . implode(',<br />', $file_paths)
1004
-                    )
1005
-                );
1006
-            }
1007
-            // get the file
1008
-            require_once($path);
1009
-            // if the class isn't already declared somewhere
1010
-            if (class_exists($class_name, false) === false) {
1011
-                // so sorry, not a class
1012
-                throw new EE_Error(
1013
-                    sprintf(
1014
-                        esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
1015
-                        $type,
1016
-                        $path,
1017
-                        $class_name
1018
-                    )
1019
-                );
1020
-            }
1021
-        } catch (EE_Error $e) {
1022
-            $e->get_error();
1023
-            return false;
1024
-        }
1025
-        return true;
1026
-    }
1027
-
1028
-
1029
-
1030
-    /**
1031
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1032
-     * before their class declaration in order to ensure that the parent class was loaded.
1033
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1034
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1035
-     *
1036
-     * @param string $class_name
1037
-     */
1038
-    protected function resolve_legacy_class_parent($class_name = '')
1039
-    {
1040
-        try {
1041
-            $legacy_parent_class_map = array(
1042
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
1043
-            );
1044
-            if(isset($legacy_parent_class_map[$class_name])) {
1045
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
1046
-            }
1047
-        } catch (Exception $exception) {
1048
-        }
1049
-    }
1050
-
1051
-
1052
-
1053
-    /**
1054
-     * _create_object
1055
-     * Attempts to instantiate the requested class via any of the
1056
-     * commonly used instantiation methods employed throughout EE.
1057
-     * The priority for instantiation is as follows:
1058
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1059
-     *        - model objects via their 'new_instance_from_db' method
1060
-     *        - model objects via their 'new_instance' method
1061
-     *        - "singleton" classes" via their 'instance' method
1062
-     *    - standard instantiable classes via their __constructor
1063
-     * Prior to instantiation, if the classname exists in the dependency_map,
1064
-     * then the constructor for the requested class will be examined to determine
1065
-     * if any dependencies exist, and if they can be injected.
1066
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1067
-     *
1068
-     * @param string $class_name
1069
-     * @param array  $arguments
1070
-     * @param string $type
1071
-     * @param bool   $from_db
1072
-     * @return null|object
1073
-     * @throws EE_Error
1074
-     * @throws ReflectionException
1075
-     */
1076
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1077
-    {
1078
-        // create reflection
1079
-        $reflector = $this->get_ReflectionClass($class_name);
1080
-        // make sure arguments are an array
1081
-        $arguments = is_array($arguments)
1082
-            ? $arguments
1083
-            : array($arguments);
1084
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1085
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1086
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1087
-            ? $arguments
1088
-            : array($arguments);
1089
-        // attempt to inject dependencies ?
1090
-        if ($this->_dependency_map->has($class_name)) {
1091
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1092
-        }
1093
-        // instantiate the class if possible
1094
-        if ($reflector->isAbstract()) {
1095
-            // nothing to instantiate, loading file was enough
1096
-            // does not throw an exception so $instantiation_mode is unused
1097
-            // $instantiation_mode = "1) no constructor abstract class";
1098
-            return true;
1099
-        }
1100
-        if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1101
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1102
-            // $instantiation_mode = "2) no constructor but instantiable";
1103
-            return $reflector->newInstance();
1104
-        }
1105
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1106
-            // $instantiation_mode = "3) new_instance_from_db()";
1107
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1108
-        }
1109
-        if (method_exists($class_name, 'new_instance')) {
1110
-            // $instantiation_mode = "4) new_instance()";
1111
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1112
-        }
1113
-        if (method_exists($class_name, 'instance')) {
1114
-            // $instantiation_mode = "5) instance()";
1115
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1116
-        }
1117
-        if ($reflector->isInstantiable()) {
1118
-            // $instantiation_mode = "6) constructor";
1119
-            return $reflector->newInstanceArgs($arguments);
1120
-        }
1121
-        // heh ? something's not right !
1122
-        throw new EE_Error(
1123
-            sprintf(
1124
-                __('The %s file %s could not be instantiated.', 'event_espresso'),
1125
-                $type,
1126
-                $class_name
1127
-            )
1128
-        );
1129
-    }
1130
-
1131
-
1132
-
1133
-    /**
1134
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1135
-     * @param array $array
1136
-     * @return bool
1137
-     */
1138
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1139
-    {
1140
-        return ! empty($array)
1141
-            ? array_keys($array) === range(0, count($array) - 1)
1142
-            : true;
1143
-    }
1144
-
1145
-
1146
-
1147
-    /**
1148
-     * getReflectionClass
1149
-     * checks if a ReflectionClass object has already been generated for a class
1150
-     * and returns that instead of creating a new one
1151
-     *
1152
-     * @param string $class_name
1153
-     * @return ReflectionClass
1154
-     * @throws ReflectionException
1155
-     */
1156
-    public function get_ReflectionClass($class_name)
1157
-    {
1158
-        if (
1159
-            ! isset($this->_reflectors[$class_name])
1160
-            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
1161
-        ) {
1162
-            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
1163
-        }
1164
-        return $this->_reflectors[$class_name];
1165
-    }
1166
-
1167
-
1168
-
1169
-    /**
1170
-     * _resolve_dependencies
1171
-     * examines the constructor for the requested class to determine
1172
-     * if any dependencies exist, and if they can be injected.
1173
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1174
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1175
-     * For example:
1176
-     *        if attempting to load a class "Foo" with the following constructor:
1177
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1178
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1179
-     *        but only IF they are NOT already present in the incoming arguments array,
1180
-     *        and the correct classes can be loaded
1181
-     *
1182
-     * @param ReflectionClass $reflector
1183
-     * @param string          $class_name
1184
-     * @param array           $arguments
1185
-     * @return array
1186
-     * @throws EE_Error
1187
-     * @throws ReflectionException
1188
-     */
1189
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1190
-    {
1191
-        // let's examine the constructor
1192
-        $constructor = $reflector->getConstructor();
1193
-        // whu? huh? nothing?
1194
-        if (! $constructor) {
1195
-            return $arguments;
1196
-        }
1197
-        // get constructor parameters
1198
-        $params = $constructor->getParameters();
1199
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1200
-        $argument_keys = array_keys($arguments);
1201
-        // now loop thru all of the constructors expected parameters
1202
-        foreach ($params as $index => $param) {
1203
-            // is this a dependency for a specific class ?
1204
-            $param_class = $param->getClass()
1205
-                ? $param->getClass()->name
1206
-                : null;
1207
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1208
-            $param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1209
-                ? $this->_dependency_map->get_alias($param_class, $class_name)
1210
-                : $param_class;
1211
-            if (
1212
-                // param is not even a class
1213
-                $param_class === null
1214
-                // and something already exists in the incoming arguments for this param
1215
-                && array_key_exists($index, $argument_keys)
1216
-                && array_key_exists($argument_keys[$index], $arguments)
1217
-            ) {
1218
-                // so let's skip this argument and move on to the next
1219
-                continue;
1220
-            }
1221
-            if (
1222
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1223
-                $param_class !== null
1224
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1225
-                && $arguments[$argument_keys[$index]] instanceof $param_class
1226
-            ) {
1227
-                // skip this argument and move on to the next
1228
-                continue;
1229
-            }
1230
-            if (
1231
-                // parameter is type hinted as a class, and should be injected
1232
-                $param_class !== null
1233
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1234
-            ) {
1235
-                $arguments = $this->_resolve_dependency(
1236
-                    $class_name,
1237
-                    $param_class,
1238
-                    $arguments,
1239
-                    $index,
1240
-                    $argument_keys
1241
-                );
1242
-            } else {
1243
-                try {
1244
-                    $arguments[$index] = $param->isDefaultValueAvailable()
1245
-                        ? $param->getDefaultValue()
1246
-                        : null;
1247
-                } catch (ReflectionException $e) {
1248
-                    throw new ReflectionException(
1249
-                        sprintf(
1250
-                            esc_html__('%1$s for parameter "$%2$s on classname "%3$s"', 'event_espresso'),
1251
-                            $e->getMessage(),
1252
-                            $param->getName(),
1253
-                            $class_name
1254
-                        )
1255
-                    );
1256
-                }
1257
-            }
1258
-        }
1259
-        return $arguments;
1260
-    }
1261
-
1262
-
1263
-
1264
-    /**
1265
-     * @param string $class_name
1266
-     * @param string $param_class
1267
-     * @param array  $arguments
1268
-     * @param mixed  $index
1269
-     * @param array  $argument_keys
1270
-     * @return array
1271
-     * @throws EE_Error
1272
-     * @throws ReflectionException
1273
-     * @throws InvalidArgumentException
1274
-     * @throws InvalidInterfaceException
1275
-     * @throws InvalidDataTypeException
1276
-     */
1277
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1278
-    {
1279
-        $dependency = null;
1280
-        // should dependency be loaded from cache ?
1281
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1282
-            $class_name,
1283
-            $param_class
1284
-        );
1285
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1286
-        // we might have a dependency...
1287
-        // let's MAYBE try and find it in our cache if that's what's been requested
1288
-        $cached_class = $cache_on
1289
-            ? $this->_get_cached_class($param_class)
1290
-            : null;
1291
-        // and grab it if it exists
1292
-        if ($cached_class instanceof $param_class) {
1293
-            $dependency = $cached_class;
1294
-        } else if ($param_class !== $class_name) {
1295
-            // obtain the loader method from the dependency map
1296
-            $loader = $this->_dependency_map->class_loader($param_class);
1297
-            // is loader a custom closure ?
1298
-            if ($loader instanceof Closure) {
1299
-                $dependency = $loader($arguments);
1300
-            } else {
1301
-                // set the cache on property for the recursive loading call
1302
-                $this->_cache_on = $cache_on;
1303
-                // if not, then let's try and load it via the registry
1304
-                if ($loader && method_exists($this, $loader)) {
1305
-                    $dependency = $this->{$loader}($param_class);
1306
-                } else {
1307
-                    $dependency = LoaderFactory::getLoader()->load(
1308
-                        $param_class,
1309
-                        array(),
1310
-                        $cache_on
1311
-                    );
1312
-                }
1313
-            }
1314
-        }
1315
-        // did we successfully find the correct dependency ?
1316
-        if ($dependency instanceof $param_class) {
1317
-            // then let's inject it into the incoming array of arguments at the correct location
1318
-            $arguments[$index] = $dependency;
1319
-        }
1320
-        return $arguments;
1321
-    }
1322
-
1323
-
1324
-
1325
-    /**
1326
-     * _set_cached_class
1327
-     * attempts to cache the instantiated class locally
1328
-     * in one of the following places, in the following order:
1329
-     *        $this->{class_abbreviation}   ie:    $this->CART
1330
-     *        $this->{$class_name}          ie:    $this->Some_Class
1331
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1332
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1333
-     *
1334
-     * @param object $class_obj
1335
-     * @param string $class_name
1336
-     * @param string $class_prefix
1337
-     * @param bool   $from_db
1338
-     * @return void
1339
-     * @throws OutOfBoundsException
1340
-     */
1341
-    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1342
-    {
1343
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1344
-            return;
1345
-        }
1346
-        // return newly instantiated class
1347
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1348
-        if ($class_abbreviation) {
1349
-            $this->{$class_abbreviation} = $class_obj;
1350
-            return;
1351
-        }
1352
-        $class_name = str_replace('\\', '_', $class_name);
1353
-        if (property_exists($this, $class_name)) {
1354
-            $this->{$class_name} = $class_obj;
1355
-            return;
1356
-        }
1357
-        if ($class_prefix === 'addon') {
1358
-            $this->addons->{$class_name} = $class_obj;
1359
-            return;
1360
-        }
1361
-        if (! $from_db) {
1362
-            $this->LIB->{$class_name} = $class_obj;
1363
-        }
1364
-    }
1365
-
1366
-
1367
-
1368
-    /**
1369
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1370
-     *
1371
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1372
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1373
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1374
-     * @param array  $arguments
1375
-     * @return object
1376
-     */
1377
-    public static function factory($classname, $arguments = array())
1378
-    {
1379
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1380
-        if ($loader instanceof Closure) {
1381
-            return $loader($arguments);
1382
-        }
1383
-        if (method_exists(self::instance(), $loader)) {
1384
-            return self::instance()->{$loader}($classname, $arguments);
1385
-        }
1386
-        return null;
1387
-    }
1388
-
1389
-
1390
-
1391
-    /**
1392
-     * Gets the addon by its class name
1393
-     *
1394
-     * @param string $class_name
1395
-     * @return EE_Addon
1396
-     * @throws OutOfBoundsException
1397
-     */
1398
-    public function getAddon($class_name)
1399
-    {
1400
-        $class_name = str_replace('\\', '_', $class_name);
1401
-        return $this->addons->{$class_name};
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * removes the addon from the internal cache
1407
-     *
1408
-     * @param string $class_name
1409
-     * @return void
1410
-     */
1411
-    public function removeAddon($class_name)
1412
-    {
1413
-        $class_name = str_replace('\\', '_', $class_name);
1414
-        unset($this->addons->{$class_name});
1415
-    }
1416
-
1417
-
1418
-
1419
-    /**
1420
-     * Gets the addon by its name/slug (not classname. For that, just
1421
-     * use the get_addon() method above
1422
-     *
1423
-     * @param string $name
1424
-     * @return EE_Addon
1425
-     */
1426
-    public function get_addon_by_name($name)
1427
-    {
1428
-        foreach ($this->addons as $addon) {
1429
-            if ($addon->name() === $name) {
1430
-                return $addon;
1431
-            }
1432
-        }
1433
-        return null;
1434
-    }
1435
-
1436
-
1437
-
1438
-    /**
1439
-     * Gets an array of all the registered addons, where the keys are their names.
1440
-     * (ie, what each returns for their name() function)
1441
-     * They're already available on EE_Registry::instance()->addons as properties,
1442
-     * where each property's name is the addon's classname,
1443
-     * So if you just want to get the addon by classname,
1444
-     * OR use the get_addon() method above.
1445
-     * PLEASE  NOTE:
1446
-     * addons with Fully Qualified Class Names
1447
-     * have had the namespace separators converted to underscores,
1448
-     * so a classname like Fully\Qualified\ClassName
1449
-     * would have been converted to Fully_Qualified_ClassName
1450
-     *
1451
-     * @return EE_Addon[] where the KEYS are the addon's name()
1452
-     */
1453
-    public function get_addons_by_name()
1454
-    {
1455
-        $addons = array();
1456
-        foreach ($this->addons as $addon) {
1457
-            $addons[$addon->name()] = $addon;
1458
-        }
1459
-        return $addons;
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1465
-     * a stale copy of it around
1466
-     *
1467
-     * @param string $model_name
1468
-     * @return \EEM_Base
1469
-     * @throws \EE_Error
1470
-     */
1471
-    public function reset_model($model_name)
1472
-    {
1473
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1474
-            ? "EEM_{$model_name}"
1475
-            : $model_name;
1476
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1477
-            return null;
1478
-        }
1479
-        //get that model reset it and make sure we nuke the old reference to it
1480
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name
1481
-            && is_callable(
1482
-                array($model_class_name, 'reset')
1483
-            )) {
1484
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1485
-        } else {
1486
-            throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1487
-        }
1488
-        return $this->LIB->{$model_class_name};
1489
-    }
1490
-
1491
-
1492
-
1493
-    /**
1494
-     * Resets the registry.
1495
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1496
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1497
-     * - $_dependency_map
1498
-     * - $_class_abbreviations
1499
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1500
-     * - $REQ:  Still on the same request so no need to change.
1501
-     * - $CAP: There is no site specific state in the EE_Capability class.
1502
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1503
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1504
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1505
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1506
-     *             switch or on the restore.
1507
-     * - $modules
1508
-     * - $shortcodes
1509
-     * - $widgets
1510
-     *
1511
-     * @param boolean $hard             [deprecated]
1512
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1513
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1514
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1515
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1516
-     *                                  client
1517
-     *                                  code instead can just change the model context to a different blog id if
1518
-     *                                  necessary
1519
-     * @return EE_Registry
1520
-     * @throws EE_Error
1521
-     * @throws ReflectionException
1522
-     */
1523
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1524
-    {
1525
-        $instance = self::instance();
1526
-        $instance->_cache_on = true;
1527
-        // reset some "special" classes
1528
-        EEH_Activation::reset();
1529
-        $hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1530
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1531
-        $instance->CART = null;
1532
-        $instance->MRM = null;
1533
-        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1534
-        //messages reset
1535
-        EED_Messages::reset();
1536
-        //handle of objects cached on LIB
1537
-        foreach (array('LIB', 'modules') as $cache) {
1538
-            foreach ($instance->{$cache} as $class_name => $class) {
1539
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1540
-                    unset($instance->{$cache}->{$class_name});
1541
-                }
1542
-            }
1543
-        }
1544
-        return $instance;
1545
-    }
1546
-
1547
-
1548
-
1549
-    /**
1550
-     * if passed object implements ResettableInterface, then call it's reset() method
1551
-     * if passed object implements InterminableInterface, then return false,
1552
-     * to indicate that it should NOT be cleared from the Registry cache
1553
-     *
1554
-     * @param      $object
1555
-     * @param bool $reset_models
1556
-     * @return bool returns true if cached object should be unset
1557
-     */
1558
-    private static function _reset_and_unset_object($object, $reset_models)
1559
-    {
1560
-        if (! is_object($object)) {
1561
-            // don't unset anything that's not an object
1562
-            return false;
1563
-        }
1564
-        if ($object instanceof EED_Module) {
1565
-            $object::reset();
1566
-            // don't unset modules
1567
-            return false;
1568
-        }
1569
-        if ($object instanceof ResettableInterface) {
1570
-            if ($object instanceof EEM_Base) {
1571
-                if ($reset_models) {
1572
-                    $object->reset();
1573
-                    return true;
1574
-                }
1575
-                return false;
1576
-            }
1577
-            $object->reset();
1578
-            return true;
1579
-        }
1580
-        if (! $object instanceof InterminableInterface) {
1581
-            return true;
1582
-        }
1583
-        return false;
1584
-    }
1585
-
1586
-
1587
-
1588
-    /**
1589
-     * Gets all the custom post type models defined
1590
-     *
1591
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1592
-     */
1593
-    public function cpt_models()
1594
-    {
1595
-        $cpt_models = array();
1596
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1597
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1598
-                $cpt_models[$short_name] = $classname;
1599
-            }
1600
-        }
1601
-        return $cpt_models;
1602
-    }
1603
-
1604
-
1605
-
1606
-    /**
1607
-     * @return \EE_Config
1608
-     */
1609
-    public static function CFG()
1610
-    {
1611
-        return self::instance()->CFG;
1612
-    }
26
+	/**
27
+	 * @var EE_Registry $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var EE_Dependency_Map $_dependency_map
33
+	 */
34
+	protected $_dependency_map;
35
+
36
+	/**
37
+	 * @var array $_class_abbreviations
38
+	 */
39
+	protected $_class_abbreviations = array();
40
+
41
+	/**
42
+	 * @var CommandBusInterface $BUS
43
+	 */
44
+	public $BUS;
45
+
46
+	/**
47
+	 * @var EE_Cart $CART
48
+	 */
49
+	public $CART;
50
+
51
+	/**
52
+	 * @var EE_Config $CFG
53
+	 */
54
+	public $CFG;
55
+
56
+	/**
57
+	 * @var EE_Network_Config $NET_CFG
58
+	 */
59
+	public $NET_CFG;
60
+
61
+	/**
62
+	 * StdClass object for storing library classes in
63
+	 *
64
+	 * @var StdClass $LIB
65
+	 */
66
+	public $LIB;
67
+
68
+	/**
69
+	 * @var EE_Request_Handler $REQ
70
+	 */
71
+	public $REQ;
72
+
73
+	/**
74
+	 * @var EE_Session $SSN
75
+	 */
76
+	public $SSN;
77
+
78
+	/**
79
+	 * @since 4.5.0
80
+	 * @var EE_Capabilities $CAP
81
+	 */
82
+	public $CAP;
83
+
84
+	/**
85
+	 * @since 4.9.0
86
+	 * @var EE_Message_Resource_Manager $MRM
87
+	 */
88
+	public $MRM;
89
+
90
+
91
+	/**
92
+	 * @var Registry $AssetsRegistry
93
+	 */
94
+	public $AssetsRegistry;
95
+
96
+	/**
97
+	 * StdClass object for holding addons which have registered themselves to work with EE core
98
+	 *
99
+	 * @var EE_Addon[] $addons
100
+	 */
101
+	public $addons;
102
+
103
+	/**
104
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
105
+	 *
106
+	 * @var EEM_Base[] $models
107
+	 */
108
+	public $models = array();
109
+
110
+	/**
111
+	 * @var EED_Module[] $modules
112
+	 */
113
+	public $modules;
114
+
115
+	/**
116
+	 * @var EES_Shortcode[] $shortcodes
117
+	 */
118
+	public $shortcodes;
119
+
120
+	/**
121
+	 * @var WP_Widget[] $widgets
122
+	 */
123
+	public $widgets;
124
+
125
+	/**
126
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
127
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
128
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
129
+	 * classnames (eg "EEM_Event")
130
+	 *
131
+	 * @var array $non_abstract_db_models
132
+	 */
133
+	public $non_abstract_db_models = array();
134
+
135
+
136
+	/**
137
+	 * internationalization for JS strings
138
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
139
+	 *    in js file:  var translatedString = eei18n.string_key;
140
+	 *
141
+	 * @var array $i18n_js_strings
142
+	 */
143
+	public static $i18n_js_strings = array();
144
+
145
+
146
+	/**
147
+	 * $main_file - path to espresso.php
148
+	 *
149
+	 * @var array $main_file
150
+	 */
151
+	public $main_file;
152
+
153
+	/**
154
+	 * array of ReflectionClass objects where the key is the class name
155
+	 *
156
+	 * @var ReflectionClass[] $_reflectors
157
+	 */
158
+	public $_reflectors;
159
+
160
+	/**
161
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
162
+	 *
163
+	 * @var boolean $_cache_on
164
+	 */
165
+	protected $_cache_on = true;
166
+
167
+
168
+
169
+	/**
170
+	 * @singleton method used to instantiate class object
171
+	 * @param  EE_Dependency_Map $dependency_map
172
+	 * @return EE_Registry instance
173
+	 * @throws InvalidArgumentException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws InvalidDataTypeException
176
+	 */
177
+	public static function instance(EE_Dependency_Map $dependency_map = null)
178
+	{
179
+		// check if class object is instantiated
180
+		if (! self::$_instance instanceof EE_Registry) {
181
+			self::$_instance = new self($dependency_map);
182
+		}
183
+		return self::$_instance;
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * protected constructor to prevent direct creation
190
+	 *
191
+	 * @Constructor
192
+	 * @param  EE_Dependency_Map $dependency_map
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 * @throws InvalidArgumentException
196
+	 */
197
+	protected function __construct(EE_Dependency_Map $dependency_map)
198
+	{
199
+		$this->_dependency_map = $dependency_map;
200
+		// $registry_container = new RegistryContainer();
201
+		$this->LIB = new RegistryContainer();
202
+		$this->addons = new RegistryContainer();
203
+		$this->modules = new RegistryContainer();
204
+		$this->shortcodes = new RegistryContainer();
205
+		$this->widgets = new RegistryContainer();
206
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
207
+	}
208
+
209
+
210
+
211
+	/**
212
+	 * initialize
213
+	 *
214
+	 * @throws EE_Error
215
+	 * @throws ReflectionException
216
+	 */
217
+	public function initialize()
218
+	{
219
+		$this->_class_abbreviations = apply_filters(
220
+			'FHEE__EE_Registry____construct___class_abbreviations',
221
+			array(
222
+				'EE_Config'                                       => 'CFG',
223
+				'EE_Session'                                      => 'SSN',
224
+				'EE_Capabilities'                                 => 'CAP',
225
+				'EE_Cart'                                         => 'CART',
226
+				'EE_Network_Config'                               => 'NET_CFG',
227
+				'EE_Request_Handler'                              => 'REQ',
228
+				'EE_Message_Resource_Manager'                     => 'MRM',
229
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
230
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
231
+			)
232
+		);
233
+		$this->load_core('Base', array(), true);
234
+		// add our request and response objects to the cache
235
+		$request_loader = $this->_dependency_map->class_loader(
236
+			'EventEspresso\core\services\request\Request'
237
+		);
238
+		$this->_set_cached_class(
239
+			$request_loader(),
240
+			'EventEspresso\core\services\request\Request'
241
+		);
242
+		$response_loader = $this->_dependency_map->class_loader(
243
+			'EventEspresso\core\services\request\Response'
244
+		);
245
+		$this->_set_cached_class(
246
+			$response_loader(),
247
+			'EventEspresso\core\services\request\Response'
248
+		);
249
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 * @return void
256
+	 */
257
+	public function init()
258
+	{
259
+		// Get current page protocol
260
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
261
+		// Output admin-ajax.php URL with same protocol as current page
262
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
263
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
264
+	}
265
+
266
+
267
+
268
+	/**
269
+	 * localize_i18n_js_strings
270
+	 *
271
+	 * @return string
272
+	 */
273
+	public static function localize_i18n_js_strings()
274
+	{
275
+		$i18n_js_strings = (array)self::$i18n_js_strings;
276
+		foreach ($i18n_js_strings as $key => $value) {
277
+			if (is_scalar($value)) {
278
+				$i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
279
+			}
280
+		}
281
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @param mixed string | EED_Module $module
288
+	 * @throws EE_Error
289
+	 * @throws ReflectionException
290
+	 */
291
+	public function add_module($module)
292
+	{
293
+		if ($module instanceof EED_Module) {
294
+			$module_class = get_class($module);
295
+			$this->modules->{$module_class} = $module;
296
+		} else {
297
+			if ( ! class_exists('EE_Module_Request_Router', false)) {
298
+				$this->load_core('Module_Request_Router');
299
+			}
300
+			EE_Module_Request_Router::module_factory($module);
301
+		}
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @param string $module_name
308
+	 * @return mixed EED_Module | NULL
309
+	 */
310
+	public function get_module($module_name = '')
311
+	{
312
+		return isset($this->modules->{$module_name})
313
+			? $this->modules->{$module_name}
314
+			: null;
315
+	}
316
+
317
+
318
+
319
+	/**
320
+	 * loads core classes - must be singletons
321
+	 *
322
+	 * @param string $class_name - simple class name ie: session
323
+	 * @param mixed  $arguments
324
+	 * @param bool   $load_only
325
+	 * @return mixed
326
+	 * @throws EE_Error
327
+	 * @throws ReflectionException
328
+	 */
329
+	public function load_core($class_name, $arguments = array(), $load_only = false)
330
+	{
331
+		$core_paths = apply_filters(
332
+			'FHEE__EE_Registry__load_core__core_paths',
333
+			array(
334
+				EE_CORE,
335
+				EE_ADMIN,
336
+				EE_CPTS,
337
+				EE_CORE . 'data_migration_scripts' . DS,
338
+				EE_CORE . 'capabilities' . DS,
339
+				EE_CORE . 'request_stack' . DS,
340
+				EE_CORE . 'middleware' . DS,
341
+			)
342
+		);
343
+		// retrieve instantiated class
344
+		return $this->_load(
345
+			$core_paths,
346
+			'EE_',
347
+			$class_name,
348
+			'core',
349
+			$arguments,
350
+			false,
351
+			true,
352
+			$load_only
353
+		);
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * loads service classes
360
+	 *
361
+	 * @param string $class_name - simple class name ie: session
362
+	 * @param mixed  $arguments
363
+	 * @param bool   $load_only
364
+	 * @return mixed
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	public function load_service($class_name, $arguments = array(), $load_only = false)
369
+	{
370
+		$service_paths = apply_filters(
371
+			'FHEE__EE_Registry__load_service__service_paths',
372
+			array(
373
+				EE_CORE . 'services' . DS,
374
+			)
375
+		);
376
+		// retrieve instantiated class
377
+		return $this->_load(
378
+			$service_paths,
379
+			'EE_',
380
+			$class_name,
381
+			'class',
382
+			$arguments,
383
+			false,
384
+			true,
385
+			$load_only
386
+		);
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * loads data_migration_scripts
393
+	 *
394
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
395
+	 * @param mixed  $arguments
396
+	 * @return EE_Data_Migration_Script_Base|mixed
397
+	 * @throws EE_Error
398
+	 * @throws ReflectionException
399
+	 */
400
+	public function load_dms($class_name, $arguments = array())
401
+	{
402
+		// retrieve instantiated class
403
+		return $this->_load(
404
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
405
+			'EE_DMS_',
406
+			$class_name,
407
+			'dms',
408
+			$arguments,
409
+			false,
410
+			false
411
+		);
412
+	}
413
+
414
+
415
+
416
+	/**
417
+	 * loads object creating classes - must be singletons
418
+	 *
419
+	 * @param string $class_name - simple class name ie: attendee
420
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
421
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
422
+	 *                           instantiate
423
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
424
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
425
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
426
+	 *                           (default)
427
+	 * @return EE_Base_Class | bool
428
+	 * @throws EE_Error
429
+	 * @throws ReflectionException
430
+	 */
431
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
432
+	{
433
+		$paths = apply_filters(
434
+			'FHEE__EE_Registry__load_class__paths', array(
435
+			EE_CORE,
436
+			EE_CLASSES,
437
+			EE_BUSINESS,
438
+		)
439
+		);
440
+		// retrieve instantiated class
441
+		return $this->_load(
442
+			$paths,
443
+			'EE_',
444
+			$class_name,
445
+			'class',
446
+			$arguments,
447
+			$from_db,
448
+			$cache,
449
+			$load_only
450
+		);
451
+	}
452
+
453
+
454
+
455
+	/**
456
+	 * loads helper classes - must be singletons
457
+	 *
458
+	 * @param string $class_name - simple class name ie: price
459
+	 * @param mixed  $arguments
460
+	 * @param bool   $load_only
461
+	 * @return EEH_Base | bool
462
+	 * @throws EE_Error
463
+	 * @throws ReflectionException
464
+	 */
465
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
466
+	{
467
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
468
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
469
+		// retrieve instantiated class
470
+		return $this->_load(
471
+			$helper_paths,
472
+			'EEH_',
473
+			$class_name,
474
+			'helper',
475
+			$arguments,
476
+			false,
477
+			true,
478
+			$load_only
479
+		);
480
+	}
481
+
482
+
483
+
484
+	/**
485
+	 * loads core classes - must be singletons
486
+	 *
487
+	 * @param string $class_name - simple class name ie: session
488
+	 * @param mixed  $arguments
489
+	 * @param bool   $load_only
490
+	 * @param bool   $cache      whether to cache the object or not.
491
+	 * @return mixed
492
+	 * @throws EE_Error
493
+	 * @throws ReflectionException
494
+	 */
495
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
496
+	{
497
+		$paths = array(
498
+			EE_LIBRARIES,
499
+			EE_LIBRARIES . 'messages' . DS,
500
+			EE_LIBRARIES . 'shortcodes' . DS,
501
+			EE_LIBRARIES . 'qtips' . DS,
502
+			EE_LIBRARIES . 'payment_methods' . DS,
503
+		);
504
+		// retrieve instantiated class
505
+		return $this->_load(
506
+			$paths,
507
+			'EE_',
508
+			$class_name,
509
+			'lib',
510
+			$arguments,
511
+			false,
512
+			$cache,
513
+			$load_only
514
+		);
515
+	}
516
+
517
+
518
+
519
+	/**
520
+	 * loads model classes - must be singletons
521
+	 *
522
+	 * @param string $class_name - simple class name ie: price
523
+	 * @param mixed  $arguments
524
+	 * @param bool   $load_only
525
+	 * @return EEM_Base | bool
526
+	 * @throws EE_Error
527
+	 * @throws ReflectionException
528
+	 */
529
+	public function load_model($class_name, $arguments = array(), $load_only = false)
530
+	{
531
+		$paths = apply_filters(
532
+			'FHEE__EE_Registry__load_model__paths', array(
533
+			EE_MODELS,
534
+			EE_CORE,
535
+		)
536
+		);
537
+		// retrieve instantiated class
538
+		return $this->_load(
539
+			$paths,
540
+			'EEM_',
541
+			$class_name,
542
+			'model',
543
+			$arguments,
544
+			false,
545
+			true,
546
+			$load_only
547
+		);
548
+	}
549
+
550
+
551
+
552
+	/**
553
+	 * loads model classes - must be singletons
554
+	 *
555
+	 * @param string $class_name - simple class name ie: price
556
+	 * @param mixed  $arguments
557
+	 * @param bool   $load_only
558
+	 * @return mixed | bool
559
+	 * @throws EE_Error
560
+	 * @throws ReflectionException
561
+	 */
562
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
563
+	{
564
+		$paths = array(
565
+			EE_MODELS . 'fields' . DS,
566
+			EE_MODELS . 'helpers' . DS,
567
+			EE_MODELS . 'relations' . DS,
568
+			EE_MODELS . 'strategies' . DS,
569
+		);
570
+		// retrieve instantiated class
571
+		return $this->_load(
572
+			$paths,
573
+			'EE_',
574
+			$class_name,
575
+			'',
576
+			$arguments,
577
+			false,
578
+			true,
579
+			$load_only
580
+		);
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 * Determines if $model_name is the name of an actual EE model.
587
+	 *
588
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
589
+	 * @return boolean
590
+	 */
591
+	public function is_model_name($model_name)
592
+	{
593
+		return isset($this->models[$model_name]);
594
+	}
595
+
596
+
597
+
598
+	/**
599
+	 * generic class loader
600
+	 *
601
+	 * @param string $path_to_file - directory path to file location, not including filename
602
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
603
+	 * @param string $type         - file type - core? class? helper? model?
604
+	 * @param mixed  $arguments
605
+	 * @param bool   $load_only
606
+	 * @return mixed
607
+	 * @throws EE_Error
608
+	 * @throws ReflectionException
609
+	 */
610
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
611
+	{
612
+		// retrieve instantiated class
613
+		return $this->_load(
614
+			$path_to_file,
615
+			'',
616
+			$file_name,
617
+			$type,
618
+			$arguments,
619
+			false,
620
+			true,
621
+			$load_only
622
+		);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @param string $path_to_file - directory path to file location, not including filename
629
+	 * @param string $class_name   - full class name  ie:  My_Class
630
+	 * @param string $type         - file type - core? class? helper? model?
631
+	 * @param mixed  $arguments
632
+	 * @param bool   $load_only
633
+	 * @return bool|EE_Addon|object
634
+	 * @throws EE_Error
635
+	 * @throws ReflectionException
636
+	 */
637
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
638
+	{
639
+		// retrieve instantiated class
640
+		return $this->_load(
641
+			$path_to_file,
642
+			'addon',
643
+			$class_name,
644
+			$type,
645
+			$arguments,
646
+			false,
647
+			true,
648
+			$load_only
649
+		);
650
+	}
651
+
652
+
653
+
654
+	/**
655
+	 * instantiates, caches, and automatically resolves dependencies
656
+	 * for classes that use a Fully Qualified Class Name.
657
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
658
+	 * then you need to use one of the existing load_*() methods
659
+	 * which can resolve the classname and filepath from the passed arguments
660
+	 *
661
+	 * @param bool|string $class_name   Fully Qualified Class Name
662
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
663
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
664
+	 * @param bool        $from_db      some classes are instantiated from the db
665
+	 *                                  and thus call a different method to instantiate
666
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
667
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
668
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
669
+	 *                                  object = class loaded and instantiated successfully.
670
+	 *                                  bool = fail or success when $load_only is true
671
+	 * @throws EE_Error
672
+	 * @throws ReflectionException
673
+	 */
674
+	public function create(
675
+		$class_name = false,
676
+		$arguments = array(),
677
+		$cache = false,
678
+		$from_db = false,
679
+		$load_only = false,
680
+		$addon = false
681
+	) {
682
+		$class_name = ltrim($class_name, '\\');
683
+		$class_name = $this->_dependency_map->get_alias($class_name);
684
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
685
+		// if a non-FQCN was passed, then verifyClassExists() might return an object
686
+		// or it could return null if the class just could not be found anywhere
687
+		if ($class_exists instanceof $class_name || $class_exists === null){
688
+			// either way, return the results
689
+			return $class_exists;
690
+		}
691
+		$class_name = $class_exists;
692
+		// if we're only loading the class and it already exists, then let's just return true immediately
693
+		if ($load_only) {
694
+			return true;
695
+		}
696
+		$addon = $addon
697
+			? 'addon'
698
+			: '';
699
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
700
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
701
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
702
+		if ($this->_cache_on && $cache && ! $load_only) {
703
+			// return object if it's already cached
704
+			$cached_class = $this->_get_cached_class($class_name, $addon);
705
+			if ($cached_class !== null) {
706
+				return $cached_class;
707
+			}
708
+		}
709
+		// obtain the loader method from the dependency map
710
+		$loader = $this->_dependency_map->class_loader($class_name);
711
+		// instantiate the requested object
712
+		if ($loader instanceof Closure) {
713
+			$class_obj = $loader($arguments);
714
+		} else if ($loader && method_exists($this, $loader)) {
715
+			$class_obj = $this->{$loader}($class_name, $arguments);
716
+		} else {
717
+			$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
718
+		}
719
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
720
+			// save it for later... kinda like gum  { : $
721
+			$this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
722
+		}
723
+		$this->_cache_on = true;
724
+		return $class_obj;
725
+	}
726
+
727
+
728
+
729
+	/**
730
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
731
+	 *
732
+	 * @param string $class_name
733
+	 * @param array  $arguments
734
+	 * @param int    $attempt
735
+	 * @return mixed
736
+	 */
737
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1) {
738
+		if (is_object($class_name) || class_exists($class_name)) {
739
+			return $class_name;
740
+		}
741
+		switch ($attempt) {
742
+			case 1:
743
+				// if it's a FQCN then maybe the class is registered with a preceding \
744
+				$class_name = strpos($class_name, '\\') !== false
745
+					? '\\' . ltrim($class_name, '\\')
746
+					: $class_name;
747
+				break;
748
+			case 2:
749
+				//
750
+				$loader = $this->_dependency_map->class_loader($class_name);
751
+				if ($loader && method_exists($this, $loader)) {
752
+					return $this->{$loader}($class_name, $arguments);
753
+				}
754
+				break;
755
+			case 3:
756
+			default;
757
+				return null;
758
+		}
759
+		$attempt++;
760
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
761
+	}
762
+
763
+
764
+
765
+	/**
766
+	 * instantiates, caches, and injects dependencies for classes
767
+	 *
768
+	 * @param array       $file_paths   an array of paths to folders to look in
769
+	 * @param string      $class_prefix EE  or EEM or... ???
770
+	 * @param bool|string $class_name   $class name
771
+	 * @param string      $type         file type - core? class? helper? model?
772
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
773
+	 * @param bool        $from_db      some classes are instantiated from the db
774
+	 *                                  and thus call a different method to instantiate
775
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
776
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
777
+	 * @return bool|null|object null = failure to load or instantiate class object.
778
+	 *                                  object = class loaded and instantiated successfully.
779
+	 *                                  bool = fail or success when $load_only is true
780
+	 * @throws EE_Error
781
+	 * @throws ReflectionException
782
+	 */
783
+	protected function _load(
784
+		$file_paths = array(),
785
+		$class_prefix = 'EE_',
786
+		$class_name = false,
787
+		$type = 'class',
788
+		$arguments = array(),
789
+		$from_db = false,
790
+		$cache = true,
791
+		$load_only = false
792
+	) {
793
+		$class_name = ltrim($class_name, '\\');
794
+		// strip php file extension
795
+		$class_name = str_replace('.php', '', trim($class_name));
796
+		// does the class have a prefix ?
797
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
798
+			// make sure $class_prefix is uppercase
799
+			$class_prefix = strtoupper(trim($class_prefix));
800
+			// add class prefix ONCE!!!
801
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
802
+		}
803
+		$class_name = $this->_dependency_map->get_alias($class_name);
804
+		$class_exists = class_exists($class_name, false);
805
+		// if we're only loading the class and it already exists, then let's just return true immediately
806
+		if ($load_only && $class_exists) {
807
+			return true;
808
+		}
809
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
810
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
811
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
812
+		if ($this->_cache_on && $cache && ! $load_only) {
813
+			// return object if it's already cached
814
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix);
815
+			if ($cached_class !== null) {
816
+				return $cached_class;
817
+			}
818
+		}
819
+		// if the class doesn't already exist.. then we need to try and find the file and load it
820
+		if (! $class_exists) {
821
+			// get full path to file
822
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
823
+			// load the file
824
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
825
+			// if loading failed, or we are only loading a file but NOT instantiating an object
826
+			if (! $loaded || $load_only) {
827
+				// return boolean if only loading, or null if an object was expected
828
+				return $load_only
829
+					? $loaded
830
+					: null;
831
+			}
832
+		}
833
+		// instantiate the requested object
834
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
835
+		if ($this->_cache_on && $cache) {
836
+			// save it for later... kinda like gum  { : $
837
+			$this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
838
+		}
839
+		$this->_cache_on = true;
840
+		return $class_obj;
841
+	}
842
+
843
+
844
+
845
+	/**
846
+	 * @param string $class_name
847
+	 * @param string $default have to specify something, but not anything that will conflict
848
+	 * @return mixed|string
849
+	 */
850
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
851
+	{
852
+		return isset($this->_class_abbreviations[$class_name])
853
+			? $this->_class_abbreviations[$class_name]
854
+			: $default;
855
+	}
856
+
857
+	/**
858
+	 * attempts to find a cached version of the requested class
859
+	 * by looking in the following places:
860
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
861
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
862
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
863
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
864
+	 *
865
+	 * @param string $class_name
866
+	 * @param string $class_prefix
867
+	 * @return mixed
868
+	 * @throws OutOfBoundsException
869
+	 */
870
+	protected function _get_cached_class($class_name, $class_prefix = '')
871
+	{
872
+		if ($class_name === 'EE_Registry') {
873
+			return $this;
874
+		}
875
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
876
+		$class_name = str_replace('\\', '_', $class_name);
877
+		// check if class has already been loaded, and return it if it has been
878
+		if (isset($this->{$class_abbreviation})) {
879
+			return $this->{$class_abbreviation};
880
+		}
881
+		if (isset ($this->{$class_name})) {
882
+			return $this->{$class_name};
883
+		}
884
+		if (isset ($this->LIB->{$class_name})) {
885
+			return $this->LIB->{$class_name};
886
+		}
887
+		if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
888
+			return $this->addons->{$class_name};
889
+		}
890
+		return null;
891
+	}
892
+
893
+
894
+
895
+	/**
896
+	 * removes a cached version of the requested class
897
+	 *
898
+	 * @param string  $class_name
899
+	 * @param boolean $addon
900
+	 * @return boolean
901
+	 * @throws OutOfBoundsException
902
+	 */
903
+	public function clear_cached_class($class_name, $addon = false)
904
+	{
905
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
906
+		$class_name = str_replace('\\', '_', $class_name);
907
+		// check if class has already been loaded, and return it if it has been
908
+		if (isset($this->{$class_abbreviation})) {
909
+			$this->{$class_abbreviation} = null;
910
+			return true;
911
+		}
912
+		if (isset($this->{$class_name})) {
913
+			$this->{$class_name} = null;
914
+			return true;
915
+		}
916
+		if (isset($this->LIB->{$class_name})) {
917
+			unset($this->LIB->{$class_name});
918
+			return true;
919
+		}
920
+		if ($addon && isset($this->addons->{$class_name})) {
921
+			unset($this->addons->{$class_name});
922
+			return true;
923
+		}
924
+		return false;
925
+	}
926
+
927
+
928
+
929
+	/**
930
+	 * attempts to find a full valid filepath for the requested class.
931
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
932
+	 * then returns that path if the target file has been found and is readable
933
+	 *
934
+	 * @param string $class_name
935
+	 * @param string $type
936
+	 * @param array  $file_paths
937
+	 * @return string | bool
938
+	 */
939
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
940
+	{
941
+		// make sure $file_paths is an array
942
+		$file_paths = is_array($file_paths)
943
+			? $file_paths
944
+			: array($file_paths);
945
+		// cycle thru paths
946
+		foreach ($file_paths as $key => $file_path) {
947
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
948
+			$file_path = $file_path
949
+				? str_replace(array('/', '\\'), DS, $file_path)
950
+				: EE_CLASSES;
951
+			// prep file type
952
+			$type = ! empty($type)
953
+				? trim($type, '.') . '.'
954
+				: '';
955
+			// build full file path
956
+			$file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
957
+			//does the file exist and can be read ?
958
+			if (is_readable($file_paths[$key])) {
959
+				return $file_paths[$key];
960
+			}
961
+		}
962
+		return false;
963
+	}
964
+
965
+
966
+
967
+	/**
968
+	 * basically just performs a require_once()
969
+	 * but with some error handling
970
+	 *
971
+	 * @param  string $path
972
+	 * @param  string $class_name
973
+	 * @param  string $type
974
+	 * @param  array  $file_paths
975
+	 * @return bool
976
+	 * @throws EE_Error
977
+	 * @throws ReflectionException
978
+	 */
979
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
980
+	{
981
+		$this->resolve_legacy_class_parent($class_name);
982
+		// don't give up! you gotta...
983
+		try {
984
+			//does the file exist and can it be read ?
985
+			if (! $path) {
986
+				// just in case the file has already been autoloaded,
987
+				// but discrepancies in the naming schema are preventing it from
988
+				// being loaded via one of the EE_Registry::load_*() methods,
989
+				// then let's try one last hail mary before throwing an exception
990
+				// and call class_exists() again, but with autoloading turned ON
991
+				if(class_exists($class_name)) {
992
+					return true;
993
+				}
994
+				// so sorry, can't find the file
995
+				throw new EE_Error (
996
+					sprintf(
997
+						esc_html__(
998
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
999
+							'event_espresso'
1000
+						),
1001
+						trim($type, '.'),
1002
+						$class_name,
1003
+						'<br />' . implode(',<br />', $file_paths)
1004
+					)
1005
+				);
1006
+			}
1007
+			// get the file
1008
+			require_once($path);
1009
+			// if the class isn't already declared somewhere
1010
+			if (class_exists($class_name, false) === false) {
1011
+				// so sorry, not a class
1012
+				throw new EE_Error(
1013
+					sprintf(
1014
+						esc_html__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
1015
+						$type,
1016
+						$path,
1017
+						$class_name
1018
+					)
1019
+				);
1020
+			}
1021
+		} catch (EE_Error $e) {
1022
+			$e->get_error();
1023
+			return false;
1024
+		}
1025
+		return true;
1026
+	}
1027
+
1028
+
1029
+
1030
+	/**
1031
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1032
+	 * before their class declaration in order to ensure that the parent class was loaded.
1033
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1034
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1035
+	 *
1036
+	 * @param string $class_name
1037
+	 */
1038
+	protected function resolve_legacy_class_parent($class_name = '')
1039
+	{
1040
+		try {
1041
+			$legacy_parent_class_map = array(
1042
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php'
1043
+			);
1044
+			if(isset($legacy_parent_class_map[$class_name])) {
1045
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[$class_name];
1046
+			}
1047
+		} catch (Exception $exception) {
1048
+		}
1049
+	}
1050
+
1051
+
1052
+
1053
+	/**
1054
+	 * _create_object
1055
+	 * Attempts to instantiate the requested class via any of the
1056
+	 * commonly used instantiation methods employed throughout EE.
1057
+	 * The priority for instantiation is as follows:
1058
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1059
+	 *        - model objects via their 'new_instance_from_db' method
1060
+	 *        - model objects via their 'new_instance' method
1061
+	 *        - "singleton" classes" via their 'instance' method
1062
+	 *    - standard instantiable classes via their __constructor
1063
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1064
+	 * then the constructor for the requested class will be examined to determine
1065
+	 * if any dependencies exist, and if they can be injected.
1066
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1067
+	 *
1068
+	 * @param string $class_name
1069
+	 * @param array  $arguments
1070
+	 * @param string $type
1071
+	 * @param bool   $from_db
1072
+	 * @return null|object
1073
+	 * @throws EE_Error
1074
+	 * @throws ReflectionException
1075
+	 */
1076
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1077
+	{
1078
+		// create reflection
1079
+		$reflector = $this->get_ReflectionClass($class_name);
1080
+		// make sure arguments are an array
1081
+		$arguments = is_array($arguments)
1082
+			? $arguments
1083
+			: array($arguments);
1084
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1085
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1086
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1087
+			? $arguments
1088
+			: array($arguments);
1089
+		// attempt to inject dependencies ?
1090
+		if ($this->_dependency_map->has($class_name)) {
1091
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1092
+		}
1093
+		// instantiate the class if possible
1094
+		if ($reflector->isAbstract()) {
1095
+			// nothing to instantiate, loading file was enough
1096
+			// does not throw an exception so $instantiation_mode is unused
1097
+			// $instantiation_mode = "1) no constructor abstract class";
1098
+			return true;
1099
+		}
1100
+		if (empty($arguments) && $reflector->getConstructor() === null && $reflector->isInstantiable()) {
1101
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1102
+			// $instantiation_mode = "2) no constructor but instantiable";
1103
+			return $reflector->newInstance();
1104
+		}
1105
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1106
+			// $instantiation_mode = "3) new_instance_from_db()";
1107
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1108
+		}
1109
+		if (method_exists($class_name, 'new_instance')) {
1110
+			// $instantiation_mode = "4) new_instance()";
1111
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1112
+		}
1113
+		if (method_exists($class_name, 'instance')) {
1114
+			// $instantiation_mode = "5) instance()";
1115
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1116
+		}
1117
+		if ($reflector->isInstantiable()) {
1118
+			// $instantiation_mode = "6) constructor";
1119
+			return $reflector->newInstanceArgs($arguments);
1120
+		}
1121
+		// heh ? something's not right !
1122
+		throw new EE_Error(
1123
+			sprintf(
1124
+				__('The %s file %s could not be instantiated.', 'event_espresso'),
1125
+				$type,
1126
+				$class_name
1127
+			)
1128
+		);
1129
+	}
1130
+
1131
+
1132
+
1133
+	/**
1134
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1135
+	 * @param array $array
1136
+	 * @return bool
1137
+	 */
1138
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1139
+	{
1140
+		return ! empty($array)
1141
+			? array_keys($array) === range(0, count($array) - 1)
1142
+			: true;
1143
+	}
1144
+
1145
+
1146
+
1147
+	/**
1148
+	 * getReflectionClass
1149
+	 * checks if a ReflectionClass object has already been generated for a class
1150
+	 * and returns that instead of creating a new one
1151
+	 *
1152
+	 * @param string $class_name
1153
+	 * @return ReflectionClass
1154
+	 * @throws ReflectionException
1155
+	 */
1156
+	public function get_ReflectionClass($class_name)
1157
+	{
1158
+		if (
1159
+			! isset($this->_reflectors[$class_name])
1160
+			|| ! $this->_reflectors[$class_name] instanceof ReflectionClass
1161
+		) {
1162
+			$this->_reflectors[$class_name] = new ReflectionClass($class_name);
1163
+		}
1164
+		return $this->_reflectors[$class_name];
1165
+	}
1166
+
1167
+
1168
+
1169
+	/**
1170
+	 * _resolve_dependencies
1171
+	 * examines the constructor for the requested class to determine
1172
+	 * if any dependencies exist, and if they can be injected.
1173
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1174
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1175
+	 * For example:
1176
+	 *        if attempting to load a class "Foo" with the following constructor:
1177
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1178
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1179
+	 *        but only IF they are NOT already present in the incoming arguments array,
1180
+	 *        and the correct classes can be loaded
1181
+	 *
1182
+	 * @param ReflectionClass $reflector
1183
+	 * @param string          $class_name
1184
+	 * @param array           $arguments
1185
+	 * @return array
1186
+	 * @throws EE_Error
1187
+	 * @throws ReflectionException
1188
+	 */
1189
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1190
+	{
1191
+		// let's examine the constructor
1192
+		$constructor = $reflector->getConstructor();
1193
+		// whu? huh? nothing?
1194
+		if (! $constructor) {
1195
+			return $arguments;
1196
+		}
1197
+		// get constructor parameters
1198
+		$params = $constructor->getParameters();
1199
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1200
+		$argument_keys = array_keys($arguments);
1201
+		// now loop thru all of the constructors expected parameters
1202
+		foreach ($params as $index => $param) {
1203
+			// is this a dependency for a specific class ?
1204
+			$param_class = $param->getClass()
1205
+				? $param->getClass()->name
1206
+				: null;
1207
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1208
+			$param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1209
+				? $this->_dependency_map->get_alias($param_class, $class_name)
1210
+				: $param_class;
1211
+			if (
1212
+				// param is not even a class
1213
+				$param_class === null
1214
+				// and something already exists in the incoming arguments for this param
1215
+				&& array_key_exists($index, $argument_keys)
1216
+				&& array_key_exists($argument_keys[$index], $arguments)
1217
+			) {
1218
+				// so let's skip this argument and move on to the next
1219
+				continue;
1220
+			}
1221
+			if (
1222
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1223
+				$param_class !== null
1224
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1225
+				&& $arguments[$argument_keys[$index]] instanceof $param_class
1226
+			) {
1227
+				// skip this argument and move on to the next
1228
+				continue;
1229
+			}
1230
+			if (
1231
+				// parameter is type hinted as a class, and should be injected
1232
+				$param_class !== null
1233
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1234
+			) {
1235
+				$arguments = $this->_resolve_dependency(
1236
+					$class_name,
1237
+					$param_class,
1238
+					$arguments,
1239
+					$index,
1240
+					$argument_keys
1241
+				);
1242
+			} else {
1243
+				try {
1244
+					$arguments[$index] = $param->isDefaultValueAvailable()
1245
+						? $param->getDefaultValue()
1246
+						: null;
1247
+				} catch (ReflectionException $e) {
1248
+					throw new ReflectionException(
1249
+						sprintf(
1250
+							esc_html__('%1$s for parameter "$%2$s on classname "%3$s"', 'event_espresso'),
1251
+							$e->getMessage(),
1252
+							$param->getName(),
1253
+							$class_name
1254
+						)
1255
+					);
1256
+				}
1257
+			}
1258
+		}
1259
+		return $arguments;
1260
+	}
1261
+
1262
+
1263
+
1264
+	/**
1265
+	 * @param string $class_name
1266
+	 * @param string $param_class
1267
+	 * @param array  $arguments
1268
+	 * @param mixed  $index
1269
+	 * @param array  $argument_keys
1270
+	 * @return array
1271
+	 * @throws EE_Error
1272
+	 * @throws ReflectionException
1273
+	 * @throws InvalidArgumentException
1274
+	 * @throws InvalidInterfaceException
1275
+	 * @throws InvalidDataTypeException
1276
+	 */
1277
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index, array $argument_keys)
1278
+	{
1279
+		$dependency = null;
1280
+		// should dependency be loaded from cache ?
1281
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1282
+			$class_name,
1283
+			$param_class
1284
+		);
1285
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1286
+		// we might have a dependency...
1287
+		// let's MAYBE try and find it in our cache if that's what's been requested
1288
+		$cached_class = $cache_on
1289
+			? $this->_get_cached_class($param_class)
1290
+			: null;
1291
+		// and grab it if it exists
1292
+		if ($cached_class instanceof $param_class) {
1293
+			$dependency = $cached_class;
1294
+		} else if ($param_class !== $class_name) {
1295
+			// obtain the loader method from the dependency map
1296
+			$loader = $this->_dependency_map->class_loader($param_class);
1297
+			// is loader a custom closure ?
1298
+			if ($loader instanceof Closure) {
1299
+				$dependency = $loader($arguments);
1300
+			} else {
1301
+				// set the cache on property for the recursive loading call
1302
+				$this->_cache_on = $cache_on;
1303
+				// if not, then let's try and load it via the registry
1304
+				if ($loader && method_exists($this, $loader)) {
1305
+					$dependency = $this->{$loader}($param_class);
1306
+				} else {
1307
+					$dependency = LoaderFactory::getLoader()->load(
1308
+						$param_class,
1309
+						array(),
1310
+						$cache_on
1311
+					);
1312
+				}
1313
+			}
1314
+		}
1315
+		// did we successfully find the correct dependency ?
1316
+		if ($dependency instanceof $param_class) {
1317
+			// then let's inject it into the incoming array of arguments at the correct location
1318
+			$arguments[$index] = $dependency;
1319
+		}
1320
+		return $arguments;
1321
+	}
1322
+
1323
+
1324
+
1325
+	/**
1326
+	 * _set_cached_class
1327
+	 * attempts to cache the instantiated class locally
1328
+	 * in one of the following places, in the following order:
1329
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1330
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1331
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1332
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1333
+	 *
1334
+	 * @param object $class_obj
1335
+	 * @param string $class_name
1336
+	 * @param string $class_prefix
1337
+	 * @param bool   $from_db
1338
+	 * @return void
1339
+	 * @throws OutOfBoundsException
1340
+	 */
1341
+	protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1342
+	{
1343
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1344
+			return;
1345
+		}
1346
+		// return newly instantiated class
1347
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1348
+		if ($class_abbreviation) {
1349
+			$this->{$class_abbreviation} = $class_obj;
1350
+			return;
1351
+		}
1352
+		$class_name = str_replace('\\', '_', $class_name);
1353
+		if (property_exists($this, $class_name)) {
1354
+			$this->{$class_name} = $class_obj;
1355
+			return;
1356
+		}
1357
+		if ($class_prefix === 'addon') {
1358
+			$this->addons->{$class_name} = $class_obj;
1359
+			return;
1360
+		}
1361
+		if (! $from_db) {
1362
+			$this->LIB->{$class_name} = $class_obj;
1363
+		}
1364
+	}
1365
+
1366
+
1367
+
1368
+	/**
1369
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1370
+	 *
1371
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1372
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1373
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1374
+	 * @param array  $arguments
1375
+	 * @return object
1376
+	 */
1377
+	public static function factory($classname, $arguments = array())
1378
+	{
1379
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1380
+		if ($loader instanceof Closure) {
1381
+			return $loader($arguments);
1382
+		}
1383
+		if (method_exists(self::instance(), $loader)) {
1384
+			return self::instance()->{$loader}($classname, $arguments);
1385
+		}
1386
+		return null;
1387
+	}
1388
+
1389
+
1390
+
1391
+	/**
1392
+	 * Gets the addon by its class name
1393
+	 *
1394
+	 * @param string $class_name
1395
+	 * @return EE_Addon
1396
+	 * @throws OutOfBoundsException
1397
+	 */
1398
+	public function getAddon($class_name)
1399
+	{
1400
+		$class_name = str_replace('\\', '_', $class_name);
1401
+		return $this->addons->{$class_name};
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * removes the addon from the internal cache
1407
+	 *
1408
+	 * @param string $class_name
1409
+	 * @return void
1410
+	 */
1411
+	public function removeAddon($class_name)
1412
+	{
1413
+		$class_name = str_replace('\\', '_', $class_name);
1414
+		unset($this->addons->{$class_name});
1415
+	}
1416
+
1417
+
1418
+
1419
+	/**
1420
+	 * Gets the addon by its name/slug (not classname. For that, just
1421
+	 * use the get_addon() method above
1422
+	 *
1423
+	 * @param string $name
1424
+	 * @return EE_Addon
1425
+	 */
1426
+	public function get_addon_by_name($name)
1427
+	{
1428
+		foreach ($this->addons as $addon) {
1429
+			if ($addon->name() === $name) {
1430
+				return $addon;
1431
+			}
1432
+		}
1433
+		return null;
1434
+	}
1435
+
1436
+
1437
+
1438
+	/**
1439
+	 * Gets an array of all the registered addons, where the keys are their names.
1440
+	 * (ie, what each returns for their name() function)
1441
+	 * They're already available on EE_Registry::instance()->addons as properties,
1442
+	 * where each property's name is the addon's classname,
1443
+	 * So if you just want to get the addon by classname,
1444
+	 * OR use the get_addon() method above.
1445
+	 * PLEASE  NOTE:
1446
+	 * addons with Fully Qualified Class Names
1447
+	 * have had the namespace separators converted to underscores,
1448
+	 * so a classname like Fully\Qualified\ClassName
1449
+	 * would have been converted to Fully_Qualified_ClassName
1450
+	 *
1451
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1452
+	 */
1453
+	public function get_addons_by_name()
1454
+	{
1455
+		$addons = array();
1456
+		foreach ($this->addons as $addon) {
1457
+			$addons[$addon->name()] = $addon;
1458
+		}
1459
+		return $addons;
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1465
+	 * a stale copy of it around
1466
+	 *
1467
+	 * @param string $model_name
1468
+	 * @return \EEM_Base
1469
+	 * @throws \EE_Error
1470
+	 */
1471
+	public function reset_model($model_name)
1472
+	{
1473
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1474
+			? "EEM_{$model_name}"
1475
+			: $model_name;
1476
+		if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1477
+			return null;
1478
+		}
1479
+		//get that model reset it and make sure we nuke the old reference to it
1480
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name
1481
+			&& is_callable(
1482
+				array($model_class_name, 'reset')
1483
+			)) {
1484
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1485
+		} else {
1486
+			throw new EE_Error(sprintf(esc_html__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1487
+		}
1488
+		return $this->LIB->{$model_class_name};
1489
+	}
1490
+
1491
+
1492
+
1493
+	/**
1494
+	 * Resets the registry.
1495
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1496
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1497
+	 * - $_dependency_map
1498
+	 * - $_class_abbreviations
1499
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1500
+	 * - $REQ:  Still on the same request so no need to change.
1501
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1502
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1503
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1504
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1505
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1506
+	 *             switch or on the restore.
1507
+	 * - $modules
1508
+	 * - $shortcodes
1509
+	 * - $widgets
1510
+	 *
1511
+	 * @param boolean $hard             [deprecated]
1512
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1513
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1514
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1515
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1516
+	 *                                  client
1517
+	 *                                  code instead can just change the model context to a different blog id if
1518
+	 *                                  necessary
1519
+	 * @return EE_Registry
1520
+	 * @throws EE_Error
1521
+	 * @throws ReflectionException
1522
+	 */
1523
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1524
+	{
1525
+		$instance = self::instance();
1526
+		$instance->_cache_on = true;
1527
+		// reset some "special" classes
1528
+		EEH_Activation::reset();
1529
+		$hard = apply_filters( 'FHEE__EE_Registry__reset__hard', $hard);
1530
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1531
+		$instance->CART = null;
1532
+		$instance->MRM = null;
1533
+		$instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1534
+		//messages reset
1535
+		EED_Messages::reset();
1536
+		//handle of objects cached on LIB
1537
+		foreach (array('LIB', 'modules') as $cache) {
1538
+			foreach ($instance->{$cache} as $class_name => $class) {
1539
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1540
+					unset($instance->{$cache}->{$class_name});
1541
+				}
1542
+			}
1543
+		}
1544
+		return $instance;
1545
+	}
1546
+
1547
+
1548
+
1549
+	/**
1550
+	 * if passed object implements ResettableInterface, then call it's reset() method
1551
+	 * if passed object implements InterminableInterface, then return false,
1552
+	 * to indicate that it should NOT be cleared from the Registry cache
1553
+	 *
1554
+	 * @param      $object
1555
+	 * @param bool $reset_models
1556
+	 * @return bool returns true if cached object should be unset
1557
+	 */
1558
+	private static function _reset_and_unset_object($object, $reset_models)
1559
+	{
1560
+		if (! is_object($object)) {
1561
+			// don't unset anything that's not an object
1562
+			return false;
1563
+		}
1564
+		if ($object instanceof EED_Module) {
1565
+			$object::reset();
1566
+			// don't unset modules
1567
+			return false;
1568
+		}
1569
+		if ($object instanceof ResettableInterface) {
1570
+			if ($object instanceof EEM_Base) {
1571
+				if ($reset_models) {
1572
+					$object->reset();
1573
+					return true;
1574
+				}
1575
+				return false;
1576
+			}
1577
+			$object->reset();
1578
+			return true;
1579
+		}
1580
+		if (! $object instanceof InterminableInterface) {
1581
+			return true;
1582
+		}
1583
+		return false;
1584
+	}
1585
+
1586
+
1587
+
1588
+	/**
1589
+	 * Gets all the custom post type models defined
1590
+	 *
1591
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1592
+	 */
1593
+	public function cpt_models()
1594
+	{
1595
+		$cpt_models = array();
1596
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1597
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1598
+				$cpt_models[$short_name] = $classname;
1599
+			}
1600
+		}
1601
+		return $cpt_models;
1602
+	}
1603
+
1604
+
1605
+
1606
+	/**
1607
+	 * @return \EE_Config
1608
+	 */
1609
+	public static function CFG()
1610
+	{
1611
+		return self::instance()->CFG;
1612
+	}
1613 1613
 
1614 1614
 
1615 1615
 }
Please login to merge, or discard this patch.
core/EE_Session.core.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -542,7 +542,7 @@  discard block
 block discarded – undo
542 542
     /**
543 543
      * @initiate session
544 544
      * @access   private
545
-     * @return TRUE on success, FALSE on fail
545
+     * @return boolean on success, FALSE on fail
546 546
      * @throws EE_Error
547 547
      * @throws InvalidArgumentException
548 548
      * @throws InvalidDataTypeException
@@ -778,7 +778,7 @@  discard block
 block discarded – undo
778 778
      * @update session data  prior to saving to the db
779 779
      * @access public
780 780
      * @param bool $new_session
781
-     * @return TRUE on success, FALSE on fail
781
+     * @return boolean on success, FALSE on fail
782 782
      * @throws EE_Error
783 783
      * @throws InvalidArgumentException
784 784
      * @throws InvalidDataTypeException
@@ -879,7 +879,7 @@  discard block
 block discarded – undo
879 879
      * _save_session_to_db
880 880
      *
881 881
      * @param bool $clear_session
882
-     * @return string
882
+     * @return boolean
883 883
      * @throws EE_Error
884 884
      * @throws InvalidArgumentException
885 885
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +1215 added lines, -1215 removed lines patch added patch discarded remove patch
@@ -22,1213 +22,1213 @@  discard block
 block discarded – undo
22 22
 class EE_Session implements SessionIdentifierInterface
23 23
 {
24 24
 
25
-    const session_id_prefix    = 'ee_ssn_';
26
-
27
-    const hash_check_prefix    = 'ee_shc_';
28
-
29
-    const OPTION_NAME_SETTINGS = 'ee_session_settings';
30
-
31
-    const STATUS_CLOSED        = 0;
32
-
33
-    const STATUS_OPEN          = 1;
34
-
35
-    /**
36
-     * instance of the EE_Session object
37
-     *
38
-     * @var EE_Session
39
-     */
40
-    private static $_instance;
41
-
42
-    /**
43
-     * @var CacheStorageInterface $cache_storage
44
-     */
45
-    protected $cache_storage;
46
-
47
-    /**
48
-     * EE_Encryption object
49
-     *
50
-     * @var EE_Encryption
51
-     */
52
-    protected $encryption;
53
-
54
-    /**
55
-     * the session id
56
-     *
57
-     * @var string
58
-     */
59
-    private $_sid;
60
-
61
-    /**
62
-     * session id salt
63
-     *
64
-     * @var string
65
-     */
66
-    private $_sid_salt;
67
-
68
-    /**
69
-     * session data
70
-     *
71
-     * @var array
72
-     */
73
-    private $_session_data = array();
74
-
75
-    /**
76
-     * how long an EE session lasts
77
-     * default session lifespan of 1 hour (for not so instant IPNs)
78
-     *
79
-     * @var SessionLifespan $session_lifespan
80
-     */
81
-    private $session_lifespan;
82
-
83
-    /**
84
-     * session expiration time as Unix timestamp in GMT
85
-     *
86
-     * @var int
87
-     */
88
-    private $_expiration;
89
-
90
-    /**
91
-     * whether or not session has expired at some point
92
-     *
93
-     * @var boolean
94
-     */
95
-    private $_expired = false;
96
-
97
-    /**
98
-     * current time as Unix timestamp in GMT
99
-     *
100
-     * @var int
101
-     */
102
-    private $_time;
103
-
104
-    /**
105
-     * whether to encrypt session data
106
-     *
107
-     * @var bool
108
-     */
109
-    private $_use_encryption;
110
-
111
-    /**
112
-     * well... according to the server...
113
-     *
114
-     * @var null
115
-     */
116
-    private $_user_agent;
117
-
118
-    /**
119
-     * do you really trust the server ?
120
-     *
121
-     * @var null
122
-     */
123
-    private $_ip_address;
124
-
125
-    /**
126
-     * current WP user_id
127
-     *
128
-     * @var null
129
-     */
130
-    private $_wp_user_id;
131
-
132
-    /**
133
-     * array for defining default session vars
134
-     *
135
-     * @var array
136
-     */
137
-    private $_default_session_vars = array(
138
-        'id'            => null,
139
-        'user_id'       => null,
140
-        'ip_address'    => null,
141
-        'user_agent'    => null,
142
-        'init_access'   => null,
143
-        'last_access'   => null,
144
-        'expiration'    => null,
145
-        'pages_visited' => array(),
146
-    );
147
-
148
-    /**
149
-     * timestamp for when last garbage collection cycle was performed
150
-     *
151
-     * @var int $_last_gc
152
-     */
153
-    private $_last_gc;
154
-
155
-    /**
156
-     * @var RequestInterface $request
157
-     */
158
-    protected $request;
159
-
160
-    /**
161
-     * whether session is active or not
162
-     *
163
-     * @var int $status
164
-     */
165
-    private $status = EE_Session::STATUS_CLOSED;
166
-
167
-
168
-
169
-    /**
170
-     * @singleton method used to instantiate class object
171
-     * @param CacheStorageInterface $cache_storage
172
-     * @param SessionLifespan|null  $lifespan
173
-     * @param RequestInterface      $request
174
-     * @param EE_Encryption         $encryption
175
-     * @return EE_Session
176
-     * @throws InvalidArgumentException
177
-     * @throws InvalidDataTypeException
178
-     * @throws InvalidInterfaceException
179
-     */
180
-    public static function instance(
181
-        CacheStorageInterface $cache_storage = null,
182
-        SessionLifespan $lifespan = null,
183
-        RequestInterface $request = null,
184
-        EE_Encryption $encryption = null
185
-    ) {
186
-        // check if class object is instantiated
187
-        // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
188
-        // add_filter( 'FHEE_load_EE_Session', '__return_false' );
189
-        if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
190
-            self::$_instance = new self(
191
-                $cache_storage,
192
-                $lifespan,
193
-                $request,
194
-                $encryption
195
-            );
196
-        }
197
-        return self::$_instance;
198
-    }
199
-
200
-
201
-    /**
202
-     * protected constructor to prevent direct creation
203
-     *
204
-     * @param CacheStorageInterface $cache_storage
205
-     * @param SessionLifespan       $lifespan
206
-     * @param RequestInterface      $request
207
-     * @param EE_Encryption         $encryption
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     */
212
-    protected function __construct(
213
-        CacheStorageInterface $cache_storage,
214
-        SessionLifespan $lifespan,
215
-        RequestInterface $request,
216
-        EE_Encryption $encryption = null
217
-    ) {
218
-        // session loading is turned ON by default,
219
-        // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
220
-        // (which currently fires on the init hook at priority 9),
221
-        // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
222
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
223
-            return;
224
-        }
225
-        $this->session_lifespan = $lifespan;
226
-        $this->request          = $request;
227
-        if (! defined('ESPRESSO_SESSION')) {
228
-            define('ESPRESSO_SESSION', true);
229
-        }
230
-        // retrieve session options from db
231
-        $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
232
-        if (! empty($session_settings)) {
233
-            // cycle though existing session options
234
-            foreach ($session_settings as $var_name => $session_setting) {
235
-                // set values for class properties
236
-                $var_name          = '_' . $var_name;
237
-                $this->{$var_name} = $session_setting;
238
-            }
239
-        }
240
-        $this->cache_storage = $cache_storage;
241
-        // are we using encryption?
242
-        $this->_use_encryption = $encryption instanceof EE_Encryption
243
-                                 && EE_Registry::instance()->CFG->admin->encode_session_data();
244
-        // \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__);
245
-        // encrypt data via: $this->encryption->encrypt();
246
-        $this->encryption = $encryption;
247
-        // filter hook allows outside functions/classes/plugins to change default empty cart
248
-        $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
249
-        array_merge($this->_default_session_vars, $extra_default_session_vars);
250
-        // apply default session vars
251
-        $this->_set_defaults();
252
-        add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
253
-        // check request for 'clear_session' param
254
-        add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
255
-        // once everything is all said and done,
256
-        add_action('shutdown', array($this, 'update'), 100);
257
-        add_action('shutdown', array($this, 'garbageCollection'), 1000);
258
-        $this->configure_garbage_collection_filters();
259
-    }
260
-
261
-
262
-    /**
263
-     * @return bool
264
-     * @throws InvalidArgumentException
265
-     * @throws InvalidDataTypeException
266
-     * @throws InvalidInterfaceException
267
-     */
268
-    public static function isLoadedAndActive()
269
-    {
270
-        return did_action('AHEE__EE_System__core_loaded_and_ready')
271
-               && EE_Session::instance() instanceof EE_Session
272
-               && EE_Session::instance()->isActive();
273
-    }
274
-
275
-
276
-    /**
277
-     * @return bool
278
-     */
279
-    public function isActive()
280
-    {
281
-        return $this->status === EE_Session::STATUS_OPEN;
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @return void
288
-     * @throws EE_Error
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidDataTypeException
291
-     * @throws InvalidInterfaceException
292
-     * @throws InvalidSessionDataException
293
-     */
294
-    public function open_session()
295
-    {
296
-        // check for existing session and retrieve it from db
297
-        if (! $this->_espresso_session()) {
298
-            // or just start a new one
299
-            $this->_create_espresso_session();
300
-        }
301
-    }
302
-
303
-
304
-
305
-    /**
306
-     * @return bool
307
-     */
308
-    public function expired()
309
-    {
310
-        return $this->_expired;
311
-    }
312
-
313
-
314
-
315
-    /**
316
-     * @return void
317
-     */
318
-    public function reset_expired()
319
-    {
320
-        $this->_expired = false;
321
-    }
322
-
323
-
324
-    /**
325
-     * @return int
326
-     */
327
-    public function expiration()
328
-    {
329
-        return $this->_expiration;
330
-    }
331
-
332
-
333
-
334
-    /**
335
-     * @return int
336
-     */
337
-    public function extension()
338
-    {
339
-        return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
340
-    }
341
-
342
-
343
-
344
-    /**
345
-     * @param int $time number of seconds to add to session expiration
346
-     */
347
-    public function extend_expiration($time = 0)
348
-    {
349
-        $time              = $time ? $time : $this->extension();
350
-        $this->_expiration += absint($time);
351
-    }
352
-
353
-
354
-
355
-    /**
356
-     * @return int
357
-     */
358
-    public function lifespan()
359
-    {
360
-        return $this->session_lifespan->inSeconds();
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * This just sets some defaults for the _session data property
367
-     *
368
-     * @access private
369
-     * @return void
370
-     */
371
-    private function _set_defaults()
372
-    {
373
-        // set some defaults
374
-        foreach ($this->_default_session_vars as $key => $default_var) {
375
-            if (is_array($default_var)) {
376
-                $this->_session_data[ $key ] = array();
377
-            } else {
378
-                $this->_session_data[ $key ] = '';
379
-            }
380
-        }
381
-    }
25
+	const session_id_prefix    = 'ee_ssn_';
26
+
27
+	const hash_check_prefix    = 'ee_shc_';
28
+
29
+	const OPTION_NAME_SETTINGS = 'ee_session_settings';
30
+
31
+	const STATUS_CLOSED        = 0;
32
+
33
+	const STATUS_OPEN          = 1;
34
+
35
+	/**
36
+	 * instance of the EE_Session object
37
+	 *
38
+	 * @var EE_Session
39
+	 */
40
+	private static $_instance;
41
+
42
+	/**
43
+	 * @var CacheStorageInterface $cache_storage
44
+	 */
45
+	protected $cache_storage;
46
+
47
+	/**
48
+	 * EE_Encryption object
49
+	 *
50
+	 * @var EE_Encryption
51
+	 */
52
+	protected $encryption;
53
+
54
+	/**
55
+	 * the session id
56
+	 *
57
+	 * @var string
58
+	 */
59
+	private $_sid;
60
+
61
+	/**
62
+	 * session id salt
63
+	 *
64
+	 * @var string
65
+	 */
66
+	private $_sid_salt;
67
+
68
+	/**
69
+	 * session data
70
+	 *
71
+	 * @var array
72
+	 */
73
+	private $_session_data = array();
74
+
75
+	/**
76
+	 * how long an EE session lasts
77
+	 * default session lifespan of 1 hour (for not so instant IPNs)
78
+	 *
79
+	 * @var SessionLifespan $session_lifespan
80
+	 */
81
+	private $session_lifespan;
82
+
83
+	/**
84
+	 * session expiration time as Unix timestamp in GMT
85
+	 *
86
+	 * @var int
87
+	 */
88
+	private $_expiration;
89
+
90
+	/**
91
+	 * whether or not session has expired at some point
92
+	 *
93
+	 * @var boolean
94
+	 */
95
+	private $_expired = false;
96
+
97
+	/**
98
+	 * current time as Unix timestamp in GMT
99
+	 *
100
+	 * @var int
101
+	 */
102
+	private $_time;
103
+
104
+	/**
105
+	 * whether to encrypt session data
106
+	 *
107
+	 * @var bool
108
+	 */
109
+	private $_use_encryption;
110
+
111
+	/**
112
+	 * well... according to the server...
113
+	 *
114
+	 * @var null
115
+	 */
116
+	private $_user_agent;
117
+
118
+	/**
119
+	 * do you really trust the server ?
120
+	 *
121
+	 * @var null
122
+	 */
123
+	private $_ip_address;
124
+
125
+	/**
126
+	 * current WP user_id
127
+	 *
128
+	 * @var null
129
+	 */
130
+	private $_wp_user_id;
131
+
132
+	/**
133
+	 * array for defining default session vars
134
+	 *
135
+	 * @var array
136
+	 */
137
+	private $_default_session_vars = array(
138
+		'id'            => null,
139
+		'user_id'       => null,
140
+		'ip_address'    => null,
141
+		'user_agent'    => null,
142
+		'init_access'   => null,
143
+		'last_access'   => null,
144
+		'expiration'    => null,
145
+		'pages_visited' => array(),
146
+	);
147
+
148
+	/**
149
+	 * timestamp for when last garbage collection cycle was performed
150
+	 *
151
+	 * @var int $_last_gc
152
+	 */
153
+	private $_last_gc;
154
+
155
+	/**
156
+	 * @var RequestInterface $request
157
+	 */
158
+	protected $request;
159
+
160
+	/**
161
+	 * whether session is active or not
162
+	 *
163
+	 * @var int $status
164
+	 */
165
+	private $status = EE_Session::STATUS_CLOSED;
166
+
167
+
168
+
169
+	/**
170
+	 * @singleton method used to instantiate class object
171
+	 * @param CacheStorageInterface $cache_storage
172
+	 * @param SessionLifespan|null  $lifespan
173
+	 * @param RequestInterface      $request
174
+	 * @param EE_Encryption         $encryption
175
+	 * @return EE_Session
176
+	 * @throws InvalidArgumentException
177
+	 * @throws InvalidDataTypeException
178
+	 * @throws InvalidInterfaceException
179
+	 */
180
+	public static function instance(
181
+		CacheStorageInterface $cache_storage = null,
182
+		SessionLifespan $lifespan = null,
183
+		RequestInterface $request = null,
184
+		EE_Encryption $encryption = null
185
+	) {
186
+		// check if class object is instantiated
187
+		// session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
188
+		// add_filter( 'FHEE_load_EE_Session', '__return_false' );
189
+		if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
190
+			self::$_instance = new self(
191
+				$cache_storage,
192
+				$lifespan,
193
+				$request,
194
+				$encryption
195
+			);
196
+		}
197
+		return self::$_instance;
198
+	}
199
+
200
+
201
+	/**
202
+	 * protected constructor to prevent direct creation
203
+	 *
204
+	 * @param CacheStorageInterface $cache_storage
205
+	 * @param SessionLifespan       $lifespan
206
+	 * @param RequestInterface      $request
207
+	 * @param EE_Encryption         $encryption
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 */
212
+	protected function __construct(
213
+		CacheStorageInterface $cache_storage,
214
+		SessionLifespan $lifespan,
215
+		RequestInterface $request,
216
+		EE_Encryption $encryption = null
217
+	) {
218
+		// session loading is turned ON by default,
219
+		// but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
220
+		// (which currently fires on the init hook at priority 9),
221
+		// can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
222
+		if (! apply_filters('FHEE_load_EE_Session', true)) {
223
+			return;
224
+		}
225
+		$this->session_lifespan = $lifespan;
226
+		$this->request          = $request;
227
+		if (! defined('ESPRESSO_SESSION')) {
228
+			define('ESPRESSO_SESSION', true);
229
+		}
230
+		// retrieve session options from db
231
+		$session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
232
+		if (! empty($session_settings)) {
233
+			// cycle though existing session options
234
+			foreach ($session_settings as $var_name => $session_setting) {
235
+				// set values for class properties
236
+				$var_name          = '_' . $var_name;
237
+				$this->{$var_name} = $session_setting;
238
+			}
239
+		}
240
+		$this->cache_storage = $cache_storage;
241
+		// are we using encryption?
242
+		$this->_use_encryption = $encryption instanceof EE_Encryption
243
+								 && EE_Registry::instance()->CFG->admin->encode_session_data();
244
+		// \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__);
245
+		// encrypt data via: $this->encryption->encrypt();
246
+		$this->encryption = $encryption;
247
+		// filter hook allows outside functions/classes/plugins to change default empty cart
248
+		$extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
249
+		array_merge($this->_default_session_vars, $extra_default_session_vars);
250
+		// apply default session vars
251
+		$this->_set_defaults();
252
+		add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
253
+		// check request for 'clear_session' param
254
+		add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
255
+		// once everything is all said and done,
256
+		add_action('shutdown', array($this, 'update'), 100);
257
+		add_action('shutdown', array($this, 'garbageCollection'), 1000);
258
+		$this->configure_garbage_collection_filters();
259
+	}
260
+
261
+
262
+	/**
263
+	 * @return bool
264
+	 * @throws InvalidArgumentException
265
+	 * @throws InvalidDataTypeException
266
+	 * @throws InvalidInterfaceException
267
+	 */
268
+	public static function isLoadedAndActive()
269
+	{
270
+		return did_action('AHEE__EE_System__core_loaded_and_ready')
271
+			   && EE_Session::instance() instanceof EE_Session
272
+			   && EE_Session::instance()->isActive();
273
+	}
274
+
275
+
276
+	/**
277
+	 * @return bool
278
+	 */
279
+	public function isActive()
280
+	{
281
+		return $this->status === EE_Session::STATUS_OPEN;
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @return void
288
+	 * @throws EE_Error
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidDataTypeException
291
+	 * @throws InvalidInterfaceException
292
+	 * @throws InvalidSessionDataException
293
+	 */
294
+	public function open_session()
295
+	{
296
+		// check for existing session and retrieve it from db
297
+		if (! $this->_espresso_session()) {
298
+			// or just start a new one
299
+			$this->_create_espresso_session();
300
+		}
301
+	}
302
+
303
+
304
+
305
+	/**
306
+	 * @return bool
307
+	 */
308
+	public function expired()
309
+	{
310
+		return $this->_expired;
311
+	}
312
+
313
+
314
+
315
+	/**
316
+	 * @return void
317
+	 */
318
+	public function reset_expired()
319
+	{
320
+		$this->_expired = false;
321
+	}
322
+
323
+
324
+	/**
325
+	 * @return int
326
+	 */
327
+	public function expiration()
328
+	{
329
+		return $this->_expiration;
330
+	}
331
+
332
+
333
+
334
+	/**
335
+	 * @return int
336
+	 */
337
+	public function extension()
338
+	{
339
+		return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
340
+	}
341
+
342
+
343
+
344
+	/**
345
+	 * @param int $time number of seconds to add to session expiration
346
+	 */
347
+	public function extend_expiration($time = 0)
348
+	{
349
+		$time              = $time ? $time : $this->extension();
350
+		$this->_expiration += absint($time);
351
+	}
352
+
353
+
354
+
355
+	/**
356
+	 * @return int
357
+	 */
358
+	public function lifespan()
359
+	{
360
+		return $this->session_lifespan->inSeconds();
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * This just sets some defaults for the _session data property
367
+	 *
368
+	 * @access private
369
+	 * @return void
370
+	 */
371
+	private function _set_defaults()
372
+	{
373
+		// set some defaults
374
+		foreach ($this->_default_session_vars as $key => $default_var) {
375
+			if (is_array($default_var)) {
376
+				$this->_session_data[ $key ] = array();
377
+			} else {
378
+				$this->_session_data[ $key ] = '';
379
+			}
380
+		}
381
+	}
382 382
 
383 383
 
384
-
385
-    /**
386
-     * @retrieve  session data
387
-     * @access    public
388
-     * @return    string
389
-     */
390
-    public function id()
391
-    {
392
-        return $this->_sid;
393
-    }
384
+
385
+	/**
386
+	 * @retrieve  session data
387
+	 * @access    public
388
+	 * @return    string
389
+	 */
390
+	public function id()
391
+	{
392
+		return $this->_sid;
393
+	}
394 394
 
395 395
 
396 396
 
397
-    /**
398
-     * @param \EE_Cart $cart
399
-     * @return bool
400
-     */
401
-    public function set_cart(EE_Cart $cart)
402
-    {
403
-        $this->_session_data['cart'] = $cart;
404
-        return true;
405
-    }
406
-
407
-
408
-
409
-    /**
410
-     * reset_cart
411
-     */
412
-    public function reset_cart()
413
-    {
414
-        do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
415
-        $this->_session_data['cart'] = null;
416
-    }
417
-
418
-
419
-
420
-    /**
421
-     * @return \EE_Cart
422
-     */
423
-    public function cart()
424
-    {
425
-        return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
426
-            ? $this->_session_data['cart']
427
-            : null;
428
-    }
429
-
430
-
431
-
432
-    /**
433
-     * @param \EE_Checkout $checkout
434
-     * @return bool
435
-     */
436
-    public function set_checkout(EE_Checkout $checkout)
437
-    {
438
-        $this->_session_data['checkout'] = $checkout;
439
-        return true;
440
-    }
441
-
442
-
443
-
444
-    /**
445
-     * reset_checkout
446
-     */
447
-    public function reset_checkout()
448
-    {
449
-        do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
450
-        $this->_session_data['checkout'] = null;
451
-    }
452
-
453
-
454
-
455
-    /**
456
-     * @return \EE_Checkout
457
-     */
458
-    public function checkout()
459
-    {
460
-        return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
461
-            ? $this->_session_data['checkout']
462
-            : null;
463
-    }
464
-
465
-
466
-
467
-    /**
468
-     * @param \EE_Transaction $transaction
469
-     * @return bool
470
-     * @throws EE_Error
471
-     */
472
-    public function set_transaction(EE_Transaction $transaction)
473
-    {
474
-        // first remove the session from the transaction before we save the transaction in the session
475
-        $transaction->set_txn_session_data(null);
476
-        $this->_session_data['transaction'] = $transaction;
477
-        return true;
478
-    }
479
-
480
-
481
-
482
-    /**
483
-     * reset_transaction
484
-     */
485
-    public function reset_transaction()
486
-    {
487
-        do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
488
-        $this->_session_data['transaction'] = null;
489
-    }
490
-
491
-
492
-
493
-    /**
494
-     * @return \EE_Transaction
495
-     */
496
-    public function transaction()
497
-    {
498
-        return isset($this->_session_data['transaction'])
499
-               && $this->_session_data['transaction'] instanceof EE_Transaction
500
-            ? $this->_session_data['transaction']
501
-            : null;
502
-    }
503
-
504
-
505
-    /**
506
-     * retrieve session data
507
-     *
508
-     * @param null $key
509
-     * @param bool $reset_cache
510
-     * @return array
511
-     */
512
-    public function get_session_data($key = null, $reset_cache = false)
513
-    {
514
-        if ($reset_cache) {
515
-            $this->reset_cart();
516
-            $this->reset_checkout();
517
-            $this->reset_transaction();
518
-        }
519
-        if (! empty($key)) {
520
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
521
-        }
522
-        return $this->_session_data;
523
-    }
524
-
525
-
526
-    /**
527
-     * Returns TRUE on success, FALSE on fail
528
-     *
529
-     * @param array $data
530
-     * @return bool
531
-     */
532
-    public function set_session_data($data)
533
-    {
534
-
535
-        // nothing ??? bad data ??? go home!
536
-        if (empty($data) || ! is_array($data)) {
537
-            EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__,
538
-                __FUNCTION__, __LINE__);
539
-            return false;
540
-        }
541
-        foreach ($data as $key => $value) {
542
-            if (isset($this->_default_session_vars[ $key ])) {
543
-                EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
544
-                    'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__);
545
-                return false;
546
-            }
547
-            $this->_session_data[ $key ] = $value;
548
-        }
549
-        return true;
550
-    }
551
-
552
-
553
-
554
-    /**
555
-     * @initiate session
556
-     * @access   private
557
-     * @return TRUE on success, FALSE on fail
558
-     * @throws EE_Error
559
-     * @throws InvalidArgumentException
560
-     * @throws InvalidDataTypeException
561
-     * @throws InvalidInterfaceException
562
-     * @throws InvalidSessionDataException
563
-     */
564
-    private function _espresso_session()
565
-    {
566
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
567
-        // check that session has started
568
-        if (session_id() === '') {
569
-            //starts a new session if one doesn't already exist, or re-initiates an existing one
570
-            session_start();
571
-        }
572
-        $this->status = EE_Session::STATUS_OPEN;
573
-        // get our modified session ID
574
-        $this->_sid = $this->_generate_session_id();
575
-        // and the visitors IP
576
-        $this->_ip_address = $this->request->ipAddress();
577
-        // set the "user agent"
578
-        $this->_user_agent = $this->request->userAgent();
579
-        // now let's retrieve what's in the db
580
-        $session_data = $this->_retrieve_session_data();
581
-        if (! empty($session_data)) {
582
-            // get the current time in UTC
583
-            $this->_time = $this->_time !== null ? $this->_time : time();
584
-            // and reset the session expiration
585
-            $this->_expiration = isset($session_data['expiration'])
586
-                ? $session_data['expiration']
587
-                : $this->_time + $this->session_lifespan->inSeconds();
588
-        } else {
589
-            // set initial site access time and the session expiration
590
-            $this->_set_init_access_and_expiration();
591
-            // set referer
592
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
593
-                ? esc_attr($_SERVER['HTTP_REFERER'])
594
-                : '';
595
-            // no previous session = go back and create one (on top of the data above)
596
-            return false;
597
-        }
598
-        // now the user agent
599
-        if ($session_data['user_agent'] !== $this->_user_agent) {
600
-            return false;
601
-        }
602
-        // wait a minute... how old are you?
603
-        if ($this->_time > $this->_expiration) {
604
-            // yer too old fer me!
605
-            $this->_expired = true;
606
-            // wipe out everything that isn't a default session datum
607
-            $this->clear_session(__CLASS__, __FUNCTION__);
608
-        }
609
-        // make event espresso session data available to plugin
610
-        $this->_session_data = array_merge($this->_session_data, $session_data);
611
-        return true;
612
-    }
613
-
614
-
615
-
616
-    /**
617
-     * _get_session_data
618
-     * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
619
-     * databases
620
-     *
621
-     * @return array
622
-     * @throws EE_Error
623
-     * @throws InvalidArgumentException
624
-     * @throws InvalidSessionDataException
625
-     * @throws InvalidDataTypeException
626
-     * @throws InvalidInterfaceException
627
-     */
628
-    protected function _retrieve_session_data()
629
-    {
630
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
631
-        try {
632
-            // we're using WP's Transient API to store session data using the PHP session ID as the option name
633
-            $session_data = $this->cache_storage->get($ssn_key, false);
634
-            if (empty($session_data)) {
635
-                return array();
636
-            }
637
-            if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
638
-                $hash_check = $this->cache_storage->get(
639
-                    EE_Session::hash_check_prefix . $this->_sid,
640
-                    false
641
-                );
642
-                if ($hash_check && $hash_check !== md5($session_data)) {
643
-                    EE_Error::add_error(
644
-                        sprintf(
645
-                            __(
646
-                                'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
647
-                                'event_espresso'
648
-                            ),
649
-                            EE_Session::session_id_prefix . $this->_sid
650
-                        ),
651
-                        __FILE__, __FUNCTION__, __LINE__
652
-                    );
653
-                }
654
-            }
655
-        } catch (Exception $e) {
656
-            // let's just eat that error for now and attempt to correct any corrupted data
657
-            global $wpdb;
658
-            $row          = $wpdb->get_row(
659
-                $wpdb->prepare(
660
-                    "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
661
-                    '_transient_' . $ssn_key
662
-                )
663
-            );
664
-            $session_data = is_object($row) ? $row->option_value : null;
665
-            if ($session_data) {
666
-                $session_data = preg_replace_callback(
667
-                    '!s:(d+):"(.*?)";!',
668
-                    function ($match)
669
-                    {
670
-                        return $match[1] === strlen($match[2])
671
-                            ? $match[0]
672
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
673
-                    },
674
-                    $session_data
675
-                );
676
-            }
677
-            $session_data = maybe_unserialize($session_data);
678
-        }
679
-        // in case the data is encoded... try to decode it
680
-        $session_data = $this->encryption instanceof EE_Encryption
681
-            ? $this->encryption->base64_string_decode($session_data)
682
-            : $session_data;
683
-        if (! is_array($session_data)) {
684
-            try {
685
-                $session_data = maybe_unserialize($session_data);
686
-            } catch (Exception $e) {
687
-                $msg = esc_html__(
688
-                    'An error occurred while attempting to unserialize the session data.',
689
-                    'event_espresso'
690
-                );
691
-                $msg .= WP_DEBUG
692
-                    ? '<br><pre>'
693
-                      . print_r($session_data, true)
694
-                      . '</pre><br>'
695
-                      . $this->find_serialize_error($session_data)
696
-                    : '';
697
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
698
-                throw new InvalidSessionDataException($msg, 0, $e);
699
-            }
700
-        }
701
-        // just a check to make sure the session array is indeed an array
702
-        if (! is_array($session_data)) {
703
-            // no?!?! then something is wrong
704
-            $msg = esc_html__(
705
-                'The session data is missing, invalid, or corrupted.',
706
-                'event_espresso'
707
-            );
708
-            $msg .= WP_DEBUG
709
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
710
-                : '';
711
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
712
-            throw new InvalidSessionDataException($msg);
713
-        }
714
-        if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
715
-            $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
716
-                $session_data['transaction']
717
-            );
718
-        }
719
-        return $session_data;
720
-    }
721
-
722
-
723
-
724
-    /**
725
-     * _generate_session_id
726
-     * Retrieves the PHP session id either directly from the PHP session,
727
-     * or from the $_REQUEST array if it was passed in from an AJAX request.
728
-     * The session id is then salted and hashed (mmm sounds tasty)
729
-     * so that it can be safely used as a $_REQUEST param
730
-     *
731
-     * @return string
732
-     */
733
-    protected function _generate_session_id()
734
-    {
735
-        // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
736
-        if (isset($_REQUEST['EESID'])) {
737
-            $session_id = sanitize_text_field($_REQUEST['EESID']);
738
-        } else {
739
-            $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
740
-        }
741
-        return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
742
-    }
743
-
744
-
745
-
746
-    /**
747
-     * _get_sid_salt
748
-     *
749
-     * @return string
750
-     */
751
-    protected function _get_sid_salt()
752
-    {
753
-        // was session id salt already saved to db ?
754
-        if (empty($this->_sid_salt)) {
755
-            // no?  then maybe use WP defined constant
756
-            if (defined('AUTH_SALT')) {
757
-                $this->_sid_salt = AUTH_SALT;
758
-            }
759
-            // if salt doesn't exist or is too short
760
-            if (strlen($this->_sid_salt) < 32) {
761
-                // create a new one
762
-                $this->_sid_salt = wp_generate_password(64);
763
-            }
764
-            // and save it as a permanent session setting
765
-            $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
766
-        }
767
-        return $this->_sid_salt;
768
-    }
769
-
770
-
771
-
772
-    /**
773
-     * _set_init_access_and_expiration
774
-     *
775
-     * @return void
776
-     */
777
-    protected function _set_init_access_and_expiration()
778
-    {
779
-        $this->_time       = time();
780
-        $this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
781
-        // set initial site access time
782
-        $this->_session_data['init_access'] = $this->_time;
783
-        // and the session expiration
784
-        $this->_session_data['expiration'] = $this->_expiration;
785
-    }
786
-
787
-
788
-
789
-    /**
790
-     * @update session data  prior to saving to the db
791
-     * @access public
792
-     * @param bool $new_session
793
-     * @return TRUE on success, FALSE on fail
794
-     * @throws EE_Error
795
-     * @throws InvalidArgumentException
796
-     * @throws InvalidDataTypeException
797
-     * @throws InvalidInterfaceException
798
-     */
799
-    public function update($new_session = false)
800
-    {
801
-        $this->_session_data = $this->_session_data !== null
802
-                               && is_array($this->_session_data)
803
-                               && isset($this->_session_data['id'])
804
-            ? $this->_session_data
805
-            : array();
806
-        if (empty($this->_session_data)) {
807
-            $this->_set_defaults();
808
-        }
809
-        $session_data = array();
810
-        foreach ($this->_session_data as $key => $value) {
811
-
812
-            switch ($key) {
813
-
814
-                case 'id' :
815
-                    // session ID
816
-                    $session_data['id'] = $this->_sid;
817
-                    break;
818
-                case 'ip_address' :
819
-                    // visitor ip address
820
-                    $session_data['ip_address'] = $this->request->ipAddress();
821
-                    break;
822
-                case 'user_agent' :
823
-                    // visitor user_agent
824
-                    $session_data['user_agent'] = $this->_user_agent;
825
-                    break;
826
-                case 'init_access' :
827
-                    $session_data['init_access'] = absint($value);
828
-                    break;
829
-                case 'last_access' :
830
-                    // current access time
831
-                    $session_data['last_access'] = $this->_time;
832
-                    break;
833
-                case 'expiration' :
834
-                    // when the session expires
835
-                    $session_data['expiration'] = ! empty($this->_expiration)
836
-                        ? $this->_expiration
837
-                        : $session_data['init_access'] + $this->session_lifespan->inSeconds();
838
-                    break;
839
-                case 'user_id' :
840
-                    // current user if logged in
841
-                    $session_data['user_id'] = $this->_wp_user_id();
842
-                    break;
843
-                case 'pages_visited' :
844
-                    $page_visit = $this->_get_page_visit();
845
-                    if ($page_visit) {
846
-                        // set pages visited where the first will be the http referrer
847
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
848
-                        // we'll only save the last 10 page visits.
849
-                        $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
850
-                    }
851
-                    break;
852
-                default :
853
-                    // carry any other data over
854
-                    $session_data[ $key ] = $this->_session_data[ $key ];
855
-            }
856
-        }
857
-        $this->_session_data = $session_data;
858
-        // creating a new session does not require saving to the db just yet
859
-        if (! $new_session) {
860
-            // ready? let's save
861
-            if ($this->_save_session_to_db()) {
862
-                return true;
863
-            }
864
-            return false;
865
-        }
866
-        // meh, why not?
867
-        return true;
868
-    }
869
-
870
-
871
-
872
-    /**
873
-     * @create session data array
874
-     * @access public
875
-     * @return bool
876
-     * @throws EE_Error
877
-     * @throws InvalidArgumentException
878
-     * @throws InvalidDataTypeException
879
-     * @throws InvalidInterfaceException
880
-     */
881
-    private function _create_espresso_session()
882
-    {
883
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
884
-        // use the update function for now with $new_session arg set to TRUE
885
-        return $this->update(true) ? true : false;
886
-    }
887
-
888
-
889
-
890
-    /**
891
-     * _save_session_to_db
892
-     *
893
-     * @param bool $clear_session
894
-     * @return string
895
-     * @throws EE_Error
896
-     * @throws InvalidArgumentException
897
-     * @throws InvalidDataTypeException
898
-     * @throws InvalidInterfaceException
899
-     */
900
-    private function _save_session_to_db($clear_session = false)
901
-    {
902
-        // don't save sessions for crawlers
903
-        // and unless we're deleting the session data, don't save anything if there isn't a cart
904
-        if ($this->request->isBot() || (! $clear_session && ! $this->cart() instanceof EE_Cart)) {
905
-            return false;
906
-        }
907
-        $transaction = $this->transaction();
908
-        if ($transaction instanceof EE_Transaction) {
909
-            if (! $transaction->ID()) {
910
-                $transaction->save();
911
-            }
912
-            $this->_session_data['transaction'] = $transaction->ID();
913
-        }
914
-        // then serialize all of our session data
915
-        $session_data = serialize($this->_session_data);
916
-        // do we need to also encode it to avoid corrupted data when saved to the db?
917
-        $session_data = $this->_use_encryption
918
-            ? $this->encryption->base64_string_encode($session_data)
919
-            : $session_data;
920
-        // maybe save hash check
921
-        if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
922
-            $this->cache_storage->add(
923
-                EE_Session::hash_check_prefix . $this->_sid,
924
-                md5($session_data),
925
-                $this->session_lifespan->inSeconds()
926
-            );
927
-        }
928
-        // we're using the Transient API for storing session data,
929
-        return $this->cache_storage->add(
930
-            EE_Session::session_id_prefix . $this->_sid,
931
-            $session_data,
932
-            $this->session_lifespan->inSeconds()
933
-        );
934
-    }
935
-
936
-
937
-    /**
938
-     * @get    the full page request the visitor is accessing
939
-     * @access public
940
-     * @return string
941
-     */
942
-    public function _get_page_visit()
943
-    {
944
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
945
-        // check for request url
946
-        if (isset($_SERVER['REQUEST_URI'])) {
947
-            $http_host   = '';
948
-            $page_id     = '?';
949
-            $e_reg       = '';
950
-            $request_uri = esc_url($_SERVER['REQUEST_URI']);
951
-            $ru_bits     = explode('?', $request_uri);
952
-            $request_uri = $ru_bits[0];
953
-            // check for and grab host as well
954
-            if (isset($_SERVER['HTTP_HOST'])) {
955
-                $http_host = esc_url($_SERVER['HTTP_HOST']);
956
-            }
957
-            // check for page_id in SERVER REQUEST
958
-            if (isset($_REQUEST['page_id'])) {
959
-                // rebuild $e_reg without any of the extra parameters
960
-                $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
961
-            }
962
-            // check for $e_reg in SERVER REQUEST
963
-            if (isset($_REQUEST['ee'])) {
964
-                // rebuild $e_reg without any of the extra parameters
965
-                $e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
966
-            }
967
-            $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
968
-        }
969
-        return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
970
-    }
971
-
972
-
973
-
974
-    /**
975
-     * @the    current wp user id
976
-     * @access public
977
-     * @return int
978
-     */
979
-    public function _wp_user_id()
980
-    {
981
-        // if I need to explain the following lines of code, then you shouldn't be looking at this!
982
-        $this->_wp_user_id = get_current_user_id();
983
-        return $this->_wp_user_id;
984
-    }
985
-
986
-
987
-
988
-    /**
989
-     * Clear EE_Session data
990
-     *
991
-     * @access public
992
-     * @param string $class
993
-     * @param string $function
994
-     * @return void
995
-     * @throws EE_Error
996
-     * @throws InvalidArgumentException
997
-     * @throws InvalidDataTypeException
998
-     * @throws InvalidInterfaceException
999
-     */
1000
-    public function clear_session($class = '', $function = '')
1001
-    {
1002
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1003
-        $this->reset_cart();
1004
-        $this->reset_checkout();
1005
-        $this->reset_transaction();
1006
-        // wipe out everything that isn't a default session datum
1007
-        $this->reset_data(array_keys($this->_session_data));
1008
-        // reset initial site access time and the session expiration
1009
-        $this->_set_init_access_and_expiration();
1010
-        $this->_save_session_to_db(true);
1011
-    }
1012
-
1013
-
1014
-    /**
1015
-     * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1016
-     *
1017
-     * @param array|mixed $data_to_reset
1018
-     * @param bool        $show_all_notices
1019
-     * @return bool
1020
-     */
1021
-    public function reset_data($data_to_reset = array(), $show_all_notices = false)
1022
-    {
1023
-        // if $data_to_reset is not in an array, then put it in one
1024
-        if (! is_array($data_to_reset)) {
1025
-            $data_to_reset = array($data_to_reset);
1026
-        }
1027
-        // nothing ??? go home!
1028
-        if (empty($data_to_reset)) {
1029
-            EE_Error::add_error(__('No session data could be reset, because no session var name was provided.',
1030
-                'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1031
-            return false;
1032
-        }
1033
-        $return_value = true;
1034
-        // since $data_to_reset is an array, cycle through the values
1035
-        foreach ($data_to_reset as $reset) {
1036
-
1037
-            // first check to make sure it is a valid session var
1038
-            if (isset($this->_session_data[ $reset ])) {
1039
-                // then check to make sure it is not a default var
1040
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1041
-                    // remove session var
1042
-                    unset($this->_session_data[ $reset ]);
1043
-                    if ($show_all_notices) {
1044
-                        EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'),
1045
-                            $reset), __FILE__, __FUNCTION__, __LINE__);
1046
-                    }
1047
-                } else {
1048
-                    // yeeeeeeeeerrrrrrrrrrr OUT !!!!
1049
-                    if ($show_all_notices) {
1050
-                        EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
1051
-                            'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1052
-                    }
1053
-                    $return_value = false;
1054
-                }
1055
-            } elseif ($show_all_notices) {
1056
-                // oops! that session var does not exist!
1057
-                EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.',
1058
-                    'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1059
-                $return_value = false;
1060
-            }
1061
-        } // end of foreach
1062
-        return $return_value;
1063
-    }
1064
-
1065
-
1066
-
1067
-    /**
1068
-     *   wp_loaded
1069
-     *
1070
-     * @access public
1071
-     * @throws EE_Error
1072
-     * @throws InvalidDataTypeException
1073
-     * @throws InvalidInterfaceException
1074
-     * @throws InvalidArgumentException
1075
-     */
1076
-    public function wp_loaded()
1077
-    {
1078
-        if ($this->request->requestParamIsSet('clear_session')) {
1079
-            $this->clear_session(__CLASS__, __FUNCTION__);
1080
-        }
1081
-    }
1082
-
1083
-
1084
-
1085
-    /**
1086
-     * Used to reset the entire object (for tests).
1087
-     *
1088
-     * @since 4.3.0
1089
-     * @throws EE_Error
1090
-     * @throws InvalidDataTypeException
1091
-     * @throws InvalidInterfaceException
1092
-     * @throws InvalidArgumentException
1093
-     */
1094
-    public function reset_instance()
1095
-    {
1096
-        $this->clear_session();
1097
-        self::$_instance = null;
1098
-    }
1099
-
1100
-
1101
-
1102
-    public function configure_garbage_collection_filters()
1103
-    {
1104
-        // run old filter we had for controlling session cleanup
1105
-        $expired_session_transient_delete_query_limit = absint(
1106
-            apply_filters(
1107
-                'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1108
-                50
1109
-            )
1110
-        );
1111
-        // is there a value? or one that is different than the default 50 records?
1112
-        if ($expired_session_transient_delete_query_limit === 0) {
1113
-            // hook into TransientCacheStorage in case Session cleanup was turned off
1114
-            add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1115
-        } elseif ($expired_session_transient_delete_query_limit !== 50) {
1116
-            // or use that for the new transient cleanup query limit
1117
-            add_filter(
1118
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1119
-                function () use ($expired_session_transient_delete_query_limit)
1120
-                {
1121
-                    return $expired_session_transient_delete_query_limit;
1122
-                }
1123
-            );
1124
-        }
1125
-    }
1126
-
1127
-
1128
-
1129
-    /**
1130
-     * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1131
-     * @param $data1
1132
-     * @return string
1133
-     */
1134
-    private function find_serialize_error($data1)
1135
-    {
1136
-        $error = '<pre>';
1137
-        $data2 = preg_replace_callback(
1138
-            '!s:(\d+):"(.*?)";!',
1139
-            function ($match)
1140
-            {
1141
-                return ($match[1] === strlen($match[2]))
1142
-                    ? $match[0]
1143
-                    : 's:'
1144
-                      . strlen($match[2])
1145
-                      . ':"'
1146
-                      . $match[2]
1147
-                      . '";';
1148
-            },
1149
-            $data1
1150
-        );
1151
-        $max   = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1152
-        $error .= $data1 . PHP_EOL;
1153
-        $error .= $data2 . PHP_EOL;
1154
-        for ($i = 0; $i < $max; $i++) {
1155
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1156
-                $error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1157
-                $error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1158
-                $error  .= "\t-> Line Number = $i" . PHP_EOL;
1159
-                $start  = ($i - 20);
1160
-                $start  = ($start < 0) ? 0 : $start;
1161
-                $length = 40;
1162
-                $point  = $max - $i;
1163
-                if ($point < 20) {
1164
-                    $rlength = 1;
1165
-                    $rpoint  = -$point;
1166
-                } else {
1167
-                    $rpoint  = $length - 20;
1168
-                    $rlength = 1;
1169
-                }
1170
-                $error .= "\t-> Section Data1  = ";
1171
-                $error .= substr_replace(
1172
-                    substr($data1, $start, $length),
1173
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1174
-                    $rpoint,
1175
-                    $rlength
1176
-                );
1177
-                $error .= PHP_EOL;
1178
-                $error .= "\t-> Section Data2  = ";
1179
-                $error .= substr_replace(
1180
-                    substr($data2, $start, $length),
1181
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1182
-                    $rpoint,
1183
-                    $rlength
1184
-                );
1185
-                $error .= PHP_EOL;
1186
-            }
1187
-        }
1188
-        $error .= '</pre>';
1189
-        return $error;
1190
-    }
1191
-
1192
-
1193
-    /**
1194
-     * Saves an  array of settings used for configuring aspects of session behaviour
1195
-     *
1196
-     * @param array $updated_settings
1197
-     */
1198
-    private function updateSessionSettings(array $updated_settings = array())
1199
-    {
1200
-        // add existing settings, but only if not included in incoming $updated_settings array
1201
-        $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1202
-        update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * garbage_collection
1208
-     */
1209
-    public function garbageCollection()
1210
-    {
1211
-        // only perform during regular requests if last garbage collection was over an hour ago
1212
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1213
-            $this->_last_gc = time();
1214
-            $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1215
-            /** @type WPDB $wpdb */
1216
-            global $wpdb;
1217
-            // filter the query limit. Set to 0 to turn off garbage collection
1218
-            $expired_session_transient_delete_query_limit = absint(
1219
-                apply_filters(
1220
-                    'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1221
-                    50
1222
-                )
1223
-            );
1224
-            // non-zero LIMIT means take out the trash
1225
-            if ($expired_session_transient_delete_query_limit) {
1226
-                $session_key    = str_replace('_', '\_', EE_Session::session_id_prefix);
1227
-                $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1228
-                // since transient expiration timestamps are set in the future, we can compare against NOW
1229
-                // but we only want to pick up any trash that's been around for more than a day
1230
-                $expiration = time() - DAY_IN_SECONDS;
1231
-                $SQL        = "
397
+	/**
398
+	 * @param \EE_Cart $cart
399
+	 * @return bool
400
+	 */
401
+	public function set_cart(EE_Cart $cart)
402
+	{
403
+		$this->_session_data['cart'] = $cart;
404
+		return true;
405
+	}
406
+
407
+
408
+
409
+	/**
410
+	 * reset_cart
411
+	 */
412
+	public function reset_cart()
413
+	{
414
+		do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
415
+		$this->_session_data['cart'] = null;
416
+	}
417
+
418
+
419
+
420
+	/**
421
+	 * @return \EE_Cart
422
+	 */
423
+	public function cart()
424
+	{
425
+		return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
426
+			? $this->_session_data['cart']
427
+			: null;
428
+	}
429
+
430
+
431
+
432
+	/**
433
+	 * @param \EE_Checkout $checkout
434
+	 * @return bool
435
+	 */
436
+	public function set_checkout(EE_Checkout $checkout)
437
+	{
438
+		$this->_session_data['checkout'] = $checkout;
439
+		return true;
440
+	}
441
+
442
+
443
+
444
+	/**
445
+	 * reset_checkout
446
+	 */
447
+	public function reset_checkout()
448
+	{
449
+		do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
450
+		$this->_session_data['checkout'] = null;
451
+	}
452
+
453
+
454
+
455
+	/**
456
+	 * @return \EE_Checkout
457
+	 */
458
+	public function checkout()
459
+	{
460
+		return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
461
+			? $this->_session_data['checkout']
462
+			: null;
463
+	}
464
+
465
+
466
+
467
+	/**
468
+	 * @param \EE_Transaction $transaction
469
+	 * @return bool
470
+	 * @throws EE_Error
471
+	 */
472
+	public function set_transaction(EE_Transaction $transaction)
473
+	{
474
+		// first remove the session from the transaction before we save the transaction in the session
475
+		$transaction->set_txn_session_data(null);
476
+		$this->_session_data['transaction'] = $transaction;
477
+		return true;
478
+	}
479
+
480
+
481
+
482
+	/**
483
+	 * reset_transaction
484
+	 */
485
+	public function reset_transaction()
486
+	{
487
+		do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
488
+		$this->_session_data['transaction'] = null;
489
+	}
490
+
491
+
492
+
493
+	/**
494
+	 * @return \EE_Transaction
495
+	 */
496
+	public function transaction()
497
+	{
498
+		return isset($this->_session_data['transaction'])
499
+			   && $this->_session_data['transaction'] instanceof EE_Transaction
500
+			? $this->_session_data['transaction']
501
+			: null;
502
+	}
503
+
504
+
505
+	/**
506
+	 * retrieve session data
507
+	 *
508
+	 * @param null $key
509
+	 * @param bool $reset_cache
510
+	 * @return array
511
+	 */
512
+	public function get_session_data($key = null, $reset_cache = false)
513
+	{
514
+		if ($reset_cache) {
515
+			$this->reset_cart();
516
+			$this->reset_checkout();
517
+			$this->reset_transaction();
518
+		}
519
+		if (! empty($key)) {
520
+			return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
521
+		}
522
+		return $this->_session_data;
523
+	}
524
+
525
+
526
+	/**
527
+	 * Returns TRUE on success, FALSE on fail
528
+	 *
529
+	 * @param array $data
530
+	 * @return bool
531
+	 */
532
+	public function set_session_data($data)
533
+	{
534
+
535
+		// nothing ??? bad data ??? go home!
536
+		if (empty($data) || ! is_array($data)) {
537
+			EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__,
538
+				__FUNCTION__, __LINE__);
539
+			return false;
540
+		}
541
+		foreach ($data as $key => $value) {
542
+			if (isset($this->_default_session_vars[ $key ])) {
543
+				EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
544
+					'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__);
545
+				return false;
546
+			}
547
+			$this->_session_data[ $key ] = $value;
548
+		}
549
+		return true;
550
+	}
551
+
552
+
553
+
554
+	/**
555
+	 * @initiate session
556
+	 * @access   private
557
+	 * @return TRUE on success, FALSE on fail
558
+	 * @throws EE_Error
559
+	 * @throws InvalidArgumentException
560
+	 * @throws InvalidDataTypeException
561
+	 * @throws InvalidInterfaceException
562
+	 * @throws InvalidSessionDataException
563
+	 */
564
+	private function _espresso_session()
565
+	{
566
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
567
+		// check that session has started
568
+		if (session_id() === '') {
569
+			//starts a new session if one doesn't already exist, or re-initiates an existing one
570
+			session_start();
571
+		}
572
+		$this->status = EE_Session::STATUS_OPEN;
573
+		// get our modified session ID
574
+		$this->_sid = $this->_generate_session_id();
575
+		// and the visitors IP
576
+		$this->_ip_address = $this->request->ipAddress();
577
+		// set the "user agent"
578
+		$this->_user_agent = $this->request->userAgent();
579
+		// now let's retrieve what's in the db
580
+		$session_data = $this->_retrieve_session_data();
581
+		if (! empty($session_data)) {
582
+			// get the current time in UTC
583
+			$this->_time = $this->_time !== null ? $this->_time : time();
584
+			// and reset the session expiration
585
+			$this->_expiration = isset($session_data['expiration'])
586
+				? $session_data['expiration']
587
+				: $this->_time + $this->session_lifespan->inSeconds();
588
+		} else {
589
+			// set initial site access time and the session expiration
590
+			$this->_set_init_access_and_expiration();
591
+			// set referer
592
+			$this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
593
+				? esc_attr($_SERVER['HTTP_REFERER'])
594
+				: '';
595
+			// no previous session = go back and create one (on top of the data above)
596
+			return false;
597
+		}
598
+		// now the user agent
599
+		if ($session_data['user_agent'] !== $this->_user_agent) {
600
+			return false;
601
+		}
602
+		// wait a minute... how old are you?
603
+		if ($this->_time > $this->_expiration) {
604
+			// yer too old fer me!
605
+			$this->_expired = true;
606
+			// wipe out everything that isn't a default session datum
607
+			$this->clear_session(__CLASS__, __FUNCTION__);
608
+		}
609
+		// make event espresso session data available to plugin
610
+		$this->_session_data = array_merge($this->_session_data, $session_data);
611
+		return true;
612
+	}
613
+
614
+
615
+
616
+	/**
617
+	 * _get_session_data
618
+	 * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
619
+	 * databases
620
+	 *
621
+	 * @return array
622
+	 * @throws EE_Error
623
+	 * @throws InvalidArgumentException
624
+	 * @throws InvalidSessionDataException
625
+	 * @throws InvalidDataTypeException
626
+	 * @throws InvalidInterfaceException
627
+	 */
628
+	protected function _retrieve_session_data()
629
+	{
630
+		$ssn_key = EE_Session::session_id_prefix . $this->_sid;
631
+		try {
632
+			// we're using WP's Transient API to store session data using the PHP session ID as the option name
633
+			$session_data = $this->cache_storage->get($ssn_key, false);
634
+			if (empty($session_data)) {
635
+				return array();
636
+			}
637
+			if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
638
+				$hash_check = $this->cache_storage->get(
639
+					EE_Session::hash_check_prefix . $this->_sid,
640
+					false
641
+				);
642
+				if ($hash_check && $hash_check !== md5($session_data)) {
643
+					EE_Error::add_error(
644
+						sprintf(
645
+							__(
646
+								'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
647
+								'event_espresso'
648
+							),
649
+							EE_Session::session_id_prefix . $this->_sid
650
+						),
651
+						__FILE__, __FUNCTION__, __LINE__
652
+					);
653
+				}
654
+			}
655
+		} catch (Exception $e) {
656
+			// let's just eat that error for now and attempt to correct any corrupted data
657
+			global $wpdb;
658
+			$row          = $wpdb->get_row(
659
+				$wpdb->prepare(
660
+					"SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
661
+					'_transient_' . $ssn_key
662
+				)
663
+			);
664
+			$session_data = is_object($row) ? $row->option_value : null;
665
+			if ($session_data) {
666
+				$session_data = preg_replace_callback(
667
+					'!s:(d+):"(.*?)";!',
668
+					function ($match)
669
+					{
670
+						return $match[1] === strlen($match[2])
671
+							? $match[0]
672
+							: 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
673
+					},
674
+					$session_data
675
+				);
676
+			}
677
+			$session_data = maybe_unserialize($session_data);
678
+		}
679
+		// in case the data is encoded... try to decode it
680
+		$session_data = $this->encryption instanceof EE_Encryption
681
+			? $this->encryption->base64_string_decode($session_data)
682
+			: $session_data;
683
+		if (! is_array($session_data)) {
684
+			try {
685
+				$session_data = maybe_unserialize($session_data);
686
+			} catch (Exception $e) {
687
+				$msg = esc_html__(
688
+					'An error occurred while attempting to unserialize the session data.',
689
+					'event_espresso'
690
+				);
691
+				$msg .= WP_DEBUG
692
+					? '<br><pre>'
693
+					  . print_r($session_data, true)
694
+					  . '</pre><br>'
695
+					  . $this->find_serialize_error($session_data)
696
+					: '';
697
+				$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
698
+				throw new InvalidSessionDataException($msg, 0, $e);
699
+			}
700
+		}
701
+		// just a check to make sure the session array is indeed an array
702
+		if (! is_array($session_data)) {
703
+			// no?!?! then something is wrong
704
+			$msg = esc_html__(
705
+				'The session data is missing, invalid, or corrupted.',
706
+				'event_espresso'
707
+			);
708
+			$msg .= WP_DEBUG
709
+				? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
710
+				: '';
711
+			$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
712
+			throw new InvalidSessionDataException($msg);
713
+		}
714
+		if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
715
+			$session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
716
+				$session_data['transaction']
717
+			);
718
+		}
719
+		return $session_data;
720
+	}
721
+
722
+
723
+
724
+	/**
725
+	 * _generate_session_id
726
+	 * Retrieves the PHP session id either directly from the PHP session,
727
+	 * or from the $_REQUEST array if it was passed in from an AJAX request.
728
+	 * The session id is then salted and hashed (mmm sounds tasty)
729
+	 * so that it can be safely used as a $_REQUEST param
730
+	 *
731
+	 * @return string
732
+	 */
733
+	protected function _generate_session_id()
734
+	{
735
+		// check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
736
+		if (isset($_REQUEST['EESID'])) {
737
+			$session_id = sanitize_text_field($_REQUEST['EESID']);
738
+		} else {
739
+			$session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
740
+		}
741
+		return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
742
+	}
743
+
744
+
745
+
746
+	/**
747
+	 * _get_sid_salt
748
+	 *
749
+	 * @return string
750
+	 */
751
+	protected function _get_sid_salt()
752
+	{
753
+		// was session id salt already saved to db ?
754
+		if (empty($this->_sid_salt)) {
755
+			// no?  then maybe use WP defined constant
756
+			if (defined('AUTH_SALT')) {
757
+				$this->_sid_salt = AUTH_SALT;
758
+			}
759
+			// if salt doesn't exist or is too short
760
+			if (strlen($this->_sid_salt) < 32) {
761
+				// create a new one
762
+				$this->_sid_salt = wp_generate_password(64);
763
+			}
764
+			// and save it as a permanent session setting
765
+			$this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
766
+		}
767
+		return $this->_sid_salt;
768
+	}
769
+
770
+
771
+
772
+	/**
773
+	 * _set_init_access_and_expiration
774
+	 *
775
+	 * @return void
776
+	 */
777
+	protected function _set_init_access_and_expiration()
778
+	{
779
+		$this->_time       = time();
780
+		$this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
781
+		// set initial site access time
782
+		$this->_session_data['init_access'] = $this->_time;
783
+		// and the session expiration
784
+		$this->_session_data['expiration'] = $this->_expiration;
785
+	}
786
+
787
+
788
+
789
+	/**
790
+	 * @update session data  prior to saving to the db
791
+	 * @access public
792
+	 * @param bool $new_session
793
+	 * @return TRUE on success, FALSE on fail
794
+	 * @throws EE_Error
795
+	 * @throws InvalidArgumentException
796
+	 * @throws InvalidDataTypeException
797
+	 * @throws InvalidInterfaceException
798
+	 */
799
+	public function update($new_session = false)
800
+	{
801
+		$this->_session_data = $this->_session_data !== null
802
+							   && is_array($this->_session_data)
803
+							   && isset($this->_session_data['id'])
804
+			? $this->_session_data
805
+			: array();
806
+		if (empty($this->_session_data)) {
807
+			$this->_set_defaults();
808
+		}
809
+		$session_data = array();
810
+		foreach ($this->_session_data as $key => $value) {
811
+
812
+			switch ($key) {
813
+
814
+				case 'id' :
815
+					// session ID
816
+					$session_data['id'] = $this->_sid;
817
+					break;
818
+				case 'ip_address' :
819
+					// visitor ip address
820
+					$session_data['ip_address'] = $this->request->ipAddress();
821
+					break;
822
+				case 'user_agent' :
823
+					// visitor user_agent
824
+					$session_data['user_agent'] = $this->_user_agent;
825
+					break;
826
+				case 'init_access' :
827
+					$session_data['init_access'] = absint($value);
828
+					break;
829
+				case 'last_access' :
830
+					// current access time
831
+					$session_data['last_access'] = $this->_time;
832
+					break;
833
+				case 'expiration' :
834
+					// when the session expires
835
+					$session_data['expiration'] = ! empty($this->_expiration)
836
+						? $this->_expiration
837
+						: $session_data['init_access'] + $this->session_lifespan->inSeconds();
838
+					break;
839
+				case 'user_id' :
840
+					// current user if logged in
841
+					$session_data['user_id'] = $this->_wp_user_id();
842
+					break;
843
+				case 'pages_visited' :
844
+					$page_visit = $this->_get_page_visit();
845
+					if ($page_visit) {
846
+						// set pages visited where the first will be the http referrer
847
+						$this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
848
+						// we'll only save the last 10 page visits.
849
+						$session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
850
+					}
851
+					break;
852
+				default :
853
+					// carry any other data over
854
+					$session_data[ $key ] = $this->_session_data[ $key ];
855
+			}
856
+		}
857
+		$this->_session_data = $session_data;
858
+		// creating a new session does not require saving to the db just yet
859
+		if (! $new_session) {
860
+			// ready? let's save
861
+			if ($this->_save_session_to_db()) {
862
+				return true;
863
+			}
864
+			return false;
865
+		}
866
+		// meh, why not?
867
+		return true;
868
+	}
869
+
870
+
871
+
872
+	/**
873
+	 * @create session data array
874
+	 * @access public
875
+	 * @return bool
876
+	 * @throws EE_Error
877
+	 * @throws InvalidArgumentException
878
+	 * @throws InvalidDataTypeException
879
+	 * @throws InvalidInterfaceException
880
+	 */
881
+	private function _create_espresso_session()
882
+	{
883
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
884
+		// use the update function for now with $new_session arg set to TRUE
885
+		return $this->update(true) ? true : false;
886
+	}
887
+
888
+
889
+
890
+	/**
891
+	 * _save_session_to_db
892
+	 *
893
+	 * @param bool $clear_session
894
+	 * @return string
895
+	 * @throws EE_Error
896
+	 * @throws InvalidArgumentException
897
+	 * @throws InvalidDataTypeException
898
+	 * @throws InvalidInterfaceException
899
+	 */
900
+	private function _save_session_to_db($clear_session = false)
901
+	{
902
+		// don't save sessions for crawlers
903
+		// and unless we're deleting the session data, don't save anything if there isn't a cart
904
+		if ($this->request->isBot() || (! $clear_session && ! $this->cart() instanceof EE_Cart)) {
905
+			return false;
906
+		}
907
+		$transaction = $this->transaction();
908
+		if ($transaction instanceof EE_Transaction) {
909
+			if (! $transaction->ID()) {
910
+				$transaction->save();
911
+			}
912
+			$this->_session_data['transaction'] = $transaction->ID();
913
+		}
914
+		// then serialize all of our session data
915
+		$session_data = serialize($this->_session_data);
916
+		// do we need to also encode it to avoid corrupted data when saved to the db?
917
+		$session_data = $this->_use_encryption
918
+			? $this->encryption->base64_string_encode($session_data)
919
+			: $session_data;
920
+		// maybe save hash check
921
+		if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
922
+			$this->cache_storage->add(
923
+				EE_Session::hash_check_prefix . $this->_sid,
924
+				md5($session_data),
925
+				$this->session_lifespan->inSeconds()
926
+			);
927
+		}
928
+		// we're using the Transient API for storing session data,
929
+		return $this->cache_storage->add(
930
+			EE_Session::session_id_prefix . $this->_sid,
931
+			$session_data,
932
+			$this->session_lifespan->inSeconds()
933
+		);
934
+	}
935
+
936
+
937
+	/**
938
+	 * @get    the full page request the visitor is accessing
939
+	 * @access public
940
+	 * @return string
941
+	 */
942
+	public function _get_page_visit()
943
+	{
944
+		$page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
945
+		// check for request url
946
+		if (isset($_SERVER['REQUEST_URI'])) {
947
+			$http_host   = '';
948
+			$page_id     = '?';
949
+			$e_reg       = '';
950
+			$request_uri = esc_url($_SERVER['REQUEST_URI']);
951
+			$ru_bits     = explode('?', $request_uri);
952
+			$request_uri = $ru_bits[0];
953
+			// check for and grab host as well
954
+			if (isset($_SERVER['HTTP_HOST'])) {
955
+				$http_host = esc_url($_SERVER['HTTP_HOST']);
956
+			}
957
+			// check for page_id in SERVER REQUEST
958
+			if (isset($_REQUEST['page_id'])) {
959
+				// rebuild $e_reg without any of the extra parameters
960
+				$page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
961
+			}
962
+			// check for $e_reg in SERVER REQUEST
963
+			if (isset($_REQUEST['ee'])) {
964
+				// rebuild $e_reg without any of the extra parameters
965
+				$e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
966
+			}
967
+			$page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
968
+		}
969
+		return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
970
+	}
971
+
972
+
973
+
974
+	/**
975
+	 * @the    current wp user id
976
+	 * @access public
977
+	 * @return int
978
+	 */
979
+	public function _wp_user_id()
980
+	{
981
+		// if I need to explain the following lines of code, then you shouldn't be looking at this!
982
+		$this->_wp_user_id = get_current_user_id();
983
+		return $this->_wp_user_id;
984
+	}
985
+
986
+
987
+
988
+	/**
989
+	 * Clear EE_Session data
990
+	 *
991
+	 * @access public
992
+	 * @param string $class
993
+	 * @param string $function
994
+	 * @return void
995
+	 * @throws EE_Error
996
+	 * @throws InvalidArgumentException
997
+	 * @throws InvalidDataTypeException
998
+	 * @throws InvalidInterfaceException
999
+	 */
1000
+	public function clear_session($class = '', $function = '')
1001
+	{
1002
+		do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1003
+		$this->reset_cart();
1004
+		$this->reset_checkout();
1005
+		$this->reset_transaction();
1006
+		// wipe out everything that isn't a default session datum
1007
+		$this->reset_data(array_keys($this->_session_data));
1008
+		// reset initial site access time and the session expiration
1009
+		$this->_set_init_access_and_expiration();
1010
+		$this->_save_session_to_db(true);
1011
+	}
1012
+
1013
+
1014
+	/**
1015
+	 * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1016
+	 *
1017
+	 * @param array|mixed $data_to_reset
1018
+	 * @param bool        $show_all_notices
1019
+	 * @return bool
1020
+	 */
1021
+	public function reset_data($data_to_reset = array(), $show_all_notices = false)
1022
+	{
1023
+		// if $data_to_reset is not in an array, then put it in one
1024
+		if (! is_array($data_to_reset)) {
1025
+			$data_to_reset = array($data_to_reset);
1026
+		}
1027
+		// nothing ??? go home!
1028
+		if (empty($data_to_reset)) {
1029
+			EE_Error::add_error(__('No session data could be reset, because no session var name was provided.',
1030
+				'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1031
+			return false;
1032
+		}
1033
+		$return_value = true;
1034
+		// since $data_to_reset is an array, cycle through the values
1035
+		foreach ($data_to_reset as $reset) {
1036
+
1037
+			// first check to make sure it is a valid session var
1038
+			if (isset($this->_session_data[ $reset ])) {
1039
+				// then check to make sure it is not a default var
1040
+				if (! array_key_exists($reset, $this->_default_session_vars)) {
1041
+					// remove session var
1042
+					unset($this->_session_data[ $reset ]);
1043
+					if ($show_all_notices) {
1044
+						EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'),
1045
+							$reset), __FILE__, __FUNCTION__, __LINE__);
1046
+					}
1047
+				} else {
1048
+					// yeeeeeeeeerrrrrrrrrrr OUT !!!!
1049
+					if ($show_all_notices) {
1050
+						EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
1051
+							'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1052
+					}
1053
+					$return_value = false;
1054
+				}
1055
+			} elseif ($show_all_notices) {
1056
+				// oops! that session var does not exist!
1057
+				EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.',
1058
+					'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1059
+				$return_value = false;
1060
+			}
1061
+		} // end of foreach
1062
+		return $return_value;
1063
+	}
1064
+
1065
+
1066
+
1067
+	/**
1068
+	 *   wp_loaded
1069
+	 *
1070
+	 * @access public
1071
+	 * @throws EE_Error
1072
+	 * @throws InvalidDataTypeException
1073
+	 * @throws InvalidInterfaceException
1074
+	 * @throws InvalidArgumentException
1075
+	 */
1076
+	public function wp_loaded()
1077
+	{
1078
+		if ($this->request->requestParamIsSet('clear_session')) {
1079
+			$this->clear_session(__CLASS__, __FUNCTION__);
1080
+		}
1081
+	}
1082
+
1083
+
1084
+
1085
+	/**
1086
+	 * Used to reset the entire object (for tests).
1087
+	 *
1088
+	 * @since 4.3.0
1089
+	 * @throws EE_Error
1090
+	 * @throws InvalidDataTypeException
1091
+	 * @throws InvalidInterfaceException
1092
+	 * @throws InvalidArgumentException
1093
+	 */
1094
+	public function reset_instance()
1095
+	{
1096
+		$this->clear_session();
1097
+		self::$_instance = null;
1098
+	}
1099
+
1100
+
1101
+
1102
+	public function configure_garbage_collection_filters()
1103
+	{
1104
+		// run old filter we had for controlling session cleanup
1105
+		$expired_session_transient_delete_query_limit = absint(
1106
+			apply_filters(
1107
+				'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1108
+				50
1109
+			)
1110
+		);
1111
+		// is there a value? or one that is different than the default 50 records?
1112
+		if ($expired_session_transient_delete_query_limit === 0) {
1113
+			// hook into TransientCacheStorage in case Session cleanup was turned off
1114
+			add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1115
+		} elseif ($expired_session_transient_delete_query_limit !== 50) {
1116
+			// or use that for the new transient cleanup query limit
1117
+			add_filter(
1118
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1119
+				function () use ($expired_session_transient_delete_query_limit)
1120
+				{
1121
+					return $expired_session_transient_delete_query_limit;
1122
+				}
1123
+			);
1124
+		}
1125
+	}
1126
+
1127
+
1128
+
1129
+	/**
1130
+	 * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1131
+	 * @param $data1
1132
+	 * @return string
1133
+	 */
1134
+	private function find_serialize_error($data1)
1135
+	{
1136
+		$error = '<pre>';
1137
+		$data2 = preg_replace_callback(
1138
+			'!s:(\d+):"(.*?)";!',
1139
+			function ($match)
1140
+			{
1141
+				return ($match[1] === strlen($match[2]))
1142
+					? $match[0]
1143
+					: 's:'
1144
+					  . strlen($match[2])
1145
+					  . ':"'
1146
+					  . $match[2]
1147
+					  . '";';
1148
+			},
1149
+			$data1
1150
+		);
1151
+		$max   = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1152
+		$error .= $data1 . PHP_EOL;
1153
+		$error .= $data2 . PHP_EOL;
1154
+		for ($i = 0; $i < $max; $i++) {
1155
+			if (@$data1[ $i ] !== @$data2[ $i ]) {
1156
+				$error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1157
+				$error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1158
+				$error  .= "\t-> Line Number = $i" . PHP_EOL;
1159
+				$start  = ($i - 20);
1160
+				$start  = ($start < 0) ? 0 : $start;
1161
+				$length = 40;
1162
+				$point  = $max - $i;
1163
+				if ($point < 20) {
1164
+					$rlength = 1;
1165
+					$rpoint  = -$point;
1166
+				} else {
1167
+					$rpoint  = $length - 20;
1168
+					$rlength = 1;
1169
+				}
1170
+				$error .= "\t-> Section Data1  = ";
1171
+				$error .= substr_replace(
1172
+					substr($data1, $start, $length),
1173
+					"<b style=\"color:green\">{$data1[ $i ]}</b>",
1174
+					$rpoint,
1175
+					$rlength
1176
+				);
1177
+				$error .= PHP_EOL;
1178
+				$error .= "\t-> Section Data2  = ";
1179
+				$error .= substr_replace(
1180
+					substr($data2, $start, $length),
1181
+					"<b style=\"color:red\">{$data2[ $i ]}</b>",
1182
+					$rpoint,
1183
+					$rlength
1184
+				);
1185
+				$error .= PHP_EOL;
1186
+			}
1187
+		}
1188
+		$error .= '</pre>';
1189
+		return $error;
1190
+	}
1191
+
1192
+
1193
+	/**
1194
+	 * Saves an  array of settings used for configuring aspects of session behaviour
1195
+	 *
1196
+	 * @param array $updated_settings
1197
+	 */
1198
+	private function updateSessionSettings(array $updated_settings = array())
1199
+	{
1200
+		// add existing settings, but only if not included in incoming $updated_settings array
1201
+		$updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1202
+		update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * garbage_collection
1208
+	 */
1209
+	public function garbageCollection()
1210
+	{
1211
+		// only perform during regular requests if last garbage collection was over an hour ago
1212
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1213
+			$this->_last_gc = time();
1214
+			$this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1215
+			/** @type WPDB $wpdb */
1216
+			global $wpdb;
1217
+			// filter the query limit. Set to 0 to turn off garbage collection
1218
+			$expired_session_transient_delete_query_limit = absint(
1219
+				apply_filters(
1220
+					'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1221
+					50
1222
+				)
1223
+			);
1224
+			// non-zero LIMIT means take out the trash
1225
+			if ($expired_session_transient_delete_query_limit) {
1226
+				$session_key    = str_replace('_', '\_', EE_Session::session_id_prefix);
1227
+				$hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1228
+				// since transient expiration timestamps are set in the future, we can compare against NOW
1229
+				// but we only want to pick up any trash that's been around for more than a day
1230
+				$expiration = time() - DAY_IN_SECONDS;
1231
+				$SQL        = "
1232 1232
                     SELECT option_name
1233 1233
                     FROM {$wpdb->options}
1234 1234
                     WHERE
@@ -1237,19 +1237,19 @@  discard block
 block discarded – undo
1237 1237
                     AND option_value < {$expiration}
1238 1238
                     LIMIT {$expired_session_transient_delete_query_limit}
1239 1239
                 ";
1240
-                // produces something like:
1241
-                // SELECT option_name FROM wp_options
1242
-                // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1243
-                // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1244
-                // AND option_value < 1508368198 LIMIT 50
1245
-                $expired_sessions = $wpdb->get_col($SQL);
1246
-                // valid results?
1247
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1248
-                    $this->cache_storage->deleteMany($expired_sessions, true);
1249
-                }
1250
-            }
1251
-        }
1252
-    }
1240
+				// produces something like:
1241
+				// SELECT option_name FROM wp_options
1242
+				// WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1243
+				// OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1244
+				// AND option_value < 1508368198 LIMIT 50
1245
+				$expired_sessions = $wpdb->get_col($SQL);
1246
+				// valid results?
1247
+				if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1248
+					$this->cache_storage->deleteMany($expired_sessions, true);
1249
+				}
1250
+			}
1251
+		}
1252
+	}
1253 1253
 
1254 1254
 
1255 1255
 
Please login to merge, or discard this patch.
Spacing   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
         // check if class object is instantiated
187 187
         // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
188 188
         // add_filter( 'FHEE_load_EE_Session', '__return_false' );
189
-        if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
189
+        if ( ! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
190 190
             self::$_instance = new self(
191 191
                 $cache_storage,
192 192
                 $lifespan,
@@ -219,21 +219,21 @@  discard block
 block discarded – undo
219 219
         // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
220 220
         // (which currently fires on the init hook at priority 9),
221 221
         // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
222
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
222
+        if ( ! apply_filters('FHEE_load_EE_Session', true)) {
223 223
             return;
224 224
         }
225 225
         $this->session_lifespan = $lifespan;
226 226
         $this->request          = $request;
227
-        if (! defined('ESPRESSO_SESSION')) {
227
+        if ( ! defined('ESPRESSO_SESSION')) {
228 228
             define('ESPRESSO_SESSION', true);
229 229
         }
230 230
         // retrieve session options from db
231 231
         $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
232
-        if (! empty($session_settings)) {
232
+        if ( ! empty($session_settings)) {
233 233
             // cycle though existing session options
234 234
             foreach ($session_settings as $var_name => $session_setting) {
235 235
                 // set values for class properties
236
-                $var_name          = '_' . $var_name;
236
+                $var_name          = '_'.$var_name;
237 237
                 $this->{$var_name} = $session_setting;
238 238
             }
239 239
         }
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
     public function open_session()
295 295
     {
296 296
         // check for existing session and retrieve it from db
297
-        if (! $this->_espresso_session()) {
297
+        if ( ! $this->_espresso_session()) {
298 298
             // or just start a new one
299 299
             $this->_create_espresso_session();
300 300
         }
@@ -346,7 +346,7 @@  discard block
 block discarded – undo
346 346
      */
347 347
     public function extend_expiration($time = 0)
348 348
     {
349
-        $time              = $time ? $time : $this->extension();
349
+        $time = $time ? $time : $this->extension();
350 350
         $this->_expiration += absint($time);
351 351
     }
352 352
 
@@ -373,9 +373,9 @@  discard block
 block discarded – undo
373 373
         // set some defaults
374 374
         foreach ($this->_default_session_vars as $key => $default_var) {
375 375
             if (is_array($default_var)) {
376
-                $this->_session_data[ $key ] = array();
376
+                $this->_session_data[$key] = array();
377 377
             } else {
378
-                $this->_session_data[ $key ] = '';
378
+                $this->_session_data[$key] = '';
379 379
             }
380 380
         }
381 381
     }
@@ -516,8 +516,8 @@  discard block
 block discarded – undo
516 516
             $this->reset_checkout();
517 517
             $this->reset_transaction();
518 518
         }
519
-        if (! empty($key)) {
520
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
519
+        if ( ! empty($key)) {
520
+            return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null;
521 521
         }
522 522
         return $this->_session_data;
523 523
     }
@@ -539,12 +539,12 @@  discard block
 block discarded – undo
539 539
             return false;
540 540
         }
541 541
         foreach ($data as $key => $value) {
542
-            if (isset($this->_default_session_vars[ $key ])) {
542
+            if (isset($this->_default_session_vars[$key])) {
543 543
                 EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
544 544
                     'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__);
545 545
                 return false;
546 546
             }
547
-            $this->_session_data[ $key ] = $value;
547
+            $this->_session_data[$key] = $value;
548 548
         }
549 549
         return true;
550 550
     }
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
         $this->_user_agent = $this->request->userAgent();
579 579
         // now let's retrieve what's in the db
580 580
         $session_data = $this->_retrieve_session_data();
581
-        if (! empty($session_data)) {
581
+        if ( ! empty($session_data)) {
582 582
             // get the current time in UTC
583 583
             $this->_time = $this->_time !== null ? $this->_time : time();
584 584
             // and reset the session expiration
@@ -589,7 +589,7 @@  discard block
 block discarded – undo
589 589
             // set initial site access time and the session expiration
590 590
             $this->_set_init_access_and_expiration();
591 591
             // set referer
592
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
592
+            $this->_session_data['pages_visited'][$this->_session_data['init_access']] = isset($_SERVER['HTTP_REFERER'])
593 593
                 ? esc_attr($_SERVER['HTTP_REFERER'])
594 594
                 : '';
595 595
             // no previous session = go back and create one (on top of the data above)
@@ -627,7 +627,7 @@  discard block
 block discarded – undo
627 627
      */
628 628
     protected function _retrieve_session_data()
629 629
     {
630
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
630
+        $ssn_key = EE_Session::session_id_prefix.$this->_sid;
631 631
         try {
632 632
             // we're using WP's Transient API to store session data using the PHP session ID as the option name
633 633
             $session_data = $this->cache_storage->get($ssn_key, false);
@@ -636,7 +636,7 @@  discard block
 block discarded – undo
636 636
             }
637 637
             if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
638 638
                 $hash_check = $this->cache_storage->get(
639
-                    EE_Session::hash_check_prefix . $this->_sid,
639
+                    EE_Session::hash_check_prefix.$this->_sid,
640 640
                     false
641 641
                 );
642 642
                 if ($hash_check && $hash_check !== md5($session_data)) {
@@ -646,7 +646,7 @@  discard block
 block discarded – undo
646 646
                                 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
647 647
                                 'event_espresso'
648 648
                             ),
649
-                            EE_Session::session_id_prefix . $this->_sid
649
+                            EE_Session::session_id_prefix.$this->_sid
650 650
                         ),
651 651
                         __FILE__, __FUNCTION__, __LINE__
652 652
                     );
@@ -655,21 +655,21 @@  discard block
 block discarded – undo
655 655
         } catch (Exception $e) {
656 656
             // let's just eat that error for now and attempt to correct any corrupted data
657 657
             global $wpdb;
658
-            $row          = $wpdb->get_row(
658
+            $row = $wpdb->get_row(
659 659
                 $wpdb->prepare(
660 660
                     "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
661
-                    '_transient_' . $ssn_key
661
+                    '_transient_'.$ssn_key
662 662
                 )
663 663
             );
664 664
             $session_data = is_object($row) ? $row->option_value : null;
665 665
             if ($session_data) {
666 666
                 $session_data = preg_replace_callback(
667 667
                     '!s:(d+):"(.*?)";!',
668
-                    function ($match)
668
+                    function($match)
669 669
                     {
670 670
                         return $match[1] === strlen($match[2])
671 671
                             ? $match[0]
672
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
672
+                            : 's:'.strlen($match[2]).':"'.$match[2].'";';
673 673
                     },
674 674
                     $session_data
675 675
                 );
@@ -680,7 +680,7 @@  discard block
 block discarded – undo
680 680
         $session_data = $this->encryption instanceof EE_Encryption
681 681
             ? $this->encryption->base64_string_decode($session_data)
682 682
             : $session_data;
683
-        if (! is_array($session_data)) {
683
+        if ( ! is_array($session_data)) {
684 684
             try {
685 685
                 $session_data = maybe_unserialize($session_data);
686 686
             } catch (Exception $e) {
@@ -694,21 +694,21 @@  discard block
 block discarded – undo
694 694
                       . '</pre><br>'
695 695
                       . $this->find_serialize_error($session_data)
696 696
                     : '';
697
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
697
+                $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
698 698
                 throw new InvalidSessionDataException($msg, 0, $e);
699 699
             }
700 700
         }
701 701
         // just a check to make sure the session array is indeed an array
702
-        if (! is_array($session_data)) {
702
+        if ( ! is_array($session_data)) {
703 703
             // no?!?! then something is wrong
704 704
             $msg = esc_html__(
705 705
                 'The session data is missing, invalid, or corrupted.',
706 706
                 'event_espresso'
707 707
             );
708 708
             $msg .= WP_DEBUG
709
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
709
+                ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data)
710 710
                 : '';
711
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
711
+            $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
712 712
             throw new InvalidSessionDataException($msg);
713 713
         }
714 714
         if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
@@ -736,7 +736,7 @@  discard block
 block discarded – undo
736 736
         if (isset($_REQUEST['EESID'])) {
737 737
             $session_id = sanitize_text_field($_REQUEST['EESID']);
738 738
         } else {
739
-            $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
739
+            $session_id = md5(session_id().get_current_blog_id().$this->_get_sid_salt());
740 740
         }
741 741
         return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
742 742
     }
@@ -844,19 +844,19 @@  discard block
 block discarded – undo
844 844
                     $page_visit = $this->_get_page_visit();
845 845
                     if ($page_visit) {
846 846
                         // set pages visited where the first will be the http referrer
847
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
847
+                        $this->_session_data['pages_visited'][$this->_time] = $page_visit;
848 848
                         // we'll only save the last 10 page visits.
849 849
                         $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
850 850
                     }
851 851
                     break;
852 852
                 default :
853 853
                     // carry any other data over
854
-                    $session_data[ $key ] = $this->_session_data[ $key ];
854
+                    $session_data[$key] = $this->_session_data[$key];
855 855
             }
856 856
         }
857 857
         $this->_session_data = $session_data;
858 858
         // creating a new session does not require saving to the db just yet
859
-        if (! $new_session) {
859
+        if ( ! $new_session) {
860 860
             // ready? let's save
861 861
             if ($this->_save_session_to_db()) {
862 862
                 return true;
@@ -901,12 +901,12 @@  discard block
 block discarded – undo
901 901
     {
902 902
         // don't save sessions for crawlers
903 903
         // and unless we're deleting the session data, don't save anything if there isn't a cart
904
-        if ($this->request->isBot() || (! $clear_session && ! $this->cart() instanceof EE_Cart)) {
904
+        if ($this->request->isBot() || ( ! $clear_session && ! $this->cart() instanceof EE_Cart)) {
905 905
             return false;
906 906
         }
907 907
         $transaction = $this->transaction();
908 908
         if ($transaction instanceof EE_Transaction) {
909
-            if (! $transaction->ID()) {
909
+            if ( ! $transaction->ID()) {
910 910
                 $transaction->save();
911 911
             }
912 912
             $this->_session_data['transaction'] = $transaction->ID();
@@ -920,14 +920,14 @@  discard block
 block discarded – undo
920 920
         // maybe save hash check
921 921
         if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
922 922
             $this->cache_storage->add(
923
-                EE_Session::hash_check_prefix . $this->_sid,
923
+                EE_Session::hash_check_prefix.$this->_sid,
924 924
                 md5($session_data),
925 925
                 $this->session_lifespan->inSeconds()
926 926
             );
927 927
         }
928 928
         // we're using the Transient API for storing session data,
929 929
         return $this->cache_storage->add(
930
-            EE_Session::session_id_prefix . $this->_sid,
930
+            EE_Session::session_id_prefix.$this->_sid,
931 931
             $session_data,
932 932
             $this->session_lifespan->inSeconds()
933 933
         );
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
      */
942 942
     public function _get_page_visit()
943 943
     {
944
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
944
+        $page_visit = home_url('/').'wp-admin/admin-ajax.php';
945 945
         // check for request url
946 946
         if (isset($_SERVER['REQUEST_URI'])) {
947 947
             $http_host   = '';
@@ -957,14 +957,14 @@  discard block
 block discarded – undo
957 957
             // check for page_id in SERVER REQUEST
958 958
             if (isset($_REQUEST['page_id'])) {
959 959
                 // rebuild $e_reg without any of the extra parameters
960
-                $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
960
+                $page_id = '?page_id='.esc_attr($_REQUEST['page_id']).'&amp;';
961 961
             }
962 962
             // check for $e_reg in SERVER REQUEST
963 963
             if (isset($_REQUEST['ee'])) {
964 964
                 // rebuild $e_reg without any of the extra parameters
965
-                $e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
965
+                $e_reg = 'ee='.esc_attr($_REQUEST['ee']);
966 966
             }
967
-            $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
967
+            $page_visit = rtrim($http_host.$request_uri.$page_id.$e_reg, '?');
968 968
         }
969 969
         return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
970 970
     }
@@ -999,7 +999,7 @@  discard block
 block discarded – undo
999 999
      */
1000 1000
     public function clear_session($class = '', $function = '')
1001 1001
     {
1002
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1002
+        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()');
1003 1003
         $this->reset_cart();
1004 1004
         $this->reset_checkout();
1005 1005
         $this->reset_transaction();
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
     public function reset_data($data_to_reset = array(), $show_all_notices = false)
1022 1022
     {
1023 1023
         // if $data_to_reset is not in an array, then put it in one
1024
-        if (! is_array($data_to_reset)) {
1024
+        if ( ! is_array($data_to_reset)) {
1025 1025
             $data_to_reset = array($data_to_reset);
1026 1026
         }
1027 1027
         // nothing ??? go home!
@@ -1035,11 +1035,11 @@  discard block
 block discarded – undo
1035 1035
         foreach ($data_to_reset as $reset) {
1036 1036
 
1037 1037
             // first check to make sure it is a valid session var
1038
-            if (isset($this->_session_data[ $reset ])) {
1038
+            if (isset($this->_session_data[$reset])) {
1039 1039
                 // then check to make sure it is not a default var
1040
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1040
+                if ( ! array_key_exists($reset, $this->_default_session_vars)) {
1041 1041
                     // remove session var
1042
-                    unset($this->_session_data[ $reset ]);
1042
+                    unset($this->_session_data[$reset]);
1043 1043
                     if ($show_all_notices) {
1044 1044
                         EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'),
1045 1045
                             $reset), __FILE__, __FUNCTION__, __LINE__);
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
             // or use that for the new transient cleanup query limit
1117 1117
             add_filter(
1118 1118
                 'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1119
-                function () use ($expired_session_transient_delete_query_limit)
1119
+                function() use ($expired_session_transient_delete_query_limit)
1120 1120
                 {
1121 1121
                     return $expired_session_transient_delete_query_limit;
1122 1122
                 }
@@ -1136,7 +1136,7 @@  discard block
 block discarded – undo
1136 1136
         $error = '<pre>';
1137 1137
         $data2 = preg_replace_callback(
1138 1138
             '!s:(\d+):"(.*?)";!',
1139
-            function ($match)
1139
+            function($match)
1140 1140
             {
1141 1141
                 return ($match[1] === strlen($match[2]))
1142 1142
                     ? $match[0]
@@ -1148,14 +1148,14 @@  discard block
 block discarded – undo
1148 1148
             },
1149 1149
             $data1
1150 1150
         );
1151
-        $max   = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1152
-        $error .= $data1 . PHP_EOL;
1153
-        $error .= $data2 . PHP_EOL;
1151
+        $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1152
+        $error .= $data1.PHP_EOL;
1153
+        $error .= $data2.PHP_EOL;
1154 1154
         for ($i = 0; $i < $max; $i++) {
1155
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1156
-                $error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1157
-                $error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1158
-                $error  .= "\t-> Line Number = $i" . PHP_EOL;
1155
+            if (@$data1[$i] !== @$data2[$i]) {
1156
+                $error  .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL;
1157
+                $error  .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL;
1158
+                $error  .= "\t-> Line Number = $i".PHP_EOL;
1159 1159
                 $start  = ($i - 20);
1160 1160
                 $start  = ($start < 0) ? 0 : $start;
1161 1161
                 $length = 40;
@@ -1170,7 +1170,7 @@  discard block
 block discarded – undo
1170 1170
                 $error .= "\t-> Section Data1  = ";
1171 1171
                 $error .= substr_replace(
1172 1172
                     substr($data1, $start, $length),
1173
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1173
+                    "<b style=\"color:green\">{$data1[$i]}</b>",
1174 1174
                     $rpoint,
1175 1175
                     $rlength
1176 1176
                 );
@@ -1178,7 +1178,7 @@  discard block
 block discarded – undo
1178 1178
                 $error .= "\t-> Section Data2  = ";
1179 1179
                 $error .= substr_replace(
1180 1180
                     substr($data2, $start, $length),
1181
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1181
+                    "<b style=\"color:red\">{$data2[$i]}</b>",
1182 1182
                     $rpoint,
1183 1183
                     $rlength
1184 1184
                 );
@@ -1209,7 +1209,7 @@  discard block
 block discarded – undo
1209 1209
     public function garbageCollection()
1210 1210
     {
1211 1211
         // only perform during regular requests if last garbage collection was over an hour ago
1212
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1212
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1213 1213
             $this->_last_gc = time();
1214 1214
             $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1215 1215
             /** @type WPDB $wpdb */
@@ -1244,7 +1244,7 @@  discard block
 block discarded – undo
1244 1244
                 // AND option_value < 1508368198 LIMIT 50
1245 1245
                 $expired_sessions = $wpdb->get_col($SQL);
1246 1246
                 // valid results?
1247
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1247
+                if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1248 1248
                     $this->cache_storage->deleteMany($expired_sessions, true);
1249 1249
                 }
1250 1250
             }
Please login to merge, or discard this patch.
core/EE_Error.core.php 2 patches
Spacing   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -102,14 +102,14 @@  discard block
 block discarded – undo
102 102
             default :
103 103
                 $to = get_option('admin_email');
104 104
         }
105
-        $subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
105
+        $subject = $type.' '.$message.' in '.EVENT_ESPRESSO_VERSION.' on '.site_url();
106 106
         $msg = EE_Error::_format_error($type, $message, $file, $line);
107 107
         if (function_exists('wp_mail')) {
108 108
             add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
109 109
             wp_mail($to, $subject, $msg);
110 110
         }
111 111
         echo '<div id="message" class="espresso-notices error"><p>';
112
-        echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
112
+        echo $type.': '.$message.'<br />'.$file.' line '.$line;
113 113
         echo '<br /></p></div>';
114 114
     }
115 115
 
@@ -334,7 +334,7 @@  discard block
 block discarded – undo
334 334
 	}
335 335
 </style>
336 336
 <div id="ee-error-message" class="error">';
337
-        if (! WP_DEBUG) {
337
+        if ( ! WP_DEBUG) {
338 338
             $output .= '
339 339
 	<p>';
340 340
         }
@@ -393,14 +393,14 @@  discard block
 block discarded – undo
393 393
                     $class_dsply = ! empty($class) ? $class : '&nbsp;';
394 394
                     $type_dsply = ! empty($type) ? $type : '&nbsp;';
395 395
                     $function_dsply = ! empty($function) ? $function : '&nbsp;';
396
-                    $args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
396
+                    $args_dsply = ! empty($args) ? '( '.$args.' )' : '';
397 397
                     $trace_details .= '
398 398
 					<tr>
399
-						<td align="right" class="' . $zebra . '">' . $nmbr_dsply . '</td>
400
-						<td align="right" class="' . $zebra . '">' . $line_dsply . '</td>
401
-						<td align="left" class="' . $zebra . '">' . $file_dsply . '</td>
402
-						<td align="left" class="' . $zebra . '">' . $class_dsply . '</td>
403
-						<td align="left" class="' . $zebra . '">' . $type_dsply . $function_dsply . $args_dsply . '</td>
399
+						<td align="right" class="' . $zebra.'">'.$nmbr_dsply.'</td>
400
+						<td align="right" class="' . $zebra.'">'.$line_dsply.'</td>
401
+						<td align="left" class="' . $zebra.'">'.$file_dsply.'</td>
402
+						<td align="left" class="' . $zebra.'">'.$class_dsply.'</td>
403
+						<td align="left" class="' . $zebra.'">'.$type_dsply.$function_dsply.$args_dsply.'</td>
404 404
 					</tr>';
405 405
                 }
406 406
                 $trace_details .= '
@@ -409,7 +409,7 @@  discard block
 block discarded – undo
409 409
             }
410 410
             $ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
411 411
             // add generic non-identifying messages for non-privileged users
412
-            if (! WP_DEBUG) {
412
+            if ( ! WP_DEBUG) {
413 413
                 $output .= '<span class="ee-error-user-msg-spn">'
414 414
                            . trim($ex['msg'])
415 415
                            . '</span> &nbsp; <sup>'
@@ -451,14 +451,14 @@  discard block
 block discarded – undo
451 451
                            . '-dv" class="ee-error-trace-dv" style="display: none;">
452 452
 				'
453 453
                            . $trace_details;
454
-                if (! empty($class)) {
454
+                if ( ! empty($class)) {
455 455
                     $output .= '
456 456
 				<div style="padding:3px; margin:0 0 1em; border:1px solid #666; background:#fff; border-radius:3px;">
457 457
 					<div style="padding:1em 2em; border:1px solid #666; background:#f9f9f9;">
458 458
 						<h3>Class Details</h3>';
459 459
                     $a = new ReflectionClass($class);
460 460
                     $output .= '
461
-						<pre>' . $a . '</pre>
461
+						<pre>' . $a.'</pre>
462 462
 					</div>
463 463
 				</div>';
464 464
                 }
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
         }
472 472
         // remove last linebreak
473 473
         $output = substr($output, 0, -6);
474
-        if (! WP_DEBUG) {
474
+        if ( ! WP_DEBUG) {
475 475
             $output .= '
476 476
 	</p>';
477 477
         }
@@ -498,20 +498,20 @@  discard block
 block discarded – undo
498 498
     private function _convert_args_to_string($arguments = array(), $array = false)
499 499
     {
500 500
         $arg_string = '';
501
-        if (! empty($arguments)) {
501
+        if ( ! empty($arguments)) {
502 502
             $args = array();
503 503
             foreach ($arguments as $arg) {
504
-                if (! empty($arg)) {
504
+                if ( ! empty($arg)) {
505 505
                     if (is_string($arg)) {
506
-                        $args[] = " '" . $arg . "'";
506
+                        $args[] = " '".$arg."'";
507 507
                     } elseif (is_array($arg)) {
508
-                        $args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
508
+                        $args[] = 'ARRAY('.$this->_convert_args_to_string($arg, true);
509 509
                     } elseif ($arg === null) {
510 510
                         $args[] = ' NULL';
511 511
                     } elseif (is_bool($arg)) {
512 512
                         $args[] = ($arg) ? ' TRUE' : ' FALSE';
513 513
                     } elseif (is_object($arg)) {
514
-                        $args[] = ' OBJECT ' . get_class($arg);
514
+                        $args[] = ' OBJECT '.get_class($arg);
515 515
                     } elseif (is_resource($arg)) {
516 516
                         $args[] = get_resource_type($arg);
517 517
                     } else {
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
     {
615 615
         if (empty($msg)) {
616 616
             EE_Error::doing_it_wrong(
617
-                'EE_Error::add_' . $type . '()',
617
+                'EE_Error::add_'.$type.'()',
618 618
                 sprintf(
619 619
                     __('Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
620 620
                         'event_espresso'),
@@ -650,11 +650,11 @@  discard block
 block discarded – undo
650 650
         do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
651 651
         $msg = WP_DEBUG ? $dev_msg : $user_msg;
652 652
         // add notice if message exists
653
-        if (! empty($msg)) {
653
+        if ( ! empty($msg)) {
654 654
             // get error code
655 655
             $notice_code = EE_Error::generate_error_code($file, $func, $line);
656 656
             if (WP_DEBUG && $type === 'errors') {
657
-                $msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
657
+                $msg .= '<br/><span class="tiny-text">'.$notice_code.'</span>';
658 658
             }
659 659
             // add notice. Index by code if it's not blank
660 660
             if ($notice_code) {
@@ -868,13 +868,13 @@  discard block
 block discarded – undo
868 868
         if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
869 869
             // combine messages
870 870
             $success_messages .= implode(self::$_espresso_notices['success'], '<br />');
871
-            $print_scripts    = true;
871
+            $print_scripts = true;
872 872
         }
873 873
         // check for attention messages
874 874
         if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
875 875
             // combine messages
876 876
             $attention_messages .= implode(self::$_espresso_notices['attention'], '<br />');
877
-            $print_scripts      = true;
877
+            $print_scripts = true;
878 878
         }
879 879
         // check for error messages
880 880
         if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
@@ -883,7 +883,7 @@  discard block
 block discarded – undo
883 883
                 : __('An error has occurred:<br />', 'event_espresso');
884 884
             // combine messages
885 885
             $error_messages .= implode(self::$_espresso_notices['errors'], '<br />');
886
-            $print_scripts  = true;
886
+            $print_scripts = true;
887 887
         }
888 888
         if ($format_output) {
889 889
             $notices = EE_Error::formatNoticesOutput(
@@ -924,16 +924,16 @@  discard block
 block discarded – undo
924 924
         $print_scripts = false;
925 925
         // grab any notices that have been previously saved
926 926
         $notices = EE_Error::getStoredNotices();
927
-        if (! empty($notices)) {
927
+        if ( ! empty($notices)) {
928 928
             foreach ($notices as $type => $notice) {
929 929
                 if (is_array($notice) && ! empty($notice)) {
930 930
                     // make sure that existing notice type is an array
931
-                    self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
932
-                                                        && ! empty(self::$_espresso_notices[ $type ])
933
-                        ? self::$_espresso_notices[ $type ]
931
+                    self::$_espresso_notices[$type] = is_array(self::$_espresso_notices[$type])
932
+                                                        && ! empty(self::$_espresso_notices[$type])
933
+                        ? self::$_espresso_notices[$type]
934 934
                         : array();
935 935
                     // add newly created notices to existing ones
936
-                    self::$_espresso_notices[ $type ] += $notice;
936
+                    self::$_espresso_notices[$type] += $notice;
937 937
                     $print_scripts = true;
938 938
                 }
939 939
             }
@@ -960,10 +960,10 @@  discard block
 block discarded – undo
960 960
             $css_id    = is_admin() ? 'message' : 'espresso-notices-success';
961 961
             $css_class = is_admin() ? 'updated fade' : 'success fade-away';
962 962
             //showMessage( $success_messages );
963
-            $notices .= '<div id="' . $css_id . '" '
964
-                        . 'class="espresso-notices ' . $css_class . '" '
963
+            $notices .= '<div id="'.$css_id.'" '
964
+                        . 'class="espresso-notices '.$css_class.'" '
965 965
                         . 'style="display:none;">'
966
-                        . '<p>' . $success_messages . '</p>'
966
+                        . '<p>'.$success_messages.'</p>'
967 967
                         . $close
968 968
                         . '</div>';
969 969
         }
@@ -971,10 +971,10 @@  discard block
 block discarded – undo
971 971
             $css_id    = is_admin() ? 'message' : 'espresso-notices-attention';
972 972
             $css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
973 973
             //showMessage( $error_messages, TRUE );
974
-            $notices .= '<div id="' . $css_id . '" '
975
-                        . 'class="espresso-notices ' . $css_class . '" '
974
+            $notices .= '<div id="'.$css_id.'" '
975
+                        . 'class="espresso-notices '.$css_class.'" '
976 976
                         . 'style="display:none;">'
977
-                        . '<p>' . $attention_messages . '</p>'
977
+                        . '<p>'.$attention_messages.'</p>'
978 978
                         . $close
979 979
                         . '</div>';
980 980
         }
@@ -982,10 +982,10 @@  discard block
 block discarded – undo
982 982
             $css_id    = is_admin() ? 'message' : 'espresso-notices-error';
983 983
             $css_class = is_admin() ? 'error' : 'error fade-away';
984 984
             //showMessage( $error_messages, TRUE );
985
-            $notices .= '<div id="' . $css_id . '" '
986
-                        . 'class="espresso-notices ' . $css_class . '" '
985
+            $notices .= '<div id="'.$css_id.'" '
986
+                        . 'class="espresso-notices '.$css_class.'" '
987 987
                         . 'style="display:none;">'
988
-                        . '<p>' . $error_messages . '</p>'
988
+                        . '<p>'.$error_messages.'</p>'
989 989
                         . $close
990 990
                         . '</div>';
991 991
         }
@@ -1003,7 +1003,7 @@  discard block
 block discarded – undo
1003 1003
      */
1004 1004
     private static function _print_scripts($force_print = false)
1005 1005
     {
1006
-        if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1006
+        if ( ! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1007 1007
             if (wp_script_is('ee_error_js', 'enqueued')) {
1008 1008
                 return '';
1009 1009
             }
@@ -1017,12 +1017,12 @@  discard block
 block discarded – undo
1017 1017
             return '
1018 1018
 <script>
1019 1019
 /* <![CDATA[ */
1020
-var ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
1020
+var ee_settings = {"wp_debug":"' . WP_DEBUG.'"};
1021 1021
 /* ]]> */
1022 1022
 </script>
1023
-<script src="' . includes_url() . 'js/jquery/jquery.js" type="text/javascript"></script>
1024
-<script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1025
-<script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1023
+<script src="' . includes_url().'js/jquery/jquery.js" type="text/javascript"></script>
1024
+<script src="' . EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js'.'?ver='.espresso_version().'" type="text/javascript"></script>
1025
+<script src="' . EE_GLOBAL_ASSETS_URL.'scripts/EE_Error.js'.'?ver='.espresso_version().'" type="text/javascript"></script>
1026 1026
 ';
1027 1027
         }
1028 1028
         return '';
@@ -1053,8 +1053,8 @@  discard block
 block discarded – undo
1053 1053
     {
1054 1054
         $file       = explode('.', basename($file));
1055 1055
         $error_code = ! empty($file[0]) ? $file[0] : '';
1056
-        $error_code .= ! empty($func) ? ' - ' . $func : '';
1057
-        $error_code .= ! empty($line) ? ' - ' . $line : '';
1056
+        $error_code .= ! empty($func) ? ' - '.$func : '';
1057
+        $error_code .= ! empty($line) ? ' - '.$line : '';
1058 1058
         return $error_code;
1059 1059
     }
1060 1060
 
@@ -1074,18 +1074,18 @@  discard block
 block discarded – undo
1074 1074
         if (empty($ex)) {
1075 1075
             return;
1076 1076
         }
1077
-        if (! $time) {
1077
+        if ( ! $time) {
1078 1078
             $time = time();
1079 1079
         }
1080 1080
         $exception_log = '----------------------------------------------------------------------------------------'
1081 1081
                          . PHP_EOL;
1082
-        $exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1083
-        $exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1084
-        $exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1085
-        $exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1086
-        $exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1087
-        $exception_log .= 'Stack trace: ' . PHP_EOL;
1088
-        $exception_log .= $ex['string'] . PHP_EOL;
1082
+        $exception_log .= '['.date('Y-m-d H:i:s', $time).']  Exception Details'.PHP_EOL;
1083
+        $exception_log .= 'Message: '.$ex['msg'].PHP_EOL;
1084
+        $exception_log .= 'Code: '.$ex['code'].PHP_EOL;
1085
+        $exception_log .= 'File: '.$ex['file'].PHP_EOL;
1086
+        $exception_log .= 'Line No: '.$ex['line'].PHP_EOL;
1087
+        $exception_log .= 'Stack trace: '.PHP_EOL;
1088
+        $exception_log .= $ex['string'].PHP_EOL;
1089 1089
         $exception_log .= '----------------------------------------------------------------------------------------'
1090 1090
                           . PHP_EOL;
1091 1091
         try {
@@ -1258,14 +1258,14 @@  discard block
 block discarded – undo
1258 1258
     // js for error handling
1259 1259
     wp_register_script(
1260 1260
         'espresso_core',
1261
-        EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1261
+        EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js',
1262 1262
         array('jquery'),
1263 1263
         EVENT_ESPRESSO_VERSION,
1264 1264
         false
1265 1265
     );
1266 1266
     wp_register_script(
1267 1267
         'ee_error_js',
1268
-        EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1268
+        EE_GLOBAL_ASSETS_URL.'scripts/EE_Error.js',
1269 1269
         array('espresso_core'),
1270 1270
         EVENT_ESPRESSO_VERSION,
1271 1271
         false
Please login to merge, or discard this patch.
Indentation   +1142 added lines, -1142 removed lines patch added patch discarded remove patch
@@ -11,8 +11,8 @@  discard block
 block discarded – undo
11 11
 // if you're a dev and want to receive all errors via email
12 12
 // add this to your wp-config.php: define( 'EE_ERROR_EMAILS', TRUE );
13 13
 if (defined('WP_DEBUG') && WP_DEBUG === true && defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS === true) {
14
-    set_error_handler(array('EE_Error', 'error_handler'));
15
-    register_shutdown_function(array('EE_Error', 'fatal_error_handler'));
14
+	set_error_handler(array('EE_Error', 'error_handler'));
15
+	register_shutdown_function(array('EE_Error', 'fatal_error_handler'));
16 16
 }
17 17
 
18 18
 
@@ -27,258 +27,258 @@  discard block
 block discarded – undo
27 27
 class EE_Error extends Exception
28 28
 {
29 29
 
30
-    const OPTIONS_KEY_NOTICES = 'ee_notices';
31
-
32
-
33
-    /**
34
-     * name of the file to log exceptions to
35
-     *
36
-     * @var string
37
-     */
38
-    private static $_exception_log_file = 'espresso_error_log.txt';
39
-
40
-    /**
41
-     *    stores details for all exception
42
-     *
43
-     * @var array
44
-     */
45
-    private static $_all_exceptions = array();
46
-
47
-    /**
48
-     *    tracks number of errors
49
-     *
50
-     * @var int
51
-     */
52
-    private static $_error_count = 0;
53
-
54
-    /**
55
-     * @var array $_espresso_notices
56
-     */
57
-    private static $_espresso_notices = array('success' => false, 'errors' => false, 'attention' => false);
58
-
59
-
60
-
61
-    /**
62
-     * @override default exception handling
63
-     * @param string         $message
64
-     * @param int            $code
65
-     * @param Exception|null $previous
66
-     */
67
-    public function __construct($message, $code = 0, Exception $previous = null)
68
-    {
69
-        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
70
-            parent::__construct($message, $code);
71
-        } else {
72
-            parent::__construct($message, $code, $previous);
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     *    error_handler
79
-     *
80
-     * @param $code
81
-     * @param $message
82
-     * @param $file
83
-     * @param $line
84
-     * @return void
85
-     */
86
-    public static function error_handler($code, $message, $file, $line)
87
-    {
88
-        $type = EE_Error::error_type($code);
89
-        $site = site_url();
90
-        switch ($site) {
91
-            case 'http://ee4.eventespresso.com/' :
92
-            case 'http://ee4decaf.eventespresso.com/' :
93
-            case 'http://ee4hf.eventespresso.com/' :
94
-            case 'http://ee4a.eventespresso.com/' :
95
-            case 'http://ee4ad.eventespresso.com/' :
96
-            case 'http://ee4b.eventespresso.com/' :
97
-            case 'http://ee4bd.eventespresso.com/' :
98
-            case 'http://ee4d.eventespresso.com/' :
99
-            case 'http://ee4dd.eventespresso.com/' :
100
-                $to = '[email protected]';
101
-                break;
102
-            default :
103
-                $to = get_option('admin_email');
104
-        }
105
-        $subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
106
-        $msg = EE_Error::_format_error($type, $message, $file, $line);
107
-        if (function_exists('wp_mail')) {
108
-            add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
109
-            wp_mail($to, $subject, $msg);
110
-        }
111
-        echo '<div id="message" class="espresso-notices error"><p>';
112
-        echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
113
-        echo '<br /></p></div>';
114
-    }
115
-
116
-
117
-
118
-    /**
119
-     * error_type
120
-     * http://www.php.net/manual/en/errorfunc.constants.php#109430
121
-     *
122
-     * @param $code
123
-     * @return string
124
-     */
125
-    public static function error_type($code)
126
-    {
127
-        switch ($code) {
128
-            case E_ERROR: // 1 //
129
-                return 'E_ERROR';
130
-            case E_WARNING: // 2 //
131
-                return 'E_WARNING';
132
-            case E_PARSE: // 4 //
133
-                return 'E_PARSE';
134
-            case E_NOTICE: // 8 //
135
-                return 'E_NOTICE';
136
-            case E_CORE_ERROR: // 16 //
137
-                return 'E_CORE_ERROR';
138
-            case E_CORE_WARNING: // 32 //
139
-                return 'E_CORE_WARNING';
140
-            case E_COMPILE_ERROR: // 64 //
141
-                return 'E_COMPILE_ERROR';
142
-            case E_COMPILE_WARNING: // 128 //
143
-                return 'E_COMPILE_WARNING';
144
-            case E_USER_ERROR: // 256 //
145
-                return 'E_USER_ERROR';
146
-            case E_USER_WARNING: // 512 //
147
-                return 'E_USER_WARNING';
148
-            case E_USER_NOTICE: // 1024 //
149
-                return 'E_USER_NOTICE';
150
-            case E_STRICT: // 2048 //
151
-                return 'E_STRICT';
152
-            case E_RECOVERABLE_ERROR: // 4096 //
153
-                return 'E_RECOVERABLE_ERROR';
154
-            case E_DEPRECATED: // 8192 //
155
-                return 'E_DEPRECATED';
156
-            case E_USER_DEPRECATED: // 16384 //
157
-                return 'E_USER_DEPRECATED';
158
-            case E_ALL: // 16384 //
159
-                return 'E_ALL';
160
-        }
161
-        return '';
162
-    }
163
-
164
-
165
-
166
-    /**
167
-     *    fatal_error_handler
168
-     *
169
-     * @return void
170
-     */
171
-    public static function fatal_error_handler()
172
-    {
173
-        $last_error = error_get_last();
174
-        if ($last_error['type'] === E_ERROR) {
175
-            EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
176
-        }
177
-    }
178
-
179
-
180
-
181
-    /**
182
-     * _format_error
183
-     *
184
-     * @param $code
185
-     * @param $message
186
-     * @param $file
187
-     * @param $line
188
-     * @return string
189
-     */
190
-    private static function _format_error($code, $message, $file, $line)
191
-    {
192
-        $html = "<table cellpadding='5'><thead bgcolor='#f8f8f8'><th>Item</th><th align='left'>Details</th></thead><tbody>";
193
-        $html .= "<tr valign='top'><td><b>Code</b></td><td>$code</td></tr>";
194
-        $html .= "<tr valign='top'><td><b>Error</b></td><td>$message</td></tr>";
195
-        $html .= "<tr valign='top'><td><b>File</b></td><td>$file</td></tr>";
196
-        $html .= "<tr valign='top'><td><b>Line</b></td><td>$line</td></tr>";
197
-        $html .= '</tbody></table>';
198
-        return $html;
199
-    }
200
-
201
-
202
-
203
-    /**
204
-     * set_content_type
205
-     *
206
-     * @param $content_type
207
-     * @return string
208
-     */
209
-    public static function set_content_type($content_type)
210
-    {
211
-        return 'text/html';
212
-    }
213
-
214
-
215
-
216
-    /**
217
-     * @return void
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    public function get_error()
222
-    {
223
-        if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
224
-            throw $this;
225
-        }
226
-        // get separate user and developer messages if they exist
227
-        $msg = explode('||', $this->getMessage());
228
-        $user_msg = $msg[0];
229
-        $dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
230
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
231
-        // add details to _all_exceptions array
232
-        $x_time = time();
233
-        self::$_all_exceptions[$x_time]['name'] = get_class($this);
234
-        self::$_all_exceptions[$x_time]['file'] = $this->getFile();
235
-        self::$_all_exceptions[$x_time]['line'] = $this->getLine();
236
-        self::$_all_exceptions[$x_time]['msg'] = $msg;
237
-        self::$_all_exceptions[$x_time]['code'] = $this->getCode();
238
-        self::$_all_exceptions[$x_time]['trace'] = $this->getTrace();
239
-        self::$_all_exceptions[$x_time]['string'] = $this->getTraceAsString();
240
-        self::$_error_count++;
241
-        //add_action( 'shutdown', array( $this, 'display_errors' ));
242
-        $this->display_errors();
243
-    }
244
-
245
-
246
-    /**
247
-     * @param bool   $check_stored
248
-     * @param string $type_to_check
249
-     * @return bool
250
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
251
-     * @throws \InvalidArgumentException
252
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
253
-     * @throws InvalidInterfaceException
254
-     */
255
-    public static function has_error($check_stored = false, $type_to_check = 'errors')
256
-    {
257
-        $has_error = isset(self::$_espresso_notices[$type_to_check])
258
-                     && ! empty(self::$_espresso_notices[$type_to_check])
259
-            ? true
260
-            : false;
261
-        if ($check_stored && ! $has_error) {
262
-            $notices = EE_Error::getStoredNotices();
263
-            foreach ($notices as $type => $notice) {
264
-                if ($type === $type_to_check && $notice) {
265
-                    return true;
266
-                }
267
-            }
268
-        }
269
-        return $has_error;
270
-    }
271
-
272
-
273
-
274
-    /**
275
-     * @echo string
276
-     * @throws \ReflectionException
277
-     */
278
-    public function display_errors()
279
-    {
280
-        $trace_details = '';
281
-        $output = '
30
+	const OPTIONS_KEY_NOTICES = 'ee_notices';
31
+
32
+
33
+	/**
34
+	 * name of the file to log exceptions to
35
+	 *
36
+	 * @var string
37
+	 */
38
+	private static $_exception_log_file = 'espresso_error_log.txt';
39
+
40
+	/**
41
+	 *    stores details for all exception
42
+	 *
43
+	 * @var array
44
+	 */
45
+	private static $_all_exceptions = array();
46
+
47
+	/**
48
+	 *    tracks number of errors
49
+	 *
50
+	 * @var int
51
+	 */
52
+	private static $_error_count = 0;
53
+
54
+	/**
55
+	 * @var array $_espresso_notices
56
+	 */
57
+	private static $_espresso_notices = array('success' => false, 'errors' => false, 'attention' => false);
58
+
59
+
60
+
61
+	/**
62
+	 * @override default exception handling
63
+	 * @param string         $message
64
+	 * @param int            $code
65
+	 * @param Exception|null $previous
66
+	 */
67
+	public function __construct($message, $code = 0, Exception $previous = null)
68
+	{
69
+		if (version_compare(PHP_VERSION, '5.3.0', '<')) {
70
+			parent::__construct($message, $code);
71
+		} else {
72
+			parent::__construct($message, $code, $previous);
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 *    error_handler
79
+	 *
80
+	 * @param $code
81
+	 * @param $message
82
+	 * @param $file
83
+	 * @param $line
84
+	 * @return void
85
+	 */
86
+	public static function error_handler($code, $message, $file, $line)
87
+	{
88
+		$type = EE_Error::error_type($code);
89
+		$site = site_url();
90
+		switch ($site) {
91
+			case 'http://ee4.eventespresso.com/' :
92
+			case 'http://ee4decaf.eventespresso.com/' :
93
+			case 'http://ee4hf.eventespresso.com/' :
94
+			case 'http://ee4a.eventespresso.com/' :
95
+			case 'http://ee4ad.eventespresso.com/' :
96
+			case 'http://ee4b.eventespresso.com/' :
97
+			case 'http://ee4bd.eventespresso.com/' :
98
+			case 'http://ee4d.eventespresso.com/' :
99
+			case 'http://ee4dd.eventespresso.com/' :
100
+				$to = '[email protected]';
101
+				break;
102
+			default :
103
+				$to = get_option('admin_email');
104
+		}
105
+		$subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
106
+		$msg = EE_Error::_format_error($type, $message, $file, $line);
107
+		if (function_exists('wp_mail')) {
108
+			add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
109
+			wp_mail($to, $subject, $msg);
110
+		}
111
+		echo '<div id="message" class="espresso-notices error"><p>';
112
+		echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
113
+		echo '<br /></p></div>';
114
+	}
115
+
116
+
117
+
118
+	/**
119
+	 * error_type
120
+	 * http://www.php.net/manual/en/errorfunc.constants.php#109430
121
+	 *
122
+	 * @param $code
123
+	 * @return string
124
+	 */
125
+	public static function error_type($code)
126
+	{
127
+		switch ($code) {
128
+			case E_ERROR: // 1 //
129
+				return 'E_ERROR';
130
+			case E_WARNING: // 2 //
131
+				return 'E_WARNING';
132
+			case E_PARSE: // 4 //
133
+				return 'E_PARSE';
134
+			case E_NOTICE: // 8 //
135
+				return 'E_NOTICE';
136
+			case E_CORE_ERROR: // 16 //
137
+				return 'E_CORE_ERROR';
138
+			case E_CORE_WARNING: // 32 //
139
+				return 'E_CORE_WARNING';
140
+			case E_COMPILE_ERROR: // 64 //
141
+				return 'E_COMPILE_ERROR';
142
+			case E_COMPILE_WARNING: // 128 //
143
+				return 'E_COMPILE_WARNING';
144
+			case E_USER_ERROR: // 256 //
145
+				return 'E_USER_ERROR';
146
+			case E_USER_WARNING: // 512 //
147
+				return 'E_USER_WARNING';
148
+			case E_USER_NOTICE: // 1024 //
149
+				return 'E_USER_NOTICE';
150
+			case E_STRICT: // 2048 //
151
+				return 'E_STRICT';
152
+			case E_RECOVERABLE_ERROR: // 4096 //
153
+				return 'E_RECOVERABLE_ERROR';
154
+			case E_DEPRECATED: // 8192 //
155
+				return 'E_DEPRECATED';
156
+			case E_USER_DEPRECATED: // 16384 //
157
+				return 'E_USER_DEPRECATED';
158
+			case E_ALL: // 16384 //
159
+				return 'E_ALL';
160
+		}
161
+		return '';
162
+	}
163
+
164
+
165
+
166
+	/**
167
+	 *    fatal_error_handler
168
+	 *
169
+	 * @return void
170
+	 */
171
+	public static function fatal_error_handler()
172
+	{
173
+		$last_error = error_get_last();
174
+		if ($last_error['type'] === E_ERROR) {
175
+			EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
176
+		}
177
+	}
178
+
179
+
180
+
181
+	/**
182
+	 * _format_error
183
+	 *
184
+	 * @param $code
185
+	 * @param $message
186
+	 * @param $file
187
+	 * @param $line
188
+	 * @return string
189
+	 */
190
+	private static function _format_error($code, $message, $file, $line)
191
+	{
192
+		$html = "<table cellpadding='5'><thead bgcolor='#f8f8f8'><th>Item</th><th align='left'>Details</th></thead><tbody>";
193
+		$html .= "<tr valign='top'><td><b>Code</b></td><td>$code</td></tr>";
194
+		$html .= "<tr valign='top'><td><b>Error</b></td><td>$message</td></tr>";
195
+		$html .= "<tr valign='top'><td><b>File</b></td><td>$file</td></tr>";
196
+		$html .= "<tr valign='top'><td><b>Line</b></td><td>$line</td></tr>";
197
+		$html .= '</tbody></table>';
198
+		return $html;
199
+	}
200
+
201
+
202
+
203
+	/**
204
+	 * set_content_type
205
+	 *
206
+	 * @param $content_type
207
+	 * @return string
208
+	 */
209
+	public static function set_content_type($content_type)
210
+	{
211
+		return 'text/html';
212
+	}
213
+
214
+
215
+
216
+	/**
217
+	 * @return void
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	public function get_error()
222
+	{
223
+		if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
224
+			throw $this;
225
+		}
226
+		// get separate user and developer messages if they exist
227
+		$msg = explode('||', $this->getMessage());
228
+		$user_msg = $msg[0];
229
+		$dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
230
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
231
+		// add details to _all_exceptions array
232
+		$x_time = time();
233
+		self::$_all_exceptions[$x_time]['name'] = get_class($this);
234
+		self::$_all_exceptions[$x_time]['file'] = $this->getFile();
235
+		self::$_all_exceptions[$x_time]['line'] = $this->getLine();
236
+		self::$_all_exceptions[$x_time]['msg'] = $msg;
237
+		self::$_all_exceptions[$x_time]['code'] = $this->getCode();
238
+		self::$_all_exceptions[$x_time]['trace'] = $this->getTrace();
239
+		self::$_all_exceptions[$x_time]['string'] = $this->getTraceAsString();
240
+		self::$_error_count++;
241
+		//add_action( 'shutdown', array( $this, 'display_errors' ));
242
+		$this->display_errors();
243
+	}
244
+
245
+
246
+	/**
247
+	 * @param bool   $check_stored
248
+	 * @param string $type_to_check
249
+	 * @return bool
250
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
251
+	 * @throws \InvalidArgumentException
252
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
253
+	 * @throws InvalidInterfaceException
254
+	 */
255
+	public static function has_error($check_stored = false, $type_to_check = 'errors')
256
+	{
257
+		$has_error = isset(self::$_espresso_notices[$type_to_check])
258
+					 && ! empty(self::$_espresso_notices[$type_to_check])
259
+			? true
260
+			: false;
261
+		if ($check_stored && ! $has_error) {
262
+			$notices = EE_Error::getStoredNotices();
263
+			foreach ($notices as $type => $notice) {
264
+				if ($type === $type_to_check && $notice) {
265
+					return true;
266
+				}
267
+			}
268
+		}
269
+		return $has_error;
270
+	}
271
+
272
+
273
+
274
+	/**
275
+	 * @echo string
276
+	 * @throws \ReflectionException
277
+	 */
278
+	public function display_errors()
279
+	{
280
+		$trace_details = '';
281
+		$output = '
282 282
 <style type="text/css">
283 283
 	#ee-error-message {
284 284
 		max-width:90% !important;
@@ -334,21 +334,21 @@  discard block
 block discarded – undo
334 334
 	}
335 335
 </style>
336 336
 <div id="ee-error-message" class="error">';
337
-        if (! WP_DEBUG) {
338
-            $output .= '
337
+		if (! WP_DEBUG) {
338
+			$output .= '
339 339
 	<p>';
340
-        }
341
-        // cycle thru errors
342
-        foreach (self::$_all_exceptions as $time => $ex) {
343
-            $error_code = '';
344
-            // process trace info
345
-            if (empty($ex['trace'])) {
346
-                $trace_details .= __(
347
-                    'Sorry, but no trace information was available for this exception.',
348
-                    'event_espresso'
349
-                );
350
-            } else {
351
-                $trace_details .= '
340
+		}
341
+		// cycle thru errors
342
+		foreach (self::$_all_exceptions as $time => $ex) {
343
+			$error_code = '';
344
+			// process trace info
345
+			if (empty($ex['trace'])) {
346
+				$trace_details .= __(
347
+					'Sorry, but no trace information was available for this exception.',
348
+					'event_espresso'
349
+				);
350
+			} else {
351
+				$trace_details .= '
352 352
 			<div id="ee-trace-details">
353 353
 			<table width="100%" border="0" cellpadding="5" cellspacing="0">
354 354
 				<tr>
@@ -358,43 +358,43 @@  discard block
 block discarded – undo
358 358
 					<th scope="col" align="left">Class</th>
359 359
 					<th scope="col" align="left">Method( arguments )</th>
360 360
 				</tr>';
361
-                $last_on_stack = count($ex['trace']) - 1;
362
-                // reverse array so that stack is in proper chronological order
363
-                $sorted_trace = array_reverse($ex['trace']);
364
-                foreach ($sorted_trace as $nmbr => $trace) {
365
-                    $file = isset($trace['file']) ? $trace['file'] : '';
366
-                    $class = isset($trace['class']) ? $trace['class'] : '';
367
-                    $type = isset($trace['type']) ? $trace['type'] : '';
368
-                    $function = isset($trace['function']) ? $trace['function'] : '';
369
-                    $args = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
370
-                    $line = isset($trace['line']) ? $trace['line'] : '';
371
-                    $zebra = ($nmbr % 2) ? ' odd' : '';
372
-                    if (empty($file) && ! empty($class)) {
373
-                        $a = new ReflectionClass($class);
374
-                        $file = $a->getFileName();
375
-                        if (empty($line) && ! empty($function)) {
376
-                            try {
377
-                                //if $function is a closure, this throws an exception
378
-                                $b = new ReflectionMethod($class, $function);
379
-                                $line = $b->getStartLine();
380
-                            } catch (Exception $closure_exception) {
381
-                                $line = 'unknown';
382
-                            }
383
-                        }
384
-                    }
385
-                    if ($nmbr === $last_on_stack) {
386
-                        $file = $ex['file'] !== '' ? $ex['file'] : $file;
387
-                        $line = $ex['line'] !== '' ? $ex['line'] : $line;
388
-                        $error_code = self::generate_error_code($file, $trace['function'], $line);
389
-                    }
390
-                    $nmbr_dsply = ! empty($nmbr) ? $nmbr : '&nbsp;';
391
-                    $line_dsply = ! empty($line) ? $line : '&nbsp;';
392
-                    $file_dsply = ! empty($file) ? $file : '&nbsp;';
393
-                    $class_dsply = ! empty($class) ? $class : '&nbsp;';
394
-                    $type_dsply = ! empty($type) ? $type : '&nbsp;';
395
-                    $function_dsply = ! empty($function) ? $function : '&nbsp;';
396
-                    $args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
397
-                    $trace_details .= '
361
+				$last_on_stack = count($ex['trace']) - 1;
362
+				// reverse array so that stack is in proper chronological order
363
+				$sorted_trace = array_reverse($ex['trace']);
364
+				foreach ($sorted_trace as $nmbr => $trace) {
365
+					$file = isset($trace['file']) ? $trace['file'] : '';
366
+					$class = isset($trace['class']) ? $trace['class'] : '';
367
+					$type = isset($trace['type']) ? $trace['type'] : '';
368
+					$function = isset($trace['function']) ? $trace['function'] : '';
369
+					$args = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
370
+					$line = isset($trace['line']) ? $trace['line'] : '';
371
+					$zebra = ($nmbr % 2) ? ' odd' : '';
372
+					if (empty($file) && ! empty($class)) {
373
+						$a = new ReflectionClass($class);
374
+						$file = $a->getFileName();
375
+						if (empty($line) && ! empty($function)) {
376
+							try {
377
+								//if $function is a closure, this throws an exception
378
+								$b = new ReflectionMethod($class, $function);
379
+								$line = $b->getStartLine();
380
+							} catch (Exception $closure_exception) {
381
+								$line = 'unknown';
382
+							}
383
+						}
384
+					}
385
+					if ($nmbr === $last_on_stack) {
386
+						$file = $ex['file'] !== '' ? $ex['file'] : $file;
387
+						$line = $ex['line'] !== '' ? $ex['line'] : $line;
388
+						$error_code = self::generate_error_code($file, $trace['function'], $line);
389
+					}
390
+					$nmbr_dsply = ! empty($nmbr) ? $nmbr : '&nbsp;';
391
+					$line_dsply = ! empty($line) ? $line : '&nbsp;';
392
+					$file_dsply = ! empty($file) ? $file : '&nbsp;';
393
+					$class_dsply = ! empty($class) ? $class : '&nbsp;';
394
+					$type_dsply = ! empty($type) ? $type : '&nbsp;';
395
+					$function_dsply = ! empty($function) ? $function : '&nbsp;';
396
+					$args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
397
+					$trace_details .= '
398 398
 					<tr>
399 399
 						<td align="right" class="' . $zebra . '">' . $nmbr_dsply . '</td>
400 400
 						<td align="right" class="' . $zebra . '">' . $line_dsply . '</td>
@@ -402,633 +402,633 @@  discard block
 block discarded – undo
402 402
 						<td align="left" class="' . $zebra . '">' . $class_dsply . '</td>
403 403
 						<td align="left" class="' . $zebra . '">' . $type_dsply . $function_dsply . $args_dsply . '</td>
404 404
 					</tr>';
405
-                }
406
-                $trace_details .= '
405
+				}
406
+				$trace_details .= '
407 407
 			 </table>
408 408
 			</div>';
409
-            }
410
-            $ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
411
-            // add generic non-identifying messages for non-privileged users
412
-            if (! WP_DEBUG) {
413
-                $output .= '<span class="ee-error-user-msg-spn">'
414
-                           . trim($ex['msg'])
415
-                           . '</span> &nbsp; <sup>'
416
-                           . $ex['code']
417
-                           . '</sup><br />';
418
-            } else {
419
-                // or helpful developer messages if debugging is on
420
-                $output .= '
409
+			}
410
+			$ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
411
+			// add generic non-identifying messages for non-privileged users
412
+			if (! WP_DEBUG) {
413
+				$output .= '<span class="ee-error-user-msg-spn">'
414
+						   . trim($ex['msg'])
415
+						   . '</span> &nbsp; <sup>'
416
+						   . $ex['code']
417
+						   . '</sup><br />';
418
+			} else {
419
+				// or helpful developer messages if debugging is on
420
+				$output .= '
421 421
 		<div class="ee-error-dev-msg-dv">
422 422
 			<p class="ee-error-dev-msg-pg">
423 423
 				<strong class="ee-error-dev-msg-str">An '
424
-                           . $ex['name']
425
-                           . ' exception was thrown!</strong>  &nbsp; <span>code: '
426
-                           . $ex['code']
427
-                           . '</span><br />
424
+						   . $ex['name']
425
+						   . ' exception was thrown!</strong>  &nbsp; <span>code: '
426
+						   . $ex['code']
427
+						   . '</span><br />
428 428
 				<span class="big-text">"'
429
-                           . trim($ex['msg'])
430
-                           . '"</span><br/>
429
+						   . trim($ex['msg'])
430
+						   . '"</span><br/>
431 431
 				<a id="display-ee-error-trace-'
432
-                           . self::$_error_count
433
-                           . $time
434
-                           . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
435
-                           . self::$_error_count
436
-                           . $time
437
-                           . '">
432
+						   . self::$_error_count
433
+						   . $time
434
+						   . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
435
+						   . self::$_error_count
436
+						   . $time
437
+						   . '">
438 438
 					'
439
-                           . __('click to view backtrace and class/method details', 'event_espresso')
440
-                           . '
439
+						   . __('click to view backtrace and class/method details', 'event_espresso')
440
+						   . '
441 441
 				</a><br />
442 442
 				<span class="small-text lt-grey-text">'
443
-                           . $ex['file']
444
-                           . ' &nbsp; ( line no: '
445
-                           . $ex['line']
446
-                           . ' )</span>
443
+						   . $ex['file']
444
+						   . ' &nbsp; ( line no: '
445
+						   . $ex['line']
446
+						   . ' )</span>
447 447
 			</p>
448 448
 			<div id="ee-error-trace-'
449
-                           . self::$_error_count
450
-                           . $time
451
-                           . '-dv" class="ee-error-trace-dv" style="display: none;">
449
+						   . self::$_error_count
450
+						   . $time
451
+						   . '-dv" class="ee-error-trace-dv" style="display: none;">
452 452
 				'
453
-                           . $trace_details;
454
-                if (! empty($class)) {
455
-                    $output .= '
453
+						   . $trace_details;
454
+				if (! empty($class)) {
455
+					$output .= '
456 456
 				<div style="padding:3px; margin:0 0 1em; border:1px solid #666; background:#fff; border-radius:3px;">
457 457
 					<div style="padding:1em 2em; border:1px solid #666; background:#f9f9f9;">
458 458
 						<h3>Class Details</h3>';
459
-                    $a = new ReflectionClass($class);
460
-                    $output .= '
459
+					$a = new ReflectionClass($class);
460
+					$output .= '
461 461
 						<pre>' . $a . '</pre>
462 462
 					</div>
463 463
 				</div>';
464
-                }
465
-                $output .= '
464
+				}
465
+				$output .= '
466 466
 			</div>
467 467
 		</div>
468 468
 		<br />';
469
-            }
470
-            $this->write_to_error_log($time, $ex);
471
-        }
472
-        // remove last linebreak
473
-        $output = substr($output, 0, -6);
474
-        if (! WP_DEBUG) {
475
-            $output .= '
469
+			}
470
+			$this->write_to_error_log($time, $ex);
471
+		}
472
+		// remove last linebreak
473
+		$output = substr($output, 0, -6);
474
+		if (! WP_DEBUG) {
475
+			$output .= '
476 476
 	</p>';
477
-        }
478
-        $output .= '
477
+		}
478
+		$output .= '
479 479
 </div>';
480
-        $output .= self::_print_scripts(true);
481
-        if (defined('DOING_AJAX')) {
482
-            echo wp_json_encode(array('error' => $output));
483
-            exit();
484
-        }
485
-        echo $output;
486
-        die();
487
-    }
488
-
489
-
490
-
491
-    /**
492
-     *    generate string from exception trace args
493
-     *
494
-     * @param array $arguments
495
-     * @param bool  $array
496
-     * @return string
497
-     */
498
-    private function _convert_args_to_string($arguments = array(), $array = false)
499
-    {
500
-        $arg_string = '';
501
-        if (! empty($arguments)) {
502
-            $args = array();
503
-            foreach ($arguments as $arg) {
504
-                if (! empty($arg)) {
505
-                    if (is_string($arg)) {
506
-                        $args[] = " '" . $arg . "'";
507
-                    } elseif (is_array($arg)) {
508
-                        $args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
509
-                    } elseif ($arg === null) {
510
-                        $args[] = ' NULL';
511
-                    } elseif (is_bool($arg)) {
512
-                        $args[] = ($arg) ? ' TRUE' : ' FALSE';
513
-                    } elseif (is_object($arg)) {
514
-                        $args[] = ' OBJECT ' . get_class($arg);
515
-                    } elseif (is_resource($arg)) {
516
-                        $args[] = get_resource_type($arg);
517
-                    } else {
518
-                        $args[] = $arg;
519
-                    }
520
-                }
521
-            }
522
-            $arg_string = implode(', ', $args);
523
-        }
524
-        if ($array) {
525
-            $arg_string .= ' )';
526
-        }
527
-        return $arg_string;
528
-    }
529
-
530
-
531
-
532
-    /**
533
-     *    add error message
534
-     *
535
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
536
-     *                            separate messages for user || dev
537
-     * @param        string $file the file that the error occurred in - just use __FILE__
538
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
539
-     * @param        string $line the line number where the error occurred - just use __LINE__
540
-     * @return        void
541
-     */
542
-    public static function add_error($msg = null, $file = null, $func = null, $line = null)
543
-    {
544
-        self::_add_notice('errors', $msg, $file, $func, $line);
545
-        self::$_error_count++;
546
-    }
547
-
548
-
549
-
550
-    /**
551
-     * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
552
-     * adds an error
553
-     *
554
-     * @param string $msg
555
-     * @param string $file
556
-     * @param string $func
557
-     * @param string $line
558
-     * @throws EE_Error
559
-     */
560
-    public static function throw_exception_if_debugging($msg = null, $file = null, $func = null, $line = null)
561
-    {
562
-        if (WP_DEBUG) {
563
-            throw new EE_Error($msg);
564
-        }
565
-        EE_Error::add_error($msg, $file, $func, $line);
566
-    }
567
-
568
-
569
-
570
-    /**
571
-     *    add success message
572
-     *
573
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
574
-     *                            separate messages for user || dev
575
-     * @param        string $file the file that the error occurred in - just use __FILE__
576
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
577
-     * @param        string $line the line number where the error occurred - just use __LINE__
578
-     * @return        void
579
-     */
580
-    public static function add_success($msg = null, $file = null, $func = null, $line = null)
581
-    {
582
-        self::_add_notice('success', $msg, $file, $func, $line);
583
-    }
584
-
585
-
586
-
587
-    /**
588
-     *    add attention message
589
-     *
590
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
591
-     *                            separate messages for user || dev
592
-     * @param        string $file the file that the error occurred in - just use __FILE__
593
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
594
-     * @param        string $line the line number where the error occurred - just use __LINE__
595
-     * @return        void
596
-     */
597
-    public static function add_attention($msg = null, $file = null, $func = null, $line = null)
598
-    {
599
-        self::_add_notice('attention', $msg, $file, $func, $line);
600
-    }
601
-
602
-
603
-
604
-    /**
605
-     * @param string $type whether the message is for a success or error notification
606
-     * @param string $msg the message to display to users or developers
607
-     *                    - adding a double pipe || (OR) creates separate messages for user || dev
608
-     * @param string $file the file that the error occurred in - just use __FILE__
609
-     * @param string $func the function/method that the error occurred in - just use __FUNCTION__
610
-     * @param string $line the line number where the error occurred - just use __LINE__
611
-     * @return void
612
-     */
613
-    private static function _add_notice($type = 'success', $msg = '', $file = '', $func = '', $line = '')
614
-    {
615
-        if (empty($msg)) {
616
-            EE_Error::doing_it_wrong(
617
-                'EE_Error::add_' . $type . '()',
618
-                sprintf(
619
-                    __('Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
620
-                        'event_espresso'),
621
-                    $type,
622
-                    $file,
623
-                    $line
624
-                ),
625
-                EVENT_ESPRESSO_VERSION
626
-            );
627
-        }
628
-        if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
629
-            EE_Error::doing_it_wrong(
630
-                'EE_Error::add_error()',
631
-                __('You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
632
-                    'event_espresso'),
633
-                EVENT_ESPRESSO_VERSION
634
-            );
635
-        }
636
-        // get separate user and developer messages if they exist
637
-        $msg      = explode('||', $msg);
638
-        $user_msg = $msg[0];
639
-        $dev_msg  = isset($msg[1]) ? $msg[1] : $msg[0];
640
-        /**
641
-         * Do an action so other code can be triggered when a notice is created
642
-         *
643
-         * @param string $type     can be 'errors', 'attention', or 'success'
644
-         * @param string $user_msg message displayed to user when WP_DEBUG is off
645
-         * @param string $user_msg message displayed to user when WP_DEBUG is on
646
-         * @param string $file     file where error was generated
647
-         * @param string $func     function where error was generated
648
-         * @param string $line     line where error was generated
649
-         */
650
-        do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
651
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
652
-        // add notice if message exists
653
-        if (! empty($msg)) {
654
-            // get error code
655
-            $notice_code = EE_Error::generate_error_code($file, $func, $line);
656
-            if (WP_DEBUG && $type === 'errors') {
657
-                $msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
658
-            }
659
-            // add notice. Index by code if it's not blank
660
-            if ($notice_code) {
661
-                self::$_espresso_notices[$type][$notice_code] = $msg;
662
-            } else {
663
-                self::$_espresso_notices[$type][] = $msg;
664
-            }
665
-            add_action('wp_footer', array('EE_Error', 'enqueue_error_scripts'), 1);
666
-        }
667
-    }
668
-
669
-
670
-    /**
671
-     * in some case it may be necessary to overwrite the existing success messages
672
-     *
673
-     * @return        void
674
-     */
675
-    public static function overwrite_success()
676
-    {
677
-        self::$_espresso_notices['success'] = false;
678
-    }
679
-
680
-
681
-
682
-    /**
683
-     * in some case it may be necessary to overwrite the existing attention messages
684
-     *
685
-     * @return void
686
-     */
687
-    public static function overwrite_attention()
688
-    {
689
-        self::$_espresso_notices['attention'] = false;
690
-    }
691
-
692
-
693
-
694
-    /**
695
-     * in some case it may be necessary to overwrite the existing error messages
696
-     *
697
-     * @return void
698
-     */
699
-    public static function overwrite_errors()
700
-    {
701
-        self::$_espresso_notices['errors'] = false;
702
-    }
703
-
704
-
705
-
706
-    /**
707
-     * @return void
708
-     */
709
-    public static function reset_notices()
710
-    {
711
-        self::$_espresso_notices['success']   = false;
712
-        self::$_espresso_notices['attention'] = false;
713
-        self::$_espresso_notices['errors']    = false;
714
-    }
715
-
716
-
717
-
718
-    /**
719
-     * @return int
720
-     */
721
-    public static function has_notices()
722
-    {
723
-        $has_notices = 0;
724
-        // check for success messages
725
-        $has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])
726
-            ? 3
727
-            : $has_notices;
728
-        // check for attention messages
729
-        $has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])
730
-            ? 2
731
-            : $has_notices;
732
-        // check for error messages
733
-        $has_notices = self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])
734
-            ? 1
735
-            : $has_notices;
736
-        return $has_notices;
737
-    }
738
-
739
-
740
-    /**
741
-     * This simply returns non formatted error notices as they were sent into the EE_Error object.
742
-     *
743
-     * @since 4.9.0
744
-     * @return array
745
-     */
746
-    public static function get_vanilla_notices()
747
-    {
748
-        return array(
749
-            'success'   => isset(self::$_espresso_notices['success'])
750
-                ? self::$_espresso_notices['success']
751
-                : array(),
752
-            'attention' => isset(self::$_espresso_notices['attention'])
753
-                ? self::$_espresso_notices['attention']
754
-                : array(),
755
-            'errors'    => isset(self::$_espresso_notices['errors'])
756
-                ? self::$_espresso_notices['errors']
757
-                : array(),
758
-        );
759
-    }
760
-
761
-
762
-    /**
763
-     * @return array
764
-     * @throws InvalidArgumentException
765
-     * @throws InvalidDataTypeException
766
-     * @throws InvalidInterfaceException
767
-     */
768
-    public static function getStoredNotices()
769
-    {
770
-        if ($user_id = get_current_user_id()) {
771
-            // get notices for logged in user
772
-            $notices = get_user_option(EE_Error::OPTIONS_KEY_NOTICES, $user_id);
773
-            return is_array($notices) ? $notices : array();
774
-        }
775
-        if (EE_Session::isLoadedAndActive()) {
776
-            // get notices for user currently engaged in a session
777
-            $session_data = EE_Session::instance()->get_session_data(EE_Error::OPTIONS_KEY_NOTICES);
778
-            return is_array($session_data) ? $session_data : array();
779
-        }
780
-        // get global notices and hope they apply to the current site visitor
781
-        $notices = get_option(EE_Error::OPTIONS_KEY_NOTICES, array());
782
-        return is_array($notices) ? $notices : array();
783
-    }
784
-
785
-
786
-    /**
787
-     * @param array $notices
788
-     * @return bool
789
-     * @throws InvalidArgumentException
790
-     * @throws InvalidDataTypeException
791
-     * @throws InvalidInterfaceException
792
-     */
793
-    public static function storeNotices(array $notices)
794
-    {
795
-        if ($user_id = get_current_user_id()) {
796
-            // store notices for logged in user
797
-            return (bool) update_user_option(
798
-                $user_id,
799
-                EE_Error::OPTIONS_KEY_NOTICES,
800
-                $notices
801
-            );
802
-        }
803
-        if (EE_Session::isLoadedAndActive()) {
804
-            // store notices for user currently engaged in a session
805
-            return EE_Session::instance()->set_session_data(
806
-                array(EE_Error::OPTIONS_KEY_NOTICES => $notices)
807
-            );
808
-        }
809
-        // store global notices and hope they apply to the same site visitor on the next request
810
-        return update_option(EE_Error::OPTIONS_KEY_NOTICES, $notices);
811
-    }
812
-
813
-
814
-    /**
815
-     * @return bool|TRUE
816
-     * @throws InvalidArgumentException
817
-     * @throws InvalidDataTypeException
818
-     * @throws InvalidInterfaceException
819
-     */
820
-    public static function clearNotices()
821
-    {
822
-        if ($user_id = get_current_user_id()) {
823
-            // clear notices for logged in user
824
-            return (bool) update_user_option(
825
-                $user_id,
826
-                EE_Error::OPTIONS_KEY_NOTICES,
827
-                array()
828
-            );
829
-        }
830
-        if (EE_Session::isLoadedAndActive()) {
831
-            // clear notices for user currently engaged in a session
832
-            return EE_Session::instance()->reset_data(EE_Error::OPTIONS_KEY_NOTICES);
833
-        }
834
-        // clear global notices and hope none belonged to some for some other site visitor
835
-        return update_option(EE_Error::OPTIONS_KEY_NOTICES, array());
836
-    }
837
-
838
-
839
-    /**
840
-     * saves notices to the db for retrieval on next request
841
-     *
842
-     * @return void
843
-     * @throws InvalidArgumentException
844
-     * @throws InvalidDataTypeException
845
-     * @throws InvalidInterfaceException
846
-     */
847
-    public static function stashNoticesBeforeRedirect()
848
-    {
849
-        EE_Error::get_notices(false, true);
850
-    }
851
-
852
-
853
-    /**
854
-     * compile all error or success messages into one string
855
-     *
856
-     * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
857
-     * @param boolean $format_output            whether or not to format the messages for display in the WP admin
858
-     * @param boolean $save_to_transient        whether or not to save notices to the db for retrieval on next request
859
-     *                                          - ONLY do this just before redirecting
860
-     * @param boolean $remove_empty             whether or not to unset empty messages
861
-     * @return array
862
-     * @throws InvalidArgumentException
863
-     * @throws InvalidDataTypeException
864
-     * @throws InvalidInterfaceException
865
-     */
866
-    public static function get_notices($format_output = true, $save_to_transient = false, $remove_empty = true)
867
-    {
868
-        $success_messages   = '';
869
-        $attention_messages = '';
870
-        $error_messages     = '';
871
-        // either save notices to the db
872
-        if ($save_to_transient || isset($_REQUEST['activate-selected'])) {
873
-            self::$_espresso_notices = array_merge(
874
-                EE_Error::getStoredNotices(),
875
-                self::$_espresso_notices
876
-            );
877
-            EE_Error::storeNotices(self::$_espresso_notices);
878
-            return array();
879
-        }
880
-        $print_scripts = EE_Error::combineExistingAndNewNotices();
881
-        // check for success messages
882
-        if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
883
-            // combine messages
884
-            $success_messages .= implode(self::$_espresso_notices['success'], '<br />');
885
-            $print_scripts    = true;
886
-        }
887
-        // check for attention messages
888
-        if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
889
-            // combine messages
890
-            $attention_messages .= implode(self::$_espresso_notices['attention'], '<br />');
891
-            $print_scripts      = true;
892
-        }
893
-        // check for error messages
894
-        if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
895
-            $error_messages .= count(self::$_espresso_notices['errors']) > 1
896
-                ? __('The following errors have occurred:<br />', 'event_espresso')
897
-                : __('An error has occurred:<br />', 'event_espresso');
898
-            // combine messages
899
-            $error_messages .= implode(self::$_espresso_notices['errors'], '<br />');
900
-            $print_scripts  = true;
901
-        }
902
-        if ($format_output) {
903
-            $notices = EE_Error::formatNoticesOutput(
904
-                $success_messages,
905
-                $attention_messages,
906
-                $error_messages
907
-            );
908
-        } else {
909
-            $notices = array(
910
-                'success'   => $success_messages,
911
-                'attention' => $attention_messages,
912
-                'errors'    => $error_messages,
913
-            );
914
-            if ($remove_empty) {
915
-                // remove empty notices
916
-                foreach ($notices as $type => $notice) {
917
-                    if (empty($notice)) {
918
-                        unset($notices[$type]);
919
-                    }
920
-                }
921
-            }
922
-        }
923
-        if ($print_scripts) {
924
-            self::_print_scripts();
925
-        }
926
-        return $notices;
927
-    }
928
-
929
-
930
-    /**
931
-     * @return bool
932
-     * @throws InvalidArgumentException
933
-     * @throws InvalidDataTypeException
934
-     * @throws InvalidInterfaceException
935
-     */
936
-    private static function combineExistingAndNewNotices()
937
-    {
938
-        $print_scripts = false;
939
-        // grab any notices that have been previously saved
940
-        $notices = EE_Error::getStoredNotices();
941
-        if (! empty($notices)) {
942
-            foreach ($notices as $type => $notice) {
943
-                if (is_array($notice) && ! empty($notice)) {
944
-                    // make sure that existing notice type is an array
945
-                    self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
946
-                                                        && ! empty(self::$_espresso_notices[ $type ])
947
-                        ? self::$_espresso_notices[ $type ]
948
-                        : array();
949
-                    // add newly created notices to existing ones
950
-                    self::$_espresso_notices[ $type ] += $notice;
951
-                    $print_scripts = true;
952
-                }
953
-            }
954
-            // now clear any stored notices
955
-            EE_Error::clearNotices();
956
-        }
957
-        return $print_scripts;
958
-    }
959
-
960
-
961
-    /**
962
-     * @param string $success_messages
963
-     * @param string $attention_messages
964
-     * @param string $error_messages
965
-     * @return string
966
-     */
967
-    private static function formatNoticesOutput($success_messages, $attention_messages, $error_messages)
968
-    {
969
-        $notices = '<div id="espresso-notices">';
970
-        $close   = is_admin()
971
-            ? ''
972
-            : '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"/></a>';
973
-        if ($success_messages !== '') {
974
-            $css_id    = is_admin() ? 'message' : 'espresso-notices-success';
975
-            $css_class = is_admin() ? 'updated fade' : 'success fade-away';
976
-            //showMessage( $success_messages );
977
-            $notices .= '<div id="' . $css_id . '" '
978
-                        . 'class="espresso-notices ' . $css_class . '" '
979
-                        . 'style="display:none;">'
980
-                        . '<p>' . $success_messages . '</p>'
981
-                        . $close
982
-                        . '</div>';
983
-        }
984
-        if ($attention_messages !== '') {
985
-            $css_id    = is_admin() ? 'message' : 'espresso-notices-attention';
986
-            $css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
987
-            //showMessage( $error_messages, TRUE );
988
-            $notices .= '<div id="' . $css_id . '" '
989
-                        . 'class="espresso-notices ' . $css_class . '" '
990
-                        . 'style="display:none;">'
991
-                        . '<p>' . $attention_messages . '</p>'
992
-                        . $close
993
-                        . '</div>';
994
-        }
995
-        if ($error_messages !== '') {
996
-            $css_id    = is_admin() ? 'message' : 'espresso-notices-error';
997
-            $css_class = is_admin() ? 'error' : 'error fade-away';
998
-            //showMessage( $error_messages, TRUE );
999
-            $notices .= '<div id="' . $css_id . '" '
1000
-                        . 'class="espresso-notices ' . $css_class . '" '
1001
-                        . 'style="display:none;">'
1002
-                        . '<p>' . $error_messages . '</p>'
1003
-                        . $close
1004
-                        . '</div>';
1005
-        }
1006
-        $notices .= '</div>';
1007
-        return $notices;
1008
-    }
1009
-
1010
-
1011
-
1012
-    /**
1013
-     * _print_scripts
1014
-     *
1015
-     * @param    bool $force_print
1016
-     * @return    string
1017
-     */
1018
-    private static function _print_scripts($force_print = false)
1019
-    {
1020
-        if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1021
-            if (wp_script_is('ee_error_js', 'enqueued')) {
1022
-                return '';
1023
-            }
1024
-            if (wp_script_is('ee_error_js', 'registered')) {
1025
-                wp_enqueue_style('espresso_default');
1026
-                wp_enqueue_style('espresso_custom_css');
1027
-                wp_enqueue_script('ee_error_js');
1028
-                wp_localize_script('ee_error_js', 'ee_settings', array('wp_debug' => WP_DEBUG));
1029
-            }
1030
-        } else {
1031
-            return '
480
+		$output .= self::_print_scripts(true);
481
+		if (defined('DOING_AJAX')) {
482
+			echo wp_json_encode(array('error' => $output));
483
+			exit();
484
+		}
485
+		echo $output;
486
+		die();
487
+	}
488
+
489
+
490
+
491
+	/**
492
+	 *    generate string from exception trace args
493
+	 *
494
+	 * @param array $arguments
495
+	 * @param bool  $array
496
+	 * @return string
497
+	 */
498
+	private function _convert_args_to_string($arguments = array(), $array = false)
499
+	{
500
+		$arg_string = '';
501
+		if (! empty($arguments)) {
502
+			$args = array();
503
+			foreach ($arguments as $arg) {
504
+				if (! empty($arg)) {
505
+					if (is_string($arg)) {
506
+						$args[] = " '" . $arg . "'";
507
+					} elseif (is_array($arg)) {
508
+						$args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
509
+					} elseif ($arg === null) {
510
+						$args[] = ' NULL';
511
+					} elseif (is_bool($arg)) {
512
+						$args[] = ($arg) ? ' TRUE' : ' FALSE';
513
+					} elseif (is_object($arg)) {
514
+						$args[] = ' OBJECT ' . get_class($arg);
515
+					} elseif (is_resource($arg)) {
516
+						$args[] = get_resource_type($arg);
517
+					} else {
518
+						$args[] = $arg;
519
+					}
520
+				}
521
+			}
522
+			$arg_string = implode(', ', $args);
523
+		}
524
+		if ($array) {
525
+			$arg_string .= ' )';
526
+		}
527
+		return $arg_string;
528
+	}
529
+
530
+
531
+
532
+	/**
533
+	 *    add error message
534
+	 *
535
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
536
+	 *                            separate messages for user || dev
537
+	 * @param        string $file the file that the error occurred in - just use __FILE__
538
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
539
+	 * @param        string $line the line number where the error occurred - just use __LINE__
540
+	 * @return        void
541
+	 */
542
+	public static function add_error($msg = null, $file = null, $func = null, $line = null)
543
+	{
544
+		self::_add_notice('errors', $msg, $file, $func, $line);
545
+		self::$_error_count++;
546
+	}
547
+
548
+
549
+
550
+	/**
551
+	 * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
552
+	 * adds an error
553
+	 *
554
+	 * @param string $msg
555
+	 * @param string $file
556
+	 * @param string $func
557
+	 * @param string $line
558
+	 * @throws EE_Error
559
+	 */
560
+	public static function throw_exception_if_debugging($msg = null, $file = null, $func = null, $line = null)
561
+	{
562
+		if (WP_DEBUG) {
563
+			throw new EE_Error($msg);
564
+		}
565
+		EE_Error::add_error($msg, $file, $func, $line);
566
+	}
567
+
568
+
569
+
570
+	/**
571
+	 *    add success message
572
+	 *
573
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
574
+	 *                            separate messages for user || dev
575
+	 * @param        string $file the file that the error occurred in - just use __FILE__
576
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
577
+	 * @param        string $line the line number where the error occurred - just use __LINE__
578
+	 * @return        void
579
+	 */
580
+	public static function add_success($msg = null, $file = null, $func = null, $line = null)
581
+	{
582
+		self::_add_notice('success', $msg, $file, $func, $line);
583
+	}
584
+
585
+
586
+
587
+	/**
588
+	 *    add attention message
589
+	 *
590
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
591
+	 *                            separate messages for user || dev
592
+	 * @param        string $file the file that the error occurred in - just use __FILE__
593
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
594
+	 * @param        string $line the line number where the error occurred - just use __LINE__
595
+	 * @return        void
596
+	 */
597
+	public static function add_attention($msg = null, $file = null, $func = null, $line = null)
598
+	{
599
+		self::_add_notice('attention', $msg, $file, $func, $line);
600
+	}
601
+
602
+
603
+
604
+	/**
605
+	 * @param string $type whether the message is for a success or error notification
606
+	 * @param string $msg the message to display to users or developers
607
+	 *                    - adding a double pipe || (OR) creates separate messages for user || dev
608
+	 * @param string $file the file that the error occurred in - just use __FILE__
609
+	 * @param string $func the function/method that the error occurred in - just use __FUNCTION__
610
+	 * @param string $line the line number where the error occurred - just use __LINE__
611
+	 * @return void
612
+	 */
613
+	private static function _add_notice($type = 'success', $msg = '', $file = '', $func = '', $line = '')
614
+	{
615
+		if (empty($msg)) {
616
+			EE_Error::doing_it_wrong(
617
+				'EE_Error::add_' . $type . '()',
618
+				sprintf(
619
+					__('Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
620
+						'event_espresso'),
621
+					$type,
622
+					$file,
623
+					$line
624
+				),
625
+				EVENT_ESPRESSO_VERSION
626
+			);
627
+		}
628
+		if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
629
+			EE_Error::doing_it_wrong(
630
+				'EE_Error::add_error()',
631
+				__('You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
632
+					'event_espresso'),
633
+				EVENT_ESPRESSO_VERSION
634
+			);
635
+		}
636
+		// get separate user and developer messages if they exist
637
+		$msg      = explode('||', $msg);
638
+		$user_msg = $msg[0];
639
+		$dev_msg  = isset($msg[1]) ? $msg[1] : $msg[0];
640
+		/**
641
+		 * Do an action so other code can be triggered when a notice is created
642
+		 *
643
+		 * @param string $type     can be 'errors', 'attention', or 'success'
644
+		 * @param string $user_msg message displayed to user when WP_DEBUG is off
645
+		 * @param string $user_msg message displayed to user when WP_DEBUG is on
646
+		 * @param string $file     file where error was generated
647
+		 * @param string $func     function where error was generated
648
+		 * @param string $line     line where error was generated
649
+		 */
650
+		do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
651
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
652
+		// add notice if message exists
653
+		if (! empty($msg)) {
654
+			// get error code
655
+			$notice_code = EE_Error::generate_error_code($file, $func, $line);
656
+			if (WP_DEBUG && $type === 'errors') {
657
+				$msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
658
+			}
659
+			// add notice. Index by code if it's not blank
660
+			if ($notice_code) {
661
+				self::$_espresso_notices[$type][$notice_code] = $msg;
662
+			} else {
663
+				self::$_espresso_notices[$type][] = $msg;
664
+			}
665
+			add_action('wp_footer', array('EE_Error', 'enqueue_error_scripts'), 1);
666
+		}
667
+	}
668
+
669
+
670
+	/**
671
+	 * in some case it may be necessary to overwrite the existing success messages
672
+	 *
673
+	 * @return        void
674
+	 */
675
+	public static function overwrite_success()
676
+	{
677
+		self::$_espresso_notices['success'] = false;
678
+	}
679
+
680
+
681
+
682
+	/**
683
+	 * in some case it may be necessary to overwrite the existing attention messages
684
+	 *
685
+	 * @return void
686
+	 */
687
+	public static function overwrite_attention()
688
+	{
689
+		self::$_espresso_notices['attention'] = false;
690
+	}
691
+
692
+
693
+
694
+	/**
695
+	 * in some case it may be necessary to overwrite the existing error messages
696
+	 *
697
+	 * @return void
698
+	 */
699
+	public static function overwrite_errors()
700
+	{
701
+		self::$_espresso_notices['errors'] = false;
702
+	}
703
+
704
+
705
+
706
+	/**
707
+	 * @return void
708
+	 */
709
+	public static function reset_notices()
710
+	{
711
+		self::$_espresso_notices['success']   = false;
712
+		self::$_espresso_notices['attention'] = false;
713
+		self::$_espresso_notices['errors']    = false;
714
+	}
715
+
716
+
717
+
718
+	/**
719
+	 * @return int
720
+	 */
721
+	public static function has_notices()
722
+	{
723
+		$has_notices = 0;
724
+		// check for success messages
725
+		$has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])
726
+			? 3
727
+			: $has_notices;
728
+		// check for attention messages
729
+		$has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])
730
+			? 2
731
+			: $has_notices;
732
+		// check for error messages
733
+		$has_notices = self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])
734
+			? 1
735
+			: $has_notices;
736
+		return $has_notices;
737
+	}
738
+
739
+
740
+	/**
741
+	 * This simply returns non formatted error notices as they were sent into the EE_Error object.
742
+	 *
743
+	 * @since 4.9.0
744
+	 * @return array
745
+	 */
746
+	public static function get_vanilla_notices()
747
+	{
748
+		return array(
749
+			'success'   => isset(self::$_espresso_notices['success'])
750
+				? self::$_espresso_notices['success']
751
+				: array(),
752
+			'attention' => isset(self::$_espresso_notices['attention'])
753
+				? self::$_espresso_notices['attention']
754
+				: array(),
755
+			'errors'    => isset(self::$_espresso_notices['errors'])
756
+				? self::$_espresso_notices['errors']
757
+				: array(),
758
+		);
759
+	}
760
+
761
+
762
+	/**
763
+	 * @return array
764
+	 * @throws InvalidArgumentException
765
+	 * @throws InvalidDataTypeException
766
+	 * @throws InvalidInterfaceException
767
+	 */
768
+	public static function getStoredNotices()
769
+	{
770
+		if ($user_id = get_current_user_id()) {
771
+			// get notices for logged in user
772
+			$notices = get_user_option(EE_Error::OPTIONS_KEY_NOTICES, $user_id);
773
+			return is_array($notices) ? $notices : array();
774
+		}
775
+		if (EE_Session::isLoadedAndActive()) {
776
+			// get notices for user currently engaged in a session
777
+			$session_data = EE_Session::instance()->get_session_data(EE_Error::OPTIONS_KEY_NOTICES);
778
+			return is_array($session_data) ? $session_data : array();
779
+		}
780
+		// get global notices and hope they apply to the current site visitor
781
+		$notices = get_option(EE_Error::OPTIONS_KEY_NOTICES, array());
782
+		return is_array($notices) ? $notices : array();
783
+	}
784
+
785
+
786
+	/**
787
+	 * @param array $notices
788
+	 * @return bool
789
+	 * @throws InvalidArgumentException
790
+	 * @throws InvalidDataTypeException
791
+	 * @throws InvalidInterfaceException
792
+	 */
793
+	public static function storeNotices(array $notices)
794
+	{
795
+		if ($user_id = get_current_user_id()) {
796
+			// store notices for logged in user
797
+			return (bool) update_user_option(
798
+				$user_id,
799
+				EE_Error::OPTIONS_KEY_NOTICES,
800
+				$notices
801
+			);
802
+		}
803
+		if (EE_Session::isLoadedAndActive()) {
804
+			// store notices for user currently engaged in a session
805
+			return EE_Session::instance()->set_session_data(
806
+				array(EE_Error::OPTIONS_KEY_NOTICES => $notices)
807
+			);
808
+		}
809
+		// store global notices and hope they apply to the same site visitor on the next request
810
+		return update_option(EE_Error::OPTIONS_KEY_NOTICES, $notices);
811
+	}
812
+
813
+
814
+	/**
815
+	 * @return bool|TRUE
816
+	 * @throws InvalidArgumentException
817
+	 * @throws InvalidDataTypeException
818
+	 * @throws InvalidInterfaceException
819
+	 */
820
+	public static function clearNotices()
821
+	{
822
+		if ($user_id = get_current_user_id()) {
823
+			// clear notices for logged in user
824
+			return (bool) update_user_option(
825
+				$user_id,
826
+				EE_Error::OPTIONS_KEY_NOTICES,
827
+				array()
828
+			);
829
+		}
830
+		if (EE_Session::isLoadedAndActive()) {
831
+			// clear notices for user currently engaged in a session
832
+			return EE_Session::instance()->reset_data(EE_Error::OPTIONS_KEY_NOTICES);
833
+		}
834
+		// clear global notices and hope none belonged to some for some other site visitor
835
+		return update_option(EE_Error::OPTIONS_KEY_NOTICES, array());
836
+	}
837
+
838
+
839
+	/**
840
+	 * saves notices to the db for retrieval on next request
841
+	 *
842
+	 * @return void
843
+	 * @throws InvalidArgumentException
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws InvalidInterfaceException
846
+	 */
847
+	public static function stashNoticesBeforeRedirect()
848
+	{
849
+		EE_Error::get_notices(false, true);
850
+	}
851
+
852
+
853
+	/**
854
+	 * compile all error or success messages into one string
855
+	 *
856
+	 * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
857
+	 * @param boolean $format_output            whether or not to format the messages for display in the WP admin
858
+	 * @param boolean $save_to_transient        whether or not to save notices to the db for retrieval on next request
859
+	 *                                          - ONLY do this just before redirecting
860
+	 * @param boolean $remove_empty             whether or not to unset empty messages
861
+	 * @return array
862
+	 * @throws InvalidArgumentException
863
+	 * @throws InvalidDataTypeException
864
+	 * @throws InvalidInterfaceException
865
+	 */
866
+	public static function get_notices($format_output = true, $save_to_transient = false, $remove_empty = true)
867
+	{
868
+		$success_messages   = '';
869
+		$attention_messages = '';
870
+		$error_messages     = '';
871
+		// either save notices to the db
872
+		if ($save_to_transient || isset($_REQUEST['activate-selected'])) {
873
+			self::$_espresso_notices = array_merge(
874
+				EE_Error::getStoredNotices(),
875
+				self::$_espresso_notices
876
+			);
877
+			EE_Error::storeNotices(self::$_espresso_notices);
878
+			return array();
879
+		}
880
+		$print_scripts = EE_Error::combineExistingAndNewNotices();
881
+		// check for success messages
882
+		if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
883
+			// combine messages
884
+			$success_messages .= implode(self::$_espresso_notices['success'], '<br />');
885
+			$print_scripts    = true;
886
+		}
887
+		// check for attention messages
888
+		if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
889
+			// combine messages
890
+			$attention_messages .= implode(self::$_espresso_notices['attention'], '<br />');
891
+			$print_scripts      = true;
892
+		}
893
+		// check for error messages
894
+		if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
895
+			$error_messages .= count(self::$_espresso_notices['errors']) > 1
896
+				? __('The following errors have occurred:<br />', 'event_espresso')
897
+				: __('An error has occurred:<br />', 'event_espresso');
898
+			// combine messages
899
+			$error_messages .= implode(self::$_espresso_notices['errors'], '<br />');
900
+			$print_scripts  = true;
901
+		}
902
+		if ($format_output) {
903
+			$notices = EE_Error::formatNoticesOutput(
904
+				$success_messages,
905
+				$attention_messages,
906
+				$error_messages
907
+			);
908
+		} else {
909
+			$notices = array(
910
+				'success'   => $success_messages,
911
+				'attention' => $attention_messages,
912
+				'errors'    => $error_messages,
913
+			);
914
+			if ($remove_empty) {
915
+				// remove empty notices
916
+				foreach ($notices as $type => $notice) {
917
+					if (empty($notice)) {
918
+						unset($notices[$type]);
919
+					}
920
+				}
921
+			}
922
+		}
923
+		if ($print_scripts) {
924
+			self::_print_scripts();
925
+		}
926
+		return $notices;
927
+	}
928
+
929
+
930
+	/**
931
+	 * @return bool
932
+	 * @throws InvalidArgumentException
933
+	 * @throws InvalidDataTypeException
934
+	 * @throws InvalidInterfaceException
935
+	 */
936
+	private static function combineExistingAndNewNotices()
937
+	{
938
+		$print_scripts = false;
939
+		// grab any notices that have been previously saved
940
+		$notices = EE_Error::getStoredNotices();
941
+		if (! empty($notices)) {
942
+			foreach ($notices as $type => $notice) {
943
+				if (is_array($notice) && ! empty($notice)) {
944
+					// make sure that existing notice type is an array
945
+					self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
946
+														&& ! empty(self::$_espresso_notices[ $type ])
947
+						? self::$_espresso_notices[ $type ]
948
+						: array();
949
+					// add newly created notices to existing ones
950
+					self::$_espresso_notices[ $type ] += $notice;
951
+					$print_scripts = true;
952
+				}
953
+			}
954
+			// now clear any stored notices
955
+			EE_Error::clearNotices();
956
+		}
957
+		return $print_scripts;
958
+	}
959
+
960
+
961
+	/**
962
+	 * @param string $success_messages
963
+	 * @param string $attention_messages
964
+	 * @param string $error_messages
965
+	 * @return string
966
+	 */
967
+	private static function formatNoticesOutput($success_messages, $attention_messages, $error_messages)
968
+	{
969
+		$notices = '<div id="espresso-notices">';
970
+		$close   = is_admin()
971
+			? ''
972
+			: '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"/></a>';
973
+		if ($success_messages !== '') {
974
+			$css_id    = is_admin() ? 'message' : 'espresso-notices-success';
975
+			$css_class = is_admin() ? 'updated fade' : 'success fade-away';
976
+			//showMessage( $success_messages );
977
+			$notices .= '<div id="' . $css_id . '" '
978
+						. 'class="espresso-notices ' . $css_class . '" '
979
+						. 'style="display:none;">'
980
+						. '<p>' . $success_messages . '</p>'
981
+						. $close
982
+						. '</div>';
983
+		}
984
+		if ($attention_messages !== '') {
985
+			$css_id    = is_admin() ? 'message' : 'espresso-notices-attention';
986
+			$css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
987
+			//showMessage( $error_messages, TRUE );
988
+			$notices .= '<div id="' . $css_id . '" '
989
+						. 'class="espresso-notices ' . $css_class . '" '
990
+						. 'style="display:none;">'
991
+						. '<p>' . $attention_messages . '</p>'
992
+						. $close
993
+						. '</div>';
994
+		}
995
+		if ($error_messages !== '') {
996
+			$css_id    = is_admin() ? 'message' : 'espresso-notices-error';
997
+			$css_class = is_admin() ? 'error' : 'error fade-away';
998
+			//showMessage( $error_messages, TRUE );
999
+			$notices .= '<div id="' . $css_id . '" '
1000
+						. 'class="espresso-notices ' . $css_class . '" '
1001
+						. 'style="display:none;">'
1002
+						. '<p>' . $error_messages . '</p>'
1003
+						. $close
1004
+						. '</div>';
1005
+		}
1006
+		$notices .= '</div>';
1007
+		return $notices;
1008
+	}
1009
+
1010
+
1011
+
1012
+	/**
1013
+	 * _print_scripts
1014
+	 *
1015
+	 * @param    bool $force_print
1016
+	 * @return    string
1017
+	 */
1018
+	private static function _print_scripts($force_print = false)
1019
+	{
1020
+		if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1021
+			if (wp_script_is('ee_error_js', 'enqueued')) {
1022
+				return '';
1023
+			}
1024
+			if (wp_script_is('ee_error_js', 'registered')) {
1025
+				wp_enqueue_style('espresso_default');
1026
+				wp_enqueue_style('espresso_custom_css');
1027
+				wp_enqueue_script('ee_error_js');
1028
+				wp_localize_script('ee_error_js', 'ee_settings', array('wp_debug' => WP_DEBUG));
1029
+			}
1030
+		} else {
1031
+			return '
1032 1032
 <script>
1033 1033
 /* <![CDATA[ */
1034 1034
 var ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
@@ -1038,223 +1038,223 @@  discard block
 block discarded – undo
1038 1038
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1039 1039
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1040 1040
 ';
1041
-        }
1042
-        return '';
1043
-    }
1044
-
1045
-
1046
-
1047
-    /**
1048
-     * @return void
1049
-     */
1050
-    public static function enqueue_error_scripts()
1051
-    {
1052
-        self::_print_scripts();
1053
-    }
1054
-
1055
-
1056
-
1057
-    /**
1058
-     * create error code from filepath, function name,
1059
-     * and line number where exception or error was thrown
1060
-     *
1061
-     * @param string $file
1062
-     * @param string $func
1063
-     * @param string $line
1064
-     * @return string
1065
-     */
1066
-    public static function generate_error_code($file = '', $func = '', $line = '')
1067
-    {
1068
-        $file       = explode('.', basename($file));
1069
-        $error_code = ! empty($file[0]) ? $file[0] : '';
1070
-        $error_code .= ! empty($func) ? ' - ' . $func : '';
1071
-        $error_code .= ! empty($line) ? ' - ' . $line : '';
1072
-        return $error_code;
1073
-    }
1074
-
1075
-
1076
-
1077
-    /**
1078
-     * write exception details to log file
1079
-     * Since 4.9.53.rc.006 this writes to the standard PHP log file, not EE's custom log file
1080
-     *
1081
-     * @param int   $time
1082
-     * @param array $ex
1083
-     * @param bool  $clear
1084
-     * @return void
1085
-     */
1086
-    public function write_to_error_log($time = 0, $ex = array(), $clear = false)
1087
-    {
1088
-        if (empty($ex)) {
1089
-            return;
1090
-        }
1091
-        if (! $time) {
1092
-            $time = time();
1093
-        }
1094
-        $exception_log = '----------------------------------------------------------------------------------------'
1095
-                         . PHP_EOL;
1096
-        $exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1097
-        $exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1098
-        $exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1099
-        $exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1100
-        $exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1101
-        $exception_log .= 'Stack trace: ' . PHP_EOL;
1102
-        $exception_log .= $ex['string'] . PHP_EOL;
1103
-        $exception_log .= '----------------------------------------------------------------------------------------'
1104
-                          . PHP_EOL;
1105
-        try {
1106
-            error_log($exception_log);
1107
-        } catch (EE_Error $e) {
1108
-            EE_Error::add_error(sprintf(__('Event Espresso error logging could not be setup because: %s',
1109
-                'event_espresso'), $e->getMessage()));
1110
-        }
1111
-    }
1112
-
1113
-
1114
-
1115
-    /**
1116
-     * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1117
-     * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1118
-     * but the code execution is done in a manner that could lead to unexpected results
1119
-     * (i.e. running to early, or too late in WP or EE loading process).
1120
-     * A good test for knowing whether to use this method is:
1121
-     * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1122
-     * Yes -> use EE_Error::add_error() or throw new EE_Error()
1123
-     * 2. If this is loaded before something else, it won't break anything,
1124
-     * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1125
-     *
1126
-     * @uses   constant WP_DEBUG test if wp_debug is on or not
1127
-     * @param string $function      The function that was called
1128
-     * @param string $message       A message explaining what has been done incorrectly
1129
-     * @param string $version       The version of Event Espresso where the error was added
1130
-     * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
1131
-     *                              for a deprecated function. This allows deprecation to occur during one version,
1132
-     *                              but not have any notices appear until a later version. This allows developers
1133
-     *                              extra time to update their code before notices appear.
1134
-     * @param int    $error_type
1135
-     */
1136
-    public static function doing_it_wrong(
1137
-        $function,
1138
-        $message,
1139
-        $version,
1140
-        $applies_when = '',
1141
-        $error_type = null
1142
-    ) {
1143
-        if (defined('WP_DEBUG') && WP_DEBUG) {
1144
-            EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1145
-        }
1146
-    }
1147
-
1148
-
1149
-
1150
-    /**
1151
-     * Like get_notices, but returns an array of all the notices of the given type.
1152
-     *
1153
-     * @return array {
1154
-     *  @type array $success   all the success messages
1155
-     *  @type array $errors    all the error messages
1156
-     *  @type array $attention all the attention messages
1157
-     * }
1158
-     */
1159
-    public static function get_raw_notices()
1160
-    {
1161
-        return self::$_espresso_notices;
1162
-    }
1163
-
1164
-
1165
-
1166
-    /**
1167
-     * @deprecated 4.9.27
1168
-     * @param string $pan_name     the name, or key of the Persistent Admin Notice to be stored
1169
-     * @param string $pan_message  the message to be stored persistently until dismissed
1170
-     * @param bool   $force_update allows one to enforce the reappearance of a persistent message.
1171
-     * @return void
1172
-     * @throws InvalidDataTypeException
1173
-     */
1174
-    public static function add_persistent_admin_notice($pan_name = '', $pan_message, $force_update = false)
1175
-    {
1176
-        new PersistentAdminNotice(
1177
-            $pan_name,
1178
-            $pan_message,
1179
-            $force_update
1180
-        );
1181
-        EE_Error::doing_it_wrong(
1182
-            __METHOD__,
1183
-            sprintf(
1184
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1185
-                '\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
1186
-            ),
1187
-            '4.9.27'
1188
-        );
1189
-    }
1190
-
1191
-
1192
-
1193
-    /**
1194
-     * @deprecated 4.9.27
1195
-     * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
1196
-     * @param bool   $purge
1197
-     * @param bool   $return
1198
-     * @throws DomainException
1199
-     * @throws InvalidInterfaceException
1200
-     * @throws InvalidDataTypeException
1201
-     * @throws ServiceNotFoundException
1202
-     * @throws InvalidArgumentException
1203
-     */
1204
-    public static function dismiss_persistent_admin_notice($pan_name = '', $purge = false, $return = false)
1205
-    {
1206
-        /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
1207
-        $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
1208
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1209
-        );
1210
-        $persistent_admin_notice_manager->dismissNotice($pan_name, $purge, $return);
1211
-        EE_Error::doing_it_wrong(
1212
-            __METHOD__,
1213
-            sprintf(
1214
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1215
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1216
-            ),
1217
-            '4.9.27'
1218
-        );
1219
-    }
1220
-
1221
-
1222
-
1223
-    /**
1224
-     * @deprecated 4.9.27
1225
-     * @param  string $pan_name    the name, or key of the Persistent Admin Notice to be stored
1226
-     * @param  string $pan_message the message to be stored persistently until dismissed
1227
-     * @param  string $return_url  URL to go back to after nag notice is dismissed
1228
-     */
1229
-    public static function display_persistent_admin_notices($pan_name = '', $pan_message = '', $return_url = '')
1230
-    {
1231
-        EE_Error::doing_it_wrong(
1232
-            __METHOD__,
1233
-            sprintf(
1234
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1235
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1236
-            ),
1237
-            '4.9.27'
1238
-        );
1239
-    }
1240
-
1241
-
1242
-
1243
-    /**
1244
-     * @deprecated 4.9.27
1245
-     * @param string $return_url
1246
-     */
1247
-    public static function get_persistent_admin_notices($return_url = '')
1248
-    {
1249
-        EE_Error::doing_it_wrong(
1250
-            __METHOD__,
1251
-            sprintf(
1252
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1253
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1254
-            ),
1255
-            '4.9.27'
1256
-        );
1257
-    }
1041
+		}
1042
+		return '';
1043
+	}
1044
+
1045
+
1046
+
1047
+	/**
1048
+	 * @return void
1049
+	 */
1050
+	public static function enqueue_error_scripts()
1051
+	{
1052
+		self::_print_scripts();
1053
+	}
1054
+
1055
+
1056
+
1057
+	/**
1058
+	 * create error code from filepath, function name,
1059
+	 * and line number where exception or error was thrown
1060
+	 *
1061
+	 * @param string $file
1062
+	 * @param string $func
1063
+	 * @param string $line
1064
+	 * @return string
1065
+	 */
1066
+	public static function generate_error_code($file = '', $func = '', $line = '')
1067
+	{
1068
+		$file       = explode('.', basename($file));
1069
+		$error_code = ! empty($file[0]) ? $file[0] : '';
1070
+		$error_code .= ! empty($func) ? ' - ' . $func : '';
1071
+		$error_code .= ! empty($line) ? ' - ' . $line : '';
1072
+		return $error_code;
1073
+	}
1074
+
1075
+
1076
+
1077
+	/**
1078
+	 * write exception details to log file
1079
+	 * Since 4.9.53.rc.006 this writes to the standard PHP log file, not EE's custom log file
1080
+	 *
1081
+	 * @param int   $time
1082
+	 * @param array $ex
1083
+	 * @param bool  $clear
1084
+	 * @return void
1085
+	 */
1086
+	public function write_to_error_log($time = 0, $ex = array(), $clear = false)
1087
+	{
1088
+		if (empty($ex)) {
1089
+			return;
1090
+		}
1091
+		if (! $time) {
1092
+			$time = time();
1093
+		}
1094
+		$exception_log = '----------------------------------------------------------------------------------------'
1095
+						 . PHP_EOL;
1096
+		$exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1097
+		$exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1098
+		$exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1099
+		$exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1100
+		$exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1101
+		$exception_log .= 'Stack trace: ' . PHP_EOL;
1102
+		$exception_log .= $ex['string'] . PHP_EOL;
1103
+		$exception_log .= '----------------------------------------------------------------------------------------'
1104
+						  . PHP_EOL;
1105
+		try {
1106
+			error_log($exception_log);
1107
+		} catch (EE_Error $e) {
1108
+			EE_Error::add_error(sprintf(__('Event Espresso error logging could not be setup because: %s',
1109
+				'event_espresso'), $e->getMessage()));
1110
+		}
1111
+	}
1112
+
1113
+
1114
+
1115
+	/**
1116
+	 * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1117
+	 * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1118
+	 * but the code execution is done in a manner that could lead to unexpected results
1119
+	 * (i.e. running to early, or too late in WP or EE loading process).
1120
+	 * A good test for knowing whether to use this method is:
1121
+	 * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1122
+	 * Yes -> use EE_Error::add_error() or throw new EE_Error()
1123
+	 * 2. If this is loaded before something else, it won't break anything,
1124
+	 * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1125
+	 *
1126
+	 * @uses   constant WP_DEBUG test if wp_debug is on or not
1127
+	 * @param string $function      The function that was called
1128
+	 * @param string $message       A message explaining what has been done incorrectly
1129
+	 * @param string $version       The version of Event Espresso where the error was added
1130
+	 * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
1131
+	 *                              for a deprecated function. This allows deprecation to occur during one version,
1132
+	 *                              but not have any notices appear until a later version. This allows developers
1133
+	 *                              extra time to update their code before notices appear.
1134
+	 * @param int    $error_type
1135
+	 */
1136
+	public static function doing_it_wrong(
1137
+		$function,
1138
+		$message,
1139
+		$version,
1140
+		$applies_when = '',
1141
+		$error_type = null
1142
+	) {
1143
+		if (defined('WP_DEBUG') && WP_DEBUG) {
1144
+			EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1145
+		}
1146
+	}
1147
+
1148
+
1149
+
1150
+	/**
1151
+	 * Like get_notices, but returns an array of all the notices of the given type.
1152
+	 *
1153
+	 * @return array {
1154
+	 *  @type array $success   all the success messages
1155
+	 *  @type array $errors    all the error messages
1156
+	 *  @type array $attention all the attention messages
1157
+	 * }
1158
+	 */
1159
+	public static function get_raw_notices()
1160
+	{
1161
+		return self::$_espresso_notices;
1162
+	}
1163
+
1164
+
1165
+
1166
+	/**
1167
+	 * @deprecated 4.9.27
1168
+	 * @param string $pan_name     the name, or key of the Persistent Admin Notice to be stored
1169
+	 * @param string $pan_message  the message to be stored persistently until dismissed
1170
+	 * @param bool   $force_update allows one to enforce the reappearance of a persistent message.
1171
+	 * @return void
1172
+	 * @throws InvalidDataTypeException
1173
+	 */
1174
+	public static function add_persistent_admin_notice($pan_name = '', $pan_message, $force_update = false)
1175
+	{
1176
+		new PersistentAdminNotice(
1177
+			$pan_name,
1178
+			$pan_message,
1179
+			$force_update
1180
+		);
1181
+		EE_Error::doing_it_wrong(
1182
+			__METHOD__,
1183
+			sprintf(
1184
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1185
+				'\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
1186
+			),
1187
+			'4.9.27'
1188
+		);
1189
+	}
1190
+
1191
+
1192
+
1193
+	/**
1194
+	 * @deprecated 4.9.27
1195
+	 * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
1196
+	 * @param bool   $purge
1197
+	 * @param bool   $return
1198
+	 * @throws DomainException
1199
+	 * @throws InvalidInterfaceException
1200
+	 * @throws InvalidDataTypeException
1201
+	 * @throws ServiceNotFoundException
1202
+	 * @throws InvalidArgumentException
1203
+	 */
1204
+	public static function dismiss_persistent_admin_notice($pan_name = '', $purge = false, $return = false)
1205
+	{
1206
+		/** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
1207
+		$persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
1208
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1209
+		);
1210
+		$persistent_admin_notice_manager->dismissNotice($pan_name, $purge, $return);
1211
+		EE_Error::doing_it_wrong(
1212
+			__METHOD__,
1213
+			sprintf(
1214
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1215
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1216
+			),
1217
+			'4.9.27'
1218
+		);
1219
+	}
1220
+
1221
+
1222
+
1223
+	/**
1224
+	 * @deprecated 4.9.27
1225
+	 * @param  string $pan_name    the name, or key of the Persistent Admin Notice to be stored
1226
+	 * @param  string $pan_message the message to be stored persistently until dismissed
1227
+	 * @param  string $return_url  URL to go back to after nag notice is dismissed
1228
+	 */
1229
+	public static function display_persistent_admin_notices($pan_name = '', $pan_message = '', $return_url = '')
1230
+	{
1231
+		EE_Error::doing_it_wrong(
1232
+			__METHOD__,
1233
+			sprintf(
1234
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1235
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1236
+			),
1237
+			'4.9.27'
1238
+		);
1239
+	}
1240
+
1241
+
1242
+
1243
+	/**
1244
+	 * @deprecated 4.9.27
1245
+	 * @param string $return_url
1246
+	 */
1247
+	public static function get_persistent_admin_notices($return_url = '')
1248
+	{
1249
+		EE_Error::doing_it_wrong(
1250
+			__METHOD__,
1251
+			sprintf(
1252
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1253
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1254
+			),
1255
+			'4.9.27'
1256
+		);
1257
+	}
1258 1258
 
1259 1259
 
1260 1260
 
@@ -1269,27 +1269,27 @@  discard block
 block discarded – undo
1269 1269
  */
1270 1270
 function espresso_error_enqueue_scripts()
1271 1271
 {
1272
-    // js for error handling
1273
-    wp_register_script(
1274
-        'espresso_core',
1275
-        EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1276
-        array('jquery'),
1277
-        EVENT_ESPRESSO_VERSION,
1278
-        false
1279
-    );
1280
-    wp_register_script(
1281
-        'ee_error_js',
1282
-        EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1283
-        array('espresso_core'),
1284
-        EVENT_ESPRESSO_VERSION,
1285
-        false
1286
-    );
1272
+	// js for error handling
1273
+	wp_register_script(
1274
+		'espresso_core',
1275
+		EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1276
+		array('jquery'),
1277
+		EVENT_ESPRESSO_VERSION,
1278
+		false
1279
+	);
1280
+	wp_register_script(
1281
+		'ee_error_js',
1282
+		EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1283
+		array('espresso_core'),
1284
+		EVENT_ESPRESSO_VERSION,
1285
+		false
1286
+	);
1287 1287
 }
1288 1288
 
1289 1289
 if (is_admin()) {
1290
-    add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1290
+	add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1291 1291
 } else {
1292
-    add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1292
+	add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 2);
1293 1293
 }
1294 1294
 
1295 1295
 
Please login to merge, or discard this patch.
core/libraries/messages/messenger/EE_Email_messenger.class.php 2 patches
Indentation   +645 added lines, -645 removed lines patch added patch discarded remove patch
@@ -8,649 +8,649 @@
 block discarded – undo
8 8
 class EE_Email_messenger extends EE_messenger
9 9
 {
10 10
 
11
-    /**
12
-     * To field for email
13
-     * @var string
14
-     */
15
-    protected $_to = '';
16
-
17
-
18
-    /**
19
-     * CC field for email.
20
-     * @var string
21
-     */
22
-    protected $_cc = '';
23
-
24
-    /**
25
-     * From field for email
26
-     * @var string
27
-     */
28
-    protected $_from = '';
29
-
30
-
31
-    /**
32
-     * Subject field for email
33
-     * @var string
34
-     */
35
-    protected $_subject = '';
36
-
37
-
38
-    /**
39
-     * Content field for email
40
-     * @var string
41
-     */
42
-    protected $_content = '';
43
-
44
-
45
-    /**
46
-     * constructor
47
-     *
48
-     * @access public
49
-     */
50
-    public function __construct()
51
-    {
52
-        //set name and description properties
53
-        $this->name                = 'email';
54
-        $this->description         = sprintf(
55
-            esc_html__(
56
-                'This messenger delivers messages via email using the built-in %s function included with WordPress',
57
-                'event_espresso'
58
-            ),
59
-            '<code>wp_mail</code>'
60
-        );
61
-        $this->label               = array(
62
-            'singular' => esc_html__('email', 'event_espresso'),
63
-            'plural'   => esc_html__('emails', 'event_espresso'),
64
-        );
65
-        $this->activate_on_install = true;
66
-
67
-        //we're using defaults so let's call parent constructor that will take care of setting up all the other
68
-        // properties
69
-        parent::__construct();
70
-    }
71
-
72
-
73
-    /**
74
-     * see abstract declaration in parent class for details.
75
-     */
76
-    protected function _set_admin_pages()
77
-    {
78
-        $this->admin_registered_pages = array(
79
-            'events_edit' => true,
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * see abstract declaration in parent class for details
86
-     */
87
-    protected function _set_valid_shortcodes()
88
-    {
89
-        //remember by leaving the other fields not set, those fields will inherit the valid shortcodes from the
90
-        // message type.
91
-        $this->_valid_shortcodes = array(
92
-            'to'   => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
93
-            'cc' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
94
-            'from' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
95
-        );
96
-    }
97
-
98
-
99
-    /**
100
-     * see abstract declaration in parent class for details
101
-     *
102
-     * @access protected
103
-     * @return void
104
-     */
105
-    protected function _set_validator_config()
106
-    {
107
-        $valid_shortcodes = $this->get_valid_shortcodes();
108
-
109
-        $this->_validator_config = array(
110
-            'to'            => array(
111
-                'shortcodes' => $valid_shortcodes['to'],
112
-                'type'       => 'email',
113
-            ),
114
-            'cc' => array(
115
-                'shortcodes' => $valid_shortcodes['to'],
116
-                'type' => 'email',
117
-            ),
118
-            'from'          => array(
119
-                'shortcodes' => $valid_shortcodes['from'],
120
-                'type'       => 'email',
121
-            ),
122
-            'subject'       => array(
123
-                'shortcodes' => array(
124
-                    'organization',
125
-                    'primary_registration_details',
126
-                    'event_author',
127
-                    'primary_registration_details',
128
-                    'recipient_details',
129
-                ),
130
-            ),
131
-            'content'       => array(
132
-                'shortcodes' => array(
133
-                    'event_list',
134
-                    'attendee_list',
135
-                    'ticket_list',
136
-                    'organization',
137
-                    'primary_registration_details',
138
-                    'primary_registration_list',
139
-                    'event_author',
140
-                    'recipient_details',
141
-                    'recipient_list',
142
-                    'transaction',
143
-                    'messenger',
144
-                ),
145
-            ),
146
-            'attendee_list' => array(
147
-                'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
148
-                'required'   => array('[ATTENDEE_LIST]'),
149
-            ),
150
-            'event_list'    => array(
151
-                'shortcodes' => array(
152
-                    'event',
153
-                    'attendee_list',
154
-                    'ticket_list',
155
-                    'venue',
156
-                    'datetime_list',
157
-                    'attendee',
158
-                    'primary_registration_details',
159
-                    'primary_registration_list',
160
-                    'event_author',
161
-                    'recipient_details',
162
-                    'recipient_list',
163
-                ),
164
-                'required'   => array('[EVENT_LIST]'),
165
-            ),
166
-            'ticket_list'   => array(
167
-                'shortcodes' => array(
168
-                    'event_list',
169
-                    'attendee_list',
170
-                    'ticket',
171
-                    'datetime_list',
172
-                    'primary_registration_details',
173
-                    'recipient_details',
174
-                ),
175
-                'required'   => array('[TICKET_LIST]'),
176
-            ),
177
-            'datetime_list' => array(
178
-                'shortcodes' => array('datetime'),
179
-                'required'   => array('[DATETIME_LIST]'),
180
-            ),
181
-        );
182
-    }
183
-
184
-
185
-    /**
186
-     * @see   parent EE_messenger class for docs
187
-     * @since 4.5.0
188
-     */
189
-    public function do_secondary_messenger_hooks($sending_messenger_name)
190
-    {
191
-        if ($sending_messenger_name = 'html') {
192
-            add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
193
-        }
194
-    }
195
-
196
-
197
-    public function add_email_css(
198
-        $variation_path,
199
-        $messenger,
200
-        $message_type,
201
-        $type,
202
-        $variation,
203
-        $file_extension,
204
-        $url,
205
-        EE_Messages_Template_Pack $template_pack
206
-    ) {
207
-        //prevent recursion on this callback.
208
-        remove_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10);
209
-        $variation = $this->get_variation($template_pack, $message_type, $url, 'main', $variation, false);
210
-
211
-        add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
212
-        return $variation;
213
-    }
214
-
215
-
216
-    /**
217
-     * See parent for details
218
-     *
219
-     * @access protected
220
-     * @return void
221
-     */
222
-    protected function _set_test_settings_fields()
223
-    {
224
-        $this->_test_settings_fields = array(
225
-            'to'      => array(
226
-                'input'      => 'text',
227
-                'label'      => esc_html__('Send a test email to', 'event_espresso'),
228
-                'type'       => 'email',
229
-                'required'   => true,
230
-                'validation' => true,
231
-                'css_class'  => 'large-text',
232
-                'format'     => '%s',
233
-                'default'    => get_bloginfo('admin_email'),
234
-            ),
235
-            'subject' => array(
236
-                'input'      => 'hidden',
237
-                'label'      => '',
238
-                'type'       => 'string',
239
-                'required'   => false,
240
-                'validation' => false,
241
-                'format'     => '%s',
242
-                'value'      => sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name')),
243
-                'default'    => '',
244
-                'css_class'  => '',
245
-            ),
246
-        );
247
-    }
248
-
249
-
250
-    /**
251
-     * _set_template_fields
252
-     * This sets up the fields that a messenger requires for the message to go out.
253
-     *
254
-     * @access  protected
255
-     * @return void
256
-     */
257
-    protected function _set_template_fields()
258
-    {
259
-        // any extra template fields that are NOT used by the messenger but will get used by a messenger field for
260
-        // shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field
261
-        // they relate to.  This is important for the Messages_admin to know what fields to display to the user.
262
-        //  Also, notice that the "values" are equal to the field type that messages admin will use to know what
263
-        // kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array
264
-        // indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be
265
-        // displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and
266
-        // will not be displayed/parsed.
267
-        $this->_template_fields = array(
268
-            'to'      => array(
269
-                'input'      => 'text',
270
-                'label'      => esc_html_x(
271
-                    'To',
272
-                    'Label for the "To" field for email addresses',
273
-                    'event_espresso'
274
-                ),
275
-                'type'       => 'string',
276
-                'required'   => true,
277
-                'validation' => true,
278
-                'css_class'  => 'large-text',
279
-                'format'     => '%s',
280
-            ),
281
-            'cc'      => array(
282
-                'input'      => 'text',
283
-                'label'      => esc_html_x(
284
-                    'CC',
285
-                    'Label for the "Carbon Copy" field used for additional email addresses',
286
-                    'event_espresso'
287
-                ),
288
-                'type'       => 'string',
289
-                'required'   => false,
290
-                'validation' => true,
291
-                'css_class'  => 'large-text',
292
-                'format'     => '%s',
293
-            ),
294
-            'from'    => array(
295
-                'input'      => 'text',
296
-                'label'      => esc_html_x(
297
-                    'From',
298
-                    'Label for the "From" field for email addresses.',
299
-                    'event_espresso'
300
-                ),
301
-                'type'       => 'string',
302
-                'required'   => true,
303
-                'validation' => true,
304
-                'css_class'  => 'large-text',
305
-                'format'     => '%s',
306
-            ),
307
-            'subject' => array(
308
-                'input'      => 'text',
309
-                'label'      => esc_html_x(
310
-                    'Subject',
311
-                    'Label for the "Subject" field (short description of contents) for emails.',
312
-                    'event_espresso'
313
-                ),
314
-                'type'       => 'string',
315
-                'required'   => true,
316
-                'validation' => true,
317
-                'css_class'  => 'large-text',
318
-                'format'     => '%s',
319
-            ),
320
-            'content' => '',
321
-            //left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
322
-            'extra'   => array(
323
-                'content' => array(
324
-                    'main'          => array(
325
-                        'input'      => 'wp_editor',
326
-                        'label'      => esc_html__('Main Content', 'event_espresso'),
327
-                        'type'       => 'string',
328
-                        'required'   => true,
329
-                        'validation' => true,
330
-                        'format'     => '%s',
331
-                        'rows'       => '15',
332
-                    ),
333
-                    'event_list'    => array(
334
-                        'input'               => 'wp_editor',
335
-                        'label'               => '[EVENT_LIST]',
336
-                        'type'                => 'string',
337
-                        'required'            => true,
338
-                        'validation'          => true,
339
-                        'format'              => '%s',
340
-                        'rows'                => '15',
341
-                        'shortcodes_required' => array('[EVENT_LIST]'),
342
-                    ),
343
-                    'attendee_list' => array(
344
-                        'input'               => 'textarea',
345
-                        'label'               => '[ATTENDEE_LIST]',
346
-                        'type'                => 'string',
347
-                        'required'            => true,
348
-                        'validation'          => true,
349
-                        'format'              => '%s',
350
-                        'css_class'           => 'large-text',
351
-                        'rows'                => '5',
352
-                        'shortcodes_required' => array('[ATTENDEE_LIST]'),
353
-                    ),
354
-                    'ticket_list'   => array(
355
-                        'input'               => 'textarea',
356
-                        'label'               => '[TICKET_LIST]',
357
-                        'type'                => 'string',
358
-                        'required'            => true,
359
-                        'validation'          => true,
360
-                        'format'              => '%s',
361
-                        'css_class'           => 'large-text',
362
-                        'rows'                => '10',
363
-                        'shortcodes_required' => array('[TICKET_LIST]'),
364
-                    ),
365
-                    'datetime_list' => array(
366
-                        'input'               => 'textarea',
367
-                        'label'               => '[DATETIME_LIST]',
368
-                        'type'                => 'string',
369
-                        'required'            => true,
370
-                        'validation'          => true,
371
-                        'format'              => '%s',
372
-                        'css_class'           => 'large-text',
373
-                        'rows'                => '10',
374
-                        'shortcodes_required' => array('[DATETIME_LIST]'),
375
-                    ),
376
-                ),
377
-            ),
378
-        );
379
-    }
380
-
381
-
382
-    /**
383
-     * See definition of this class in parent
384
-     */
385
-    protected function _set_default_message_types()
386
-    {
387
-        $this->_default_message_types = array(
388
-            'payment',
389
-            'payment_refund',
390
-            'registration',
391
-            'not_approved_registration',
392
-            'pending_approval',
393
-        );
394
-    }
395
-
396
-
397
-    /**
398
-     * @see   definition of this class in parent
399
-     * @since 4.5.0
400
-     */
401
-    protected function _set_valid_message_types()
402
-    {
403
-        $this->_valid_message_types = array(
404
-            'payment',
405
-            'registration',
406
-            'not_approved_registration',
407
-            'declined_registration',
408
-            'cancelled_registration',
409
-            'pending_approval',
410
-            'registration_summary',
411
-            'payment_reminder',
412
-            'payment_declined',
413
-            'payment_refund',
414
-        );
415
-    }
416
-
417
-
418
-    /**
419
-     * setting up admin_settings_fields for messenger.
420
-     */
421
-    protected function _set_admin_settings_fields()
422
-    {
423
-    }
424
-
425
-    /**
426
-     * We just deliver the messages don't kill us!!
427
-     *
428
-     * @return bool|WP_Error true if message delivered, false if it didn't deliver OR bubble up any error object if
429
-     *              present.
430
-     * @throws EE_Error
431
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
432
-     */
433
-    protected function _send_message()
434
-    {
435
-        $success = wp_mail(
436
-            $this->_to,
437
-            //some old values for subject may be expecting HTML entities to be decoded in the subject
438
-            //and subjects aren't interpreted as HTML, so there should be no HTML in them
439
-            wp_strip_all_tags(wp_specialchars_decode($this->_subject, ENT_QUOTES)),
440
-            $this->_body(),
441
-            $this->_headers()
442
-        );
443
-        if (! $success) {
444
-            EE_Error::add_error(
445
-                sprintf(
446
-                    esc_html__(
447
-                        'The email did not send successfully.%3$sThe WordPress wp_mail function is used for sending mails but does not give any useful information when an email fails to send.%3$sIt is possible the "to" address (%1$s) or "from" address (%2$s) is invalid.%3$s',
448
-                        'event_espresso'
449
-                    ),
450
-                    $this->_to,
451
-                    $this->_from,
452
-                    '<br />'
453
-                ),
454
-                __FILE__,
455
-                __FUNCTION__,
456
-                __LINE__
457
-            );
458
-        }
459
-        return $success;
460
-    }
461
-
462
-
463
-    /**
464
-     * see parent for definition
465
-     *
466
-     * @return string html body of the message content and the related css.
467
-     * @throws EE_Error
468
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
469
-     */
470
-    protected function _preview()
471
-    {
472
-        return $this->_body(true);
473
-    }
474
-
475
-
476
-    /**
477
-     * Setup headers for email
478
-     *
479
-     * @access protected
480
-     * @return string formatted header for email
481
-     */
482
-    protected function _headers()
483
-    {
484
-        $this->_ensure_has_from_email_address();
485
-        $from    = $this->_from;
486
-        $headers = array(
487
-            'From:' . $from,
488
-            'Reply-To:' . $from,
489
-            'Content-Type:text/html; charset=utf-8',
490
-        );
491
-
492
-        /**
493
-         * Second condition added as a result of https://events.codebasehq.com/projects/event-espresso/tickets/11416 to
494
-         * cover back compat where there may be users who have saved cc values in their db for the newsletter message
495
-         * type which they are no longer able to change.
496
-         */
497
-        if (! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
498
-            $headers[] = 'cc: ' . $this->_cc;
499
-        }
500
-
501
-        //but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
502
-        // header.
503
-        add_filter('wp_mail_from', array($this, 'set_from_address'), 100);
504
-        add_filter('wp_mail_from_name', array($this, 'set_from_name'), 100);
505
-        return apply_filters('FHEE__EE_Email_messenger___headers', $headers, $this->_incoming_message_type, $this);
506
-    }
507
-
508
-
509
-    /**
510
-     * This simply ensures that the from address is not empty.  If it is, then we use whatever is set as the site email
511
-     * address for the from address to avoid problems with sending emails.
512
-     */
513
-    protected function _ensure_has_from_email_address()
514
-    {
515
-        if (empty($this->_from)) {
516
-            $this->_from = get_bloginfo('admin_email');
517
-        }
518
-    }
519
-
520
-
521
-    /**
522
-     * This simply parses whatever is set as the $_from address and determines if it is in the format {name} <{email}>
523
-     * or just {email} and returns an array with the "from_name" and "from_email" as the values. Note from_name *MAY*
524
-     * be empty
525
-     *
526
-     * @since 4.3.1
527
-     * @return array
528
-     */
529
-    private function _parse_from()
530
-    {
531
-        if (strpos($this->_from, '<') !== false) {
532
-            $from_name = substr($this->_from, 0, strpos($this->_from, '<') - 1);
533
-            $from_name = str_replace('"', '', $from_name);
534
-            $from_name = trim($from_name);
535
-
536
-            $from_email = substr($this->_from, strpos($this->_from, '<') + 1);
537
-            $from_email = str_replace('>', '', $from_email);
538
-            $from_email = trim($from_email);
539
-        } elseif (trim($this->_from) !== '') {
540
-            $from_name  = '';
541
-            $from_email = trim($this->_from);
542
-        } else {
543
-            $from_name = $from_email = '';
544
-        }
545
-        return array($from_name, $from_email);
546
-    }
547
-
548
-
549
-    /**
550
-     * Callback for the wp_mail_from filter.
551
-     *
552
-     * @since 4.3.1
553
-     * @param string $from_email What the original from_email is.
554
-     * @return string
555
-     */
556
-    public function set_from_address($from_email)
557
-    {
558
-        $parsed_from = $this->_parse_from();
559
-        //includes fallback if the parsing failed.
560
-        $from_email = is_array($parsed_from) && ! empty($parsed_from[1])
561
-            ? $parsed_from[1]
562
-            : get_bloginfo('admin_email');
563
-        return $from_email;
564
-    }
565
-
566
-
567
-    /**
568
-     * Callback fro the wp_mail_from_name filter.
569
-     *
570
-     * @since 4.3.1
571
-     * @param string $from_name The original from_name.
572
-     * @return string
573
-     */
574
-    public function set_from_name($from_name)
575
-    {
576
-        $parsed_from = $this->_parse_from();
577
-        if (is_array($parsed_from) && ! empty($parsed_from[0])) {
578
-            $from_name = $parsed_from[0];
579
-        }
580
-
581
-        //if from name is "WordPress" let's sub in the site name instead (more friendly!)
582
-        //but realize the default name is HTML entity-encoded
583
-        $from_name = $from_name == 'WordPress' ? wp_specialchars_decode(get_bloginfo(), ENT_QUOTES) : $from_name;
584
-
585
-        return $from_name;
586
-    }
587
-
588
-
589
-    /**
590
-     * setup body for email
591
-     *
592
-     * @param bool $preview will determine whether this is preview template or not.
593
-     * @return string formatted body for email.
594
-     * @throws EE_Error
595
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
596
-     */
597
-    protected function _body($preview = false)
598
-    {
599
-        //setup template args!
600
-        $this->_template_args = array(
601
-            'subject'   => $this->_subject,
602
-            'from'      => $this->_from,
603
-            'main_body' => wpautop($this->_content),
604
-        );
605
-        $body                 = $this->_get_main_template($preview);
606
-
607
-        /**
608
-         * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
609
-         *
610
-         * @type    bool $preview Indicates whether a preview is being generated or not.
611
-         * @return  bool    true  indicates to use the inliner, false bypasses it.
612
-         */
613
-        if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
614
-            //require CssToInlineStyles library and its dependencies via composer autoloader
615
-            require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
616
-
617
-            //now if this isn't a preview, let's setup the body so it has inline styles
618
-            if (! $preview || ($preview && defined('DOING_AJAX'))) {
619
-                $style = file_get_contents(
620
-                    $this->get_variation(
621
-                        $this->_tmp_pack,
622
-                        $this->_incoming_message_type->name,
623
-                        false,
624
-                        'main',
625
-                        $this->_variation
626
-                    ),
627
-                    true
628
-                );
629
-                $CSS   = new TijsVerkoyen\CssToInlineStyles\CssToInlineStyles($body, $style);
630
-                //for some reason the library has a bracket and new line at the beginning.  This takes care of that.
631
-                $body  = ltrim($CSS->convert(true), ">\n");
632
-                //see https://events.codebasehq.com/projects/event-espresso/tickets/8609
633
-                $body  = ltrim($body, "<?");
634
-            }
635
-
636
-        }
637
-        return $body;
638
-    }
639
-
640
-
641
-    /**
642
-     * This just returns any existing test settings that might be saved in the database
643
-     *
644
-     * @access public
645
-     * @return array
646
-     */
647
-    public function get_existing_test_settings()
648
-    {
649
-        $settings = parent::get_existing_test_settings();
650
-        //override subject if present because we always want it to be fresh.
651
-        if (is_array($settings) && ! empty($settings['subject'])) {
652
-            $settings['subject'] = sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name'));
653
-        }
654
-        return $settings;
655
-    }
11
+	/**
12
+	 * To field for email
13
+	 * @var string
14
+	 */
15
+	protected $_to = '';
16
+
17
+
18
+	/**
19
+	 * CC field for email.
20
+	 * @var string
21
+	 */
22
+	protected $_cc = '';
23
+
24
+	/**
25
+	 * From field for email
26
+	 * @var string
27
+	 */
28
+	protected $_from = '';
29
+
30
+
31
+	/**
32
+	 * Subject field for email
33
+	 * @var string
34
+	 */
35
+	protected $_subject = '';
36
+
37
+
38
+	/**
39
+	 * Content field for email
40
+	 * @var string
41
+	 */
42
+	protected $_content = '';
43
+
44
+
45
+	/**
46
+	 * constructor
47
+	 *
48
+	 * @access public
49
+	 */
50
+	public function __construct()
51
+	{
52
+		//set name and description properties
53
+		$this->name                = 'email';
54
+		$this->description         = sprintf(
55
+			esc_html__(
56
+				'This messenger delivers messages via email using the built-in %s function included with WordPress',
57
+				'event_espresso'
58
+			),
59
+			'<code>wp_mail</code>'
60
+		);
61
+		$this->label               = array(
62
+			'singular' => esc_html__('email', 'event_espresso'),
63
+			'plural'   => esc_html__('emails', 'event_espresso'),
64
+		);
65
+		$this->activate_on_install = true;
66
+
67
+		//we're using defaults so let's call parent constructor that will take care of setting up all the other
68
+		// properties
69
+		parent::__construct();
70
+	}
71
+
72
+
73
+	/**
74
+	 * see abstract declaration in parent class for details.
75
+	 */
76
+	protected function _set_admin_pages()
77
+	{
78
+		$this->admin_registered_pages = array(
79
+			'events_edit' => true,
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * see abstract declaration in parent class for details
86
+	 */
87
+	protected function _set_valid_shortcodes()
88
+	{
89
+		//remember by leaving the other fields not set, those fields will inherit the valid shortcodes from the
90
+		// message type.
91
+		$this->_valid_shortcodes = array(
92
+			'to'   => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
93
+			'cc' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
94
+			'from' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
95
+		);
96
+	}
97
+
98
+
99
+	/**
100
+	 * see abstract declaration in parent class for details
101
+	 *
102
+	 * @access protected
103
+	 * @return void
104
+	 */
105
+	protected function _set_validator_config()
106
+	{
107
+		$valid_shortcodes = $this->get_valid_shortcodes();
108
+
109
+		$this->_validator_config = array(
110
+			'to'            => array(
111
+				'shortcodes' => $valid_shortcodes['to'],
112
+				'type'       => 'email',
113
+			),
114
+			'cc' => array(
115
+				'shortcodes' => $valid_shortcodes['to'],
116
+				'type' => 'email',
117
+			),
118
+			'from'          => array(
119
+				'shortcodes' => $valid_shortcodes['from'],
120
+				'type'       => 'email',
121
+			),
122
+			'subject'       => array(
123
+				'shortcodes' => array(
124
+					'organization',
125
+					'primary_registration_details',
126
+					'event_author',
127
+					'primary_registration_details',
128
+					'recipient_details',
129
+				),
130
+			),
131
+			'content'       => array(
132
+				'shortcodes' => array(
133
+					'event_list',
134
+					'attendee_list',
135
+					'ticket_list',
136
+					'organization',
137
+					'primary_registration_details',
138
+					'primary_registration_list',
139
+					'event_author',
140
+					'recipient_details',
141
+					'recipient_list',
142
+					'transaction',
143
+					'messenger',
144
+				),
145
+			),
146
+			'attendee_list' => array(
147
+				'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
148
+				'required'   => array('[ATTENDEE_LIST]'),
149
+			),
150
+			'event_list'    => array(
151
+				'shortcodes' => array(
152
+					'event',
153
+					'attendee_list',
154
+					'ticket_list',
155
+					'venue',
156
+					'datetime_list',
157
+					'attendee',
158
+					'primary_registration_details',
159
+					'primary_registration_list',
160
+					'event_author',
161
+					'recipient_details',
162
+					'recipient_list',
163
+				),
164
+				'required'   => array('[EVENT_LIST]'),
165
+			),
166
+			'ticket_list'   => array(
167
+				'shortcodes' => array(
168
+					'event_list',
169
+					'attendee_list',
170
+					'ticket',
171
+					'datetime_list',
172
+					'primary_registration_details',
173
+					'recipient_details',
174
+				),
175
+				'required'   => array('[TICKET_LIST]'),
176
+			),
177
+			'datetime_list' => array(
178
+				'shortcodes' => array('datetime'),
179
+				'required'   => array('[DATETIME_LIST]'),
180
+			),
181
+		);
182
+	}
183
+
184
+
185
+	/**
186
+	 * @see   parent EE_messenger class for docs
187
+	 * @since 4.5.0
188
+	 */
189
+	public function do_secondary_messenger_hooks($sending_messenger_name)
190
+	{
191
+		if ($sending_messenger_name = 'html') {
192
+			add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
193
+		}
194
+	}
195
+
196
+
197
+	public function add_email_css(
198
+		$variation_path,
199
+		$messenger,
200
+		$message_type,
201
+		$type,
202
+		$variation,
203
+		$file_extension,
204
+		$url,
205
+		EE_Messages_Template_Pack $template_pack
206
+	) {
207
+		//prevent recursion on this callback.
208
+		remove_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10);
209
+		$variation = $this->get_variation($template_pack, $message_type, $url, 'main', $variation, false);
210
+
211
+		add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
212
+		return $variation;
213
+	}
214
+
215
+
216
+	/**
217
+	 * See parent for details
218
+	 *
219
+	 * @access protected
220
+	 * @return void
221
+	 */
222
+	protected function _set_test_settings_fields()
223
+	{
224
+		$this->_test_settings_fields = array(
225
+			'to'      => array(
226
+				'input'      => 'text',
227
+				'label'      => esc_html__('Send a test email to', 'event_espresso'),
228
+				'type'       => 'email',
229
+				'required'   => true,
230
+				'validation' => true,
231
+				'css_class'  => 'large-text',
232
+				'format'     => '%s',
233
+				'default'    => get_bloginfo('admin_email'),
234
+			),
235
+			'subject' => array(
236
+				'input'      => 'hidden',
237
+				'label'      => '',
238
+				'type'       => 'string',
239
+				'required'   => false,
240
+				'validation' => false,
241
+				'format'     => '%s',
242
+				'value'      => sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name')),
243
+				'default'    => '',
244
+				'css_class'  => '',
245
+			),
246
+		);
247
+	}
248
+
249
+
250
+	/**
251
+	 * _set_template_fields
252
+	 * This sets up the fields that a messenger requires for the message to go out.
253
+	 *
254
+	 * @access  protected
255
+	 * @return void
256
+	 */
257
+	protected function _set_template_fields()
258
+	{
259
+		// any extra template fields that are NOT used by the messenger but will get used by a messenger field for
260
+		// shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field
261
+		// they relate to.  This is important for the Messages_admin to know what fields to display to the user.
262
+		//  Also, notice that the "values" are equal to the field type that messages admin will use to know what
263
+		// kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array
264
+		// indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be
265
+		// displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and
266
+		// will not be displayed/parsed.
267
+		$this->_template_fields = array(
268
+			'to'      => array(
269
+				'input'      => 'text',
270
+				'label'      => esc_html_x(
271
+					'To',
272
+					'Label for the "To" field for email addresses',
273
+					'event_espresso'
274
+				),
275
+				'type'       => 'string',
276
+				'required'   => true,
277
+				'validation' => true,
278
+				'css_class'  => 'large-text',
279
+				'format'     => '%s',
280
+			),
281
+			'cc'      => array(
282
+				'input'      => 'text',
283
+				'label'      => esc_html_x(
284
+					'CC',
285
+					'Label for the "Carbon Copy" field used for additional email addresses',
286
+					'event_espresso'
287
+				),
288
+				'type'       => 'string',
289
+				'required'   => false,
290
+				'validation' => true,
291
+				'css_class'  => 'large-text',
292
+				'format'     => '%s',
293
+			),
294
+			'from'    => array(
295
+				'input'      => 'text',
296
+				'label'      => esc_html_x(
297
+					'From',
298
+					'Label for the "From" field for email addresses.',
299
+					'event_espresso'
300
+				),
301
+				'type'       => 'string',
302
+				'required'   => true,
303
+				'validation' => true,
304
+				'css_class'  => 'large-text',
305
+				'format'     => '%s',
306
+			),
307
+			'subject' => array(
308
+				'input'      => 'text',
309
+				'label'      => esc_html_x(
310
+					'Subject',
311
+					'Label for the "Subject" field (short description of contents) for emails.',
312
+					'event_espresso'
313
+				),
314
+				'type'       => 'string',
315
+				'required'   => true,
316
+				'validation' => true,
317
+				'css_class'  => 'large-text',
318
+				'format'     => '%s',
319
+			),
320
+			'content' => '',
321
+			//left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
322
+			'extra'   => array(
323
+				'content' => array(
324
+					'main'          => array(
325
+						'input'      => 'wp_editor',
326
+						'label'      => esc_html__('Main Content', 'event_espresso'),
327
+						'type'       => 'string',
328
+						'required'   => true,
329
+						'validation' => true,
330
+						'format'     => '%s',
331
+						'rows'       => '15',
332
+					),
333
+					'event_list'    => array(
334
+						'input'               => 'wp_editor',
335
+						'label'               => '[EVENT_LIST]',
336
+						'type'                => 'string',
337
+						'required'            => true,
338
+						'validation'          => true,
339
+						'format'              => '%s',
340
+						'rows'                => '15',
341
+						'shortcodes_required' => array('[EVENT_LIST]'),
342
+					),
343
+					'attendee_list' => array(
344
+						'input'               => 'textarea',
345
+						'label'               => '[ATTENDEE_LIST]',
346
+						'type'                => 'string',
347
+						'required'            => true,
348
+						'validation'          => true,
349
+						'format'              => '%s',
350
+						'css_class'           => 'large-text',
351
+						'rows'                => '5',
352
+						'shortcodes_required' => array('[ATTENDEE_LIST]'),
353
+					),
354
+					'ticket_list'   => array(
355
+						'input'               => 'textarea',
356
+						'label'               => '[TICKET_LIST]',
357
+						'type'                => 'string',
358
+						'required'            => true,
359
+						'validation'          => true,
360
+						'format'              => '%s',
361
+						'css_class'           => 'large-text',
362
+						'rows'                => '10',
363
+						'shortcodes_required' => array('[TICKET_LIST]'),
364
+					),
365
+					'datetime_list' => array(
366
+						'input'               => 'textarea',
367
+						'label'               => '[DATETIME_LIST]',
368
+						'type'                => 'string',
369
+						'required'            => true,
370
+						'validation'          => true,
371
+						'format'              => '%s',
372
+						'css_class'           => 'large-text',
373
+						'rows'                => '10',
374
+						'shortcodes_required' => array('[DATETIME_LIST]'),
375
+					),
376
+				),
377
+			),
378
+		);
379
+	}
380
+
381
+
382
+	/**
383
+	 * See definition of this class in parent
384
+	 */
385
+	protected function _set_default_message_types()
386
+	{
387
+		$this->_default_message_types = array(
388
+			'payment',
389
+			'payment_refund',
390
+			'registration',
391
+			'not_approved_registration',
392
+			'pending_approval',
393
+		);
394
+	}
395
+
396
+
397
+	/**
398
+	 * @see   definition of this class in parent
399
+	 * @since 4.5.0
400
+	 */
401
+	protected function _set_valid_message_types()
402
+	{
403
+		$this->_valid_message_types = array(
404
+			'payment',
405
+			'registration',
406
+			'not_approved_registration',
407
+			'declined_registration',
408
+			'cancelled_registration',
409
+			'pending_approval',
410
+			'registration_summary',
411
+			'payment_reminder',
412
+			'payment_declined',
413
+			'payment_refund',
414
+		);
415
+	}
416
+
417
+
418
+	/**
419
+	 * setting up admin_settings_fields for messenger.
420
+	 */
421
+	protected function _set_admin_settings_fields()
422
+	{
423
+	}
424
+
425
+	/**
426
+	 * We just deliver the messages don't kill us!!
427
+	 *
428
+	 * @return bool|WP_Error true if message delivered, false if it didn't deliver OR bubble up any error object if
429
+	 *              present.
430
+	 * @throws EE_Error
431
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
432
+	 */
433
+	protected function _send_message()
434
+	{
435
+		$success = wp_mail(
436
+			$this->_to,
437
+			//some old values for subject may be expecting HTML entities to be decoded in the subject
438
+			//and subjects aren't interpreted as HTML, so there should be no HTML in them
439
+			wp_strip_all_tags(wp_specialchars_decode($this->_subject, ENT_QUOTES)),
440
+			$this->_body(),
441
+			$this->_headers()
442
+		);
443
+		if (! $success) {
444
+			EE_Error::add_error(
445
+				sprintf(
446
+					esc_html__(
447
+						'The email did not send successfully.%3$sThe WordPress wp_mail function is used for sending mails but does not give any useful information when an email fails to send.%3$sIt is possible the "to" address (%1$s) or "from" address (%2$s) is invalid.%3$s',
448
+						'event_espresso'
449
+					),
450
+					$this->_to,
451
+					$this->_from,
452
+					'<br />'
453
+				),
454
+				__FILE__,
455
+				__FUNCTION__,
456
+				__LINE__
457
+			);
458
+		}
459
+		return $success;
460
+	}
461
+
462
+
463
+	/**
464
+	 * see parent for definition
465
+	 *
466
+	 * @return string html body of the message content and the related css.
467
+	 * @throws EE_Error
468
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
469
+	 */
470
+	protected function _preview()
471
+	{
472
+		return $this->_body(true);
473
+	}
474
+
475
+
476
+	/**
477
+	 * Setup headers for email
478
+	 *
479
+	 * @access protected
480
+	 * @return string formatted header for email
481
+	 */
482
+	protected function _headers()
483
+	{
484
+		$this->_ensure_has_from_email_address();
485
+		$from    = $this->_from;
486
+		$headers = array(
487
+			'From:' . $from,
488
+			'Reply-To:' . $from,
489
+			'Content-Type:text/html; charset=utf-8',
490
+		);
491
+
492
+		/**
493
+		 * Second condition added as a result of https://events.codebasehq.com/projects/event-espresso/tickets/11416 to
494
+		 * cover back compat where there may be users who have saved cc values in their db for the newsletter message
495
+		 * type which they are no longer able to change.
496
+		 */
497
+		if (! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
498
+			$headers[] = 'cc: ' . $this->_cc;
499
+		}
500
+
501
+		//but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
502
+		// header.
503
+		add_filter('wp_mail_from', array($this, 'set_from_address'), 100);
504
+		add_filter('wp_mail_from_name', array($this, 'set_from_name'), 100);
505
+		return apply_filters('FHEE__EE_Email_messenger___headers', $headers, $this->_incoming_message_type, $this);
506
+	}
507
+
508
+
509
+	/**
510
+	 * This simply ensures that the from address is not empty.  If it is, then we use whatever is set as the site email
511
+	 * address for the from address to avoid problems with sending emails.
512
+	 */
513
+	protected function _ensure_has_from_email_address()
514
+	{
515
+		if (empty($this->_from)) {
516
+			$this->_from = get_bloginfo('admin_email');
517
+		}
518
+	}
519
+
520
+
521
+	/**
522
+	 * This simply parses whatever is set as the $_from address and determines if it is in the format {name} <{email}>
523
+	 * or just {email} and returns an array with the "from_name" and "from_email" as the values. Note from_name *MAY*
524
+	 * be empty
525
+	 *
526
+	 * @since 4.3.1
527
+	 * @return array
528
+	 */
529
+	private function _parse_from()
530
+	{
531
+		if (strpos($this->_from, '<') !== false) {
532
+			$from_name = substr($this->_from, 0, strpos($this->_from, '<') - 1);
533
+			$from_name = str_replace('"', '', $from_name);
534
+			$from_name = trim($from_name);
535
+
536
+			$from_email = substr($this->_from, strpos($this->_from, '<') + 1);
537
+			$from_email = str_replace('>', '', $from_email);
538
+			$from_email = trim($from_email);
539
+		} elseif (trim($this->_from) !== '') {
540
+			$from_name  = '';
541
+			$from_email = trim($this->_from);
542
+		} else {
543
+			$from_name = $from_email = '';
544
+		}
545
+		return array($from_name, $from_email);
546
+	}
547
+
548
+
549
+	/**
550
+	 * Callback for the wp_mail_from filter.
551
+	 *
552
+	 * @since 4.3.1
553
+	 * @param string $from_email What the original from_email is.
554
+	 * @return string
555
+	 */
556
+	public function set_from_address($from_email)
557
+	{
558
+		$parsed_from = $this->_parse_from();
559
+		//includes fallback if the parsing failed.
560
+		$from_email = is_array($parsed_from) && ! empty($parsed_from[1])
561
+			? $parsed_from[1]
562
+			: get_bloginfo('admin_email');
563
+		return $from_email;
564
+	}
565
+
566
+
567
+	/**
568
+	 * Callback fro the wp_mail_from_name filter.
569
+	 *
570
+	 * @since 4.3.1
571
+	 * @param string $from_name The original from_name.
572
+	 * @return string
573
+	 */
574
+	public function set_from_name($from_name)
575
+	{
576
+		$parsed_from = $this->_parse_from();
577
+		if (is_array($parsed_from) && ! empty($parsed_from[0])) {
578
+			$from_name = $parsed_from[0];
579
+		}
580
+
581
+		//if from name is "WordPress" let's sub in the site name instead (more friendly!)
582
+		//but realize the default name is HTML entity-encoded
583
+		$from_name = $from_name == 'WordPress' ? wp_specialchars_decode(get_bloginfo(), ENT_QUOTES) : $from_name;
584
+
585
+		return $from_name;
586
+	}
587
+
588
+
589
+	/**
590
+	 * setup body for email
591
+	 *
592
+	 * @param bool $preview will determine whether this is preview template or not.
593
+	 * @return string formatted body for email.
594
+	 * @throws EE_Error
595
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
596
+	 */
597
+	protected function _body($preview = false)
598
+	{
599
+		//setup template args!
600
+		$this->_template_args = array(
601
+			'subject'   => $this->_subject,
602
+			'from'      => $this->_from,
603
+			'main_body' => wpautop($this->_content),
604
+		);
605
+		$body                 = $this->_get_main_template($preview);
606
+
607
+		/**
608
+		 * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
609
+		 *
610
+		 * @type    bool $preview Indicates whether a preview is being generated or not.
611
+		 * @return  bool    true  indicates to use the inliner, false bypasses it.
612
+		 */
613
+		if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
614
+			//require CssToInlineStyles library and its dependencies via composer autoloader
615
+			require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
616
+
617
+			//now if this isn't a preview, let's setup the body so it has inline styles
618
+			if (! $preview || ($preview && defined('DOING_AJAX'))) {
619
+				$style = file_get_contents(
620
+					$this->get_variation(
621
+						$this->_tmp_pack,
622
+						$this->_incoming_message_type->name,
623
+						false,
624
+						'main',
625
+						$this->_variation
626
+					),
627
+					true
628
+				);
629
+				$CSS   = new TijsVerkoyen\CssToInlineStyles\CssToInlineStyles($body, $style);
630
+				//for some reason the library has a bracket and new line at the beginning.  This takes care of that.
631
+				$body  = ltrim($CSS->convert(true), ">\n");
632
+				//see https://events.codebasehq.com/projects/event-espresso/tickets/8609
633
+				$body  = ltrim($body, "<?");
634
+			}
635
+
636
+		}
637
+		return $body;
638
+	}
639
+
640
+
641
+	/**
642
+	 * This just returns any existing test settings that might be saved in the database
643
+	 *
644
+	 * @access public
645
+	 * @return array
646
+	 */
647
+	public function get_existing_test_settings()
648
+	{
649
+		$settings = parent::get_existing_test_settings();
650
+		//override subject if present because we always want it to be fresh.
651
+		if (is_array($settings) && ! empty($settings['subject'])) {
652
+			$settings['subject'] = sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name'));
653
+		}
654
+		return $settings;
655
+	}
656 656
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
             ),
59 59
             '<code>wp_mail</code>'
60 60
         );
61
-        $this->label               = array(
61
+        $this->label = array(
62 62
             'singular' => esc_html__('email', 'event_espresso'),
63 63
             'plural'   => esc_html__('emails', 'event_espresso'),
64 64
         );
@@ -440,7 +440,7 @@  discard block
 block discarded – undo
440 440
             $this->_body(),
441 441
             $this->_headers()
442 442
         );
443
-        if (! $success) {
443
+        if ( ! $success) {
444 444
             EE_Error::add_error(
445 445
                 sprintf(
446 446
                     esc_html__(
@@ -484,8 +484,8 @@  discard block
 block discarded – undo
484 484
         $this->_ensure_has_from_email_address();
485 485
         $from    = $this->_from;
486 486
         $headers = array(
487
-            'From:' . $from,
488
-            'Reply-To:' . $from,
487
+            'From:'.$from,
488
+            'Reply-To:'.$from,
489 489
             'Content-Type:text/html; charset=utf-8',
490 490
         );
491 491
 
@@ -494,8 +494,8 @@  discard block
 block discarded – undo
494 494
          * cover back compat where there may be users who have saved cc values in their db for the newsletter message
495 495
          * type which they are no longer able to change.
496 496
          */
497
-        if (! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
498
-            $headers[] = 'cc: ' . $this->_cc;
497
+        if ( ! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
498
+            $headers[] = 'cc: '.$this->_cc;
499 499
         }
500 500
 
501 501
         //but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
@@ -602,7 +602,7 @@  discard block
 block discarded – undo
602 602
             'from'      => $this->_from,
603 603
             'main_body' => wpautop($this->_content),
604 604
         );
605
-        $body                 = $this->_get_main_template($preview);
605
+        $body = $this->_get_main_template($preview);
606 606
 
607 607
         /**
608 608
          * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
@@ -612,10 +612,10 @@  discard block
 block discarded – undo
612 612
          */
613 613
         if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
614 614
             //require CssToInlineStyles library and its dependencies via composer autoloader
615
-            require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
615
+            require_once EE_THIRD_PARTY.'cssinliner/vendor/autoload.php';
616 616
 
617 617
             //now if this isn't a preview, let's setup the body so it has inline styles
618
-            if (! $preview || ($preview && defined('DOING_AJAX'))) {
618
+            if ( ! $preview || ($preview && defined('DOING_AJAX'))) {
619 619
                 $style = file_get_contents(
620 620
                     $this->get_variation(
621 621
                         $this->_tmp_pack,
Please login to merge, or discard this patch.