Completed
Branch BUG/reg-status-change-recursio... (fbd515)
by
unknown
09:28 queued 36s
created
core/helpers/EEH_Line_Item.helper.php 1 patch
Indentation   +1685 added lines, -1685 removed lines patch added patch discarded remove patch
@@ -20,1689 +20,1689 @@
 block discarded – undo
20 20
 class EEH_Line_Item
21 21
 {
22 22
 
23
-    // other functions: cancel ticket purchase
24
-    // delete ticket purchase
25
-    // add promotion
26
-
27
-
28
-    /**
29
-     * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
30
-     * Does NOT automatically re-calculate the line item totals or update the related transaction.
31
-     * You should call recalculate_total_including_taxes() on the grant total line item after this
32
-     * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
33
-     * to keep the registration final prices in-sync with the transaction's total.
34
-     *
35
-     * @param EE_Line_Item $parent_line_item
36
-     * @param string $name
37
-     * @param float $unit_price
38
-     * @param string $description
39
-     * @param int $quantity
40
-     * @param boolean $taxable
41
-     * @param boolean $code if set to a value, ensures there is only one line item with that code
42
-     * @return boolean success
43
-     * @throws \EE_Error
44
-     */
45
-    public static function add_unrelated_item(EE_Line_Item $parent_line_item, $name, $unit_price, $description = '', $quantity = 1, $taxable = false, $code = null)
46
-    {
47
-        $items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
48
-        $line_item = EE_Line_Item::new_instance(array(
49
-            'LIN_name' => $name,
50
-            'LIN_desc' => $description,
51
-            'LIN_unit_price' => $unit_price,
52
-            'LIN_quantity' => $quantity,
53
-            'LIN_percent' => null,
54
-            'LIN_is_taxable' => $taxable,
55
-            'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
56
-            'LIN_total' => (float) $unit_price * (int) $quantity,
57
-            'LIN_type' => EEM_Line_Item::type_line_item,
58
-            'LIN_code' => $code,
59
-        ));
60
-        $line_item = apply_filters(
61
-            'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
62
-            $line_item,
63
-            $parent_line_item
64
-        );
65
-        return self::add_item($parent_line_item, $line_item);
66
-    }
67
-
68
-
69
-    /**
70
-     * Adds a simple item ( unrelated to any other model object) to the total line item,
71
-     * in the correct spot in the line item tree. Automatically
72
-     * re-calculates the line item totals and updates the related transaction. But
73
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
74
-     * should probably change because of this).
75
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
76
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
77
-     *
78
-     * @param EE_Line_Item $parent_line_item
79
-     * @param string $name
80
-     * @param float $percentage_amount
81
-     * @param string $description
82
-     * @param boolean $taxable
83
-     * @return boolean success
84
-     * @throws \EE_Error
85
-     */
86
-    public static function add_percentage_based_item(EE_Line_Item $parent_line_item, $name, $percentage_amount, $description = '', $taxable = false)
87
-    {
88
-        $line_item = EE_Line_Item::new_instance(array(
89
-            'LIN_name' => $name,
90
-            'LIN_desc' => $description,
91
-            'LIN_unit_price' => 0,
92
-            'LIN_percent' => $percentage_amount,
93
-            'LIN_quantity' => 1,
94
-            'LIN_is_taxable' => $taxable,
95
-            'LIN_total' => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
96
-            'LIN_type' => EEM_Line_Item::type_line_item,
97
-            'LIN_parent' => $parent_line_item->ID()
98
-        ));
99
-        $line_item = apply_filters(
100
-            'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
101
-            $line_item
102
-        );
103
-        return $parent_line_item->add_child_line_item($line_item, false);
104
-    }
105
-
106
-
107
-    /**
108
-     * Returns the new line item created by adding a purchase of the ticket
109
-     * ensures that ticket line item is saved, and that cart total has been recalculated.
110
-     * If this ticket has already been purchased, just increments its count.
111
-     * Automatically re-calculates the line item totals and updates the related transaction. But
112
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
113
-     * should probably change because of this).
114
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
115
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
116
-     *
117
-     * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
118
-     * @param EE_Ticket $ticket
119
-     * @param int $qty
120
-     * @return \EE_Line_Item
121
-     * @throws \EE_Error
122
-     */
123
-    public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
124
-    {
125
-        if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) {
126
-            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()));
127
-        }
128
-        // either increment the qty for an existing ticket
129
-        $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
130
-        // or add a new one
131
-        if (!$line_item instanceof EE_Line_Item) {
132
-            $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
133
-        }
134
-        $total_line_item->recalculate_total_including_taxes();
135
-        return $line_item;
136
-    }
137
-
138
-
139
-    /**
140
-     * Returns the new line item created by adding a purchase of the ticket
141
-     * @param \EE_Line_Item $total_line_item
142
-     * @param EE_Ticket $ticket
143
-     * @param int $qty
144
-     * @return \EE_Line_Item
145
-     * @throws \EE_Error
146
-     */
147
-    public static function increment_ticket_qty_if_already_in_cart(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
148
-    {
149
-        $line_item = null;
150
-        if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
151
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
152
-            foreach ((array) $ticket_line_items as $ticket_line_item) {
153
-                if ($ticket_line_item instanceof EE_Line_Item
154
-                    && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
155
-                ) {
156
-                    $line_item = $ticket_line_item;
157
-                    break;
158
-                }
159
-            }
160
-        }
161
-        if ($line_item instanceof EE_Line_Item) {
162
-            EEH_Line_Item::increment_quantity($line_item, $qty);
163
-            return $line_item;
164
-        }
165
-        return null;
166
-    }
167
-
168
-
169
-    /**
170
-     * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
171
-     * Does NOT save or recalculate other line items totals
172
-     *
173
-     * @param EE_Line_Item $line_item
174
-     * @param int $qty
175
-     * @return void
176
-     * @throws \EE_Error
177
-     */
178
-    public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
179
-    {
180
-        if (!$line_item->is_percent()) {
181
-            $qty += $line_item->quantity();
182
-            $line_item->set_quantity($qty);
183
-            $line_item->set_total($line_item->unit_price() * $qty);
184
-            $line_item->save();
185
-        }
186
-        foreach ($line_item->children() as $child) {
187
-            if ($child->is_sub_line_item()) {
188
-                EEH_Line_Item::update_quantity($child, $qty);
189
-            }
190
-        }
191
-    }
192
-
193
-
194
-    /**
195
-     * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
196
-     * Does NOT save or recalculate other line items totals
197
-     *
198
-     * @param EE_Line_Item $line_item
199
-     * @param int $qty
200
-     * @return void
201
-     * @throws \EE_Error
202
-     */
203
-    public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
204
-    {
205
-        if (!$line_item->is_percent()) {
206
-            $qty = $line_item->quantity() - $qty;
207
-            $qty = max($qty, 0);
208
-            $line_item->set_quantity($qty);
209
-            $line_item->set_total($line_item->unit_price() * $qty);
210
-            $line_item->save();
211
-        }
212
-        foreach ($line_item->children() as $child) {
213
-            if ($child->is_sub_line_item()) {
214
-                EEH_Line_Item::update_quantity($child, $qty);
215
-            }
216
-        }
217
-    }
218
-
219
-
220
-    /**
221
-     * Updates the line item and its children's quantities to the specified number.
222
-     * Does NOT save them or recalculate totals.
223
-     *
224
-     * @param EE_Line_Item $line_item
225
-     * @param int $new_quantity
226
-     * @throws \EE_Error
227
-     */
228
-    public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
229
-    {
230
-        if (!$line_item->is_percent()) {
231
-            $line_item->set_quantity($new_quantity);
232
-            $line_item->set_total($line_item->unit_price() * $new_quantity);
233
-            $line_item->save();
234
-        }
235
-        foreach ($line_item->children() as $child) {
236
-            if ($child->is_sub_line_item()) {
237
-                EEH_Line_Item::update_quantity($child, $new_quantity);
238
-            }
239
-        }
240
-    }
241
-
242
-
243
-    /**
244
-     * Returns the new line item created by adding a purchase of the ticket
245
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
246
-     * @param EE_Ticket $ticket
247
-     * @param int $qty
248
-     * @return \EE_Line_Item
249
-     * @throws \EE_Error
250
-     */
251
-    public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
252
-    {
253
-        $datetimes = $ticket->datetimes();
254
-        $first_datetime = reset($datetimes);
255
-        if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
256
-            $first_datetime_name = $first_datetime->event()->name();
257
-        } else {
258
-            $first_datetime_name = __('Event', 'event_espresso');
259
-        }
260
-        $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
261
-        // get event subtotal line
262
-        $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
263
-        // add $ticket to cart
264
-        $line_item = EE_Line_Item::new_instance(array(
265
-            'LIN_name' => $ticket->name(),
266
-            'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
267
-            'LIN_unit_price' => $ticket->price(),
268
-            'LIN_quantity' => $qty,
269
-            'LIN_is_taxable' => $ticket->taxable(),
270
-            'LIN_order' => count($events_sub_total->children()),
271
-            'LIN_total' => $ticket->price() * $qty,
272
-            'LIN_type' => EEM_Line_Item::type_line_item,
273
-            'OBJ_ID' => $ticket->ID(),
274
-            'OBJ_type' => 'Ticket'
275
-        ));
276
-        $line_item = apply_filters(
277
-            'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
278
-            $line_item
279
-        );
280
-        $events_sub_total->add_child_line_item($line_item);
281
-        // now add the sub-line items
282
-        $running_total_for_ticket = 0;
283
-        foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
284
-            $sign = $price->is_discount() ? -1 : 1;
285
-            $price_total = $price->is_percent()
286
-                ? $running_total_for_ticket * $price->amount() / 100
287
-                : $price->amount() * $qty;
288
-            $sub_line_item = EE_Line_Item::new_instance(array(
289
-                'LIN_name' => $price->name(),
290
-                'LIN_desc' => $price->desc(),
291
-                'LIN_quantity' => $price->is_percent() ? null : $qty,
292
-                'LIN_is_taxable' => false,
293
-                'LIN_order' => $price->order(),
294
-                'LIN_total' => $sign * $price_total,
295
-                'LIN_type' => EEM_Line_Item::type_sub_line_item,
296
-                'OBJ_ID' => $price->ID(),
297
-                'OBJ_type' => 'Price'
298
-            ));
299
-            $sub_line_item = apply_filters(
300
-                'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
301
-                $sub_line_item
302
-            );
303
-            if ($price->is_percent()) {
304
-                $sub_line_item->set_percent($sign * $price->amount());
305
-            } else {
306
-                $sub_line_item->set_unit_price($sign * $price->amount());
307
-            }
308
-            $running_total_for_ticket += $price_total;
309
-            $line_item->add_child_line_item($sub_line_item);
310
-        }
311
-        return $line_item;
312
-    }
313
-
314
-
315
-    /**
316
-     * Adds the specified item under the pre-tax-sub-total line item. Automatically
317
-     * re-calculates the line item totals and updates the related transaction. But
318
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
319
-     * should probably change because of this).
320
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
321
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
322
-     *
323
-     * @param EE_Line_Item $total_line_item
324
-     * @param EE_Line_Item $item to be added
325
-     * @return boolean
326
-     * @throws \EE_Error
327
-     */
328
-    public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
329
-    {
330
-        $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
331
-        if ($pre_tax_subtotal instanceof EE_Line_Item) {
332
-            $success = $pre_tax_subtotal->add_child_line_item($item);
333
-        } else {
334
-            return false;
335
-        }
336
-        $total_line_item->recalculate_total_including_taxes();
337
-        return $success;
338
-    }
339
-
340
-
341
-    /**
342
-     * cancels an existing ticket line item,
343
-     * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
344
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
345
-     *
346
-     * @param EE_Line_Item $ticket_line_item
347
-     * @param int $qty
348
-     * @return bool success
349
-     * @throws \EE_Error
350
-     */
351
-    public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
352
-    {
353
-        // validate incoming line_item
354
-        if ($ticket_line_item->OBJ_type() !== 'Ticket') {
355
-            throw new EE_Error(
356
-                sprintf(
357
-                    __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
358
-                    $ticket_line_item->type()
359
-                )
360
-            );
361
-        }
362
-        if ($ticket_line_item->quantity() < $qty) {
363
-            throw new EE_Error(
364
-                sprintf(
365
-                    __('Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', 'event_espresso'),
366
-                    $qty,
367
-                    $ticket_line_item->quantity()
368
-                )
369
-            );
370
-        }
371
-        // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
372
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
373
-        foreach ($ticket_line_item->children() as $child_line_item) {
374
-            if ($child_line_item->is_sub_line_item()
375
-                && !$child_line_item->is_percent()
376
-                && !$child_line_item->is_cancellation()
377
-            ) {
378
-                $child_line_item->set_quantity($child_line_item->quantity() - $qty);
379
-            }
380
-        }
381
-        // get cancellation sub line item
382
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
383
-            $ticket_line_item,
384
-            EEM_Line_Item::type_cancellation
385
-        );
386
-        $cancellation_line_item = reset($cancellation_line_item);
387
-        // verify that this ticket was indeed previously cancelled
388
-        if ($cancellation_line_item instanceof EE_Line_Item) {
389
-            // increment cancelled quantity
390
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
391
-        } else {
392
-            // create cancellation sub line item
393
-            $cancellation_line_item = EE_Line_Item::new_instance(array(
394
-                'LIN_name' => __('Cancellation', 'event_espresso'),
395
-                'LIN_desc' => sprintf(
396
-                    _x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'),
397
-                    $ticket_line_item->name(),
398
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
399
-                ),
400
-                'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
401
-                'LIN_quantity' => $qty,
402
-                'LIN_is_taxable' => $ticket_line_item->is_taxable(),
403
-                'LIN_order' => count($ticket_line_item->children()),
404
-                'LIN_total' => 0, // $ticket_line_item->unit_price()
405
-                'LIN_type' => EEM_Line_Item::type_cancellation,
406
-            ));
407
-            $ticket_line_item->add_child_line_item($cancellation_line_item);
408
-        }
409
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
410
-            // decrement parent line item quantity
411
-            $event_line_item = $ticket_line_item->parent();
412
-            if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
413
-                $event_line_item->set_quantity($event_line_item->quantity() - $qty);
414
-                $event_line_item->save();
415
-            }
416
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
417
-            return true;
418
-        }
419
-        return false;
420
-    }
421
-
422
-
423
-    /**
424
-     * reinstates (un-cancels?) a previously canceled ticket line item,
425
-     * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
426
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
427
-     *
428
-     * @param EE_Line_Item $ticket_line_item
429
-     * @param int $qty
430
-     * @return bool success
431
-     * @throws \EE_Error
432
-     */
433
-    public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
434
-    {
435
-        // validate incoming line_item
436
-        if ($ticket_line_item->OBJ_type() !== 'Ticket') {
437
-            throw new EE_Error(
438
-                sprintf(
439
-                    __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
440
-                    $ticket_line_item->type()
441
-                )
442
-            );
443
-        }
444
-        // get cancellation sub line item
445
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
446
-            $ticket_line_item,
447
-            EEM_Line_Item::type_cancellation
448
-        );
449
-        $cancellation_line_item = reset($cancellation_line_item);
450
-        // verify that this ticket was indeed previously cancelled
451
-        if (!$cancellation_line_item instanceof EE_Line_Item) {
452
-            return false;
453
-        }
454
-        if ($cancellation_line_item->quantity() > $qty) {
455
-            // decrement cancelled quantity
456
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
457
-        } elseif ($cancellation_line_item->quantity() == $qty) {
458
-            // decrement cancelled quantity in case anyone still has the object kicking around
459
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
460
-            // delete because quantity will end up as 0
461
-            $cancellation_line_item->delete();
462
-            // and attempt to destroy the object,
463
-            // even though PHP won't actually destroy it until it needs the memory
464
-            unset($cancellation_line_item);
465
-        } else {
466
-            // what ?!?! negative quantity ?!?!
467
-            throw new EE_Error(
468
-                sprintf(
469
-                    __(
470
-                        'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
471
-                        'event_espresso'
472
-                    ),
473
-                    $qty,
474
-                    $cancellation_line_item->quantity()
475
-                )
476
-            );
477
-        }
478
-        // increment ticket quantity
479
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
480
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
481
-            // increment parent line item quantity
482
-            $event_line_item = $ticket_line_item->parent();
483
-            if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
484
-                $event_line_item->set_quantity($event_line_item->quantity() + $qty);
485
-            }
486
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
487
-            return true;
488
-        }
489
-        return false;
490
-    }
491
-
492
-
493
-    /**
494
-     * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
495
-     * then EE_Line_Item::recalculate_total_including_taxes() on the result
496
-     *
497
-     * @param EE_Line_Item $line_item
498
-     * @return \EE_Line_Item
499
-     */
500
-    public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
501
-    {
502
-        $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
503
-        return $grand_total_line_item->recalculate_total_including_taxes();
504
-    }
505
-
506
-
507
-    /**
508
-     * Gets the line item which contains the subtotal of all the items
509
-     *
510
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
511
-     * @return \EE_Line_Item
512
-     * @throws \EE_Error
513
-     */
514
-    public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
515
-    {
516
-        $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
517
-        return $pre_tax_subtotal instanceof EE_Line_Item
518
-            ? $pre_tax_subtotal
519
-            : self::create_pre_tax_subtotal($total_line_item);
520
-    }
521
-
522
-
523
-    /**
524
-     * Gets the line item for the taxes subtotal
525
-     *
526
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
527
-     * @return \EE_Line_Item
528
-     * @throws \EE_Error
529
-     */
530
-    public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
531
-    {
532
-        $taxes = $total_line_item->get_child_line_item('taxes');
533
-        return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
534
-    }
535
-
536
-
537
-    /**
538
-     * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
539
-     *
540
-     * @param EE_Line_Item $line_item
541
-     * @param EE_Transaction $transaction
542
-     * @return void
543
-     * @throws \EE_Error
544
-     */
545
-    public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null)
546
-    {
547
-        if ($transaction) {
548
-            /** @type EEM_Transaction $EEM_Transaction */
549
-            $EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
550
-            $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
551
-            $line_item->set_TXN_ID($TXN_ID);
552
-        }
553
-    }
554
-
555
-
556
-    /**
557
-     * Creates a new default total line item for the transaction,
558
-     * and its tickets subtotal and taxes subtotal line items (and adds the
559
-     * existing taxes as children of the taxes subtotal line item)
560
-     *
561
-     * @param EE_Transaction $transaction
562
-     * @return \EE_Line_Item of type total
563
-     * @throws \EE_Error
564
-     */
565
-    public static function create_total_line_item($transaction = null)
566
-    {
567
-        $total_line_item = EE_Line_Item::new_instance(array(
568
-            'LIN_code' => 'total',
569
-            'LIN_name' => __('Grand Total', 'event_espresso'),
570
-            'LIN_type' => EEM_Line_Item::type_total,
571
-            'OBJ_type' => 'Transaction'
572
-        ));
573
-        $total_line_item = apply_filters(
574
-            'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
575
-            $total_line_item
576
-        );
577
-        self::set_TXN_ID($total_line_item, $transaction);
578
-        self::create_pre_tax_subtotal($total_line_item, $transaction);
579
-        self::create_taxes_subtotal($total_line_item, $transaction);
580
-        return $total_line_item;
581
-    }
582
-
583
-
584
-    /**
585
-     * Creates a default items subtotal line item
586
-     *
587
-     * @param EE_Line_Item $total_line_item
588
-     * @param EE_Transaction $transaction
589
-     * @return EE_Line_Item
590
-     * @throws \EE_Error
591
-     */
592
-    protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null)
593
-    {
594
-        $pre_tax_line_item = EE_Line_Item::new_instance(array(
595
-            'LIN_code' => 'pre-tax-subtotal',
596
-            'LIN_name' => __('Pre-Tax Subtotal', 'event_espresso'),
597
-            'LIN_type' => EEM_Line_Item::type_sub_total
598
-        ));
599
-        $pre_tax_line_item = apply_filters(
600
-            'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
601
-            $pre_tax_line_item
602
-        );
603
-        self::set_TXN_ID($pre_tax_line_item, $transaction);
604
-        $total_line_item->add_child_line_item($pre_tax_line_item);
605
-        self::create_event_subtotal($pre_tax_line_item, $transaction);
606
-        return $pre_tax_line_item;
607
-    }
608
-
609
-
610
-    /**
611
-     * Creates a line item for the taxes subtotal and finds all the tax prices
612
-     * and applies taxes to it
613
-     *
614
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
615
-     * @param EE_Transaction $transaction
616
-     * @return EE_Line_Item
617
-     * @throws \EE_Error
618
-     */
619
-    protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
620
-    {
621
-        $tax_line_item = EE_Line_Item::new_instance(array(
622
-            'LIN_code' => 'taxes',
623
-            'LIN_name' => __('Taxes', 'event_espresso'),
624
-            'LIN_type' => EEM_Line_Item::type_tax_sub_total,
625
-            'LIN_order' => 1000,// this should always come last
626
-        ));
627
-        $tax_line_item = apply_filters(
628
-            'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
629
-            $tax_line_item
630
-        );
631
-        self::set_TXN_ID($tax_line_item, $transaction);
632
-        $total_line_item->add_child_line_item($tax_line_item);
633
-        // and lastly, add the actual taxes
634
-        self::apply_taxes($total_line_item);
635
-        return $tax_line_item;
636
-    }
637
-
638
-
639
-    /**
640
-     * Creates a default items subtotal line item
641
-     *
642
-     * @param EE_Line_Item $pre_tax_line_item
643
-     * @param EE_Transaction $transaction
644
-     * @param EE_Event $event
645
-     * @return EE_Line_Item
646
-     * @throws \EE_Error
647
-     */
648
-    public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null)
649
-    {
650
-        $event_line_item = EE_Line_Item::new_instance(array(
651
-            'LIN_code' => self::get_event_code($event),
652
-            'LIN_name' => self::get_event_name($event),
653
-            'LIN_desc' => self::get_event_desc($event),
654
-            'LIN_type' => EEM_Line_Item::type_sub_total,
655
-            'OBJ_type' => 'Event',
656
-            'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0
657
-        ));
658
-        $event_line_item = apply_filters(
659
-            'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
660
-            $event_line_item
661
-        );
662
-        self::set_TXN_ID($event_line_item, $transaction);
663
-        $pre_tax_line_item->add_child_line_item($event_line_item);
664
-        return $event_line_item;
665
-    }
666
-
667
-
668
-    /**
669
-     * Gets what the event ticket's code SHOULD be
670
-     *
671
-     * @param EE_Event $event
672
-     * @return string
673
-     * @throws \EE_Error
674
-     */
675
-    public static function get_event_code($event)
676
-    {
677
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
678
-    }
679
-
680
-    /**
681
-     * Gets the event name
682
-     * @param EE_Event $event
683
-     * @return string
684
-     */
685
-    public static function get_event_name($event)
686
-    {
687
-        return $event instanceof EE_Event ? mb_substr($event->name(), 0, 245) : __('Event', 'event_espresso');
688
-    }
689
-
690
-    /**
691
-     * Gets the event excerpt
692
-     * @param EE_Event $event
693
-     * @return string
694
-     */
695
-    public static function get_event_desc($event)
696
-    {
697
-        return $event instanceof EE_Event ? $event->short_description() : '';
698
-    }
699
-
700
-    /**
701
-     * Given the grand total line item and a ticket, finds the event sub-total
702
-     * line item the ticket's purchase should be added onto
703
-     *
704
-     * @access public
705
-     * @param EE_Line_Item $grand_total the grand total line item
706
-     * @param EE_Ticket $ticket
707
-     * @throws \EE_Error
708
-     * @return EE_Line_Item
709
-     */
710
-    public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
711
-    {
712
-        $first_datetime = $ticket->first_datetime();
713
-        if (!$first_datetime instanceof EE_Datetime) {
714
-            throw new EE_Error(
715
-                sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID())
716
-            );
717
-        }
718
-        $event = $first_datetime->event();
719
-        if (!$event instanceof EE_Event) {
720
-            throw new EE_Error(
721
-                sprintf(
722
-                    __('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'),
723
-                    $ticket->ID()
724
-                )
725
-            );
726
-        }
727
-        $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
728
-        if (!$events_sub_total instanceof EE_Line_Item) {
729
-            throw new EE_Error(
730
-                sprintf(
731
-                    __('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'),
732
-                    $ticket->ID(),
733
-                    $grand_total->ID()
734
-                )
735
-            );
736
-        }
737
-        return $events_sub_total;
738
-    }
739
-
740
-
741
-    /**
742
-     * Gets the event line item
743
-     *
744
-     * @param EE_Line_Item $grand_total
745
-     * @param EE_Event $event
746
-     * @return EE_Line_Item for the event subtotal which is a child of $grand_total
747
-     * @throws \EE_Error
748
-     */
749
-    public static function get_event_line_item(EE_Line_Item $grand_total, $event)
750
-    {
751
-        /** @type EE_Event $event */
752
-        $event = EEM_Event::instance()->ensure_is_obj($event, true);
753
-        $event_line_item = null;
754
-        $found = false;
755
-        foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
756
-            // default event subtotal, we should only ever find this the first time this method is called
757
-            if (!$event_line_item->OBJ_ID()) {
758
-                // let's use this! but first... set the event details
759
-                EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
760
-                $found = true;
761
-                break;
762
-            } elseif ($event_line_item->OBJ_ID() === $event->ID()) {
763
-                // found existing line item for this event in the cart, so break out of loop and use this one
764
-                $found = true;
765
-                break;
766
-            }
767
-        }
768
-        if (!$found) {
769
-            // there is no event sub-total yet, so add it
770
-            $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
771
-            // create a new "event" subtotal below that
772
-            $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
773
-            // and set the event details
774
-            EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
775
-        }
776
-        return $event_line_item;
777
-    }
778
-
779
-
780
-    /**
781
-     * Creates a default items subtotal line item
782
-     *
783
-     * @param EE_Line_Item $event_line_item
784
-     * @param EE_Event $event
785
-     * @param EE_Transaction $transaction
786
-     * @return EE_Line_Item
787
-     * @throws \EE_Error
788
-     */
789
-    public static function set_event_subtotal_details(
790
-        EE_Line_Item $event_line_item,
791
-        EE_Event $event,
792
-        $transaction = null
793
-    ) {
794
-        if ($event instanceof EE_Event) {
795
-            $event_line_item->set_code(self::get_event_code($event));
796
-            $event_line_item->set_name(self::get_event_name($event));
797
-            $event_line_item->set_desc(self::get_event_desc($event));
798
-            $event_line_item->set_OBJ_ID($event->ID());
799
-        }
800
-        self::set_TXN_ID($event_line_item, $transaction);
801
-    }
802
-
803
-
804
-    /**
805
-     * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
806
-     * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
807
-     * any old taxes are removed
808
-     *
809
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
810
-     * @throws \EE_Error
811
-     */
812
-    public static function apply_taxes(EE_Line_Item $total_line_item)
813
-    {
814
-        /** @type EEM_Price $EEM_Price */
815
-        $EEM_Price = EE_Registry::instance()->load_model('Price');
816
-        // get array of taxes via Price Model
817
-        $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
818
-        ksort($ordered_taxes);
819
-        $taxes_line_item = self::get_taxes_subtotal($total_line_item);
820
-        // just to be safe, remove its old tax line items
821
-        $taxes_line_item->delete_children_line_items();
822
-        // loop thru taxes
823
-        foreach ($ordered_taxes as $order => $taxes) {
824
-            foreach ($taxes as $tax) {
825
-                if ($tax instanceof EE_Price) {
826
-                    $tax_line_item = EE_Line_Item::new_instance(
827
-                        array(
828
-                            'LIN_name' => $tax->name(),
829
-                            'LIN_desc' => $tax->desc(),
830
-                            'LIN_percent' => $tax->amount(),
831
-                            'LIN_is_taxable' => false,
832
-                            'LIN_order' => $order,
833
-                            'LIN_total' => 0,
834
-                            'LIN_type' => EEM_Line_Item::type_tax,
835
-                            'OBJ_type' => 'Price',
836
-                            'OBJ_ID' => $tax->ID()
837
-                        )
838
-                    );
839
-                    $tax_line_item = apply_filters(
840
-                        'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
841
-                        $tax_line_item
842
-                    );
843
-                    $taxes_line_item->add_child_line_item($tax_line_item);
844
-                }
845
-            }
846
-        }
847
-        $total_line_item->recalculate_total_including_taxes();
848
-    }
849
-
850
-
851
-    /**
852
-     * Ensures that taxes have been applied to the order, if not applies them.
853
-     * Returns the total amount of tax
854
-     *
855
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
856
-     * @return float
857
-     * @throws \EE_Error
858
-     */
859
-    public static function ensure_taxes_applied($total_line_item)
860
-    {
861
-        $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
862
-        if (!$taxes_subtotal->children()) {
863
-            self::apply_taxes($total_line_item);
864
-        }
865
-        return $taxes_subtotal->total();
866
-    }
867
-
868
-
869
-    /**
870
-     * Deletes ALL children of the passed line item
871
-     *
872
-     * @param EE_Line_Item $parent_line_item
873
-     * @return bool
874
-     * @throws \EE_Error
875
-     */
876
-    public static function delete_all_child_items(EE_Line_Item $parent_line_item)
877
-    {
878
-        $deleted = 0;
879
-        foreach ($parent_line_item->children() as $child_line_item) {
880
-            if ($child_line_item instanceof EE_Line_Item) {
881
-                $deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
882
-                if ($child_line_item->ID()) {
883
-                    $child_line_item->delete();
884
-                    unset($child_line_item);
885
-                } else {
886
-                    $parent_line_item->delete_child_line_item($child_line_item->code());
887
-                }
888
-                $deleted++;
889
-            }
890
-        }
891
-        return $deleted;
892
-    }
893
-
894
-
895
-    /**
896
-     * Deletes the line items as indicated by the line item code(s) provided,
897
-     * regardless of where they're found in the line item tree. Automatically
898
-     * re-calculates the line item totals and updates the related transaction. But
899
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
900
-     * should probably change because of this).
901
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
902
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
903
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
904
-     * @param array|bool|string $line_item_codes
905
-     * @return int number of items successfully removed
906
-     */
907
-    public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
908
-    {
909
-
910
-        if ($total_line_item->type() !== EEM_Line_Item::type_total) {
911
-            EE_Error::doing_it_wrong(
912
-                'EEH_Line_Item::delete_items',
913
-                __(
914
-                    'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
915
-                    'event_espresso'
916
-                ),
917
-                '4.6.18'
918
-            );
919
-        }
920
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
921
-
922
-        // check if only a single line_item_id was passed
923
-        if (!empty($line_item_codes) && !is_array($line_item_codes)) {
924
-            // place single line_item_id in an array to appear as multiple line_item_ids
925
-            $line_item_codes = array($line_item_codes);
926
-        }
927
-        $removals = 0;
928
-        // cycle thru line_item_ids
929
-        foreach ($line_item_codes as $line_item_id) {
930
-            $removals += $total_line_item->delete_child_line_item($line_item_id);
931
-        }
932
-
933
-        if ($removals > 0) {
934
-            $total_line_item->recalculate_taxes_and_tax_total();
935
-            return $removals;
936
-        } else {
937
-            return false;
938
-        }
939
-    }
940
-
941
-
942
-    /**
943
-     * Overwrites the previous tax by clearing out the old taxes, and creates a new
944
-     * tax and updates the total line item accordingly
945
-     *
946
-     * @param EE_Line_Item $total_line_item
947
-     * @param float $amount
948
-     * @param string $name
949
-     * @param string $description
950
-     * @param string $code
951
-     * @param boolean $add_to_existing_line_item
952
-     *                          if true, and a duplicate line item with the same code is found,
953
-     *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
954
-     * @return EE_Line_Item the new tax line item created
955
-     * @throws \EE_Error
956
-     */
957
-    public static function set_total_tax_to(
958
-        EE_Line_Item $total_line_item,
959
-        $amount,
960
-        $name = null,
961
-        $description = null,
962
-        $code = null,
963
-        $add_to_existing_line_item = false
964
-    ) {
965
-        $tax_subtotal = self::get_taxes_subtotal($total_line_item);
966
-        $taxable_total = $total_line_item->taxable_total();
967
-
968
-        if ($add_to_existing_line_item) {
969
-            $new_tax = $tax_subtotal->get_child_line_item($code);
970
-            EEM_Line_Item::instance()->delete(
971
-                array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
972
-            );
973
-        } else {
974
-            $new_tax = null;
975
-            $tax_subtotal->delete_children_line_items();
976
-        }
977
-        if ($new_tax) {
978
-            $new_tax->set_total($new_tax->total() + $amount);
979
-            $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
980
-        } else {
981
-            // no existing tax item. Create it
982
-            $new_tax = EE_Line_Item::new_instance(array(
983
-                'TXN_ID' => $total_line_item->TXN_ID(),
984
-                'LIN_name' => $name ? $name : __('Tax', 'event_espresso'),
985
-                'LIN_desc' => $description ? $description : '',
986
-                'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
987
-                'LIN_total' => $amount,
988
-                'LIN_parent' => $tax_subtotal->ID(),
989
-                'LIN_type' => EEM_Line_Item::type_tax,
990
-                'LIN_code' => $code
991
-            ));
992
-        }
993
-
994
-        $new_tax = apply_filters(
995
-            'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
996
-            $new_tax,
997
-            $total_line_item
998
-        );
999
-        $new_tax->save();
1000
-        $tax_subtotal->set_total($new_tax->total());
1001
-        $tax_subtotal->save();
1002
-        $total_line_item->recalculate_total_including_taxes();
1003
-        return $new_tax;
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * Makes all the line items which are children of $line_item taxable (or not).
1009
-     * Does NOT save the line items
1010
-     * @param EE_Line_Item $line_item
1011
-     * @param string $code_substring_for_whitelist if this string is part of the line item's code
1012
-     *  it will be whitelisted (ie, except from becoming taxable)
1013
-     * @param boolean $taxable
1014
-     */
1015
-    public static function set_line_items_taxable(
1016
-        EE_Line_Item $line_item,
1017
-        $taxable = true,
1018
-        $code_substring_for_whitelist = null
1019
-    ) {
1020
-        $whitelisted = false;
1021
-        if ($code_substring_for_whitelist !== null) {
1022
-            $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false;
1023
-        }
1024
-        if (!$whitelisted && $line_item->is_line_item()) {
1025
-            $line_item->set_is_taxable($taxable);
1026
-        }
1027
-        foreach ($line_item->children() as $child_line_item) {
1028
-            EEH_Line_Item::set_line_items_taxable($child_line_item, $taxable, $code_substring_for_whitelist);
1029
-        }
1030
-    }
1031
-
1032
-
1033
-    /**
1034
-     * Gets all descendants that are event subtotals
1035
-     *
1036
-     * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1037
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1038
-     * @return EE_Line_Item[]
1039
-     */
1040
-    public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1041
-    {
1042
-        return self::get_subtotals_of_object_type($parent_line_item, 'Event');
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     * Gets all descendants subtotals that match the supplied object type
1048
-     *
1049
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1050
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1051
-     * @param string $obj_type
1052
-     * @return EE_Line_Item[]
1053
-     */
1054
-    public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1055
-    {
1056
-        return self::_get_descendants_by_type_and_object_type(
1057
-            $parent_line_item,
1058
-            EEM_Line_Item::type_sub_total,
1059
-            $obj_type
1060
-        );
1061
-    }
1062
-
1063
-
1064
-    /**
1065
-     * Gets all descendants that are tickets
1066
-     *
1067
-     * @uses  EEH_Line_Item::get_line_items_of_object_type()
1068
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1069
-     * @return EE_Line_Item[]
1070
-     */
1071
-    public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1072
-    {
1073
-        return self::get_line_items_of_object_type($parent_line_item, 'Ticket');
1074
-    }
1075
-
1076
-
1077
-    /**
1078
-     * Gets all descendants subtotals that match the supplied object type
1079
-     *
1080
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1081
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1082
-     * @param string $obj_type
1083
-     * @return EE_Line_Item[]
1084
-     */
1085
-    public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1086
-    {
1087
-        return self::_get_descendants_by_type_and_object_type($parent_line_item, EEM_Line_Item::type_line_item, $obj_type);
1088
-    }
1089
-
1090
-
1091
-    /**
1092
-     * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1093
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1094
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1095
-     * @return EE_Line_Item[]
1096
-     */
1097
-    public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1098
-    {
1099
-        return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_tax);
1100
-    }
1101
-
1102
-
1103
-    /**
1104
-     * Gets all the real items purchased which are children of this item
1105
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1106
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1107
-     * @return EE_Line_Item[]
1108
-     */
1109
-    public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1110
-    {
1111
-        return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_line_item);
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * Gets all descendants of supplied line item that match the supplied line item type
1117
-     *
1118
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1119
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1120
-     * @param string $line_item_type one of the EEM_Line_Item constants
1121
-     * @return EE_Line_Item[]
1122
-     */
1123
-    public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1124
-    {
1125
-        return self::_get_descendants_by_type_and_object_type($parent_line_item, $line_item_type, null);
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1131
-     *
1132
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1133
-     * @param string $line_item_type one of the EEM_Line_Item constants
1134
-     * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when searching
1135
-     * @return EE_Line_Item[]
1136
-     */
1137
-    protected static function _get_descendants_by_type_and_object_type(
1138
-        EE_Line_Item $parent_line_item,
1139
-        $line_item_type,
1140
-        $obj_type = null
1141
-    ) {
1142
-        $objects = array();
1143
-        foreach ($parent_line_item->children() as $child_line_item) {
1144
-            if ($child_line_item instanceof EE_Line_Item) {
1145
-                if ($child_line_item->type() === $line_item_type
1146
-                    && (
1147
-                        $child_line_item->OBJ_type() === $obj_type || $obj_type === null
1148
-                    )
1149
-                ) {
1150
-                    $objects[] = $child_line_item;
1151
-                } else {
1152
-                    // go-through-all-its children looking for more matches
1153
-                    $objects = array_merge(
1154
-                        $objects,
1155
-                        self::_get_descendants_by_type_and_object_type(
1156
-                            $child_line_item,
1157
-                            $line_item_type,
1158
-                            $obj_type
1159
-                        )
1160
-                    );
1161
-                }
1162
-            }
1163
-        }
1164
-        return $objects;
1165
-    }
1166
-
1167
-
1168
-    /**
1169
-     * Gets all descendants subtotals that match the supplied object type
1170
-     *
1171
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1172
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1173
-     * @param string $OBJ_type object type (like Event)
1174
-     * @param array $OBJ_IDs array of OBJ_IDs
1175
-     * @return EE_Line_Item[]
1176
-     */
1177
-    public static function get_line_items_by_object_type_and_IDs(
1178
-        EE_Line_Item $parent_line_item,
1179
-        $OBJ_type = '',
1180
-        $OBJ_IDs = array()
1181
-    ) {
1182
-        return self::_get_descendants_by_object_type_and_object_ID($parent_line_item, $OBJ_type, $OBJ_IDs);
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1188
-     *
1189
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1190
-     * @param string $OBJ_type object type (like Event)
1191
-     * @param array $OBJ_IDs array of OBJ_IDs
1192
-     * @return EE_Line_Item[]
1193
-     */
1194
-    protected static function _get_descendants_by_object_type_and_object_ID(
1195
-        EE_Line_Item $parent_line_item,
1196
-        $OBJ_type,
1197
-        $OBJ_IDs
1198
-    ) {
1199
-        $objects = array();
1200
-        foreach ($parent_line_item->children() as $child_line_item) {
1201
-            if ($child_line_item instanceof EE_Line_Item) {
1202
-                if ($child_line_item->OBJ_type() === $OBJ_type
1203
-                    && is_array($OBJ_IDs)
1204
-                    && in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1205
-                ) {
1206
-                    $objects[] = $child_line_item;
1207
-                } else {
1208
-                    // go-through-all-its children looking for more matches
1209
-                    $objects = array_merge(
1210
-                        $objects,
1211
-                        self::_get_descendants_by_object_type_and_object_ID(
1212
-                            $child_line_item,
1213
-                            $OBJ_type,
1214
-                            $OBJ_IDs
1215
-                        )
1216
-                    );
1217
-                }
1218
-            }
1219
-        }
1220
-        return $objects;
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * Uses a breadth-first-search in order to find the nearest descendant of
1226
-     * the specified type and returns it, else NULL
1227
-     *
1228
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1229
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1230
-     * @param string $type like one of the EEM_Line_Item::type_*
1231
-     * @return EE_Line_Item
1232
-     */
1233
-    public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1234
-    {
1235
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1236
-    }
1237
-
1238
-
1239
-    /**
1240
-     * Uses a breadth-first-search in order to find the nearest descendant
1241
-     * having the specified LIN_code and returns it, else NULL
1242
-     *
1243
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1244
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1245
-     * @param string $code any value used for LIN_code
1246
-     * @return EE_Line_Item
1247
-     */
1248
-    public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1249
-    {
1250
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1251
-    }
1252
-
1253
-
1254
-    /**
1255
-     * Uses a breadth-first-search in order to find the nearest descendant
1256
-     * having the specified LIN_code and returns it, else NULL
1257
-     *
1258
-     * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1259
-     * @param string $search_field name of EE_Line_Item property
1260
-     * @param string $value any value stored in $search_field
1261
-     * @return EE_Line_Item
1262
-     */
1263
-    protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1264
-    {
1265
-        foreach ($parent_line_item->children() as $child) {
1266
-            if ($child->get($search_field) == $value) {
1267
-                return $child;
1268
-            }
1269
-        }
1270
-        foreach ($parent_line_item->children() as $child) {
1271
-            $descendant_found = self::_get_nearest_descendant($child, $search_field, $value);
1272
-            if ($descendant_found) {
1273
-                return $descendant_found;
1274
-            }
1275
-        }
1276
-        return null;
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1282
-     * else recursively walks up the line item tree until a parent of type total is found,
1283
-     *
1284
-     * @param EE_Line_Item $line_item
1285
-     * @return \EE_Line_Item
1286
-     * @throws \EE_Error
1287
-     */
1288
-    public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1289
-    {
1290
-        if ($line_item->TXN_ID()) {
1291
-            $total_line_item = $line_item->transaction()->total_line_item(false);
1292
-            if ($total_line_item instanceof EE_Line_Item) {
1293
-                return $total_line_item;
1294
-            }
1295
-        } else {
1296
-            $line_item_parent = $line_item->parent();
1297
-            if ($line_item_parent instanceof EE_Line_Item) {
1298
-                if ($line_item_parent->is_total()) {
1299
-                    return $line_item_parent;
1300
-                }
1301
-                return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1302
-            }
1303
-        }
1304
-        throw new EE_Error(
1305
-            sprintf(
1306
-                __('A valid grand total for line item %1$d was not found.', 'event_espresso'),
1307
-                $line_item->ID()
1308
-            )
1309
-        );
1310
-    }
1311
-
1312
-
1313
-    /**
1314
-     * Prints out a representation of the line item tree
1315
-     *
1316
-     * @param EE_Line_Item $line_item
1317
-     * @param int $indentation
1318
-     * @return void
1319
-     * @throws \EE_Error
1320
-     */
1321
-    public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1322
-    {
1323
-        echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1324
-        if (!$indentation) {
1325
-            echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1326
-        }
1327
-        for ($i = 0; $i < $indentation; $i++) {
1328
-            echo ". ";
1329
-        }
1330
-        $breakdown = '';
1331
-        if ($line_item->is_line_item()) {
1332
-            if ($line_item->is_percent()) {
1333
-                $breakdown = "{$line_item->percent()}%";
1334
-            } else {
1335
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1336
-            }
1337
-        }
1338
-        echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}";
1339
-        if ($breakdown) {
1340
-            echo " ( {$breakdown} )";
1341
-        }
1342
-        if ($line_item->is_taxable()) {
1343
-            echo "  * taxable";
1344
-        }
1345
-        if ($line_item->children()) {
1346
-            foreach ($line_item->children() as $child) {
1347
-                self::visualize($child, $indentation + 1);
1348
-            }
1349
-        }
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Calculates the registration's final price, taking into account that they
1355
-     * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1356
-     * and receive a portion of any transaction-wide discounts.
1357
-     * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1358
-     * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1359
-     * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1360
-     * and brent's final price should be $5.50.
1361
-     *
1362
-     * In order to do this, we basically need to traverse the line item tree calculating
1363
-     * the running totals (just as if we were recalculating the total), but when we identify
1364
-     * regular line items, we need to keep track of their share of the grand total.
1365
-     * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1366
-     * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1367
-     * when there are non-taxable items; otherwise they would be the same)
1368
-     *
1369
-     * @param EE_Line_Item $line_item
1370
-     * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that
1371
-     *                                                                            can be included in price calculations at this moment
1372
-     * @return array        keys are line items for tickets IDs and values are their share of the running total,
1373
-     *                                          plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg
1374
-     *                                          array(
1375
-     *                                          12 => 4.3
1376
-     *                                          23 => 8.0
1377
-     *                                          'total' => 16.6,
1378
-     *                                          'taxable' => array(
1379
-     *                                          12 => 10,
1380
-     *                                          23 => 4
1381
-     *                                          ).
1382
-     *                                          So to find which registrations have which final price, we need to find which line item
1383
-     *                                          is theirs, which can be done with
1384
-     *                                          `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );`
1385
-     */
1386
-    public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array())
1387
-    {
1388
-        // init running grand total if not already
1389
-        if (!isset($running_totals['total'])) {
1390
-            $running_totals['total'] = 0;
1391
-        }
1392
-        if (!isset($running_totals['taxable'])) {
1393
-            $running_totals['taxable'] = array('total' => 0);
1394
-        }
1395
-        foreach ($line_item->children() as $child_line_item) {
1396
-            switch ($child_line_item->type()) {
1397
-                case EEM_Line_Item::type_sub_total:
1398
-                    $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities);
1399
-                    // combine arrays but preserve numeric keys
1400
-                    $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1401
-                    $running_totals['total'] += $running_totals_from_subtotal['total'];
1402
-                    $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1403
-                    break;
1404
-
1405
-                case EEM_Line_Item::type_tax_sub_total:
1406
-                    // find how much the taxes percentage is
1407
-                    if ($child_line_item->percent() !== 0) {
1408
-                        $tax_percent_decimal = $child_line_item->percent() / 100;
1409
-                    } else {
1410
-                        $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1411
-                    }
1412
-                    // and apply to all the taxable totals, and add to the pretax totals
1413
-                    foreach ($running_totals as $line_item_id => $this_running_total) {
1414
-                        // "total" and "taxable" array key is an exception
1415
-                        if ($line_item_id === 'taxable') {
1416
-                            continue;
1417
-                        }
1418
-                        $taxable_total = $running_totals['taxable'][ $line_item_id ];
1419
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1420
-                    }
1421
-                    break;
1422
-
1423
-                case EEM_Line_Item::type_line_item:
1424
-                    // ticket line items or ????
1425
-                    if ($child_line_item->OBJ_type() === 'Ticket') {
1426
-                        // kk it's a ticket
1427
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1428
-                            // huh? that shouldn't happen.
1429
-                            $running_totals['total'] += $child_line_item->total();
1430
-                        } else {
1431
-                            // its not in our running totals yet. great.
1432
-                            if ($child_line_item->is_taxable()) {
1433
-                                $taxable_amount = $child_line_item->unit_price();
1434
-                            } else {
1435
-                                $taxable_amount = 0;
1436
-                            }
1437
-                            // are we only calculating totals for some tickets?
1438
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1439
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1440
-                                $running_totals[ $child_line_item->ID() ] = $quantity
1441
-                                    ? $child_line_item->unit_price()
1442
-                                    : 0;
1443
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1444
-                                    ? $taxable_amount
1445
-                                    : 0;
1446
-                            } else {
1447
-                                $quantity = $child_line_item->quantity();
1448
-                                $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1449
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1450
-                            }
1451
-                            $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1452
-                            $running_totals['total'] += $child_line_item->unit_price() * $quantity;
1453
-                        }
1454
-                    } else {
1455
-                        // it's some other type of item added to the cart
1456
-                        // it should affect the running totals
1457
-                        // basically we want to convert it into a PERCENT modifier. Because
1458
-                        // more clearly affect all registration's final price equally
1459
-                        $line_items_percent_of_running_total = $running_totals['total'] > 0
1460
-                            ? ($child_line_item->total() / $running_totals['total']) + 1
1461
-                            : 1;
1462
-                        foreach ($running_totals as $line_item_id => $this_running_total) {
1463
-                            // the "taxable" array key is an exception
1464
-                            if ($line_item_id === 'taxable') {
1465
-                                continue;
1466
-                            }
1467
-                            // update the running totals
1468
-                            // yes this actually even works for the running grand total!
1469
-                            $running_totals[ $line_item_id ] =
1470
-                                $line_items_percent_of_running_total * $this_running_total;
1471
-
1472
-                            if ($child_line_item->is_taxable()) {
1473
-                                $running_totals['taxable'][ $line_item_id ] =
1474
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1475
-                            }
1476
-                        }
1477
-                    }
1478
-                    break;
1479
-            }
1480
-        }
1481
-        return $running_totals;
1482
-    }
1483
-
1484
-
1485
-    /**
1486
-     * @param \EE_Line_Item $total_line_item
1487
-     * @param \EE_Line_Item $ticket_line_item
1488
-     * @return float | null
1489
-     * @throws \OutOfRangeException
1490
-     */
1491
-    public static function calculate_final_price_for_ticket_line_item(\EE_Line_Item $total_line_item, \EE_Line_Item $ticket_line_item)
1492
-    {
1493
-        static $final_prices_per_ticket_line_item = array();
1494
-        if (empty($final_prices_per_ticket_line_item)) {
1495
-            $final_prices_per_ticket_line_item = \EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1496
-                $total_line_item
1497
-            );
1498
-        }
1499
-        // ok now find this new registration's final price
1500
-        if (isset($final_prices_per_ticket_line_item[ $ticket_line_item->ID() ])) {
1501
-            return $final_prices_per_ticket_line_item[ $ticket_line_item->ID() ];
1502
-        }
1503
-        $message = sprintf(
1504
-            __(
1505
-                'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1506
-                'event_espresso'
1507
-            ),
1508
-            $ticket_line_item->ID()
1509
-        );
1510
-        if (WP_DEBUG) {
1511
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1512
-            throw new \OutOfRangeException($message);
1513
-        } else {
1514
-            EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1515
-        }
1516
-        return null;
1517
-    }
1518
-
1519
-
1520
-    /**
1521
-     * Creates a duplicate of the line item tree, except only includes billable items
1522
-     * and the portion of line items attributed to billable things
1523
-     *
1524
-     * @param EE_Line_Item $line_item
1525
-     * @param EE_Registration[] $registrations
1526
-     * @return \EE_Line_Item
1527
-     * @throws \EE_Error
1528
-     */
1529
-    public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1530
-    {
1531
-        $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1532
-        foreach ($line_item->children() as $child_li) {
1533
-            $copy_li->add_child_line_item(EEH_Line_Item::billable_line_item_tree($child_li, $registrations));
1534
-        }
1535
-        // if this is the grand total line item, make sure the totals all add up
1536
-        // (we could have duplicated this logic AS we copied the line items, but
1537
-        // it seems DRYer this way)
1538
-        if ($copy_li->type() === EEM_Line_Item::type_total) {
1539
-            $copy_li->recalculate_total_including_taxes();
1540
-        }
1541
-        return $copy_li;
1542
-    }
1543
-
1544
-
1545
-    /**
1546
-     * Creates a new, unsaved line item from $line_item that factors in the
1547
-     * number of billable registrations on $registrations.
1548
-     *
1549
-     * @param EE_Line_Item $line_item
1550
-     * @return EE_Line_Item
1551
-     * @throws \EE_Error
1552
-     * @param EE_Registration[] $registrations
1553
-     */
1554
-    public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1555
-    {
1556
-        $new_li_fields = $line_item->model_field_array();
1557
-        if ($line_item->type() === EEM_Line_Item::type_line_item &&
1558
-            $line_item->OBJ_type() === 'Ticket'
1559
-        ) {
1560
-            $count = 0;
1561
-            foreach ($registrations as $registration) {
1562
-                if ($line_item->OBJ_ID() === $registration->ticket_ID() &&
1563
-                    in_array($registration->status_ID(), EEM_Registration::reg_statuses_that_allow_payment())
1564
-                ) {
1565
-                    $count++;
1566
-                }
1567
-            }
1568
-            $new_li_fields['LIN_quantity'] = $count;
1569
-        }
1570
-        // don't set the total. We'll leave that up to the code that calculates it
1571
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1572
-        return EE_Line_Item::new_instance($new_li_fields);
1573
-    }
1574
-
1575
-
1576
-    /**
1577
-     * Returns a modified line item tree where all the subtotals which have a total of 0
1578
-     * are removed, and line items with a quantity of 0
1579
-     *
1580
-     * @param EE_Line_Item $line_item |null
1581
-     * @return \EE_Line_Item|null
1582
-     * @throws \EE_Error
1583
-     */
1584
-    public static function non_empty_line_items(EE_Line_Item $line_item)
1585
-    {
1586
-        $copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1587
-        if ($copied_li === null) {
1588
-            return null;
1589
-        }
1590
-        // if this is an event subtotal, we want to only include it if it
1591
-        // has a non-zero total and at least one ticket line item child
1592
-        $ticket_children = 0;
1593
-        foreach ($line_item->children() as $child_li) {
1594
-            $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1595
-            if ($child_li_copy !== null) {
1596
-                $copied_li->add_child_line_item($child_li_copy);
1597
-                if ($child_li_copy->type() === EEM_Line_Item::type_line_item &&
1598
-                    $child_li_copy->OBJ_type() === 'Ticket'
1599
-                ) {
1600
-                    $ticket_children++;
1601
-                }
1602
-            }
1603
-        }
1604
-        // if this is an event subtotal with NO ticket children
1605
-        // we basically want to ignore it
1606
-        if ($ticket_children === 0
1607
-            && $line_item->type() === EEM_Line_Item::type_sub_total
1608
-            && $line_item->OBJ_type() === 'Event'
1609
-            && $line_item->total() === 0
1610
-        ) {
1611
-            return null;
1612
-        }
1613
-        return $copied_li;
1614
-    }
1615
-
1616
-
1617
-    /**
1618
-     * Creates a new, unsaved line item, but if it's a ticket line item
1619
-     * with a total of 0, or a subtotal of 0, returns null instead
1620
-     *
1621
-     * @param EE_Line_Item $line_item
1622
-     * @return EE_Line_Item
1623
-     * @throws \EE_Error
1624
-     */
1625
-    public static function non_empty_line_item(EE_Line_Item $line_item)
1626
-    {
1627
-        if ($line_item->type() === EEM_Line_Item::type_line_item &&
1628
-            $line_item->OBJ_type() === 'Ticket' &&
1629
-            $line_item->quantity() === 0
1630
-        ) {
1631
-            return null;
1632
-        }
1633
-        $new_li_fields = $line_item->model_field_array();
1634
-        // don't set the total. We'll leave that up to the code that calculates it
1635
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1636
-        return EE_Line_Item::new_instance($new_li_fields);
1637
-    }
1638
-
1639
-
1640
-
1641
-    /**************************************** @DEPRECATED METHODS *************************************** */
1642
-    /**
1643
-     * @deprecated
1644
-     * @param EE_Line_Item $total_line_item
1645
-     * @return \EE_Line_Item
1646
-     * @throws \EE_Error
1647
-     */
1648
-    public static function get_items_subtotal(EE_Line_Item $total_line_item)
1649
-    {
1650
-        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');
1651
-        return self::get_pre_tax_subtotal($total_line_item);
1652
-    }
1653
-
1654
-
1655
-    /**
1656
-     * @deprecated
1657
-     * @param EE_Transaction $transaction
1658
-     * @return \EE_Line_Item
1659
-     * @throws \EE_Error
1660
-     */
1661
-    public static function create_default_total_line_item($transaction = null)
1662
-    {
1663
-        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');
1664
-        return self::create_total_line_item($transaction);
1665
-    }
1666
-
1667
-
1668
-    /**
1669
-     * @deprecated
1670
-     * @param EE_Line_Item $total_line_item
1671
-     * @param EE_Transaction $transaction
1672
-     * @return \EE_Line_Item
1673
-     * @throws \EE_Error
1674
-     */
1675
-    public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null)
1676
-    {
1677
-        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');
1678
-        return self::create_pre_tax_subtotal($total_line_item, $transaction);
1679
-    }
1680
-
1681
-
1682
-    /**
1683
-     * @deprecated
1684
-     * @param EE_Line_Item $total_line_item
1685
-     * @param EE_Transaction $transaction
1686
-     * @return \EE_Line_Item
1687
-     * @throws \EE_Error
1688
-     */
1689
-    public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
1690
-    {
1691
-        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');
1692
-        return self::create_taxes_subtotal($total_line_item, $transaction);
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * @deprecated
1698
-     * @param EE_Line_Item $total_line_item
1699
-     * @param EE_Transaction $transaction
1700
-     * @return \EE_Line_Item
1701
-     * @throws \EE_Error
1702
-     */
1703
-    public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null)
1704
-    {
1705
-        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');
1706
-        return self::create_event_subtotal($total_line_item, $transaction);
1707
-    }
23
+	// other functions: cancel ticket purchase
24
+	// delete ticket purchase
25
+	// add promotion
26
+
27
+
28
+	/**
29
+	 * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
30
+	 * Does NOT automatically re-calculate the line item totals or update the related transaction.
31
+	 * You should call recalculate_total_including_taxes() on the grant total line item after this
32
+	 * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
33
+	 * to keep the registration final prices in-sync with the transaction's total.
34
+	 *
35
+	 * @param EE_Line_Item $parent_line_item
36
+	 * @param string $name
37
+	 * @param float $unit_price
38
+	 * @param string $description
39
+	 * @param int $quantity
40
+	 * @param boolean $taxable
41
+	 * @param boolean $code if set to a value, ensures there is only one line item with that code
42
+	 * @return boolean success
43
+	 * @throws \EE_Error
44
+	 */
45
+	public static function add_unrelated_item(EE_Line_Item $parent_line_item, $name, $unit_price, $description = '', $quantity = 1, $taxable = false, $code = null)
46
+	{
47
+		$items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
48
+		$line_item = EE_Line_Item::new_instance(array(
49
+			'LIN_name' => $name,
50
+			'LIN_desc' => $description,
51
+			'LIN_unit_price' => $unit_price,
52
+			'LIN_quantity' => $quantity,
53
+			'LIN_percent' => null,
54
+			'LIN_is_taxable' => $taxable,
55
+			'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
56
+			'LIN_total' => (float) $unit_price * (int) $quantity,
57
+			'LIN_type' => EEM_Line_Item::type_line_item,
58
+			'LIN_code' => $code,
59
+		));
60
+		$line_item = apply_filters(
61
+			'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
62
+			$line_item,
63
+			$parent_line_item
64
+		);
65
+		return self::add_item($parent_line_item, $line_item);
66
+	}
67
+
68
+
69
+	/**
70
+	 * Adds a simple item ( unrelated to any other model object) to the total line item,
71
+	 * in the correct spot in the line item tree. Automatically
72
+	 * re-calculates the line item totals and updates the related transaction. But
73
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
74
+	 * should probably change because of this).
75
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
76
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
77
+	 *
78
+	 * @param EE_Line_Item $parent_line_item
79
+	 * @param string $name
80
+	 * @param float $percentage_amount
81
+	 * @param string $description
82
+	 * @param boolean $taxable
83
+	 * @return boolean success
84
+	 * @throws \EE_Error
85
+	 */
86
+	public static function add_percentage_based_item(EE_Line_Item $parent_line_item, $name, $percentage_amount, $description = '', $taxable = false)
87
+	{
88
+		$line_item = EE_Line_Item::new_instance(array(
89
+			'LIN_name' => $name,
90
+			'LIN_desc' => $description,
91
+			'LIN_unit_price' => 0,
92
+			'LIN_percent' => $percentage_amount,
93
+			'LIN_quantity' => 1,
94
+			'LIN_is_taxable' => $taxable,
95
+			'LIN_total' => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
96
+			'LIN_type' => EEM_Line_Item::type_line_item,
97
+			'LIN_parent' => $parent_line_item->ID()
98
+		));
99
+		$line_item = apply_filters(
100
+			'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
101
+			$line_item
102
+		);
103
+		return $parent_line_item->add_child_line_item($line_item, false);
104
+	}
105
+
106
+
107
+	/**
108
+	 * Returns the new line item created by adding a purchase of the ticket
109
+	 * ensures that ticket line item is saved, and that cart total has been recalculated.
110
+	 * If this ticket has already been purchased, just increments its count.
111
+	 * Automatically re-calculates the line item totals and updates the related transaction. But
112
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
113
+	 * should probably change because of this).
114
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
115
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
116
+	 *
117
+	 * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
118
+	 * @param EE_Ticket $ticket
119
+	 * @param int $qty
120
+	 * @return \EE_Line_Item
121
+	 * @throws \EE_Error
122
+	 */
123
+	public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
124
+	{
125
+		if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) {
126
+			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()));
127
+		}
128
+		// either increment the qty for an existing ticket
129
+		$line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
130
+		// or add a new one
131
+		if (!$line_item instanceof EE_Line_Item) {
132
+			$line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
133
+		}
134
+		$total_line_item->recalculate_total_including_taxes();
135
+		return $line_item;
136
+	}
137
+
138
+
139
+	/**
140
+	 * Returns the new line item created by adding a purchase of the ticket
141
+	 * @param \EE_Line_Item $total_line_item
142
+	 * @param EE_Ticket $ticket
143
+	 * @param int $qty
144
+	 * @return \EE_Line_Item
145
+	 * @throws \EE_Error
146
+	 */
147
+	public static function increment_ticket_qty_if_already_in_cart(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
148
+	{
149
+		$line_item = null;
150
+		if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
151
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
152
+			foreach ((array) $ticket_line_items as $ticket_line_item) {
153
+				if ($ticket_line_item instanceof EE_Line_Item
154
+					&& (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
155
+				) {
156
+					$line_item = $ticket_line_item;
157
+					break;
158
+				}
159
+			}
160
+		}
161
+		if ($line_item instanceof EE_Line_Item) {
162
+			EEH_Line_Item::increment_quantity($line_item, $qty);
163
+			return $line_item;
164
+		}
165
+		return null;
166
+	}
167
+
168
+
169
+	/**
170
+	 * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
171
+	 * Does NOT save or recalculate other line items totals
172
+	 *
173
+	 * @param EE_Line_Item $line_item
174
+	 * @param int $qty
175
+	 * @return void
176
+	 * @throws \EE_Error
177
+	 */
178
+	public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
179
+	{
180
+		if (!$line_item->is_percent()) {
181
+			$qty += $line_item->quantity();
182
+			$line_item->set_quantity($qty);
183
+			$line_item->set_total($line_item->unit_price() * $qty);
184
+			$line_item->save();
185
+		}
186
+		foreach ($line_item->children() as $child) {
187
+			if ($child->is_sub_line_item()) {
188
+				EEH_Line_Item::update_quantity($child, $qty);
189
+			}
190
+		}
191
+	}
192
+
193
+
194
+	/**
195
+	 * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
196
+	 * Does NOT save or recalculate other line items totals
197
+	 *
198
+	 * @param EE_Line_Item $line_item
199
+	 * @param int $qty
200
+	 * @return void
201
+	 * @throws \EE_Error
202
+	 */
203
+	public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
204
+	{
205
+		if (!$line_item->is_percent()) {
206
+			$qty = $line_item->quantity() - $qty;
207
+			$qty = max($qty, 0);
208
+			$line_item->set_quantity($qty);
209
+			$line_item->set_total($line_item->unit_price() * $qty);
210
+			$line_item->save();
211
+		}
212
+		foreach ($line_item->children() as $child) {
213
+			if ($child->is_sub_line_item()) {
214
+				EEH_Line_Item::update_quantity($child, $qty);
215
+			}
216
+		}
217
+	}
218
+
219
+
220
+	/**
221
+	 * Updates the line item and its children's quantities to the specified number.
222
+	 * Does NOT save them or recalculate totals.
223
+	 *
224
+	 * @param EE_Line_Item $line_item
225
+	 * @param int $new_quantity
226
+	 * @throws \EE_Error
227
+	 */
228
+	public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
229
+	{
230
+		if (!$line_item->is_percent()) {
231
+			$line_item->set_quantity($new_quantity);
232
+			$line_item->set_total($line_item->unit_price() * $new_quantity);
233
+			$line_item->save();
234
+		}
235
+		foreach ($line_item->children() as $child) {
236
+			if ($child->is_sub_line_item()) {
237
+				EEH_Line_Item::update_quantity($child, $new_quantity);
238
+			}
239
+		}
240
+	}
241
+
242
+
243
+	/**
244
+	 * Returns the new line item created by adding a purchase of the ticket
245
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
246
+	 * @param EE_Ticket $ticket
247
+	 * @param int $qty
248
+	 * @return \EE_Line_Item
249
+	 * @throws \EE_Error
250
+	 */
251
+	public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
252
+	{
253
+		$datetimes = $ticket->datetimes();
254
+		$first_datetime = reset($datetimes);
255
+		if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
256
+			$first_datetime_name = $first_datetime->event()->name();
257
+		} else {
258
+			$first_datetime_name = __('Event', 'event_espresso');
259
+		}
260
+		$event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
261
+		// get event subtotal line
262
+		$events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
263
+		// add $ticket to cart
264
+		$line_item = EE_Line_Item::new_instance(array(
265
+			'LIN_name' => $ticket->name(),
266
+			'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
267
+			'LIN_unit_price' => $ticket->price(),
268
+			'LIN_quantity' => $qty,
269
+			'LIN_is_taxable' => $ticket->taxable(),
270
+			'LIN_order' => count($events_sub_total->children()),
271
+			'LIN_total' => $ticket->price() * $qty,
272
+			'LIN_type' => EEM_Line_Item::type_line_item,
273
+			'OBJ_ID' => $ticket->ID(),
274
+			'OBJ_type' => 'Ticket'
275
+		));
276
+		$line_item = apply_filters(
277
+			'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
278
+			$line_item
279
+		);
280
+		$events_sub_total->add_child_line_item($line_item);
281
+		// now add the sub-line items
282
+		$running_total_for_ticket = 0;
283
+		foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
284
+			$sign = $price->is_discount() ? -1 : 1;
285
+			$price_total = $price->is_percent()
286
+				? $running_total_for_ticket * $price->amount() / 100
287
+				: $price->amount() * $qty;
288
+			$sub_line_item = EE_Line_Item::new_instance(array(
289
+				'LIN_name' => $price->name(),
290
+				'LIN_desc' => $price->desc(),
291
+				'LIN_quantity' => $price->is_percent() ? null : $qty,
292
+				'LIN_is_taxable' => false,
293
+				'LIN_order' => $price->order(),
294
+				'LIN_total' => $sign * $price_total,
295
+				'LIN_type' => EEM_Line_Item::type_sub_line_item,
296
+				'OBJ_ID' => $price->ID(),
297
+				'OBJ_type' => 'Price'
298
+			));
299
+			$sub_line_item = apply_filters(
300
+				'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
301
+				$sub_line_item
302
+			);
303
+			if ($price->is_percent()) {
304
+				$sub_line_item->set_percent($sign * $price->amount());
305
+			} else {
306
+				$sub_line_item->set_unit_price($sign * $price->amount());
307
+			}
308
+			$running_total_for_ticket += $price_total;
309
+			$line_item->add_child_line_item($sub_line_item);
310
+		}
311
+		return $line_item;
312
+	}
313
+
314
+
315
+	/**
316
+	 * Adds the specified item under the pre-tax-sub-total line item. Automatically
317
+	 * re-calculates the line item totals and updates the related transaction. But
318
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
319
+	 * should probably change because of this).
320
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
321
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
322
+	 *
323
+	 * @param EE_Line_Item $total_line_item
324
+	 * @param EE_Line_Item $item to be added
325
+	 * @return boolean
326
+	 * @throws \EE_Error
327
+	 */
328
+	public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
329
+	{
330
+		$pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
331
+		if ($pre_tax_subtotal instanceof EE_Line_Item) {
332
+			$success = $pre_tax_subtotal->add_child_line_item($item);
333
+		} else {
334
+			return false;
335
+		}
336
+		$total_line_item->recalculate_total_including_taxes();
337
+		return $success;
338
+	}
339
+
340
+
341
+	/**
342
+	 * cancels an existing ticket line item,
343
+	 * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
344
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
345
+	 *
346
+	 * @param EE_Line_Item $ticket_line_item
347
+	 * @param int $qty
348
+	 * @return bool success
349
+	 * @throws \EE_Error
350
+	 */
351
+	public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
352
+	{
353
+		// validate incoming line_item
354
+		if ($ticket_line_item->OBJ_type() !== 'Ticket') {
355
+			throw new EE_Error(
356
+				sprintf(
357
+					__('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
358
+					$ticket_line_item->type()
359
+				)
360
+			);
361
+		}
362
+		if ($ticket_line_item->quantity() < $qty) {
363
+			throw new EE_Error(
364
+				sprintf(
365
+					__('Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', 'event_espresso'),
366
+					$qty,
367
+					$ticket_line_item->quantity()
368
+				)
369
+			);
370
+		}
371
+		// decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
372
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
373
+		foreach ($ticket_line_item->children() as $child_line_item) {
374
+			if ($child_line_item->is_sub_line_item()
375
+				&& !$child_line_item->is_percent()
376
+				&& !$child_line_item->is_cancellation()
377
+			) {
378
+				$child_line_item->set_quantity($child_line_item->quantity() - $qty);
379
+			}
380
+		}
381
+		// get cancellation sub line item
382
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
383
+			$ticket_line_item,
384
+			EEM_Line_Item::type_cancellation
385
+		);
386
+		$cancellation_line_item = reset($cancellation_line_item);
387
+		// verify that this ticket was indeed previously cancelled
388
+		if ($cancellation_line_item instanceof EE_Line_Item) {
389
+			// increment cancelled quantity
390
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
391
+		} else {
392
+			// create cancellation sub line item
393
+			$cancellation_line_item = EE_Line_Item::new_instance(array(
394
+				'LIN_name' => __('Cancellation', 'event_espresso'),
395
+				'LIN_desc' => sprintf(
396
+					_x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'),
397
+					$ticket_line_item->name(),
398
+					current_time(get_option('date_format') . ' ' . get_option('time_format'))
399
+				),
400
+				'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
401
+				'LIN_quantity' => $qty,
402
+				'LIN_is_taxable' => $ticket_line_item->is_taxable(),
403
+				'LIN_order' => count($ticket_line_item->children()),
404
+				'LIN_total' => 0, // $ticket_line_item->unit_price()
405
+				'LIN_type' => EEM_Line_Item::type_cancellation,
406
+			));
407
+			$ticket_line_item->add_child_line_item($cancellation_line_item);
408
+		}
409
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
410
+			// decrement parent line item quantity
411
+			$event_line_item = $ticket_line_item->parent();
412
+			if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
413
+				$event_line_item->set_quantity($event_line_item->quantity() - $qty);
414
+				$event_line_item->save();
415
+			}
416
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
417
+			return true;
418
+		}
419
+		return false;
420
+	}
421
+
422
+
423
+	/**
424
+	 * reinstates (un-cancels?) a previously canceled ticket line item,
425
+	 * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
426
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
427
+	 *
428
+	 * @param EE_Line_Item $ticket_line_item
429
+	 * @param int $qty
430
+	 * @return bool success
431
+	 * @throws \EE_Error
432
+	 */
433
+	public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
434
+	{
435
+		// validate incoming line_item
436
+		if ($ticket_line_item->OBJ_type() !== 'Ticket') {
437
+			throw new EE_Error(
438
+				sprintf(
439
+					__('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'),
440
+					$ticket_line_item->type()
441
+				)
442
+			);
443
+		}
444
+		// get cancellation sub line item
445
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
446
+			$ticket_line_item,
447
+			EEM_Line_Item::type_cancellation
448
+		);
449
+		$cancellation_line_item = reset($cancellation_line_item);
450
+		// verify that this ticket was indeed previously cancelled
451
+		if (!$cancellation_line_item instanceof EE_Line_Item) {
452
+			return false;
453
+		}
454
+		if ($cancellation_line_item->quantity() > $qty) {
455
+			// decrement cancelled quantity
456
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
457
+		} elseif ($cancellation_line_item->quantity() == $qty) {
458
+			// decrement cancelled quantity in case anyone still has the object kicking around
459
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
460
+			// delete because quantity will end up as 0
461
+			$cancellation_line_item->delete();
462
+			// and attempt to destroy the object,
463
+			// even though PHP won't actually destroy it until it needs the memory
464
+			unset($cancellation_line_item);
465
+		} else {
466
+			// what ?!?! negative quantity ?!?!
467
+			throw new EE_Error(
468
+				sprintf(
469
+					__(
470
+						'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
471
+						'event_espresso'
472
+					),
473
+					$qty,
474
+					$cancellation_line_item->quantity()
475
+				)
476
+			);
477
+		}
478
+		// increment ticket quantity
479
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
480
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
481
+			// increment parent line item quantity
482
+			$event_line_item = $ticket_line_item->parent();
483
+			if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') {
484
+				$event_line_item->set_quantity($event_line_item->quantity() + $qty);
485
+			}
486
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
487
+			return true;
488
+		}
489
+		return false;
490
+	}
491
+
492
+
493
+	/**
494
+	 * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
495
+	 * then EE_Line_Item::recalculate_total_including_taxes() on the result
496
+	 *
497
+	 * @param EE_Line_Item $line_item
498
+	 * @return \EE_Line_Item
499
+	 */
500
+	public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
501
+	{
502
+		$grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
503
+		return $grand_total_line_item->recalculate_total_including_taxes();
504
+	}
505
+
506
+
507
+	/**
508
+	 * Gets the line item which contains the subtotal of all the items
509
+	 *
510
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
511
+	 * @return \EE_Line_Item
512
+	 * @throws \EE_Error
513
+	 */
514
+	public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
515
+	{
516
+		$pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
517
+		return $pre_tax_subtotal instanceof EE_Line_Item
518
+			? $pre_tax_subtotal
519
+			: self::create_pre_tax_subtotal($total_line_item);
520
+	}
521
+
522
+
523
+	/**
524
+	 * Gets the line item for the taxes subtotal
525
+	 *
526
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
527
+	 * @return \EE_Line_Item
528
+	 * @throws \EE_Error
529
+	 */
530
+	public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
531
+	{
532
+		$taxes = $total_line_item->get_child_line_item('taxes');
533
+		return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
534
+	}
535
+
536
+
537
+	/**
538
+	 * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
539
+	 *
540
+	 * @param EE_Line_Item $line_item
541
+	 * @param EE_Transaction $transaction
542
+	 * @return void
543
+	 * @throws \EE_Error
544
+	 */
545
+	public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null)
546
+	{
547
+		if ($transaction) {
548
+			/** @type EEM_Transaction $EEM_Transaction */
549
+			$EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
550
+			$TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
551
+			$line_item->set_TXN_ID($TXN_ID);
552
+		}
553
+	}
554
+
555
+
556
+	/**
557
+	 * Creates a new default total line item for the transaction,
558
+	 * and its tickets subtotal and taxes subtotal line items (and adds the
559
+	 * existing taxes as children of the taxes subtotal line item)
560
+	 *
561
+	 * @param EE_Transaction $transaction
562
+	 * @return \EE_Line_Item of type total
563
+	 * @throws \EE_Error
564
+	 */
565
+	public static function create_total_line_item($transaction = null)
566
+	{
567
+		$total_line_item = EE_Line_Item::new_instance(array(
568
+			'LIN_code' => 'total',
569
+			'LIN_name' => __('Grand Total', 'event_espresso'),
570
+			'LIN_type' => EEM_Line_Item::type_total,
571
+			'OBJ_type' => 'Transaction'
572
+		));
573
+		$total_line_item = apply_filters(
574
+			'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
575
+			$total_line_item
576
+		);
577
+		self::set_TXN_ID($total_line_item, $transaction);
578
+		self::create_pre_tax_subtotal($total_line_item, $transaction);
579
+		self::create_taxes_subtotal($total_line_item, $transaction);
580
+		return $total_line_item;
581
+	}
582
+
583
+
584
+	/**
585
+	 * Creates a default items subtotal line item
586
+	 *
587
+	 * @param EE_Line_Item $total_line_item
588
+	 * @param EE_Transaction $transaction
589
+	 * @return EE_Line_Item
590
+	 * @throws \EE_Error
591
+	 */
592
+	protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null)
593
+	{
594
+		$pre_tax_line_item = EE_Line_Item::new_instance(array(
595
+			'LIN_code' => 'pre-tax-subtotal',
596
+			'LIN_name' => __('Pre-Tax Subtotal', 'event_espresso'),
597
+			'LIN_type' => EEM_Line_Item::type_sub_total
598
+		));
599
+		$pre_tax_line_item = apply_filters(
600
+			'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
601
+			$pre_tax_line_item
602
+		);
603
+		self::set_TXN_ID($pre_tax_line_item, $transaction);
604
+		$total_line_item->add_child_line_item($pre_tax_line_item);
605
+		self::create_event_subtotal($pre_tax_line_item, $transaction);
606
+		return $pre_tax_line_item;
607
+	}
608
+
609
+
610
+	/**
611
+	 * Creates a line item for the taxes subtotal and finds all the tax prices
612
+	 * and applies taxes to it
613
+	 *
614
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
615
+	 * @param EE_Transaction $transaction
616
+	 * @return EE_Line_Item
617
+	 * @throws \EE_Error
618
+	 */
619
+	protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
620
+	{
621
+		$tax_line_item = EE_Line_Item::new_instance(array(
622
+			'LIN_code' => 'taxes',
623
+			'LIN_name' => __('Taxes', 'event_espresso'),
624
+			'LIN_type' => EEM_Line_Item::type_tax_sub_total,
625
+			'LIN_order' => 1000,// this should always come last
626
+		));
627
+		$tax_line_item = apply_filters(
628
+			'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
629
+			$tax_line_item
630
+		);
631
+		self::set_TXN_ID($tax_line_item, $transaction);
632
+		$total_line_item->add_child_line_item($tax_line_item);
633
+		// and lastly, add the actual taxes
634
+		self::apply_taxes($total_line_item);
635
+		return $tax_line_item;
636
+	}
637
+
638
+
639
+	/**
640
+	 * Creates a default items subtotal line item
641
+	 *
642
+	 * @param EE_Line_Item $pre_tax_line_item
643
+	 * @param EE_Transaction $transaction
644
+	 * @param EE_Event $event
645
+	 * @return EE_Line_Item
646
+	 * @throws \EE_Error
647
+	 */
648
+	public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null)
649
+	{
650
+		$event_line_item = EE_Line_Item::new_instance(array(
651
+			'LIN_code' => self::get_event_code($event),
652
+			'LIN_name' => self::get_event_name($event),
653
+			'LIN_desc' => self::get_event_desc($event),
654
+			'LIN_type' => EEM_Line_Item::type_sub_total,
655
+			'OBJ_type' => 'Event',
656
+			'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0
657
+		));
658
+		$event_line_item = apply_filters(
659
+			'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
660
+			$event_line_item
661
+		);
662
+		self::set_TXN_ID($event_line_item, $transaction);
663
+		$pre_tax_line_item->add_child_line_item($event_line_item);
664
+		return $event_line_item;
665
+	}
666
+
667
+
668
+	/**
669
+	 * Gets what the event ticket's code SHOULD be
670
+	 *
671
+	 * @param EE_Event $event
672
+	 * @return string
673
+	 * @throws \EE_Error
674
+	 */
675
+	public static function get_event_code($event)
676
+	{
677
+		return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
678
+	}
679
+
680
+	/**
681
+	 * Gets the event name
682
+	 * @param EE_Event $event
683
+	 * @return string
684
+	 */
685
+	public static function get_event_name($event)
686
+	{
687
+		return $event instanceof EE_Event ? mb_substr($event->name(), 0, 245) : __('Event', 'event_espresso');
688
+	}
689
+
690
+	/**
691
+	 * Gets the event excerpt
692
+	 * @param EE_Event $event
693
+	 * @return string
694
+	 */
695
+	public static function get_event_desc($event)
696
+	{
697
+		return $event instanceof EE_Event ? $event->short_description() : '';
698
+	}
699
+
700
+	/**
701
+	 * Given the grand total line item and a ticket, finds the event sub-total
702
+	 * line item the ticket's purchase should be added onto
703
+	 *
704
+	 * @access public
705
+	 * @param EE_Line_Item $grand_total the grand total line item
706
+	 * @param EE_Ticket $ticket
707
+	 * @throws \EE_Error
708
+	 * @return EE_Line_Item
709
+	 */
710
+	public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
711
+	{
712
+		$first_datetime = $ticket->first_datetime();
713
+		if (!$first_datetime instanceof EE_Datetime) {
714
+			throw new EE_Error(
715
+				sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID())
716
+			);
717
+		}
718
+		$event = $first_datetime->event();
719
+		if (!$event instanceof EE_Event) {
720
+			throw new EE_Error(
721
+				sprintf(
722
+					__('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'),
723
+					$ticket->ID()
724
+				)
725
+			);
726
+		}
727
+		$events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
728
+		if (!$events_sub_total instanceof EE_Line_Item) {
729
+			throw new EE_Error(
730
+				sprintf(
731
+					__('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'),
732
+					$ticket->ID(),
733
+					$grand_total->ID()
734
+				)
735
+			);
736
+		}
737
+		return $events_sub_total;
738
+	}
739
+
740
+
741
+	/**
742
+	 * Gets the event line item
743
+	 *
744
+	 * @param EE_Line_Item $grand_total
745
+	 * @param EE_Event $event
746
+	 * @return EE_Line_Item for the event subtotal which is a child of $grand_total
747
+	 * @throws \EE_Error
748
+	 */
749
+	public static function get_event_line_item(EE_Line_Item $grand_total, $event)
750
+	{
751
+		/** @type EE_Event $event */
752
+		$event = EEM_Event::instance()->ensure_is_obj($event, true);
753
+		$event_line_item = null;
754
+		$found = false;
755
+		foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
756
+			// default event subtotal, we should only ever find this the first time this method is called
757
+			if (!$event_line_item->OBJ_ID()) {
758
+				// let's use this! but first... set the event details
759
+				EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
760
+				$found = true;
761
+				break;
762
+			} elseif ($event_line_item->OBJ_ID() === $event->ID()) {
763
+				// found existing line item for this event in the cart, so break out of loop and use this one
764
+				$found = true;
765
+				break;
766
+			}
767
+		}
768
+		if (!$found) {
769
+			// there is no event sub-total yet, so add it
770
+			$pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
771
+			// create a new "event" subtotal below that
772
+			$event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
773
+			// and set the event details
774
+			EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
775
+		}
776
+		return $event_line_item;
777
+	}
778
+
779
+
780
+	/**
781
+	 * Creates a default items subtotal line item
782
+	 *
783
+	 * @param EE_Line_Item $event_line_item
784
+	 * @param EE_Event $event
785
+	 * @param EE_Transaction $transaction
786
+	 * @return EE_Line_Item
787
+	 * @throws \EE_Error
788
+	 */
789
+	public static function set_event_subtotal_details(
790
+		EE_Line_Item $event_line_item,
791
+		EE_Event $event,
792
+		$transaction = null
793
+	) {
794
+		if ($event instanceof EE_Event) {
795
+			$event_line_item->set_code(self::get_event_code($event));
796
+			$event_line_item->set_name(self::get_event_name($event));
797
+			$event_line_item->set_desc(self::get_event_desc($event));
798
+			$event_line_item->set_OBJ_ID($event->ID());
799
+		}
800
+		self::set_TXN_ID($event_line_item, $transaction);
801
+	}
802
+
803
+
804
+	/**
805
+	 * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
806
+	 * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
807
+	 * any old taxes are removed
808
+	 *
809
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
810
+	 * @throws \EE_Error
811
+	 */
812
+	public static function apply_taxes(EE_Line_Item $total_line_item)
813
+	{
814
+		/** @type EEM_Price $EEM_Price */
815
+		$EEM_Price = EE_Registry::instance()->load_model('Price');
816
+		// get array of taxes via Price Model
817
+		$ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
818
+		ksort($ordered_taxes);
819
+		$taxes_line_item = self::get_taxes_subtotal($total_line_item);
820
+		// just to be safe, remove its old tax line items
821
+		$taxes_line_item->delete_children_line_items();
822
+		// loop thru taxes
823
+		foreach ($ordered_taxes as $order => $taxes) {
824
+			foreach ($taxes as $tax) {
825
+				if ($tax instanceof EE_Price) {
826
+					$tax_line_item = EE_Line_Item::new_instance(
827
+						array(
828
+							'LIN_name' => $tax->name(),
829
+							'LIN_desc' => $tax->desc(),
830
+							'LIN_percent' => $tax->amount(),
831
+							'LIN_is_taxable' => false,
832
+							'LIN_order' => $order,
833
+							'LIN_total' => 0,
834
+							'LIN_type' => EEM_Line_Item::type_tax,
835
+							'OBJ_type' => 'Price',
836
+							'OBJ_ID' => $tax->ID()
837
+						)
838
+					);
839
+					$tax_line_item = apply_filters(
840
+						'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
841
+						$tax_line_item
842
+					);
843
+					$taxes_line_item->add_child_line_item($tax_line_item);
844
+				}
845
+			}
846
+		}
847
+		$total_line_item->recalculate_total_including_taxes();
848
+	}
849
+
850
+
851
+	/**
852
+	 * Ensures that taxes have been applied to the order, if not applies them.
853
+	 * Returns the total amount of tax
854
+	 *
855
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
856
+	 * @return float
857
+	 * @throws \EE_Error
858
+	 */
859
+	public static function ensure_taxes_applied($total_line_item)
860
+	{
861
+		$taxes_subtotal = self::get_taxes_subtotal($total_line_item);
862
+		if (!$taxes_subtotal->children()) {
863
+			self::apply_taxes($total_line_item);
864
+		}
865
+		return $taxes_subtotal->total();
866
+	}
867
+
868
+
869
+	/**
870
+	 * Deletes ALL children of the passed line item
871
+	 *
872
+	 * @param EE_Line_Item $parent_line_item
873
+	 * @return bool
874
+	 * @throws \EE_Error
875
+	 */
876
+	public static function delete_all_child_items(EE_Line_Item $parent_line_item)
877
+	{
878
+		$deleted = 0;
879
+		foreach ($parent_line_item->children() as $child_line_item) {
880
+			if ($child_line_item instanceof EE_Line_Item) {
881
+				$deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
882
+				if ($child_line_item->ID()) {
883
+					$child_line_item->delete();
884
+					unset($child_line_item);
885
+				} else {
886
+					$parent_line_item->delete_child_line_item($child_line_item->code());
887
+				}
888
+				$deleted++;
889
+			}
890
+		}
891
+		return $deleted;
892
+	}
893
+
894
+
895
+	/**
896
+	 * Deletes the line items as indicated by the line item code(s) provided,
897
+	 * regardless of where they're found in the line item tree. Automatically
898
+	 * re-calculates the line item totals and updates the related transaction. But
899
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
900
+	 * should probably change because of this).
901
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
902
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
903
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
904
+	 * @param array|bool|string $line_item_codes
905
+	 * @return int number of items successfully removed
906
+	 */
907
+	public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
908
+	{
909
+
910
+		if ($total_line_item->type() !== EEM_Line_Item::type_total) {
911
+			EE_Error::doing_it_wrong(
912
+				'EEH_Line_Item::delete_items',
913
+				__(
914
+					'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
915
+					'event_espresso'
916
+				),
917
+				'4.6.18'
918
+			);
919
+		}
920
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
921
+
922
+		// check if only a single line_item_id was passed
923
+		if (!empty($line_item_codes) && !is_array($line_item_codes)) {
924
+			// place single line_item_id in an array to appear as multiple line_item_ids
925
+			$line_item_codes = array($line_item_codes);
926
+		}
927
+		$removals = 0;
928
+		// cycle thru line_item_ids
929
+		foreach ($line_item_codes as $line_item_id) {
930
+			$removals += $total_line_item->delete_child_line_item($line_item_id);
931
+		}
932
+
933
+		if ($removals > 0) {
934
+			$total_line_item->recalculate_taxes_and_tax_total();
935
+			return $removals;
936
+		} else {
937
+			return false;
938
+		}
939
+	}
940
+
941
+
942
+	/**
943
+	 * Overwrites the previous tax by clearing out the old taxes, and creates a new
944
+	 * tax and updates the total line item accordingly
945
+	 *
946
+	 * @param EE_Line_Item $total_line_item
947
+	 * @param float $amount
948
+	 * @param string $name
949
+	 * @param string $description
950
+	 * @param string $code
951
+	 * @param boolean $add_to_existing_line_item
952
+	 *                          if true, and a duplicate line item with the same code is found,
953
+	 *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
954
+	 * @return EE_Line_Item the new tax line item created
955
+	 * @throws \EE_Error
956
+	 */
957
+	public static function set_total_tax_to(
958
+		EE_Line_Item $total_line_item,
959
+		$amount,
960
+		$name = null,
961
+		$description = null,
962
+		$code = null,
963
+		$add_to_existing_line_item = false
964
+	) {
965
+		$tax_subtotal = self::get_taxes_subtotal($total_line_item);
966
+		$taxable_total = $total_line_item->taxable_total();
967
+
968
+		if ($add_to_existing_line_item) {
969
+			$new_tax = $tax_subtotal->get_child_line_item($code);
970
+			EEM_Line_Item::instance()->delete(
971
+				array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
972
+			);
973
+		} else {
974
+			$new_tax = null;
975
+			$tax_subtotal->delete_children_line_items();
976
+		}
977
+		if ($new_tax) {
978
+			$new_tax->set_total($new_tax->total() + $amount);
979
+			$new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
980
+		} else {
981
+			// no existing tax item. Create it
982
+			$new_tax = EE_Line_Item::new_instance(array(
983
+				'TXN_ID' => $total_line_item->TXN_ID(),
984
+				'LIN_name' => $name ? $name : __('Tax', 'event_espresso'),
985
+				'LIN_desc' => $description ? $description : '',
986
+				'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
987
+				'LIN_total' => $amount,
988
+				'LIN_parent' => $tax_subtotal->ID(),
989
+				'LIN_type' => EEM_Line_Item::type_tax,
990
+				'LIN_code' => $code
991
+			));
992
+		}
993
+
994
+		$new_tax = apply_filters(
995
+			'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
996
+			$new_tax,
997
+			$total_line_item
998
+		);
999
+		$new_tax->save();
1000
+		$tax_subtotal->set_total($new_tax->total());
1001
+		$tax_subtotal->save();
1002
+		$total_line_item->recalculate_total_including_taxes();
1003
+		return $new_tax;
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * Makes all the line items which are children of $line_item taxable (or not).
1009
+	 * Does NOT save the line items
1010
+	 * @param EE_Line_Item $line_item
1011
+	 * @param string $code_substring_for_whitelist if this string is part of the line item's code
1012
+	 *  it will be whitelisted (ie, except from becoming taxable)
1013
+	 * @param boolean $taxable
1014
+	 */
1015
+	public static function set_line_items_taxable(
1016
+		EE_Line_Item $line_item,
1017
+		$taxable = true,
1018
+		$code_substring_for_whitelist = null
1019
+	) {
1020
+		$whitelisted = false;
1021
+		if ($code_substring_for_whitelist !== null) {
1022
+			$whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false;
1023
+		}
1024
+		if (!$whitelisted && $line_item->is_line_item()) {
1025
+			$line_item->set_is_taxable($taxable);
1026
+		}
1027
+		foreach ($line_item->children() as $child_line_item) {
1028
+			EEH_Line_Item::set_line_items_taxable($child_line_item, $taxable, $code_substring_for_whitelist);
1029
+		}
1030
+	}
1031
+
1032
+
1033
+	/**
1034
+	 * Gets all descendants that are event subtotals
1035
+	 *
1036
+	 * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1037
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1038
+	 * @return EE_Line_Item[]
1039
+	 */
1040
+	public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1041
+	{
1042
+		return self::get_subtotals_of_object_type($parent_line_item, 'Event');
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 * Gets all descendants subtotals that match the supplied object type
1048
+	 *
1049
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1050
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1051
+	 * @param string $obj_type
1052
+	 * @return EE_Line_Item[]
1053
+	 */
1054
+	public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1055
+	{
1056
+		return self::_get_descendants_by_type_and_object_type(
1057
+			$parent_line_item,
1058
+			EEM_Line_Item::type_sub_total,
1059
+			$obj_type
1060
+		);
1061
+	}
1062
+
1063
+
1064
+	/**
1065
+	 * Gets all descendants that are tickets
1066
+	 *
1067
+	 * @uses  EEH_Line_Item::get_line_items_of_object_type()
1068
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1069
+	 * @return EE_Line_Item[]
1070
+	 */
1071
+	public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1072
+	{
1073
+		return self::get_line_items_of_object_type($parent_line_item, 'Ticket');
1074
+	}
1075
+
1076
+
1077
+	/**
1078
+	 * Gets all descendants subtotals that match the supplied object type
1079
+	 *
1080
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1081
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1082
+	 * @param string $obj_type
1083
+	 * @return EE_Line_Item[]
1084
+	 */
1085
+	public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1086
+	{
1087
+		return self::_get_descendants_by_type_and_object_type($parent_line_item, EEM_Line_Item::type_line_item, $obj_type);
1088
+	}
1089
+
1090
+
1091
+	/**
1092
+	 * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1093
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1094
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1095
+	 * @return EE_Line_Item[]
1096
+	 */
1097
+	public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1098
+	{
1099
+		return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_tax);
1100
+	}
1101
+
1102
+
1103
+	/**
1104
+	 * Gets all the real items purchased which are children of this item
1105
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1106
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1107
+	 * @return EE_Line_Item[]
1108
+	 */
1109
+	public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1110
+	{
1111
+		return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_line_item);
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * Gets all descendants of supplied line item that match the supplied line item type
1117
+	 *
1118
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1119
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1120
+	 * @param string $line_item_type one of the EEM_Line_Item constants
1121
+	 * @return EE_Line_Item[]
1122
+	 */
1123
+	public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1124
+	{
1125
+		return self::_get_descendants_by_type_and_object_type($parent_line_item, $line_item_type, null);
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1131
+	 *
1132
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1133
+	 * @param string $line_item_type one of the EEM_Line_Item constants
1134
+	 * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when searching
1135
+	 * @return EE_Line_Item[]
1136
+	 */
1137
+	protected static function _get_descendants_by_type_and_object_type(
1138
+		EE_Line_Item $parent_line_item,
1139
+		$line_item_type,
1140
+		$obj_type = null
1141
+	) {
1142
+		$objects = array();
1143
+		foreach ($parent_line_item->children() as $child_line_item) {
1144
+			if ($child_line_item instanceof EE_Line_Item) {
1145
+				if ($child_line_item->type() === $line_item_type
1146
+					&& (
1147
+						$child_line_item->OBJ_type() === $obj_type || $obj_type === null
1148
+					)
1149
+				) {
1150
+					$objects[] = $child_line_item;
1151
+				} else {
1152
+					// go-through-all-its children looking for more matches
1153
+					$objects = array_merge(
1154
+						$objects,
1155
+						self::_get_descendants_by_type_and_object_type(
1156
+							$child_line_item,
1157
+							$line_item_type,
1158
+							$obj_type
1159
+						)
1160
+					);
1161
+				}
1162
+			}
1163
+		}
1164
+		return $objects;
1165
+	}
1166
+
1167
+
1168
+	/**
1169
+	 * Gets all descendants subtotals that match the supplied object type
1170
+	 *
1171
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1172
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1173
+	 * @param string $OBJ_type object type (like Event)
1174
+	 * @param array $OBJ_IDs array of OBJ_IDs
1175
+	 * @return EE_Line_Item[]
1176
+	 */
1177
+	public static function get_line_items_by_object_type_and_IDs(
1178
+		EE_Line_Item $parent_line_item,
1179
+		$OBJ_type = '',
1180
+		$OBJ_IDs = array()
1181
+	) {
1182
+		return self::_get_descendants_by_object_type_and_object_ID($parent_line_item, $OBJ_type, $OBJ_IDs);
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well
1188
+	 *
1189
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1190
+	 * @param string $OBJ_type object type (like Event)
1191
+	 * @param array $OBJ_IDs array of OBJ_IDs
1192
+	 * @return EE_Line_Item[]
1193
+	 */
1194
+	protected static function _get_descendants_by_object_type_and_object_ID(
1195
+		EE_Line_Item $parent_line_item,
1196
+		$OBJ_type,
1197
+		$OBJ_IDs
1198
+	) {
1199
+		$objects = array();
1200
+		foreach ($parent_line_item->children() as $child_line_item) {
1201
+			if ($child_line_item instanceof EE_Line_Item) {
1202
+				if ($child_line_item->OBJ_type() === $OBJ_type
1203
+					&& is_array($OBJ_IDs)
1204
+					&& in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1205
+				) {
1206
+					$objects[] = $child_line_item;
1207
+				} else {
1208
+					// go-through-all-its children looking for more matches
1209
+					$objects = array_merge(
1210
+						$objects,
1211
+						self::_get_descendants_by_object_type_and_object_ID(
1212
+							$child_line_item,
1213
+							$OBJ_type,
1214
+							$OBJ_IDs
1215
+						)
1216
+					);
1217
+				}
1218
+			}
1219
+		}
1220
+		return $objects;
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * Uses a breadth-first-search in order to find the nearest descendant of
1226
+	 * the specified type and returns it, else NULL
1227
+	 *
1228
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1229
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1230
+	 * @param string $type like one of the EEM_Line_Item::type_*
1231
+	 * @return EE_Line_Item
1232
+	 */
1233
+	public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1234
+	{
1235
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1236
+	}
1237
+
1238
+
1239
+	/**
1240
+	 * Uses a breadth-first-search in order to find the nearest descendant
1241
+	 * having the specified LIN_code and returns it, else NULL
1242
+	 *
1243
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1244
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1245
+	 * @param string $code any value used for LIN_code
1246
+	 * @return EE_Line_Item
1247
+	 */
1248
+	public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1249
+	{
1250
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1251
+	}
1252
+
1253
+
1254
+	/**
1255
+	 * Uses a breadth-first-search in order to find the nearest descendant
1256
+	 * having the specified LIN_code and returns it, else NULL
1257
+	 *
1258
+	 * @param \EE_Line_Item $parent_line_item - the line item to find descendants of
1259
+	 * @param string $search_field name of EE_Line_Item property
1260
+	 * @param string $value any value stored in $search_field
1261
+	 * @return EE_Line_Item
1262
+	 */
1263
+	protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1264
+	{
1265
+		foreach ($parent_line_item->children() as $child) {
1266
+			if ($child->get($search_field) == $value) {
1267
+				return $child;
1268
+			}
1269
+		}
1270
+		foreach ($parent_line_item->children() as $child) {
1271
+			$descendant_found = self::_get_nearest_descendant($child, $search_field, $value);
1272
+			if ($descendant_found) {
1273
+				return $descendant_found;
1274
+			}
1275
+		}
1276
+		return null;
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1282
+	 * else recursively walks up the line item tree until a parent of type total is found,
1283
+	 *
1284
+	 * @param EE_Line_Item $line_item
1285
+	 * @return \EE_Line_Item
1286
+	 * @throws \EE_Error
1287
+	 */
1288
+	public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1289
+	{
1290
+		if ($line_item->TXN_ID()) {
1291
+			$total_line_item = $line_item->transaction()->total_line_item(false);
1292
+			if ($total_line_item instanceof EE_Line_Item) {
1293
+				return $total_line_item;
1294
+			}
1295
+		} else {
1296
+			$line_item_parent = $line_item->parent();
1297
+			if ($line_item_parent instanceof EE_Line_Item) {
1298
+				if ($line_item_parent->is_total()) {
1299
+					return $line_item_parent;
1300
+				}
1301
+				return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1302
+			}
1303
+		}
1304
+		throw new EE_Error(
1305
+			sprintf(
1306
+				__('A valid grand total for line item %1$d was not found.', 'event_espresso'),
1307
+				$line_item->ID()
1308
+			)
1309
+		);
1310
+	}
1311
+
1312
+
1313
+	/**
1314
+	 * Prints out a representation of the line item tree
1315
+	 *
1316
+	 * @param EE_Line_Item $line_item
1317
+	 * @param int $indentation
1318
+	 * @return void
1319
+	 * @throws \EE_Error
1320
+	 */
1321
+	public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1322
+	{
1323
+		echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1324
+		if (!$indentation) {
1325
+			echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1326
+		}
1327
+		for ($i = 0; $i < $indentation; $i++) {
1328
+			echo ". ";
1329
+		}
1330
+		$breakdown = '';
1331
+		if ($line_item->is_line_item()) {
1332
+			if ($line_item->is_percent()) {
1333
+				$breakdown = "{$line_item->percent()}%";
1334
+			} else {
1335
+				$breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1336
+			}
1337
+		}
1338
+		echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}";
1339
+		if ($breakdown) {
1340
+			echo " ( {$breakdown} )";
1341
+		}
1342
+		if ($line_item->is_taxable()) {
1343
+			echo "  * taxable";
1344
+		}
1345
+		if ($line_item->children()) {
1346
+			foreach ($line_item->children() as $child) {
1347
+				self::visualize($child, $indentation + 1);
1348
+			}
1349
+		}
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Calculates the registration's final price, taking into account that they
1355
+	 * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1356
+	 * and receive a portion of any transaction-wide discounts.
1357
+	 * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1358
+	 * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1359
+	 * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1360
+	 * and brent's final price should be $5.50.
1361
+	 *
1362
+	 * In order to do this, we basically need to traverse the line item tree calculating
1363
+	 * the running totals (just as if we were recalculating the total), but when we identify
1364
+	 * regular line items, we need to keep track of their share of the grand total.
1365
+	 * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1366
+	 * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1367
+	 * when there are non-taxable items; otherwise they would be the same)
1368
+	 *
1369
+	 * @param EE_Line_Item $line_item
1370
+	 * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that
1371
+	 *                                                                            can be included in price calculations at this moment
1372
+	 * @return array        keys are line items for tickets IDs and values are their share of the running total,
1373
+	 *                                          plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg
1374
+	 *                                          array(
1375
+	 *                                          12 => 4.3
1376
+	 *                                          23 => 8.0
1377
+	 *                                          'total' => 16.6,
1378
+	 *                                          'taxable' => array(
1379
+	 *                                          12 => 10,
1380
+	 *                                          23 => 4
1381
+	 *                                          ).
1382
+	 *                                          So to find which registrations have which final price, we need to find which line item
1383
+	 *                                          is theirs, which can be done with
1384
+	 *                                          `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );`
1385
+	 */
1386
+	public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array())
1387
+	{
1388
+		// init running grand total if not already
1389
+		if (!isset($running_totals['total'])) {
1390
+			$running_totals['total'] = 0;
1391
+		}
1392
+		if (!isset($running_totals['taxable'])) {
1393
+			$running_totals['taxable'] = array('total' => 0);
1394
+		}
1395
+		foreach ($line_item->children() as $child_line_item) {
1396
+			switch ($child_line_item->type()) {
1397
+				case EEM_Line_Item::type_sub_total:
1398
+					$running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities);
1399
+					// combine arrays but preserve numeric keys
1400
+					$running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1401
+					$running_totals['total'] += $running_totals_from_subtotal['total'];
1402
+					$running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1403
+					break;
1404
+
1405
+				case EEM_Line_Item::type_tax_sub_total:
1406
+					// find how much the taxes percentage is
1407
+					if ($child_line_item->percent() !== 0) {
1408
+						$tax_percent_decimal = $child_line_item->percent() / 100;
1409
+					} else {
1410
+						$tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1411
+					}
1412
+					// and apply to all the taxable totals, and add to the pretax totals
1413
+					foreach ($running_totals as $line_item_id => $this_running_total) {
1414
+						// "total" and "taxable" array key is an exception
1415
+						if ($line_item_id === 'taxable') {
1416
+							continue;
1417
+						}
1418
+						$taxable_total = $running_totals['taxable'][ $line_item_id ];
1419
+						$running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1420
+					}
1421
+					break;
1422
+
1423
+				case EEM_Line_Item::type_line_item:
1424
+					// ticket line items or ????
1425
+					if ($child_line_item->OBJ_type() === 'Ticket') {
1426
+						// kk it's a ticket
1427
+						if (isset($running_totals[ $child_line_item->ID() ])) {
1428
+							// huh? that shouldn't happen.
1429
+							$running_totals['total'] += $child_line_item->total();
1430
+						} else {
1431
+							// its not in our running totals yet. great.
1432
+							if ($child_line_item->is_taxable()) {
1433
+								$taxable_amount = $child_line_item->unit_price();
1434
+							} else {
1435
+								$taxable_amount = 0;
1436
+							}
1437
+							// are we only calculating totals for some tickets?
1438
+							if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1439
+								$quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1440
+								$running_totals[ $child_line_item->ID() ] = $quantity
1441
+									? $child_line_item->unit_price()
1442
+									: 0;
1443
+								$running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1444
+									? $taxable_amount
1445
+									: 0;
1446
+							} else {
1447
+								$quantity = $child_line_item->quantity();
1448
+								$running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1449
+								$running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1450
+							}
1451
+							$running_totals['taxable']['total'] += $taxable_amount * $quantity;
1452
+							$running_totals['total'] += $child_line_item->unit_price() * $quantity;
1453
+						}
1454
+					} else {
1455
+						// it's some other type of item added to the cart
1456
+						// it should affect the running totals
1457
+						// basically we want to convert it into a PERCENT modifier. Because
1458
+						// more clearly affect all registration's final price equally
1459
+						$line_items_percent_of_running_total = $running_totals['total'] > 0
1460
+							? ($child_line_item->total() / $running_totals['total']) + 1
1461
+							: 1;
1462
+						foreach ($running_totals as $line_item_id => $this_running_total) {
1463
+							// the "taxable" array key is an exception
1464
+							if ($line_item_id === 'taxable') {
1465
+								continue;
1466
+							}
1467
+							// update the running totals
1468
+							// yes this actually even works for the running grand total!
1469
+							$running_totals[ $line_item_id ] =
1470
+								$line_items_percent_of_running_total * $this_running_total;
1471
+
1472
+							if ($child_line_item->is_taxable()) {
1473
+								$running_totals['taxable'][ $line_item_id ] =
1474
+									$line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1475
+							}
1476
+						}
1477
+					}
1478
+					break;
1479
+			}
1480
+		}
1481
+		return $running_totals;
1482
+	}
1483
+
1484
+
1485
+	/**
1486
+	 * @param \EE_Line_Item $total_line_item
1487
+	 * @param \EE_Line_Item $ticket_line_item
1488
+	 * @return float | null
1489
+	 * @throws \OutOfRangeException
1490
+	 */
1491
+	public static function calculate_final_price_for_ticket_line_item(\EE_Line_Item $total_line_item, \EE_Line_Item $ticket_line_item)
1492
+	{
1493
+		static $final_prices_per_ticket_line_item = array();
1494
+		if (empty($final_prices_per_ticket_line_item)) {
1495
+			$final_prices_per_ticket_line_item = \EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1496
+				$total_line_item
1497
+			);
1498
+		}
1499
+		// ok now find this new registration's final price
1500
+		if (isset($final_prices_per_ticket_line_item[ $ticket_line_item->ID() ])) {
1501
+			return $final_prices_per_ticket_line_item[ $ticket_line_item->ID() ];
1502
+		}
1503
+		$message = sprintf(
1504
+			__(
1505
+				'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1506
+				'event_espresso'
1507
+			),
1508
+			$ticket_line_item->ID()
1509
+		);
1510
+		if (WP_DEBUG) {
1511
+			$message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1512
+			throw new \OutOfRangeException($message);
1513
+		} else {
1514
+			EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1515
+		}
1516
+		return null;
1517
+	}
1518
+
1519
+
1520
+	/**
1521
+	 * Creates a duplicate of the line item tree, except only includes billable items
1522
+	 * and the portion of line items attributed to billable things
1523
+	 *
1524
+	 * @param EE_Line_Item $line_item
1525
+	 * @param EE_Registration[] $registrations
1526
+	 * @return \EE_Line_Item
1527
+	 * @throws \EE_Error
1528
+	 */
1529
+	public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1530
+	{
1531
+		$copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1532
+		foreach ($line_item->children() as $child_li) {
1533
+			$copy_li->add_child_line_item(EEH_Line_Item::billable_line_item_tree($child_li, $registrations));
1534
+		}
1535
+		// if this is the grand total line item, make sure the totals all add up
1536
+		// (we could have duplicated this logic AS we copied the line items, but
1537
+		// it seems DRYer this way)
1538
+		if ($copy_li->type() === EEM_Line_Item::type_total) {
1539
+			$copy_li->recalculate_total_including_taxes();
1540
+		}
1541
+		return $copy_li;
1542
+	}
1543
+
1544
+
1545
+	/**
1546
+	 * Creates a new, unsaved line item from $line_item that factors in the
1547
+	 * number of billable registrations on $registrations.
1548
+	 *
1549
+	 * @param EE_Line_Item $line_item
1550
+	 * @return EE_Line_Item
1551
+	 * @throws \EE_Error
1552
+	 * @param EE_Registration[] $registrations
1553
+	 */
1554
+	public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1555
+	{
1556
+		$new_li_fields = $line_item->model_field_array();
1557
+		if ($line_item->type() === EEM_Line_Item::type_line_item &&
1558
+			$line_item->OBJ_type() === 'Ticket'
1559
+		) {
1560
+			$count = 0;
1561
+			foreach ($registrations as $registration) {
1562
+				if ($line_item->OBJ_ID() === $registration->ticket_ID() &&
1563
+					in_array($registration->status_ID(), EEM_Registration::reg_statuses_that_allow_payment())
1564
+				) {
1565
+					$count++;
1566
+				}
1567
+			}
1568
+			$new_li_fields['LIN_quantity'] = $count;
1569
+		}
1570
+		// don't set the total. We'll leave that up to the code that calculates it
1571
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1572
+		return EE_Line_Item::new_instance($new_li_fields);
1573
+	}
1574
+
1575
+
1576
+	/**
1577
+	 * Returns a modified line item tree where all the subtotals which have a total of 0
1578
+	 * are removed, and line items with a quantity of 0
1579
+	 *
1580
+	 * @param EE_Line_Item $line_item |null
1581
+	 * @return \EE_Line_Item|null
1582
+	 * @throws \EE_Error
1583
+	 */
1584
+	public static function non_empty_line_items(EE_Line_Item $line_item)
1585
+	{
1586
+		$copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1587
+		if ($copied_li === null) {
1588
+			return null;
1589
+		}
1590
+		// if this is an event subtotal, we want to only include it if it
1591
+		// has a non-zero total and at least one ticket line item child
1592
+		$ticket_children = 0;
1593
+		foreach ($line_item->children() as $child_li) {
1594
+			$child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1595
+			if ($child_li_copy !== null) {
1596
+				$copied_li->add_child_line_item($child_li_copy);
1597
+				if ($child_li_copy->type() === EEM_Line_Item::type_line_item &&
1598
+					$child_li_copy->OBJ_type() === 'Ticket'
1599
+				) {
1600
+					$ticket_children++;
1601
+				}
1602
+			}
1603
+		}
1604
+		// if this is an event subtotal with NO ticket children
1605
+		// we basically want to ignore it
1606
+		if ($ticket_children === 0
1607
+			&& $line_item->type() === EEM_Line_Item::type_sub_total
1608
+			&& $line_item->OBJ_type() === 'Event'
1609
+			&& $line_item->total() === 0
1610
+		) {
1611
+			return null;
1612
+		}
1613
+		return $copied_li;
1614
+	}
1615
+
1616
+
1617
+	/**
1618
+	 * Creates a new, unsaved line item, but if it's a ticket line item
1619
+	 * with a total of 0, or a subtotal of 0, returns null instead
1620
+	 *
1621
+	 * @param EE_Line_Item $line_item
1622
+	 * @return EE_Line_Item
1623
+	 * @throws \EE_Error
1624
+	 */
1625
+	public static function non_empty_line_item(EE_Line_Item $line_item)
1626
+	{
1627
+		if ($line_item->type() === EEM_Line_Item::type_line_item &&
1628
+			$line_item->OBJ_type() === 'Ticket' &&
1629
+			$line_item->quantity() === 0
1630
+		) {
1631
+			return null;
1632
+		}
1633
+		$new_li_fields = $line_item->model_field_array();
1634
+		// don't set the total. We'll leave that up to the code that calculates it
1635
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1636
+		return EE_Line_Item::new_instance($new_li_fields);
1637
+	}
1638
+
1639
+
1640
+
1641
+	/**************************************** @DEPRECATED METHODS *************************************** */
1642
+	/**
1643
+	 * @deprecated
1644
+	 * @param EE_Line_Item $total_line_item
1645
+	 * @return \EE_Line_Item
1646
+	 * @throws \EE_Error
1647
+	 */
1648
+	public static function get_items_subtotal(EE_Line_Item $total_line_item)
1649
+	{
1650
+		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');
1651
+		return self::get_pre_tax_subtotal($total_line_item);
1652
+	}
1653
+
1654
+
1655
+	/**
1656
+	 * @deprecated
1657
+	 * @param EE_Transaction $transaction
1658
+	 * @return \EE_Line_Item
1659
+	 * @throws \EE_Error
1660
+	 */
1661
+	public static function create_default_total_line_item($transaction = null)
1662
+	{
1663
+		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');
1664
+		return self::create_total_line_item($transaction);
1665
+	}
1666
+
1667
+
1668
+	/**
1669
+	 * @deprecated
1670
+	 * @param EE_Line_Item $total_line_item
1671
+	 * @param EE_Transaction $transaction
1672
+	 * @return \EE_Line_Item
1673
+	 * @throws \EE_Error
1674
+	 */
1675
+	public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null)
1676
+	{
1677
+		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');
1678
+		return self::create_pre_tax_subtotal($total_line_item, $transaction);
1679
+	}
1680
+
1681
+
1682
+	/**
1683
+	 * @deprecated
1684
+	 * @param EE_Line_Item $total_line_item
1685
+	 * @param EE_Transaction $transaction
1686
+	 * @return \EE_Line_Item
1687
+	 * @throws \EE_Error
1688
+	 */
1689
+	public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
1690
+	{
1691
+		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');
1692
+		return self::create_taxes_subtotal($total_line_item, $transaction);
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * @deprecated
1698
+	 * @param EE_Line_Item $total_line_item
1699
+	 * @param EE_Transaction $transaction
1700
+	 * @return \EE_Line_Item
1701
+	 * @throws \EE_Error
1702
+	 */
1703
+	public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null)
1704
+	{
1705
+		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');
1706
+		return self::create_event_subtotal($total_line_item, $transaction);
1707
+	}
1708 1708
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Sideloader.helper.php 2 patches
Indentation   +174 added lines, -174 removed lines patch added patch discarded remove patch
@@ -14,178 +14,178 @@
 block discarded – undo
14 14
 class EEH_Sideloader extends EEH_Base
15 15
 {
16 16
 
17
-    private $_upload_to;
18
-    private $_upload_from;
19
-    private $_permissions;
20
-    private $_new_file_name;
21
-
22
-
23
-    /**
24
-     * constructor allows the user to set the properties on the sideloader on construct.  However, there are also setters for doing so.
25
-     *
26
-     * @access public
27
-     * @param array $init array fo initializing the sideloader if keys match the properties.
28
-     */
29
-    public function __construct($init = array())
30
-    {
31
-        $this->_init($init);
32
-    }
33
-
34
-
35
-    /**
36
-     * sets the properties for class either to defaults or using incoming initialization array
37
-     *
38
-     * @access private
39
-     * @param  array  $init array on init (keys match properties others ignored)
40
-     * @return void
41
-     */
42
-    private function _init($init)
43
-    {
44
-        $defaults = array(
45
-            '_upload_to' => $this->_get_wp_uploads_dir(),
46
-            '_upload_from' => '',
47
-            '_permissions' => 0644,
48
-            '_new_file_name' => 'EE_Sideloader_' . uniqid() . '.default'
49
-            );
50
-
51
-        $props = array_merge($defaults, $init);
52
-
53
-        foreach ($props as $key => $val) {
54
-            if (EEH_Class_Tools::has_property($this, $key)) {
55
-                $this->{$key} = $val;
56
-            }
57
-        }
58
-
59
-        // make sure we include the required wp file for needed functions
60
-        require_once(ABSPATH . 'wp-admin/includes/file.php');
61
-    }
62
-
63
-
64
-    // utilities
65
-    private function _get_wp_uploads_dir()
66
-    {
67
-    }
68
-
69
-    // setters
70
-    public function set_upload_to($upload_to_folder)
71
-    {
72
-        $this->_upload_to = $upload_to_folder;
73
-    }
74
-    public function set_upload_from($upload_from_folder)
75
-    {
76
-        $this->_upload_from_folder = $upload_from_folder;
77
-    }
78
-    public function set_permissions($permissions)
79
-    {
80
-        $this->_permissions = $permissions;
81
-    }
82
-    public function set_new_file_name($new_file_name)
83
-    {
84
-        $this->_new_file_name = $new_file_name;
85
-    }
86
-
87
-    // getters
88
-    public function get_upload_to()
89
-    {
90
-        return $this->_upload_to;
91
-    }
92
-    public function get_upload_from()
93
-    {
94
-        return $this->_upload_from;
95
-    }
96
-    public function get_permissions()
97
-    {
98
-        return $this->_permissions;
99
-    }
100
-    public function get_new_file_name()
101
-    {
102
-        return $this->_new_file_name;
103
-    }
104
-
105
-
106
-    // upload methods
107
-    public function sideload()
108
-    {
109
-        // setup temp dir
110
-        $temp_file = wp_tempnam($this->_upload_from);
111
-
112
-        if (!$temp_file) {
113
-            EE_Error::add_error(
114
-                esc_html__('Something went wrong with the upload.  Unable to create a tmp file for the uploaded file on the server', 'event_espresso'),
115
-                __FILE__,
116
-                __FUNCTION__,
117
-                __LINE__
118
-            );
119
-            return false;
120
-        }
121
-
122
-        do_action('AHEE__EEH_Sideloader__sideload__before', $this, $temp_file);
123
-
124
-        $wp_remote_args = apply_filters('FHEE__EEH_Sideloader__sideload__wp_remote_args', array( 'timeout' => 500, 'stream' => true, 'filename' => $temp_file ), $this, $temp_file);
125
-
126
-        $response = wp_safe_remote_get($this->_upload_from, $wp_remote_args);
127
-
128
-        if (is_wp_error($response) || 200 != wp_remote_retrieve_response_code($response)) {
129
-            unlink($temp_file);
130
-            if (defined('WP_DEBUG') && WP_DEBUG) {
131
-                EE_Error::add_error(
132
-                    sprintf(
133
-                        esc_html__('Unable to upload the file. Either the path given to upload from is incorrect, or something else happened. Here is the path given: %s', 'event_espresso'),
134
-                        $this->_upload_from
135
-                    ),
136
-                    __FILE__,
137
-                    __FUNCTION__,
138
-                    __LINE__
139
-                );
140
-            }
141
-            return false;
142
-        }
143
-
144
-        // possible md5 check
145
-        $content_md5 = wp_remote_retrieve_header($response, 'content-md5');
146
-        if ($content_md5) {
147
-            $md5_check = verify_file_md5($temp_file, $content_md5);
148
-            if (is_wp_error($md5_check)) {
149
-                unlink($temp_file);
150
-                EE_Error::add_error(
151
-                    $md5_check->get_error_message(),
152
-                    __FILE__,
153
-                    __FUNCTION__,
154
-                    __LINE__
155
-                );
156
-                return false;
157
-            }
158
-        }
159
-
160
-        $file = $temp_file;
161
-
162
-        // now we have the file, let's get it in the right directory with the right name.
163
-        $path = apply_filters('FHEE__EEH_Sideloader__sideload__new_path', $this->_upload_to . $this->_new_file_name, $this);
164
-
165
-        // move file in
166
-        if (false === @ rename($file, $path)) {
167
-            unlink($temp_file);
168
-            EE_Error::add_error(
169
-                sprintf(
170
-                    esc_html__('Unable to move the file to new location (possible permissions errors). This is the path the class attempted to move the file to: %s', 'event_espresso'),
171
-                    $path
172
-                ),
173
-                __FILE__,
174
-                __FUNCTION__,
175
-                __LINE__
176
-            );
177
-            return false;
178
-        }
179
-
180
-        // set permissions
181
-        $permissions = apply_filters('FHEE__EEH_Sideloader__sideload__permissions_applied', $this->_permissions, $this);
182
-        chmod($path, $permissions);
183
-
184
-        // that's it.  let's allow for actions after file uploaded.
185
-        do_action('AHEE__EE_Sideloader__sideload_after', $this, $path);
186
-
187
-        // unlink tempfile
188
-        @unlink($temp_file);
189
-        return true;
190
-    }
17
+	private $_upload_to;
18
+	private $_upload_from;
19
+	private $_permissions;
20
+	private $_new_file_name;
21
+
22
+
23
+	/**
24
+	 * constructor allows the user to set the properties on the sideloader on construct.  However, there are also setters for doing so.
25
+	 *
26
+	 * @access public
27
+	 * @param array $init array fo initializing the sideloader if keys match the properties.
28
+	 */
29
+	public function __construct($init = array())
30
+	{
31
+		$this->_init($init);
32
+	}
33
+
34
+
35
+	/**
36
+	 * sets the properties for class either to defaults or using incoming initialization array
37
+	 *
38
+	 * @access private
39
+	 * @param  array  $init array on init (keys match properties others ignored)
40
+	 * @return void
41
+	 */
42
+	private function _init($init)
43
+	{
44
+		$defaults = array(
45
+			'_upload_to' => $this->_get_wp_uploads_dir(),
46
+			'_upload_from' => '',
47
+			'_permissions' => 0644,
48
+			'_new_file_name' => 'EE_Sideloader_' . uniqid() . '.default'
49
+			);
50
+
51
+		$props = array_merge($defaults, $init);
52
+
53
+		foreach ($props as $key => $val) {
54
+			if (EEH_Class_Tools::has_property($this, $key)) {
55
+				$this->{$key} = $val;
56
+			}
57
+		}
58
+
59
+		// make sure we include the required wp file for needed functions
60
+		require_once(ABSPATH . 'wp-admin/includes/file.php');
61
+	}
62
+
63
+
64
+	// utilities
65
+	private function _get_wp_uploads_dir()
66
+	{
67
+	}
68
+
69
+	// setters
70
+	public function set_upload_to($upload_to_folder)
71
+	{
72
+		$this->_upload_to = $upload_to_folder;
73
+	}
74
+	public function set_upload_from($upload_from_folder)
75
+	{
76
+		$this->_upload_from_folder = $upload_from_folder;
77
+	}
78
+	public function set_permissions($permissions)
79
+	{
80
+		$this->_permissions = $permissions;
81
+	}
82
+	public function set_new_file_name($new_file_name)
83
+	{
84
+		$this->_new_file_name = $new_file_name;
85
+	}
86
+
87
+	// getters
88
+	public function get_upload_to()
89
+	{
90
+		return $this->_upload_to;
91
+	}
92
+	public function get_upload_from()
93
+	{
94
+		return $this->_upload_from;
95
+	}
96
+	public function get_permissions()
97
+	{
98
+		return $this->_permissions;
99
+	}
100
+	public function get_new_file_name()
101
+	{
102
+		return $this->_new_file_name;
103
+	}
104
+
105
+
106
+	// upload methods
107
+	public function sideload()
108
+	{
109
+		// setup temp dir
110
+		$temp_file = wp_tempnam($this->_upload_from);
111
+
112
+		if (!$temp_file) {
113
+			EE_Error::add_error(
114
+				esc_html__('Something went wrong with the upload.  Unable to create a tmp file for the uploaded file on the server', 'event_espresso'),
115
+				__FILE__,
116
+				__FUNCTION__,
117
+				__LINE__
118
+			);
119
+			return false;
120
+		}
121
+
122
+		do_action('AHEE__EEH_Sideloader__sideload__before', $this, $temp_file);
123
+
124
+		$wp_remote_args = apply_filters('FHEE__EEH_Sideloader__sideload__wp_remote_args', array( 'timeout' => 500, 'stream' => true, 'filename' => $temp_file ), $this, $temp_file);
125
+
126
+		$response = wp_safe_remote_get($this->_upload_from, $wp_remote_args);
127
+
128
+		if (is_wp_error($response) || 200 != wp_remote_retrieve_response_code($response)) {
129
+			unlink($temp_file);
130
+			if (defined('WP_DEBUG') && WP_DEBUG) {
131
+				EE_Error::add_error(
132
+					sprintf(
133
+						esc_html__('Unable to upload the file. Either the path given to upload from is incorrect, or something else happened. Here is the path given: %s', 'event_espresso'),
134
+						$this->_upload_from
135
+					),
136
+					__FILE__,
137
+					__FUNCTION__,
138
+					__LINE__
139
+				);
140
+			}
141
+			return false;
142
+		}
143
+
144
+		// possible md5 check
145
+		$content_md5 = wp_remote_retrieve_header($response, 'content-md5');
146
+		if ($content_md5) {
147
+			$md5_check = verify_file_md5($temp_file, $content_md5);
148
+			if (is_wp_error($md5_check)) {
149
+				unlink($temp_file);
150
+				EE_Error::add_error(
151
+					$md5_check->get_error_message(),
152
+					__FILE__,
153
+					__FUNCTION__,
154
+					__LINE__
155
+				);
156
+				return false;
157
+			}
158
+		}
159
+
160
+		$file = $temp_file;
161
+
162
+		// now we have the file, let's get it in the right directory with the right name.
163
+		$path = apply_filters('FHEE__EEH_Sideloader__sideload__new_path', $this->_upload_to . $this->_new_file_name, $this);
164
+
165
+		// move file in
166
+		if (false === @ rename($file, $path)) {
167
+			unlink($temp_file);
168
+			EE_Error::add_error(
169
+				sprintf(
170
+					esc_html__('Unable to move the file to new location (possible permissions errors). This is the path the class attempted to move the file to: %s', 'event_espresso'),
171
+					$path
172
+				),
173
+				__FILE__,
174
+				__FUNCTION__,
175
+				__LINE__
176
+			);
177
+			return false;
178
+		}
179
+
180
+		// set permissions
181
+		$permissions = apply_filters('FHEE__EEH_Sideloader__sideload__permissions_applied', $this->_permissions, $this);
182
+		chmod($path, $permissions);
183
+
184
+		// that's it.  let's allow for actions after file uploaded.
185
+		do_action('AHEE__EE_Sideloader__sideload_after', $this, $path);
186
+
187
+		// unlink tempfile
188
+		@unlink($temp_file);
189
+		return true;
190
+	}
191 191
 } //end EEH_Template class
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
             '_upload_to' => $this->_get_wp_uploads_dir(),
46 46
             '_upload_from' => '',
47 47
             '_permissions' => 0644,
48
-            '_new_file_name' => 'EE_Sideloader_' . uniqid() . '.default'
48
+            '_new_file_name' => 'EE_Sideloader_'.uniqid().'.default'
49 49
             );
50 50
 
51 51
         $props = array_merge($defaults, $init);
@@ -57,7 +57,7 @@  discard block
 block discarded – undo
57 57
         }
58 58
 
59 59
         // make sure we include the required wp file for needed functions
60
-        require_once(ABSPATH . 'wp-admin/includes/file.php');
60
+        require_once(ABSPATH.'wp-admin/includes/file.php');
61 61
     }
62 62
 
63 63
 
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
         // setup temp dir
110 110
         $temp_file = wp_tempnam($this->_upload_from);
111 111
 
112
-        if (!$temp_file) {
112
+        if ( ! $temp_file) {
113 113
             EE_Error::add_error(
114 114
                 esc_html__('Something went wrong with the upload.  Unable to create a tmp file for the uploaded file on the server', 'event_espresso'),
115 115
                 __FILE__,
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
 
122 122
         do_action('AHEE__EEH_Sideloader__sideload__before', $this, $temp_file);
123 123
 
124
-        $wp_remote_args = apply_filters('FHEE__EEH_Sideloader__sideload__wp_remote_args', array( 'timeout' => 500, 'stream' => true, 'filename' => $temp_file ), $this, $temp_file);
124
+        $wp_remote_args = apply_filters('FHEE__EEH_Sideloader__sideload__wp_remote_args', array('timeout' => 500, 'stream' => true, 'filename' => $temp_file), $this, $temp_file);
125 125
 
126 126
         $response = wp_safe_remote_get($this->_upload_from, $wp_remote_args);
127 127
 
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
         $file = $temp_file;
161 161
 
162 162
         // now we have the file, let's get it in the right directory with the right name.
163
-        $path = apply_filters('FHEE__EEH_Sideloader__sideload__new_path', $this->_upload_to . $this->_new_file_name, $this);
163
+        $path = apply_filters('FHEE__EEH_Sideloader__sideload__new_path', $this->_upload_to.$this->_new_file_name, $this);
164 164
 
165 165
         // move file in
166 166
         if (false === @ rename($file, $path)) {
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 2 patches
Indentation   +2499 added lines, -2499 removed lines patch added patch discarded remove patch
@@ -14,2503 +14,2503 @@
 block discarded – undo
14 14
 class Transactions_Admin_Page extends EE_Admin_Page
15 15
 {
16 16
 
17
-    /**
18
-     * @var EE_Transaction
19
-     */
20
-    private $_transaction;
21
-
22
-    /**
23
-     * @var EE_Session
24
-     */
25
-    private $_session;
26
-
27
-    /**
28
-     * @var array $_txn_status
29
-     */
30
-    private static $_txn_status;
31
-
32
-    /**
33
-     * @var array $_pay_status
34
-     */
35
-    private static $_pay_status;
36
-
37
-    /**
38
-     * @var array $_existing_reg_payment_REG_IDs
39
-     */
40
-    protected $_existing_reg_payment_REG_IDs = null;
41
-
42
-
43
-    /**
44
-     * @Constructor
45
-     * @access public
46
-     * @param bool $routing
47
-     * @throws EE_Error
48
-     * @throws InvalidArgumentException
49
-     * @throws ReflectionException
50
-     * @throws InvalidDataTypeException
51
-     * @throws InvalidInterfaceException
52
-     */
53
-    public function __construct($routing = true)
54
-    {
55
-        parent::__construct($routing);
56
-    }
57
-
58
-
59
-    /**
60
-     *    _init_page_props
61
-     *
62
-     * @return void
63
-     */
64
-    protected function _init_page_props()
65
-    {
66
-        $this->page_slug = TXN_PG_SLUG;
67
-        $this->page_label = esc_html__('Transactions', 'event_espresso');
68
-        $this->_admin_base_url = TXN_ADMIN_URL;
69
-        $this->_admin_base_path = TXN_ADMIN;
70
-    }
71
-
72
-
73
-    /**
74
-     *    _ajax_hooks
75
-     *
76
-     * @return void
77
-     */
78
-    protected function _ajax_hooks()
79
-    {
80
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
81
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
82
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
83
-    }
84
-
85
-
86
-    /**
87
-     *    _define_page_props
88
-     *
89
-     * @return void
90
-     */
91
-    protected function _define_page_props()
92
-    {
93
-        $this->_admin_page_title = $this->page_label;
94
-        $this->_labels = array(
95
-            'buttons' => array(
96
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
97
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
98
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
99
-            ),
100
-        );
101
-    }
102
-
103
-
104
-    /**
105
-     *        grab url requests and route them
106
-     *
107
-     * @access private
108
-     * @return void
109
-     * @throws EE_Error
110
-     * @throws InvalidArgumentException
111
-     * @throws InvalidDataTypeException
112
-     * @throws InvalidInterfaceException
113
-     */
114
-    public function _set_page_routes()
115
-    {
116
-
117
-        $this->_set_transaction_status_array();
118
-
119
-        $txn_id = ! empty($this->_req_data['TXN_ID'])
120
-                  && ! is_array($this->_req_data['TXN_ID'])
121
-            ? $this->_req_data['TXN_ID']
122
-            : 0;
123
-
124
-        $this->_page_routes = array(
125
-
126
-            'default' => array(
127
-                'func'       => '_transactions_overview_list_table',
128
-                'capability' => 'ee_read_transactions',
129
-            ),
130
-
131
-            'view_transaction' => array(
132
-                'func'       => '_transaction_details',
133
-                'capability' => 'ee_read_transaction',
134
-                'obj_id'     => $txn_id,
135
-            ),
136
-
137
-            'send_payment_reminder' => array(
138
-                'func'       => '_send_payment_reminder',
139
-                'noheader'   => true,
140
-                'capability' => 'ee_send_message',
141
-            ),
142
-
143
-            'espresso_apply_payment' => array(
144
-                'func'       => 'apply_payments_or_refunds',
145
-                'noheader'   => true,
146
-                'capability' => 'ee_edit_payments',
147
-            ),
148
-
149
-            'espresso_apply_refund' => array(
150
-                'func'       => 'apply_payments_or_refunds',
151
-                'noheader'   => true,
152
-                'capability' => 'ee_edit_payments',
153
-            ),
154
-
155
-            'espresso_delete_payment' => array(
156
-                'func'       => 'delete_payment',
157
-                'noheader'   => true,
158
-                'capability' => 'ee_delete_payments',
159
-            ),
160
-
161
-        );
162
-    }
163
-
164
-
165
-    protected function _set_page_config()
166
-    {
167
-        $this->_page_config = array(
168
-            'default'          => array(
169
-                'nav'           => array(
170
-                    'label' => esc_html__('Overview', 'event_espresso'),
171
-                    'order' => 10,
172
-                ),
173
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
174
-                'help_tabs'     => array(
175
-                    'transactions_overview_help_tab'                       => array(
176
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
177
-                        'filename' => 'transactions_overview',
178
-                    ),
179
-                    'transactions_overview_table_column_headings_help_tab' => array(
180
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
181
-                        'filename' => 'transactions_overview_table_column_headings',
182
-                    ),
183
-                    'transactions_overview_views_filters_help_tab'         => array(
184
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
185
-                        'filename' => 'transactions_overview_views_filters_search',
186
-                    ),
187
-                ),
188
-                'help_tour'     => array('Transactions_Overview_Help_Tour'),
189
-                /**
190
-                 * commented out because currently we are not displaying tips for transaction list table status but this
191
-                 * may change in a later iteration so want to keep the code for then.
192
-                 */
193
-                // 'qtips' => array( 'Transactions_List_Table_Tips' ),
194
-                'require_nonce' => false,
195
-            ),
196
-            'view_transaction' => array(
197
-                'nav'       => array(
198
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
199
-                    'order'      => 5,
200
-                    'url'        => isset($this->_req_data['TXN_ID'])
201
-                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
202
-                        : $this->_admin_base_url,
203
-                    'persistent' => false,
204
-                ),
205
-                'help_tabs' => array(
206
-                    'transactions_view_transaction_help_tab'                                              => array(
207
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
208
-                        'filename' => 'transactions_view_transaction',
209
-                    ),
210
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
211
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
212
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
213
-                    ),
214
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
215
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
216
-                        'filename' => 'transactions_view_transaction_attendees_registered',
217
-                    ),
218
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
219
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
220
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
221
-                    ),
222
-                ),
223
-                'qtips'     => array('Transaction_Details_Tips'),
224
-                'help_tour' => array('Transaction_Details_Help_Tour'),
225
-                'metaboxes' => array('_transaction_details_metaboxes'),
226
-
227
-                'require_nonce' => false,
228
-            ),
229
-        );
230
-    }
231
-
232
-
233
-    /**
234
-     * The below methods aren't used by this class currently
235
-     */
236
-    protected function _add_screen_options()
237
-    {
238
-        // noop
239
-    }
240
-
241
-    protected function _add_feature_pointers()
242
-    {
243
-        // noop
244
-    }
245
-
246
-    public function admin_init()
247
-    {
248
-        // IF a registration was JUST added via the admin...
249
-        if (isset(
250
-            $this->_req_data['redirect_from'],
251
-            $this->_req_data['EVT_ID'],
252
-            $this->_req_data['event_name']
253
-        )) {
254
-            // then set a cookie so that we can block any attempts to use
255
-            // the back button as a way to enter another registration.
256
-            setcookie(
257
-                'ee_registration_added',
258
-                $this->_req_data['EVT_ID'],
259
-                time() + WEEK_IN_SECONDS,
260
-                '/'
261
-            );
262
-            // and update the global
263
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
264
-        }
265
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
266
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267
-            'event_espresso'
268
-        );
269
-        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
270
-            'An error occurred! Please refresh the page and try again.',
271
-            'event_espresso'
272
-        );
273
-        EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
274
-        EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
275
-        EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
276
-        EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
277
-            'This transaction has been overpaid ! Payments Total',
278
-            'event_espresso'
279
-        );
280
-    }
281
-
282
-    public function admin_notices()
283
-    {
284
-        // noop
285
-    }
286
-
287
-    public function admin_footer_scripts()
288
-    {
289
-        // noop
290
-    }
291
-
292
-
293
-    /**
294
-     * _set_transaction_status_array
295
-     * sets list of transaction statuses
296
-     *
297
-     * @access private
298
-     * @return void
299
-     * @throws EE_Error
300
-     * @throws InvalidArgumentException
301
-     * @throws InvalidDataTypeException
302
-     * @throws InvalidInterfaceException
303
-     */
304
-    private function _set_transaction_status_array()
305
-    {
306
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
307
-    }
308
-
309
-
310
-    /**
311
-     * get_transaction_status_array
312
-     * return the transaction status array for wp_list_table
313
-     *
314
-     * @access public
315
-     * @return array
316
-     */
317
-    public function get_transaction_status_array()
318
-    {
319
-        return self::$_txn_status;
320
-    }
321
-
322
-
323
-    /**
324
-     *    get list of payment statuses
325
-     *
326
-     * @access private
327
-     * @return void
328
-     * @throws EE_Error
329
-     * @throws InvalidArgumentException
330
-     * @throws InvalidDataTypeException
331
-     * @throws InvalidInterfaceException
332
-     */
333
-    private function _get_payment_status_array()
334
-    {
335
-        self::$_pay_status = EEM_Payment::instance()->status_array(true);
336
-        $this->_template_args['payment_status'] = self::$_pay_status;
337
-    }
338
-
339
-
340
-    /**
341
-     *    _add_screen_options_default
342
-     *
343
-     * @access protected
344
-     * @return void
345
-     * @throws InvalidArgumentException
346
-     * @throws InvalidDataTypeException
347
-     * @throws InvalidInterfaceException
348
-     */
349
-    protected function _add_screen_options_default()
350
-    {
351
-        $this->_per_page_screen_option();
352
-    }
353
-
354
-
355
-    /**
356
-     * load_scripts_styles
357
-     *
358
-     * @access public
359
-     * @return void
360
-     */
361
-    public function load_scripts_styles()
362
-    {
363
-        // enqueue style
364
-        wp_register_style(
365
-            'espresso_txn',
366
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
367
-            array(),
368
-            EVENT_ESPRESSO_VERSION
369
-        );
370
-        wp_enqueue_style('espresso_txn');
371
-        // scripts
372
-        wp_register_script(
373
-            'espresso_txn',
374
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
375
-            array(
376
-                'ee_admin_js',
377
-                'ee-datepicker',
378
-                'jquery-ui-datepicker',
379
-                'jquery-ui-draggable',
380
-                'ee-dialog',
381
-                'ee-accounting',
382
-                'ee-serialize-full-array',
383
-            ),
384
-            EVENT_ESPRESSO_VERSION,
385
-            true
386
-        );
387
-        wp_enqueue_script('espresso_txn');
388
-    }
389
-
390
-
391
-    /**
392
-     *    load_scripts_styles_view_transaction
393
-     *
394
-     * @access public
395
-     * @return void
396
-     */
397
-    public function load_scripts_styles_view_transaction()
398
-    {
399
-        // styles
400
-        wp_enqueue_style('espresso-ui-theme');
401
-    }
402
-
403
-
404
-    /**
405
-     *    load_scripts_styles_default
406
-     *
407
-     * @access public
408
-     * @return void
409
-     */
410
-    public function load_scripts_styles_default()
411
-    {
412
-        // styles
413
-        wp_enqueue_style('espresso-ui-theme');
414
-    }
415
-
416
-
417
-    /**
418
-     *    _set_list_table_views_default
419
-     *
420
-     * @access protected
421
-     * @return void
422
-     */
423
-    protected function _set_list_table_views_default()
424
-    {
425
-        $this->_views = array(
426
-            'all'       => array(
427
-                'slug'  => 'all',
428
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
429
-                'count' => 0,
430
-            ),
431
-            'abandoned' => array(
432
-                'slug'  => 'abandoned',
433
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
434
-                'count' => 0,
435
-            ),
436
-            'incomplete' => array(
437
-                'slug'  => 'incomplete',
438
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
439
-                'count' => 0,
440
-            )
441
-        );
442
-        if (/**
443
-             * Filters whether a link to the "Failed Transactions" list table
444
-             * appears on the Transactions Admin Page list table.
445
-             * List display can be turned back on via the following:
446
-             * add_filter(
447
-             *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
448
-             *     '__return_true'
449
-             * );
450
-             *
451
-             * @since 4.9.70.p
452
-             * @param boolean                 $display_failed_txns_list
453
-             * @param Transactions_Admin_Page $this
454
-             */
455
-            apply_filters(
456
-                'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
457
-                false,
458
-                $this
459
-            )
460
-        ) {
461
-            $this->_views['failed'] = array(
462
-                'slug'  => 'failed',
463
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
464
-                'count' => 0,
465
-            );
466
-        }
467
-    }
468
-
469
-
470
-    /**
471
-     * _set_transaction_object
472
-     * This sets the _transaction property for the transaction details screen
473
-     *
474
-     * @access private
475
-     * @return void
476
-     * @throws EE_Error
477
-     * @throws InvalidArgumentException
478
-     * @throws RuntimeException
479
-     * @throws InvalidDataTypeException
480
-     * @throws InvalidInterfaceException
481
-     * @throws ReflectionException
482
-     */
483
-    private function _set_transaction_object()
484
-    {
485
-        if ($this->_transaction instanceof EE_Transaction) {
486
-            return;
487
-        } //get out we've already set the object
488
-
489
-        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
490
-            ? absint($this->_req_data['TXN_ID'])
491
-            : false;
492
-
493
-        // get transaction object
494
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
495
-        $this->_session = $this->_transaction instanceof EE_Transaction
496
-            ? $this->_transaction->get('TXN_session_data')
497
-            : null;
498
-        if ($this->_transaction instanceof EE_Transaction) {
499
-            $this->_transaction->verify_abandoned_transaction_status();
500
-        }
501
-
502
-        if (! $this->_transaction instanceof EE_Transaction) {
503
-            $error_msg = sprintf(
504
-                esc_html__(
505
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
506
-                    'event_espresso'
507
-                ),
508
-                $TXN_ID
509
-            );
510
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
511
-        }
512
-    }
513
-
514
-
515
-    /**
516
-     *    _transaction_legend_items
517
-     *
518
-     * @access protected
519
-     * @return array
520
-     * @throws EE_Error
521
-     * @throws InvalidArgumentException
522
-     * @throws ReflectionException
523
-     * @throws InvalidDataTypeException
524
-     * @throws InvalidInterfaceException
525
-     */
526
-    protected function _transaction_legend_items()
527
-    {
528
-        EE_Registry::instance()->load_helper('MSG_Template');
529
-        $items = array();
530
-
531
-        if (EE_Registry::instance()->CAP->current_user_can(
532
-            'ee_read_global_messages',
533
-            'view_filtered_messages'
534
-        )) {
535
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
536
-            if (is_array($related_for_icon)
537
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
538
-            ) {
539
-                $items['view_related_messages'] = array(
540
-                    'class' => $related_for_icon['css_class'],
541
-                    'desc'  => $related_for_icon['label'],
542
-                );
543
-            }
544
-        }
545
-
546
-        $items = apply_filters(
547
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
548
-            array_merge(
549
-                $items,
550
-                array(
551
-                    'view_details'          => array(
552
-                        'class' => 'dashicons dashicons-cart',
553
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
554
-                    ),
555
-                    'view_invoice'          => array(
556
-                        'class' => 'dashicons dashicons-media-spreadsheet',
557
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
558
-                    ),
559
-                    'view_receipt'          => array(
560
-                        'class' => 'dashicons dashicons-media-default',
561
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
562
-                    ),
563
-                    'view_registration'     => array(
564
-                        'class' => 'dashicons dashicons-clipboard',
565
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
566
-                    ),
567
-                    'payment_overview_link' => array(
568
-                        'class' => 'dashicons dashicons-money',
569
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
570
-                    ),
571
-                )
572
-            )
573
-        );
574
-
575
-        if (EE_Registry::instance()->CAP->current_user_can(
576
-            'ee_send_message',
577
-            'espresso_transactions_send_payment_reminder'
578
-        )) {
579
-            if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
580
-                $items['send_payment_reminder'] = array(
581
-                    'class' => 'dashicons dashicons-email-alt',
582
-                    'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
583
-                );
584
-            } else {
585
-                $items['blank*'] = array(
586
-                    'class' => '',
587
-                    'desc'  => '',
588
-                );
589
-            }
590
-        } else {
591
-            $items['blank*'] = array(
592
-                'class' => '',
593
-                'desc'  => '',
594
-            );
595
-        }
596
-        $more_items = apply_filters(
597
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
598
-            array(
599
-                'overpaid'   => array(
600
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
601
-                    'desc'  => EEH_Template::pretty_status(
602
-                        EEM_Transaction::overpaid_status_code,
603
-                        false,
604
-                        'sentence'
605
-                    ),
606
-                ),
607
-                'complete'   => array(
608
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
609
-                    'desc'  => EEH_Template::pretty_status(
610
-                        EEM_Transaction::complete_status_code,
611
-                        false,
612
-                        'sentence'
613
-                    ),
614
-                ),
615
-                'incomplete' => array(
616
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
617
-                    'desc'  => EEH_Template::pretty_status(
618
-                        EEM_Transaction::incomplete_status_code,
619
-                        false,
620
-                        'sentence'
621
-                    ),
622
-                ),
623
-                'abandoned'  => array(
624
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
625
-                    'desc'  => EEH_Template::pretty_status(
626
-                        EEM_Transaction::abandoned_status_code,
627
-                        false,
628
-                        'sentence'
629
-                    ),
630
-                ),
631
-                'failed'     => array(
632
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
633
-                    'desc'  => EEH_Template::pretty_status(
634
-                        EEM_Transaction::failed_status_code,
635
-                        false,
636
-                        'sentence'
637
-                    ),
638
-                ),
639
-            )
640
-        );
641
-
642
-        return array_merge($items, $more_items);
643
-    }
644
-
645
-
646
-    /**
647
-     *    _transactions_overview_list_table
648
-     *
649
-     * @access protected
650
-     * @return void
651
-     * @throws DomainException
652
-     * @throws EE_Error
653
-     * @throws InvalidArgumentException
654
-     * @throws InvalidDataTypeException
655
-     * @throws InvalidInterfaceException
656
-     * @throws ReflectionException
657
-     */
658
-    protected function _transactions_overview_list_table()
659
-    {
660
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
661
-        $event = isset($this->_req_data['EVT_ID'])
662
-            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
663
-            : null;
664
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
665
-            ? sprintf(
666
-                esc_html__(
667
-                    '%sViewing Transactions for the Event: %s%s',
668
-                    'event_espresso'
669
-                ),
670
-                '<h3>',
671
-                '<a href="'
672
-                . EE_Admin_Page::add_query_args_and_nonce(
673
-                    array('action' => 'edit', 'post' => $event->ID()),
674
-                    EVENTS_ADMIN_URL
675
-                )
676
-                . '" title="'
677
-                . esc_attr__(
678
-                    'Click to Edit event',
679
-                    'event_espresso'
680
-                )
681
-                . '">' . $event->get('EVT_name') . '</a>',
682
-                '</h3>'
683
-            )
684
-            : '';
685
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
686
-        $this->display_admin_list_table_page_with_no_sidebar();
687
-    }
688
-
689
-
690
-    /**
691
-     *    _transaction_details
692
-     * generates HTML for the View Transaction Details Admin page
693
-     *
694
-     * @access protected
695
-     * @return void
696
-     * @throws DomainException
697
-     * @throws EE_Error
698
-     * @throws InvalidArgumentException
699
-     * @throws InvalidDataTypeException
700
-     * @throws InvalidInterfaceException
701
-     * @throws RuntimeException
702
-     * @throws ReflectionException
703
-     */
704
-    protected function _transaction_details()
705
-    {
706
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
707
-
708
-        $this->_set_transaction_status_array();
709
-
710
-        $this->_template_args = array();
711
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
712
-
713
-        $this->_set_transaction_object();
714
-
715
-        if (! $this->_transaction instanceof EE_Transaction) {
716
-            return;
717
-        }
718
-        $primary_registration = $this->_transaction->primary_registration();
719
-        $attendee = $primary_registration instanceof EE_Registration
720
-            ? $primary_registration->attendee()
721
-            : null;
722
-
723
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
724
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
725
-
726
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
727
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
728
-
729
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->get('STS_ID') ];
730
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
731
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
732
-
733
-        $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
734
-        $this->_template_args['total_paid'] = $this->_transaction->get('TXN_paid');
735
-
736
-        $amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
737
-        $this->_template_args['amount_due'] = EEH_Template::format_currency(
738
-            $amount_due,
739
-            true
740
-        );
741
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
742
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
743
-                                                  . $this->_template_args['amount_due'];
744
-        } else {
745
-            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
746
-        }
747
-        $this->_template_args['amount_due_class'] = '';
748
-
749
-        if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
750
-            // paid in full
751
-            $this->_template_args['amount_due'] = false;
752
-        } elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
753
-            // overpaid
754
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
755
-        } elseif ($this->_transaction->get('TXN_total') > 0
756
-                  && $this->_transaction->get('TXN_paid') > 0
757
-        ) {
758
-            // monies owing
759
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
760
-        } elseif ($this->_transaction->get('TXN_total') > 0
761
-                  && $this->_transaction->get('TXN_paid') == 0
762
-        ) {
763
-            // no payments made yet
764
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
765
-        } elseif ($this->_transaction->get('TXN_total') == 0) {
766
-            // free event
767
-            $this->_template_args['amount_due'] = false;
768
-        }
769
-
770
-        $payment_method = $this->_transaction->payment_method();
771
-
772
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
773
-            ? $payment_method->admin_name()
774
-            : esc_html__('Unknown', 'event_espresso');
775
-
776
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
777
-        // link back to overview
778
-        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
779
-            ? $_SERVER['HTTP_REFERER']
780
-            : TXN_ADMIN_URL;
781
-
782
-
783
-        // next link
784
-        $next_txn = $this->_transaction->next(
785
-            null,
786
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
787
-            'TXN_ID'
788
-        );
789
-        $this->_template_args['next_transaction'] = $next_txn
790
-            ? $this->_next_link(
791
-                EE_Admin_Page::add_query_args_and_nonce(
792
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
793
-                    TXN_ADMIN_URL
794
-                ),
795
-                'dashicons dashicons-arrow-right ee-icon-size-22'
796
-            )
797
-            : '';
798
-        // previous link
799
-        $previous_txn = $this->_transaction->previous(
800
-            null,
801
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
802
-            'TXN_ID'
803
-        );
804
-        $this->_template_args['previous_transaction'] = $previous_txn
805
-            ? $this->_previous_link(
806
-                EE_Admin_Page::add_query_args_and_nonce(
807
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
808
-                    TXN_ADMIN_URL
809
-                ),
810
-                'dashicons dashicons-arrow-left ee-icon-size-22'
811
-            )
812
-            : '';
813
-
814
-        // were we just redirected here after adding a new registration ???
815
-        if (isset(
816
-            $this->_req_data['redirect_from'],
817
-            $this->_req_data['EVT_ID'],
818
-            $this->_req_data['event_name']
819
-        )) {
820
-            if (EE_Registry::instance()->CAP->current_user_can(
821
-                'ee_edit_registrations',
822
-                'espresso_registrations_new_registration',
823
-                $this->_req_data['EVT_ID']
824
-            )) {
825
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
826
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
827
-                    array(
828
-                        'page'     => 'espresso_registrations',
829
-                        'action'   => 'new_registration',
830
-                        'return'   => 'default',
831
-                        'TXN_ID'   => $this->_transaction->ID(),
832
-                        'event_id' => $this->_req_data['EVT_ID'],
833
-                    ),
834
-                    REG_ADMIN_URL
835
-                );
836
-                $this->_admin_page_title .= '">';
837
-
838
-                $this->_admin_page_title .= sprintf(
839
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
840
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
841
-                );
842
-                $this->_admin_page_title .= '</a>';
843
-            }
844
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
845
-        }
846
-        // grab messages at the last second
847
-        $this->_template_args['notices'] = EE_Error::get_notices();
848
-        // path to template
849
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
850
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
851
-            $template_path,
852
-            $this->_template_args,
853
-            true
854
-        );
855
-
856
-        // the details template wrapper
857
-        $this->display_admin_page_with_sidebar();
858
-    }
859
-
860
-
861
-    /**
862
-     *        _transaction_details_metaboxes
863
-     *
864
-     * @access protected
865
-     * @return void
866
-     * @throws EE_Error
867
-     * @throws InvalidArgumentException
868
-     * @throws InvalidDataTypeException
869
-     * @throws InvalidInterfaceException
870
-     * @throws RuntimeException
871
-     * @throws ReflectionException
872
-     */
873
-    protected function _transaction_details_metaboxes()
874
-    {
875
-
876
-        $this->_set_transaction_object();
877
-
878
-        if (! $this->_transaction instanceof EE_Transaction) {
879
-            return;
880
-        }
881
-        add_meta_box(
882
-            'edit-txn-details-mbox',
883
-            esc_html__('Transaction Details', 'event_espresso'),
884
-            array($this, 'txn_details_meta_box'),
885
-            $this->_wp_page_slug,
886
-            'normal',
887
-            'high'
888
-        );
889
-        add_meta_box(
890
-            'edit-txn-attendees-mbox',
891
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
892
-            array($this, 'txn_attendees_meta_box'),
893
-            $this->_wp_page_slug,
894
-            'normal',
895
-            'high',
896
-            array('TXN_ID' => $this->_transaction->ID())
897
-        );
898
-        add_meta_box(
899
-            'edit-txn-registrant-mbox',
900
-            esc_html__('Primary Contact', 'event_espresso'),
901
-            array($this, 'txn_registrant_side_meta_box'),
902
-            $this->_wp_page_slug,
903
-            'side',
904
-            'high'
905
-        );
906
-        add_meta_box(
907
-            'edit-txn-billing-info-mbox',
908
-            esc_html__('Billing Information', 'event_espresso'),
909
-            array($this, 'txn_billing_info_side_meta_box'),
910
-            $this->_wp_page_slug,
911
-            'side',
912
-            'high'
913
-        );
914
-    }
915
-
916
-
917
-    /**
918
-     * Callback for transaction actions metabox.
919
-     *
920
-     * @param EE_Transaction|null $transaction
921
-     * @throws DomainException
922
-     * @throws EE_Error
923
-     * @throws InvalidArgumentException
924
-     * @throws InvalidDataTypeException
925
-     * @throws InvalidInterfaceException
926
-     * @throws ReflectionException
927
-     * @throws RuntimeException
928
-     */
929
-    public function getActionButtons(EE_Transaction $transaction = null)
930
-    {
931
-        $content = '';
932
-        $actions = array();
933
-        if (! $transaction instanceof EE_Transaction) {
934
-            return $content;
935
-        }
936
-        /** @var EE_Registration $primary_registration */
937
-        $primary_registration = $transaction->primary_registration();
938
-        $attendee = $primary_registration instanceof EE_Registration
939
-            ? $primary_registration->attendee()
940
-            : null;
941
-
942
-        if ($attendee instanceof EE_Attendee
943
-            && EE_Registry::instance()->CAP->current_user_can(
944
-                'ee_send_message',
945
-                'espresso_transactions_send_payment_reminder'
946
-            )
947
-        ) {
948
-            $actions['payment_reminder'] =
949
-                EEH_MSG_Template::is_mt_active('payment_reminder')
950
-                && $this->_transaction->get('STS_ID') !== EEM_Transaction::complete_status_code
951
-                && $this->_transaction->get('STS_ID') !== EEM_Transaction::overpaid_status_code
952
-                    ? EEH_Template::get_button_or_link(
953
-                        EE_Admin_Page::add_query_args_and_nonce(
954
-                            array(
955
-                                'action'      => 'send_payment_reminder',
956
-                                'TXN_ID'      => $this->_transaction->ID(),
957
-                                'redirect_to' => 'view_transaction',
958
-                            ),
959
-                            TXN_ADMIN_URL
960
-                        ),
961
-                        esc_html__(' Send Payment Reminder', 'event_espresso'),
962
-                        'button secondary-button',
963
-                        'dashicons dashicons-email-alt'
964
-                    )
965
-                    : '';
966
-        }
967
-
968
-        if ($primary_registration instanceof EE_Registration
969
-            && EEH_MSG_Template::is_mt_active('receipt')
970
-        ) {
971
-            $actions['receipt'] = EEH_Template::get_button_or_link(
972
-                $primary_registration->receipt_url(),
973
-                esc_html__('View Receipt', 'event_espresso'),
974
-                'button secondary-button',
975
-                'dashicons dashicons-media-default'
976
-            );
977
-        }
978
-
979
-        if ($primary_registration instanceof EE_Registration
980
-            && EEH_MSG_Template::is_mt_active('invoice')
981
-        ) {
982
-            $actions['invoice'] = EEH_Template::get_button_or_link(
983
-                $primary_registration->invoice_url(),
984
-                esc_html__('View Invoice', 'event_espresso'),
985
-                'button secondary-button',
986
-                'dashicons dashicons-media-spreadsheet'
987
-            );
988
-        }
989
-        $actions = array_filter(
990
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
991
-        );
992
-        if ($actions) {
993
-            $content = '<ul>';
994
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
995
-            $content .= '</uL>';
996
-        }
997
-        return $content;
998
-    }
999
-
1000
-
1001
-    /**
1002
-     * txn_details_meta_box
1003
-     * generates HTML for the Transaction main meta box
1004
-     *
1005
-     * @return void
1006
-     * @throws DomainException
1007
-     * @throws EE_Error
1008
-     * @throws InvalidArgumentException
1009
-     * @throws InvalidDataTypeException
1010
-     * @throws InvalidInterfaceException
1011
-     * @throws RuntimeException
1012
-     * @throws ReflectionException
1013
-     */
1014
-    public function txn_details_meta_box()
1015
-    {
1016
-        $this->_set_transaction_object();
1017
-        $this->_template_args['TXN_ID'] = $this->_transaction->ID();
1018
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1019
-            ? $this->_transaction->primary_registration()->attendee()
1020
-            : null;
1021
-        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1022
-            'ee_edit_payments',
1023
-            'apply_payment_or_refund_from_registration_details'
1024
-        );
1025
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1026
-            'ee_delete_payments',
1027
-            'delete_payment_from_registration_details'
1028
-        );
1029
-
1030
-        // get line table
1031
-        EEH_Autoloader::register_line_item_display_autoloaders();
1032
-        $Line_Item_Display = new EE_Line_Item_Display(
1033
-            'admin_table',
1034
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1035
-        );
1036
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1037
-            $this->_transaction->total_line_item()
1038
-        );
1039
-        $this->_template_args['REG_code'] = $this->_transaction->get_first_related('Registration')
1040
-                                                               ->get('REG_code');
1041
-
1042
-        // process taxes
1043
-        $taxes = $this->_transaction->get_many_related(
1044
-            'Line_Item',
1045
-            array(array('LIN_type' => EEM_Line_Item::type_tax))
1046
-        );
1047
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1048
-
1049
-        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1050
-            $this->_transaction->get('TXN_total'),
1051
-            false,
1052
-            false
1053
-        );
1054
-        $this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
1055
-        $this->_template_args['TXN_status'] = $this->_transaction->get('STS_ID');
1056
-
1057
-        // process payment details
1058
-        $payments = $this->_transaction->get_many_related('Payment');
1059
-        if (! empty($payments)) {
1060
-            $this->_template_args['payments'] = $payments;
1061
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1062
-        } else {
1063
-            $this->_template_args['payments'] = false;
1064
-            $this->_template_args['existing_reg_payments'] = array();
1065
-        }
1066
-
1067
-        $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1068
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1069
-            array('action' => 'espresso_delete_payment'),
1070
-            TXN_ADMIN_URL
1071
-        );
1072
-
1073
-        if (isset($txn_details['invoice_number'])) {
1074
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1075
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1076
-                'Invoice Number',
1077
-                'event_espresso'
1078
-            );
1079
-        }
1080
-
1081
-        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1082
-            ->get_first_related('Registration')
1083
-            ->get('REG_session');
1084
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1085
-            'Registration Session',
1086
-            'event_espresso'
1087
-        );
1088
-
1089
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1090
-            ? $this->_session['ip_address']
1091
-            : '';
1092
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1093
-            'Transaction placed from IP',
1094
-            'event_espresso'
1095
-        );
1096
-
1097
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1098
-            ? $this->_session['user_agent']
1099
-            : '';
1100
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1101
-            'Registrant User Agent',
1102
-            'event_espresso'
1103
-        );
1104
-
1105
-        $reg_steps = '<ul>';
1106
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1107
-            if ($reg_step_status === true) {
1108
-                $reg_steps .= '<li style="color:#70cc50">'
1109
-                              . sprintf(
1110
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1111
-                                  ucwords(str_replace('_', ' ', $reg_step))
1112
-                              )
1113
-                              . '</li>';
1114
-            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1115
-                $reg_steps .= '<li style="color:#2EA2CC">'
1116
-                              . sprintf(
1117
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1118
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1119
-                                  date(
1120
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1121
-                                      ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1122
-                                  )
1123
-                              )
1124
-                              . '</li>';
1125
-            } else {
1126
-                $reg_steps .= '<li style="color:#E76700">'
1127
-                              . sprintf(
1128
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1129
-                                  ucwords(str_replace('_', ' ', $reg_step))
1130
-                              )
1131
-                              . '</li>';
1132
-            }
1133
-        }
1134
-        $reg_steps .= '</ul>';
1135
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1136
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1137
-            'Registration Step Progress',
1138
-            'event_espresso'
1139
-        );
1140
-
1141
-
1142
-        $this->_get_registrations_to_apply_payment_to();
1143
-        $this->_get_payment_methods($payments);
1144
-        $this->_get_payment_status_array();
1145
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1146
-
1147
-        $this->_template_args['transaction_form_url'] = add_query_arg(
1148
-            array(
1149
-                'action'  => 'edit_transaction',
1150
-                'process' => 'transaction',
1151
-            ),
1152
-            TXN_ADMIN_URL
1153
-        );
1154
-        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1155
-            array(
1156
-                'page'   => 'espresso_transactions',
1157
-                'action' => 'espresso_apply_payment',
1158
-            ),
1159
-            WP_AJAX_URL
1160
-        );
1161
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1162
-            array(
1163
-                'page'   => 'espresso_transactions',
1164
-                'action' => 'espresso_delete_payment',
1165
-            ),
1166
-            WP_AJAX_URL
1167
-        );
1168
-
1169
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1170
-
1171
-        // 'espresso_delete_payment_nonce'
1172
-
1173
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1174
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * _get_registration_payment_IDs
1180
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1181
-     *
1182
-     * @access protected
1183
-     * @param EE_Payment[] $payments
1184
-     * @return array
1185
-     * @throws EE_Error
1186
-     * @throws InvalidArgumentException
1187
-     * @throws InvalidDataTypeException
1188
-     * @throws InvalidInterfaceException
1189
-     * @throws ReflectionException
1190
-     */
1191
-    protected function _get_registration_payment_IDs($payments = array())
1192
-    {
1193
-        $existing_reg_payments = array();
1194
-        // get all reg payments for these payments
1195
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1196
-            array(
1197
-                array(
1198
-                    'PAY_ID' => array(
1199
-                        'IN',
1200
-                        array_keys($payments),
1201
-                    ),
1202
-                ),
1203
-            )
1204
-        );
1205
-        if (! empty($reg_payments)) {
1206
-            foreach ($payments as $payment) {
1207
-                if (! $payment instanceof EE_Payment) {
1208
-                    continue;
1209
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1210
-                    $existing_reg_payments[ $payment->ID() ] = array();
1211
-                }
1212
-                foreach ($reg_payments as $reg_payment) {
1213
-                    if ($reg_payment instanceof EE_Registration_Payment
1214
-                        && $reg_payment->payment_ID() === $payment->ID()
1215
-                    ) {
1216
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1217
-                    }
1218
-                }
1219
-            }
1220
-        }
1221
-
1222
-        return $existing_reg_payments;
1223
-    }
1224
-
1225
-
1226
-    /**
1227
-     * _get_registrations_to_apply_payment_to
1228
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1229
-     * which allows the admin to only apply the payment to the specific registrations
1230
-     *
1231
-     * @access protected
1232
-     * @return void
1233
-     * @throws \EE_Error
1234
-     */
1235
-    protected function _get_registrations_to_apply_payment_to()
1236
-    {
1237
-        // we want any registration with an active status (ie: not deleted or cancelled)
1238
-        $query_params = array(
1239
-            array(
1240
-                'STS_ID' => array(
1241
-                    'IN',
1242
-                    array(
1243
-                        EEM_Registration::status_id_approved,
1244
-                        EEM_Registration::status_id_pending_payment,
1245
-                        EEM_Registration::status_id_not_approved,
1246
-                    ),
1247
-                ),
1248
-            ),
1249
-        );
1250
-        $registrations_to_apply_payment_to = EEH_HTML::br()
1251
-                                             . EEH_HTML::div(
1252
-                                                 '',
1253
-                                                 'txn-admin-apply-payment-to-registrations-dv',
1254
-                                                 '',
1255
-                                                 'clear: both; margin: 1.5em 0 0; display: none;'
1256
-                                             );
1257
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1258
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1259
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1260
-            EEH_HTML::tr(
1261
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1262
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1263
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1264
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1265
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1266
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1267
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1268
-            )
1269
-        );
1270
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1271
-        // get registrations for TXN
1272
-        $registrations = $this->_transaction->registrations($query_params);
1273
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1274
-        foreach ($registrations as $registration) {
1275
-            if ($registration instanceof EE_Registration) {
1276
-                $attendee_name = $registration->attendee() instanceof EE_Attendee
1277
-                    ? $registration->attendee()->full_name()
1278
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1279
-                $owing = $registration->final_price() - $registration->paid();
1280
-                $taxable = $registration->ticket()->taxable()
1281
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1282
-                    : '';
1283
-                $checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1284
-                    ? ' checked="checked"'
1285
-                    : '';
1286
-                $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1287
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1288
-                    EEH_HTML::td($registration->ID()) .
1289
-                    EEH_HTML::td($attendee_name) .
1290
-                    EEH_HTML::td(
1291
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1292
-                    ) .
1293
-                    EEH_HTML::td($registration->event_name()) .
1294
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1295
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1296
-                    EEH_HTML::td(
1297
-                        '<input type="checkbox" value="' . $registration->ID()
1298
-                        . '" name="txn_admin_payment[registrations]"'
1299
-                        . $checked . $disabled . '>',
1300
-                        '',
1301
-                        'jst-cntr'
1302
-                    ),
1303
-                    'apply-payment-registration-row-' . $registration->ID()
1304
-                );
1305
-            }
1306
-        }
1307
-        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1308
-        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1309
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1310
-        $registrations_to_apply_payment_to .= EEH_HTML::p(
1311
-            esc_html__(
1312
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1313
-                'event_espresso'
1314
-            ),
1315
-            '',
1316
-            'clear description'
1317
-        );
1318
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1319
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * _get_reg_status_selection
1325
-     *
1326
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1327
-     *         instead of events.
1328
-     * @access protected
1329
-     * @return void
1330
-     * @throws EE_Error
1331
-     */
1332
-    protected function _get_reg_status_selection()
1333
-    {
1334
-        // first get all possible statuses
1335
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1336
-        // let's add a "don't change" option.
1337
-        $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1338
-        $status_array = array_merge($status_array, $statuses);
1339
-        $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1340
-            'txn_reg_status_change[reg_status]',
1341
-            $status_array,
1342
-            'NAN',
1343
-            'id="txn-admin-payment-reg-status-inp"',
1344
-            'txn-reg-status-change-reg-status'
1345
-        );
1346
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1347
-            'delete_txn_reg_status_change[reg_status]',
1348
-            $status_array,
1349
-            'NAN',
1350
-            'delete-txn-admin-payment-reg-status-inp',
1351
-            'delete-txn-reg-status-change-reg-status'
1352
-        );
1353
-    }
1354
-
1355
-
1356
-    /**
1357
-     *    _get_payment_methods
1358
-     * Gets all the payment methods available generally, or the ones that are already
1359
-     * selected on these payments (in case their payment methods are no longer active).
1360
-     * Has the side-effect of updating the template args' payment_methods item
1361
-     *
1362
-     * @access private
1363
-     * @param EE_Payment[] to show on this page
1364
-     * @return void
1365
-     * @throws EE_Error
1366
-     * @throws InvalidArgumentException
1367
-     * @throws InvalidDataTypeException
1368
-     * @throws InvalidInterfaceException
1369
-     * @throws ReflectionException
1370
-     */
1371
-    private function _get_payment_methods($payments = array())
1372
-    {
1373
-        $payment_methods_of_payments = array();
1374
-        foreach ($payments as $payment) {
1375
-            if ($payment instanceof EE_Payment) {
1376
-                $payment_methods_of_payments[] = $payment->get('PMD_ID');
1377
-            }
1378
-        }
1379
-        if ($payment_methods_of_payments) {
1380
-            $query_args = array(
1381
-                array(
1382
-                    'OR*payment_method_for_payment' => array(
1383
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1384
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1385
-                    ),
1386
-                ),
1387
-            );
1388
-        } else {
1389
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1390
-        }
1391
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1392
-    }
1393
-
1394
-
1395
-    /**
1396
-     * txn_attendees_meta_box
1397
-     *    generates HTML for the Attendees Transaction main meta box
1398
-     *
1399
-     * @access public
1400
-     * @param WP_Post $post
1401
-     * @param array   $metabox
1402
-     * @return void
1403
-     * @throws DomainException
1404
-     * @throws EE_Error
1405
-     */
1406
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1407
-    {
1408
-
1409
-        /** @noinspection NonSecureExtractUsageInspection */
1410
-        extract($metabox['args']);
1411
-        $this->_template_args['post'] = $post;
1412
-        $this->_template_args['event_attendees'] = array();
1413
-        // process items in cart
1414
-        $line_items = $this->_transaction->get_many_related(
1415
-            'Line_Item',
1416
-            array(array('LIN_type' => 'line-item'))
1417
-        );
1418
-        if (! empty($line_items)) {
1419
-            foreach ($line_items as $item) {
1420
-                if ($item instanceof EE_Line_Item) {
1421
-                    switch ($item->OBJ_type()) {
1422
-                        case 'Event':
1423
-                            break;
1424
-                        case 'Ticket':
1425
-                            $ticket = $item->ticket();
1426
-                            // right now we're only handling tickets here.
1427
-                            // Cause its expected that only tickets will have attendees right?
1428
-                            if (! $ticket instanceof EE_Ticket) {
1429
-                                break;
1430
-                            }
1431
-                            try {
1432
-                                $event_name = $ticket->get_event_name();
1433
-                            } catch (Exception $e) {
1434
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1435
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1436
-                            }
1437
-                            $event_name .= ' - ' . $item->get('LIN_name');
1438
-                            $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1439
-                            // now get all of the registrations for this transaction that use this ticket
1440
-                            $registrations = $ticket->get_many_related(
1441
-                                'Registration',
1442
-                                array(array('TXN_ID' => $this->_transaction->ID()))
1443
-                            );
1444
-                            foreach ($registrations as $registration) {
1445
-                                if (! $registration instanceof EE_Registration) {
1446
-                                    break;
1447
-                                }
1448
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1449
-                                    = $registration->status_ID();
1450
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1451
-                                    = $registration->count();
1452
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1453
-                                    = $event_name;
1454
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1455
-                                    = $ticket_price;
1456
-                                // attendee info
1457
-                                $attendee = $registration->get_first_related('Attendee');
1458
-                                if ($attendee instanceof EE_Attendee) {
1459
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1460
-                                        = $attendee->ID();
1461
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1462
-                                        = $attendee->full_name();
1463
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1464
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1465
-                                          . esc_html__(
1466
-                                              ' Event',
1467
-                                              'event_espresso'
1468
-                                          )
1469
-                                          . '">' . $attendee->email() . '</a>';
1470
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1471
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1472
-                                } else {
1473
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1474
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1475
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1476
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1477
-                                }
1478
-                            }
1479
-                            break;
1480
-                    }
1481
-                }
1482
-            }
1483
-
1484
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1485
-                array(
1486
-                    'action'  => 'edit_transaction',
1487
-                    'process' => 'attendees',
1488
-                ),
1489
-                TXN_ADMIN_URL
1490
-            );
1491
-            echo EEH_Template::display_template(
1492
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1493
-                $this->_template_args,
1494
-                true
1495
-            );
1496
-        } else {
1497
-            echo sprintf(
1498
-                esc_html__(
1499
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1500
-                    'event_espresso'
1501
-                ),
1502
-                '<p class="important-notice">',
1503
-                '</p>'
1504
-            );
1505
-        }
1506
-    }
1507
-
1508
-
1509
-    /**
1510
-     * txn_registrant_side_meta_box
1511
-     * generates HTML for the Edit Transaction side meta box
1512
-     *
1513
-     * @access public
1514
-     * @return void
1515
-     * @throws DomainException
1516
-     * @throws EE_Error
1517
-     * @throws InvalidArgumentException
1518
-     * @throws InvalidDataTypeException
1519
-     * @throws InvalidInterfaceException
1520
-     * @throws ReflectionException
1521
-     */
1522
-    public function txn_registrant_side_meta_box()
1523
-    {
1524
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1525
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1526
-            : null;
1527
-        if (! $primary_att instanceof EE_Attendee) {
1528
-            $this->_template_args['no_attendee_message'] = esc_html__(
1529
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1530
-                'event_espresso'
1531
-            );
1532
-            $primary_att = EEM_Attendee::instance()->create_default_object();
1533
-        }
1534
-        $this->_template_args['ATT_ID'] = $primary_att->ID();
1535
-        $this->_template_args['prime_reg_fname'] = $primary_att->fname();
1536
-        $this->_template_args['prime_reg_lname'] = $primary_att->lname();
1537
-        $this->_template_args['prime_reg_email'] = $primary_att->email();
1538
-        $this->_template_args['prime_reg_phone'] = $primary_att->phone();
1539
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1540
-            array(
1541
-                'action' => 'edit_attendee',
1542
-                'post'   => $primary_att->ID(),
1543
-            ),
1544
-            REG_ADMIN_URL
1545
-        );
1546
-        // get formatted address for registrant
1547
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1548
-        echo EEH_Template::display_template(
1549
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1550
-            $this->_template_args,
1551
-            true
1552
-        );
1553
-    }
1554
-
1555
-
1556
-    /**
1557
-     * txn_billing_info_side_meta_box
1558
-     *    generates HTML for the Edit Transaction side meta box
1559
-     *
1560
-     * @access public
1561
-     * @return void
1562
-     * @throws DomainException
1563
-     * @throws EE_Error
1564
-     */
1565
-    public function txn_billing_info_side_meta_box()
1566
-    {
1567
-
1568
-        $this->_template_args['billing_form'] = $this->_transaction->billing_info();
1569
-        $this->_template_args['billing_form_url'] = add_query_arg(
1570
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1571
-            TXN_ADMIN_URL
1572
-        );
1573
-
1574
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1575
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1576
-    }
1577
-
1578
-
1579
-    /**
1580
-     * apply_payments_or_refunds
1581
-     *    registers a payment or refund made towards a transaction
1582
-     *
1583
-     * @access public
1584
-     * @return void
1585
-     * @throws EE_Error
1586
-     * @throws InvalidArgumentException
1587
-     * @throws ReflectionException
1588
-     * @throws RuntimeException
1589
-     * @throws InvalidDataTypeException
1590
-     * @throws InvalidInterfaceException
1591
-     */
1592
-    public function apply_payments_or_refunds()
1593
-    {
1594
-        $json_response_data = array('return_data' => false);
1595
-        $valid_data = $this->_validate_payment_request_data();
1596
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1597
-            'ee_edit_payments',
1598
-            'apply_payment_or_refund_from_registration_details'
1599
-        );
1600
-        if (! empty($valid_data) && $has_access) {
1601
-            $PAY_ID = $valid_data['PAY_ID'];
1602
-            // save  the new payment
1603
-            $payment = $this->_create_payment_from_request_data($valid_data);
1604
-            // get the TXN for this payment
1605
-            $transaction = $payment->transaction();
1606
-            // verify transaction
1607
-            if ($transaction instanceof EE_Transaction) {
1608
-                // calculate_total_payments_and_update_status
1609
-                $this->_process_transaction_payments($transaction);
1610
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1611
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1612
-                // apply payment to registrations (if applicable)
1613
-                if (! empty($REG_IDs)) {
1614
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1615
-                    $this->_maybe_send_notifications();
1616
-                    // now process status changes for the same registrations
1617
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1618
-                }
1619
-                $this->_maybe_send_notifications($payment);
1620
-                // prepare to render page
1621
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1622
-                do_action(
1623
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1624
-                    $transaction,
1625
-                    $payment
1626
-                );
1627
-            } else {
1628
-                EE_Error::add_error(
1629
-                    esc_html__(
1630
-                        'A valid Transaction for this payment could not be retrieved.',
1631
-                        'event_espresso'
1632
-                    ),
1633
-                    __FILE__,
1634
-                    __FUNCTION__,
1635
-                    __LINE__
1636
-                );
1637
-            }
1638
-        } else {
1639
-            if ($has_access) {
1640
-                EE_Error::add_error(
1641
-                    esc_html__(
1642
-                        'The payment form data could not be processed. Please try again.',
1643
-                        'event_espresso'
1644
-                    ),
1645
-                    __FILE__,
1646
-                    __FUNCTION__,
1647
-                    __LINE__
1648
-                );
1649
-            } else {
1650
-                EE_Error::add_error(
1651
-                    esc_html__(
1652
-                        'You do not have access to apply payments or refunds to a registration.',
1653
-                        'event_espresso'
1654
-                    ),
1655
-                    __FILE__,
1656
-                    __FUNCTION__,
1657
-                    __LINE__
1658
-                );
1659
-            }
1660
-        }
1661
-        $notices = EE_Error::get_notices(
1662
-            false,
1663
-            false,
1664
-            false
1665
-        );
1666
-        $this->_template_args = array(
1667
-            'data'    => $json_response_data,
1668
-            'error'   => $notices['errors'],
1669
-            'success' => $notices['success'],
1670
-        );
1671
-        $this->_return_json();
1672
-    }
1673
-
1674
-
1675
-    /**
1676
-     * _validate_payment_request_data
1677
-     *
1678
-     * @return array
1679
-     * @throws EE_Error
1680
-     */
1681
-    protected function _validate_payment_request_data()
1682
-    {
1683
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1684
-            return false;
1685
-        }
1686
-        $payment_form = $this->_generate_payment_form_section();
1687
-        try {
1688
-            if ($payment_form->was_submitted()) {
1689
-                $payment_form->receive_form_submission();
1690
-                if (! $payment_form->is_valid()) {
1691
-                    $submission_error_messages = array();
1692
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1693
-                        if ($validation_error instanceof EE_Validation_Error) {
1694
-                            $submission_error_messages[] = sprintf(
1695
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1696
-                                $validation_error->get_form_section()->html_label_text(),
1697
-                                $validation_error->getMessage()
1698
-                            );
1699
-                        }
1700
-                    }
1701
-                    EE_Error::add_error(
1702
-                        implode('<br />', $submission_error_messages),
1703
-                        __FILE__,
1704
-                        __FUNCTION__,
1705
-                        __LINE__
1706
-                    );
1707
-
1708
-                    return array();
1709
-                }
1710
-            }
1711
-        } catch (EE_Error $e) {
1712
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1713
-
1714
-            return array();
1715
-        }
1716
-
1717
-        return $payment_form->valid_data();
1718
-    }
1719
-
1720
-
1721
-    /**
1722
-     * _generate_payment_form_section
1723
-     *
1724
-     * @return EE_Form_Section_Proper
1725
-     * @throws EE_Error
1726
-     */
1727
-    protected function _generate_payment_form_section()
1728
-    {
1729
-        return new EE_Form_Section_Proper(
1730
-            array(
1731
-                'name'        => 'txn_admin_payment',
1732
-                'subsections' => array(
1733
-                    'PAY_ID'          => new EE_Text_Input(
1734
-                        array(
1735
-                            'default'               => 0,
1736
-                            'required'              => false,
1737
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1738
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1739
-                        )
1740
-                    ),
1741
-                    'TXN_ID'          => new EE_Text_Input(
1742
-                        array(
1743
-                            'default'               => 0,
1744
-                            'required'              => true,
1745
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1746
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1747
-                        )
1748
-                    ),
1749
-                    'type'            => new EE_Text_Input(
1750
-                        array(
1751
-                            'default'               => 1,
1752
-                            'required'              => true,
1753
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1754
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1755
-                        )
1756
-                    ),
1757
-                    'amount'          => new EE_Text_Input(
1758
-                        array(
1759
-                            'default'               => 0,
1760
-                            'required'              => true,
1761
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1762
-                            'validation_strategies' => array(new EE_Float_Normalization()),
1763
-                        )
1764
-                    ),
1765
-                    'status'          => new EE_Text_Input(
1766
-                        array(
1767
-                            'default'         => EEM_Payment::status_id_approved,
1768
-                            'required'        => true,
1769
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1770
-                        )
1771
-                    ),
1772
-                    'PMD_ID'          => new EE_Text_Input(
1773
-                        array(
1774
-                            'default'               => 2,
1775
-                            'required'              => true,
1776
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1777
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1778
-                        )
1779
-                    ),
1780
-                    'date'            => new EE_Text_Input(
1781
-                        array(
1782
-                            'default'         => time(),
1783
-                            'required'        => true,
1784
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1785
-                        )
1786
-                    ),
1787
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1788
-                        array(
1789
-                            'default'               => '',
1790
-                            'required'              => false,
1791
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1792
-                            'validation_strategies' => array(
1793
-                                new EE_Max_Length_Validation_Strategy(
1794
-                                    esc_html__('Input too long', 'event_espresso'),
1795
-                                    100
1796
-                                ),
1797
-                            ),
1798
-                        )
1799
-                    ),
1800
-                    'po_number'       => new EE_Text_Input(
1801
-                        array(
1802
-                            'default'               => '',
1803
-                            'required'              => false,
1804
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1805
-                            'validation_strategies' => array(
1806
-                                new EE_Max_Length_Validation_Strategy(
1807
-                                    esc_html__('Input too long', 'event_espresso'),
1808
-                                    100
1809
-                                ),
1810
-                            ),
1811
-                        )
1812
-                    ),
1813
-                    'accounting'      => new EE_Text_Input(
1814
-                        array(
1815
-                            'default'               => '',
1816
-                            'required'              => false,
1817
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1818
-                            'validation_strategies' => array(
1819
-                                new EE_Max_Length_Validation_Strategy(
1820
-                                    esc_html__('Input too long', 'event_espresso'),
1821
-                                    100
1822
-                                ),
1823
-                            ),
1824
-                        )
1825
-                    ),
1826
-                ),
1827
-            )
1828
-        );
1829
-    }
1830
-
1831
-
1832
-    /**
1833
-     * _create_payment_from_request_data
1834
-     *
1835
-     * @param array $valid_data
1836
-     * @return EE_Payment
1837
-     * @throws EE_Error
1838
-     */
1839
-    protected function _create_payment_from_request_data($valid_data)
1840
-    {
1841
-        $PAY_ID = $valid_data['PAY_ID'];
1842
-        // get payment amount
1843
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1844
-        // payments have a type value of 1 and refunds have a type value of -1
1845
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1846
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1847
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1848
-        $date = $valid_data['date']
1849
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1850
-            : date('Y-m-d g:i a', current_time('timestamp'));
1851
-        $payment = EE_Payment::new_instance(
1852
-            array(
1853
-                'TXN_ID'              => $valid_data['TXN_ID'],
1854
-                'STS_ID'              => $valid_data['status'],
1855
-                'PAY_timestamp'       => $date,
1856
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1857
-                'PMD_ID'              => $valid_data['PMD_ID'],
1858
-                'PAY_amount'          => $amount,
1859
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1860
-                'PAY_po_number'       => $valid_data['po_number'],
1861
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1862
-                'PAY_details'         => $valid_data,
1863
-                'PAY_ID'              => $PAY_ID,
1864
-            ),
1865
-            '',
1866
-            array('Y-m-d', 'g:i a')
1867
-        );
1868
-
1869
-        if (! $payment->save()) {
1870
-            EE_Error::add_error(
1871
-                sprintf(
1872
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1873
-                    $payment->ID()
1874
-                ),
1875
-                __FILE__,
1876
-                __FUNCTION__,
1877
-                __LINE__
1878
-            );
1879
-        }
1880
-
1881
-        return $payment;
1882
-    }
1883
-
1884
-
1885
-    /**
1886
-     * _process_transaction_payments
1887
-     *
1888
-     * @param \EE_Transaction $transaction
1889
-     * @return void
1890
-     * @throws EE_Error
1891
-     * @throws InvalidArgumentException
1892
-     * @throws ReflectionException
1893
-     * @throws InvalidDataTypeException
1894
-     * @throws InvalidInterfaceException
1895
-     */
1896
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1897
-    {
1898
-        /** @type EE_Transaction_Payments $transaction_payments */
1899
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1900
-        // update the transaction with this payment
1901
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1902
-            EE_Error::add_success(
1903
-                esc_html__(
1904
-                    'The payment has been processed successfully.',
1905
-                    'event_espresso'
1906
-                ),
1907
-                __FILE__,
1908
-                __FUNCTION__,
1909
-                __LINE__
1910
-            );
1911
-        } else {
1912
-            EE_Error::add_error(
1913
-                esc_html__(
1914
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1915
-                    'event_espresso'
1916
-                ),
1917
-                __FILE__,
1918
-                __FUNCTION__,
1919
-                __LINE__
1920
-            );
1921
-        }
1922
-    }
1923
-
1924
-
1925
-    /**
1926
-     * _get_REG_IDs_to_apply_payment_to
1927
-     * returns a list of registration IDs that the payment will apply to
1928
-     *
1929
-     * @param \EE_Payment $payment
1930
-     * @return array
1931
-     * @throws EE_Error
1932
-     */
1933
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1934
-    {
1935
-        $REG_IDs = array();
1936
-        // grab array of IDs for specific registrations to apply changes to
1937
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1938
-            $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1939
-        }
1940
-        // nothing specified ? then get all reg IDs
1941
-        if (empty($REG_IDs)) {
1942
-            $registrations = $payment->transaction()->registrations();
1943
-            $REG_IDs = ! empty($registrations)
1944
-                ? array_keys($registrations)
1945
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1946
-        }
1947
-
1948
-        // ensure that REG_IDs are integers and NOT strings
1949
-        return array_map('intval', $REG_IDs);
1950
-    }
1951
-
1952
-
1953
-    /**
1954
-     * @return array
1955
-     */
1956
-    public function existing_reg_payment_REG_IDs()
1957
-    {
1958
-        return $this->_existing_reg_payment_REG_IDs;
1959
-    }
1960
-
1961
-
1962
-    /**
1963
-     * @param array $existing_reg_payment_REG_IDs
1964
-     */
1965
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1966
-    {
1967
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1968
-    }
1969
-
1970
-
1971
-    /**
1972
-     * _get_existing_reg_payment_REG_IDs
1973
-     * returns a list of registration IDs that the payment is currently related to
1974
-     * as recorded in the database
1975
-     *
1976
-     * @param \EE_Payment $payment
1977
-     * @return array
1978
-     * @throws EE_Error
1979
-     */
1980
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1981
-    {
1982
-        if ($this->existing_reg_payment_REG_IDs() === null) {
1983
-            // let's get any existing reg payment records for this payment
1984
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1985
-            // but we only want the REG IDs, so grab the array keys
1986
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
1987
-                ? array_keys($existing_reg_payment_REG_IDs)
1988
-                : array();
1989
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1990
-        }
1991
-
1992
-        return $this->existing_reg_payment_REG_IDs();
1993
-    }
1994
-
1995
-
1996
-    /**
1997
-     * _remove_existing_registration_payments
1998
-     * this calculates the difference between existing relations
1999
-     * to the supplied payment and the new list registration IDs,
2000
-     * removes any related registrations that no longer apply,
2001
-     * and then updates the registration paid fields
2002
-     *
2003
-     * @param \EE_Payment $payment
2004
-     * @param int         $PAY_ID
2005
-     * @return bool;
2006
-     * @throws EE_Error
2007
-     * @throws InvalidArgumentException
2008
-     * @throws ReflectionException
2009
-     * @throws InvalidDataTypeException
2010
-     * @throws InvalidInterfaceException
2011
-     */
2012
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2013
-    {
2014
-        // newly created payments will have nothing recorded for $PAY_ID
2015
-        if ($PAY_ID == 0) {
2016
-            return false;
2017
-        }
2018
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2019
-        if (empty($existing_reg_payment_REG_IDs)) {
2020
-            return false;
2021
-        }
2022
-        /** @type EE_Transaction_Payments $transaction_payments */
2023
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2024
-
2025
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2026
-            $payment,
2027
-            array(
2028
-                array(
2029
-                    'PAY_ID' => $payment->ID(),
2030
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2031
-                ),
2032
-            )
2033
-        );
2034
-    }
2035
-
2036
-
2037
-    /**
2038
-     * _update_registration_payments
2039
-     * this applies the payments to the selected registrations
2040
-     * but only if they have not already been paid for
2041
-     *
2042
-     * @param  EE_Transaction $transaction
2043
-     * @param \EE_Payment     $payment
2044
-     * @param array           $REG_IDs
2045
-     * @return void
2046
-     * @throws EE_Error
2047
-     * @throws InvalidArgumentException
2048
-     * @throws ReflectionException
2049
-     * @throws RuntimeException
2050
-     * @throws InvalidDataTypeException
2051
-     * @throws InvalidInterfaceException
2052
-     */
2053
-    protected function _update_registration_payments(
2054
-        EE_Transaction $transaction,
2055
-        EE_Payment $payment,
2056
-        $REG_IDs = array()
2057
-    ) {
2058
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2059
-        // so let's do that using our set of REG_IDs from the form
2060
-        $registration_query_where_params = array(
2061
-            'REG_ID' => array('IN', $REG_IDs),
2062
-        );
2063
-        // but add in some conditions regarding payment,
2064
-        // so that we don't apply payments to registrations that are free or have already been paid for
2065
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2066
-        if (! $payment->is_a_refund()) {
2067
-            $registration_query_where_params['REG_final_price'] = array('!=', 0);
2068
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2069
-        }
2070
-        $registrations = $transaction->registrations(array($registration_query_where_params));
2071
-        if (! empty($registrations)) {
2072
-            /** @type EE_Payment_Processor $payment_processor */
2073
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2074
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2075
-        }
2076
-    }
2077
-
2078
-
2079
-    /**
2080
-     * _process_registration_status_change
2081
-     * This processes requested registration status changes for all the registrations
2082
-     * on a given transaction and (optionally) sends out notifications for the changes.
2083
-     *
2084
-     * @param  EE_Transaction $transaction
2085
-     * @param array           $REG_IDs
2086
-     * @return bool
2087
-     * @throws EE_Error
2088
-     * @throws InvalidArgumentException
2089
-     * @throws ReflectionException
2090
-     * @throws InvalidDataTypeException
2091
-     * @throws InvalidInterfaceException
2092
-     */
2093
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2094
-    {
2095
-        // first if there is no change in status then we get out.
2096
-        if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2097
-            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2098
-        ) {
2099
-            // no error message, no change requested, just nothing to do man.
2100
-            return false;
2101
-        }
2102
-        /** @type EE_Transaction_Processor $transaction_processor */
2103
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2104
-
2105
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2106
-        return $transaction_processor->manually_update_registration_statuses(
2107
-            $transaction,
2108
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2109
-            array(array('REG_ID' => array('IN', $REG_IDs)))
2110
-        );
2111
-    }
2112
-
2113
-
2114
-    /**
2115
-     * _build_payment_json_response
2116
-     *
2117
-     * @access public
2118
-     * @param \EE_Payment $payment
2119
-     * @param array       $REG_IDs
2120
-     * @param bool | null $delete_txn_reg_status_change
2121
-     * @return array
2122
-     * @throws EE_Error
2123
-     * @throws InvalidArgumentException
2124
-     * @throws InvalidDataTypeException
2125
-     * @throws InvalidInterfaceException
2126
-     * @throws ReflectionException
2127
-     */
2128
-    protected function _build_payment_json_response(
2129
-        EE_Payment $payment,
2130
-        $REG_IDs = array(),
2131
-        $delete_txn_reg_status_change = null
2132
-    ) {
2133
-        // was the payment deleted ?
2134
-        if (is_bool($delete_txn_reg_status_change)) {
2135
-            return array(
2136
-                'PAY_ID'                       => $payment->ID(),
2137
-                'amount'                       => $payment->amount(),
2138
-                'total_paid'                   => $payment->transaction()->paid(),
2139
-                'txn_status'                   => $payment->transaction()->status_ID(),
2140
-                'pay_status'                   => $payment->STS_ID(),
2141
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2142
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2143
-            );
2144
-        } else {
2145
-            $this->_get_payment_status_array();
2146
-
2147
-            return array(
2148
-                'amount'           => $payment->amount(),
2149
-                'total_paid'       => $payment->transaction()->paid(),
2150
-                'txn_status'       => $payment->transaction()->status_ID(),
2151
-                'pay_status'       => $payment->STS_ID(),
2152
-                'PAY_ID'           => $payment->ID(),
2153
-                'STS_ID'           => $payment->STS_ID(),
2154
-                'status'           => self::$_pay_status[ $payment->STS_ID() ],
2155
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2156
-                'method'           => strtoupper($payment->source()),
2157
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2158
-                'gateway'          => $payment->payment_method()
2159
-                    ? $payment->payment_method()->admin_name()
2160
-                    : esc_html__("Unknown", 'event_espresso'),
2161
-                'gateway_response' => $payment->gateway_response(),
2162
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2163
-                'po_number'        => $payment->po_number(),
2164
-                'extra_accntng'    => $payment->extra_accntng(),
2165
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2166
-            );
2167
-        }
2168
-    }
2169
-
2170
-
2171
-    /**
2172
-     * delete_payment
2173
-     *    delete a payment or refund made towards a transaction
2174
-     *
2175
-     * @access public
2176
-     * @return void
2177
-     * @throws EE_Error
2178
-     * @throws InvalidArgumentException
2179
-     * @throws ReflectionException
2180
-     * @throws InvalidDataTypeException
2181
-     * @throws InvalidInterfaceException
2182
-     */
2183
-    public function delete_payment()
2184
-    {
2185
-        $json_response_data = array('return_data' => false);
2186
-        $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2187
-            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2188
-            : 0;
2189
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2190
-            'ee_delete_payments',
2191
-            'delete_payment_from_registration_details'
2192
-        );
2193
-        if ($PAY_ID && $can_delete) {
2194
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2195
-                ? $this->_req_data['delete_txn_reg_status_change']
2196
-                : false;
2197
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2198
-            if ($payment instanceof EE_Payment) {
2199
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2200
-                /** @type EE_Transaction_Payments $transaction_payments */
2201
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2202
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2203
-                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2204
-                        $payment,
2205
-                        $REG_IDs,
2206
-                        $delete_txn_reg_status_change
2207
-                    );
2208
-                    if ($delete_txn_reg_status_change) {
2209
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2210
-                        // MAKE sure we also add the delete_txn_req_status_change to the
2211
-                        // $_REQUEST global because that's how messages will be looking for it.
2212
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2213
-                        $this->_maybe_send_notifications();
2214
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2215
-                    }
2216
-                }
2217
-            } else {
2218
-                EE_Error::add_error(
2219
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2220
-                    __FILE__,
2221
-                    __FUNCTION__,
2222
-                    __LINE__
2223
-                );
2224
-            }
2225
-        } else {
2226
-            if ($can_delete) {
2227
-                EE_Error::add_error(
2228
-                    esc_html__(
2229
-                        'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2230
-                        'event_espresso'
2231
-                    ),
2232
-                    __FILE__,
2233
-                    __FUNCTION__,
2234
-                    __LINE__
2235
-                );
2236
-            } else {
2237
-                EE_Error::add_error(
2238
-                    esc_html__(
2239
-                        'You do not have access to delete a payment.',
2240
-                        'event_espresso'
2241
-                    ),
2242
-                    __FILE__,
2243
-                    __FUNCTION__,
2244
-                    __LINE__
2245
-                );
2246
-            }
2247
-        }
2248
-        $notices = EE_Error::get_notices(false, false, false);
2249
-        $this->_template_args = array(
2250
-            'data'      => $json_response_data,
2251
-            'success'   => $notices['success'],
2252
-            'error'     => $notices['errors'],
2253
-            'attention' => $notices['attention'],
2254
-        );
2255
-        $this->_return_json();
2256
-    }
2257
-
2258
-
2259
-    /**
2260
-     * _registration_payment_data_array
2261
-     * adds info for 'owing' and 'paid' for each registration to the json response
2262
-     *
2263
-     * @access protected
2264
-     * @param array $REG_IDs
2265
-     * @return array
2266
-     * @throws EE_Error
2267
-     * @throws InvalidArgumentException
2268
-     * @throws InvalidDataTypeException
2269
-     * @throws InvalidInterfaceException
2270
-     * @throws ReflectionException
2271
-     */
2272
-    protected function _registration_payment_data_array($REG_IDs)
2273
-    {
2274
-        $registration_payment_data = array();
2275
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2276
-        if (! empty($REG_IDs)) {
2277
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2278
-            foreach ($registrations as $registration) {
2279
-                if ($registration instanceof EE_Registration) {
2280
-                    $registration_payment_data[ $registration->ID() ] = array(
2281
-                        'paid'  => $registration->pretty_paid(),
2282
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2283
-                    );
2284
-                }
2285
-            }
2286
-        }
2287
-
2288
-        return $registration_payment_data;
2289
-    }
2290
-
2291
-
2292
-    /**
2293
-     * _maybe_send_notifications
2294
-     * determines whether or not the admin has indicated that notifications should be sent.
2295
-     * If so, will toggle a filter switch for delivering registration notices.
2296
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2297
-     *
2298
-     * @access protected
2299
-     * @param \EE_Payment | null $payment
2300
-     */
2301
-    protected function _maybe_send_notifications($payment = null)
2302
-    {
2303
-        switch ($payment instanceof EE_Payment) {
2304
-            // payment notifications
2305
-            case true:
2306
-                if (isset(
2307
-                    $this->_req_data['txn_payments'],
2308
-                    $this->_req_data['txn_payments']['send_notifications']
2309
-                )
2310
-                    && filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2311
-                ) {
2312
-                    $this->_process_payment_notification($payment);
2313
-                }
2314
-                break;
2315
-            // registration notifications
2316
-            case false:
2317
-                if (isset(
2318
-                    $this->_req_data['txn_reg_status_change'],
2319
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
2320
-                )
2321
-                    && filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2322
-                ) {
2323
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2324
-                }
2325
-                break;
2326
-        }
2327
-    }
2328
-
2329
-
2330
-    /**
2331
-     * _send_payment_reminder
2332
-     *    generates HTML for the View Transaction Details Admin page
2333
-     *
2334
-     * @access protected
2335
-     * @return void
2336
-     * @throws EE_Error
2337
-     * @throws InvalidArgumentException
2338
-     * @throws InvalidDataTypeException
2339
-     * @throws InvalidInterfaceException
2340
-     */
2341
-    protected function _send_payment_reminder()
2342
-    {
2343
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2344
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2345
-        $query_args = isset($this->_req_data['redirect_to']) ? array(
2346
-            'action' => $this->_req_data['redirect_to'],
2347
-            'TXN_ID' => $this->_req_data['TXN_ID'],
2348
-        ) : array();
2349
-        do_action(
2350
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2351
-            $transaction
2352
-        );
2353
-        $this->_redirect_after_action(
2354
-            false,
2355
-            esc_html__('payment reminder', 'event_espresso'),
2356
-            esc_html__('sent', 'event_espresso'),
2357
-            $query_args,
2358
-            true
2359
-        );
2360
-    }
2361
-
2362
-
2363
-    /**
2364
-     *  get_transactions
2365
-     *    get transactions for given parameters (used by list table)
2366
-     *
2367
-     * @param  int     $perpage how many transactions displayed per page
2368
-     * @param  boolean $count   return the count or objects
2369
-     * @param string   $view
2370
-     * @return mixed int = count || array of transaction objects
2371
-     * @throws EE_Error
2372
-     * @throws InvalidArgumentException
2373
-     * @throws InvalidDataTypeException
2374
-     * @throws InvalidInterfaceException
2375
-     */
2376
-    public function get_transactions($perpage, $count = false, $view = '')
2377
-    {
2378
-
2379
-        $TXN = EEM_Transaction::instance();
2380
-
2381
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
2382
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2383
-            : date(
2384
-                'm/d/Y',
2385
-                strtotime('-10 year')
2386
-            );
2387
-        $end_date = isset($this->_req_data['txn-filter-end-date'])
2388
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2389
-            : date('m/d/Y');
2390
-
2391
-        // make sure our timestamps start and end right at the boundaries for each day
2392
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2393
-        $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2394
-
2395
-
2396
-        // convert to timestamps
2397
-        $start_date = strtotime($start_date);
2398
-        $end_date = strtotime($end_date);
2399
-
2400
-        // makes sure start date is the lowest value and vice versa
2401
-        $start_date = min($start_date, $end_date);
2402
-        $end_date = max($start_date, $end_date);
2403
-
2404
-        // convert to correct format for query
2405
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2406
-            'TXN_timestamp',
2407
-            date('Y-m-d H:i:s', $start_date),
2408
-            'Y-m-d H:i:s'
2409
-        );
2410
-        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2411
-            'TXN_timestamp',
2412
-            date('Y-m-d H:i:s', $end_date),
2413
-            'Y-m-d H:i:s'
2414
-        );
2415
-
2416
-
2417
-        // set orderby
2418
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2419
-
2420
-        switch ($this->_req_data['orderby']) {
2421
-            case 'TXN_ID':
2422
-                $orderby = 'TXN_ID';
2423
-                break;
2424
-            case 'ATT_fname':
2425
-                $orderby = 'Registration.Attendee.ATT_fname';
2426
-                break;
2427
-            case 'event_name':
2428
-                $orderby = 'Registration.Event.EVT_name';
2429
-                break;
2430
-            default: // 'TXN_timestamp'
2431
-                $orderby = 'TXN_timestamp';
2432
-        }
2433
-
2434
-        $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2435
-        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2436
-        $per_page = ! empty($perpage) ? $perpage : 10;
2437
-        $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2438
-
2439
-        $offset = ($current_page - 1) * $per_page;
2440
-        $limit = array($offset, $per_page);
2441
-
2442
-        $_where = array(
2443
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2444
-            'Registration.REG_count' => 1,
2445
-        );
2446
-
2447
-        if (isset($this->_req_data['EVT_ID'])) {
2448
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2449
-        }
2450
-
2451
-        if (isset($this->_req_data['s'])) {
2452
-            $search_string = '%' . $this->_req_data['s'] . '%';
2453
-            $_where['OR'] = array(
2454
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2455
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2456
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2457
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2458
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2459
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2460
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2461
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2462
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2463
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2464
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2465
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
2466
-                'Registration.REG_code'               => array('LIKE', $search_string),
2467
-                'Registration.REG_count'              => array('LIKE', $search_string),
2468
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
2469
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2470
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2471
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
2472
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2473
-                'TXN_session_data'                    => array('LIKE', $search_string),
2474
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2475
-            );
2476
-        }
2477
-
2478
-        // failed transactions
2479
-        $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2480
-                  || ($count && $view === 'failed');
2481
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2482
-                     || ($count && $view === 'abandoned');
2483
-        $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2484
-                      || ($count && $view === 'incomplete');
2485
-
2486
-        if ($failed) {
2487
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2488
-        } elseif ($abandoned) {
2489
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2490
-        } elseif ($incomplete) {
2491
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2492
-        } else {
2493
-            $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2494
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2495
-        }
2496
-
2497
-        $query_params = apply_filters(
2498
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2499
-            array(
2500
-                $_where,
2501
-                'order_by'                 => array($orderby => $sort),
2502
-                'limit'                    => $limit,
2503
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2504
-            ),
2505
-            $this->_req_data,
2506
-            $view,
2507
-            $count
2508
-        );
2509
-
2510
-        $transactions = $count
2511
-            ? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2512
-            : $TXN->get_all($query_params);
2513
-
2514
-        return $transactions;
2515
-    }
17
+	/**
18
+	 * @var EE_Transaction
19
+	 */
20
+	private $_transaction;
21
+
22
+	/**
23
+	 * @var EE_Session
24
+	 */
25
+	private $_session;
26
+
27
+	/**
28
+	 * @var array $_txn_status
29
+	 */
30
+	private static $_txn_status;
31
+
32
+	/**
33
+	 * @var array $_pay_status
34
+	 */
35
+	private static $_pay_status;
36
+
37
+	/**
38
+	 * @var array $_existing_reg_payment_REG_IDs
39
+	 */
40
+	protected $_existing_reg_payment_REG_IDs = null;
41
+
42
+
43
+	/**
44
+	 * @Constructor
45
+	 * @access public
46
+	 * @param bool $routing
47
+	 * @throws EE_Error
48
+	 * @throws InvalidArgumentException
49
+	 * @throws ReflectionException
50
+	 * @throws InvalidDataTypeException
51
+	 * @throws InvalidInterfaceException
52
+	 */
53
+	public function __construct($routing = true)
54
+	{
55
+		parent::__construct($routing);
56
+	}
57
+
58
+
59
+	/**
60
+	 *    _init_page_props
61
+	 *
62
+	 * @return void
63
+	 */
64
+	protected function _init_page_props()
65
+	{
66
+		$this->page_slug = TXN_PG_SLUG;
67
+		$this->page_label = esc_html__('Transactions', 'event_espresso');
68
+		$this->_admin_base_url = TXN_ADMIN_URL;
69
+		$this->_admin_base_path = TXN_ADMIN;
70
+	}
71
+
72
+
73
+	/**
74
+	 *    _ajax_hooks
75
+	 *
76
+	 * @return void
77
+	 */
78
+	protected function _ajax_hooks()
79
+	{
80
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
81
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
82
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
83
+	}
84
+
85
+
86
+	/**
87
+	 *    _define_page_props
88
+	 *
89
+	 * @return void
90
+	 */
91
+	protected function _define_page_props()
92
+	{
93
+		$this->_admin_page_title = $this->page_label;
94
+		$this->_labels = array(
95
+			'buttons' => array(
96
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
97
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
98
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
99
+			),
100
+		);
101
+	}
102
+
103
+
104
+	/**
105
+	 *        grab url requests and route them
106
+	 *
107
+	 * @access private
108
+	 * @return void
109
+	 * @throws EE_Error
110
+	 * @throws InvalidArgumentException
111
+	 * @throws InvalidDataTypeException
112
+	 * @throws InvalidInterfaceException
113
+	 */
114
+	public function _set_page_routes()
115
+	{
116
+
117
+		$this->_set_transaction_status_array();
118
+
119
+		$txn_id = ! empty($this->_req_data['TXN_ID'])
120
+				  && ! is_array($this->_req_data['TXN_ID'])
121
+			? $this->_req_data['TXN_ID']
122
+			: 0;
123
+
124
+		$this->_page_routes = array(
125
+
126
+			'default' => array(
127
+				'func'       => '_transactions_overview_list_table',
128
+				'capability' => 'ee_read_transactions',
129
+			),
130
+
131
+			'view_transaction' => array(
132
+				'func'       => '_transaction_details',
133
+				'capability' => 'ee_read_transaction',
134
+				'obj_id'     => $txn_id,
135
+			),
136
+
137
+			'send_payment_reminder' => array(
138
+				'func'       => '_send_payment_reminder',
139
+				'noheader'   => true,
140
+				'capability' => 'ee_send_message',
141
+			),
142
+
143
+			'espresso_apply_payment' => array(
144
+				'func'       => 'apply_payments_or_refunds',
145
+				'noheader'   => true,
146
+				'capability' => 'ee_edit_payments',
147
+			),
148
+
149
+			'espresso_apply_refund' => array(
150
+				'func'       => 'apply_payments_or_refunds',
151
+				'noheader'   => true,
152
+				'capability' => 'ee_edit_payments',
153
+			),
154
+
155
+			'espresso_delete_payment' => array(
156
+				'func'       => 'delete_payment',
157
+				'noheader'   => true,
158
+				'capability' => 'ee_delete_payments',
159
+			),
160
+
161
+		);
162
+	}
163
+
164
+
165
+	protected function _set_page_config()
166
+	{
167
+		$this->_page_config = array(
168
+			'default'          => array(
169
+				'nav'           => array(
170
+					'label' => esc_html__('Overview', 'event_espresso'),
171
+					'order' => 10,
172
+				),
173
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
174
+				'help_tabs'     => array(
175
+					'transactions_overview_help_tab'                       => array(
176
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
177
+						'filename' => 'transactions_overview',
178
+					),
179
+					'transactions_overview_table_column_headings_help_tab' => array(
180
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
181
+						'filename' => 'transactions_overview_table_column_headings',
182
+					),
183
+					'transactions_overview_views_filters_help_tab'         => array(
184
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
185
+						'filename' => 'transactions_overview_views_filters_search',
186
+					),
187
+				),
188
+				'help_tour'     => array('Transactions_Overview_Help_Tour'),
189
+				/**
190
+				 * commented out because currently we are not displaying tips for transaction list table status but this
191
+				 * may change in a later iteration so want to keep the code for then.
192
+				 */
193
+				// 'qtips' => array( 'Transactions_List_Table_Tips' ),
194
+				'require_nonce' => false,
195
+			),
196
+			'view_transaction' => array(
197
+				'nav'       => array(
198
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
199
+					'order'      => 5,
200
+					'url'        => isset($this->_req_data['TXN_ID'])
201
+						? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
202
+						: $this->_admin_base_url,
203
+					'persistent' => false,
204
+				),
205
+				'help_tabs' => array(
206
+					'transactions_view_transaction_help_tab'                                              => array(
207
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
208
+						'filename' => 'transactions_view_transaction',
209
+					),
210
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
211
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
212
+						'filename' => 'transactions_view_transaction_transaction_details_table',
213
+					),
214
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
215
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
216
+						'filename' => 'transactions_view_transaction_attendees_registered',
217
+					),
218
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
219
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
220
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
221
+					),
222
+				),
223
+				'qtips'     => array('Transaction_Details_Tips'),
224
+				'help_tour' => array('Transaction_Details_Help_Tour'),
225
+				'metaboxes' => array('_transaction_details_metaboxes'),
226
+
227
+				'require_nonce' => false,
228
+			),
229
+		);
230
+	}
231
+
232
+
233
+	/**
234
+	 * The below methods aren't used by this class currently
235
+	 */
236
+	protected function _add_screen_options()
237
+	{
238
+		// noop
239
+	}
240
+
241
+	protected function _add_feature_pointers()
242
+	{
243
+		// noop
244
+	}
245
+
246
+	public function admin_init()
247
+	{
248
+		// IF a registration was JUST added via the admin...
249
+		if (isset(
250
+			$this->_req_data['redirect_from'],
251
+			$this->_req_data['EVT_ID'],
252
+			$this->_req_data['event_name']
253
+		)) {
254
+			// then set a cookie so that we can block any attempts to use
255
+			// the back button as a way to enter another registration.
256
+			setcookie(
257
+				'ee_registration_added',
258
+				$this->_req_data['EVT_ID'],
259
+				time() + WEEK_IN_SECONDS,
260
+				'/'
261
+			);
262
+			// and update the global
263
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
264
+		}
265
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
266
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267
+			'event_espresso'
268
+		);
269
+		EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
270
+			'An error occurred! Please refresh the page and try again.',
271
+			'event_espresso'
272
+		);
273
+		EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
274
+		EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
275
+		EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
276
+		EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
277
+			'This transaction has been overpaid ! Payments Total',
278
+			'event_espresso'
279
+		);
280
+	}
281
+
282
+	public function admin_notices()
283
+	{
284
+		// noop
285
+	}
286
+
287
+	public function admin_footer_scripts()
288
+	{
289
+		// noop
290
+	}
291
+
292
+
293
+	/**
294
+	 * _set_transaction_status_array
295
+	 * sets list of transaction statuses
296
+	 *
297
+	 * @access private
298
+	 * @return void
299
+	 * @throws EE_Error
300
+	 * @throws InvalidArgumentException
301
+	 * @throws InvalidDataTypeException
302
+	 * @throws InvalidInterfaceException
303
+	 */
304
+	private function _set_transaction_status_array()
305
+	{
306
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
307
+	}
308
+
309
+
310
+	/**
311
+	 * get_transaction_status_array
312
+	 * return the transaction status array for wp_list_table
313
+	 *
314
+	 * @access public
315
+	 * @return array
316
+	 */
317
+	public function get_transaction_status_array()
318
+	{
319
+		return self::$_txn_status;
320
+	}
321
+
322
+
323
+	/**
324
+	 *    get list of payment statuses
325
+	 *
326
+	 * @access private
327
+	 * @return void
328
+	 * @throws EE_Error
329
+	 * @throws InvalidArgumentException
330
+	 * @throws InvalidDataTypeException
331
+	 * @throws InvalidInterfaceException
332
+	 */
333
+	private function _get_payment_status_array()
334
+	{
335
+		self::$_pay_status = EEM_Payment::instance()->status_array(true);
336
+		$this->_template_args['payment_status'] = self::$_pay_status;
337
+	}
338
+
339
+
340
+	/**
341
+	 *    _add_screen_options_default
342
+	 *
343
+	 * @access protected
344
+	 * @return void
345
+	 * @throws InvalidArgumentException
346
+	 * @throws InvalidDataTypeException
347
+	 * @throws InvalidInterfaceException
348
+	 */
349
+	protected function _add_screen_options_default()
350
+	{
351
+		$this->_per_page_screen_option();
352
+	}
353
+
354
+
355
+	/**
356
+	 * load_scripts_styles
357
+	 *
358
+	 * @access public
359
+	 * @return void
360
+	 */
361
+	public function load_scripts_styles()
362
+	{
363
+		// enqueue style
364
+		wp_register_style(
365
+			'espresso_txn',
366
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
367
+			array(),
368
+			EVENT_ESPRESSO_VERSION
369
+		);
370
+		wp_enqueue_style('espresso_txn');
371
+		// scripts
372
+		wp_register_script(
373
+			'espresso_txn',
374
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
375
+			array(
376
+				'ee_admin_js',
377
+				'ee-datepicker',
378
+				'jquery-ui-datepicker',
379
+				'jquery-ui-draggable',
380
+				'ee-dialog',
381
+				'ee-accounting',
382
+				'ee-serialize-full-array',
383
+			),
384
+			EVENT_ESPRESSO_VERSION,
385
+			true
386
+		);
387
+		wp_enqueue_script('espresso_txn');
388
+	}
389
+
390
+
391
+	/**
392
+	 *    load_scripts_styles_view_transaction
393
+	 *
394
+	 * @access public
395
+	 * @return void
396
+	 */
397
+	public function load_scripts_styles_view_transaction()
398
+	{
399
+		// styles
400
+		wp_enqueue_style('espresso-ui-theme');
401
+	}
402
+
403
+
404
+	/**
405
+	 *    load_scripts_styles_default
406
+	 *
407
+	 * @access public
408
+	 * @return void
409
+	 */
410
+	public function load_scripts_styles_default()
411
+	{
412
+		// styles
413
+		wp_enqueue_style('espresso-ui-theme');
414
+	}
415
+
416
+
417
+	/**
418
+	 *    _set_list_table_views_default
419
+	 *
420
+	 * @access protected
421
+	 * @return void
422
+	 */
423
+	protected function _set_list_table_views_default()
424
+	{
425
+		$this->_views = array(
426
+			'all'       => array(
427
+				'slug'  => 'all',
428
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
429
+				'count' => 0,
430
+			),
431
+			'abandoned' => array(
432
+				'slug'  => 'abandoned',
433
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
434
+				'count' => 0,
435
+			),
436
+			'incomplete' => array(
437
+				'slug'  => 'incomplete',
438
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
439
+				'count' => 0,
440
+			)
441
+		);
442
+		if (/**
443
+		 * Filters whether a link to the "Failed Transactions" list table
444
+		 * appears on the Transactions Admin Page list table.
445
+		 * List display can be turned back on via the following:
446
+		 * add_filter(
447
+		 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
448
+		 *     '__return_true'
449
+		 * );
450
+		 *
451
+		 * @since 4.9.70.p
452
+		 * @param boolean                 $display_failed_txns_list
453
+		 * @param Transactions_Admin_Page $this
454
+		 */
455
+			apply_filters(
456
+				'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
457
+				false,
458
+				$this
459
+			)
460
+		) {
461
+			$this->_views['failed'] = array(
462
+				'slug'  => 'failed',
463
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
464
+				'count' => 0,
465
+			);
466
+		}
467
+	}
468
+
469
+
470
+	/**
471
+	 * _set_transaction_object
472
+	 * This sets the _transaction property for the transaction details screen
473
+	 *
474
+	 * @access private
475
+	 * @return void
476
+	 * @throws EE_Error
477
+	 * @throws InvalidArgumentException
478
+	 * @throws RuntimeException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws InvalidInterfaceException
481
+	 * @throws ReflectionException
482
+	 */
483
+	private function _set_transaction_object()
484
+	{
485
+		if ($this->_transaction instanceof EE_Transaction) {
486
+			return;
487
+		} //get out we've already set the object
488
+
489
+		$TXN_ID = ! empty($this->_req_data['TXN_ID'])
490
+			? absint($this->_req_data['TXN_ID'])
491
+			: false;
492
+
493
+		// get transaction object
494
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
495
+		$this->_session = $this->_transaction instanceof EE_Transaction
496
+			? $this->_transaction->get('TXN_session_data')
497
+			: null;
498
+		if ($this->_transaction instanceof EE_Transaction) {
499
+			$this->_transaction->verify_abandoned_transaction_status();
500
+		}
501
+
502
+		if (! $this->_transaction instanceof EE_Transaction) {
503
+			$error_msg = sprintf(
504
+				esc_html__(
505
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
506
+					'event_espresso'
507
+				),
508
+				$TXN_ID
509
+			);
510
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
511
+		}
512
+	}
513
+
514
+
515
+	/**
516
+	 *    _transaction_legend_items
517
+	 *
518
+	 * @access protected
519
+	 * @return array
520
+	 * @throws EE_Error
521
+	 * @throws InvalidArgumentException
522
+	 * @throws ReflectionException
523
+	 * @throws InvalidDataTypeException
524
+	 * @throws InvalidInterfaceException
525
+	 */
526
+	protected function _transaction_legend_items()
527
+	{
528
+		EE_Registry::instance()->load_helper('MSG_Template');
529
+		$items = array();
530
+
531
+		if (EE_Registry::instance()->CAP->current_user_can(
532
+			'ee_read_global_messages',
533
+			'view_filtered_messages'
534
+		)) {
535
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
536
+			if (is_array($related_for_icon)
537
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
538
+			) {
539
+				$items['view_related_messages'] = array(
540
+					'class' => $related_for_icon['css_class'],
541
+					'desc'  => $related_for_icon['label'],
542
+				);
543
+			}
544
+		}
545
+
546
+		$items = apply_filters(
547
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
548
+			array_merge(
549
+				$items,
550
+				array(
551
+					'view_details'          => array(
552
+						'class' => 'dashicons dashicons-cart',
553
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
554
+					),
555
+					'view_invoice'          => array(
556
+						'class' => 'dashicons dashicons-media-spreadsheet',
557
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
558
+					),
559
+					'view_receipt'          => array(
560
+						'class' => 'dashicons dashicons-media-default',
561
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
562
+					),
563
+					'view_registration'     => array(
564
+						'class' => 'dashicons dashicons-clipboard',
565
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
566
+					),
567
+					'payment_overview_link' => array(
568
+						'class' => 'dashicons dashicons-money',
569
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
570
+					),
571
+				)
572
+			)
573
+		);
574
+
575
+		if (EE_Registry::instance()->CAP->current_user_can(
576
+			'ee_send_message',
577
+			'espresso_transactions_send_payment_reminder'
578
+		)) {
579
+			if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
580
+				$items['send_payment_reminder'] = array(
581
+					'class' => 'dashicons dashicons-email-alt',
582
+					'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
583
+				);
584
+			} else {
585
+				$items['blank*'] = array(
586
+					'class' => '',
587
+					'desc'  => '',
588
+				);
589
+			}
590
+		} else {
591
+			$items['blank*'] = array(
592
+				'class' => '',
593
+				'desc'  => '',
594
+			);
595
+		}
596
+		$more_items = apply_filters(
597
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
598
+			array(
599
+				'overpaid'   => array(
600
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
601
+					'desc'  => EEH_Template::pretty_status(
602
+						EEM_Transaction::overpaid_status_code,
603
+						false,
604
+						'sentence'
605
+					),
606
+				),
607
+				'complete'   => array(
608
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
609
+					'desc'  => EEH_Template::pretty_status(
610
+						EEM_Transaction::complete_status_code,
611
+						false,
612
+						'sentence'
613
+					),
614
+				),
615
+				'incomplete' => array(
616
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
617
+					'desc'  => EEH_Template::pretty_status(
618
+						EEM_Transaction::incomplete_status_code,
619
+						false,
620
+						'sentence'
621
+					),
622
+				),
623
+				'abandoned'  => array(
624
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
625
+					'desc'  => EEH_Template::pretty_status(
626
+						EEM_Transaction::abandoned_status_code,
627
+						false,
628
+						'sentence'
629
+					),
630
+				),
631
+				'failed'     => array(
632
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
633
+					'desc'  => EEH_Template::pretty_status(
634
+						EEM_Transaction::failed_status_code,
635
+						false,
636
+						'sentence'
637
+					),
638
+				),
639
+			)
640
+		);
641
+
642
+		return array_merge($items, $more_items);
643
+	}
644
+
645
+
646
+	/**
647
+	 *    _transactions_overview_list_table
648
+	 *
649
+	 * @access protected
650
+	 * @return void
651
+	 * @throws DomainException
652
+	 * @throws EE_Error
653
+	 * @throws InvalidArgumentException
654
+	 * @throws InvalidDataTypeException
655
+	 * @throws InvalidInterfaceException
656
+	 * @throws ReflectionException
657
+	 */
658
+	protected function _transactions_overview_list_table()
659
+	{
660
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
661
+		$event = isset($this->_req_data['EVT_ID'])
662
+			? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
663
+			: null;
664
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
665
+			? sprintf(
666
+				esc_html__(
667
+					'%sViewing Transactions for the Event: %s%s',
668
+					'event_espresso'
669
+				),
670
+				'<h3>',
671
+				'<a href="'
672
+				. EE_Admin_Page::add_query_args_and_nonce(
673
+					array('action' => 'edit', 'post' => $event->ID()),
674
+					EVENTS_ADMIN_URL
675
+				)
676
+				. '" title="'
677
+				. esc_attr__(
678
+					'Click to Edit event',
679
+					'event_espresso'
680
+				)
681
+				. '">' . $event->get('EVT_name') . '</a>',
682
+				'</h3>'
683
+			)
684
+			: '';
685
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
686
+		$this->display_admin_list_table_page_with_no_sidebar();
687
+	}
688
+
689
+
690
+	/**
691
+	 *    _transaction_details
692
+	 * generates HTML for the View Transaction Details Admin page
693
+	 *
694
+	 * @access protected
695
+	 * @return void
696
+	 * @throws DomainException
697
+	 * @throws EE_Error
698
+	 * @throws InvalidArgumentException
699
+	 * @throws InvalidDataTypeException
700
+	 * @throws InvalidInterfaceException
701
+	 * @throws RuntimeException
702
+	 * @throws ReflectionException
703
+	 */
704
+	protected function _transaction_details()
705
+	{
706
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
707
+
708
+		$this->_set_transaction_status_array();
709
+
710
+		$this->_template_args = array();
711
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
712
+
713
+		$this->_set_transaction_object();
714
+
715
+		if (! $this->_transaction instanceof EE_Transaction) {
716
+			return;
717
+		}
718
+		$primary_registration = $this->_transaction->primary_registration();
719
+		$attendee = $primary_registration instanceof EE_Registration
720
+			? $primary_registration->attendee()
721
+			: null;
722
+
723
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
724
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
725
+
726
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
727
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
728
+
729
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->get('STS_ID') ];
730
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
731
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
732
+
733
+		$this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
734
+		$this->_template_args['total_paid'] = $this->_transaction->get('TXN_paid');
735
+
736
+		$amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
737
+		$this->_template_args['amount_due'] = EEH_Template::format_currency(
738
+			$amount_due,
739
+			true
740
+		);
741
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
742
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
743
+												  . $this->_template_args['amount_due'];
744
+		} else {
745
+			$this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
746
+		}
747
+		$this->_template_args['amount_due_class'] = '';
748
+
749
+		if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
750
+			// paid in full
751
+			$this->_template_args['amount_due'] = false;
752
+		} elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
753
+			// overpaid
754
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
755
+		} elseif ($this->_transaction->get('TXN_total') > 0
756
+				  && $this->_transaction->get('TXN_paid') > 0
757
+		) {
758
+			// monies owing
759
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
760
+		} elseif ($this->_transaction->get('TXN_total') > 0
761
+				  && $this->_transaction->get('TXN_paid') == 0
762
+		) {
763
+			// no payments made yet
764
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
765
+		} elseif ($this->_transaction->get('TXN_total') == 0) {
766
+			// free event
767
+			$this->_template_args['amount_due'] = false;
768
+		}
769
+
770
+		$payment_method = $this->_transaction->payment_method();
771
+
772
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
773
+			? $payment_method->admin_name()
774
+			: esc_html__('Unknown', 'event_espresso');
775
+
776
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
777
+		// link back to overview
778
+		$this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
779
+			? $_SERVER['HTTP_REFERER']
780
+			: TXN_ADMIN_URL;
781
+
782
+
783
+		// next link
784
+		$next_txn = $this->_transaction->next(
785
+			null,
786
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
787
+			'TXN_ID'
788
+		);
789
+		$this->_template_args['next_transaction'] = $next_txn
790
+			? $this->_next_link(
791
+				EE_Admin_Page::add_query_args_and_nonce(
792
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
793
+					TXN_ADMIN_URL
794
+				),
795
+				'dashicons dashicons-arrow-right ee-icon-size-22'
796
+			)
797
+			: '';
798
+		// previous link
799
+		$previous_txn = $this->_transaction->previous(
800
+			null,
801
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
802
+			'TXN_ID'
803
+		);
804
+		$this->_template_args['previous_transaction'] = $previous_txn
805
+			? $this->_previous_link(
806
+				EE_Admin_Page::add_query_args_and_nonce(
807
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
808
+					TXN_ADMIN_URL
809
+				),
810
+				'dashicons dashicons-arrow-left ee-icon-size-22'
811
+			)
812
+			: '';
813
+
814
+		// were we just redirected here after adding a new registration ???
815
+		if (isset(
816
+			$this->_req_data['redirect_from'],
817
+			$this->_req_data['EVT_ID'],
818
+			$this->_req_data['event_name']
819
+		)) {
820
+			if (EE_Registry::instance()->CAP->current_user_can(
821
+				'ee_edit_registrations',
822
+				'espresso_registrations_new_registration',
823
+				$this->_req_data['EVT_ID']
824
+			)) {
825
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
826
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
827
+					array(
828
+						'page'     => 'espresso_registrations',
829
+						'action'   => 'new_registration',
830
+						'return'   => 'default',
831
+						'TXN_ID'   => $this->_transaction->ID(),
832
+						'event_id' => $this->_req_data['EVT_ID'],
833
+					),
834
+					REG_ADMIN_URL
835
+				);
836
+				$this->_admin_page_title .= '">';
837
+
838
+				$this->_admin_page_title .= sprintf(
839
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
840
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
841
+				);
842
+				$this->_admin_page_title .= '</a>';
843
+			}
844
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
845
+		}
846
+		// grab messages at the last second
847
+		$this->_template_args['notices'] = EE_Error::get_notices();
848
+		// path to template
849
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
850
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
851
+			$template_path,
852
+			$this->_template_args,
853
+			true
854
+		);
855
+
856
+		// the details template wrapper
857
+		$this->display_admin_page_with_sidebar();
858
+	}
859
+
860
+
861
+	/**
862
+	 *        _transaction_details_metaboxes
863
+	 *
864
+	 * @access protected
865
+	 * @return void
866
+	 * @throws EE_Error
867
+	 * @throws InvalidArgumentException
868
+	 * @throws InvalidDataTypeException
869
+	 * @throws InvalidInterfaceException
870
+	 * @throws RuntimeException
871
+	 * @throws ReflectionException
872
+	 */
873
+	protected function _transaction_details_metaboxes()
874
+	{
875
+
876
+		$this->_set_transaction_object();
877
+
878
+		if (! $this->_transaction instanceof EE_Transaction) {
879
+			return;
880
+		}
881
+		add_meta_box(
882
+			'edit-txn-details-mbox',
883
+			esc_html__('Transaction Details', 'event_espresso'),
884
+			array($this, 'txn_details_meta_box'),
885
+			$this->_wp_page_slug,
886
+			'normal',
887
+			'high'
888
+		);
889
+		add_meta_box(
890
+			'edit-txn-attendees-mbox',
891
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
892
+			array($this, 'txn_attendees_meta_box'),
893
+			$this->_wp_page_slug,
894
+			'normal',
895
+			'high',
896
+			array('TXN_ID' => $this->_transaction->ID())
897
+		);
898
+		add_meta_box(
899
+			'edit-txn-registrant-mbox',
900
+			esc_html__('Primary Contact', 'event_espresso'),
901
+			array($this, 'txn_registrant_side_meta_box'),
902
+			$this->_wp_page_slug,
903
+			'side',
904
+			'high'
905
+		);
906
+		add_meta_box(
907
+			'edit-txn-billing-info-mbox',
908
+			esc_html__('Billing Information', 'event_espresso'),
909
+			array($this, 'txn_billing_info_side_meta_box'),
910
+			$this->_wp_page_slug,
911
+			'side',
912
+			'high'
913
+		);
914
+	}
915
+
916
+
917
+	/**
918
+	 * Callback for transaction actions metabox.
919
+	 *
920
+	 * @param EE_Transaction|null $transaction
921
+	 * @throws DomainException
922
+	 * @throws EE_Error
923
+	 * @throws InvalidArgumentException
924
+	 * @throws InvalidDataTypeException
925
+	 * @throws InvalidInterfaceException
926
+	 * @throws ReflectionException
927
+	 * @throws RuntimeException
928
+	 */
929
+	public function getActionButtons(EE_Transaction $transaction = null)
930
+	{
931
+		$content = '';
932
+		$actions = array();
933
+		if (! $transaction instanceof EE_Transaction) {
934
+			return $content;
935
+		}
936
+		/** @var EE_Registration $primary_registration */
937
+		$primary_registration = $transaction->primary_registration();
938
+		$attendee = $primary_registration instanceof EE_Registration
939
+			? $primary_registration->attendee()
940
+			: null;
941
+
942
+		if ($attendee instanceof EE_Attendee
943
+			&& EE_Registry::instance()->CAP->current_user_can(
944
+				'ee_send_message',
945
+				'espresso_transactions_send_payment_reminder'
946
+			)
947
+		) {
948
+			$actions['payment_reminder'] =
949
+				EEH_MSG_Template::is_mt_active('payment_reminder')
950
+				&& $this->_transaction->get('STS_ID') !== EEM_Transaction::complete_status_code
951
+				&& $this->_transaction->get('STS_ID') !== EEM_Transaction::overpaid_status_code
952
+					? EEH_Template::get_button_or_link(
953
+						EE_Admin_Page::add_query_args_and_nonce(
954
+							array(
955
+								'action'      => 'send_payment_reminder',
956
+								'TXN_ID'      => $this->_transaction->ID(),
957
+								'redirect_to' => 'view_transaction',
958
+							),
959
+							TXN_ADMIN_URL
960
+						),
961
+						esc_html__(' Send Payment Reminder', 'event_espresso'),
962
+						'button secondary-button',
963
+						'dashicons dashicons-email-alt'
964
+					)
965
+					: '';
966
+		}
967
+
968
+		if ($primary_registration instanceof EE_Registration
969
+			&& EEH_MSG_Template::is_mt_active('receipt')
970
+		) {
971
+			$actions['receipt'] = EEH_Template::get_button_or_link(
972
+				$primary_registration->receipt_url(),
973
+				esc_html__('View Receipt', 'event_espresso'),
974
+				'button secondary-button',
975
+				'dashicons dashicons-media-default'
976
+			);
977
+		}
978
+
979
+		if ($primary_registration instanceof EE_Registration
980
+			&& EEH_MSG_Template::is_mt_active('invoice')
981
+		) {
982
+			$actions['invoice'] = EEH_Template::get_button_or_link(
983
+				$primary_registration->invoice_url(),
984
+				esc_html__('View Invoice', 'event_espresso'),
985
+				'button secondary-button',
986
+				'dashicons dashicons-media-spreadsheet'
987
+			);
988
+		}
989
+		$actions = array_filter(
990
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
991
+		);
992
+		if ($actions) {
993
+			$content = '<ul>';
994
+			$content .= '<li>' . implode('</li><li>', $actions) . '</li>';
995
+			$content .= '</uL>';
996
+		}
997
+		return $content;
998
+	}
999
+
1000
+
1001
+	/**
1002
+	 * txn_details_meta_box
1003
+	 * generates HTML for the Transaction main meta box
1004
+	 *
1005
+	 * @return void
1006
+	 * @throws DomainException
1007
+	 * @throws EE_Error
1008
+	 * @throws InvalidArgumentException
1009
+	 * @throws InvalidDataTypeException
1010
+	 * @throws InvalidInterfaceException
1011
+	 * @throws RuntimeException
1012
+	 * @throws ReflectionException
1013
+	 */
1014
+	public function txn_details_meta_box()
1015
+	{
1016
+		$this->_set_transaction_object();
1017
+		$this->_template_args['TXN_ID'] = $this->_transaction->ID();
1018
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1019
+			? $this->_transaction->primary_registration()->attendee()
1020
+			: null;
1021
+		$this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1022
+			'ee_edit_payments',
1023
+			'apply_payment_or_refund_from_registration_details'
1024
+		);
1025
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1026
+			'ee_delete_payments',
1027
+			'delete_payment_from_registration_details'
1028
+		);
1029
+
1030
+		// get line table
1031
+		EEH_Autoloader::register_line_item_display_autoloaders();
1032
+		$Line_Item_Display = new EE_Line_Item_Display(
1033
+			'admin_table',
1034
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1035
+		);
1036
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1037
+			$this->_transaction->total_line_item()
1038
+		);
1039
+		$this->_template_args['REG_code'] = $this->_transaction->get_first_related('Registration')
1040
+															   ->get('REG_code');
1041
+
1042
+		// process taxes
1043
+		$taxes = $this->_transaction->get_many_related(
1044
+			'Line_Item',
1045
+			array(array('LIN_type' => EEM_Line_Item::type_tax))
1046
+		);
1047
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1048
+
1049
+		$this->_template_args['grand_total'] = EEH_Template::format_currency(
1050
+			$this->_transaction->get('TXN_total'),
1051
+			false,
1052
+			false
1053
+		);
1054
+		$this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
1055
+		$this->_template_args['TXN_status'] = $this->_transaction->get('STS_ID');
1056
+
1057
+		// process payment details
1058
+		$payments = $this->_transaction->get_many_related('Payment');
1059
+		if (! empty($payments)) {
1060
+			$this->_template_args['payments'] = $payments;
1061
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1062
+		} else {
1063
+			$this->_template_args['payments'] = false;
1064
+			$this->_template_args['existing_reg_payments'] = array();
1065
+		}
1066
+
1067
+		$this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1068
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1069
+			array('action' => 'espresso_delete_payment'),
1070
+			TXN_ADMIN_URL
1071
+		);
1072
+
1073
+		if (isset($txn_details['invoice_number'])) {
1074
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1075
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1076
+				'Invoice Number',
1077
+				'event_espresso'
1078
+			);
1079
+		}
1080
+
1081
+		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
1082
+			->get_first_related('Registration')
1083
+			->get('REG_session');
1084
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1085
+			'Registration Session',
1086
+			'event_espresso'
1087
+		);
1088
+
1089
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1090
+			? $this->_session['ip_address']
1091
+			: '';
1092
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1093
+			'Transaction placed from IP',
1094
+			'event_espresso'
1095
+		);
1096
+
1097
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1098
+			? $this->_session['user_agent']
1099
+			: '';
1100
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1101
+			'Registrant User Agent',
1102
+			'event_espresso'
1103
+		);
1104
+
1105
+		$reg_steps = '<ul>';
1106
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1107
+			if ($reg_step_status === true) {
1108
+				$reg_steps .= '<li style="color:#70cc50">'
1109
+							  . sprintf(
1110
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1111
+								  ucwords(str_replace('_', ' ', $reg_step))
1112
+							  )
1113
+							  . '</li>';
1114
+			} elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1115
+				$reg_steps .= '<li style="color:#2EA2CC">'
1116
+							  . sprintf(
1117
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1118
+								  ucwords(str_replace('_', ' ', $reg_step)),
1119
+								  date(
1120
+									  get_option('date_format') . ' ' . get_option('time_format'),
1121
+									  ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1122
+								  )
1123
+							  )
1124
+							  . '</li>';
1125
+			} else {
1126
+				$reg_steps .= '<li style="color:#E76700">'
1127
+							  . sprintf(
1128
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1129
+								  ucwords(str_replace('_', ' ', $reg_step))
1130
+							  )
1131
+							  . '</li>';
1132
+			}
1133
+		}
1134
+		$reg_steps .= '</ul>';
1135
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1136
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1137
+			'Registration Step Progress',
1138
+			'event_espresso'
1139
+		);
1140
+
1141
+
1142
+		$this->_get_registrations_to_apply_payment_to();
1143
+		$this->_get_payment_methods($payments);
1144
+		$this->_get_payment_status_array();
1145
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1146
+
1147
+		$this->_template_args['transaction_form_url'] = add_query_arg(
1148
+			array(
1149
+				'action'  => 'edit_transaction',
1150
+				'process' => 'transaction',
1151
+			),
1152
+			TXN_ADMIN_URL
1153
+		);
1154
+		$this->_template_args['apply_payment_form_url'] = add_query_arg(
1155
+			array(
1156
+				'page'   => 'espresso_transactions',
1157
+				'action' => 'espresso_apply_payment',
1158
+			),
1159
+			WP_AJAX_URL
1160
+		);
1161
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1162
+			array(
1163
+				'page'   => 'espresso_transactions',
1164
+				'action' => 'espresso_delete_payment',
1165
+			),
1166
+			WP_AJAX_URL
1167
+		);
1168
+
1169
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1170
+
1171
+		// 'espresso_delete_payment_nonce'
1172
+
1173
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1174
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * _get_registration_payment_IDs
1180
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1181
+	 *
1182
+	 * @access protected
1183
+	 * @param EE_Payment[] $payments
1184
+	 * @return array
1185
+	 * @throws EE_Error
1186
+	 * @throws InvalidArgumentException
1187
+	 * @throws InvalidDataTypeException
1188
+	 * @throws InvalidInterfaceException
1189
+	 * @throws ReflectionException
1190
+	 */
1191
+	protected function _get_registration_payment_IDs($payments = array())
1192
+	{
1193
+		$existing_reg_payments = array();
1194
+		// get all reg payments for these payments
1195
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1196
+			array(
1197
+				array(
1198
+					'PAY_ID' => array(
1199
+						'IN',
1200
+						array_keys($payments),
1201
+					),
1202
+				),
1203
+			)
1204
+		);
1205
+		if (! empty($reg_payments)) {
1206
+			foreach ($payments as $payment) {
1207
+				if (! $payment instanceof EE_Payment) {
1208
+					continue;
1209
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1210
+					$existing_reg_payments[ $payment->ID() ] = array();
1211
+				}
1212
+				foreach ($reg_payments as $reg_payment) {
1213
+					if ($reg_payment instanceof EE_Registration_Payment
1214
+						&& $reg_payment->payment_ID() === $payment->ID()
1215
+					) {
1216
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1217
+					}
1218
+				}
1219
+			}
1220
+		}
1221
+
1222
+		return $existing_reg_payments;
1223
+	}
1224
+
1225
+
1226
+	/**
1227
+	 * _get_registrations_to_apply_payment_to
1228
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1229
+	 * which allows the admin to only apply the payment to the specific registrations
1230
+	 *
1231
+	 * @access protected
1232
+	 * @return void
1233
+	 * @throws \EE_Error
1234
+	 */
1235
+	protected function _get_registrations_to_apply_payment_to()
1236
+	{
1237
+		// we want any registration with an active status (ie: not deleted or cancelled)
1238
+		$query_params = array(
1239
+			array(
1240
+				'STS_ID' => array(
1241
+					'IN',
1242
+					array(
1243
+						EEM_Registration::status_id_approved,
1244
+						EEM_Registration::status_id_pending_payment,
1245
+						EEM_Registration::status_id_not_approved,
1246
+					),
1247
+				),
1248
+			),
1249
+		);
1250
+		$registrations_to_apply_payment_to = EEH_HTML::br()
1251
+											 . EEH_HTML::div(
1252
+												 '',
1253
+												 'txn-admin-apply-payment-to-registrations-dv',
1254
+												 '',
1255
+												 'clear: both; margin: 1.5em 0 0; display: none;'
1256
+											 );
1257
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1258
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1259
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1260
+			EEH_HTML::tr(
1261
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1262
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1263
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1264
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1265
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1266
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1267
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1268
+			)
1269
+		);
1270
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1271
+		// get registrations for TXN
1272
+		$registrations = $this->_transaction->registrations($query_params);
1273
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1274
+		foreach ($registrations as $registration) {
1275
+			if ($registration instanceof EE_Registration) {
1276
+				$attendee_name = $registration->attendee() instanceof EE_Attendee
1277
+					? $registration->attendee()->full_name()
1278
+					: esc_html__('Unknown Attendee', 'event_espresso');
1279
+				$owing = $registration->final_price() - $registration->paid();
1280
+				$taxable = $registration->ticket()->taxable()
1281
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1282
+					: '';
1283
+				$checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1284
+					? ' checked="checked"'
1285
+					: '';
1286
+				$disabled = $registration->final_price() > 0 ? '' : ' disabled';
1287
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1288
+					EEH_HTML::td($registration->ID()) .
1289
+					EEH_HTML::td($attendee_name) .
1290
+					EEH_HTML::td(
1291
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1292
+					) .
1293
+					EEH_HTML::td($registration->event_name()) .
1294
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1295
+					EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1296
+					EEH_HTML::td(
1297
+						'<input type="checkbox" value="' . $registration->ID()
1298
+						. '" name="txn_admin_payment[registrations]"'
1299
+						. $checked . $disabled . '>',
1300
+						'',
1301
+						'jst-cntr'
1302
+					),
1303
+					'apply-payment-registration-row-' . $registration->ID()
1304
+				);
1305
+			}
1306
+		}
1307
+		$registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1308
+		$registrations_to_apply_payment_to .= EEH_HTML::tablex();
1309
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1310
+		$registrations_to_apply_payment_to .= EEH_HTML::p(
1311
+			esc_html__(
1312
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1313
+				'event_espresso'
1314
+			),
1315
+			'',
1316
+			'clear description'
1317
+		);
1318
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1319
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * _get_reg_status_selection
1325
+	 *
1326
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1327
+	 *         instead of events.
1328
+	 * @access protected
1329
+	 * @return void
1330
+	 * @throws EE_Error
1331
+	 */
1332
+	protected function _get_reg_status_selection()
1333
+	{
1334
+		// first get all possible statuses
1335
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1336
+		// let's add a "don't change" option.
1337
+		$status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1338
+		$status_array = array_merge($status_array, $statuses);
1339
+		$this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1340
+			'txn_reg_status_change[reg_status]',
1341
+			$status_array,
1342
+			'NAN',
1343
+			'id="txn-admin-payment-reg-status-inp"',
1344
+			'txn-reg-status-change-reg-status'
1345
+		);
1346
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1347
+			'delete_txn_reg_status_change[reg_status]',
1348
+			$status_array,
1349
+			'NAN',
1350
+			'delete-txn-admin-payment-reg-status-inp',
1351
+			'delete-txn-reg-status-change-reg-status'
1352
+		);
1353
+	}
1354
+
1355
+
1356
+	/**
1357
+	 *    _get_payment_methods
1358
+	 * Gets all the payment methods available generally, or the ones that are already
1359
+	 * selected on these payments (in case their payment methods are no longer active).
1360
+	 * Has the side-effect of updating the template args' payment_methods item
1361
+	 *
1362
+	 * @access private
1363
+	 * @param EE_Payment[] to show on this page
1364
+	 * @return void
1365
+	 * @throws EE_Error
1366
+	 * @throws InvalidArgumentException
1367
+	 * @throws InvalidDataTypeException
1368
+	 * @throws InvalidInterfaceException
1369
+	 * @throws ReflectionException
1370
+	 */
1371
+	private function _get_payment_methods($payments = array())
1372
+	{
1373
+		$payment_methods_of_payments = array();
1374
+		foreach ($payments as $payment) {
1375
+			if ($payment instanceof EE_Payment) {
1376
+				$payment_methods_of_payments[] = $payment->get('PMD_ID');
1377
+			}
1378
+		}
1379
+		if ($payment_methods_of_payments) {
1380
+			$query_args = array(
1381
+				array(
1382
+					'OR*payment_method_for_payment' => array(
1383
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1384
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1385
+					),
1386
+				),
1387
+			);
1388
+		} else {
1389
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1390
+		}
1391
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1392
+	}
1393
+
1394
+
1395
+	/**
1396
+	 * txn_attendees_meta_box
1397
+	 *    generates HTML for the Attendees Transaction main meta box
1398
+	 *
1399
+	 * @access public
1400
+	 * @param WP_Post $post
1401
+	 * @param array   $metabox
1402
+	 * @return void
1403
+	 * @throws DomainException
1404
+	 * @throws EE_Error
1405
+	 */
1406
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1407
+	{
1408
+
1409
+		/** @noinspection NonSecureExtractUsageInspection */
1410
+		extract($metabox['args']);
1411
+		$this->_template_args['post'] = $post;
1412
+		$this->_template_args['event_attendees'] = array();
1413
+		// process items in cart
1414
+		$line_items = $this->_transaction->get_many_related(
1415
+			'Line_Item',
1416
+			array(array('LIN_type' => 'line-item'))
1417
+		);
1418
+		if (! empty($line_items)) {
1419
+			foreach ($line_items as $item) {
1420
+				if ($item instanceof EE_Line_Item) {
1421
+					switch ($item->OBJ_type()) {
1422
+						case 'Event':
1423
+							break;
1424
+						case 'Ticket':
1425
+							$ticket = $item->ticket();
1426
+							// right now we're only handling tickets here.
1427
+							// Cause its expected that only tickets will have attendees right?
1428
+							if (! $ticket instanceof EE_Ticket) {
1429
+								break;
1430
+							}
1431
+							try {
1432
+								$event_name = $ticket->get_event_name();
1433
+							} catch (Exception $e) {
1434
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1435
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1436
+							}
1437
+							$event_name .= ' - ' . $item->get('LIN_name');
1438
+							$ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1439
+							// now get all of the registrations for this transaction that use this ticket
1440
+							$registrations = $ticket->get_many_related(
1441
+								'Registration',
1442
+								array(array('TXN_ID' => $this->_transaction->ID()))
1443
+							);
1444
+							foreach ($registrations as $registration) {
1445
+								if (! $registration instanceof EE_Registration) {
1446
+									break;
1447
+								}
1448
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1449
+									= $registration->status_ID();
1450
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1451
+									= $registration->count();
1452
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1453
+									= $event_name;
1454
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1455
+									= $ticket_price;
1456
+								// attendee info
1457
+								$attendee = $registration->get_first_related('Attendee');
1458
+								if ($attendee instanceof EE_Attendee) {
1459
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1460
+										= $attendee->ID();
1461
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1462
+										= $attendee->full_name();
1463
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1464
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1465
+										  . esc_html__(
1466
+											  ' Event',
1467
+											  'event_espresso'
1468
+										  )
1469
+										  . '">' . $attendee->email() . '</a>';
1470
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1471
+										= EEH_Address::format($attendee, 'inline', false, false);
1472
+								} else {
1473
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1474
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1475
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1476
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1477
+								}
1478
+							}
1479
+							break;
1480
+					}
1481
+				}
1482
+			}
1483
+
1484
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1485
+				array(
1486
+					'action'  => 'edit_transaction',
1487
+					'process' => 'attendees',
1488
+				),
1489
+				TXN_ADMIN_URL
1490
+			);
1491
+			echo EEH_Template::display_template(
1492
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1493
+				$this->_template_args,
1494
+				true
1495
+			);
1496
+		} else {
1497
+			echo sprintf(
1498
+				esc_html__(
1499
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1500
+					'event_espresso'
1501
+				),
1502
+				'<p class="important-notice">',
1503
+				'</p>'
1504
+			);
1505
+		}
1506
+	}
1507
+
1508
+
1509
+	/**
1510
+	 * txn_registrant_side_meta_box
1511
+	 * generates HTML for the Edit Transaction side meta box
1512
+	 *
1513
+	 * @access public
1514
+	 * @return void
1515
+	 * @throws DomainException
1516
+	 * @throws EE_Error
1517
+	 * @throws InvalidArgumentException
1518
+	 * @throws InvalidDataTypeException
1519
+	 * @throws InvalidInterfaceException
1520
+	 * @throws ReflectionException
1521
+	 */
1522
+	public function txn_registrant_side_meta_box()
1523
+	{
1524
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1525
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1526
+			: null;
1527
+		if (! $primary_att instanceof EE_Attendee) {
1528
+			$this->_template_args['no_attendee_message'] = esc_html__(
1529
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1530
+				'event_espresso'
1531
+			);
1532
+			$primary_att = EEM_Attendee::instance()->create_default_object();
1533
+		}
1534
+		$this->_template_args['ATT_ID'] = $primary_att->ID();
1535
+		$this->_template_args['prime_reg_fname'] = $primary_att->fname();
1536
+		$this->_template_args['prime_reg_lname'] = $primary_att->lname();
1537
+		$this->_template_args['prime_reg_email'] = $primary_att->email();
1538
+		$this->_template_args['prime_reg_phone'] = $primary_att->phone();
1539
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1540
+			array(
1541
+				'action' => 'edit_attendee',
1542
+				'post'   => $primary_att->ID(),
1543
+			),
1544
+			REG_ADMIN_URL
1545
+		);
1546
+		// get formatted address for registrant
1547
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1548
+		echo EEH_Template::display_template(
1549
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1550
+			$this->_template_args,
1551
+			true
1552
+		);
1553
+	}
1554
+
1555
+
1556
+	/**
1557
+	 * txn_billing_info_side_meta_box
1558
+	 *    generates HTML for the Edit Transaction side meta box
1559
+	 *
1560
+	 * @access public
1561
+	 * @return void
1562
+	 * @throws DomainException
1563
+	 * @throws EE_Error
1564
+	 */
1565
+	public function txn_billing_info_side_meta_box()
1566
+	{
1567
+
1568
+		$this->_template_args['billing_form'] = $this->_transaction->billing_info();
1569
+		$this->_template_args['billing_form_url'] = add_query_arg(
1570
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1571
+			TXN_ADMIN_URL
1572
+		);
1573
+
1574
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1575
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1576
+	}
1577
+
1578
+
1579
+	/**
1580
+	 * apply_payments_or_refunds
1581
+	 *    registers a payment or refund made towards a transaction
1582
+	 *
1583
+	 * @access public
1584
+	 * @return void
1585
+	 * @throws EE_Error
1586
+	 * @throws InvalidArgumentException
1587
+	 * @throws ReflectionException
1588
+	 * @throws RuntimeException
1589
+	 * @throws InvalidDataTypeException
1590
+	 * @throws InvalidInterfaceException
1591
+	 */
1592
+	public function apply_payments_or_refunds()
1593
+	{
1594
+		$json_response_data = array('return_data' => false);
1595
+		$valid_data = $this->_validate_payment_request_data();
1596
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1597
+			'ee_edit_payments',
1598
+			'apply_payment_or_refund_from_registration_details'
1599
+		);
1600
+		if (! empty($valid_data) && $has_access) {
1601
+			$PAY_ID = $valid_data['PAY_ID'];
1602
+			// save  the new payment
1603
+			$payment = $this->_create_payment_from_request_data($valid_data);
1604
+			// get the TXN for this payment
1605
+			$transaction = $payment->transaction();
1606
+			// verify transaction
1607
+			if ($transaction instanceof EE_Transaction) {
1608
+				// calculate_total_payments_and_update_status
1609
+				$this->_process_transaction_payments($transaction);
1610
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1611
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1612
+				// apply payment to registrations (if applicable)
1613
+				if (! empty($REG_IDs)) {
1614
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1615
+					$this->_maybe_send_notifications();
1616
+					// now process status changes for the same registrations
1617
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1618
+				}
1619
+				$this->_maybe_send_notifications($payment);
1620
+				// prepare to render page
1621
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1622
+				do_action(
1623
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1624
+					$transaction,
1625
+					$payment
1626
+				);
1627
+			} else {
1628
+				EE_Error::add_error(
1629
+					esc_html__(
1630
+						'A valid Transaction for this payment could not be retrieved.',
1631
+						'event_espresso'
1632
+					),
1633
+					__FILE__,
1634
+					__FUNCTION__,
1635
+					__LINE__
1636
+				);
1637
+			}
1638
+		} else {
1639
+			if ($has_access) {
1640
+				EE_Error::add_error(
1641
+					esc_html__(
1642
+						'The payment form data could not be processed. Please try again.',
1643
+						'event_espresso'
1644
+					),
1645
+					__FILE__,
1646
+					__FUNCTION__,
1647
+					__LINE__
1648
+				);
1649
+			} else {
1650
+				EE_Error::add_error(
1651
+					esc_html__(
1652
+						'You do not have access to apply payments or refunds to a registration.',
1653
+						'event_espresso'
1654
+					),
1655
+					__FILE__,
1656
+					__FUNCTION__,
1657
+					__LINE__
1658
+				);
1659
+			}
1660
+		}
1661
+		$notices = EE_Error::get_notices(
1662
+			false,
1663
+			false,
1664
+			false
1665
+		);
1666
+		$this->_template_args = array(
1667
+			'data'    => $json_response_data,
1668
+			'error'   => $notices['errors'],
1669
+			'success' => $notices['success'],
1670
+		);
1671
+		$this->_return_json();
1672
+	}
1673
+
1674
+
1675
+	/**
1676
+	 * _validate_payment_request_data
1677
+	 *
1678
+	 * @return array
1679
+	 * @throws EE_Error
1680
+	 */
1681
+	protected function _validate_payment_request_data()
1682
+	{
1683
+		if (! isset($this->_req_data['txn_admin_payment'])) {
1684
+			return false;
1685
+		}
1686
+		$payment_form = $this->_generate_payment_form_section();
1687
+		try {
1688
+			if ($payment_form->was_submitted()) {
1689
+				$payment_form->receive_form_submission();
1690
+				if (! $payment_form->is_valid()) {
1691
+					$submission_error_messages = array();
1692
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1693
+						if ($validation_error instanceof EE_Validation_Error) {
1694
+							$submission_error_messages[] = sprintf(
1695
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1696
+								$validation_error->get_form_section()->html_label_text(),
1697
+								$validation_error->getMessage()
1698
+							);
1699
+						}
1700
+					}
1701
+					EE_Error::add_error(
1702
+						implode('<br />', $submission_error_messages),
1703
+						__FILE__,
1704
+						__FUNCTION__,
1705
+						__LINE__
1706
+					);
1707
+
1708
+					return array();
1709
+				}
1710
+			}
1711
+		} catch (EE_Error $e) {
1712
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1713
+
1714
+			return array();
1715
+		}
1716
+
1717
+		return $payment_form->valid_data();
1718
+	}
1719
+
1720
+
1721
+	/**
1722
+	 * _generate_payment_form_section
1723
+	 *
1724
+	 * @return EE_Form_Section_Proper
1725
+	 * @throws EE_Error
1726
+	 */
1727
+	protected function _generate_payment_form_section()
1728
+	{
1729
+		return new EE_Form_Section_Proper(
1730
+			array(
1731
+				'name'        => 'txn_admin_payment',
1732
+				'subsections' => array(
1733
+					'PAY_ID'          => new EE_Text_Input(
1734
+						array(
1735
+							'default'               => 0,
1736
+							'required'              => false,
1737
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1738
+							'validation_strategies' => array(new EE_Int_Normalization()),
1739
+						)
1740
+					),
1741
+					'TXN_ID'          => new EE_Text_Input(
1742
+						array(
1743
+							'default'               => 0,
1744
+							'required'              => true,
1745
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1746
+							'validation_strategies' => array(new EE_Int_Normalization()),
1747
+						)
1748
+					),
1749
+					'type'            => new EE_Text_Input(
1750
+						array(
1751
+							'default'               => 1,
1752
+							'required'              => true,
1753
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1754
+							'validation_strategies' => array(new EE_Int_Normalization()),
1755
+						)
1756
+					),
1757
+					'amount'          => new EE_Text_Input(
1758
+						array(
1759
+							'default'               => 0,
1760
+							'required'              => true,
1761
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1762
+							'validation_strategies' => array(new EE_Float_Normalization()),
1763
+						)
1764
+					),
1765
+					'status'          => new EE_Text_Input(
1766
+						array(
1767
+							'default'         => EEM_Payment::status_id_approved,
1768
+							'required'        => true,
1769
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1770
+						)
1771
+					),
1772
+					'PMD_ID'          => new EE_Text_Input(
1773
+						array(
1774
+							'default'               => 2,
1775
+							'required'              => true,
1776
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1777
+							'validation_strategies' => array(new EE_Int_Normalization()),
1778
+						)
1779
+					),
1780
+					'date'            => new EE_Text_Input(
1781
+						array(
1782
+							'default'         => time(),
1783
+							'required'        => true,
1784
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1785
+						)
1786
+					),
1787
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1788
+						array(
1789
+							'default'               => '',
1790
+							'required'              => false,
1791
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1792
+							'validation_strategies' => array(
1793
+								new EE_Max_Length_Validation_Strategy(
1794
+									esc_html__('Input too long', 'event_espresso'),
1795
+									100
1796
+								),
1797
+							),
1798
+						)
1799
+					),
1800
+					'po_number'       => new EE_Text_Input(
1801
+						array(
1802
+							'default'               => '',
1803
+							'required'              => false,
1804
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1805
+							'validation_strategies' => array(
1806
+								new EE_Max_Length_Validation_Strategy(
1807
+									esc_html__('Input too long', 'event_espresso'),
1808
+									100
1809
+								),
1810
+							),
1811
+						)
1812
+					),
1813
+					'accounting'      => new EE_Text_Input(
1814
+						array(
1815
+							'default'               => '',
1816
+							'required'              => false,
1817
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1818
+							'validation_strategies' => array(
1819
+								new EE_Max_Length_Validation_Strategy(
1820
+									esc_html__('Input too long', 'event_espresso'),
1821
+									100
1822
+								),
1823
+							),
1824
+						)
1825
+					),
1826
+				),
1827
+			)
1828
+		);
1829
+	}
1830
+
1831
+
1832
+	/**
1833
+	 * _create_payment_from_request_data
1834
+	 *
1835
+	 * @param array $valid_data
1836
+	 * @return EE_Payment
1837
+	 * @throws EE_Error
1838
+	 */
1839
+	protected function _create_payment_from_request_data($valid_data)
1840
+	{
1841
+		$PAY_ID = $valid_data['PAY_ID'];
1842
+		// get payment amount
1843
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1844
+		// payments have a type value of 1 and refunds have a type value of -1
1845
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1846
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1847
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1848
+		$date = $valid_data['date']
1849
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1850
+			: date('Y-m-d g:i a', current_time('timestamp'));
1851
+		$payment = EE_Payment::new_instance(
1852
+			array(
1853
+				'TXN_ID'              => $valid_data['TXN_ID'],
1854
+				'STS_ID'              => $valid_data['status'],
1855
+				'PAY_timestamp'       => $date,
1856
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1857
+				'PMD_ID'              => $valid_data['PMD_ID'],
1858
+				'PAY_amount'          => $amount,
1859
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1860
+				'PAY_po_number'       => $valid_data['po_number'],
1861
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1862
+				'PAY_details'         => $valid_data,
1863
+				'PAY_ID'              => $PAY_ID,
1864
+			),
1865
+			'',
1866
+			array('Y-m-d', 'g:i a')
1867
+		);
1868
+
1869
+		if (! $payment->save()) {
1870
+			EE_Error::add_error(
1871
+				sprintf(
1872
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1873
+					$payment->ID()
1874
+				),
1875
+				__FILE__,
1876
+				__FUNCTION__,
1877
+				__LINE__
1878
+			);
1879
+		}
1880
+
1881
+		return $payment;
1882
+	}
1883
+
1884
+
1885
+	/**
1886
+	 * _process_transaction_payments
1887
+	 *
1888
+	 * @param \EE_Transaction $transaction
1889
+	 * @return void
1890
+	 * @throws EE_Error
1891
+	 * @throws InvalidArgumentException
1892
+	 * @throws ReflectionException
1893
+	 * @throws InvalidDataTypeException
1894
+	 * @throws InvalidInterfaceException
1895
+	 */
1896
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1897
+	{
1898
+		/** @type EE_Transaction_Payments $transaction_payments */
1899
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1900
+		// update the transaction with this payment
1901
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1902
+			EE_Error::add_success(
1903
+				esc_html__(
1904
+					'The payment has been processed successfully.',
1905
+					'event_espresso'
1906
+				),
1907
+				__FILE__,
1908
+				__FUNCTION__,
1909
+				__LINE__
1910
+			);
1911
+		} else {
1912
+			EE_Error::add_error(
1913
+				esc_html__(
1914
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1915
+					'event_espresso'
1916
+				),
1917
+				__FILE__,
1918
+				__FUNCTION__,
1919
+				__LINE__
1920
+			);
1921
+		}
1922
+	}
1923
+
1924
+
1925
+	/**
1926
+	 * _get_REG_IDs_to_apply_payment_to
1927
+	 * returns a list of registration IDs that the payment will apply to
1928
+	 *
1929
+	 * @param \EE_Payment $payment
1930
+	 * @return array
1931
+	 * @throws EE_Error
1932
+	 */
1933
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1934
+	{
1935
+		$REG_IDs = array();
1936
+		// grab array of IDs for specific registrations to apply changes to
1937
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1938
+			$REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1939
+		}
1940
+		// nothing specified ? then get all reg IDs
1941
+		if (empty($REG_IDs)) {
1942
+			$registrations = $payment->transaction()->registrations();
1943
+			$REG_IDs = ! empty($registrations)
1944
+				? array_keys($registrations)
1945
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1946
+		}
1947
+
1948
+		// ensure that REG_IDs are integers and NOT strings
1949
+		return array_map('intval', $REG_IDs);
1950
+	}
1951
+
1952
+
1953
+	/**
1954
+	 * @return array
1955
+	 */
1956
+	public function existing_reg_payment_REG_IDs()
1957
+	{
1958
+		return $this->_existing_reg_payment_REG_IDs;
1959
+	}
1960
+
1961
+
1962
+	/**
1963
+	 * @param array $existing_reg_payment_REG_IDs
1964
+	 */
1965
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1966
+	{
1967
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1968
+	}
1969
+
1970
+
1971
+	/**
1972
+	 * _get_existing_reg_payment_REG_IDs
1973
+	 * returns a list of registration IDs that the payment is currently related to
1974
+	 * as recorded in the database
1975
+	 *
1976
+	 * @param \EE_Payment $payment
1977
+	 * @return array
1978
+	 * @throws EE_Error
1979
+	 */
1980
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1981
+	{
1982
+		if ($this->existing_reg_payment_REG_IDs() === null) {
1983
+			// let's get any existing reg payment records for this payment
1984
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1985
+			// but we only want the REG IDs, so grab the array keys
1986
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
1987
+				? array_keys($existing_reg_payment_REG_IDs)
1988
+				: array();
1989
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1990
+		}
1991
+
1992
+		return $this->existing_reg_payment_REG_IDs();
1993
+	}
1994
+
1995
+
1996
+	/**
1997
+	 * _remove_existing_registration_payments
1998
+	 * this calculates the difference between existing relations
1999
+	 * to the supplied payment and the new list registration IDs,
2000
+	 * removes any related registrations that no longer apply,
2001
+	 * and then updates the registration paid fields
2002
+	 *
2003
+	 * @param \EE_Payment $payment
2004
+	 * @param int         $PAY_ID
2005
+	 * @return bool;
2006
+	 * @throws EE_Error
2007
+	 * @throws InvalidArgumentException
2008
+	 * @throws ReflectionException
2009
+	 * @throws InvalidDataTypeException
2010
+	 * @throws InvalidInterfaceException
2011
+	 */
2012
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2013
+	{
2014
+		// newly created payments will have nothing recorded for $PAY_ID
2015
+		if ($PAY_ID == 0) {
2016
+			return false;
2017
+		}
2018
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2019
+		if (empty($existing_reg_payment_REG_IDs)) {
2020
+			return false;
2021
+		}
2022
+		/** @type EE_Transaction_Payments $transaction_payments */
2023
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2024
+
2025
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2026
+			$payment,
2027
+			array(
2028
+				array(
2029
+					'PAY_ID' => $payment->ID(),
2030
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2031
+				),
2032
+			)
2033
+		);
2034
+	}
2035
+
2036
+
2037
+	/**
2038
+	 * _update_registration_payments
2039
+	 * this applies the payments to the selected registrations
2040
+	 * but only if they have not already been paid for
2041
+	 *
2042
+	 * @param  EE_Transaction $transaction
2043
+	 * @param \EE_Payment     $payment
2044
+	 * @param array           $REG_IDs
2045
+	 * @return void
2046
+	 * @throws EE_Error
2047
+	 * @throws InvalidArgumentException
2048
+	 * @throws ReflectionException
2049
+	 * @throws RuntimeException
2050
+	 * @throws InvalidDataTypeException
2051
+	 * @throws InvalidInterfaceException
2052
+	 */
2053
+	protected function _update_registration_payments(
2054
+		EE_Transaction $transaction,
2055
+		EE_Payment $payment,
2056
+		$REG_IDs = array()
2057
+	) {
2058
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2059
+		// so let's do that using our set of REG_IDs from the form
2060
+		$registration_query_where_params = array(
2061
+			'REG_ID' => array('IN', $REG_IDs),
2062
+		);
2063
+		// but add in some conditions regarding payment,
2064
+		// so that we don't apply payments to registrations that are free or have already been paid for
2065
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2066
+		if (! $payment->is_a_refund()) {
2067
+			$registration_query_where_params['REG_final_price'] = array('!=', 0);
2068
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2069
+		}
2070
+		$registrations = $transaction->registrations(array($registration_query_where_params));
2071
+		if (! empty($registrations)) {
2072
+			/** @type EE_Payment_Processor $payment_processor */
2073
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2074
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2075
+		}
2076
+	}
2077
+
2078
+
2079
+	/**
2080
+	 * _process_registration_status_change
2081
+	 * This processes requested registration status changes for all the registrations
2082
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2083
+	 *
2084
+	 * @param  EE_Transaction $transaction
2085
+	 * @param array           $REG_IDs
2086
+	 * @return bool
2087
+	 * @throws EE_Error
2088
+	 * @throws InvalidArgumentException
2089
+	 * @throws ReflectionException
2090
+	 * @throws InvalidDataTypeException
2091
+	 * @throws InvalidInterfaceException
2092
+	 */
2093
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2094
+	{
2095
+		// first if there is no change in status then we get out.
2096
+		if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2097
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2098
+		) {
2099
+			// no error message, no change requested, just nothing to do man.
2100
+			return false;
2101
+		}
2102
+		/** @type EE_Transaction_Processor $transaction_processor */
2103
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2104
+
2105
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2106
+		return $transaction_processor->manually_update_registration_statuses(
2107
+			$transaction,
2108
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2109
+			array(array('REG_ID' => array('IN', $REG_IDs)))
2110
+		);
2111
+	}
2112
+
2113
+
2114
+	/**
2115
+	 * _build_payment_json_response
2116
+	 *
2117
+	 * @access public
2118
+	 * @param \EE_Payment $payment
2119
+	 * @param array       $REG_IDs
2120
+	 * @param bool | null $delete_txn_reg_status_change
2121
+	 * @return array
2122
+	 * @throws EE_Error
2123
+	 * @throws InvalidArgumentException
2124
+	 * @throws InvalidDataTypeException
2125
+	 * @throws InvalidInterfaceException
2126
+	 * @throws ReflectionException
2127
+	 */
2128
+	protected function _build_payment_json_response(
2129
+		EE_Payment $payment,
2130
+		$REG_IDs = array(),
2131
+		$delete_txn_reg_status_change = null
2132
+	) {
2133
+		// was the payment deleted ?
2134
+		if (is_bool($delete_txn_reg_status_change)) {
2135
+			return array(
2136
+				'PAY_ID'                       => $payment->ID(),
2137
+				'amount'                       => $payment->amount(),
2138
+				'total_paid'                   => $payment->transaction()->paid(),
2139
+				'txn_status'                   => $payment->transaction()->status_ID(),
2140
+				'pay_status'                   => $payment->STS_ID(),
2141
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2142
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2143
+			);
2144
+		} else {
2145
+			$this->_get_payment_status_array();
2146
+
2147
+			return array(
2148
+				'amount'           => $payment->amount(),
2149
+				'total_paid'       => $payment->transaction()->paid(),
2150
+				'txn_status'       => $payment->transaction()->status_ID(),
2151
+				'pay_status'       => $payment->STS_ID(),
2152
+				'PAY_ID'           => $payment->ID(),
2153
+				'STS_ID'           => $payment->STS_ID(),
2154
+				'status'           => self::$_pay_status[ $payment->STS_ID() ],
2155
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2156
+				'method'           => strtoupper($payment->source()),
2157
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2158
+				'gateway'          => $payment->payment_method()
2159
+					? $payment->payment_method()->admin_name()
2160
+					: esc_html__("Unknown", 'event_espresso'),
2161
+				'gateway_response' => $payment->gateway_response(),
2162
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2163
+				'po_number'        => $payment->po_number(),
2164
+				'extra_accntng'    => $payment->extra_accntng(),
2165
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2166
+			);
2167
+		}
2168
+	}
2169
+
2170
+
2171
+	/**
2172
+	 * delete_payment
2173
+	 *    delete a payment or refund made towards a transaction
2174
+	 *
2175
+	 * @access public
2176
+	 * @return void
2177
+	 * @throws EE_Error
2178
+	 * @throws InvalidArgumentException
2179
+	 * @throws ReflectionException
2180
+	 * @throws InvalidDataTypeException
2181
+	 * @throws InvalidInterfaceException
2182
+	 */
2183
+	public function delete_payment()
2184
+	{
2185
+		$json_response_data = array('return_data' => false);
2186
+		$PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2187
+			? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2188
+			: 0;
2189
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2190
+			'ee_delete_payments',
2191
+			'delete_payment_from_registration_details'
2192
+		);
2193
+		if ($PAY_ID && $can_delete) {
2194
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2195
+				? $this->_req_data['delete_txn_reg_status_change']
2196
+				: false;
2197
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2198
+			if ($payment instanceof EE_Payment) {
2199
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2200
+				/** @type EE_Transaction_Payments $transaction_payments */
2201
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2202
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2203
+					$json_response_data['return_data'] = $this->_build_payment_json_response(
2204
+						$payment,
2205
+						$REG_IDs,
2206
+						$delete_txn_reg_status_change
2207
+					);
2208
+					if ($delete_txn_reg_status_change) {
2209
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2210
+						// MAKE sure we also add the delete_txn_req_status_change to the
2211
+						// $_REQUEST global because that's how messages will be looking for it.
2212
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2213
+						$this->_maybe_send_notifications();
2214
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2215
+					}
2216
+				}
2217
+			} else {
2218
+				EE_Error::add_error(
2219
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2220
+					__FILE__,
2221
+					__FUNCTION__,
2222
+					__LINE__
2223
+				);
2224
+			}
2225
+		} else {
2226
+			if ($can_delete) {
2227
+				EE_Error::add_error(
2228
+					esc_html__(
2229
+						'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2230
+						'event_espresso'
2231
+					),
2232
+					__FILE__,
2233
+					__FUNCTION__,
2234
+					__LINE__
2235
+				);
2236
+			} else {
2237
+				EE_Error::add_error(
2238
+					esc_html__(
2239
+						'You do not have access to delete a payment.',
2240
+						'event_espresso'
2241
+					),
2242
+					__FILE__,
2243
+					__FUNCTION__,
2244
+					__LINE__
2245
+				);
2246
+			}
2247
+		}
2248
+		$notices = EE_Error::get_notices(false, false, false);
2249
+		$this->_template_args = array(
2250
+			'data'      => $json_response_data,
2251
+			'success'   => $notices['success'],
2252
+			'error'     => $notices['errors'],
2253
+			'attention' => $notices['attention'],
2254
+		);
2255
+		$this->_return_json();
2256
+	}
2257
+
2258
+
2259
+	/**
2260
+	 * _registration_payment_data_array
2261
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2262
+	 *
2263
+	 * @access protected
2264
+	 * @param array $REG_IDs
2265
+	 * @return array
2266
+	 * @throws EE_Error
2267
+	 * @throws InvalidArgumentException
2268
+	 * @throws InvalidDataTypeException
2269
+	 * @throws InvalidInterfaceException
2270
+	 * @throws ReflectionException
2271
+	 */
2272
+	protected function _registration_payment_data_array($REG_IDs)
2273
+	{
2274
+		$registration_payment_data = array();
2275
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2276
+		if (! empty($REG_IDs)) {
2277
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2278
+			foreach ($registrations as $registration) {
2279
+				if ($registration instanceof EE_Registration) {
2280
+					$registration_payment_data[ $registration->ID() ] = array(
2281
+						'paid'  => $registration->pretty_paid(),
2282
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2283
+					);
2284
+				}
2285
+			}
2286
+		}
2287
+
2288
+		return $registration_payment_data;
2289
+	}
2290
+
2291
+
2292
+	/**
2293
+	 * _maybe_send_notifications
2294
+	 * determines whether or not the admin has indicated that notifications should be sent.
2295
+	 * If so, will toggle a filter switch for delivering registration notices.
2296
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2297
+	 *
2298
+	 * @access protected
2299
+	 * @param \EE_Payment | null $payment
2300
+	 */
2301
+	protected function _maybe_send_notifications($payment = null)
2302
+	{
2303
+		switch ($payment instanceof EE_Payment) {
2304
+			// payment notifications
2305
+			case true:
2306
+				if (isset(
2307
+					$this->_req_data['txn_payments'],
2308
+					$this->_req_data['txn_payments']['send_notifications']
2309
+				)
2310
+					&& filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2311
+				) {
2312
+					$this->_process_payment_notification($payment);
2313
+				}
2314
+				break;
2315
+			// registration notifications
2316
+			case false:
2317
+				if (isset(
2318
+					$this->_req_data['txn_reg_status_change'],
2319
+					$this->_req_data['txn_reg_status_change']['send_notifications']
2320
+				)
2321
+					&& filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2322
+				) {
2323
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2324
+				}
2325
+				break;
2326
+		}
2327
+	}
2328
+
2329
+
2330
+	/**
2331
+	 * _send_payment_reminder
2332
+	 *    generates HTML for the View Transaction Details Admin page
2333
+	 *
2334
+	 * @access protected
2335
+	 * @return void
2336
+	 * @throws EE_Error
2337
+	 * @throws InvalidArgumentException
2338
+	 * @throws InvalidDataTypeException
2339
+	 * @throws InvalidInterfaceException
2340
+	 */
2341
+	protected function _send_payment_reminder()
2342
+	{
2343
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2344
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2345
+		$query_args = isset($this->_req_data['redirect_to']) ? array(
2346
+			'action' => $this->_req_data['redirect_to'],
2347
+			'TXN_ID' => $this->_req_data['TXN_ID'],
2348
+		) : array();
2349
+		do_action(
2350
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2351
+			$transaction
2352
+		);
2353
+		$this->_redirect_after_action(
2354
+			false,
2355
+			esc_html__('payment reminder', 'event_espresso'),
2356
+			esc_html__('sent', 'event_espresso'),
2357
+			$query_args,
2358
+			true
2359
+		);
2360
+	}
2361
+
2362
+
2363
+	/**
2364
+	 *  get_transactions
2365
+	 *    get transactions for given parameters (used by list table)
2366
+	 *
2367
+	 * @param  int     $perpage how many transactions displayed per page
2368
+	 * @param  boolean $count   return the count or objects
2369
+	 * @param string   $view
2370
+	 * @return mixed int = count || array of transaction objects
2371
+	 * @throws EE_Error
2372
+	 * @throws InvalidArgumentException
2373
+	 * @throws InvalidDataTypeException
2374
+	 * @throws InvalidInterfaceException
2375
+	 */
2376
+	public function get_transactions($perpage, $count = false, $view = '')
2377
+	{
2378
+
2379
+		$TXN = EEM_Transaction::instance();
2380
+
2381
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
2382
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2383
+			: date(
2384
+				'm/d/Y',
2385
+				strtotime('-10 year')
2386
+			);
2387
+		$end_date = isset($this->_req_data['txn-filter-end-date'])
2388
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2389
+			: date('m/d/Y');
2390
+
2391
+		// make sure our timestamps start and end right at the boundaries for each day
2392
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2393
+		$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2394
+
2395
+
2396
+		// convert to timestamps
2397
+		$start_date = strtotime($start_date);
2398
+		$end_date = strtotime($end_date);
2399
+
2400
+		// makes sure start date is the lowest value and vice versa
2401
+		$start_date = min($start_date, $end_date);
2402
+		$end_date = max($start_date, $end_date);
2403
+
2404
+		// convert to correct format for query
2405
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2406
+			'TXN_timestamp',
2407
+			date('Y-m-d H:i:s', $start_date),
2408
+			'Y-m-d H:i:s'
2409
+		);
2410
+		$end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2411
+			'TXN_timestamp',
2412
+			date('Y-m-d H:i:s', $end_date),
2413
+			'Y-m-d H:i:s'
2414
+		);
2415
+
2416
+
2417
+		// set orderby
2418
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2419
+
2420
+		switch ($this->_req_data['orderby']) {
2421
+			case 'TXN_ID':
2422
+				$orderby = 'TXN_ID';
2423
+				break;
2424
+			case 'ATT_fname':
2425
+				$orderby = 'Registration.Attendee.ATT_fname';
2426
+				break;
2427
+			case 'event_name':
2428
+				$orderby = 'Registration.Event.EVT_name';
2429
+				break;
2430
+			default: // 'TXN_timestamp'
2431
+				$orderby = 'TXN_timestamp';
2432
+		}
2433
+
2434
+		$sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2435
+		$current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2436
+		$per_page = ! empty($perpage) ? $perpage : 10;
2437
+		$per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2438
+
2439
+		$offset = ($current_page - 1) * $per_page;
2440
+		$limit = array($offset, $per_page);
2441
+
2442
+		$_where = array(
2443
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2444
+			'Registration.REG_count' => 1,
2445
+		);
2446
+
2447
+		if (isset($this->_req_data['EVT_ID'])) {
2448
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2449
+		}
2450
+
2451
+		if (isset($this->_req_data['s'])) {
2452
+			$search_string = '%' . $this->_req_data['s'] . '%';
2453
+			$_where['OR'] = array(
2454
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2455
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2456
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2457
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2458
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2459
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2460
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2461
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2462
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2463
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2464
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2465
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
2466
+				'Registration.REG_code'               => array('LIKE', $search_string),
2467
+				'Registration.REG_count'              => array('LIKE', $search_string),
2468
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
2469
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2470
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2471
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
2472
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2473
+				'TXN_session_data'                    => array('LIKE', $search_string),
2474
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2475
+			);
2476
+		}
2477
+
2478
+		// failed transactions
2479
+		$failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2480
+				  || ($count && $view === 'failed');
2481
+		$abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2482
+					 || ($count && $view === 'abandoned');
2483
+		$incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2484
+					  || ($count && $view === 'incomplete');
2485
+
2486
+		if ($failed) {
2487
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2488
+		} elseif ($abandoned) {
2489
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2490
+		} elseif ($incomplete) {
2491
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2492
+		} else {
2493
+			$_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2494
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2495
+		}
2496
+
2497
+		$query_params = apply_filters(
2498
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2499
+			array(
2500
+				$_where,
2501
+				'order_by'                 => array($orderby => $sort),
2502
+				'limit'                    => $limit,
2503
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2504
+			),
2505
+			$this->_req_data,
2506
+			$view,
2507
+			$count
2508
+		);
2509
+
2510
+		$transactions = $count
2511
+			? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2512
+			: $TXN->get_all($query_params);
2513
+
2514
+		return $transactions;
2515
+	}
2516 2516
 }
Please login to merge, or discard this patch.
Spacing   +84 added lines, -84 removed lines patch added patch discarded remove patch
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
         // enqueue style
364 364
         wp_register_style(
365 365
             'espresso_txn',
366
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
366
+            TXN_ASSETS_URL.'espresso_transactions_admin.css',
367 367
             array(),
368 368
             EVENT_ESPRESSO_VERSION
369 369
         );
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
         // scripts
372 372
         wp_register_script(
373 373
             'espresso_txn',
374
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
374
+            TXN_ASSETS_URL.'espresso_transactions_admin.js',
375 375
             array(
376 376
                 'ee_admin_js',
377 377
                 'ee-datepicker',
@@ -499,7 +499,7 @@  discard block
 block discarded – undo
499 499
             $this->_transaction->verify_abandoned_transaction_status();
500 500
         }
501 501
 
502
-        if (! $this->_transaction instanceof EE_Transaction) {
502
+        if ( ! $this->_transaction instanceof EE_Transaction) {
503 503
             $error_msg = sprintf(
504 504
                 esc_html__(
505 505
                     'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
@@ -597,7 +597,7 @@  discard block
 block discarded – undo
597 597
             'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
598 598
             array(
599 599
                 'overpaid'   => array(
600
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
600
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::overpaid_status_code,
601 601
                     'desc'  => EEH_Template::pretty_status(
602 602
                         EEM_Transaction::overpaid_status_code,
603 603
                         false,
@@ -605,7 +605,7 @@  discard block
 block discarded – undo
605 605
                     ),
606 606
                 ),
607 607
                 'complete'   => array(
608
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
608
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::complete_status_code,
609 609
                     'desc'  => EEH_Template::pretty_status(
610 610
                         EEM_Transaction::complete_status_code,
611 611
                         false,
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
                     ),
614 614
                 ),
615 615
                 'incomplete' => array(
616
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
616
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::incomplete_status_code,
617 617
                     'desc'  => EEH_Template::pretty_status(
618 618
                         EEM_Transaction::incomplete_status_code,
619 619
                         false,
@@ -621,7 +621,7 @@  discard block
 block discarded – undo
621 621
                     ),
622 622
                 ),
623 623
                 'abandoned'  => array(
624
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
624
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::abandoned_status_code,
625 625
                     'desc'  => EEH_Template::pretty_status(
626 626
                         EEM_Transaction::abandoned_status_code,
627 627
                         false,
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
                     ),
630 630
                 ),
631 631
                 'failed'     => array(
632
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
632
+                    'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::failed_status_code,
633 633
                     'desc'  => EEH_Template::pretty_status(
634 634
                         EEM_Transaction::failed_status_code,
635 635
                         false,
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
                     'Click to Edit event',
679 679
                     'event_espresso'
680 680
                 )
681
-                . '">' . $event->get('EVT_name') . '</a>',
681
+                . '">'.$event->get('EVT_name').'</a>',
682 682
                 '</h3>'
683 683
             )
684 684
             : '';
@@ -712,7 +712,7 @@  discard block
 block discarded – undo
712 712
 
713 713
         $this->_set_transaction_object();
714 714
 
715
-        if (! $this->_transaction instanceof EE_Transaction) {
715
+        if ( ! $this->_transaction instanceof EE_Transaction) {
716 716
             return;
717 717
         }
718 718
         $primary_registration = $this->_transaction->primary_registration();
@@ -726,9 +726,9 @@  discard block
 block discarded – undo
726 726
         $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
727 727
         $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
728 728
 
729
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->get('STS_ID') ];
729
+        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
730 730
         $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
731
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
731
+        $this->_template_args['txn_status']['class'] = 'status-'.$this->_transaction->get('STS_ID');
732 732
 
733 733
         $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
734 734
         $this->_template_args['total_paid'] = $this->_transaction->get('TXN_paid');
@@ -846,7 +846,7 @@  discard block
 block discarded – undo
846 846
         // grab messages at the last second
847 847
         $this->_template_args['notices'] = EE_Error::get_notices();
848 848
         // path to template
849
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
849
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_header.template.php';
850 850
         $this->_template_args['admin_page_header'] = EEH_Template::display_template(
851 851
             $template_path,
852 852
             $this->_template_args,
@@ -875,7 +875,7 @@  discard block
 block discarded – undo
875 875
 
876 876
         $this->_set_transaction_object();
877 877
 
878
-        if (! $this->_transaction instanceof EE_Transaction) {
878
+        if ( ! $this->_transaction instanceof EE_Transaction) {
879 879
             return;
880 880
         }
881 881
         add_meta_box(
@@ -930,7 +930,7 @@  discard block
 block discarded – undo
930 930
     {
931 931
         $content = '';
932 932
         $actions = array();
933
-        if (! $transaction instanceof EE_Transaction) {
933
+        if ( ! $transaction instanceof EE_Transaction) {
934 934
             return $content;
935 935
         }
936 936
         /** @var EE_Registration $primary_registration */
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
         );
992 992
         if ($actions) {
993 993
             $content = '<ul>';
994
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
994
+            $content .= '<li>'.implode('</li><li>', $actions).'</li>';
995 995
             $content .= '</uL>';
996 996
         }
997 997
         return $content;
@@ -1056,7 +1056,7 @@  discard block
 block discarded – undo
1056 1056
 
1057 1057
         // process payment details
1058 1058
         $payments = $this->_transaction->get_many_related('Payment');
1059
-        if (! empty($payments)) {
1059
+        if ( ! empty($payments)) {
1060 1060
             $this->_template_args['payments'] = $payments;
1061 1061
             $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1062 1062
         } else {
@@ -1117,7 +1117,7 @@  discard block
 block discarded – undo
1117 1117
                                   esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1118 1118
                                   ucwords(str_replace('_', ' ', $reg_step)),
1119 1119
                                   date(
1120
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1120
+                                      get_option('date_format').' '.get_option('time_format'),
1121 1121
                                       ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1122 1122
                                   )
1123 1123
                               )
@@ -1170,7 +1170,7 @@  discard block
 block discarded – undo
1170 1170
 
1171 1171
         // 'espresso_delete_payment_nonce'
1172 1172
 
1173
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1173
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_txn_details.template.php';
1174 1174
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
1175 1175
     }
1176 1176
 
@@ -1202,18 +1202,18 @@  discard block
 block discarded – undo
1202 1202
                 ),
1203 1203
             )
1204 1204
         );
1205
-        if (! empty($reg_payments)) {
1205
+        if ( ! empty($reg_payments)) {
1206 1206
             foreach ($payments as $payment) {
1207
-                if (! $payment instanceof EE_Payment) {
1207
+                if ( ! $payment instanceof EE_Payment) {
1208 1208
                     continue;
1209
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1210
-                    $existing_reg_payments[ $payment->ID() ] = array();
1209
+                } elseif ( ! isset($existing_reg_payments[$payment->ID()])) {
1210
+                    $existing_reg_payments[$payment->ID()] = array();
1211 1211
                 }
1212 1212
                 foreach ($reg_payments as $reg_payment) {
1213 1213
                     if ($reg_payment instanceof EE_Registration_Payment
1214 1214
                         && $reg_payment->payment_ID() === $payment->ID()
1215 1215
                     ) {
1216
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1216
+                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1217 1217
                     }
1218 1218
                 }
1219 1219
             }
@@ -1254,16 +1254,16 @@  discard block
 block discarded – undo
1254 1254
                                                  '',
1255 1255
                                                  'clear: both; margin: 1.5em 0 0; display: none;'
1256 1256
                                              );
1257
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1257
+        $registrations_to_apply_payment_to .= EEH_HTML::br().EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1258 1258
         $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1259 1259
         $registrations_to_apply_payment_to .= EEH_HTML::thead(
1260 1260
             EEH_HTML::tr(
1261
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1262
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1263
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1264
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1265
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1266
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1261
+                EEH_HTML::th(esc_html__('ID', 'event_espresso')).
1262
+                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')).
1263
+                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')).
1264
+                EEH_HTML::th(esc_html__('Event', 'event_espresso')).
1265
+                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr').
1266
+                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr').
1267 1267
                 EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1268 1268
             )
1269 1269
         );
@@ -1278,29 +1278,29 @@  discard block
 block discarded – undo
1278 1278
                     : esc_html__('Unknown Attendee', 'event_espresso');
1279 1279
                 $owing = $registration->final_price() - $registration->paid();
1280 1280
                 $taxable = $registration->ticket()->taxable()
1281
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1281
+                    ? ' <span class="smaller-text lt-grey-text"> '.esc_html__('+ tax', 'event_espresso').'</span>'
1282 1282
                     : '';
1283 1283
                 $checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1284 1284
                     ? ' checked="checked"'
1285 1285
                     : '';
1286 1286
                 $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1287 1287
                 $registrations_to_apply_payment_to .= EEH_HTML::tr(
1288
-                    EEH_HTML::td($registration->ID()) .
1289
-                    EEH_HTML::td($attendee_name) .
1288
+                    EEH_HTML::td($registration->ID()).
1289
+                    EEH_HTML::td($attendee_name).
1290 1290
                     EEH_HTML::td(
1291
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1292
-                    ) .
1293
-                    EEH_HTML::td($registration->event_name()) .
1294
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1295
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1291
+                        $registration->ticket()->name().' : '.$registration->ticket()->pretty_price().$taxable
1292
+                    ).
1293
+                    EEH_HTML::td($registration->event_name()).
1294
+                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr').
1295
+                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr').
1296 1296
                     EEH_HTML::td(
1297
-                        '<input type="checkbox" value="' . $registration->ID()
1297
+                        '<input type="checkbox" value="'.$registration->ID()
1298 1298
                         . '" name="txn_admin_payment[registrations]"'
1299
-                        . $checked . $disabled . '>',
1299
+                        . $checked.$disabled.'>',
1300 1300
                         '',
1301 1301
                         'jst-cntr'
1302 1302
                     ),
1303
-                    'apply-payment-registration-row-' . $registration->ID()
1303
+                    'apply-payment-registration-row-'.$registration->ID()
1304 1304
                 );
1305 1305
             }
1306 1306
         }
@@ -1381,12 +1381,12 @@  discard block
 block discarded – undo
1381 1381
                 array(
1382 1382
                     'OR*payment_method_for_payment' => array(
1383 1383
                         'PMD_ID'    => array('IN', $payment_methods_of_payments),
1384
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1384
+                        'PMD_scope' => array('LIKE', '%'.EEM_Payment_Method::scope_admin.'%'),
1385 1385
                     ),
1386 1386
                 ),
1387 1387
             );
1388 1388
         } else {
1389
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1389
+            $query_args = array(array('PMD_scope' => array('LIKE', '%'.EEM_Payment_Method::scope_admin.'%')));
1390 1390
         }
1391 1391
         $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1392 1392
     }
@@ -1415,7 +1415,7 @@  discard block
 block discarded – undo
1415 1415
             'Line_Item',
1416 1416
             array(array('LIN_type' => 'line-item'))
1417 1417
         );
1418
-        if (! empty($line_items)) {
1418
+        if ( ! empty($line_items)) {
1419 1419
             foreach ($line_items as $item) {
1420 1420
                 if ($item instanceof EE_Line_Item) {
1421 1421
                     switch ($item->OBJ_type()) {
@@ -1425,7 +1425,7 @@  discard block
 block discarded – undo
1425 1425
                             $ticket = $item->ticket();
1426 1426
                             // right now we're only handling tickets here.
1427 1427
                             // Cause its expected that only tickets will have attendees right?
1428
-                            if (! $ticket instanceof EE_Ticket) {
1428
+                            if ( ! $ticket instanceof EE_Ticket) {
1429 1429
                                 break;
1430 1430
                             }
1431 1431
                             try {
@@ -1434,7 +1434,7 @@  discard block
 block discarded – undo
1434 1434
                                 EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1435 1435
                                 $event_name = esc_html__('Unknown Event', 'event_espresso');
1436 1436
                             }
1437
-                            $event_name .= ' - ' . $item->get('LIN_name');
1437
+                            $event_name .= ' - '.$item->get('LIN_name');
1438 1438
                             $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1439 1439
                             // now get all of the registrations for this transaction that use this ticket
1440 1440
                             $registrations = $ticket->get_many_related(
@@ -1442,38 +1442,38 @@  discard block
 block discarded – undo
1442 1442
                                 array(array('TXN_ID' => $this->_transaction->ID()))
1443 1443
                             );
1444 1444
                             foreach ($registrations as $registration) {
1445
-                                if (! $registration instanceof EE_Registration) {
1445
+                                if ( ! $registration instanceof EE_Registration) {
1446 1446
                                     break;
1447 1447
                                 }
1448
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1448
+                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1449 1449
                                     = $registration->status_ID();
1450
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1450
+                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']
1451 1451
                                     = $registration->count();
1452
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1452
+                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1453 1453
                                     = $event_name;
1454
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1454
+                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1455 1455
                                     = $ticket_price;
1456 1456
                                 // attendee info
1457 1457
                                 $attendee = $registration->get_first_related('Attendee');
1458 1458
                                 if ($attendee instanceof EE_Attendee) {
1459
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1459
+                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']
1460 1460
                                         = $attendee->ID();
1461
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1461
+                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee']
1462 1462
                                         = $attendee->full_name();
1463
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1464
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1463
+                                    $this->_template_args['event_attendees'][$registration->ID()]['email']
1464
+                                        = '<a href="mailto:'.$attendee->email().'?subject='.$event_name
1465 1465
                                           . esc_html__(
1466 1466
                                               ' Event',
1467 1467
                                               'event_espresso'
1468 1468
                                           )
1469
-                                          . '">' . $attendee->email() . '</a>';
1470
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1469
+                                          . '">'.$attendee->email().'</a>';
1470
+                                    $this->_template_args['event_attendees'][$registration->ID()]['address']
1471 1471
                                         = EEH_Address::format($attendee, 'inline', false, false);
1472 1472
                                 } else {
1473
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1474
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1475
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1476
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1473
+                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id'] = '';
1474
+                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1475
+                                    $this->_template_args['event_attendees'][$registration->ID()]['email'] = '';
1476
+                                    $this->_template_args['event_attendees'][$registration->ID()]['address'] = '';
1477 1477
                                 }
1478 1478
                             }
1479 1479
                             break;
@@ -1489,7 +1489,7 @@  discard block
 block discarded – undo
1489 1489
                 TXN_ADMIN_URL
1490 1490
             );
1491 1491
             echo EEH_Template::display_template(
1492
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1492
+                TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_attendees.template.php',
1493 1493
                 $this->_template_args,
1494 1494
                 true
1495 1495
             );
@@ -1524,7 +1524,7 @@  discard block
 block discarded – undo
1524 1524
         $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1525 1525
             ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1526 1526
             : null;
1527
-        if (! $primary_att instanceof EE_Attendee) {
1527
+        if ( ! $primary_att instanceof EE_Attendee) {
1528 1528
             $this->_template_args['no_attendee_message'] = esc_html__(
1529 1529
                 'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1530 1530
                 'event_espresso'
@@ -1546,7 +1546,7 @@  discard block
 block discarded – undo
1546 1546
         // get formatted address for registrant
1547 1547
         $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1548 1548
         echo EEH_Template::display_template(
1549
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1549
+            TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_registrant.template.php',
1550 1550
             $this->_template_args,
1551 1551
             true
1552 1552
         );
@@ -1571,8 +1571,8 @@  discard block
 block discarded – undo
1571 1571
             TXN_ADMIN_URL
1572 1572
         );
1573 1573
 
1574
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1575
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1574
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_billing_info.template.php';
1575
+        echo EEH_Template::display_template($template_path, $this->_template_args, true); /**/
1576 1576
     }
1577 1577
 
1578 1578
 
@@ -1597,7 +1597,7 @@  discard block
 block discarded – undo
1597 1597
             'ee_edit_payments',
1598 1598
             'apply_payment_or_refund_from_registration_details'
1599 1599
         );
1600
-        if (! empty($valid_data) && $has_access) {
1600
+        if ( ! empty($valid_data) && $has_access) {
1601 1601
             $PAY_ID = $valid_data['PAY_ID'];
1602 1602
             // save  the new payment
1603 1603
             $payment = $this->_create_payment_from_request_data($valid_data);
@@ -1610,7 +1610,7 @@  discard block
 block discarded – undo
1610 1610
                 $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1611 1611
                 $this->_remove_existing_registration_payments($payment, $PAY_ID);
1612 1612
                 // apply payment to registrations (if applicable)
1613
-                if (! empty($REG_IDs)) {
1613
+                if ( ! empty($REG_IDs)) {
1614 1614
                     $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1615 1615
                     $this->_maybe_send_notifications();
1616 1616
                     // now process status changes for the same registrations
@@ -1680,14 +1680,14 @@  discard block
 block discarded – undo
1680 1680
      */
1681 1681
     protected function _validate_payment_request_data()
1682 1682
     {
1683
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1683
+        if ( ! isset($this->_req_data['txn_admin_payment'])) {
1684 1684
             return false;
1685 1685
         }
1686 1686
         $payment_form = $this->_generate_payment_form_section();
1687 1687
         try {
1688 1688
             if ($payment_form->was_submitted()) {
1689 1689
                 $payment_form->receive_form_submission();
1690
-                if (! $payment_form->is_valid()) {
1690
+                if ( ! $payment_form->is_valid()) {
1691 1691
                     $submission_error_messages = array();
1692 1692
                     foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1693 1693
                         if ($validation_error instanceof EE_Validation_Error) {
@@ -1866,7 +1866,7 @@  discard block
 block discarded – undo
1866 1866
             array('Y-m-d', 'g:i a')
1867 1867
         );
1868 1868
 
1869
-        if (! $payment->save()) {
1869
+        if ( ! $payment->save()) {
1870 1870
             EE_Error::add_error(
1871 1871
                 sprintf(
1872 1872
                     esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
@@ -2063,12 +2063,12 @@  discard block
 block discarded – undo
2063 2063
         // but add in some conditions regarding payment,
2064 2064
         // so that we don't apply payments to registrations that are free or have already been paid for
2065 2065
         // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2066
-        if (! $payment->is_a_refund()) {
2066
+        if ( ! $payment->is_a_refund()) {
2067 2067
             $registration_query_where_params['REG_final_price'] = array('!=', 0);
2068 2068
             $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2069 2069
         }
2070 2070
         $registrations = $transaction->registrations(array($registration_query_where_params));
2071
-        if (! empty($registrations)) {
2071
+        if ( ! empty($registrations)) {
2072 2072
             /** @type EE_Payment_Processor $payment_processor */
2073 2073
             $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2074 2074
             $payment_processor->process_registration_payments($transaction, $payment, $registrations);
@@ -2093,7 +2093,7 @@  discard block
 block discarded – undo
2093 2093
     protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2094 2094
     {
2095 2095
         // first if there is no change in status then we get out.
2096
-        if (! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2096
+        if ( ! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2097 2097
             || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2098 2098
         ) {
2099 2099
             // no error message, no change requested, just nothing to do man.
@@ -2151,7 +2151,7 @@  discard block
 block discarded – undo
2151 2151
                 'pay_status'       => $payment->STS_ID(),
2152 2152
                 'PAY_ID'           => $payment->ID(),
2153 2153
                 'STS_ID'           => $payment->STS_ID(),
2154
-                'status'           => self::$_pay_status[ $payment->STS_ID() ],
2154
+                'status'           => self::$_pay_status[$payment->STS_ID()],
2155 2155
                 'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2156 2156
                 'method'           => strtoupper($payment->source()),
2157 2157
                 'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
@@ -2273,11 +2273,11 @@  discard block
 block discarded – undo
2273 2273
     {
2274 2274
         $registration_payment_data = array();
2275 2275
         // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2276
-        if (! empty($REG_IDs)) {
2276
+        if ( ! empty($REG_IDs)) {
2277 2277
             $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2278 2278
             foreach ($registrations as $registration) {
2279 2279
                 if ($registration instanceof EE_Registration) {
2280
-                    $registration_payment_data[ $registration->ID() ] = array(
2280
+                    $registration_payment_data[$registration->ID()] = array(
2281 2281
                         'paid'  => $registration->pretty_paid(),
2282 2282
                         'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2283 2283
                     );
@@ -2389,8 +2389,8 @@  discard block
 block discarded – undo
2389 2389
             : date('m/d/Y');
2390 2390
 
2391 2391
         // make sure our timestamps start and end right at the boundaries for each day
2392
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2393
-        $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2392
+        $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
2393
+        $end_date = date('Y-m-d', strtotime($end_date)).' 23:59:59';
2394 2394
 
2395 2395
 
2396 2396
         // convert to timestamps
@@ -2449,7 +2449,7 @@  discard block
 block discarded – undo
2449 2449
         }
2450 2450
 
2451 2451
         if (isset($this->_req_data['s'])) {
2452
-            $search_string = '%' . $this->_req_data['s'] . '%';
2452
+            $search_string = '%'.$this->_req_data['s'].'%';
2453 2453
             $_where['OR'] = array(
2454 2454
                 'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2455 2455
                 'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
@@ -2476,11 +2476,11 @@  discard block
 block discarded – undo
2476 2476
         }
2477 2477
 
2478 2478
         // failed transactions
2479
-        $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2479
+        $failed = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2480 2480
                   || ($count && $view === 'failed');
2481
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2481
+        $abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2482 2482
                      || ($count && $view === 'abandoned');
2483
-        $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2483
+        $incomplete = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2484 2484
                       || ($count && $view === 'incomplete');
2485 2485
 
2486 2486
         if ($failed) {
Please login to merge, or discard this patch.
core/db_models/relations/EE_HABTM_Relation.php 2 patches
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -65,18 +65,18 @@  discard block
 block discarded – undo
65 65
         // remember the model relation chain to the JOIN model, because we'll
66 66
         // need it for get_join_statement()
67 67
         $this->_model_relation_chain_to_join_model = $model_relation_chain;
68
-        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field();// get_foreign_key_to($this->get_other_model()->get_this_model_name());
68
+        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field(); // get_foreign_key_to($this->get_other_model()->get_this_model_name());
69 69
         $join_table_fk_field_to_this_table         = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
70 70
         $this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
71 71
             $model_relation_chain,
72 72
             $this->get_this_model()->get_this_model_name()
73
-        ) . $this_table_pk_field->get_table_alias();
73
+        ).$this_table_pk_field->get_table_alias();
74 74
 
75 75
         $join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
76 76
             $model_relation_chain,
77 77
             $this->get_join_model()->get_this_model_name()
78
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
79
-        $join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
78
+        ).$join_table_fk_field_to_this_table->get_table_alias();
79
+        $join_table = $this->get_join_model()->get_table_for_alias($join_table_alias);
80 80
         // phew! ok, we have all the info we need, now we can create the SQL join string
81 81
         $SQL = $this->_left_join(
82 82
             $join_table,
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
             $join_table_fk_field_to_this_table->get_table_column(),
85 85
             $this_table_alias,
86 86
             $this_table_pk_field->get_table_column()
87
-        ) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
87
+        ).$this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
88 88
 
89 89
         return $SQL;
90 90
     }
@@ -113,14 +113,14 @@  discard block
 block discarded – undo
113 113
         $join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
114 114
             $this->_model_relation_chain_to_join_model,
115 115
             $this->get_join_model()->get_this_model_name()
116
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
116
+        ).$join_table_fk_field_to_this_table->get_table_alias();
117 117
         $other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
118 118
         $join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
119 119
         $other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
120 120
             $model_relation_chain,
121 121
             $this->get_other_model()->get_this_model_name()
122
-        ) . $other_table_pk_field->get_table_alias();
123
-        $other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
122
+        ).$other_table_pk_field->get_table_alias();
123
+        $other_table = $this->get_other_model()->get_table_for_alias($other_table_alias);
124 124
 
125 125
         $SQL = $this->_left_join(
126 126
             $other_table,
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
             $other_table_pk_field->get_table_column(),
129 129
             $join_table_alias,
130 130
             $join_table_fk_field_to_other_table->get_table_column()
131
-        ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
131
+        ).$this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
132 132
         return $SQL;
133 133
     }
134 134
 
@@ -161,17 +161,17 @@  discard block
 block discarded – undo
161 161
         );
162 162
 
163 163
         // if $where_query exists lets add them to the query_params.
164
-        if (! empty($extra_join_model_fields_n_values)) {
164
+        if ( ! empty($extra_join_model_fields_n_values)) {
165 165
             // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
166 166
             // make sure we strip THIS models name from the query param
167 167
             $parsed_query = array();
168 168
             foreach ($extra_join_model_fields_n_values as $query_param => $val) {
169
-                $query_param                = str_replace(
170
-                    $this->get_join_model()->get_this_model_name() . ".",
169
+                $query_param = str_replace(
170
+                    $this->get_join_model()->get_this_model_name().".",
171 171
                     "",
172 172
                     $query_param
173 173
                 );
174
-                $parsed_query[ $query_param ] = $val;
174
+                $parsed_query[$query_param] = $val;
175 175
             }
176 176
             $all_fields = array_merge($foreign_keys, $parsed_query);
177 177
         }
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
         // new row.
182 182
         // Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
183 183
         // the other tables) use the joining model directly!
184
-        if (! $existing_entry_in_join_table) {
184
+        if ( ! $existing_entry_in_join_table) {
185 185
             $this->get_join_model()->insert($all_fields);
186 186
         }
187 187
         return $other_model_obj;
@@ -212,17 +212,17 @@  discard block
 block discarded – undo
212 212
         );
213 213
 
214 214
         // if $where_query exists lets add them to the query_params.
215
-        if (! empty($where_query)) {
215
+        if ( ! empty($where_query)) {
216 216
             // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
217 217
             // make sure we strip THIS models name from the query param
218 218
             $parsed_query = array();
219 219
             foreach ($where_query as $query_param => $val) {
220
-                $query_param                = str_replace(
221
-                    $this->get_join_model()->get_this_model_name() . ".",
220
+                $query_param = str_replace(
221
+                    $this->get_join_model()->get_this_model_name().".",
222 222
                     "",
223 223
                     $query_param
224 224
                 );
225
-                $parsed_query[ $query_param ] = $val;
225
+                $parsed_query[$query_param] = $val;
226 226
             }
227 227
             $cols_n_values = array_merge($cols_n_values, $parsed_query);
228 228
         }
Please login to merge, or discard this patch.
Indentation   +234 added lines, -234 removed lines patch added patch discarded remove patch
@@ -9,261 +9,261 @@
 block discarded – undo
9 9
  */
10 10
 class EE_HABTM_Relation extends EE_Model_Relation_Base
11 11
 {
12
-    /**
13
-     * Model which defines the relation between two other models. Eg, the EE_Event_Question_Group model,
14
-     * which joins EE_Event and EE_Question_Group
15
-     *
16
-     * @var EEM_Base
17
-     */
18
-    protected $_joining_model_name;
12
+	/**
13
+	 * Model which defines the relation between two other models. Eg, the EE_Event_Question_Group model,
14
+	 * which joins EE_Event and EE_Question_Group
15
+	 *
16
+	 * @var EEM_Base
17
+	 */
18
+	protected $_joining_model_name;
19 19
 
20
-    protected $_model_relation_chain_to_join_model;
20
+	protected $_model_relation_chain_to_join_model;
21 21
 
22 22
 
23
-    /**
24
-     * Object representing the relationship between two models. HasAndBelongsToMany relations always use a join-table
25
-     * (and an ee joining-model.) This knows how to join the models,
26
-     * get related models across the relation, and add-and-remove the relationships.
27
-     *
28
-     * @param bool    $joining_model_name
29
-     * @param boolean $block_deletes                 for this type of relation, we block by default for now. if there
30
-     *                                               are related models across this relation, block (prevent and add an
31
-     *                                               error) the deletion of this model
32
-     * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
33
-     *                                               default
34
-     */
35
-    public function __construct($joining_model_name, $block_deletes = true, $blocking_delete_error_message = '')
36
-    {
37
-        $this->_joining_model_name = $joining_model_name;
38
-        parent::__construct($block_deletes, $blocking_delete_error_message);
39
-    }
23
+	/**
24
+	 * Object representing the relationship between two models. HasAndBelongsToMany relations always use a join-table
25
+	 * (and an ee joining-model.) This knows how to join the models,
26
+	 * get related models across the relation, and add-and-remove the relationships.
27
+	 *
28
+	 * @param bool    $joining_model_name
29
+	 * @param boolean $block_deletes                 for this type of relation, we block by default for now. if there
30
+	 *                                               are related models across this relation, block (prevent and add an
31
+	 *                                               error) the deletion of this model
32
+	 * @param string  $blocking_delete_error_message a customized error message on blocking deletes instead of the
33
+	 *                                               default
34
+	 */
35
+	public function __construct($joining_model_name, $block_deletes = true, $blocking_delete_error_message = '')
36
+	{
37
+		$this->_joining_model_name = $joining_model_name;
38
+		parent::__construct($block_deletes, $blocking_delete_error_message);
39
+	}
40 40
 
41
-    /**
42
-     * Gets the joining model's object
43
-     *
44
-     * @return EEM_Base
45
-     */
46
-    public function get_join_model()
47
-    {
48
-        return $this->_get_model($this->_joining_model_name);
49
-    }
41
+	/**
42
+	 * Gets the joining model's object
43
+	 *
44
+	 * @return EEM_Base
45
+	 */
46
+	public function get_join_model()
47
+	{
48
+		return $this->_get_model($this->_joining_model_name);
49
+	}
50 50
 
51 51
 
52
-    /**
53
-     * Gets the SQL string for joining the main model's table containing the pk to the join table. Eg "LEFT JOIN
54
-     * real_join_table AS join_table_alias ON this_table_alias.pk = join_table_alias.fk_to_this_table"
55
-     *
56
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
57
-     * @return string of SQL
58
-     * @throws \EE_Error
59
-     */
60
-    public function get_join_to_intermediate_model_statement($model_relation_chain)
61
-    {
62
-        // create sql like
63
-        // LEFT JOIN join_table AS join_table_alias ON this_table_alias.this_table_pk = join_table_alias.join_table_fk_to_this
64
-        // LEFT JOIN other_table AS other_table_alias ON join_table_alias.join_table_fk_to_other = other_table_alias.other_table_pk
65
-        // remember the model relation chain to the JOIN model, because we'll
66
-        // need it for get_join_statement()
67
-        $this->_model_relation_chain_to_join_model = $model_relation_chain;
68
-        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field();// get_foreign_key_to($this->get_other_model()->get_this_model_name());
69
-        $join_table_fk_field_to_this_table         = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
70
-        $this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
71
-            $model_relation_chain,
72
-            $this->get_this_model()->get_this_model_name()
73
-        ) . $this_table_pk_field->get_table_alias();
52
+	/**
53
+	 * Gets the SQL string for joining the main model's table containing the pk to the join table. Eg "LEFT JOIN
54
+	 * real_join_table AS join_table_alias ON this_table_alias.pk = join_table_alias.fk_to_this_table"
55
+	 *
56
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
57
+	 * @return string of SQL
58
+	 * @throws \EE_Error
59
+	 */
60
+	public function get_join_to_intermediate_model_statement($model_relation_chain)
61
+	{
62
+		// create sql like
63
+		// LEFT JOIN join_table AS join_table_alias ON this_table_alias.this_table_pk = join_table_alias.join_table_fk_to_this
64
+		// LEFT JOIN other_table AS other_table_alias ON join_table_alias.join_table_fk_to_other = other_table_alias.other_table_pk
65
+		// remember the model relation chain to the JOIN model, because we'll
66
+		// need it for get_join_statement()
67
+		$this->_model_relation_chain_to_join_model = $model_relation_chain;
68
+		$this_table_pk_field                       = $this->get_this_model()->get_primary_key_field();// get_foreign_key_to($this->get_other_model()->get_this_model_name());
69
+		$join_table_fk_field_to_this_table         = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
70
+		$this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
71
+			$model_relation_chain,
72
+			$this->get_this_model()->get_this_model_name()
73
+		) . $this_table_pk_field->get_table_alias();
74 74
 
75
-        $join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
76
-            $model_relation_chain,
77
-            $this->get_join_model()->get_this_model_name()
78
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
79
-        $join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
80
-        // phew! ok, we have all the info we need, now we can create the SQL join string
81
-        $SQL = $this->_left_join(
82
-            $join_table,
83
-            $join_table_alias,
84
-            $join_table_fk_field_to_this_table->get_table_column(),
85
-            $this_table_alias,
86
-            $this_table_pk_field->get_table_column()
87
-        ) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
75
+		$join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
76
+			$model_relation_chain,
77
+			$this->get_join_model()->get_this_model_name()
78
+		) . $join_table_fk_field_to_this_table->get_table_alias();
79
+		$join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
80
+		// phew! ok, we have all the info we need, now we can create the SQL join string
81
+		$SQL = $this->_left_join(
82
+			$join_table,
83
+			$join_table_alias,
84
+			$join_table_fk_field_to_this_table->get_table_column(),
85
+			$this_table_alias,
86
+			$this_table_pk_field->get_table_column()
87
+		) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
88 88
 
89
-        return $SQL;
90
-    }
89
+		return $SQL;
90
+	}
91 91
 
92 92
 
93
-    /**
94
-     * Gets the SQL string for joining the join table to the other model's pk's table. Eg "LEFT JOIN real_other_table
95
-     * AS other_table_alias ON join_table_alias.fk_to_other_table = other_table_alias.pk" If you want to join between
96
-     * modelA -> joinModelAB -> modelB (eg, Event -> Event_Question_Group -> Question_Group), you should prepend the
97
-     * result of this function with results from get_join_to_intermediate_model_statement(), so that you join first to
98
-     * the intermediate join table, and then to the other model's pk's table
99
-     *
100
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
101
-     * @return string of SQL
102
-     * @throws \EE_Error
103
-     */
104
-    public function get_join_statement($model_relation_chain)
105
-    {
106
-        if ($this->_model_relation_chain_to_join_model === null) {
107
-            throw new EE_Error(sprintf(__(
108
-                'When using EE_HABTM_Relation to create a join, you must call get_join_to_intermediate_model_statement BEFORE get_join_statement',
109
-                'event_espresso'
110
-            )));
111
-        }
112
-        $join_table_fk_field_to_this_table  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
113
-        $join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
114
-            $this->_model_relation_chain_to_join_model,
115
-            $this->get_join_model()->get_this_model_name()
116
-        ) . $join_table_fk_field_to_this_table->get_table_alias();
117
-        $other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
118
-        $join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
119
-        $other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
120
-            $model_relation_chain,
121
-            $this->get_other_model()->get_this_model_name()
122
-        ) . $other_table_pk_field->get_table_alias();
123
-        $other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
93
+	/**
94
+	 * Gets the SQL string for joining the join table to the other model's pk's table. Eg "LEFT JOIN real_other_table
95
+	 * AS other_table_alias ON join_table_alias.fk_to_other_table = other_table_alias.pk" If you want to join between
96
+	 * modelA -> joinModelAB -> modelB (eg, Event -> Event_Question_Group -> Question_Group), you should prepend the
97
+	 * result of this function with results from get_join_to_intermediate_model_statement(), so that you join first to
98
+	 * the intermediate join table, and then to the other model's pk's table
99
+	 *
100
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
101
+	 * @return string of SQL
102
+	 * @throws \EE_Error
103
+	 */
104
+	public function get_join_statement($model_relation_chain)
105
+	{
106
+		if ($this->_model_relation_chain_to_join_model === null) {
107
+			throw new EE_Error(sprintf(__(
108
+				'When using EE_HABTM_Relation to create a join, you must call get_join_to_intermediate_model_statement BEFORE get_join_statement',
109
+				'event_espresso'
110
+			)));
111
+		}
112
+		$join_table_fk_field_to_this_table  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
113
+		$join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
114
+			$this->_model_relation_chain_to_join_model,
115
+			$this->get_join_model()->get_this_model_name()
116
+		) . $join_table_fk_field_to_this_table->get_table_alias();
117
+		$other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
118
+		$join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
119
+		$other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
120
+			$model_relation_chain,
121
+			$this->get_other_model()->get_this_model_name()
122
+		) . $other_table_pk_field->get_table_alias();
123
+		$other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
124 124
 
125
-        $SQL = $this->_left_join(
126
-            $other_table,
127
-            $other_table_alias,
128
-            $other_table_pk_field->get_table_column(),
129
-            $join_table_alias,
130
-            $join_table_fk_field_to_other_table->get_table_column()
131
-        ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
132
-        return $SQL;
133
-    }
125
+		$SQL = $this->_left_join(
126
+			$other_table,
127
+			$other_table_alias,
128
+			$other_table_pk_field->get_table_column(),
129
+			$join_table_alias,
130
+			$join_table_fk_field_to_other_table->get_table_column()
131
+		) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
132
+		return $SQL;
133
+	}
134 134
 
135 135
 
136
-    /**
137
-     * Ensures there is an entry in the join table between these two models. Feel free to do this manually if you like.
138
-     * If the join table has additional columns (eg, the Event_Question_Group table has a is_primary column), then
139
-     * you'll want to directly use the EEM_Event_Question_Group model to add the entry to the table and set those extra
140
-     * columns' values
141
-     *
142
-     * @param EE_Base_Class|int $this_obj_or_id
143
-     * @param EE_Base_Class|int $other_obj_or_id
144
-     * @param array             $extra_join_model_fields_n_values col=>val pairs that are used as extra conditions for
145
-     *                                                            checking existing values and for setting new rows if
146
-     *                                                            no exact matches.
147
-     * @return EE_Base_Class
148
-     * @throws \EE_Error
149
-     */
150
-    public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
151
-    {
152
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
153
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
154
-        // check if such a relationship already exists
155
-        $join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
156
-        $join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
136
+	/**
137
+	 * Ensures there is an entry in the join table between these two models. Feel free to do this manually if you like.
138
+	 * If the join table has additional columns (eg, the Event_Question_Group table has a is_primary column), then
139
+	 * you'll want to directly use the EEM_Event_Question_Group model to add the entry to the table and set those extra
140
+	 * columns' values
141
+	 *
142
+	 * @param EE_Base_Class|int $this_obj_or_id
143
+	 * @param EE_Base_Class|int $other_obj_or_id
144
+	 * @param array             $extra_join_model_fields_n_values col=>val pairs that are used as extra conditions for
145
+	 *                                                            checking existing values and for setting new rows if
146
+	 *                                                            no exact matches.
147
+	 * @return EE_Base_Class
148
+	 * @throws \EE_Error
149
+	 */
150
+	public function add_relation_to($this_obj_or_id, $other_obj_or_id, $extra_join_model_fields_n_values = array())
151
+	{
152
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
153
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
154
+		// check if such a relationship already exists
155
+		$join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
156
+		$join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
157 157
 
158
-        $foreign_keys = $all_fields = array(
159
-            $join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
160
-            $join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
161
-        );
158
+		$foreign_keys = $all_fields = array(
159
+			$join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
160
+			$join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
161
+		);
162 162
 
163
-        // if $where_query exists lets add them to the query_params.
164
-        if (! empty($extra_join_model_fields_n_values)) {
165
-            // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
166
-            // make sure we strip THIS models name from the query param
167
-            $parsed_query = array();
168
-            foreach ($extra_join_model_fields_n_values as $query_param => $val) {
169
-                $query_param                = str_replace(
170
-                    $this->get_join_model()->get_this_model_name() . ".",
171
-                    "",
172
-                    $query_param
173
-                );
174
-                $parsed_query[ $query_param ] = $val;
175
-            }
176
-            $all_fields = array_merge($foreign_keys, $parsed_query);
177
-        }
163
+		// if $where_query exists lets add them to the query_params.
164
+		if (! empty($extra_join_model_fields_n_values)) {
165
+			// make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
166
+			// make sure we strip THIS models name from the query param
167
+			$parsed_query = array();
168
+			foreach ($extra_join_model_fields_n_values as $query_param => $val) {
169
+				$query_param                = str_replace(
170
+					$this->get_join_model()->get_this_model_name() . ".",
171
+					"",
172
+					$query_param
173
+				);
174
+				$parsed_query[ $query_param ] = $val;
175
+			}
176
+			$all_fields = array_merge($foreign_keys, $parsed_query);
177
+		}
178 178
 
179
-        $existing_entry_in_join_table = $this->get_join_model()->get_one(array($all_fields));
180
-        // If there is already an entry in the join table, indicating a relationship, update it instead of adding a
181
-        // new row.
182
-        // Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
183
-        // the other tables) use the joining model directly!
184
-        if (! $existing_entry_in_join_table) {
185
-            $this->get_join_model()->insert($all_fields);
186
-        }
187
-        return $other_model_obj;
188
-    }
179
+		$existing_entry_in_join_table = $this->get_join_model()->get_one(array($all_fields));
180
+		// If there is already an entry in the join table, indicating a relationship, update it instead of adding a
181
+		// new row.
182
+		// Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
183
+		// the other tables) use the joining model directly!
184
+		if (! $existing_entry_in_join_table) {
185
+			$this->get_join_model()->insert($all_fields);
186
+		}
187
+		return $other_model_obj;
188
+	}
189 189
 
190 190
 
191
-    /**
192
-     * Deletes any rows in the join table that have foreign keys matching the other model objects specified
193
-     *
194
-     * @param EE_Base_Class|int $this_obj_or_id
195
-     * @param EE_Base_Class|int $other_obj_or_id
196
-     * @param array             $where_query col=>val pairs that are used as extra conditions for checking existing
197
-     *                                       values and for removing existing rows if exact matches exist.
198
-     * @return EE_Base_Class
199
-     * @throws \EE_Error
200
-     */
201
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
202
-    {
203
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
204
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
205
-        // check if such a relationship already exists
206
-        $join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
207
-        $join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
191
+	/**
192
+	 * Deletes any rows in the join table that have foreign keys matching the other model objects specified
193
+	 *
194
+	 * @param EE_Base_Class|int $this_obj_or_id
195
+	 * @param EE_Base_Class|int $other_obj_or_id
196
+	 * @param array             $where_query col=>val pairs that are used as extra conditions for checking existing
197
+	 *                                       values and for removing existing rows if exact matches exist.
198
+	 * @return EE_Base_Class
199
+	 * @throws \EE_Error
200
+	 */
201
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, $where_query = array())
202
+	{
203
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
204
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
205
+		// check if such a relationship already exists
206
+		$join_model_fk_to_this_model  = $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
207
+		$join_model_fk_to_other_model = $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
208 208
 
209
-        $cols_n_values = array(
210
-            $join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
211
-            $join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
212
-        );
209
+		$cols_n_values = array(
210
+			$join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
211
+			$join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
212
+		);
213 213
 
214
-        // if $where_query exists lets add them to the query_params.
215
-        if (! empty($where_query)) {
216
-            // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
217
-            // make sure we strip THIS models name from the query param
218
-            $parsed_query = array();
219
-            foreach ($where_query as $query_param => $val) {
220
-                $query_param                = str_replace(
221
-                    $this->get_join_model()->get_this_model_name() . ".",
222
-                    "",
223
-                    $query_param
224
-                );
225
-                $parsed_query[ $query_param ] = $val;
226
-            }
227
-            $cols_n_values = array_merge($cols_n_values, $parsed_query);
228
-        }
214
+		// if $where_query exists lets add them to the query_params.
215
+		if (! empty($where_query)) {
216
+			// make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
217
+			// make sure we strip THIS models name from the query param
218
+			$parsed_query = array();
219
+			foreach ($where_query as $query_param => $val) {
220
+				$query_param                = str_replace(
221
+					$this->get_join_model()->get_this_model_name() . ".",
222
+					"",
223
+					$query_param
224
+				);
225
+				$parsed_query[ $query_param ] = $val;
226
+			}
227
+			$cols_n_values = array_merge($cols_n_values, $parsed_query);
228
+		}
229 229
 
230
-        $this->get_join_model()->delete(array($cols_n_values));
231
-        return $other_model_obj;
232
-    }
230
+		$this->get_join_model()->delete(array($cols_n_values));
231
+		return $other_model_obj;
232
+	}
233 233
 
234
-    /**
235
-     * Gets all the non-key fields (ie, not the primary key and not foreign keys) on the join model.
236
-     * @since 4.9.76.p
237
-     * @return EE_Model_Field_Base[]
238
-     * @throws EE_Error
239
-     */
240
-    public function getNonKeyFields()
241
-    {
242
-        // all fields besides the primary key and two foreign keys should be parameters
243
-        $join_model = $this->get_join_model();
244
-        $standard_fields = array();
245
-        if ($join_model->has_primary_key_field()) {
246
-            $standard_fields[] = $join_model->primary_key_name();
247
-        }
248
-        if ($this->get_this_model()->has_primary_key_field()) {
249
-            $standard_fields[] = $this->get_this_model()->primary_key_name();
250
-        }
251
-        if ($this->get_other_model()->has_primary_key_field()) {
252
-            $standard_fields[] = $this->get_other_model()->primary_key_name();
253
-        }
254
-        return array_diff_key(
255
-            $join_model->field_settings(),
256
-            array_flip($standard_fields)
257
-        );
258
-    }
234
+	/**
235
+	 * Gets all the non-key fields (ie, not the primary key and not foreign keys) on the join model.
236
+	 * @since 4.9.76.p
237
+	 * @return EE_Model_Field_Base[]
238
+	 * @throws EE_Error
239
+	 */
240
+	public function getNonKeyFields()
241
+	{
242
+		// all fields besides the primary key and two foreign keys should be parameters
243
+		$join_model = $this->get_join_model();
244
+		$standard_fields = array();
245
+		if ($join_model->has_primary_key_field()) {
246
+			$standard_fields[] = $join_model->primary_key_name();
247
+		}
248
+		if ($this->get_this_model()->has_primary_key_field()) {
249
+			$standard_fields[] = $this->get_this_model()->primary_key_name();
250
+		}
251
+		if ($this->get_other_model()->has_primary_key_field()) {
252
+			$standard_fields[] = $this->get_other_model()->primary_key_name();
253
+		}
254
+		return array_diff_key(
255
+			$join_model->field_settings(),
256
+			array_flip($standard_fields)
257
+		);
258
+	}
259 259
 
260
-    /**
261
-     * Returns true if the join model has non-key fields (ie, fields that aren't the primary key or foreign keys.)
262
-     * @since 4.9.76.p
263
-     * @return boolean
264
-     */
265
-    public function hasNonKeyFields()
266
-    {
267
-        return count($this->get_join_model()->field_settings()) > 3;
268
-    }
260
+	/**
261
+	 * Returns true if the join model has non-key fields (ie, fields that aren't the primary key or foreign keys.)
262
+	 * @since 4.9.76.p
263
+	 * @return boolean
264
+	 */
265
+	public function hasNonKeyFields()
266
+	{
267
+		return count($this->get_join_model()->field_settings()) > 3;
268
+	}
269 269
 }
Please login to merge, or discard this patch.
core/domain/entities/shortcodes/EspressoEventAttendees.php 1 patch
Indentation   +309 added lines, -309 removed lines patch added patch discarded remove patch
@@ -31,338 +31,338 @@
 block discarded – undo
31 31
 class EspressoEventAttendees extends EspressoShortcode
32 32
 {
33 33
 
34
-    private $query_params = array(
35
-        0 => array(),
36
-    );
34
+	private $query_params = array(
35
+		0 => array(),
36
+	);
37 37
 
38
-    private $template_args = array(
39
-        'contacts' => array(),
40
-        'event'    => null,
41
-        'datetime' => null,
42
-        'ticket'   => null,
43
-    );
38
+	private $template_args = array(
39
+		'contacts' => array(),
40
+		'event'    => null,
41
+		'datetime' => null,
42
+		'ticket'   => null,
43
+	);
44 44
 
45
-    /**
46
-     * the actual shortcode tag that gets registered with WordPress
47
-     *
48
-     * @return string
49
-     */
50
-    public function getTag()
51
-    {
52
-        return 'ESPRESSO_EVENT_ATTENDEES';
53
-    }
45
+	/**
46
+	 * the actual shortcode tag that gets registered with WordPress
47
+	 *
48
+	 * @return string
49
+	 */
50
+	public function getTag()
51
+	{
52
+		return 'ESPRESSO_EVENT_ATTENDEES';
53
+	}
54 54
 
55 55
 
56
-    /**
57
-     * the time in seconds to cache the results of the processShortcode() method
58
-     * 0 means the processShortcode() results will NOT be cached at all
59
-     *
60
-     * @return int
61
-     */
62
-    public function cacheExpiration()
63
-    {
64
-        return 0;
65
-    }
56
+	/**
57
+	 * the time in seconds to cache the results of the processShortcode() method
58
+	 * 0 means the processShortcode() results will NOT be cached at all
59
+	 *
60
+	 * @return int
61
+	 */
62
+	public function cacheExpiration()
63
+	{
64
+		return 0;
65
+	}
66 66
 
67 67
 
68
-    /**
69
-     * a place for adding any initialization code that needs to run prior to wp_header().
70
-     * this may be required for shortcodes that utilize a corresponding module,
71
-     * and need to enqueue assets for that module
72
-     *
73
-     * @return void
74
-     */
75
-    public function initializeShortcode()
76
-    {
77
-        $this->shortcodeHasBeenInitialized();
78
-    }
68
+	/**
69
+	 * a place for adding any initialization code that needs to run prior to wp_header().
70
+	 * this may be required for shortcodes that utilize a corresponding module,
71
+	 * and need to enqueue assets for that module
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public function initializeShortcode()
76
+	{
77
+		$this->shortcodeHasBeenInitialized();
78
+	}
79 79
 
80 80
 
81
-    /**
82
-     * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
83
-     *  [ESPRESSO_EVENT_ATTENDEES]
84
-     *  - defaults to attendees for earliest active event, or earliest upcoming event.
85
-     *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
86
-     *  - attendees for specific event.
87
-     *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
88
-     *  - attendees for a specific datetime.
89
-     *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
90
-     *  - attendees for a specific ticket.
91
-     *  [ESPRESSO_EVENT_ATTENDEES status=all]
92
-     *  - specific registration status (use status id) or all for all attendees regardless of status.
93
-     *  Note default is to only return approved attendees
94
-     *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
95
-     *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
96
-     *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
97
-     *  - default is to not display attendees list on archive pages.
98
-     * Note: because of the relationship between event_id, ticket_id, and datetime_id:
99
-     * If more than one of those params is included, then preference is given to the following:
100
-     *  - event_id is used whenever its present and any others are ignored.
101
-     *  - if no event_id then datetime is used whenever its present and any others are ignored.
102
-     *  - otherwise ticket_id is used if present.
103
-     *
104
-     * @param array $attributes
105
-     * @return string
106
-     * @throws EE_Error
107
-     * @throws InvalidDataTypeException
108
-     * @throws InvalidInterfaceException
109
-     * @throws InvalidArgumentException
110
-     * @throws DomainException
111
-     */
112
-    public function processShortcode($attributes = array())
113
-    {
114
-        // grab attributes and merge with defaults
115
-        $attributes = $this->getAttributes((array) $attributes);
116
-        $attributes['limit'] = (int) $attributes['limit'];
117
-        $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
118
-        // don't display on archives unless 'display_on_archives' is true
119
-        if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) {
120
-            return '';
121
-        }
122
-        try {
123
-            $this->setBaseTemplateArguments($attributes);
124
-            $this->validateEntities($attributes);
125
-            $this->setBaseQueryParams();
126
-        } catch (EntityNotFoundException $e) {
127
-            if (WP_DEBUG) {
128
-                return '<div class="important-notice ee-error">'
129
-                       . $e->getMessage()
130
-                       . '</div>';
131
-            }
132
-            return '';
133
-        }
134
-        $this->setAdditionalQueryParams($attributes);
135
-        // get contacts!
136
-        $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
137
-        // all set let's load up the template and return.
138
-        return EEH_Template::locate_template(
139
-            'loop-espresso_event_attendees.php',
140
-            $this->template_args
141
-        );
142
-    }
81
+	/**
82
+	 * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event.
83
+	 *  [ESPRESSO_EVENT_ATTENDEES]
84
+	 *  - defaults to attendees for earliest active event, or earliest upcoming event.
85
+	 *  [ESPRESSO_EVENT_ATTENDEES event_id=123]
86
+	 *  - attendees for specific event.
87
+	 *  [ESPRESSO_EVENT_ATTENDEES datetime_id=245]
88
+	 *  - attendees for a specific datetime.
89
+	 *  [ESPRESSO_EVENT_ATTENDEES ticket_id=123]
90
+	 *  - attendees for a specific ticket.
91
+	 *  [ESPRESSO_EVENT_ATTENDEES status=all]
92
+	 *  - specific registration status (use status id) or all for all attendees regardless of status.
93
+	 *  Note default is to only return approved attendees
94
+	 *  [ESPRESSO_EVENT_ATTENDEES show_gravatar=true]
95
+	 *  - default is to not return gravatar.  Otherwise if this is set then return gravatar for email address given.
96
+	 *  [ESPRESSO_EVENT_ATTENDEES display_on_archives=true]
97
+	 *  - default is to not display attendees list on archive pages.
98
+	 * Note: because of the relationship between event_id, ticket_id, and datetime_id:
99
+	 * If more than one of those params is included, then preference is given to the following:
100
+	 *  - event_id is used whenever its present and any others are ignored.
101
+	 *  - if no event_id then datetime is used whenever its present and any others are ignored.
102
+	 *  - otherwise ticket_id is used if present.
103
+	 *
104
+	 * @param array $attributes
105
+	 * @return string
106
+	 * @throws EE_Error
107
+	 * @throws InvalidDataTypeException
108
+	 * @throws InvalidInterfaceException
109
+	 * @throws InvalidArgumentException
110
+	 * @throws DomainException
111
+	 */
112
+	public function processShortcode($attributes = array())
113
+	{
114
+		// grab attributes and merge with defaults
115
+		$attributes = $this->getAttributes((array) $attributes);
116
+		$attributes['limit'] = (int) $attributes['limit'];
117
+		$display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN);
118
+		// don't display on archives unless 'display_on_archives' is true
119
+		if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) {
120
+			return '';
121
+		}
122
+		try {
123
+			$this->setBaseTemplateArguments($attributes);
124
+			$this->validateEntities($attributes);
125
+			$this->setBaseQueryParams();
126
+		} catch (EntityNotFoundException $e) {
127
+			if (WP_DEBUG) {
128
+				return '<div class="important-notice ee-error">'
129
+					   . $e->getMessage()
130
+					   . '</div>';
131
+			}
132
+			return '';
133
+		}
134
+		$this->setAdditionalQueryParams($attributes);
135
+		// get contacts!
136
+		$this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params);
137
+		// all set let's load up the template and return.
138
+		return EEH_Template::locate_template(
139
+			'loop-espresso_event_attendees.php',
140
+			$this->template_args
141
+		);
142
+	}
143 143
 
144 144
 
145
-    /**
146
-     * merge incoming attributes with filtered defaults
147
-     *
148
-     * @param array $attributes
149
-     * @return array
150
-     */
151
-    private function getAttributes(array $attributes)
152
-    {
153
-        return (array) apply_filters(
154
-            'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
155
-            $attributes + array(
156
-                'event_id'            => null,
157
-                'datetime_id'         => null,
158
-                'ticket_id'           => null,
159
-                'status'              => EEM_Registration::status_id_approved,
160
-                'show_gravatar'       => false,
161
-                'display_on_archives' => false,
162
-                'limit'               => 999,
163
-            )
164
-        );
165
-    }
145
+	/**
146
+	 * merge incoming attributes with filtered defaults
147
+	 *
148
+	 * @param array $attributes
149
+	 * @return array
150
+	 */
151
+	private function getAttributes(array $attributes)
152
+	{
153
+		return (array) apply_filters(
154
+			'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts',
155
+			$attributes + array(
156
+				'event_id'            => null,
157
+				'datetime_id'         => null,
158
+				'ticket_id'           => null,
159
+				'status'              => EEM_Registration::status_id_approved,
160
+				'show_gravatar'       => false,
161
+				'display_on_archives' => false,
162
+				'limit'               => 999,
163
+			)
164
+		);
165
+	}
166 166
 
167 167
 
168
-    /**
169
-     * Set all the base template arguments from the incoming attributes.
170
-     * * Note: because of the relationship between event_id, ticket_id, and datetime_id:
171
-     * If more than one of those params is included, then preference is given to the following:
172
-     *  - event_id is used whenever its present and any others are ignored.
173
-     *  - if no event_id then datetime is used whenever its present and any others are ignored.
174
-     *  - otherwise ticket_id is used if present.
175
-     *
176
-     * @param array $attributes
177
-     * @throws EE_Error
178
-     * @throws InvalidDataTypeException
179
-     * @throws InvalidInterfaceException
180
-     * @throws InvalidArgumentException
181
-     */
182
-    private function setBaseTemplateArguments(array $attributes)
183
-    {
184
-        $this->template_args['show_gravatar'] = $attributes['show_gravatar'];
185
-        $this->template_args['event'] = $this->getEvent($attributes);
186
-        $this->template_args['datetime'] = empty($attributes['event_id'])
187
-            ? $this->getDatetime($attributes)
188
-            : null;
189
-        $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id'])
190
-            ? $this->getTicket($attributes)
191
-            : null;
192
-    }
168
+	/**
169
+	 * Set all the base template arguments from the incoming attributes.
170
+	 * * Note: because of the relationship between event_id, ticket_id, and datetime_id:
171
+	 * If more than one of those params is included, then preference is given to the following:
172
+	 *  - event_id is used whenever its present and any others are ignored.
173
+	 *  - if no event_id then datetime is used whenever its present and any others are ignored.
174
+	 *  - otherwise ticket_id is used if present.
175
+	 *
176
+	 * @param array $attributes
177
+	 * @throws EE_Error
178
+	 * @throws InvalidDataTypeException
179
+	 * @throws InvalidInterfaceException
180
+	 * @throws InvalidArgumentException
181
+	 */
182
+	private function setBaseTemplateArguments(array $attributes)
183
+	{
184
+		$this->template_args['show_gravatar'] = $attributes['show_gravatar'];
185
+		$this->template_args['event'] = $this->getEvent($attributes);
186
+		$this->template_args['datetime'] = empty($attributes['event_id'])
187
+			? $this->getDatetime($attributes)
188
+			: null;
189
+		$this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id'])
190
+			? $this->getTicket($attributes)
191
+			: null;
192
+	}
193 193
 
194 194
 
195
-    /**
196
-     * Validates the presence of entities for the given attribute values.
197
-     *
198
-     * @param array $attributes
199
-     * @throws EntityNotFoundException
200
-     */
201
-    private function validateEntities(array $attributes)
202
-    {
203
-        if (! $this->template_args['event'] instanceof EE_Event
204
-            || (
205
-                empty($attributes['event_id'])
206
-                && $attributes['datetime_id']
207
-                && ! $this->template_args['datetime'] instanceof EE_Datetime
208
-            )
209
-            || (
210
-                empty($attributes['event_id'])
211
-                && empty($attributes['datetime_id'])
212
-                && $attributes['ticket_id']
213
-                && ! $this->template_args['ticket'] instanceof EE_Ticket
214
-            )
215
-        ) {
216
-            throw new EntityNotFoundException(
217
-                '',
218
-                '',
219
-                esc_html__(
220
-                    'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly.  Please double check the arguments you used for any typos.  In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.',
221
-                    'event_espresso'
222
-                )
223
-            );
224
-        }
225
-    }
195
+	/**
196
+	 * Validates the presence of entities for the given attribute values.
197
+	 *
198
+	 * @param array $attributes
199
+	 * @throws EntityNotFoundException
200
+	 */
201
+	private function validateEntities(array $attributes)
202
+	{
203
+		if (! $this->template_args['event'] instanceof EE_Event
204
+			|| (
205
+				empty($attributes['event_id'])
206
+				&& $attributes['datetime_id']
207
+				&& ! $this->template_args['datetime'] instanceof EE_Datetime
208
+			)
209
+			|| (
210
+				empty($attributes['event_id'])
211
+				&& empty($attributes['datetime_id'])
212
+				&& $attributes['ticket_id']
213
+				&& ! $this->template_args['ticket'] instanceof EE_Ticket
214
+			)
215
+		) {
216
+			throw new EntityNotFoundException(
217
+				'',
218
+				'',
219
+				esc_html__(
220
+					'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly.  Please double check the arguments you used for any typos.  In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.',
221
+					'event_espresso'
222
+				)
223
+			);
224
+		}
225
+	}
226 226
 
227 227
 
228
-    /**
229
-     * Sets the query params for the base query elements.
230
-     */
231
-    private function setBaseQueryParams()
232
-    {
233
-        switch (true) {
234
-            case $this->template_args['datetime'] instanceof EE_Datetime:
235
-                $this->query_params = array(
236
-                    0                          => array(
237
-                        'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(),
238
-                    ),
239
-                    'default_where_conditions' => 'this_model_only',
240
-                );
241
-                break;
242
-            case $this->template_args['ticket'] instanceof EE_Ticket:
243
-                $this->query_params[0] = array(
244
-                    'Registration.TKT_ID' => $this->template_args['ticket']->ID(),
245
-                );
246
-                break;
247
-            case $this->template_args['event'] instanceof EE_Event:
248
-                $this->query_params[0] = array(
249
-                    'Registration.EVT_ID' => $this->template_args['event']->ID(),
250
-                );
251
-                break;
252
-        }
253
-    }
228
+	/**
229
+	 * Sets the query params for the base query elements.
230
+	 */
231
+	private function setBaseQueryParams()
232
+	{
233
+		switch (true) {
234
+			case $this->template_args['datetime'] instanceof EE_Datetime:
235
+				$this->query_params = array(
236
+					0                          => array(
237
+						'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(),
238
+					),
239
+					'default_where_conditions' => 'this_model_only',
240
+				);
241
+				break;
242
+			case $this->template_args['ticket'] instanceof EE_Ticket:
243
+				$this->query_params[0] = array(
244
+					'Registration.TKT_ID' => $this->template_args['ticket']->ID(),
245
+				);
246
+				break;
247
+			case $this->template_args['event'] instanceof EE_Event:
248
+				$this->query_params[0] = array(
249
+					'Registration.EVT_ID' => $this->template_args['event']->ID(),
250
+				);
251
+				break;
252
+		}
253
+	}
254 254
 
255 255
 
256
-    /**
257
-     * @param array $attributes
258
-     * @return EE_Event|null
259
-     * @throws EE_Error
260
-     * @throws InvalidDataTypeException
261
-     * @throws InvalidInterfaceException
262
-     * @throws InvalidArgumentException
263
-     */
264
-    private function getEvent(array $attributes)
265
-    {
266
-        switch (true) {
267
-            case ! empty($attributes['event_id']):
268
-                $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
269
-                break;
270
-            case ! empty($attributes['datetime_id']):
271
-                $event = EEM_Event::instance()->get_one(array(
272
-                    array(
273
-                        'Datetime.DTT_ID' => $attributes['datetime_id'],
274
-                    ),
275
-                ));
276
-                break;
277
-            case ! empty($attributes['ticket_id']):
278
-                $event = EEM_Event::instance()->get_one(array(
279
-                    array(
280
-                        'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'],
281
-                    ),
282
-                    'default_where_conditions' => 'none'
283
-                ));
284
-                break;
285
-            case is_espresso_event():
286
-                $event = EEH_Event_View::get_event();
287
-                break;
288
-            default:
289
-                // one last shot...
290
-                // try getting the earliest active event
291
-                $events = EEM_Event::instance()->get_active_events(array(
292
-                    'limit'    => 1,
293
-                    'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
294
-                ));
295
-                //  if none then get the next upcoming
296
-                $events = empty($events)
297
-                    ? EEM_Event::instance()->get_upcoming_events(array(
298
-                        'limit'    => 1,
299
-                        'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
300
-                    ))
301
-                    : $events;
302
-                $event = reset($events);
303
-        }
256
+	/**
257
+	 * @param array $attributes
258
+	 * @return EE_Event|null
259
+	 * @throws EE_Error
260
+	 * @throws InvalidDataTypeException
261
+	 * @throws InvalidInterfaceException
262
+	 * @throws InvalidArgumentException
263
+	 */
264
+	private function getEvent(array $attributes)
265
+	{
266
+		switch (true) {
267
+			case ! empty($attributes['event_id']):
268
+				$event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']);
269
+				break;
270
+			case ! empty($attributes['datetime_id']):
271
+				$event = EEM_Event::instance()->get_one(array(
272
+					array(
273
+						'Datetime.DTT_ID' => $attributes['datetime_id'],
274
+					),
275
+				));
276
+				break;
277
+			case ! empty($attributes['ticket_id']):
278
+				$event = EEM_Event::instance()->get_one(array(
279
+					array(
280
+						'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'],
281
+					),
282
+					'default_where_conditions' => 'none'
283
+				));
284
+				break;
285
+			case is_espresso_event():
286
+				$event = EEH_Event_View::get_event();
287
+				break;
288
+			default:
289
+				// one last shot...
290
+				// try getting the earliest active event
291
+				$events = EEM_Event::instance()->get_active_events(array(
292
+					'limit'    => 1,
293
+					'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
294
+				));
295
+				//  if none then get the next upcoming
296
+				$events = empty($events)
297
+					? EEM_Event::instance()->get_upcoming_events(array(
298
+						'limit'    => 1,
299
+						'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'),
300
+					))
301
+					: $events;
302
+				$event = reset($events);
303
+		}
304 304
 
305
-        return $event instanceof EE_Event ? $event : null;
306
-    }
305
+		return $event instanceof EE_Event ? $event : null;
306
+	}
307 307
 
308 308
 
309
-    /**
310
-     * @param array $attributes
311
-     * @return EE_Datetime|null
312
-     * @throws EE_Error
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws InvalidArgumentException
316
-     */
317
-    private function getDatetime(array $attributes)
318
-    {
319
-        if (! empty($attributes['datetime_id'])) {
320
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
321
-            if ($datetime instanceof EE_Datetime) {
322
-                return $datetime;
323
-            }
324
-        }
325
-        return null;
326
-    }
309
+	/**
310
+	 * @param array $attributes
311
+	 * @return EE_Datetime|null
312
+	 * @throws EE_Error
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws InvalidArgumentException
316
+	 */
317
+	private function getDatetime(array $attributes)
318
+	{
319
+		if (! empty($attributes['datetime_id'])) {
320
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']);
321
+			if ($datetime instanceof EE_Datetime) {
322
+				return $datetime;
323
+			}
324
+		}
325
+		return null;
326
+	}
327 327
 
328 328
 
329
-    /**
330
-     * @param array $attributes
331
-     * @return \EE_Base_Class|EE_Ticket|null
332
-     * @throws EE_Error
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     * @throws InvalidArgumentException
336
-     */
337
-    private function getTicket(array $attributes)
338
-    {
339
-        if (! empty($attributes['ticket_id'])) {
340
-            $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
341
-            if ($ticket instanceof EE_Ticket) {
342
-                return $ticket;
343
-            }
344
-        }
345
-        return null;
346
-    }
329
+	/**
330
+	 * @param array $attributes
331
+	 * @return \EE_Base_Class|EE_Ticket|null
332
+	 * @throws EE_Error
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws InvalidArgumentException
336
+	 */
337
+	private function getTicket(array $attributes)
338
+	{
339
+		if (! empty($attributes['ticket_id'])) {
340
+			$ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']);
341
+			if ($ticket instanceof EE_Ticket) {
342
+				return $ticket;
343
+			}
344
+		}
345
+		return null;
346
+	}
347 347
 
348 348
 
349
-    /**
350
-     * @param array $attributes
351
-     * @throws EE_Error
352
-     */
353
-    private function setAdditionalQueryParams(array $attributes)
354
-    {
355
-        $reg_status_array = EEM_Registration::reg_status_array();
356
-        if (isset($reg_status_array[ $attributes['status'] ])) {
357
-            $this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
358
-        }
359
-        if (absint($attributes['limit'])) {
360
-            $this->query_params['limit'] = $attributes['limit'];
361
-        }
362
-        $this->query_params['group_by'] = array('ATT_ID');
363
-        $this->query_params['order_by'] = (array) apply_filters(
364
-            'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
365
-            array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
366
-        );
367
-    }
349
+	/**
350
+	 * @param array $attributes
351
+	 * @throws EE_Error
352
+	 */
353
+	private function setAdditionalQueryParams(array $attributes)
354
+	{
355
+		$reg_status_array = EEM_Registration::reg_status_array();
356
+		if (isset($reg_status_array[ $attributes['status'] ])) {
357
+			$this->query_params[0]['Registration.STS_ID'] = $attributes['status'];
358
+		}
359
+		if (absint($attributes['limit'])) {
360
+			$this->query_params['limit'] = $attributes['limit'];
361
+		}
362
+		$this->query_params['group_by'] = array('ATT_ID');
363
+		$this->query_params['order_by'] = (array) apply_filters(
364
+			'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by',
365
+			array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC')
366
+		);
367
+	}
368 368
 }
Please login to merge, or discard this patch.
core/domain/services/assets/CoreAssetManager.php 1 patch
Indentation   +531 added lines, -531 removed lines patch added patch discarded remove patch
@@ -31,554 +31,554 @@
 block discarded – undo
31 31
 class CoreAssetManager extends AssetManager
32 32
 {
33 33
 
34
-    // WordPress core / Third party JS asset handles
35
-    const JS_HANDLE_JQUERY = 'jquery';
34
+	// WordPress core / Third party JS asset handles
35
+	const JS_HANDLE_JQUERY = 'jquery';
36 36
 
37
-    const JS_HANDLE_JQUERY_VALIDATE = 'jquery-validate';
37
+	const JS_HANDLE_JQUERY_VALIDATE = 'jquery-validate';
38 38
 
39
-    const JS_HANDLE_JQUERY_VALIDATE_EXTRA = 'jquery-validate-extra-methods';
39
+	const JS_HANDLE_JQUERY_VALIDATE_EXTRA = 'jquery-validate-extra-methods';
40 40
 
41
-    const JS_HANDLE_UNDERSCORE = 'underscore';
41
+	const JS_HANDLE_UNDERSCORE = 'underscore';
42 42
 
43
-    const JS_HANDLE_ACCOUNTING_CORE = 'ee-accounting-core';
43
+	const JS_HANDLE_ACCOUNTING_CORE = 'ee-accounting-core';
44 44
 
45
-    /**
46
-     * @since 4.9.71.p
47
-     */
48
-    const JS_HANDLE_REACT = 'react';
45
+	/**
46
+	 * @since 4.9.71.p
47
+	 */
48
+	const JS_HANDLE_REACT = 'react';
49 49
 
50
-    /**
51
-     * @since 4.9.71.p
52
-     */
53
-    const JS_HANDLE_REACT_DOM = 'react-dom';
50
+	/**
51
+	 * @since 4.9.71.p
52
+	 */
53
+	const JS_HANDLE_REACT_DOM = 'react-dom';
54 54
 
55
-    /**
56
-     * @since 4.9.71.p
57
-     */
58
-    const JS_HANDLE_LODASH = 'lodash';
55
+	/**
56
+	 * @since 4.9.71.p
57
+	 */
58
+	const JS_HANDLE_LODASH = 'lodash';
59 59
 
60
-    // EE JS assets handles
61
-    const JS_HANDLE_MANIFEST = 'ee-manifest';
60
+	// EE JS assets handles
61
+	const JS_HANDLE_MANIFEST = 'ee-manifest';
62 62
 
63
-    const JS_HANDLE_JS_CORE = 'eejs-core';
63
+	const JS_HANDLE_JS_CORE = 'eejs-core';
64 64
 
65
-    const JS_HANDLE_VENDOR = 'eventespresso-vendor';
65
+	const JS_HANDLE_VENDOR = 'eventespresso-vendor';
66 66
 
67
-    const JS_HANDLE_DATA_STORES = 'eventespresso-data-stores';
67
+	const JS_HANDLE_DATA_STORES = 'eventespresso-data-stores';
68 68
 
69
-    const JS_HANDLE_HELPERS = 'eventespresso-helpers';
69
+	const JS_HANDLE_HELPERS = 'eventespresso-helpers';
70 70
 
71
-    const JS_HANDLE_MODEL = 'eventespresso-model';
71
+	const JS_HANDLE_MODEL = 'eventespresso-model';
72 72
 
73
-    const JS_HANDLE_VALUE_OBJECTS = 'eventespresso-value-objects';
73
+	const JS_HANDLE_VALUE_OBJECTS = 'eventespresso-value-objects';
74 74
 
75
-    const JS_HANDLE_HOCS = 'eventespresso-hocs';
75
+	const JS_HANDLE_HOCS = 'eventespresso-hocs';
76 76
 
77
-    const JS_HANDLE_COMPONENTS = 'eventespresso-components';
78
-
79
-    const JS_HANDLE_EDITOR_HOCS = 'eventespresso-editor-hocs';
77
+	const JS_HANDLE_COMPONENTS = 'eventespresso-components';
78
+
79
+	const JS_HANDLE_EDITOR_HOCS = 'eventespresso-editor-hocs';
80 80
 
81
-    const JS_HANDLE_VALIDATORS = 'eventespresso-validators';
81
+	const JS_HANDLE_VALIDATORS = 'eventespresso-validators';
82 82
 
83
-    const JS_HANDLE_CORE = 'espresso_core';
83
+	const JS_HANDLE_CORE = 'espresso_core';
84 84
 
85
-    const JS_HANDLE_I18N = 'eei18n';
86
-
87
-    const JS_HANDLE_ACCOUNTING = 'ee-accounting';
88
-
89
-    const JS_HANDLE_WP_PLUGINS_PAGE = 'ee-wp-plugins-page';
90
-
91
-    // EE CSS assets handles
92
-    const CSS_HANDLE_DEFAULT = 'espresso_default';
93
-
94
-    const CSS_HANDLE_CUSTOM = 'espresso_custom_css';
95
-
96
-    const CSS_HANDLE_COMPONENTS = 'eventespresso-components';
97
-
98
-    /**
99
-     * @var EE_Currency_Config $currency_config
100
-     */
101
-    protected $currency_config;
102
-
103
-    /**
104
-     * @var EE_Template_Config $template_config
105
-     */
106
-    protected $template_config;
107
-
108
-
109
-    /**
110
-     * CoreAssetRegister constructor.
111
-     *
112
-     * @param AssetCollection    $assets
113
-     * @param EE_Currency_Config $currency_config
114
-     * @param EE_Template_Config $template_config
115
-     * @param DomainInterface    $domain
116
-     * @param Registry           $registry
117
-     */
118
-    public function __construct(
119
-        AssetCollection $assets,
120
-        EE_Currency_Config $currency_config,
121
-        EE_Template_Config $template_config,
122
-        DomainInterface $domain,
123
-        Registry $registry
124
-    ) {
125
-        $this->currency_config = $currency_config;
126
-        $this->template_config = $template_config;
127
-        parent::__construct($domain, $assets, $registry);
128
-    }
129
-
130
-
131
-    /**
132
-     * @since 4.9.62.p
133
-     * @throws DomainException
134
-     * @throws DuplicateCollectionIdentifierException
135
-     * @throws InvalidArgumentException
136
-     * @throws InvalidDataTypeException
137
-     * @throws InvalidEntityException
138
-     * @throws InvalidInterfaceException
139
-     */
140
-    public function addAssets()
141
-    {
142
-        $this->addJavascriptFiles();
143
-        $this->addStylesheetFiles();
144
-    }
145
-
146
-
147
-    /**
148
-     * @since 4.9.62.p
149
-     * @throws DomainException
150
-     * @throws DuplicateCollectionIdentifierException
151
-     * @throws InvalidArgumentException
152
-     * @throws InvalidDataTypeException
153
-     * @throws InvalidEntityException
154
-     * @throws InvalidInterfaceException
155
-     */
156
-    public function addJavascriptFiles()
157
-    {
158
-        $this->loadCoreJs();
159
-        $this->loadJqueryValidate();
160
-        $this->loadAccountingJs();
161
-        add_action(
162
-            'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__before_script',
163
-            array($this, 'loadQtipJs')
164
-        );
165
-        $this->registerAdminAssets();
166
-    }
167
-
168
-
169
-    /**
170
-     * @since 4.9.62.p
171
-     * @throws DuplicateCollectionIdentifierException
172
-     * @throws InvalidDataTypeException
173
-     * @throws InvalidEntityException
174
-     */
175
-    public function addStylesheetFiles()
176
-    {
177
-        $this->loadCoreCss();
178
-    }
179
-
180
-
181
-    /**
182
-     * core default javascript
183
-     *
184
-     * @since 4.9.62.p
185
-     * @throws DomainException
186
-     * @throws DuplicateCollectionIdentifierException
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidEntityException
190
-     * @throws InvalidInterfaceException
191
-     */
192
-    private function loadCoreJs()
193
-    {
194
-        // conditionally load third-party libraries that WP core MIGHT have.
195
-        $this->registerWpAssets();
196
-
197
-        $this->addJavascript(
198
-            CoreAssetManager::JS_HANDLE_MANIFEST,
199
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'manifest')
200
-        );
201
-
202
-        $this->addJavascript(
203
-            CoreAssetManager::JS_HANDLE_JS_CORE,
204
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'eejs'),
205
-            array(CoreAssetManager::JS_HANDLE_MANIFEST)
206
-        )
207
-        ->setHasInlineData();
208
-
209
-        $this->addJavascript(
210
-            CoreAssetManager::JS_HANDLE_VENDOR,
211
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'vendor'),
212
-            array(
213
-                CoreAssetManager::JS_HANDLE_JS_CORE,
214
-                CoreAssetManager::JS_HANDLE_REACT,
215
-                CoreAssetManager::JS_HANDLE_REACT_DOM,
216
-                CoreAssetManager::JS_HANDLE_LODASH,
217
-            )
218
-        );
219
-
220
-        $this->addJavascript(
221
-            CoreAssetManager::JS_HANDLE_VALIDATORS,
222
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'validators')
223
-        )->setRequiresTranslation();
224
-
225
-        $this->addJavascript(
226
-            CoreAssetManager::JS_HANDLE_HELPERS,
227
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'helpers'),
228
-            array(
229
-                CoreAssetManager::JS_HANDLE_VALIDATORS
230
-            )
231
-        )->setRequiresTranslation();
232
-
233
-        $this->addJavascript(
234
-            CoreAssetManager::JS_HANDLE_MODEL,
235
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'model'),
236
-            array(
237
-                CoreAssetManager::JS_HANDLE_HELPERS
238
-            )
239
-        )->setRequiresTranslation();
240
-
241
-        $this->addJavascript(
242
-            CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
243
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'valueObjects'),
244
-            array(
245
-                CoreAssetManager::JS_HANDLE_MODEL
246
-            )
247
-        )->setRequiresTranslation();
248
-
249
-        $this->addJavascript(
250
-            CoreAssetManager::JS_HANDLE_DATA_STORES,
251
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'data-stores'),
252
-            array(
253
-                CoreAssetManager::JS_HANDLE_VENDOR,
254
-                'wp-data',
255
-                'wp-api-fetch',
256
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS
257
-            )
258
-        )
259
-             ->setRequiresTranslation()
260
-             ->setInlineDataCallback(
261
-                 function() {
262
-                     wp_add_inline_script(
263
-                         CoreAssetManager::JS_HANDLE_DATA_STORES,
264
-                         is_admin()
265
-                             ? 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware( eejs.middleWares.apiFetch.CONTEXT_CAPS_EDIT ) )'
266
-                             : 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware )'
267
-                     );
268
-                 }
269
-             );
270
-
271
-        $this->addJavascript(
272
-            CoreAssetManager::JS_HANDLE_HOCS,
273
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'hocs'),
274
-            array(
275
-                CoreAssetManager::JS_HANDLE_DATA_STORES,
276
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
277
-                'wp-components',
278
-            )
279
-        )->setRequiresTranslation();
280
-
281
-        $this->addJavascript(
282
-            CoreAssetManager::JS_HANDLE_COMPONENTS,
283
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'components'),
284
-            array(
285
-                CoreAssetManager::JS_HANDLE_DATA_STORES,
286
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
287
-                'wp-components',
288
-            )
289
-        )
290
-        ->setRequiresTranslation();
291
-
292
-        $this->addJavascript(
293
-            CoreAssetManager::JS_HANDLE_EDITOR_HOCS,
294
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'editor-hocs'),
295
-            array(
296
-                CoreAssetManager::JS_HANDLE_COMPONENTS
297
-            )
298
-        )->setRequiresTranslation();
299
-
300
-        $this->registry->addData('eejs_api_nonce', wp_create_nonce('wp_rest'));
301
-        $this->registry->addData(
302
-            'paths',
303
-            array(
304
-                'base_rest_route' => rest_url(),
305
-                'rest_route' => rest_url('ee/v4.8.36/'),
306
-                'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName(),
307
-                'primary_keys' => EED_Core_Rest_Api::getPrimaryKeyNamesIndexedByModelName(),
308
-                'site_url' => site_url('/'),
309
-                'admin_url' => admin_url('/'),
310
-            )
311
-        );
312
-        /** site formatting values **/
313
-        $this->registry->addData(
314
-            'site_formats',
315
-            array(
316
-                'date_formats' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats()
317
-            )
318
-        );
319
-        /** currency data **/
320
-        $this->registry->addData(
321
-            'currency_config',
322
-            $this->getCurrencySettings()
323
-        );
324
-        /** site timezone */
325
-        $this->registry->addData(
326
-            'default_timezone',
327
-            array(
328
-                'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
329
-                'string' => get_option('timezone_string'),
330
-                'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
331
-            )
332
-        );
333
-        /** site locale (user locale if user logged in) */
334
-        $this->registry->addData(
335
-            'locale',
336
-            array(
337
-                'user' => get_user_locale(),
338
-                'site' => get_locale()
339
-            )
340
-        );
341
-
342
-        $this->addJavascript(
343
-            CoreAssetManager::JS_HANDLE_CORE,
344
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
345
-            array(CoreAssetManager::JS_HANDLE_JQUERY)
346
-        )
347
-        ->setInlineDataCallback(
348
-            function () {
349
-                wp_localize_script(
350
-                    CoreAssetManager::JS_HANDLE_CORE,
351
-                    CoreAssetManager::JS_HANDLE_I18N,
352
-                    EE_Registry::$i18n_js_strings
353
-                );
354
-            }
355
-        );
356
-    }
357
-
358
-
359
-    /**
360
-     * Registers vendor files that are bundled with a later version WP but might not be for the current version of
361
-     * WordPress in the running environment.
362
-     *
363
-     * @throws DuplicateCollectionIdentifierException
364
-     * @throws InvalidDataTypeException
365
-     * @throws InvalidEntityException
366
-     * @throws DomainException
367
-     * @since 4.9.71.p
368
-     */
369
-    private function registerWpAssets()
370
-    {
371
-        global $wp_version;
372
-        if (version_compare($wp_version, '5.0.beta', '>=')) {
373
-            return;
374
-        }
375
-        $this->addVendorJavascript(CoreAssetManager::JS_HANDLE_REACT)
376
-            ->setVersion('16.6.0');
377
-        $this->addVendorJavascript(
378
-            CoreAssetManager::JS_HANDLE_REACT_DOM,
379
-            array(CoreAssetManager::JS_HANDLE_REACT)
380
-        )->setVersion('16.6.0');
381
-        $this->addVendorJavascript(CoreAssetManager::JS_HANDLE_LODASH)
382
-            ->setInlineDataCallback(
383
-                function() {
384
-                    wp_add_inline_script(
385
-                        CoreAssetManager::JS_HANDLE_LODASH,
386
-                        'window.lodash = _.noConflict();'
387
-                    );
388
-                }
389
-            )
390
-            ->setVersion('4.17.11');
391
-    }
392
-
393
-
394
-    /**
395
-     * Returns configuration data for the accounting-js library.
396
-     * @since 4.9.71.p
397
-     * @return array
398
-     */
399
-    private function getAccountingSettings() {
400
-        return array(
401
-            'currency' => array(
402
-                'symbol'    => $this->currency_config->sign,
403
-                'format'    => array(
404
-                    'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
405
-                    'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
406
-                    'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
407
-                ),
408
-                'decimal'   => $this->currency_config->dec_mrk,
409
-                'thousand'  => $this->currency_config->thsnds,
410
-                'precision' => $this->currency_config->dec_plc,
411
-            ),
412
-            'number'   => array(
413
-                'precision' => $this->currency_config->dec_plc,
414
-                'thousand'  => $this->currency_config->thsnds,
415
-                'decimal'   => $this->currency_config->dec_mrk,
416
-            ),
417
-        );
418
-    }
419
-
420
-
421
-    /**
422
-     * Returns configuration data for the js Currency VO.
423
-     * @since 4.9.71.p
424
-     * @return array
425
-     */
426
-    private function getCurrencySettings()
427
-    {
428
-        return array(
429
-            'code' => $this->currency_config->code,
430
-            'singularLabel' => $this->currency_config->name,
431
-            'pluralLabel' => $this->currency_config->plural,
432
-            'sign' => $this->currency_config->sign,
433
-            'signB4' => $this->currency_config->sign_b4,
434
-            'decimalPlaces' => $this->currency_config->dec_plc,
435
-            'decimalMark' => $this->currency_config->dec_mrk,
436
-            'thousandsSeparator' => $this->currency_config->thsnds,
437
-        );
438
-    }
439
-
440
-
441
-    /**
442
-     * @since 4.9.62.p
443
-     * @throws DuplicateCollectionIdentifierException
444
-     * @throws InvalidDataTypeException
445
-     * @throws InvalidEntityException
446
-     */
447
-    private function loadCoreCss()
448
-    {
449
-        if ($this->template_config->enable_default_style && ! is_admin()) {
450
-            $this->addStylesheet(
451
-                CoreAssetManager::CSS_HANDLE_DEFAULT,
452
-                is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
453
-                    ? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
454
-                    : EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
455
-                array('dashicons')
456
-            );
457
-            //Load custom style sheet if available
458
-            if ($this->template_config->custom_style_sheet !== null) {
459
-                $this->addStylesheet(
460
-                    CoreAssetManager::CSS_HANDLE_CUSTOM,
461
-                    EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
462
-                    array(CoreAssetManager::CSS_HANDLE_DEFAULT)
463
-                );
464
-            }
465
-        }
466
-        $this->addStylesheet(
467
-            CoreAssetManager::CSS_HANDLE_COMPONENTS,
468
-            $this->registry->getCssUrl(
469
-                $this->domain->assetNamespace(),
470
-                'components'
471
-            )
472
-        );
473
-    }
474
-
475
-
476
-    /**
477
-     * jQuery Validate for form validation
478
-     *
479
-     * @since 4.9.62.p
480
-     * @throws DomainException
481
-     * @throws DuplicateCollectionIdentifierException
482
-     * @throws InvalidDataTypeException
483
-     * @throws InvalidEntityException
484
-     */
485
-    private function loadJqueryValidate()
486
-    {
487
-        $this->addJavascript(
488
-            CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE,
489
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
490
-            array(CoreAssetManager::JS_HANDLE_JQUERY)
491
-        )
492
-        ->setVersion('1.15.0');
493
-
494
-        $this->addJavascript(
495
-            CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE_EXTRA,
496
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
497
-            array(CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE)
498
-        )
499
-        ->setVersion('1.15.0');
500
-    }
501
-
502
-
503
-    /**
504
-     * accounting.js for performing client-side calculations
505
-     *
506
-     * @since 4.9.62.p
507
-     * @throws DomainException
508
-     * @throws DuplicateCollectionIdentifierException
509
-     * @throws InvalidDataTypeException
510
-     * @throws InvalidEntityException
511
-     */
512
-    private function loadAccountingJs()
513
-    {
514
-        //accounting.js library
515
-        // @link http://josscrowcroft.github.io/accounting.js/
516
-        $this->addJavascript(
517
-            CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE,
518
-            EE_THIRD_PARTY_URL . 'accounting/accounting.js',
519
-            array(CoreAssetManager::JS_HANDLE_UNDERSCORE)
520
-        )
521
-        ->setVersion('0.3.2');
522
-
523
-        $this->addJavascript(
524
-            CoreAssetManager::JS_HANDLE_ACCOUNTING,
525
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
526
-            array(CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE)
527
-        )
528
-        ->setInlineDataCallback(
529
-            function () {
530
-                 wp_localize_script(
531
-                     CoreAssetManager::JS_HANDLE_ACCOUNTING,
532
-                     'EE_ACCOUNTING_CFG',
533
-                     $this->getAccountingSettings()
534
-                 );
535
-            }
536
-        )
537
-        ->setVersion();
538
-    }
539
-
540
-
541
-    /**
542
-     * registers assets for cleaning your ears
543
-     *
544
-     * @param JavascriptAsset $script
545
-     */
546
-    public function loadQtipJs(JavascriptAsset $script)
547
-    {
548
-        // qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
549
-        // can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
550
-        if (
551
-            $script->handle() === CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE
552
-            && apply_filters('FHEE_load_qtip', false)
553
-        ) {
554
-            EEH_Qtip_Loader::instance()->register_and_enqueue();
555
-        }
556
-    }
557
-
558
-
559
-    /**
560
-     * assets that are used in the WordPress admin
561
-     *
562
-     * @since 4.9.62.p
563
-     * @throws DuplicateCollectionIdentifierException
564
-     * @throws InvalidDataTypeException
565
-     * @throws InvalidEntityException
566
-     */
567
-    private function registerAdminAssets()
568
-    {
569
-        $this->addJavascript(
570
-            CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
571
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'wp-plugins-page'),
572
-            array(
573
-                CoreAssetManager::JS_HANDLE_JQUERY,
574
-                CoreAssetManager::JS_HANDLE_VENDOR,
575
-            )
576
-        )
577
-        ->setRequiresTranslation();
578
-
579
-        $this->addStylesheet(
580
-            CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
581
-            $this->registry->getCssUrl($this->domain->assetNamespace(), 'wp-plugins-page')
582
-        );
583
-    }
85
+	const JS_HANDLE_I18N = 'eei18n';
86
+
87
+	const JS_HANDLE_ACCOUNTING = 'ee-accounting';
88
+
89
+	const JS_HANDLE_WP_PLUGINS_PAGE = 'ee-wp-plugins-page';
90
+
91
+	// EE CSS assets handles
92
+	const CSS_HANDLE_DEFAULT = 'espresso_default';
93
+
94
+	const CSS_HANDLE_CUSTOM = 'espresso_custom_css';
95
+
96
+	const CSS_HANDLE_COMPONENTS = 'eventespresso-components';
97
+
98
+	/**
99
+	 * @var EE_Currency_Config $currency_config
100
+	 */
101
+	protected $currency_config;
102
+
103
+	/**
104
+	 * @var EE_Template_Config $template_config
105
+	 */
106
+	protected $template_config;
107
+
108
+
109
+	/**
110
+	 * CoreAssetRegister constructor.
111
+	 *
112
+	 * @param AssetCollection    $assets
113
+	 * @param EE_Currency_Config $currency_config
114
+	 * @param EE_Template_Config $template_config
115
+	 * @param DomainInterface    $domain
116
+	 * @param Registry           $registry
117
+	 */
118
+	public function __construct(
119
+		AssetCollection $assets,
120
+		EE_Currency_Config $currency_config,
121
+		EE_Template_Config $template_config,
122
+		DomainInterface $domain,
123
+		Registry $registry
124
+	) {
125
+		$this->currency_config = $currency_config;
126
+		$this->template_config = $template_config;
127
+		parent::__construct($domain, $assets, $registry);
128
+	}
129
+
130
+
131
+	/**
132
+	 * @since 4.9.62.p
133
+	 * @throws DomainException
134
+	 * @throws DuplicateCollectionIdentifierException
135
+	 * @throws InvalidArgumentException
136
+	 * @throws InvalidDataTypeException
137
+	 * @throws InvalidEntityException
138
+	 * @throws InvalidInterfaceException
139
+	 */
140
+	public function addAssets()
141
+	{
142
+		$this->addJavascriptFiles();
143
+		$this->addStylesheetFiles();
144
+	}
145
+
146
+
147
+	/**
148
+	 * @since 4.9.62.p
149
+	 * @throws DomainException
150
+	 * @throws DuplicateCollectionIdentifierException
151
+	 * @throws InvalidArgumentException
152
+	 * @throws InvalidDataTypeException
153
+	 * @throws InvalidEntityException
154
+	 * @throws InvalidInterfaceException
155
+	 */
156
+	public function addJavascriptFiles()
157
+	{
158
+		$this->loadCoreJs();
159
+		$this->loadJqueryValidate();
160
+		$this->loadAccountingJs();
161
+		add_action(
162
+			'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__before_script',
163
+			array($this, 'loadQtipJs')
164
+		);
165
+		$this->registerAdminAssets();
166
+	}
167
+
168
+
169
+	/**
170
+	 * @since 4.9.62.p
171
+	 * @throws DuplicateCollectionIdentifierException
172
+	 * @throws InvalidDataTypeException
173
+	 * @throws InvalidEntityException
174
+	 */
175
+	public function addStylesheetFiles()
176
+	{
177
+		$this->loadCoreCss();
178
+	}
179
+
180
+
181
+	/**
182
+	 * core default javascript
183
+	 *
184
+	 * @since 4.9.62.p
185
+	 * @throws DomainException
186
+	 * @throws DuplicateCollectionIdentifierException
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidEntityException
190
+	 * @throws InvalidInterfaceException
191
+	 */
192
+	private function loadCoreJs()
193
+	{
194
+		// conditionally load third-party libraries that WP core MIGHT have.
195
+		$this->registerWpAssets();
196
+
197
+		$this->addJavascript(
198
+			CoreAssetManager::JS_HANDLE_MANIFEST,
199
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'manifest')
200
+		);
201
+
202
+		$this->addJavascript(
203
+			CoreAssetManager::JS_HANDLE_JS_CORE,
204
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'eejs'),
205
+			array(CoreAssetManager::JS_HANDLE_MANIFEST)
206
+		)
207
+		->setHasInlineData();
208
+
209
+		$this->addJavascript(
210
+			CoreAssetManager::JS_HANDLE_VENDOR,
211
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'vendor'),
212
+			array(
213
+				CoreAssetManager::JS_HANDLE_JS_CORE,
214
+				CoreAssetManager::JS_HANDLE_REACT,
215
+				CoreAssetManager::JS_HANDLE_REACT_DOM,
216
+				CoreAssetManager::JS_HANDLE_LODASH,
217
+			)
218
+		);
219
+
220
+		$this->addJavascript(
221
+			CoreAssetManager::JS_HANDLE_VALIDATORS,
222
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'validators')
223
+		)->setRequiresTranslation();
224
+
225
+		$this->addJavascript(
226
+			CoreAssetManager::JS_HANDLE_HELPERS,
227
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'helpers'),
228
+			array(
229
+				CoreAssetManager::JS_HANDLE_VALIDATORS
230
+			)
231
+		)->setRequiresTranslation();
232
+
233
+		$this->addJavascript(
234
+			CoreAssetManager::JS_HANDLE_MODEL,
235
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'model'),
236
+			array(
237
+				CoreAssetManager::JS_HANDLE_HELPERS
238
+			)
239
+		)->setRequiresTranslation();
240
+
241
+		$this->addJavascript(
242
+			CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
243
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'valueObjects'),
244
+			array(
245
+				CoreAssetManager::JS_HANDLE_MODEL
246
+			)
247
+		)->setRequiresTranslation();
248
+
249
+		$this->addJavascript(
250
+			CoreAssetManager::JS_HANDLE_DATA_STORES,
251
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'data-stores'),
252
+			array(
253
+				CoreAssetManager::JS_HANDLE_VENDOR,
254
+				'wp-data',
255
+				'wp-api-fetch',
256
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS
257
+			)
258
+		)
259
+			 ->setRequiresTranslation()
260
+			 ->setInlineDataCallback(
261
+				 function() {
262
+					 wp_add_inline_script(
263
+						 CoreAssetManager::JS_HANDLE_DATA_STORES,
264
+						 is_admin()
265
+							 ? 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware( eejs.middleWares.apiFetch.CONTEXT_CAPS_EDIT ) )'
266
+							 : 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware )'
267
+					 );
268
+				 }
269
+			 );
270
+
271
+		$this->addJavascript(
272
+			CoreAssetManager::JS_HANDLE_HOCS,
273
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'hocs'),
274
+			array(
275
+				CoreAssetManager::JS_HANDLE_DATA_STORES,
276
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
277
+				'wp-components',
278
+			)
279
+		)->setRequiresTranslation();
280
+
281
+		$this->addJavascript(
282
+			CoreAssetManager::JS_HANDLE_COMPONENTS,
283
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'components'),
284
+			array(
285
+				CoreAssetManager::JS_HANDLE_DATA_STORES,
286
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
287
+				'wp-components',
288
+			)
289
+		)
290
+		->setRequiresTranslation();
291
+
292
+		$this->addJavascript(
293
+			CoreAssetManager::JS_HANDLE_EDITOR_HOCS,
294
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'editor-hocs'),
295
+			array(
296
+				CoreAssetManager::JS_HANDLE_COMPONENTS
297
+			)
298
+		)->setRequiresTranslation();
299
+
300
+		$this->registry->addData('eejs_api_nonce', wp_create_nonce('wp_rest'));
301
+		$this->registry->addData(
302
+			'paths',
303
+			array(
304
+				'base_rest_route' => rest_url(),
305
+				'rest_route' => rest_url('ee/v4.8.36/'),
306
+				'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName(),
307
+				'primary_keys' => EED_Core_Rest_Api::getPrimaryKeyNamesIndexedByModelName(),
308
+				'site_url' => site_url('/'),
309
+				'admin_url' => admin_url('/'),
310
+			)
311
+		);
312
+		/** site formatting values **/
313
+		$this->registry->addData(
314
+			'site_formats',
315
+			array(
316
+				'date_formats' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats()
317
+			)
318
+		);
319
+		/** currency data **/
320
+		$this->registry->addData(
321
+			'currency_config',
322
+			$this->getCurrencySettings()
323
+		);
324
+		/** site timezone */
325
+		$this->registry->addData(
326
+			'default_timezone',
327
+			array(
328
+				'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
329
+				'string' => get_option('timezone_string'),
330
+				'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
331
+			)
332
+		);
333
+		/** site locale (user locale if user logged in) */
334
+		$this->registry->addData(
335
+			'locale',
336
+			array(
337
+				'user' => get_user_locale(),
338
+				'site' => get_locale()
339
+			)
340
+		);
341
+
342
+		$this->addJavascript(
343
+			CoreAssetManager::JS_HANDLE_CORE,
344
+			EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
345
+			array(CoreAssetManager::JS_HANDLE_JQUERY)
346
+		)
347
+		->setInlineDataCallback(
348
+			function () {
349
+				wp_localize_script(
350
+					CoreAssetManager::JS_HANDLE_CORE,
351
+					CoreAssetManager::JS_HANDLE_I18N,
352
+					EE_Registry::$i18n_js_strings
353
+				);
354
+			}
355
+		);
356
+	}
357
+
358
+
359
+	/**
360
+	 * Registers vendor files that are bundled with a later version WP but might not be for the current version of
361
+	 * WordPress in the running environment.
362
+	 *
363
+	 * @throws DuplicateCollectionIdentifierException
364
+	 * @throws InvalidDataTypeException
365
+	 * @throws InvalidEntityException
366
+	 * @throws DomainException
367
+	 * @since 4.9.71.p
368
+	 */
369
+	private function registerWpAssets()
370
+	{
371
+		global $wp_version;
372
+		if (version_compare($wp_version, '5.0.beta', '>=')) {
373
+			return;
374
+		}
375
+		$this->addVendorJavascript(CoreAssetManager::JS_HANDLE_REACT)
376
+			->setVersion('16.6.0');
377
+		$this->addVendorJavascript(
378
+			CoreAssetManager::JS_HANDLE_REACT_DOM,
379
+			array(CoreAssetManager::JS_HANDLE_REACT)
380
+		)->setVersion('16.6.0');
381
+		$this->addVendorJavascript(CoreAssetManager::JS_HANDLE_LODASH)
382
+			->setInlineDataCallback(
383
+				function() {
384
+					wp_add_inline_script(
385
+						CoreAssetManager::JS_HANDLE_LODASH,
386
+						'window.lodash = _.noConflict();'
387
+					);
388
+				}
389
+			)
390
+			->setVersion('4.17.11');
391
+	}
392
+
393
+
394
+	/**
395
+	 * Returns configuration data for the accounting-js library.
396
+	 * @since 4.9.71.p
397
+	 * @return array
398
+	 */
399
+	private function getAccountingSettings() {
400
+		return array(
401
+			'currency' => array(
402
+				'symbol'    => $this->currency_config->sign,
403
+				'format'    => array(
404
+					'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
405
+					'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
406
+					'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
407
+				),
408
+				'decimal'   => $this->currency_config->dec_mrk,
409
+				'thousand'  => $this->currency_config->thsnds,
410
+				'precision' => $this->currency_config->dec_plc,
411
+			),
412
+			'number'   => array(
413
+				'precision' => $this->currency_config->dec_plc,
414
+				'thousand'  => $this->currency_config->thsnds,
415
+				'decimal'   => $this->currency_config->dec_mrk,
416
+			),
417
+		);
418
+	}
419
+
420
+
421
+	/**
422
+	 * Returns configuration data for the js Currency VO.
423
+	 * @since 4.9.71.p
424
+	 * @return array
425
+	 */
426
+	private function getCurrencySettings()
427
+	{
428
+		return array(
429
+			'code' => $this->currency_config->code,
430
+			'singularLabel' => $this->currency_config->name,
431
+			'pluralLabel' => $this->currency_config->plural,
432
+			'sign' => $this->currency_config->sign,
433
+			'signB4' => $this->currency_config->sign_b4,
434
+			'decimalPlaces' => $this->currency_config->dec_plc,
435
+			'decimalMark' => $this->currency_config->dec_mrk,
436
+			'thousandsSeparator' => $this->currency_config->thsnds,
437
+		);
438
+	}
439
+
440
+
441
+	/**
442
+	 * @since 4.9.62.p
443
+	 * @throws DuplicateCollectionIdentifierException
444
+	 * @throws InvalidDataTypeException
445
+	 * @throws InvalidEntityException
446
+	 */
447
+	private function loadCoreCss()
448
+	{
449
+		if ($this->template_config->enable_default_style && ! is_admin()) {
450
+			$this->addStylesheet(
451
+				CoreAssetManager::CSS_HANDLE_DEFAULT,
452
+				is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
453
+					? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
454
+					: EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
455
+				array('dashicons')
456
+			);
457
+			//Load custom style sheet if available
458
+			if ($this->template_config->custom_style_sheet !== null) {
459
+				$this->addStylesheet(
460
+					CoreAssetManager::CSS_HANDLE_CUSTOM,
461
+					EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
462
+					array(CoreAssetManager::CSS_HANDLE_DEFAULT)
463
+				);
464
+			}
465
+		}
466
+		$this->addStylesheet(
467
+			CoreAssetManager::CSS_HANDLE_COMPONENTS,
468
+			$this->registry->getCssUrl(
469
+				$this->domain->assetNamespace(),
470
+				'components'
471
+			)
472
+		);
473
+	}
474
+
475
+
476
+	/**
477
+	 * jQuery Validate for form validation
478
+	 *
479
+	 * @since 4.9.62.p
480
+	 * @throws DomainException
481
+	 * @throws DuplicateCollectionIdentifierException
482
+	 * @throws InvalidDataTypeException
483
+	 * @throws InvalidEntityException
484
+	 */
485
+	private function loadJqueryValidate()
486
+	{
487
+		$this->addJavascript(
488
+			CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE,
489
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
490
+			array(CoreAssetManager::JS_HANDLE_JQUERY)
491
+		)
492
+		->setVersion('1.15.0');
493
+
494
+		$this->addJavascript(
495
+			CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE_EXTRA,
496
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
497
+			array(CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE)
498
+		)
499
+		->setVersion('1.15.0');
500
+	}
501
+
502
+
503
+	/**
504
+	 * accounting.js for performing client-side calculations
505
+	 *
506
+	 * @since 4.9.62.p
507
+	 * @throws DomainException
508
+	 * @throws DuplicateCollectionIdentifierException
509
+	 * @throws InvalidDataTypeException
510
+	 * @throws InvalidEntityException
511
+	 */
512
+	private function loadAccountingJs()
513
+	{
514
+		//accounting.js library
515
+		// @link http://josscrowcroft.github.io/accounting.js/
516
+		$this->addJavascript(
517
+			CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE,
518
+			EE_THIRD_PARTY_URL . 'accounting/accounting.js',
519
+			array(CoreAssetManager::JS_HANDLE_UNDERSCORE)
520
+		)
521
+		->setVersion('0.3.2');
522
+
523
+		$this->addJavascript(
524
+			CoreAssetManager::JS_HANDLE_ACCOUNTING,
525
+			EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
526
+			array(CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE)
527
+		)
528
+		->setInlineDataCallback(
529
+			function () {
530
+				 wp_localize_script(
531
+					 CoreAssetManager::JS_HANDLE_ACCOUNTING,
532
+					 'EE_ACCOUNTING_CFG',
533
+					 $this->getAccountingSettings()
534
+				 );
535
+			}
536
+		)
537
+		->setVersion();
538
+	}
539
+
540
+
541
+	/**
542
+	 * registers assets for cleaning your ears
543
+	 *
544
+	 * @param JavascriptAsset $script
545
+	 */
546
+	public function loadQtipJs(JavascriptAsset $script)
547
+	{
548
+		// qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
549
+		// can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
550
+		if (
551
+			$script->handle() === CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE
552
+			&& apply_filters('FHEE_load_qtip', false)
553
+		) {
554
+			EEH_Qtip_Loader::instance()->register_and_enqueue();
555
+		}
556
+	}
557
+
558
+
559
+	/**
560
+	 * assets that are used in the WordPress admin
561
+	 *
562
+	 * @since 4.9.62.p
563
+	 * @throws DuplicateCollectionIdentifierException
564
+	 * @throws InvalidDataTypeException
565
+	 * @throws InvalidEntityException
566
+	 */
567
+	private function registerAdminAssets()
568
+	{
569
+		$this->addJavascript(
570
+			CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
571
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'wp-plugins-page'),
572
+			array(
573
+				CoreAssetManager::JS_HANDLE_JQUERY,
574
+				CoreAssetManager::JS_HANDLE_VENDOR,
575
+			)
576
+		)
577
+		->setRequiresTranslation();
578
+
579
+		$this->addStylesheet(
580
+			CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
581
+			$this->registry->getCssUrl($this->domain->assetNamespace(), 'wp-plugins-page')
582
+		);
583
+	}
584 584
 }
Please login to merge, or discard this patch.
modules/batch/EED_Batch.module.php 1 patch
Indentation   +310 added lines, -310 removed lines patch added patch discarded remove patch
@@ -23,336 +23,336 @@
 block discarded – undo
23 23
 class EED_Batch extends EED_Module
24 24
 {
25 25
 
26
-    /**
27
-     * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
28
-     * processes data only
29
-     */
30
-    const batch_job = 'job';
31
-    /**
32
-     * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
33
-     * produces a file for download
34
-     */
35
-    const batch_file_job = 'file';
36
-    /**
37
-     * Possibly value for $_REQUEST[ 'batch' ]. Indicates this request is NOT
38
-     * for a batch job. It's the same as not providing the $_REQUEST[ 'batch' ]
39
-     * at all
40
-     */
41
-    const batch_not_job = 'none';
26
+	/**
27
+	 * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
28
+	 * processes data only
29
+	 */
30
+	const batch_job = 'job';
31
+	/**
32
+	 * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that
33
+	 * produces a file for download
34
+	 */
35
+	const batch_file_job = 'file';
36
+	/**
37
+	 * Possibly value for $_REQUEST[ 'batch' ]. Indicates this request is NOT
38
+	 * for a batch job. It's the same as not providing the $_REQUEST[ 'batch' ]
39
+	 * at all
40
+	 */
41
+	const batch_not_job = 'none';
42 42
 
43
-    /**
44
-     *
45
-     * @var string 'file', or 'job', or false to indicate its not a batch request at all
46
-     */
47
-    protected $_batch_request_type = null;
43
+	/**
44
+	 *
45
+	 * @var string 'file', or 'job', or false to indicate its not a batch request at all
46
+	 */
47
+	protected $_batch_request_type = null;
48 48
 
49
-    /**
50
-     * Because we want to use the response in both the localized JS and in the body
51
-     * we need to make this response available between method calls
52
-     *
53
-     * @var \EventEspressoBatchRequest\Helpers\JobStepResponse
54
-     */
55
-    protected $_job_step_response = null;
49
+	/**
50
+	 * Because we want to use the response in both the localized JS and in the body
51
+	 * we need to make this response available between method calls
52
+	 *
53
+	 * @var \EventEspressoBatchRequest\Helpers\JobStepResponse
54
+	 */
55
+	protected $_job_step_response = null;
56 56
 
57
-    /**
58
-     * Gets the batch instance
59
-     *
60
-     * @return EED_Batch
61
-     */
62
-    public static function instance()
63
-    {
64
-        return self::get_instance();
65
-    }
57
+	/**
58
+	 * Gets the batch instance
59
+	 *
60
+	 * @return EED_Batch
61
+	 */
62
+	public static function instance()
63
+	{
64
+		return self::get_instance();
65
+	}
66 66
 
67
-    /**
68
-     * Sets hooks to enable batch jobs on the frontend. Disabled by default
69
-     * because it's an attack vector and there are currently no implementations
70
-     */
71
-    public static function set_hooks()
72
-    {
73
-        // because this is a possibel attack vector, let's have this disabled until
74
-        // we at least have a real use for it on the frontend
75
-        if (apply_filters('FHEE__EED_Batch__set_hooks__enable_frontend_batch', false)) {
76
-            add_action('wp_enqueue_scripts', array(self::instance(), 'enqueue_scripts'));
77
-            add_filter('template_include', array(self::instance(), 'override_template'), 99);
78
-        }
79
-    }
67
+	/**
68
+	 * Sets hooks to enable batch jobs on the frontend. Disabled by default
69
+	 * because it's an attack vector and there are currently no implementations
70
+	 */
71
+	public static function set_hooks()
72
+	{
73
+		// because this is a possibel attack vector, let's have this disabled until
74
+		// we at least have a real use for it on the frontend
75
+		if (apply_filters('FHEE__EED_Batch__set_hooks__enable_frontend_batch', false)) {
76
+			add_action('wp_enqueue_scripts', array(self::instance(), 'enqueue_scripts'));
77
+			add_filter('template_include', array(self::instance(), 'override_template'), 99);
78
+		}
79
+	}
80 80
 
81
-    /**
82
-     * Initializes some hooks for the admin in order to run batch jobs
83
-     */
84
-    public static function set_hooks_admin()
85
-    {
86
-        add_action('admin_menu', array(self::instance(), 'register_admin_pages'));
87
-        add_action('admin_enqueue_scripts', array(self::instance(), 'enqueue_scripts'));
81
+	/**
82
+	 * Initializes some hooks for the admin in order to run batch jobs
83
+	 */
84
+	public static function set_hooks_admin()
85
+	{
86
+		add_action('admin_menu', array(self::instance(), 'register_admin_pages'));
87
+		add_action('admin_enqueue_scripts', array(self::instance(), 'enqueue_scripts'));
88 88
 
89
-        // ajax
90
-        add_action('wp_ajax_espresso_batch_continue', array(self::instance(), 'batch_continue'));
91
-        add_action('wp_ajax_espresso_batch_cleanup', array(self::instance(), 'batch_cleanup'));
92
-        add_action('wp_ajax_nopriv_espresso_batch_continue', array(self::instance(), 'batch_continue'));
93
-        add_action('wp_ajax_nopriv_espresso_batch_cleanup', array(self::instance(), 'batch_cleanup'));
94
-    }
89
+		// ajax
90
+		add_action('wp_ajax_espresso_batch_continue', array(self::instance(), 'batch_continue'));
91
+		add_action('wp_ajax_espresso_batch_cleanup', array(self::instance(), 'batch_cleanup'));
92
+		add_action('wp_ajax_nopriv_espresso_batch_continue', array(self::instance(), 'batch_continue'));
93
+		add_action('wp_ajax_nopriv_espresso_batch_cleanup', array(self::instance(), 'batch_cleanup'));
94
+	}
95 95
 
96
-    /**
97
-     * Enqueues batch scripts on the frontend or admin, and creates a job
98
-     */
99
-    public function enqueue_scripts()
100
-    {
101
-        if (isset($_REQUEST['espresso_batch'])
102
-            ||
103
-            (
104
-                isset($_REQUEST['page'])
105
-                && $_REQUEST['page'] == 'espresso_batch'
106
-            )
107
-        ) {
108
-            switch ($this->batch_request_type()) {
109
-                case self::batch_job:
110
-                    $this->enqueue_scripts_styles_batch_create();
111
-                    break;
112
-                case self::batch_file_job:
113
-                    $this->enqueue_scripts_styles_batch_file_create();
114
-                    break;
115
-            }
116
-        }
117
-    }
96
+	/**
97
+	 * Enqueues batch scripts on the frontend or admin, and creates a job
98
+	 */
99
+	public function enqueue_scripts()
100
+	{
101
+		if (isset($_REQUEST['espresso_batch'])
102
+			||
103
+			(
104
+				isset($_REQUEST['page'])
105
+				&& $_REQUEST['page'] == 'espresso_batch'
106
+			)
107
+		) {
108
+			switch ($this->batch_request_type()) {
109
+				case self::batch_job:
110
+					$this->enqueue_scripts_styles_batch_create();
111
+					break;
112
+				case self::batch_file_job:
113
+					$this->enqueue_scripts_styles_batch_file_create();
114
+					break;
115
+			}
116
+		}
117
+	}
118 118
 
119
-    /**
120
-     * Create a batch job, enqueues a script to run it, and localizes some data for it
121
-     */
122
-    public function enqueue_scripts_styles_batch_create()
123
-    {
124
-        $job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
125
-        wp_enqueue_script(
126
-            'batch_runner_init',
127
-            BATCH_URL . 'assets/batch_runner_init.js',
128
-            array('batch_runner'),
129
-            EVENT_ESPRESSO_VERSION,
130
-            true
131
-        );
132
-        wp_localize_script('batch_runner_init', 'ee_job_response', $job_response->to_array());
133
-        wp_localize_script(
134
-            'batch_runner_init',
135
-            'ee_job_i18n',
136
-            array(
137
-                'return_url' => $_REQUEST['return_url'],
138
-            )
139
-        );
140
-    }
119
+	/**
120
+	 * Create a batch job, enqueues a script to run it, and localizes some data for it
121
+	 */
122
+	public function enqueue_scripts_styles_batch_create()
123
+	{
124
+		$job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
125
+		wp_enqueue_script(
126
+			'batch_runner_init',
127
+			BATCH_URL . 'assets/batch_runner_init.js',
128
+			array('batch_runner'),
129
+			EVENT_ESPRESSO_VERSION,
130
+			true
131
+		);
132
+		wp_localize_script('batch_runner_init', 'ee_job_response', $job_response->to_array());
133
+		wp_localize_script(
134
+			'batch_runner_init',
135
+			'ee_job_i18n',
136
+			array(
137
+				'return_url' => $_REQUEST['return_url'],
138
+			)
139
+		);
140
+	}
141 141
 
142
-    /**
143
-     * Creates a batch job which will download a file, enqueues a script to run the job, and localizes some data for it
144
-     */
145
-    public function enqueue_scripts_styles_batch_file_create()
146
-    {
147
-        // creates a job based on the request variable
148
-        $job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
149
-        wp_enqueue_script(
150
-            'batch_file_runner_init',
151
-            BATCH_URL . 'assets/batch_file_runner_init.js',
152
-            array('batch_runner'),
153
-            EVENT_ESPRESSO_VERSION,
154
-            true
155
-        );
156
-        wp_localize_script('batch_file_runner_init', 'ee_job_response', $job_response->to_array());
157
-        wp_localize_script(
158
-            'batch_file_runner_init',
159
-            'ee_job_i18n',
160
-            array(
161
-                'download_and_redirecting' => sprintf(
162
-                    __('File Generation complete. Downloading, and %1$sredirecting%2$s...', 'event_espresso'),
163
-                    '<a href="' . $_REQUEST['return_url'] . '">',
164
-                    '</a>'
165
-                ),
166
-                'return_url'               => $_REQUEST['return_url'],
167
-            )
168
-        );
169
-    }
142
+	/**
143
+	 * Creates a batch job which will download a file, enqueues a script to run the job, and localizes some data for it
144
+	 */
145
+	public function enqueue_scripts_styles_batch_file_create()
146
+	{
147
+		// creates a job based on the request variable
148
+		$job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job();
149
+		wp_enqueue_script(
150
+			'batch_file_runner_init',
151
+			BATCH_URL . 'assets/batch_file_runner_init.js',
152
+			array('batch_runner'),
153
+			EVENT_ESPRESSO_VERSION,
154
+			true
155
+		);
156
+		wp_localize_script('batch_file_runner_init', 'ee_job_response', $job_response->to_array());
157
+		wp_localize_script(
158
+			'batch_file_runner_init',
159
+			'ee_job_i18n',
160
+			array(
161
+				'download_and_redirecting' => sprintf(
162
+					__('File Generation complete. Downloading, and %1$sredirecting%2$s...', 'event_espresso'),
163
+					'<a href="' . $_REQUEST['return_url'] . '">',
164
+					'</a>'
165
+				),
166
+				'return_url'               => $_REQUEST['return_url'],
167
+			)
168
+		);
169
+	}
170 170
 
171
-    /**
172
-     * Enqueues scripts and styles common to any batch job, and creates
173
-     * a job from the request data, and stores the response in the
174
-     * $this->_job_step_response property
175
-     *
176
-     * @return \EventEspressoBatchRequest\Helpers\JobStepResponse
177
-     */
178
-    protected function _enqueue_batch_job_scripts_and_styles_and_start_job()
179
-    {
180
-        wp_register_script(
181
-            'progress_bar',
182
-            EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.js',
183
-            array('jquery')
184
-        );
185
-        wp_enqueue_style(
186
-            'progress_bar',
187
-            EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.css',
188
-            array(),
189
-            EVENT_ESPRESSO_VERSION
190
-        );
191
-        wp_enqueue_script(
192
-            'batch_runner',
193
-            EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/batch_runner.js',
194
-            array('progress_bar')
195
-        );
196
-        // just copy the bits of EE admin's eei18n that we need in the JS
197
-        wp_localize_script(
198
-            'batch_runner',
199
-            'eei18n',
200
-            array(
201
-                'ajax_url'      => WP_AJAX_URL,
202
-                'is_admin'      => (bool) is_admin(),
203
-                'error_message' => esc_html__('An error occurred and the job has been stopped. Please refresh the page to try again.', 'event_espresso'),
204
-            )
205
-        );
206
-        $job_handler_classname = stripslashes($_GET['job_handler']);
207
-        $request_data = array_diff_key(
208
-            $_REQUEST,
209
-            array_flip(array('action', 'page', 'ee', 'batch'))
210
-        );
211
-        $batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor();
212
-        // eg 'EventEspressoBatchRequest\JobHandlers\RegistrationsReport'
213
-        $job_response = $batch_runner->create_job($job_handler_classname, $request_data);
214
-        // remember the response for later. We need it to display the page body
215
-        $this->_job_step_response = $job_response;
216
-        return $job_response;
217
-    }
171
+	/**
172
+	 * Enqueues scripts and styles common to any batch job, and creates
173
+	 * a job from the request data, and stores the response in the
174
+	 * $this->_job_step_response property
175
+	 *
176
+	 * @return \EventEspressoBatchRequest\Helpers\JobStepResponse
177
+	 */
178
+	protected function _enqueue_batch_job_scripts_and_styles_and_start_job()
179
+	{
180
+		wp_register_script(
181
+			'progress_bar',
182
+			EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.js',
183
+			array('jquery')
184
+		);
185
+		wp_enqueue_style(
186
+			'progress_bar',
187
+			EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.css',
188
+			array(),
189
+			EVENT_ESPRESSO_VERSION
190
+		);
191
+		wp_enqueue_script(
192
+			'batch_runner',
193
+			EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/batch_runner.js',
194
+			array('progress_bar')
195
+		);
196
+		// just copy the bits of EE admin's eei18n that we need in the JS
197
+		wp_localize_script(
198
+			'batch_runner',
199
+			'eei18n',
200
+			array(
201
+				'ajax_url'      => WP_AJAX_URL,
202
+				'is_admin'      => (bool) is_admin(),
203
+				'error_message' => esc_html__('An error occurred and the job has been stopped. Please refresh the page to try again.', 'event_espresso'),
204
+			)
205
+		);
206
+		$job_handler_classname = stripslashes($_GET['job_handler']);
207
+		$request_data = array_diff_key(
208
+			$_REQUEST,
209
+			array_flip(array('action', 'page', 'ee', 'batch'))
210
+		);
211
+		$batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor();
212
+		// eg 'EventEspressoBatchRequest\JobHandlers\RegistrationsReport'
213
+		$job_response = $batch_runner->create_job($job_handler_classname, $request_data);
214
+		// remember the response for later. We need it to display the page body
215
+		$this->_job_step_response = $job_response;
216
+		return $job_response;
217
+	}
218 218
 
219
-    /**
220
-     * If we are doing a frontend batch job, this makes it so WP shows our template's HTML
221
-     *
222
-     * @param string $template
223
-     * @return string
224
-     */
225
-    public function override_template($template)
226
-    {
227
-        if (isset($_REQUEST['espresso_batch']) && isset($_REQUEST['batch'])) {
228
-            return EE_MODULES . 'batch' . DS . 'templates' . DS . 'batch_frontend_wrapper.template.html';
229
-        }
230
-        return $template;
231
-    }
219
+	/**
220
+	 * If we are doing a frontend batch job, this makes it so WP shows our template's HTML
221
+	 *
222
+	 * @param string $template
223
+	 * @return string
224
+	 */
225
+	public function override_template($template)
226
+	{
227
+		if (isset($_REQUEST['espresso_batch']) && isset($_REQUEST['batch'])) {
228
+			return EE_MODULES . 'batch' . DS . 'templates' . DS . 'batch_frontend_wrapper.template.html';
229
+		}
230
+		return $template;
231
+	}
232 232
 
233
-    /**
234
-     * Adds an admin page which doesn't appear in the admin menu
235
-     */
236
-    public function register_admin_pages()
237
-    {
238
-        add_submenu_page(
239
-            '', // parent slug. we don't want this to actually appear in the menu
240
-            __('Batch Job', 'event_espresso'), // page title
241
-            'n/a', // menu title
242
-            'read', // we want this page to actually be accessible to anyone,
243
-            'espresso_batch', // menu slug
244
-            array(self::instance(), 'show_admin_page')
245
-        );
246
-    }
233
+	/**
234
+	 * Adds an admin page which doesn't appear in the admin menu
235
+	 */
236
+	public function register_admin_pages()
237
+	{
238
+		add_submenu_page(
239
+			'', // parent slug. we don't want this to actually appear in the menu
240
+			__('Batch Job', 'event_espresso'), // page title
241
+			'n/a', // menu title
242
+			'read', // we want this page to actually be accessible to anyone,
243
+			'espresso_batch', // menu slug
244
+			array(self::instance(), 'show_admin_page')
245
+		);
246
+	}
247 247
 
248
-    /**
249
-     * Renders the admin page, after most of the work was already done during enqueuing scripts
250
-     * of creating the job and localizing some data
251
-     */
252
-    public function show_admin_page()
253
-    {
254
-        echo EEH_Template::locate_template(
255
-            EE_MODULES . 'batch' . DS . 'templates' . DS . 'batch_wrapper.template.html',
256
-            array('batch_request_type' => $this->batch_request_type())
257
-        );
258
-    }
248
+	/**
249
+	 * Renders the admin page, after most of the work was already done during enqueuing scripts
250
+	 * of creating the job and localizing some data
251
+	 */
252
+	public function show_admin_page()
253
+	{
254
+		echo EEH_Template::locate_template(
255
+			EE_MODULES . 'batch' . DS . 'templates' . DS . 'batch_wrapper.template.html',
256
+			array('batch_request_type' => $this->batch_request_type())
257
+		);
258
+	}
259 259
 
260
-    /**
261
-     * Receives ajax calls for continuing a job
262
-     */
263
-    public function batch_continue()
264
-    {
265
-        $job_id = sanitize_text_field($_REQUEST['job_id']);
266
-        $batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor();
267
-        $response_obj = $batch_runner->continue_job($job_id);
268
-        $this->_return_json($response_obj->to_array());
269
-    }
260
+	/**
261
+	 * Receives ajax calls for continuing a job
262
+	 */
263
+	public function batch_continue()
264
+	{
265
+		$job_id = sanitize_text_field($_REQUEST['job_id']);
266
+		$batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor();
267
+		$response_obj = $batch_runner->continue_job($job_id);
268
+		$this->_return_json($response_obj->to_array());
269
+	}
270 270
 
271
-    /**
272
-     * Receives the ajax call to cleanup a job
273
-     *
274
-     * @return type
275
-     */
276
-    public function batch_cleanup()
277
-    {
278
-        $job_id = sanitize_text_field($_REQUEST['job_id']);
279
-        $batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor();
280
-        $response_obj = $batch_runner->cleanup_job($job_id);
281
-        $this->_return_json($response_obj->to_array());
282
-    }
271
+	/**
272
+	 * Receives the ajax call to cleanup a job
273
+	 *
274
+	 * @return type
275
+	 */
276
+	public function batch_cleanup()
277
+	{
278
+		$job_id = sanitize_text_field($_REQUEST['job_id']);
279
+		$batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor();
280
+		$response_obj = $batch_runner->cleanup_job($job_id);
281
+		$this->_return_json($response_obj->to_array());
282
+	}
283 283
 
284 284
 
285
-    /**
286
-     * Returns a json response
287
-     *
288
-     * @param array $data The data we want to send echo via in the JSON response's "data" element
289
-     *
290
-     * The returned json object is created from an array in the following format:
291
-     * array(
292
-     *    'notices' => '', // - contains any EE_Error formatted notices
293
-     *    'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
294
-     *    We're also going to include the template args with every package (so js can pick out any specific template
295
-     *    args that might be included in here)
296
-     *    'isEEajax' => true,//indicates this is a response from EE
297
-     * )
298
-     */
299
-    protected function _return_json($data)
300
-    {
301
-        $json = array(
302
-            'notices'  => EE_Error::get_notices(),
303
-            'data'     => $data,
304
-            'isEEajax' => true
305
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
306
-        );
285
+	/**
286
+	 * Returns a json response
287
+	 *
288
+	 * @param array $data The data we want to send echo via in the JSON response's "data" element
289
+	 *
290
+	 * The returned json object is created from an array in the following format:
291
+	 * array(
292
+	 *    'notices' => '', // - contains any EE_Error formatted notices
293
+	 *    'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
294
+	 *    We're also going to include the template args with every package (so js can pick out any specific template
295
+	 *    args that might be included in here)
296
+	 *    'isEEajax' => true,//indicates this is a response from EE
297
+	 * )
298
+	 */
299
+	protected function _return_json($data)
300
+	{
301
+		$json = array(
302
+			'notices'  => EE_Error::get_notices(),
303
+			'data'     => $data,
304
+			'isEEajax' => true
305
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
306
+		);
307 307
 
308 308
 
309
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
310
-        if (null === error_get_last() || ! headers_sent()) {
311
-            header('Content-Type: application/json; charset=UTF-8');
312
-        }
313
-        echo wp_json_encode($json);
314
-        exit();
315
-    }
309
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
310
+		if (null === error_get_last() || ! headers_sent()) {
311
+			header('Content-Type: application/json; charset=UTF-8');
312
+		}
313
+		echo wp_json_encode($json);
314
+		exit();
315
+	}
316 316
 
317
-    /**
318
-     * Gets the job step response which was done during the enqueuing of scripts
319
-     *
320
-     * @return \EventEspressoBatchRequest\Helpers\JobStepResponse
321
-     */
322
-    public function job_step_response()
323
-    {
324
-        return $this->_job_step_response;
325
-    }
317
+	/**
318
+	 * Gets the job step response which was done during the enqueuing of scripts
319
+	 *
320
+	 * @return \EventEspressoBatchRequest\Helpers\JobStepResponse
321
+	 */
322
+	public function job_step_response()
323
+	{
324
+		return $this->_job_step_response;
325
+	}
326 326
 
327
-    /**
328
-     * Gets the batch request type indicated in the $_REQUEST
329
-     *
330
-     * @return string: EED_Batch::batch_job, EED_Batch::batch_file_job, EED_Batch::batch_not_job
331
-     */
332
-    public function batch_request_type()
333
-    {
334
-        if ($this->_batch_request_type === null) {
335
-            if (isset($_GET['batch'])) {
336
-                if ($_GET['batch'] == self::batch_job) {
337
-                    $this->_batch_request_type = self::batch_job;
338
-                } elseif ($_GET['batch'] == self::batch_file_job) {
339
-                    $this->_batch_request_type = self::batch_file_job;
340
-                }
341
-            }
342
-            // if we didn't find that it was a batch request, indicate it wasn't
343
-            if ($this->_batch_request_type === null) {
344
-                $this->_batch_request_type = self::batch_not_job;
345
-            }
346
-        }
347
-        return $this->_batch_request_type;
348
-    }
327
+	/**
328
+	 * Gets the batch request type indicated in the $_REQUEST
329
+	 *
330
+	 * @return string: EED_Batch::batch_job, EED_Batch::batch_file_job, EED_Batch::batch_not_job
331
+	 */
332
+	public function batch_request_type()
333
+	{
334
+		if ($this->_batch_request_type === null) {
335
+			if (isset($_GET['batch'])) {
336
+				if ($_GET['batch'] == self::batch_job) {
337
+					$this->_batch_request_type = self::batch_job;
338
+				} elseif ($_GET['batch'] == self::batch_file_job) {
339
+					$this->_batch_request_type = self::batch_file_job;
340
+				}
341
+			}
342
+			// if we didn't find that it was a batch request, indicate it wasn't
343
+			if ($this->_batch_request_type === null) {
344
+				$this->_batch_request_type = self::batch_not_job;
345
+			}
346
+		}
347
+		return $this->_batch_request_type;
348
+	}
349 349
 
350
-    /**
351
-     * Unnecessary
352
-     *
353
-     * @param type $WP
354
-     */
355
-    public function run($WP)
356
-    {
357
-    }
350
+	/**
351
+	 * Unnecessary
352
+	 *
353
+	 * @param type $WP
354
+	 */
355
+	public function run($WP)
356
+	{
357
+	}
358 358
 }
Please login to merge, or discard this patch.
caffeinated/modules/recaptcha_invisible/EED_Recaptcha_Invisible.module.php 2 patches
Indentation   +328 added lines, -328 removed lines patch added patch discarded remove patch
@@ -18,332 +18,332 @@
 block discarded – undo
18 18
 class EED_Recaptcha_Invisible extends EED_Module
19 19
 {
20 20
 
21
-    /**
22
-     * @var EE_Registration_Config $config
23
-     */
24
-    private static $config;
25
-
26
-
27
-    /**
28
-     * @return EED_Module|EED_Recaptcha
29
-     */
30
-    public static function instance()
31
-    {
32
-        return parent::get_instance(__CLASS__);
33
-    }
34
-
35
-
36
-    /**
37
-     * @return void
38
-     * @throws InvalidInterfaceException
39
-     * @throws InvalidDataTypeException
40
-     * @throws InvalidArgumentException
41
-     */
42
-    public static function set_hooks()
43
-    {
44
-        EED_Recaptcha_Invisible::setProperties();
45
-        if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) {
46
-            if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
47
-                // ticket selection
48
-                add_filter(
49
-                    'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
50
-                    array('EED_Recaptcha_Invisible', 'ticketSelectorForm'),
51
-                    10,
52
-                    3
53
-                );
54
-                add_action(
55
-                    'EED_Ticket_Selector__process_ticket_selections__before',
56
-                    array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
57
-                );
58
-            }
59
-            if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
60
-                // checkout
61
-                add_action(
62
-                    'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form',
63
-                    array('EED_Recaptcha_Invisible', 'spcoRegStepForm')
64
-                );
65
-                add_filter(
66
-                    'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
67
-                    array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
68
-                    10,
69
-                    2
70
-                );
71
-            }
72
-            add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars'));
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     * @return void
79
-     * @throws InvalidInterfaceException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidArgumentException
82
-     */
83
-    public static function set_hooks_admin()
84
-    {
85
-        EED_Recaptcha_Invisible::setProperties();
86
-        if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
87
-            add_action(
88
-                'EED_Ticket_Selector__process_ticket_selections__before',
89
-                array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
90
-            );
91
-        }
92
-        if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
93
-            add_filter(
94
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
95
-                array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
96
-                10,
97
-                2
98
-            );
99
-        }
100
-        // admin settings
101
-        add_action(
102
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
103
-            array('EED_Recaptcha_Invisible', 'adminSettings')
104
-        );
105
-        add_filter(
106
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
107
-            array('EED_Recaptcha_Invisible', 'updateAdminSettings')
108
-        );
109
-    }
110
-
111
-
112
-    /**
113
-     * @return void
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidDataTypeException
116
-     * @throws InvalidArgumentException
117
-     */
118
-    public static function setProperties()
119
-    {
120
-
121
-        EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration;
122
-    }
123
-
124
-
125
-    /**
126
-     * @return boolean
127
-     */
128
-    public static function useInvisibleRecaptcha()
129
-    {
130
-        return EED_Recaptcha_Invisible::$config->use_captcha
131
-               && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible';
132
-    }
133
-
134
-
135
-    /**
136
-     * @param string $form
137
-     * @return boolean
138
-     */
139
-    public static function protectForm($form)
140
-    {
141
-        return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms)
142
-               && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true);
143
-    }
144
-
145
-
146
-    /**
147
-     * @return void
148
-     * @throws InvalidInterfaceException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidArgumentException
151
-     */
152
-    public static function localizeScriptVars()
153
-    {
154
-        /** @var \EventEspresso\core\services\request\Request $request */
155
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156
-        // Invisible Recaptcha is ONLY ever required for the frontend and admin
157
-        // so we don't need to load any JS assets for other types of requests (like AJAX or API).
158
-        if (! ($request->isAdmin() || $request->isFrontend())) {
159
-            return;
160
-        }
161
-        wp_localize_script(
162
-            EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA,
163
-            'eeRecaptcha',
164
-            RecaptchaFactory::create()->getLocalizedVars()
165
-        );
166
-    }
167
-
168
-
169
-    /**
170
-     * @return string
171
-     */
172
-    public static function assetsUrl()
173
-    {
174
-        return plugin_dir_url(__FILE__) . 'assets' . DS;
175
-    }
176
-
177
-
178
-    /**
179
-     * @param \WP $WP
180
-     */
181
-    public function run($WP)
182
-    {
183
-    }
184
-
185
-
186
-    /**
187
-     * @param RequestInterface $request
188
-     * @return bool
189
-     * @throws InvalidArgumentException
190
-     * @throws InvalidDataTypeException
191
-     * @throws InvalidInterfaceException
192
-     * @throws RuntimeException
193
-     */
194
-    public static function verifyToken(RequestInterface $request)
195
-    {
196
-        return RecaptchaFactory::create()->verifyToken($request);
197
-    }
198
-
199
-
200
-    /**
201
-     * @param EE_Form_Section_Proper $reg_form
202
-     * @return void
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws DomainException
208
-     */
209
-    public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210
-    {
211
-        // do nothing if form isn't for a reg step or test has already been passed
212
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
213
-            return;
214
-        }
215
-        $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
216
-        if ($default_hidden_inputs instanceof EE_Form_Section_Proper) {
217
-            $invisible_recaptcha = RecaptchaFactory::create();
218
-            $invisible_recaptcha->addToFormSection($default_hidden_inputs);
219
-        }
220
-    }
221
-
222
-
223
-    /**
224
-     * @param EE_Form_Section_Proper $reg_form
225
-     * @return bool
226
-     * @throws InvalidDataTypeException
227
-     * @throws InvalidInterfaceException
228
-     * @throws EE_Error
229
-     * @throws InvalidArgumentException
230
-     */
231
-    public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form)
232
-    {
233
-        return strpos($reg_form->name(), 'reg-step-form') !== false
234
-               && ! RecaptchaFactory::create()->recaptchaPassed();
235
-    }
236
-
237
-
238
-    /**
239
-     * @param array|null             $req_data
240
-     * @param EE_Form_Section_Proper $reg_form
241
-     * @return array
242
-     * @throws EE_Error
243
-     * @throws InvalidArgumentException
244
-     * @throws InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     * @throws RuntimeException
247
-     */
248
-    public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249
-    {
250
-        // do nothing if form isn't for a reg step or test has already been passed
251
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
252
-            return $req_data;
253
-        }
254
-        /** @var RequestInterface $request */
255
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
257
-            if ($request->isAjax()) {
258
-                $json_response = new EE_SPCO_JSON_Response();
259
-                $json_response->echoAndExit();
260
-            }
261
-            EEH_URL::safeRedirectAndExit(
262
-                EE_Registry::instance()->CFG->core->reg_page_url()
263
-            );
264
-        }
265
-        return $req_data;
266
-    }
267
-
268
-
269
-    /**
270
-     * @param string   $html
271
-     * @param EE_Event $event
272
-     * @param bool     $iframe
273
-     * @return string
274
-     * @throws EE_Error
275
-     * @throws InvalidArgumentException
276
-     * @throws InvalidDataTypeException
277
-     * @throws InvalidInterfaceException
278
-     * @throws ReflectionException
279
-     * @throws DomainException
280
-     */
281
-    public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false)
282
-    {
283
-        $recaptcha = RecaptchaFactory::create();
284
-        // do nothing if test has  already  been passed
285
-        if ($recaptcha->recaptchaPassed()) {
286
-            return $html;
287
-        }
288
-        $html .= $recaptcha->getInputHtml(
289
-            array(
290
-                'recaptcha_id'   => $event->ID(),
291
-                'iframe'         => $iframe,
292
-                'localized_vars' => $recaptcha->getLocalizedVars(),
293
-            )
294
-        );
295
-        return $html;
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws InvalidArgumentException
302
-     * @throws InvalidInterfaceException
303
-     * @throws InvalidDataTypeException
304
-     * @throws RuntimeException
305
-     */
306
-    public static function processTicketSelectorForm()
307
-    {
308
-        // do nothing if test has  already  been passed
309
-        if (RecaptchaFactory::create()->recaptchaPassed()) {
310
-            return;
311
-        }
312
-        /** @var RequestInterface $request */
313
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
315
-            $event_id = $request->getRequestParam('tkt-slctr-event-id');
316
-            $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317
-                ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
318
-                : get_permalink($event_id);
319
-            EEH_URL::safeRedirectAndExit($return_url);
320
-        }
321
-    }
322
-
323
-
324
-    /**
325
-     * @throws EE_Error
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    public static function adminSettings()
331
-    {
332
-        RecaptchaFactory::getAdminModule()->adminSettings();
333
-    }
334
-
335
-
336
-    /**
337
-     * @param EE_Registration_Config $EE_Registration_Config
338
-     * @return EE_Registration_Config
339
-     * @throws EE_Error
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     */
345
-    public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config)
346
-    {
347
-        return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config);
348
-    }
21
+	/**
22
+	 * @var EE_Registration_Config $config
23
+	 */
24
+	private static $config;
25
+
26
+
27
+	/**
28
+	 * @return EED_Module|EED_Recaptcha
29
+	 */
30
+	public static function instance()
31
+	{
32
+		return parent::get_instance(__CLASS__);
33
+	}
34
+
35
+
36
+	/**
37
+	 * @return void
38
+	 * @throws InvalidInterfaceException
39
+	 * @throws InvalidDataTypeException
40
+	 * @throws InvalidArgumentException
41
+	 */
42
+	public static function set_hooks()
43
+	{
44
+		EED_Recaptcha_Invisible::setProperties();
45
+		if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) {
46
+			if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
47
+				// ticket selection
48
+				add_filter(
49
+					'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
50
+					array('EED_Recaptcha_Invisible', 'ticketSelectorForm'),
51
+					10,
52
+					3
53
+				);
54
+				add_action(
55
+					'EED_Ticket_Selector__process_ticket_selections__before',
56
+					array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
57
+				);
58
+			}
59
+			if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
60
+				// checkout
61
+				add_action(
62
+					'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form',
63
+					array('EED_Recaptcha_Invisible', 'spcoRegStepForm')
64
+				);
65
+				add_filter(
66
+					'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
67
+					array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
68
+					10,
69
+					2
70
+				);
71
+			}
72
+			add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars'));
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 * @return void
79
+	 * @throws InvalidInterfaceException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidArgumentException
82
+	 */
83
+	public static function set_hooks_admin()
84
+	{
85
+		EED_Recaptcha_Invisible::setProperties();
86
+		if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
87
+			add_action(
88
+				'EED_Ticket_Selector__process_ticket_selections__before',
89
+				array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
90
+			);
91
+		}
92
+		if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
93
+			add_filter(
94
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
95
+				array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
96
+				10,
97
+				2
98
+			);
99
+		}
100
+		// admin settings
101
+		add_action(
102
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
103
+			array('EED_Recaptcha_Invisible', 'adminSettings')
104
+		);
105
+		add_filter(
106
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
107
+			array('EED_Recaptcha_Invisible', 'updateAdminSettings')
108
+		);
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return void
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws InvalidArgumentException
117
+	 */
118
+	public static function setProperties()
119
+	{
120
+
121
+		EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration;
122
+	}
123
+
124
+
125
+	/**
126
+	 * @return boolean
127
+	 */
128
+	public static function useInvisibleRecaptcha()
129
+	{
130
+		return EED_Recaptcha_Invisible::$config->use_captcha
131
+			   && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible';
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param string $form
137
+	 * @return boolean
138
+	 */
139
+	public static function protectForm($form)
140
+	{
141
+		return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms)
142
+			   && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true);
143
+	}
144
+
145
+
146
+	/**
147
+	 * @return void
148
+	 * @throws InvalidInterfaceException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidArgumentException
151
+	 */
152
+	public static function localizeScriptVars()
153
+	{
154
+		/** @var \EventEspresso\core\services\request\Request $request */
155
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156
+		// Invisible Recaptcha is ONLY ever required for the frontend and admin
157
+		// so we don't need to load any JS assets for other types of requests (like AJAX or API).
158
+		if (! ($request->isAdmin() || $request->isFrontend())) {
159
+			return;
160
+		}
161
+		wp_localize_script(
162
+			EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA,
163
+			'eeRecaptcha',
164
+			RecaptchaFactory::create()->getLocalizedVars()
165
+		);
166
+	}
167
+
168
+
169
+	/**
170
+	 * @return string
171
+	 */
172
+	public static function assetsUrl()
173
+	{
174
+		return plugin_dir_url(__FILE__) . 'assets' . DS;
175
+	}
176
+
177
+
178
+	/**
179
+	 * @param \WP $WP
180
+	 */
181
+	public function run($WP)
182
+	{
183
+	}
184
+
185
+
186
+	/**
187
+	 * @param RequestInterface $request
188
+	 * @return bool
189
+	 * @throws InvalidArgumentException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws InvalidInterfaceException
192
+	 * @throws RuntimeException
193
+	 */
194
+	public static function verifyToken(RequestInterface $request)
195
+	{
196
+		return RecaptchaFactory::create()->verifyToken($request);
197
+	}
198
+
199
+
200
+	/**
201
+	 * @param EE_Form_Section_Proper $reg_form
202
+	 * @return void
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws DomainException
208
+	 */
209
+	public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210
+	{
211
+		// do nothing if form isn't for a reg step or test has already been passed
212
+		if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
213
+			return;
214
+		}
215
+		$default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
216
+		if ($default_hidden_inputs instanceof EE_Form_Section_Proper) {
217
+			$invisible_recaptcha = RecaptchaFactory::create();
218
+			$invisible_recaptcha->addToFormSection($default_hidden_inputs);
219
+		}
220
+	}
221
+
222
+
223
+	/**
224
+	 * @param EE_Form_Section_Proper $reg_form
225
+	 * @return bool
226
+	 * @throws InvalidDataTypeException
227
+	 * @throws InvalidInterfaceException
228
+	 * @throws EE_Error
229
+	 * @throws InvalidArgumentException
230
+	 */
231
+	public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form)
232
+	{
233
+		return strpos($reg_form->name(), 'reg-step-form') !== false
234
+			   && ! RecaptchaFactory::create()->recaptchaPassed();
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param array|null             $req_data
240
+	 * @param EE_Form_Section_Proper $reg_form
241
+	 * @return array
242
+	 * @throws EE_Error
243
+	 * @throws InvalidArgumentException
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 * @throws RuntimeException
247
+	 */
248
+	public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249
+	{
250
+		// do nothing if form isn't for a reg step or test has already been passed
251
+		if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
252
+			return $req_data;
253
+		}
254
+		/** @var RequestInterface $request */
255
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
+		if (! EED_Recaptcha_Invisible::verifyToken($request)) {
257
+			if ($request->isAjax()) {
258
+				$json_response = new EE_SPCO_JSON_Response();
259
+				$json_response->echoAndExit();
260
+			}
261
+			EEH_URL::safeRedirectAndExit(
262
+				EE_Registry::instance()->CFG->core->reg_page_url()
263
+			);
264
+		}
265
+		return $req_data;
266
+	}
267
+
268
+
269
+	/**
270
+	 * @param string   $html
271
+	 * @param EE_Event $event
272
+	 * @param bool     $iframe
273
+	 * @return string
274
+	 * @throws EE_Error
275
+	 * @throws InvalidArgumentException
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws InvalidInterfaceException
278
+	 * @throws ReflectionException
279
+	 * @throws DomainException
280
+	 */
281
+	public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false)
282
+	{
283
+		$recaptcha = RecaptchaFactory::create();
284
+		// do nothing if test has  already  been passed
285
+		if ($recaptcha->recaptchaPassed()) {
286
+			return $html;
287
+		}
288
+		$html .= $recaptcha->getInputHtml(
289
+			array(
290
+				'recaptcha_id'   => $event->ID(),
291
+				'iframe'         => $iframe,
292
+				'localized_vars' => $recaptcha->getLocalizedVars(),
293
+			)
294
+		);
295
+		return $html;
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws InvalidArgumentException
302
+	 * @throws InvalidInterfaceException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws RuntimeException
305
+	 */
306
+	public static function processTicketSelectorForm()
307
+	{
308
+		// do nothing if test has  already  been passed
309
+		if (RecaptchaFactory::create()->recaptchaPassed()) {
310
+			return;
311
+		}
312
+		/** @var RequestInterface $request */
313
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
+		if (! EED_Recaptcha_Invisible::verifyToken($request)) {
315
+			$event_id = $request->getRequestParam('tkt-slctr-event-id');
316
+			$return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317
+				? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
318
+				: get_permalink($event_id);
319
+			EEH_URL::safeRedirectAndExit($return_url);
320
+		}
321
+	}
322
+
323
+
324
+	/**
325
+	 * @throws EE_Error
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	public static function adminSettings()
331
+	{
332
+		RecaptchaFactory::getAdminModule()->adminSettings();
333
+	}
334
+
335
+
336
+	/**
337
+	 * @param EE_Registration_Config $EE_Registration_Config
338
+	 * @return EE_Registration_Config
339
+	 * @throws EE_Error
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 */
345
+	public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config)
346
+	{
347
+		return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config);
348
+	}
349 349
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156 156
         // Invisible Recaptcha is ONLY ever required for the frontend and admin
157 157
         // so we don't need to load any JS assets for other types of requests (like AJAX or API).
158
-        if (! ($request->isAdmin() || $request->isFrontend())) {
158
+        if ( ! ($request->isAdmin() || $request->isFrontend())) {
159 159
             return;
160 160
         }
161 161
         wp_localize_script(
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
      */
172 172
     public static function assetsUrl()
173 173
     {
174
-        return plugin_dir_url(__FILE__) . 'assets' . DS;
174
+        return plugin_dir_url(__FILE__).'assets'.DS;
175 175
     }
176 176
 
177 177
 
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
     public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210 210
     {
211 211
         // do nothing if form isn't for a reg step or test has already been passed
212
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
212
+        if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
213 213
             return;
214 214
         }
215 215
         $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
@@ -248,12 +248,12 @@  discard block
 block discarded – undo
248 248
     public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249 249
     {
250 250
         // do nothing if form isn't for a reg step or test has already been passed
251
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
251
+        if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
252 252
             return $req_data;
253 253
         }
254 254
         /** @var RequestInterface $request */
255 255
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
256
+        if ( ! EED_Recaptcha_Invisible::verifyToken($request)) {
257 257
             if ($request->isAjax()) {
258 258
                 $json_response = new EE_SPCO_JSON_Response();
259 259
                 $json_response->echoAndExit();
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
         }
312 312
         /** @var RequestInterface $request */
313 313
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
314
+        if ( ! EED_Recaptcha_Invisible::verifyToken($request)) {
315 315
             $event_id = $request->getRequestParam('tkt-slctr-event-id');
316 316
             $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317 317
                 ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
Please login to merge, or discard this patch.
caffeinated/modules/recaptcha_invisible/InvisibleRecaptcha.php 2 patches
Indentation   +228 added lines, -228 removed lines patch added patch discarded remove patch
@@ -27,258 +27,258 @@
 block discarded – undo
27 27
 class InvisibleRecaptcha
28 28
 {
29 29
 
30
-    const URL_GOOGLE_RECAPTCHA_API          = 'https://www.google.com/recaptcha/api/siteverify';
30
+	const URL_GOOGLE_RECAPTCHA_API          = 'https://www.google.com/recaptcha/api/siteverify';
31 31
 
32
-    const SESSION_DATA_KEY_RECAPTCHA_PASSED = 'recaptcha_passed';
32
+	const SESSION_DATA_KEY_RECAPTCHA_PASSED = 'recaptcha_passed';
33 33
 
34
-    /**
35
-     * @var EE_Registration_Config $config
36
-     */
37
-    private $config;
34
+	/**
35
+	 * @var EE_Registration_Config $config
36
+	 */
37
+	private $config;
38 38
 
39
-    /**
40
-     * @var EE_Session $session
41
-     */
42
-    private $session;
39
+	/**
40
+	 * @var EE_Session $session
41
+	 */
42
+	private $session;
43 43
 
44
-    /**
45
-     * @var boolean $recaptcha_passed
46
-     */
47
-    private $recaptcha_passed;
44
+	/**
45
+	 * @var boolean $recaptcha_passed
46
+	 */
47
+	private $recaptcha_passed;
48 48
 
49 49
 
50
-    /**
51
-     * InvisibleRecaptcha constructor.
52
-     *
53
-     * @param EE_Registration_Config $registration_config
54
-     * @param EE_Session             $session
55
-     */
56
-    public function __construct(EE_Registration_Config $registration_config, EE_Session $session)
57
-    {
58
-        $this->config = $registration_config;
59
-        $this->session = $session;
60
-    }
50
+	/**
51
+	 * InvisibleRecaptcha constructor.
52
+	 *
53
+	 * @param EE_Registration_Config $registration_config
54
+	 * @param EE_Session             $session
55
+	 */
56
+	public function __construct(EE_Registration_Config $registration_config, EE_Session $session)
57
+	{
58
+		$this->config = $registration_config;
59
+		$this->session = $session;
60
+	}
61 61
 
62 62
 
63
-    /**
64
-     * @return boolean
65
-     */
66
-    public function useInvisibleRecaptcha()
67
-    {
68
-        return $this->config->use_captcha && $this->config->recaptcha_theme === 'invisible';
69
-    }
63
+	/**
64
+	 * @return boolean
65
+	 */
66
+	public function useInvisibleRecaptcha()
67
+	{
68
+		return $this->config->use_captcha && $this->config->recaptcha_theme === 'invisible';
69
+	}
70 70
 
71 71
 
72
-    /**
73
-     * @param array $input_settings
74
-     * @return EE_Invisible_Recaptcha_Input
75
-     * @throws InvalidDataTypeException
76
-     * @throws InvalidInterfaceException
77
-     * @throws InvalidArgumentException
78
-     * @throws DomainException
79
-     */
80
-    public function getInput(array $input_settings = array())
81
-    {
82
-        return new EE_Invisible_Recaptcha_Input(
83
-            $input_settings,
84
-            $this->config
85
-        );
86
-    }
72
+	/**
73
+	 * @param array $input_settings
74
+	 * @return EE_Invisible_Recaptcha_Input
75
+	 * @throws InvalidDataTypeException
76
+	 * @throws InvalidInterfaceException
77
+	 * @throws InvalidArgumentException
78
+	 * @throws DomainException
79
+	 */
80
+	public function getInput(array $input_settings = array())
81
+	{
82
+		return new EE_Invisible_Recaptcha_Input(
83
+			$input_settings,
84
+			$this->config
85
+		);
86
+	}
87 87
 
88 88
 
89
-    /**
90
-     * @param array $input_settings
91
-     * @return string
92
-     * @throws EE_Error
93
-     * @throws InvalidDataTypeException
94
-     * @throws InvalidInterfaceException
95
-     * @throws InvalidArgumentException
96
-     * @throws DomainException
97
-     */
98
-    public function getInputHtml(array $input_settings = array())
99
-    {
100
-        return $this->getInput($input_settings)->get_html_for_input();
101
-    }
89
+	/**
90
+	 * @param array $input_settings
91
+	 * @return string
92
+	 * @throws EE_Error
93
+	 * @throws InvalidDataTypeException
94
+	 * @throws InvalidInterfaceException
95
+	 * @throws InvalidArgumentException
96
+	 * @throws DomainException
97
+	 */
98
+	public function getInputHtml(array $input_settings = array())
99
+	{
100
+		return $this->getInput($input_settings)->get_html_for_input();
101
+	}
102 102
 
103 103
 
104
-    /**
105
-     * @param EE_Form_Section_Proper $form
106
-     * @param array                  $input_settings
107
-     * @throws EE_Error
108
-     * @throws InvalidArgumentException
109
-     * @throws InvalidDataTypeException
110
-     * @throws InvalidInterfaceException
111
-     * @throws DomainException
112
-     */
113
-    public function addToFormSection(EE_Form_Section_Proper $form, array $input_settings = array())
114
-    {
115
-        $form->add_subsections(
116
-            array(
117
-                'espresso_recaptcha' => $this->getInput($input_settings),
118
-            ),
119
-            null,
120
-            false
121
-        );
122
-    }
104
+	/**
105
+	 * @param EE_Form_Section_Proper $form
106
+	 * @param array                  $input_settings
107
+	 * @throws EE_Error
108
+	 * @throws InvalidArgumentException
109
+	 * @throws InvalidDataTypeException
110
+	 * @throws InvalidInterfaceException
111
+	 * @throws DomainException
112
+	 */
113
+	public function addToFormSection(EE_Form_Section_Proper $form, array $input_settings = array())
114
+	{
115
+		$form->add_subsections(
116
+			array(
117
+				'espresso_recaptcha' => $this->getInput($input_settings),
118
+			),
119
+			null,
120
+			false
121
+		);
122
+	}
123 123
 
124 124
 
125
-    /**
126
-     * @param RequestInterface $request
127
-     * @return boolean
128
-     * @throws InvalidArgumentException
129
-     * @throws InvalidDataTypeException
130
-     * @throws InvalidInterfaceException
131
-     * @throws RuntimeException
132
-     */
133
-    public function verifyToken(RequestInterface $request)
134
-    {
135
-        static $previous_recaptcha_response = array();
136
-        $grecaptcha_response = $request->getRequestParam('g-recaptcha-response');
137
-        if ($grecaptcha_response === null) {
138
-            $this->generateError(
139
-                sprintf(
140
-                    esc_html__(
141
-                        'The "%1$s" parameter is missing.',
142
-                        'event_espresso'
143
-                    ),
144
-                    'g-recaptcha-response'
145
-                ),
146
-                true
147
-            );
148
-            return false;
149
-        }
150
-        // if this token has already been verified, then return previous response
151
-        if (isset($previous_recaptcha_response[ $grecaptcha_response ])) {
152
-            return $previous_recaptcha_response[ $grecaptcha_response ];
153
-        }
154
-        // will update to true if everything passes
155
-        $previous_recaptcha_response[ $grecaptcha_response ] = false;
156
-        $response                                            = wp_safe_remote_post(
157
-            InvisibleRecaptcha::URL_GOOGLE_RECAPTCHA_API,
158
-            array(
159
-                'body' => array(
160
-                    'secret'   => $this->config->recaptcha_privatekey,
161
-                    'response' => $grecaptcha_response,
162
-                    'remoteip' => $request->ipAddress(),
163
-                ),
164
-            )
165
-        );
166
-        if ($response instanceof WP_Error) {
167
-            $this->generateError($response->get_error_messages());
168
-            return false;
169
-        }
170
-        $results = json_decode(wp_remote_retrieve_body($response), true);
171
-        if (filter_var($results['success'], FILTER_VALIDATE_BOOLEAN) !== true) {
172
-            $errors   = array_map(
173
-                array($this, 'getErrorCode'),
174
-                $results['error-codes']
175
-            );
176
-            if (isset($results['challenge_ts'])) {
177
-                $errors[] = 'challenge timestamp: ' . $results['challenge_ts'] . '.';
178
-            }
179
-            $this->generateError(implode(' ', $errors), true);
180
-        }
181
-        $previous_recaptcha_response[ $grecaptcha_response ] = true;
182
-        add_action('shutdown', array($this, 'setSessionData'));
183
-        return true;
184
-    }
125
+	/**
126
+	 * @param RequestInterface $request
127
+	 * @return boolean
128
+	 * @throws InvalidArgumentException
129
+	 * @throws InvalidDataTypeException
130
+	 * @throws InvalidInterfaceException
131
+	 * @throws RuntimeException
132
+	 */
133
+	public function verifyToken(RequestInterface $request)
134
+	{
135
+		static $previous_recaptcha_response = array();
136
+		$grecaptcha_response = $request->getRequestParam('g-recaptcha-response');
137
+		if ($grecaptcha_response === null) {
138
+			$this->generateError(
139
+				sprintf(
140
+					esc_html__(
141
+						'The "%1$s" parameter is missing.',
142
+						'event_espresso'
143
+					),
144
+					'g-recaptcha-response'
145
+				),
146
+				true
147
+			);
148
+			return false;
149
+		}
150
+		// if this token has already been verified, then return previous response
151
+		if (isset($previous_recaptcha_response[ $grecaptcha_response ])) {
152
+			return $previous_recaptcha_response[ $grecaptcha_response ];
153
+		}
154
+		// will update to true if everything passes
155
+		$previous_recaptcha_response[ $grecaptcha_response ] = false;
156
+		$response                                            = wp_safe_remote_post(
157
+			InvisibleRecaptcha::URL_GOOGLE_RECAPTCHA_API,
158
+			array(
159
+				'body' => array(
160
+					'secret'   => $this->config->recaptcha_privatekey,
161
+					'response' => $grecaptcha_response,
162
+					'remoteip' => $request->ipAddress(),
163
+				),
164
+			)
165
+		);
166
+		if ($response instanceof WP_Error) {
167
+			$this->generateError($response->get_error_messages());
168
+			return false;
169
+		}
170
+		$results = json_decode(wp_remote_retrieve_body($response), true);
171
+		if (filter_var($results['success'], FILTER_VALIDATE_BOOLEAN) !== true) {
172
+			$errors   = array_map(
173
+				array($this, 'getErrorCode'),
174
+				$results['error-codes']
175
+			);
176
+			if (isset($results['challenge_ts'])) {
177
+				$errors[] = 'challenge timestamp: ' . $results['challenge_ts'] . '.';
178
+			}
179
+			$this->generateError(implode(' ', $errors), true);
180
+		}
181
+		$previous_recaptcha_response[ $grecaptcha_response ] = true;
182
+		add_action('shutdown', array($this, 'setSessionData'));
183
+		return true;
184
+	}
185 185
 
186 186
 
187
-    /**
188
-     * @param string $error_response
189
-     * @param bool   $show_errors
190
-     * @return void
191
-     * @throws RuntimeException
192
-     */
193
-    public function generateError($error_response = '', $show_errors = false)
194
-    {
195
-        throw new RuntimeException(
196
-            sprintf(
197
-                esc_html__(
198
-                    'We\'re sorry but an attempt to verify the form\'s reCAPTCHA has failed. %1$s %2$s Please try again.',
199
-                    'event_espresso'
200
-                ),
201
-                '<br />',
202
-                $show_errors || current_user_can('manage_options') ? $error_response : ''
203
-            )
204
-        );
205
-    }
187
+	/**
188
+	 * @param string $error_response
189
+	 * @param bool   $show_errors
190
+	 * @return void
191
+	 * @throws RuntimeException
192
+	 */
193
+	public function generateError($error_response = '', $show_errors = false)
194
+	{
195
+		throw new RuntimeException(
196
+			sprintf(
197
+				esc_html__(
198
+					'We\'re sorry but an attempt to verify the form\'s reCAPTCHA has failed. %1$s %2$s Please try again.',
199
+					'event_espresso'
200
+				),
201
+				'<br />',
202
+				$show_errors || current_user_can('manage_options') ? $error_response : ''
203
+			)
204
+		);
205
+	}
206 206
 
207 207
 
208
-    /**
209
-     * @param string $error_code
210
-     * @return string
211
-     */
212
-    public function getErrorCode(&$error_code)
213
-    {
214
-        $error_codes = array(
215
-            'missing-input-secret'   => 'The secret parameter is missing.',
216
-            'invalid-input-secret'   => 'The secret parameter is invalid or malformed.',
217
-            'missing-input-response' => 'The response parameter is missing.',
218
-            'invalid-input-response' => 'The response parameter is invalid or malformed.',
219
-            'bad-request'            => 'The request is invalid or malformed.',
220
-            'timeout-or-duplicate'   => 'The request took too long to be sent or was a duplicate of a previous request.',
221
-        );
222
-        return isset($error_codes[ $error_code ]) ? $error_codes[ $error_code ] : '';
223
-    }
208
+	/**
209
+	 * @param string $error_code
210
+	 * @return string
211
+	 */
212
+	public function getErrorCode(&$error_code)
213
+	{
214
+		$error_codes = array(
215
+			'missing-input-secret'   => 'The secret parameter is missing.',
216
+			'invalid-input-secret'   => 'The secret parameter is invalid or malformed.',
217
+			'missing-input-response' => 'The response parameter is missing.',
218
+			'invalid-input-response' => 'The response parameter is invalid or malformed.',
219
+			'bad-request'            => 'The request is invalid or malformed.',
220
+			'timeout-or-duplicate'   => 'The request took too long to be sent or was a duplicate of a previous request.',
221
+		);
222
+		return isset($error_codes[ $error_code ]) ? $error_codes[ $error_code ] : '';
223
+	}
224 224
 
225 225
 
226
-    /**
227
-     * @return array
228
-     * @throws InvalidInterfaceException
229
-     * @throws InvalidDataTypeException
230
-     * @throws InvalidArgumentException
231
-     */
232
-    public function getLocalizedVars()
233
-    {
234
-        return (array) apply_filters(
235
-            'FHEE__EventEspresso_caffeinated_modules_recaptcha_invisible_InvisibleRecaptcha__getLocalizedVars__localized_vars',
236
-            array(
237
-                'siteKey'          => $this->config->recaptcha_publickey,
238
-                'recaptcha_passed' => $this->recaptchaPassed(),
239
-                'wp_debug'         => WP_DEBUG,
240
-                'disable_submit'   => defined('EE_EVENT_QUEUE_BASE_URL'),
241
-            )
242
-        );
243
-    }
226
+	/**
227
+	 * @return array
228
+	 * @throws InvalidInterfaceException
229
+	 * @throws InvalidDataTypeException
230
+	 * @throws InvalidArgumentException
231
+	 */
232
+	public function getLocalizedVars()
233
+	{
234
+		return (array) apply_filters(
235
+			'FHEE__EventEspresso_caffeinated_modules_recaptcha_invisible_InvisibleRecaptcha__getLocalizedVars__localized_vars',
236
+			array(
237
+				'siteKey'          => $this->config->recaptcha_publickey,
238
+				'recaptcha_passed' => $this->recaptchaPassed(),
239
+				'wp_debug'         => WP_DEBUG,
240
+				'disable_submit'   => defined('EE_EVENT_QUEUE_BASE_URL'),
241
+			)
242
+		);
243
+	}
244 244
 
245 245
 
246
-    /**
247
-     * @return boolean
248
-     * @throws InvalidInterfaceException
249
-     * @throws InvalidDataTypeException
250
-     * @throws InvalidArgumentException
251
-     */
252
-    public function recaptchaPassed()
253
-    {
254
-        if ($this->recaptcha_passed !== null) {
255
-            return $this->recaptcha_passed;
256
-        }
257
-        // logged in means you have already passed a turing test of sorts
258
-        if ($this->useInvisibleRecaptcha() === false || is_user_logged_in()) {
259
-            $this->recaptcha_passed = true;
260
-            return $this->recaptcha_passed;
261
-        }
262
-        // was test already passed?
263
-        $this->recaptcha_passed = filter_var(
264
-            $this->session->get_session_data(
265
-                InvisibleRecaptcha::SESSION_DATA_KEY_RECAPTCHA_PASSED
266
-            ),
267
-            FILTER_VALIDATE_BOOLEAN
268
-        );
269
-        return $this->recaptcha_passed;
270
-    }
246
+	/**
247
+	 * @return boolean
248
+	 * @throws InvalidInterfaceException
249
+	 * @throws InvalidDataTypeException
250
+	 * @throws InvalidArgumentException
251
+	 */
252
+	public function recaptchaPassed()
253
+	{
254
+		if ($this->recaptcha_passed !== null) {
255
+			return $this->recaptcha_passed;
256
+		}
257
+		// logged in means you have already passed a turing test of sorts
258
+		if ($this->useInvisibleRecaptcha() === false || is_user_logged_in()) {
259
+			$this->recaptcha_passed = true;
260
+			return $this->recaptcha_passed;
261
+		}
262
+		// was test already passed?
263
+		$this->recaptcha_passed = filter_var(
264
+			$this->session->get_session_data(
265
+				InvisibleRecaptcha::SESSION_DATA_KEY_RECAPTCHA_PASSED
266
+			),
267
+			FILTER_VALIDATE_BOOLEAN
268
+		);
269
+		return $this->recaptcha_passed;
270
+	}
271 271
 
272 272
 
273
-    /**
274
-     * @throws InvalidArgumentException
275
-     * @throws InvalidDataTypeException
276
-     * @throws InvalidInterfaceException
277
-     */
278
-    public function setSessionData()
279
-    {
280
-        $this->session->set_session_data(
281
-            array(InvisibleRecaptcha::SESSION_DATA_KEY_RECAPTCHA_PASSED => true)
282
-        );
283
-    }
273
+	/**
274
+	 * @throws InvalidArgumentException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws InvalidInterfaceException
277
+	 */
278
+	public function setSessionData()
279
+	{
280
+		$this->session->set_session_data(
281
+			array(InvisibleRecaptcha::SESSION_DATA_KEY_RECAPTCHA_PASSED => true)
282
+		);
283
+	}
284 284
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -148,11 +148,11 @@  discard block
 block discarded – undo
148 148
             return false;
149 149
         }
150 150
         // if this token has already been verified, then return previous response
151
-        if (isset($previous_recaptcha_response[ $grecaptcha_response ])) {
152
-            return $previous_recaptcha_response[ $grecaptcha_response ];
151
+        if (isset($previous_recaptcha_response[$grecaptcha_response])) {
152
+            return $previous_recaptcha_response[$grecaptcha_response];
153 153
         }
154 154
         // will update to true if everything passes
155
-        $previous_recaptcha_response[ $grecaptcha_response ] = false;
155
+        $previous_recaptcha_response[$grecaptcha_response] = false;
156 156
         $response                                            = wp_safe_remote_post(
157 157
             InvisibleRecaptcha::URL_GOOGLE_RECAPTCHA_API,
158 158
             array(
@@ -169,16 +169,16 @@  discard block
 block discarded – undo
169 169
         }
170 170
         $results = json_decode(wp_remote_retrieve_body($response), true);
171 171
         if (filter_var($results['success'], FILTER_VALIDATE_BOOLEAN) !== true) {
172
-            $errors   = array_map(
172
+            $errors = array_map(
173 173
                 array($this, 'getErrorCode'),
174 174
                 $results['error-codes']
175 175
             );
176 176
             if (isset($results['challenge_ts'])) {
177
-                $errors[] = 'challenge timestamp: ' . $results['challenge_ts'] . '.';
177
+                $errors[] = 'challenge timestamp: '.$results['challenge_ts'].'.';
178 178
             }
179 179
             $this->generateError(implode(' ', $errors), true);
180 180
         }
181
-        $previous_recaptcha_response[ $grecaptcha_response ] = true;
181
+        $previous_recaptcha_response[$grecaptcha_response] = true;
182 182
         add_action('shutdown', array($this, 'setSessionData'));
183 183
         return true;
184 184
     }
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
             'bad-request'            => 'The request is invalid or malformed.',
220 220
             'timeout-or-duplicate'   => 'The request took too long to be sent or was a duplicate of a previous request.',
221 221
         );
222
-        return isset($error_codes[ $error_code ]) ? $error_codes[ $error_code ] : '';
222
+        return isset($error_codes[$error_code]) ? $error_codes[$error_code] : '';
223 223
     }
224 224
 
225 225
 
Please login to merge, or discard this patch.